Skip to content

Comments

feat: Add Users and Permissions system#307

Draft
fvanderflier wants to merge 2 commits intomainfrom
feature/users-and-permissions-system
Draft

feat: Add Users and Permissions system#307
fvanderflier wants to merge 2 commits intomainfrom
feature/users-and-permissions-system

Conversation

@fvanderflier
Copy link
Collaborator

@fvanderflier fvanderflier commented Feb 22, 2026

What Changed?

  • Added a new Project that will serve as a plugin for managing end-users/roles/permissions.
  • Use existing controllers to generate meta data for granular permissions per method via new source generator MethodAndPermissionsGenerator
  • Add new tables for managing this, that by using the project.
  • Came up with convention to call plugins Systems. So this is the UsersAndPermissionsSystem.
  • Added some AI Generated docs for this system at https://github.com/codechem/dappi/blob/3c709ca9be79f11e8fdaa11ce297d65b19c5c704/USERS_AND_PERMISSIONS_SETUP.md
  • Added a new endpoint for getting this permissions api/roles-and-permissions

TODOS

  • In scope of PR

    • Add authorization attributes dynamically so these are evaluated.
    • Add a way to allow external tokens and user registration
    • Add token enrichment with the permissions for the role.
    • Improve the AI generated documentation (simplify).
    • Add end-user registration via email
  • Out of scope of PR

    • Add external Auth providers

Some AI-generated diagrams to help/confuse you:

flowchart TD
    A["1️⃣ Source Generator<br/>Scans Controllers"] --> B["2️⃣ Generates<br/>PermissionsMeta.cs"]
    
    B --> C["3️⃣ AddUsersAndPermissionsSystem<br/>DI Setup"]
    
    C --> D["4️⃣ Define Roles<br/>AppRoleAndPermissionsBuilder"]
    
    D --> E["5️⃣ UseUsersAndPermissionsSystem<br/>Initialize & Migrate"]
    
    E --> F["6️⃣ Ready for<br/>Authorization"]
    
    F --> G["User Request"]
    G -->|Check Permissions| H{Has Access?}
    H -->|Yes| I["✓ Allow"]
    H -->|No| J["✗ Deny"]
    
    style A fill:#e1f5ff
    style B fill:#e1f5ff
    style C fill:#fff9c4
    style D fill:#fff9c4
    style E fill:#fff9c4
    style F fill:#c8e6c9
    style G fill:#f8bbd0
    style I fill:#c8e6c9
    style J fill:#ffccbc

Loading

What Happens at Each Step

Step Component Action
1️⃣ Source Generator Discovers all controller methods (CRUD)
2️⃣ PermissionsMeta.cs Generated file with all available permissions
3️⃣ AddUsersAndPermissionsSystem Registers DbContext, DbContextAccessor, PermissionsRepository
4️⃣ AppRoleAndPermissionsBuilder You define which roles can access which methods
5️⃣ UseUsersAndPermissionsSystem Runs migrations, syncs permissions & roles to database
6️⃣ Authorization System ready, checks user permissions on each request

Why?

Closes #308

Type of Change

  • ✨ New feature (adds new functionality without breaking existing features)

How Did You Test This?

  • add new db context
    public class AppUsersAndPermissionsDbContext(DbContextOptions<AppUsersAndPermissionsDbContext> options) : UsersAndPermissionsDbContext(options)
    {
        public DbSet<AppUser> AppUsers { get; set; }

        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            base.OnModelCreating(modelBuilder);

            modelBuilder.Entity<AppUser>()
                .HasOne(u => u.Role)
                .WithMany(r => (IEnumerable<AppUser>)r.Users);
        }
  • modify program.cs
...
        builder.Services.AddUsersAndPermissionsSystem<AppUsersAndPermissionsDbContext>(PermissionsMeta.Controllers, builder.Configuration);
        builder.Services.AddDappiSwaggerGen();
        
        var app = builder.Build();

        var permBuilder = new AppRoleAndPermissionsBuilder<AppUser>();
        permBuilder.ForRole(UsersAndPermissionsConstants.DefaultRoles.Authenticated)
            .ForController(nameof(TestController))
            .Allow(nameof(TestController.TestCustomMethod))
            .Allow(nameof(TestController.GetAllTests));
    
    await app.UseUsersAndPermissionsSystem<AppUsersAndPermissionsDbContext, AppUser>(permBuilder);
....
        
        app.Run();
  • add test controller
public partial class TestController
{
    [HttpGet("test-custom")]
    public IActionResult TestCustomMethod()
    {
        return Ok("This is a test method.");
    }
}
  • run endpoint
    http://localhost:5149/api/UsersAndPermissions?roleName=Authenticated
  • get response
{
  "TestController": [
    {
      "PermissionName": "TestCustomMethod",
      "Description": "GET/test-custom",
      "Selected": true
    },
    {
      "PermissionName": "GetTests",
      "Description": "GET/Test",
      "Selected": false
    },
    {
      "PermissionName": "GetTest",
      "Description": "GET/Test/{id}",
      "Selected": false
    },
    {
      "PermissionName": "Create",
      "Description": "POST/Test",
      "Selected": false
    },
    {
      "PermissionName": "Update",
      "Description": "PUT/Test/{id}",
      "Selected": false
    },
    {
      "PermissionName": "Delete",
      "Description": "DELETE/Test/{id}",
      "Selected": false
    },
    {
      "PermissionName": "GetAllTests",
      "Description": "GET/Test/get-all",
      "Selected": true
    },
    {
      "PermissionName": "JsonPatchTest",
      "Description": "PATCH/Test/{id}",
      "Selected": false
    }
  ]
}

Review Checklist

  • My code follows the project's style and conventions
  • I've reviewed my own code for obvious issues
  • I've added comments where the code might be confusing
  • I've updated relevant documentation (if needed)
  • I've tested my changes and they work as expected

Screenshots / Additional Context

@fvanderflier fvanderflier marked this pull request as draft February 22, 2026 21:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Users And Permissions System (Plugin)

1 participant