Skip to content

Conversation

@ysmoradi
Copy link
Member

@ysmoradi ysmoradi commented Jun 10, 2025

closes #10960

Summary by CodeRabbit

  • New Features
    • Added support for storing cryptographic keys in the database to enhance data protection.
    • Introduced new error messages for built-in and SuperAdmin role management.
  • Improvements
    • Enhanced role management security by preventing modifications to built-in roles and SuperAdmin role claims.
    • Updated user group and SuperAdmin-related resource messages for clarity.
  • Bug Fixes
    • Improved handling of field clearing and validation in the sign-in panel.
  • Chores
    • Updated and aligned method names related to removing users from roles for consistency.

@ysmoradi ysmoradi requested review from Copilot and msynk June 10, 2025 14:15
@coderabbitai
Copy link

coderabbitai bot commented Jun 10, 2025

Important

Review skipped

Auto incremental reviews are disabled on this repository.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Walkthrough

This update enhances the boilerplate project template's identity management by storing Data Protection API keys in the database, introduces restrictions to prevent modification or deletion of built-in roles, and updates localized resource strings for role management. Several method and resource key names are also clarified for consistency.

Changes

Files/Groups Change Summary
RolesPage.razor, RolesPage.razor.cs, IRoleManagementController.cs, RoleManagementController.cs Renamed method RemoveRoleFromAllUsers to RemoveAllUsersFromRole and updated references.
AppStrings.resx, AppStrings.fa.resx Improved and added resource strings for role management, including messages for built-in roles and SuperAdmin restrictions.
AppRoles.cs Added IsBuiltInRole static method to identify built-in roles.
RoleManagementController.cs Added checks to prevent modification/deletion of built-in roles and SuperAdmin claims; removed SuperAdmin check in GetRole.
Directory.Packages.props, Boilerplate.Server.Api.csproj Added Microsoft.AspNetCore.DataProtection.EntityFrameworkCore package reference.
AppDbContext.cs Implemented IDataProtectionKeyContext and added DataProtectionKeys DbSet for storing Data Protection keys.
Program.Services.cs Registered Data Protection service to persist keys to the database context.
SignInPanel.razor.cs Enhanced CleanModel method to clear and notify relevant fields based on panel type and OTP state.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant RolesPage
    participant RoleManagementController
    participant AppDbContext

    User->>RolesPage: Click "Remove all users from role"
    RolesPage->>RoleManagementController: RemoveAllUsersFromRole(roleId)
    RoleManagementController->>AppRoles: IsBuiltInRole(role.Name)
    alt If built-in role
        RoleManagementController-->>RolesPage: Throw BadRequestException
    else
        RoleManagementController->>AppDbContext: Remove users from role
        AppDbContext-->>RoleManagementController: Complete
        RoleManagementController-->>RolesPage: Success
    end
Loading
sequenceDiagram
    participant AppStartup
    participant Program.Services
    participant AppDbContext

    AppStartup->>Program.Services: ConfigureServices()
    Program.Services->>Program.Services: AddDataProtection()
    Program.Services->>AppDbContext: PersistKeysToDbContext<AppDbContext>()
Loading

Assessment against linked issues

Objective Addressed Explanation
Store Data Protection API keys in shared storage/database (#10960)
Prevent built-in roles from modification/deletion (#10960)
Role's page needs minor localized strings improvements (#10960)

Poem

In the garden of code where the data keys grow,
Rabbits now store them where safe waters flow.
Built-in roles are guarded—no edits allowed,
With strings now refined, the devs are all wowed!
🐇✨
Hopping ahead, secure and neat,
This boilerplate’s update is truly a treat!


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR enhances the identity boilerplate by adding database-backed data protection, tightening built-in role protections, and clarifying method names.

  • Persist DataProtection keys to the database and implement the key context
  • Introduce AppRoles.IsBuiltInRole checks and update related error messages
  • Rename RemoveRoleFromAllUsers to RemoveAllUsersFromRole in API and client

Reviewed Changes

Copilot reviewed 12 out of 12 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
src/.../Shared/Services/AppRoles.cs Add Demo constant and IsBuiltInRole helper
src/.../Shared/Resources/AppStrings.resx Update built-in role messages and add new keys
src/.../Shared/Resources/AppStrings.fa.resx Sync localized messages and resource keys
src/.../Controllers/Identity/IRoleManagementController.cs Rename RemoveRoleFromAllUsers to clarify intent
src/.../Program.Services.cs Configure AddDataProtection().PersistKeysToDbContext
src/.../Data/AppDbContext.cs Implement IDataProtectionKeyContext
src/.../Controllers/Identity/RoleManagementController.cs Enforce built-in role guards and rename remove action
src/.../Pages/Authorized/Management/RolesPage.razor(.cs) Align client method/event names with API change

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

🧹 Nitpick comments (2)
src/Templates/Boilerplate/Bit.Boilerplate/src/Server/Boilerplate.Server.Api/Program.Services.cs (1)

279-280: Excellent Data Protection configuration with important security reminder.

The implementation correctly configures Data Protection to persist keys to the database using the AppDbContext. The comment about using ProtectKeysWithCertificate is valuable security guidance for production deployments.

For enhanced security in production environments, consider adding certificate-based key protection:

 services.AddDataProtection()
-   .PersistKeysToDbContext<AppDbContext>(); // It's advised to secure database-stored keys with a certificate by invoking ProtectKeysWithCertificate.
+   .PersistKeysToDbContext<AppDbContext>()
+   .ProtectKeysWithCertificate(certificateThumbprint); // Add certificate protection in production
src/Templates/Boilerplate/Bit.Boilerplate/src/Server/Boilerplate.Server.Api/Controllers/Identity/RoleManagementController.cs (1)

79-80: Consider consolidating error message keys for better maintainability.

While the security checks are well-implemented, consider whether all built-in role operations (including SuperAdmin) could use the same error message key for consistency, since SuperAdmin is likely a built-in role.

If SuperAdmin is considered a built-in role, you could unify the error handling:

-        if (role.Name == AppRoles.SuperAdmin)
-            throw new BadRequestException(Localizer[nameof(AppStrings.UserCantChangeSuperAdminRoleClaimsErrorMessage)]);
+        if (AppRoles.IsBuiltInRole(role.Name!))
+            throw new BadRequestException(Localizer[nameof(AppStrings.CanNotChangeBuitlInRole), role.Name!]);

This would require updating the localization string to be more generic for both role and claim operations.

Also applies to: 101-102, 118-119, 136-137, 159-160

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
Knowledge Base: Disabled due to Reviews > Disable Knowledge Base setting

📥 Commits

Reviewing files that changed from the base of the PR and between d87df19 and fbe2d33.

📒 Files selected for processing (12)
  • src/Templates/Boilerplate/Bit.Boilerplate/src/Client/Boilerplate.Client.Core/Components/Pages/Authorized/Management/RolesPage.razor (1 hunks)
  • src/Templates/Boilerplate/Bit.Boilerplate/src/Client/Boilerplate.Client.Core/Components/Pages/Authorized/Management/RolesPage.razor.cs (1 hunks)
  • src/Templates/Boilerplate/Bit.Boilerplate/src/Client/Boilerplate.Client.Core/Components/Pages/Identity/SignIn/SignInPanel.razor.cs (1 hunks)
  • src/Templates/Boilerplate/Bit.Boilerplate/src/Directory.Packages.props (1 hunks)
  • src/Templates/Boilerplate/Bit.Boilerplate/src/Server/Boilerplate.Server.Api/Boilerplate.Server.Api.csproj (1 hunks)
  • src/Templates/Boilerplate/Bit.Boilerplate/src/Server/Boilerplate.Server.Api/Controllers/Identity/RoleManagementController.cs (6 hunks)
  • src/Templates/Boilerplate/Bit.Boilerplate/src/Server/Boilerplate.Server.Api/Data/AppDbContext.cs (2 hunks)
  • src/Templates/Boilerplate/Bit.Boilerplate/src/Server/Boilerplate.Server.Api/Program.Services.cs (2 hunks)
  • src/Templates/Boilerplate/Bit.Boilerplate/src/Shared/Controllers/Identity/IRoleManagementController.cs (1 hunks)
  • src/Templates/Boilerplate/Bit.Boilerplate/src/Shared/Resources/AppStrings.fa.resx (1 hunks)
  • src/Templates/Boilerplate/Bit.Boilerplate/src/Shared/Resources/AppStrings.resx (1 hunks)
  • src/Templates/Boilerplate/Bit.Boilerplate/src/Shared/Services/AppRoles.cs (1 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (1)
src/Templates/Boilerplate/Bit.Boilerplate/src/Server/Boilerplate.Server.Api/Data/AppDbContext.cs (6)
src/Templates/Boilerplate/Bit.Boilerplate/src/Server/Boilerplate.Server.Api/Models/Identity/User.cs (1)
  • User (9-55)
src/Templates/Boilerplate/Bit.Boilerplate/src/Server/Boilerplate.Server.Api/Models/Identity/UserClaim.cs (1)
  • UserClaim (3-6)
src/Templates/Boilerplate/Bit.Boilerplate/src/Server/Boilerplate.Server.Api/Models/Identity/UserRole.cs (1)
  • UserRole (3-8)
src/Templates/Boilerplate/Bit.Boilerplate/src/Server/Boilerplate.Server.Api/Models/Identity/UserLogin.cs (1)
  • UserLogin (3-6)
src/Templates/Boilerplate/Bit.Boilerplate/src/Server/Boilerplate.Server.Api/Models/Identity/RoleClaim.cs (1)
  • RoleClaim (3-6)
src/Templates/Boilerplate/Bit.Boilerplate/src/Server/Boilerplate.Server.Api/Models/Identity/UserToken.cs (1)
  • UserToken (3-6)
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: build and test
🔇 Additional comments (20)
src/Templates/Boilerplate/Bit.Boilerplate/src/Shared/Services/AppRoles.cs (1)

13-16: LGTM! Clean implementation of built-in role identification.

The method correctly uses pattern matching to identify SuperAdmin and Demo roles. This provides a centralized way to check for built-in roles that need special protection.

src/Templates/Boilerplate/Bit.Boilerplate/src/Client/Boilerplate.Client.Core/Components/Pages/Identity/SignIn/SignInPanel.razor.cs (1)

377-397: Excellent enhancement to form field management based on panel type.

The conditional logic correctly clears irrelevant fields based on the sign-in panel type:

  • Clears password for OTP-only authentication
  • Clears OTP for password-only authentication when OTP hasn't been sent
  • Uses null-conditional operators for safer field change notifications

This improves user experience by preventing validation conflicts between different authentication methods.

src/Templates/Boilerplate/Bit.Boilerplate/src/Client/Boilerplate.Client.Core/Components/Pages/Authorized/Management/RolesPage.razor (1)

232-232: Good method name update for semantic clarity.

The renamed method RemoveAllUsersFromRole is more semantically accurate than the previous name, clearly indicating that users are being removed from the role.

src/Templates/Boilerplate/Bit.Boilerplate/src/Shared/Controllers/Identity/IRoleManagementController.cs (1)

43-43: Interface method renamed for better semantic clarity.

The new method name RemoveAllUsersFromRole more accurately describes the operation and aligns with the implementation updates across the application.

src/Templates/Boilerplate/Bit.Boilerplate/src/Client/Boilerplate.Client.Core/Components/Pages/Authorized/Management/RolesPage.razor.cs (1)

385-394: Method renamed consistently with interface updates.

The implementation correctly updates both the method name and the internal controller call to maintain consistency across the application layers. The logic and error handling remain appropriately unchanged.

src/Templates/Boilerplate/Bit.Boilerplate/src/Shared/Resources/AppStrings.fa.resx (1)

1298-1300: LGTM! Improved specificity for SuperAdmin claims protection.

The key renaming from UserCantChangeSuperAdminRoleErrorMessage to UserCantChangeSuperAdminRoleClaimsErrorMessage better reflects its specific use case for preventing SuperAdmin role claims modification.

src/Templates/Boilerplate/Bit.Boilerplate/src/Shared/Resources/AppStrings.resx (2)

1298-1300: LGTM! Improved message clarity.

The updated message "You can't remove this user from the SuperAdmin user group" is more descriptive and user-friendly.


1301-1303: LGTM! Better specificity for claims protection.

The key renaming and message update provide clearer context for SuperAdmin claims protection scenarios.

src/Templates/Boilerplate/Bit.Boilerplate/src/Server/Boilerplate.Server.Api/Controllers/Identity/RoleManagementController.cs (7)

118-120: LGTM! Excellent SuperAdmin claims protection.

The implementation correctly prevents modification of SuperAdmin role claims across all claim management methods, using the appropriately renamed resource key.

Also applies to: 136-138, 159-161


210-210: LGTM! Better method naming.

The rename from RemoveRoleFromAllUsers to RemoveAllUsersFromRole is semantically more accurate and improves code readability.


101-102: LGTM! Consistent built-in role protection.

The same built-in role check is properly applied to the Delete method, maintaining consistency with the Update method. This prevents accidental deletion of system roles.


136-137: LGTM! Consistent SuperAdmin claim protection.

The same SuperAdmin claim protection is properly applied to both UpdateClaims and DeleteClaims methods, maintaining consistency across all claim modification operations.

Also applies to: 159-160


210-210: LGTM! Improved method naming for clarity.

The method rename from RemoveRoleFromAllUsers to RemoveAllUsersFromRole is more descriptive and clearly indicates the operation being performed.


118-119:

✅ Verification successful

Verify the localization string exists and consider SuperAdmin detection consistency.

The SuperAdmin claim protection is a good security measure. However, verify that the referenced localization string exists and consider if the SuperAdmin detection should be consistent with the built-in role check logic.


🏁 Script executed:

#!/bin/bash
# Search for the localization string in resource files
rg "UserCantChangeSuperAdminRoleClaimsErrorMessage"

# Check if SuperAdmin is considered a built-in role
rg -A 5 -B 5 "SuperAdmin.*IsBuiltInRole\|IsBuiltInRole.*SuperAdmin"

Length of output: 1190


Localization string verified; review SuperAdmin detection

  • The UserCantChangeSuperAdminRoleClaimsErrorMessage key is present in:
    • src/Shared/Resources/AppStrings.resx
    • src/Shared/Resources/AppStrings.fa.resx
  • No existing IsBuiltInRole (or equivalent) check was detected around the SuperAdmin logic in RoleManagementController.cs. Consider invoking a centralized built-in role check method—if one exists—to keep SuperAdmin detection consistent across the codebase.

79-80:

✅ Verification successful

Verify the AppRoles.IsBuiltInRole method implementation.

The built-in role protection logic is a good security measure. However, ensure that the AppRoles.IsBuiltInRole method is properly implemented and handles edge cases correctly.


🏁 Script executed:

#!/bin/bash
# Search for the AppRoles.IsBuiltInRole method implementation
ast-grep --pattern 'class AppRoles {
  $$$
  IsBuiltInRole($_) {
    $$$
  }
  $$$
}'

# Also search for any static method with this name
rg -A 10 "IsBuiltInRole"

Length of output: 4131


Built-in role check implementation confirmed

I’ve reviewed AppRoles.IsBuiltInRole in
src/Templates/Boilerplate/Bit.Boilerplate/src/Shared/Services/AppRoles.cs—it correctly returns true only for the SuperAdmin and Demo constants and safely returns false for null or any other values. No changes are needed here; just remember to update this method whenever new built-in roles are added.

src/Templates/Boilerplate/Bit.Boilerplate/src/Server/Boilerplate.Server.Api/Data/AppDbContext.cs (2)

20-20: LGTM: Correct using statement for Data Protection EntityFrameworkCore integration.

The using statement properly imports the namespace needed for IDataProtectionKeyContext and DataProtectionKey types.


25-25: LGTM: Proper implementation of IDataProtectionKeyContext interface.

Implementing IDataProtectionKeyContext correctly enables the AppDbContext to store ASP.NET Core Data Protection keys in the database, which is essential for multi-instance deployments.

src/Templates/Boilerplate/Bit.Boilerplate/src/Server/Boilerplate.Server.Api/Boilerplate.Server.Api.csproj (1)

32-32: LGTM: Correct package reference for Data Protection EntityFrameworkCore.

The package reference is properly added and will use the version specified in Directory.Packages.props, maintaining consistency with the project's central package management approach.

src/Templates/Boilerplate/Bit.Boilerplate/src/Directory.Packages.props (1)

23-23:

✅ Verification successful

Verify package version currency and compatibility.

The package version entry is correctly added for central package management. However, let's verify that version 9.0.5 is the latest stable version available.


🌐 Web query:

What is the latest stable version of Microsoft.AspNetCore.DataProtection.EntityFrameworkCore package for .NET 9.0?

💡 Result:

Based on the search results, the latest stable version of Microsoft.AspNetCore.DataProtection.EntityFrameworkCore package for .NET 9.0 is 9.0.5.

The Microsoft.AspNetCore.DataProtection.EntityFrameworkCore package provides a mechanism for storing data protection keys to a database using Entity Framework Core[5]. This package must be added separately to your project as it's not part of the Microsoft.AspNetCore.App metapackage[5].

The package targets .NET 9.0 and is compatible with this framework or higher[1]. Version 9.0.5 is the current stable release, which aligns with the latest patch version of .NET 9 itself, which was released on May 13, 2025[10].

This package allows you to store data protection keys in a database by using Entity Framework Core, which enables sharing keys across multiple instances of a web application[5]. To use this functionality, you would typically:

  1. Add the package to your project
  2. Create a DbContext that implements IDataProtectionKeyContext
  3. Configure your services to use this DbContext for key persistence

The package has dependencies on Microsoft.AspNetCore.DataProtection (>= 9.0.3) and Microsoft.EntityFrameworkCore (>= 9.0.3)[1], ensuring compatibility with the broader .NET 9 ecosystem.

Citations:


Approve addition of Microsoft.AspNetCore.DataProtection.EntityFrameworkCore 9.0.5

Version 9.0.5 is the latest stable release for .NET 9.0 and aligns with the current patch level. No further changes are needed.

src/Templates/Boilerplate/Bit.Boilerplate/src/Server/Boilerplate.Server.Api/Program.Services.cs (1)

17-17: LGTM: Required using statement for Data Protection services.

The using statement correctly imports the namespace needed for the AddDataProtection() extension method.

@ysmoradi ysmoradi merged commit c698a2a into bitfoundation:develop Jun 10, 2025
3 checks passed
@ysmoradi ysmoradi deleted the 10960 branch June 10, 2025 18:41
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.

Boilerplate project template identity needs improements

1 participant