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
- 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'
);
- 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>
- 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) {
...
}