Skip to main content

Roles and Permissions

Marblism integrate robust authorization and permissions system.

Simple Admin use-case

If your app have users and admin, everything is already built-in.

Check if a User is an admin in the front-end:

const store = useCoreStore()

return (
<>
{store.isAdmin && (
<div>
<Tag color="red">Admin</Tag>
</div>
)}
</>
)

Protect a back-end endpoint

add @AccessControl.Roles('admin') to any endpoint

@Delete('/:userId')
@AccessControl.Roles('admin')
async delete(@Param('userId') userId: string) {
...
}

Add a new Admin

-- Create the admin role
INSERT INTO "authorization_role" (
"id",
"name"
) VALUES (
'a7548b29-a984-40b5-a5ea-286b9ebeae18',
'admin'
);

-- Link the admin role to a User
INSERT INTO "authorization_role_user" (
"userId",
"roleId"
) VALUES (
'21a857f1-ba5f-4435-bcf6-f910ec07c0dc',
'a7548b29-a984-40b5-a5ea-286b9ebeae18'
);

Different Roles

Let's say you have a marketplace with Freelancers and Clients. Here is how to make it work.

Set-up

  1. Create the Freelancer and Client roles in the database
-- Create the Freelancer and Client role
INSERT INTO "authorization_role" (
"id",
"name"
) VALUES (
'f919e083-3db1-4409-a429-6ad2bc065732',
'freelancer'
);

INSERT INTO "authorization_role" (
"id",
"name"
) VALUES (
'03b56e71-b305-4054-8377-43dd695b1c0e',
'client'
);
  1. Front-end: When a User register they can choose between 'Freelancer' and 'Client'

/apps/web/src/app/(non-authenticated)/register/components/RegisterForm/index.tsx

<Form.Item label="Role" name="role">
<Radio.Group
options={[
{ label: 'Freelancer', value: 'freelancer' },
{ label: 'Client', value: 'Client' },
]}
optionType="button"
buttonStyle="solid"
/>
</Form.Item>
  1. Back-end: Link the role chose by the User

Update the DTO of the User Registration to allow for the new 'role' field to be included in the body request:

/apps/server/src/modules/authentication/application/authentication.dto.ts

export class AuthenticationRegisterDto {

...

@IsString()
@IsIn(['freelancer', 'client'])
role: string

...
}
...

Link the role chose by the User in the register endpoint

/apps/server/src/modules/authentication/application/authentication.controller.ts

 @Post('/register')
@Authentication.Public()
async register(
@Req() request: Request,
@Body() body: AuthenticationRegisterDto,
@Res({ passthrough: true }) response: Response,
) {
const { email, password, role } = body

...

const role = await this.authorizationDomainFacade.role.findOneByNameOrFail(role)

await this.authorizationDomainFacade.roleUser.create(user, role)

...
}

Don't forget to import AuthorizationDomainFacade in the AuthenticationController

export class AuthenticationController {
constructor(private authorizationDomainFacade: AuthorizationDomainFacade)
}

and to import AuthorizationDomainModule in your authentication.application.module.ts

@Module({
imports: [AuthorizationDomainModule],
})
export class AuthenticationApplicationModule {}

Using it

Check if a User is a Freelancer in the front-end:

const store = useCoreStore()

return (
<>
{store.roles.some(role => role.name === 'freelancer') && (
<>Hello I'm a freelancer</>
)}
</>
)

Protect a back-end endpoint

Add @AccessControl.Roles('freelancer') to any endpoint

@Delete('/:userId')
@AccessControl.Roles('freelancer')
async delete(@Param('userId') userId: string) {
...
}