UI: password change enforcement + migration recovery
- Web UI admin password reset now enforces admin role server-side (was cookie-auth + CSRF only; any logged-in user could previously reset any account's password) - Added self-service password change UI at GET/PUT /profile: current_password + new_password + confirm_password; server-side equality check; lockout + Argon2id verification; revokes all other sessions on success - password_change_form.html fragment and profile.html page - Nav bar actor name now links to /profile - policy: ActionChangePassword + default rule -7 allowing human accounts to change their own password - openapi.yaml: built-in rules count updated to -7 Migration recovery: - mciasdb schema force --version N: new subcommand to clear dirty migration state without running SQL (break-glass) - schema subcommands bypass auto-migration on open so the tool stays usable when the database is dirty - Migrate(): shim no longer overrides schema_migrations when it already has an entry; duplicate-column error on the latest migration is force-cleaned and treated as success (handles columns added outside the runner) Security: - Admin role is now validated in handleAdminResetPassword before any DB access; non-admin receives 403 - handleSelfChangePassword follows identical lockout + constant-time Argon2id path as the REST self-service handler; current password required to prevent token-theft account takeover Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -42,6 +42,18 @@ var defaultRules = []Rule{
|
||||
Actions: []Action{ActionEnrollTOTP},
|
||||
Effect: Allow,
|
||||
},
|
||||
{
|
||||
// Self-service password change: any authenticated human account may
|
||||
// change their own password. The handler derives the target exclusively
|
||||
// from the JWT subject (claims.Subject) and requires the current
|
||||
// password, so a non-admin caller can only affect their own account.
|
||||
ID: -7,
|
||||
Description: "Self-service: any human account may change their own password",
|
||||
Priority: 0,
|
||||
AccountTypes: []string{"human"},
|
||||
Actions: []Action{ActionChangePassword},
|
||||
Effect: Allow,
|
||||
},
|
||||
{
|
||||
// System accounts reading their own pgcreds: a service that has already
|
||||
// authenticated (e.g. via its bearer service token) may retrieve its own
|
||||
|
||||
@@ -42,8 +42,9 @@ const (
|
||||
ActionEnrollTOTP Action = "totp:enroll" // self-service
|
||||
ActionRemoveTOTP Action = "totp:remove" // admin
|
||||
|
||||
ActionLogin Action = "auth:login" // public
|
||||
ActionLogout Action = "auth:logout" // self-service
|
||||
ActionLogin Action = "auth:login" // public
|
||||
ActionLogout Action = "auth:logout" // self-service
|
||||
ActionChangePassword Action = "auth:change_password" // self-service
|
||||
|
||||
ActionListRules Action = "policy:list"
|
||||
ActionManageRules Action = "policy:manage"
|
||||
|
||||
Reference in New Issue
Block a user