Skip to content

RE1-T113 Set pw on first login#330

Merged
ucswift merged 2 commits intomasterfrom
develop
Apr 13, 2026
Merged

RE1-T113 Set pw on first login#330
ucswift merged 2 commits intomasterfrom
develop

Conversation

@ucswift
Copy link
Copy Markdown
Member

@ucswift ucswift commented Apr 13, 2026

Summary by CodeRabbit

  • New Features

    • Administrators can now require users to change their password on the next login when creating new accounts or resetting passwords.
    • Users required to change their password are prompted to do so immediately upon login, with the requirement automatically cleared after the password change is completed.
  • Bug Fixes

    • Fixed async operation handling in department member deletion process.
    • Improved active department membership validation to properly account for disabled memberships.

@request-info
Copy link
Copy Markdown

request-info bot commented Apr 13, 2026

Thanks for opening this, but we'd appreciate a little more information. Could you update it with more details?

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Apr 13, 2026

Warning

Rate limit exceeded

@ucswift has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 20 minutes and 54 seconds before requesting another review.

Your organization is not enrolled in usage-based pricing. Contact your admin to enable usage-based pricing to continue reviews beyond the rate limit, or try again in 20 minutes and 54 seconds.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: cbd13e7b-e79a-4427-bacb-8b8dbc48132e

📥 Commits

Reviewing files that changed from the base of the PR and between a0dec90 and d414d3f.

⛔ Files ignored due to path filters (18)
  • Core/Resgrid.Localization/Areas/User/Personnel/Person.ar.resx is excluded by !**/*.resx
  • Core/Resgrid.Localization/Areas/User/Personnel/Person.de.resx is excluded by !**/*.resx
  • Core/Resgrid.Localization/Areas/User/Personnel/Person.en.resx is excluded by !**/*.resx
  • Core/Resgrid.Localization/Areas/User/Personnel/Person.es.resx is excluded by !**/*.resx
  • Core/Resgrid.Localization/Areas/User/Personnel/Person.fr.resx is excluded by !**/*.resx
  • Core/Resgrid.Localization/Areas/User/Personnel/Person.it.resx is excluded by !**/*.resx
  • Core/Resgrid.Localization/Areas/User/Personnel/Person.pl.resx is excluded by !**/*.resx
  • Core/Resgrid.Localization/Areas/User/Personnel/Person.sv.resx is excluded by !**/*.resx
  • Core/Resgrid.Localization/Areas/User/Personnel/Person.uk.resx is excluded by !**/*.resx
  • Core/Resgrid.Localization/Areas/User/Profile/Profile.ar.resx is excluded by !**/*.resx
  • Core/Resgrid.Localization/Areas/User/Profile/Profile.de.resx is excluded by !**/*.resx
  • Core/Resgrid.Localization/Areas/User/Profile/Profile.en.resx is excluded by !**/*.resx
  • Core/Resgrid.Localization/Areas/User/Profile/Profile.es.resx is excluded by !**/*.resx
  • Core/Resgrid.Localization/Areas/User/Profile/Profile.fr.resx is excluded by !**/*.resx
  • Core/Resgrid.Localization/Areas/User/Profile/Profile.it.resx is excluded by !**/*.resx
  • Core/Resgrid.Localization/Areas/User/Profile/Profile.pl.resx is excluded by !**/*.resx
  • Core/Resgrid.Localization/Areas/User/Profile/Profile.sv.resx is excluded by !**/*.resx
  • Core/Resgrid.Localization/Areas/User/Profile/Profile.uk.resx is excluded by !**/*.resx
📒 Files selected for processing (4)
  • Core/Resgrid.Model/DepartmentMember.cs
  • Web/Resgrid.Web/Areas/User/Controllers/ProfileController.cs
  • Web/Resgrid.Web/Areas/User/Views/Personnel/AddPerson.cshtml
  • Web/Resgrid.Web/Areas/User/Views/Profile/ResetPasswordForUser.cshtml
📝 Walkthrough

Walkthrough

This PR adds a forced password change feature to allow administrators to require users to change their password on next login. It introduces a new MustChangePassword boolean property to the DepartmentMember entity, supporting database migrations for SQL Server and PostgreSQL, and integrates password change enforcement into the login, user creation, and password reset workflows.

Changes

Cohort / File(s) Summary
Model Entity
Core/Resgrid.Model/DepartmentMember.cs
Added MustChangePassword boolean property to flag users requiring password change on next login.
Database Migrations
Providers/Resgrid.Providers.Migrations/Migrations/M0064_AddingMustChangePassword.cs, Providers/Resgrid.Providers.MigrationsPg/Migrations/M0064_AddingMustChangePasswordPg.cs
Added migrations (v64) to create non-nullable MustChangePassword column with default false in DepartmentMembers table for SQL Server and PostgreSQL.
Service Layer
Core/Resgrid.Services/DepartmentsService.cs, Core/Resgrid.Services/UsersService.cs
Fixed async/await in member deletion; updated active department check to exclude disabled memberships.
View Models
Web/Resgrid.Web/Areas/User/Models/AddPersonModel.cs, Web/Resgrid.Web/Areas/User/Models/Profile/ResetPasswordForUserView.cs
Added MustChangePasswordOnLogin property to support admin control during user creation and password resets.
Controller Logic
Web/Resgrid.Web/Areas/User/Controllers/PersonnelController.cs, Web/Resgrid.Web/Areas/User/Controllers/ProfileController.cs, Web/Resgrid.Web/Controllers/AccountController.cs
Personnel creation now sets flag if requested; password reset updates flag based on admin choice; login enforces flag by redirecting to forced password change; flag cleared after successful password change.
Razor Views
Web/Resgrid.Web/Areas/User/Views/Personnel/AddPerson.cshtml, Web/Resgrid.Web/Areas/User/Views/Profile/ResetPasswordForUser.cshtml
Added "Require Password Change" checkbox fields to user creation and password reset forms.

Sequence Diagram(s)

sequenceDiagram
    actor User as User
    participant AC as AccountController
    participant DS as DepartmentsService
    participant DB as Database
    participant Session as Session

    User->>AC: Login with credentials
    AC->>AC: Authenticate username/password
    alt Authentication successful
        AC->>DS: GetDepartmentMemberAsync(userId, deptId)
        DS->>DB: Query DepartmentMembers
        DB-->>DS: Return member record
        DS-->>AC: Return member
        
        alt member.MustChangePassword == true
            AC->>Session: Store ForcePasswordChangeUserId
            AC->>Session: Store ForcePasswordChangeDeptId
            AC-->>User: Redirect to ForcePasswordChange
            User->>AC: POST new password to ForcePasswordChange
            AC->>AC: Hash and update password
            AC->>DS: GetDepartmentMemberAsync(userId, deptId)
            DS->>DB: Query DepartmentMembers
            DB-->>DS: Return member record
            DS-->>AC: Return member
            AC->>AC: member.MustChangePassword = false
            AC->>DS: SaveDepartmentMemberAsync(member)
            DS->>DB: Update DepartmentMembers
            DB-->>DS: Confirm update
            AC->>Session: Remove force change flags
            AC-->>User: Redirect to Dashboard
        else MustChangePassword == false
            AC-->>User: Proceed to Dashboard
        end
    else Authentication failed
        AC-->>User: Show login error
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 9.09% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'RE1-T113 Set pw on first login' directly corresponds to the main feature: forcing users to change their password on first login after admin-initiated password resets or account creation.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch develop

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

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@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: 3

🧹 Nitpick comments (2)
Web/Resgrid.Web/Areas/User/Models/Profile/ResetPasswordForUserView.cs (1)

29-29: Prefer setting the default in the model.

Initialize MustChangePasswordOnLogin here (e.g., = true) and let the Razor checkbox bind naturally, instead of forcing checked state in markup.

♻️ Proposed change
-		public bool MustChangePasswordOnLogin { get; set; }
+		public bool MustChangePasswordOnLogin { get; set; } = true;
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Web/Resgrid.Web/Areas/User/Models/Profile/ResetPasswordForUserView.cs` at
line 29, Set the default value for MustChangePasswordOnLogin on the
ResetPasswordForUserView model (e.g., initialize the property to true) so the
Razor checkbox can bind naturally; update the property declaration for
MustChangePasswordOnLogin to include the default initializer and remove any
forced checked logic in the Razor view so the checkbox state comes from the
model binding instead.
Web/Resgrid.Web/Areas/User/Controllers/ProfileController.cs (1)

1003-1008: Pass CancellationToken to SaveDepartmentMemberAsync for consistency.

The SaveDepartmentMemberAsync call on line 1007 omits the cancellationToken parameter, inconsistent with other async service calls in this controller (e.g., line 1001 and similar calls throughout the codebase). This prevents proper request cancellation propagation. The method accepts a CancellationToken parameter with a default value, but should be passed explicitly for consistency.

🔧 Proposed fix
 				var member = await _departmentsService.GetDepartmentMemberAsync(model.UserId, DepartmentId);
 				if (member != null)
 				{
 					member.MustChangePassword = model.MustChangePasswordOnLogin;
-					await _departmentsService.SaveDepartmentMemberAsync(member);
+					await _departmentsService.SaveDepartmentMemberAsync(member, cancellationToken);
 				}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Web/Resgrid.Web/Areas/User/Controllers/ProfileController.cs` around lines
1003 - 1008, The SaveDepartmentMemberAsync call is missing the cancellationToken
parameter causing inconsistent cancellation propagation; update the block that
retrieves and updates the member (using
_departmentsService.GetDepartmentMemberAsync and member.MustChangePassword) to
pass the existing cancellationToken into SaveDepartmentMemberAsync (i.e., call
_departmentsService.SaveDepartmentMemberAsync(member, cancellationToken)) so the
request cancellation is propagated consistently like other async service calls
in this controller.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@Core/Resgrid.Model/DepartmentMember.cs`:
- Around line 83-89: The MustChangePassword property on the DepartmentMember
class is missing a ProtoMember attribute and will be omitted during protobuf
serialization; add the [ProtoMember(13)] annotation directly above the public
bool MustChangePassword { get; set; } property so it is included in
SerializerHelper.PrepareSerializer<DepartmentMember>() serialization; ensure the
numeric tag 13 continues the existing sequence (1–12) used by the other members.

In `@Web/Resgrid.Web/Areas/User/Views/Personnel/AddPerson.cshtml`:
- Around line 188-197: The checkbox label and help text in the AddPerson view
are hard-coded; replace them with localized strings by using the view's
IViewLocalizer/Localizer indexer (e.g., localizer["RequirePasswordChange"] and
localizer["MustChangePasswordOnLoginHelp"]) instead of plain text for the label
"Require Password Change" and the help-block text; update the markup that
references the MustChangePasswordOnLogin checkbox and add the corresponding
resource keys to your resource files so the UI is translated correctly.

In `@Web/Resgrid.Web/Areas/User/Views/Profile/ResetPasswordForUser.cshtml`:
- Around line 99-108: The Require Password Change UI hard-codes the checkbox
state and plain text; modify the view to use the MustChangePasswordOnLogin model
binding (keep asp-for="MustChangePasswordOnLogin" but remove the static
checked="checked") so the checkbox state comes from the model, and replace
static label and help text with localized strings using localizer[...] (use the
same keys for the label and the help-block) so the label and help text are
pulled from the localization resources.

---

Nitpick comments:
In `@Web/Resgrid.Web/Areas/User/Controllers/ProfileController.cs`:
- Around line 1003-1008: The SaveDepartmentMemberAsync call is missing the
cancellationToken parameter causing inconsistent cancellation propagation;
update the block that retrieves and updates the member (using
_departmentsService.GetDepartmentMemberAsync and member.MustChangePassword) to
pass the existing cancellationToken into SaveDepartmentMemberAsync (i.e., call
_departmentsService.SaveDepartmentMemberAsync(member, cancellationToken)) so the
request cancellation is propagated consistently like other async service calls
in this controller.

In `@Web/Resgrid.Web/Areas/User/Models/Profile/ResetPasswordForUserView.cs`:
- Line 29: Set the default value for MustChangePasswordOnLogin on the
ResetPasswordForUserView model (e.g., initialize the property to true) so the
Razor checkbox can bind naturally; update the property declaration for
MustChangePasswordOnLogin to include the default initializer and remove any
forced checked logic in the Razor view so the checkbox state comes from the
model binding instead.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 642bba93-9136-4bb5-9d40-0cc0c42b3000

📥 Commits

Reviewing files that changed from the base of the PR and between 1f38dde and a0dec90.

📒 Files selected for processing (12)
  • Core/Resgrid.Model/DepartmentMember.cs
  • Core/Resgrid.Services/DepartmentsService.cs
  • Core/Resgrid.Services/UsersService.cs
  • Providers/Resgrid.Providers.Migrations/Migrations/M0064_AddingMustChangePassword.cs
  • Providers/Resgrid.Providers.MigrationsPg/Migrations/M0064_AddingMustChangePasswordPg.cs
  • Web/Resgrid.Web/Areas/User/Controllers/PersonnelController.cs
  • Web/Resgrid.Web/Areas/User/Controllers/ProfileController.cs
  • Web/Resgrid.Web/Areas/User/Models/AddPersonModel.cs
  • Web/Resgrid.Web/Areas/User/Models/Profile/ResetPasswordForUserView.cs
  • Web/Resgrid.Web/Areas/User/Views/Personnel/AddPerson.cshtml
  • Web/Resgrid.Web/Areas/User/Views/Profile/ResetPasswordForUser.cshtml
  • Web/Resgrid.Web/Controllers/AccountController.cs

@ucswift
Copy link
Copy Markdown
Member Author

ucswift commented Apr 13, 2026

Approve

Copy link
Copy Markdown

@github-actions github-actions bot left a comment

Choose a reason for hiding this comment

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

This PR is approved.

@ucswift ucswift merged commit 11b789e into master Apr 13, 2026
18 of 19 checks passed
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.

1 participant