Single-Role Scenario
In a Single-Role Scenario, each user in your application is assigned one role, and permissions are granted based on that role. This scenario is simpler because the user's role defines their access to resources without involving multiple roles or complex combinations.
Example Setup
Let's imagine you have a file where the authentication user roles for your application are defined. Here's how that could look:
export enum UserRoles {
Admin = "admin",
User = "user",
Moderator = "moderator",
BetaTester = "betaTester",
}
export interface AuthUser {
userId: string;
role: UserRoles;
// other user properties
}
In this example, the AuthUser
interface defines the authenticated user, including their role which is one of the UserRoles
.
Next, let's define a resource model, say ToDoModel
:
export type ToDoModel = {
authorId: string;
title: string;
description: string;
};
Now, let’s consider how we structure the permissions for this model. Here’s how you would organize the access control:
access-control
├── permissions.config.ts
└── index.ts
In permissions.config.ts
, you'll define the structure of your permissions for different resources. For instance:
// access-control/permissions.config.ts
import { ResourceConfig } from "rolebaker";
export interface MyResourceConfig extends ResourceConfig {
resources: {
todos: {
dataType: ToDoModel;
action: "read" | "write" | "delete";
};
betaResource: {
dataType: string;
action: "view";
};
};
}
Here, MyResourceConfig
extends ResourceConfig
and defines two resources: todos
(representing a to-do list) and betaResource
(a special resource only for betaTester
roles). Each resource is associated with actions (like read
, write
, delete
for todos
or view
for betaResource
).
Assigning Permissions
Now, in index.ts
, you’ll specify which users can perform which actions on these resources. Here’s how you can configure it:
// access-control/index.config.ts
import { MyResourceConfig } from "./permissions.config.ts";
import { bakeAuthorization } from "rolebaker";
import { UserRoles, AuthUser } from "your-auth-file";
export const { hasPermission } = bakeAuthorization<
UserRoles,
AuthUser,
MyResourceConfig
>({
userRoleMode: "singleRole", // This defines that users can only have one role at a time
permissionsConfig: {
admin: {
todos: { read: true, write: true, delete: true },
},
moderator: {
todos: { read: true, write: false, delete: false },
},
user: {
todos: {
read: true,
write: false,
delete: {
checkFunction: (authUser, todo) => todo?.authorId === authUser.userId, // Allows a user to delete only their own todo
},
},
},
betaTester: {
betaResource: { view: true }, // Only beta testers can view this resource
},
},
});
Permissions Configuration
Here’s what’s happening:
- Admin can read, write, and delete todos.
- Moderator can only read todos and cannot write or delete.
- User can only read todos and has restricted delete permissions (they can only delete their own todos).
- BetaTester can view the special
betaResource
but has no access to todos.
Has Permission?
The hasPermission
function checks if a user has the right to perform a specific action on a resource. It takes the user, resource, and action as arguments and returns a boolean or evaluates custom logic for permission checks.
export const { hashPermission} = bakeAuthorization<...>(...)
// Example
const authorUser: AuthUser = { role: UserRoles.User, userId: "user1" };
const resourceData: ToDoModel = {
authorId: "user1",
title: "title",
description: "description",
};
const isAllowed = hasPermission(authorUser, "todos", "delete", resourceData) // true