Skip to content

feat: add user role assignment expiry and history tracking#1816

Merged
Eugeny merged 8 commits into
warp-tech:mainfrom
mrmm:mrmm/feat-role-expiry
Apr 6, 2026
Merged

feat: add user role assignment expiry and history tracking#1816
Eugeny merged 8 commits into
warp-tech:mainfrom
mrmm:mrmm/feat-role-expiry

Conversation

@mrmm

@mrmm mrmm commented Mar 23, 2026

Copy link
Copy Markdown
Contributor

Add time-limited role assignments with optional expiry.

What's new

  • Role expiry — assign roles with an optional expires_at timestamp; expired roles are automatically denied during authorization
  • Soft revocation — revoking a role sets revoked_at instead of deleting the row
  • Re-activationPOST /users/:id/roles/:role_id on a revoked/expired assignment re-activates it (instead of 409)
  • Admin UI — expiry presets (4h/8h/12h/1d/3d/7d/30d), live countdown timers, re-enable expired roles
  • Connection history — user page shows past sessions with protocol, target, and duration
  • 9 E2E tests covering expiry, revocation, and re-activation

Screenshots

User roles with mixed expiry states

role-list

Permanent access

permanent-access

Expiry modal with presets

expiry-modal

API changes

Modified endpoint

Method Path Change
POST /users/:id/roles/:role_id Body is now optional. Accepts {"expires_at": "..."} or no body (permanent). Re-activates revoked/expired assignments instead of 409.

New endpoints

Method Path Description
GET /users/:id/roles List all role assignments with expiry info
GET /users/:id/roles/:role_id Get single assignment details
PUT /users/:id/roles/:role_id/expiry Set or update expiry
DELETE /users/:id/roles/:role_id/expiry Remove expiry (make permanent)

Migration

m00033_user_role_expiry_history:

  • Adds granted_at, granted_by, expires_at, revoked_at, revoked_by columns to user_roles
  • Backfills granted_at for existing rows

@mrmm mrmm changed the title add user role assignment expiry and history tracking feat: add user role assignment expiry and history tracking Mar 23, 2026
mrmm added a commit to mrmm/terraform-provider-warpgate that referenced this pull request Mar 23, 2026
User role assignments can now have optional expiration timestamps for
time-limited access grants. Compatible with warp-tech/warpgate#1816.

Changes:
- Added expiry block to warpgate_user_role resource with expires_at field
- Added UpdateContext to allow modifying expiry on existing assignments
- New UserRoleAssignment struct with expiry and activity metadata
- Updated AddUserRole to accept optional expiresAt parameter
- Added GetUserRole, UpdateUserRoleExpiry, and RemoveUserRoleExpiry client methods
- GetUserRoles now returns UserRoleAssignment with expiry fields
- Updated docs with time-limited assignment example

Example usage:
  resource "warpgate_user_role" "temporary" {
    user_id = warpgate_user.alice.id
    role_id = warpgate_role.contractor.id
    expiry {
      expires_at = "2026-12-31T23:59:59Z"
    }
  }
@Eugeny

Eugeny commented Mar 23, 2026

Copy link
Copy Markdown
Member

Could you please remove the history tracking part from this PR?

I actually had a different approach to this in mind - using the log as a source of data and having a "User audit log" link from the user profile to a pre-filtered log viewer. Log entries tagged as audit would then have an independent, longer expiry as well. As for the UI, the log viewer could then include dedicated UI elements for specific log entry types

The background behind this is that there are more important audit log types than just role assignments and I don't want to build separate UI and database structures for them all

@mrmm

mrmm commented Mar 24, 2026

Copy link
Copy Markdown
Contributor Author

@Eugeny Got it ! I have removed the role assignement history from this PR! Let me know if you want to reduce further the scope of the.
I am really interested in the technical details of how you envision implementing the audit logs types.

Edit: Do you need me also to remove the UI of the Connection History from the user UI if it was also planned to be somewhere else ?

Add time-limited role assignments with optional expiry timestamps.
Expired and revoked roles are automatically denied during authorization.

Backend:
- Migration m00033: adds granted_at, granted_by, expires_at, revoked_at,
  revoked_by columns to user_roles table
- UserRoleAssignment entity extended with expiry/revocation fields
- New API endpoints: get_user_role, update_user_role_expiry,
  remove_user_role_expiry
- add_user_role now accepts optional expires_at body; re-activates
  revoked/expired assignments instead of returning 409
- delete_user_role soft-deletes (sets revoked_at)
- authorize_target filters out expired/revoked role assignments
- SSO role removal uses soft-delete
- delete_role cleans up user_roles and target_roles FK references
- sessions list accepts optional username filter

Frontend:
- Role list shows expiry status with live countdown timer
- Expired roles shown with strikethrough and Re-enable button
- Expiry modal with presets (4h/8h/12h/1d/3d/7d/30d) and custom picker
- Connection history section on user page

Tests:
- 9 E2E tests covering grant with TTL, expired denied, re-enable,
  revoke, reactivate, API state listing, duplicate detection
- Permission enforcement test cases for new endpoints
- OIDC stale role test updated for soft-delete behavior
@mrmm mrmm force-pushed the mrmm/feat-role-expiry branch from 2040b56 to a94d17d Compare March 24, 2026 12:20
@Eugeny

Eugeny commented Apr 1, 2026

Copy link
Copy Markdown
Member

Here's a rough draft of what I had in mind regarding the log:

#1832

Screenshot 2026-04-02 at 01 16 12

@Eugeny

Eugeny commented Apr 6, 2026

Copy link
Copy Markdown
Member

Thank you - I've simplified the UI a bit

@Eugeny Eugeny merged commit cab9540 into warp-tech:main Apr 6, 2026
18 checks passed
@mrmm

mrmm commented Apr 6, 2026

Copy link
Copy Markdown
Contributor Author

Thanks @Eugeny I have seen that you have merge the PR ! I was meaning to take a look into it to fix the failing build test tomorrow ! But U did fix that !
Thanks !

DO you want me to prepare the File transfer restriction related PR or not ?

captain686 pushed a commit to captain686/warpgate that referenced this pull request May 29, 2026
…#1816)

Add time-limited role assignments with optional expiry.

## What's new

- **Role expiry** — assign roles with an optional `expires_at`
timestamp; expired roles are automatically denied during authorization
- **Soft revocation** — revoking a role sets `revoked_at` instead of
deleting the row
- **Re-activation** — `POST /users/:id/roles/:role_id` on a
revoked/expired assignment re-activates it (instead of 409)
- **Admin UI** — expiry presets (4h/8h/12h/1d/3d/7d/30d), live countdown
timers, re-enable expired roles
- **Connection history** — user page shows past sessions with protocol,
target, and duration
- **9 E2E tests** covering expiry, revocation, and re-activation

## Screenshots

### User roles with mixed expiry states
<img width="802" alt="role-list"
src="https://github.com/user-attachments/assets/abf2c49a-8b01-4901-b945-3e7066d63af9"
/>

### Permanent access
<img width="601" alt="permanent-access"
src="https://github.com/user-attachments/assets/6797d3c4-1c47-48f6-b4ff-0d13660dd030"
/>

### Expiry modal with presets
<img width="534" alt="expiry-modal"
src="https://github.com/user-attachments/assets/94bd8733-d930-4c28-a8dc-c3c3e2e883e4"
/>

## API changes

### Modified endpoint

| Method | Path | Change |
|--------|------|--------|
| `POST` | `/users/:id/roles/:role_id` | Body is now optional. Accepts
`{"expires_at": "..."}` or no body (permanent). Re-activates
revoked/expired assignments instead of 409. |

### New endpoints

| Method | Path | Description |
|--------|------|-------------|
| `GET` | `/users/:id/roles` | List all role assignments with expiry
info |
| `GET` | `/users/:id/roles/:role_id` | Get single assignment details |
| `PUT` | `/users/:id/roles/:role_id/expiry` | Set or update expiry |
| `DELETE` | `/users/:id/roles/:role_id/expiry` | Remove expiry (make
permanent) |

## Migration

`m00033_user_role_expiry_history`:
- Adds `granted_at`, `granted_by`, `expires_at`, `revoked_at`,
`revoked_by` columns to `user_roles`
- Backfills `granted_at` for existing rows

---------

Co-authored-by: Eugene <inbox@null.page>
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.

2 participants