Photo by Pawel Czerwinski on Unsplash

REACT ARCHITECTURE SERIES

React Project Architecture 20— (Authorization — II)

Onur Dayıbaşı
learnreactui
Published in
2 min readDec 14, 2024

--

I’ve already talked about authorization models and authorization with React CASL. In this post, I’d like to deepen this topic a bit more

In my previous 2 blog posts, I explained Authorization Models and how we can do Routing level authorization with React CASL.

In this article, I will explain how we can authorize the components of the application through ToDO App.

ToDO Authorization

Live Demo : https://onurdayibasi.dev/miniapp/task-management-authorization-comp You can access the live use of the example at this address.

In this example we have users in different roles using our ToDo application, it is actually similar to the example in the previous post;

export const AUTHORIZATION_ROLES = {
SUPER_ADMIN: "SuperAdmin",
ADMIN: "Admin ",
STANDART_USER: "User",
};

And let’s define the Subject/Resource that this will work on

export const AUTHORIZATION_RESOURCES = {
TODO: "Todo",
};

And let’s list the operations we can perform on this Resource.

export const AUTHORIZATION_ACTIONS = {
CREATE: "create",
READ: "read",
UPDATE: "update",
DELETE: "delete",
};

What I’m going to do next is to create the Ability/Permission Structure. I’m here

  • Super Admin → All Skills
  • Admin → Not Only Delete Ability
  • User → Read Only Ability..
import { AbilityBuilder, Ability, AbilityClass } from "@casl/ability";
import { AUTHORIZATION_ROLES as roles } from "./roles";
import { AUTHORIZATION_ACTIONS as actions } from "./actions";
import { AUTHORIZATION_RESOURCES as resources } from "./resources";

export type AppAbility = Ability<[Actions, Subjects]>;
export const appAbility = Ability as AbilityClass<AppAbility>;

export default function defineRulesFor(role: string) {
const { can, rules } = new AbilityBuilder(appAbility);

if (role === roles.SUPER_ADMIN) {
can(actions.DELETE, resources.TODO);
can(actions.CREATE, resources.TODO);
can(actions.UPDATE, resources.TODO);
can(actions.READ, resources.TODO);
} else if (role === roles.ADMIN) {
can(actions.CREATE, resources.TODO);
can(actions.UPDATE, resources.TODO);
can(actions.READ, resources.TODO);
} else if (role === roles.STANDART_USER) {
can(actions.READ, resources.TODO);
}

return rules;
}

export function buildAbilityFor(role: string): AppAbility {
return new appAbility(defineRulesFor(role), {
// https://casl.js.org/v5/en/guide/subject-type-detection
detectSubjectType: (object) => object!.type,
});
}

Now after these we wrap them with buttons or the Can or Cannot ability on the components we want.

 <Can do={AUTHORIZATION_ACTIONS.DELETE} on={AUTHORIZATION_RESOURCES.TODO}>
<ODButtons.DeleteBulkButton
entityName="Task"
propName="Taskname"
selectedEntities={selectedEntities}
handleDeleteBulk={(deleteTasksIds: string[]) => {
mutation.mutate(deleteTasksIds);
}}
/>
</Can>

Of course, don’t forget to update the Ability when you change roles.

    const ability = useContext(AbilityContext);
ability.update(defineRulesFor(updatedRole);

Continue Reading 😃

You can click on this link for the continuation of this article or to access other articles in the article group (react-architecture).

--

--

learnreactui
learnreactui

Published in learnreactui

This publications are updates of ebooks about react, frontend, javascript and software engineer

No responses yet