chrisK824 / fastapi-rbac-example

FastAPI example with distinct permissions for each route
MIT License
57 stars 10 forks source link

Roles in Docs #77

Open dura0ok opened 5 months ago

dura0ok commented 5 months ago

What about describe roles, which needed to execute some endpoint?

chrisK824 commented 5 months ago

Hey @dura0ok ,

the whole idea is to use resources to set distinctive permissions and attach those on each endpoint.

This way, the endpoint is always secured from the exact suitable permissions and can be accessed by any role that has those permissions.

Obvious advantage of this is the fact that permissions can change for each role in time if needed, modifying the access to endpoints without even touching the endpoints themselves.

Hope that helps, cheers!

dura0ok commented 5 months ago

Yes, it's cool, but it would be cool if the current roles that need to be in order to access the endpoint were displayed in the generated documentation

chrisK824 commented 5 months ago

Well, two points here:

  1. the necessary "thing" required for each endpoint is permissions really, not roles. So, roles that can access the endpoint can be from none to many and that's the point of it all, the flexibility to add custom roles based on permissions as you move on.
  2. I guess what you are after here would be exposing the necessary permissions of an endpoint into the openapi docs somehow?
dura0ok commented 5 months ago

Yes))

chrisK824 commented 4 months ago

@dura0ok sorry, didn't get that one sooner. I don't believe this would be any helpful really, not with that approach anyway, since the scopes defined are only internal. Unless all of those were exposed to user and one could request a custom token with which peemissions they wish in some kind of on demand tokens fashion.

joshwisehub commented 4 months ago

Context:
I have three types of users: Admin, Service Provider, and Applicant. Based on an example provided, I am considering the following implementation:

User Types and Registration Process

Proposed Implementation Steps

  1. Database Schema:

    • Roles Table:
      • Fields: role name.
      • Many-to-many relationship with permissions.
    • Permissions Table:
      • Fields: permission name, description.
    • Users Table:
      • Fields: user information (e.g., business name, taxpayer ID, email, password).
      • Many-to-many relationship with roles.
    • Role-User Table:
      • Fields: user_id, role_id (to manage the many-to-many relationship between users and roles).
    • Role-Permission Table:
      • Fields: role_id, permission_id (to manage the many-to-many relationship between roles and permissions).
  2. Registration Process:

    • Service Providers:
      • Admin registers the Service Provider.
      • Sends an email with an activation link to the Service Provider.
    • Applicants:
      • Applicants register themselves using a registration route.
      • Sends a verification code to the Applicant’s email.
  3. Email Verification:

    • Implement functionality to send activation links and verification codes via email.
    • Create endpoints for handling activation link clicks and code verification.
  4. Assign Permissions:

    • Upon successful email verification (activation link or code), update the user’s status.
    • Assign the appropriate role to the user.
    • Roles automatically grant the necessary permissions through their many-to-many relationship with permissions.

Workflow

  1. Admin Creates Service Provider:

    • Admin registers a new Service Provider.
    • Service Provider receives an email with an activation link.
    • Service Provider clicks the activation link.
    • The account is verified and activated.
    • The Service Provider is assigned the appropriate role, which grants the necessary permissions.
  2. Applicant Self-Registration:

    • Applicant registers using the provided form.
    • Applicant receives a verification code via email.
    • Applicant enters the code to verify their email.
    • The account is created and activated.
    • The Applicant is assigned the appropriate role, which grants the necessary permissions.

Is my workflow a good approach.How can i modify your example to meet my usecase.If not how can i adopt it to fit well in mine

chrisK824 commented 4 months ago

Hey @joshwisehub , sorry for the late response, kinda busy these days.

Well it all sounds good, but with couple of caveats:

  1. In terms of roles and their permissions, if you are to keep them in your database, instead of just in your code, you will need some initialization scripts to get them in your database in the first place. Given that you won't be really able to "secure" them behind some relevant endpoints, as you would cut off yourself in the process or give those endpoints free access, since there would be nothing (roles or permissions) to authorize against in that stage.

  2. On top of the previous point, with your approach you would probably need some definitions duplication. You see, permissions in my example are defined in the codebase so that they can be used at will in routers/endpoints dependencies. If your permissions for example are just in your database, then I don't see how you could have them available for definition time of your endpoints without duplicating the information in your code as well to use them. Remember, endpoints definition with the dependency injection is just like any other Python decorator, so they are evaluated during startup and interpretation, so you can't really have those permissions at this stage if they are only present in your database. Even if you manage to somehow load them in memory before all routers definition starts, I guess it would be quite tricky.

joshwisehub commented 3 months ago

Yeah, it's true will have to load the permissions and roles on initial start up using a migration script, But one final question before trying your approach. Will it be easy to populate the permissions and roles in the UI for example if you connect to a client that use frontend framework like react. To allow adding or assigning permissions or even revoking permissions from a role or a specific user. Since with current implementation, in order to do that you have to go back to the code and manually add a new role or add a set of permissions to a new role. Can you help on how I can handle a scenario where the Administrator of a system will not be a developer, so he can just add a new role and set permissions to that newly added role in the UI without touching the code.

This question comes from the benefits section of your medium article on this topic.

chrisK824 commented 3 months ago

Well, you could handle the whole thing with simple CRUD operations, but you will still have limitations.

  1. Since your endpoints are depending on permissions, those need to exist already when the app loads. Even if you get away with the migration script trick for the first load, it means you still cannot create new permissions and effectively use them for anything. So as I think of it you will need new deployment for new permissions. Which should be ok, given that new permissions should be used by new endpoints anyway which would require a deployment whatsoever.
  2. That doesn't seem to be a limitation for roles though. Given that permissions are defined already you could CRUD roles with set of permissions with no problem and assign them to users.