#Best practice in implementing roles/authorization?

3 messages · Page 1 of 1 (latest)

oak nest
#

What's the best way to implement roles/authorization in nestjs? I'm not using CASL right now, I'm not sure if it suits my simple use case.

For a brief background:
A. the project uses typeorm

B. notably, there are two roles: student and instructor

C. majority of the database tables/entities have the same way of doing CRUD operations (in this case, let's call these specific entities as "domain entities/records" because they are directly related to the business domain of the project)

D. each domain record has a foreign key that points to an Activity record upon creation (Activity a non-domain entity, but just note that this table has columns such as **startDate **and endDate)

E. no other app roles/permissions are expected to be changed/created in the future.

F. API implementation is REST


Here are some of the typical rules:

  1. all users can MANAGE (FULL CRUD) domain entities/records as long as they own these records (i.e., they were the one who created such)

  2. in addition to rule 1, instructor-users can also READ other domain records as long as the owner of these records are their own students

  3. additional logic to rule 1; student-users can only CREATE a domain record if the current date of creation/api request is within the start/endDate (in reference to the Activity relation previously mentioned, background item D)

  4. instructor-users can MANAGE non-domain entities/records, while student-users can only READ them

Any suggestions on how to implement these with best practices? Do I still need to use CASL for this?

shadow owl
#

Role Table:

  • id: integer
  • name: string

Permission Table:

  • id: integer
  • name: string

User Table:

  • id: integer
  • username: string

UserRole Table:

  • user_id: integer
  • role_id: integer

UserPermission Table:

  • user_id: integer
  • permission_id: integer
function checkPermission(user: User, requiredPermission: string): boolean {
  // Check if the user has the required permission
  for (const role of user.roles) {
    for (const permission of role.permissions) {
      if (permission.name === requiredPermission) {
        return true;
      }
    }
  }

  // Check if the user has additional permissions
  for (const permission of user.permissions) {
    if (permission.name === requiredPermission) {
      return true;
    }
  }

  return false;
}

// Usage example
function getPost(user: User) {
  if (checkPermission(user, 'read post')) {
    // Logic
  } else {
    // Permission denied
  }
}

You can implement this to Guard as decorator, but u should use caching or jwt like things to get permissions cuz you dont want really querying db and mapping permission name things every request

#

and i dont know is it best practice or not, its just what i use and i dont care best practices, it just works