@spinajs/rbac-http-admin 2.0.485 → 2.0.487

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (66) hide show
  1. package/README.md +104 -5
  2. package/lib/cjs/config/rbac-http-admin.d.ts +25 -0
  3. package/lib/cjs/config/rbac-http-admin.d.ts.map +1 -1
  4. package/lib/cjs/config/rbac-http-admin.js +25 -0
  5. package/lib/cjs/config/rbac-http-admin.js.map +1 -1
  6. package/lib/cjs/controllers/Users/Profile.d.ts.map +1 -1
  7. package/lib/cjs/controllers/Users/Profile.js +3 -1
  8. package/lib/cjs/controllers/Users/Profile.js.map +1 -1
  9. package/lib/cjs/controllers/Users/Roles.d.ts +15 -8
  10. package/lib/cjs/controllers/Users/Roles.d.ts.map +1 -1
  11. package/lib/cjs/controllers/Users/Roles.js +34 -16
  12. package/lib/cjs/controllers/Users/Roles.js.map +1 -1
  13. package/lib/cjs/controllers/Users/Security.d.ts +151 -11
  14. package/lib/cjs/controllers/Users/Security.d.ts.map +1 -1
  15. package/lib/cjs/controllers/Users/Security.js +303 -30
  16. package/lib/cjs/controllers/Users/Security.js.map +1 -1
  17. package/lib/cjs/controllers/Users/Users.d.ts +97 -14
  18. package/lib/cjs/controllers/Users/Users.d.ts.map +1 -1
  19. package/lib/cjs/controllers/Users/Users.js +278 -73
  20. package/lib/cjs/controllers/Users/Users.js.map +1 -1
  21. package/lib/cjs/index.d.ts +6 -1
  22. package/lib/cjs/index.d.ts.map +1 -1
  23. package/lib/cjs/index.js +5 -0
  24. package/lib/cjs/index.js.map +1 -1
  25. package/lib/cjs/interfaces.d.ts +81 -0
  26. package/lib/cjs/interfaces.d.ts.map +1 -0
  27. package/lib/cjs/interfaces.js +20 -0
  28. package/lib/cjs/interfaces.js.map +1 -0
  29. package/lib/cjs/services/RoleGuard.d.ts +96 -0
  30. package/lib/cjs/services/RoleGuard.d.ts.map +1 -0
  31. package/lib/cjs/services/RoleGuard.js +258 -0
  32. package/lib/cjs/services/RoleGuard.js.map +1 -0
  33. package/lib/mjs/config/rbac-http-admin.d.ts +25 -0
  34. package/lib/mjs/config/rbac-http-admin.d.ts.map +1 -1
  35. package/lib/mjs/config/rbac-http-admin.js +25 -0
  36. package/lib/mjs/config/rbac-http-admin.js.map +1 -1
  37. package/lib/mjs/controllers/Users/Profile.d.ts.map +1 -1
  38. package/lib/mjs/controllers/Users/Profile.js +4 -2
  39. package/lib/mjs/controllers/Users/Profile.js.map +1 -1
  40. package/lib/mjs/controllers/Users/Roles.d.ts +15 -8
  41. package/lib/mjs/controllers/Users/Roles.d.ts.map +1 -1
  42. package/lib/mjs/controllers/Users/Roles.js +35 -17
  43. package/lib/mjs/controllers/Users/Roles.js.map +1 -1
  44. package/lib/mjs/controllers/Users/Security.d.ts +151 -11
  45. package/lib/mjs/controllers/Users/Security.d.ts.map +1 -1
  46. package/lib/mjs/controllers/Users/Security.js +304 -31
  47. package/lib/mjs/controllers/Users/Security.js.map +1 -1
  48. package/lib/mjs/controllers/Users/Users.d.ts +97 -14
  49. package/lib/mjs/controllers/Users/Users.d.ts.map +1 -1
  50. package/lib/mjs/controllers/Users/Users.js +279 -74
  51. package/lib/mjs/controllers/Users/Users.js.map +1 -1
  52. package/lib/mjs/index.d.ts +6 -1
  53. package/lib/mjs/index.d.ts.map +1 -1
  54. package/lib/mjs/index.js +6 -1
  55. package/lib/mjs/index.js.map +1 -1
  56. package/lib/mjs/interfaces.d.ts +81 -0
  57. package/lib/mjs/interfaces.d.ts.map +1 -0
  58. package/lib/mjs/interfaces.js +16 -0
  59. package/lib/mjs/interfaces.js.map +1 -0
  60. package/lib/mjs/services/RoleGuard.d.ts +96 -0
  61. package/lib/mjs/services/RoleGuard.d.ts.map +1 -0
  62. package/lib/mjs/services/RoleGuard.js +252 -0
  63. package/lib/mjs/services/RoleGuard.js.map +1 -0
  64. package/lib/tsconfig.cjs.tsbuildinfo +1 -1
  65. package/lib/tsconfig.mjs.tsbuildinfo +1 -1
  66. package/package.json +14 -12
package/README.md CHANGED
@@ -1,11 +1,110 @@
1
- # `rbac-http`
1
+ # `@spinajs/rbac-http-admin`
2
2
 
3
- > TODO: description
3
+ Administrative HTTP API for user accounts: listing and editing users, roles, passwords, two-factor
4
+ authentication, bans, login lockouts and live sessions.
4
5
 
5
- ## Usage
6
+ Every route sits behind `AuthorizedPolicy` plus a route-level `@Permission` on the `users` resource,
7
+ so an application grants access with ordinary rbac grants:
6
8
 
9
+ ```js
10
+ grants: {
11
+ admin: {
12
+ users: { 'create:any': ['*'], 'read:any': ['*'], 'update:any': ['*'], 'delete:any': ['*'] },
13
+ },
14
+ }
7
15
  ```
8
- const rbacHttp = require('rbac-http');
9
16
 
10
- // TODO: DEMONSTRATE API
17
+ ## Routes
18
+
19
+ | Method | Path | Permission | What it does |
20
+ | -------- | --------------------------------------------- | ----------- | --------------------------------------------------------- |
21
+ | `GET` | `/users` | `readAny` | Paginated, filterable, sortable list. `X-Total-Count` header |
22
+ | `GET` | `/users/roles` | `readAny` | Roles the caller is allowed to assign |
23
+ | `GET` | `/users/:uuid` | `readAny` | One account |
24
+ | `GET` | `/users/byLogin/:login` | `readAny` | One account, addressed by login |
25
+ | `POST` | `/users` | `createAny` | Create an account ( inactive, temporary password discarded ) |
26
+ | `PATCH` | `/users/:uuid` | `updateAny` | Partial update of login / email / role |
27
+ | `DELETE` | `/users/:uuid` | `deleteAny` | Soft delete + session revocation |
28
+ | `PATCH` | `/users/:uuid/restore` | `deleteAny` | Clear `DeletedAt` |
29
+ | `PATCH` | `/users/role/add/:login` | `updateAny` | Grant a role |
30
+ | `PATCH` | `/users/role/revoke/:login` | `updateAny` | Revoke a role |
31
+ | `GET` | `/users/profile/:login` | `readAny` | Profile through the configured `UserProfileProvider` |
32
+ | `PATCH` | `/users/security/changePassword/:uuid` | `updateAny` | Set a password. Revokes every session of that user |
33
+ | `POST` | `/users/security/password-reset-request/:uuid`| `updateAny` | Issue a reset token and emit `UserPasswordChangeRequest` |
34
+ | `POST` | `/users/security/expire-password/:uuid` | `deleteAny` | Expire the password ( deactivates the account ) |
35
+ | `PATCH` | `/users/security/reset2fa/:uuid` | `updateAny` | Clear the TOTP secret |
36
+ | `POST` | `/users/security/2fa/enable/:uuid` | `updateAny` | Enrol 2FA, returns the enrolment url |
37
+ | `POST` | `/users/security/2fa/disable/:uuid` | `updateAny` | Turn 2FA off |
38
+ | `POST` | `/users/security/activate/:uuid` | `updateAny` | Activate the account |
39
+ | `POST` | `/users/security/deactivate/:uuid` | `deleteAny` | Deactivate + revoke sessions |
40
+ | `POST` | `/users/security/ban/:uuid` | `deleteAny` | Ban for `duration` seconds + revoke sessions |
41
+ | `POST` | `/users/security/unban/:uuid` | `updateAny` | Lift a ban |
42
+ | `POST` | `/users/security/unlock/:uuid` | `updateAny` | Clear a login-throttle lockout |
43
+ | `GET` | `/users/security/sessions/:uuid` | `readAny` | Live sessions, by opaque handle |
44
+ | `DELETE` | `/users/security/sessions/:uuid/:handle` | `updateAny` | Revoke one session |
45
+ | `DELETE` | `/users/security/sessions/:uuid` | `updateAny` | Revoke every session of the user |
46
+
47
+ User metadata is NOT managed here — `@spinajs/rbac-http-user` owns `/user/:uuid/metadata`, which
48
+ validates one entry at a time.
49
+
50
+ ## Handing a new account to its owner
51
+
52
+ `POST /users` creates the account **inactive** and throws the generated temporary password away, so a
53
+ created account cannot be logged into yet. The intended flow is:
54
+
55
+ 1. `POST /users`
56
+ 2. `POST /users/security/password-reset-request/:uuid` — the application delivers the token by
57
+ hooking `UserPasswordChangeRequest`
58
+ 3. the user sets their own password through `POST /auth/password/reset`
59
+ 4. `POST /users/security/activate/:uuid`
60
+
61
+ ## Role guard
62
+
63
+ Role changes are the one operation in this API that can grant MORE than the caller holds, so they run
64
+ through a `RoleGuard` service first. Configure it under `rbac.admin.roleGuard`:
65
+
66
+ ```js
67
+ rbac: {
68
+ admin: {
69
+ roleGuard: {
70
+ service: 'DefaultRoleGuard',
71
+
72
+ // reject role names not declared in rbac.grants / rbac.roles
73
+ requireKnownRole: true,
74
+ // rbac.systemRole is never assignable or revocable over HTTP
75
+ protectSystemRole: true,
76
+ // a role whose grants exceed the caller's cannot be handed out
77
+ preventEscalation: true,
78
+ // no self-deactivation, self-deletion, self-ban, self-demotion
79
+ preventSelfLockout: true,
80
+ // never empty a privileged role of its last active holder
81
+ preventLastPrivilegedRemoval: true,
82
+
83
+ // what counts as "privileged" for the two checks above
84
+ privilegedResource: 'users',
85
+ privilegedAction: 'update:any',
86
+ },
87
+ },
88
+ }
11
89
  ```
90
+
91
+ Replace the whole policy by registering your own class under the `RoleGuard` base and naming it in
92
+ `service`:
93
+
94
+ ```ts
95
+ @Injectable(RoleGuard)
96
+ export class MyRoleGuard extends RoleGuard { /* ... */ }
97
+ ```
98
+
99
+ ## Breaking changes in this release
100
+
101
+ - `activate`, `deactivate` and the forced logout moved off `GET`. They are now
102
+ `POST /users/security/activate/:uuid`, `POST /users/security/deactivate/:uuid` and
103
+ `DELETE /users/security/sessions/:uuid`.
104
+ - `activate` now requires `updateAny` instead of `deleteAny`.
105
+ - `GET /users/:uuid` and `GET /users/byLogin/:login` now require `readAny`. They previously required
106
+ nothing beyond a valid session — any authenticated account could read any other.
107
+ - `PATCH /users/:uuid` no longer accepts `Metadata`, and its body is validated as a partial update
108
+ ( `Login`, `Email`, `Role` are all optional, unknown properties are rejected ).
109
+ - Credential-bearing metadata ( password-reset token, 2FA secret, ban and lockout state ) is filtered
110
+ out of every dehydrated user, in this package and everywhere else.
@@ -6,6 +6,31 @@ declare const rbacHttpAdmin: {
6
6
  views: string[];
7
7
  };
8
8
  };
9
+ rbac: {
10
+ admin: {
11
+ /**
12
+ * Guards applied to every admin operation that changes what an account may
13
+ * do. Defaults are the strict end — see IRoleGuardConfig for what each one
14
+ * refuses and why. Turn individual checks off here rather than replacing
15
+ * the service.
16
+ */
17
+ roleGuard: {
18
+ service: string;
19
+ requireKnownRole: boolean;
20
+ protectSystemRole: boolean;
21
+ preventEscalation: boolean;
22
+ preventSelfLockout: boolean;
23
+ preventLastPrivilegedRemoval: boolean;
24
+ /**
25
+ * What makes a role "privileged" for the self-lockout and last-holder
26
+ * checks. Action uses accesscontrol grant notation, exactly as written
27
+ * in `rbac.grants`.
28
+ */
29
+ privilegedResource: string;
30
+ privilegedAction: string;
31
+ };
32
+ };
33
+ };
9
34
  };
10
35
  export default rbacHttpAdmin;
11
36
  //# sourceMappingURL=rbac-http-admin.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"rbac-http-admin.d.ts","sourceRoot":"","sources":["../../../src/config/rbac-http-admin.ts"],"names":[],"mappings":"AAOA,QAAA,MAAM,aAAa;;;;;;;;CAQlB,CAAC;AAEF,eAAe,aAAa,CAAC"}
1
+ {"version":3,"file":"rbac-http-admin.d.ts","sourceRoot":"","sources":["../../../src/config/rbac-http-admin.ts"],"names":[],"mappings":"AAOA,QAAA,MAAM,aAAa;;;;;;;;;;YAWb;;;;;eAKG;;;;;;;;gBAUD;;;;mBAIG;;;;;;CAMV,CAAC;AAEF,eAAe,aAAa,CAAC"}
@@ -13,6 +13,31 @@ const rbacHttpAdmin = {
13
13
  views: [dir('views')],
14
14
  },
15
15
  },
16
+ rbac: {
17
+ admin: {
18
+ /**
19
+ * Guards applied to every admin operation that changes what an account may
20
+ * do. Defaults are the strict end — see IRoleGuardConfig for what each one
21
+ * refuses and why. Turn individual checks off here rather than replacing
22
+ * the service.
23
+ */
24
+ roleGuard: {
25
+ service: 'DefaultRoleGuard',
26
+ requireKnownRole: true,
27
+ protectSystemRole: true,
28
+ preventEscalation: true,
29
+ preventSelfLockout: true,
30
+ preventLastPrivilegedRemoval: true,
31
+ /**
32
+ * What makes a role "privileged" for the self-lockout and last-holder
33
+ * checks. Action uses accesscontrol grant notation, exactly as written
34
+ * in `rbac.grants`.
35
+ */
36
+ privilegedResource: 'users',
37
+ privilegedAction: 'update:any',
38
+ },
39
+ },
40
+ },
16
41
  };
17
42
  exports.default = rbacHttpAdmin;
18
43
  //# sourceMappingURL=rbac-http-admin.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"rbac-http-admin.js","sourceRoot":"","sources":["../../../src/config/rbac-http-admin.ts"],"names":[],"mappings":";;AAAA,+BAAgD;AAEhD,SAAS,GAAG,CAAC,IAAY;IACvB,MAAM,UAAU,GAAG,OAAO,MAAM,KAAK,WAAW,CAAC;IACjD,OAAO,IAAA,cAAO,EAAC,IAAA,gBAAS,EAAC,IAAA,WAAI,EAAC,OAAO,CAAC,GAAG,CAAC,mBAAmB,IAAI,OAAO,CAAC,GAAG,EAAE,EAAE,cAAc,EAAE,UAAU,EAAE,iBAAiB,EAAE,KAAK,EAAE,UAAU,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC;AAC5K,CAAC;AAED,MAAM,aAAa,GAAG;IACpB,MAAM,EAAE;QACN,IAAI,EAAE;YACJ,WAAW,EAAE,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC;YACjC,OAAO,EAAE,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;YACzB,KAAK,EAAE,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;SACtB;KACF;CACF,CAAC;AAEF,kBAAe,aAAa,CAAC"}
1
+ {"version":3,"file":"rbac-http-admin.js","sourceRoot":"","sources":["../../../src/config/rbac-http-admin.ts"],"names":[],"mappings":";;AAAA,+BAAgD;AAEhD,SAAS,GAAG,CAAC,IAAY;IACvB,MAAM,UAAU,GAAG,OAAO,MAAM,KAAK,WAAW,CAAC;IACjD,OAAO,IAAA,cAAO,EAAC,IAAA,gBAAS,EAAC,IAAA,WAAI,EAAC,OAAO,CAAC,GAAG,CAAC,mBAAmB,IAAI,OAAO,CAAC,GAAG,EAAE,EAAE,cAAc,EAAE,UAAU,EAAE,iBAAiB,EAAE,KAAK,EAAE,UAAU,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC;AAC5K,CAAC;AAED,MAAM,aAAa,GAAG;IACpB,MAAM,EAAE;QACN,IAAI,EAAE;YACJ,WAAW,EAAE,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC;YACjC,OAAO,EAAE,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;YACzB,KAAK,EAAE,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;SACtB;KACF;IAED,IAAI,EAAE;QACJ,KAAK,EAAE;YACL;;;;;eAKG;YACH,SAAS,EAAE;gBACT,OAAO,EAAE,kBAAkB;gBAE3B,gBAAgB,EAAE,IAAI;gBACtB,iBAAiB,EAAE,IAAI;gBACvB,iBAAiB,EAAE,IAAI;gBACvB,kBAAkB,EAAE,IAAI;gBACxB,4BAA4B,EAAE,IAAI;gBAElC;;;;mBAIG;gBACH,kBAAkB,EAAE,OAAO;gBAC3B,gBAAgB,EAAE,YAAY;aAC/B;SACF;KACF;CACF,CAAC;AAEF,kBAAe,aAAa,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"Profile.d.ts","sourceRoot":"","sources":["../../../../src/controllers/Users/Profile.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAiB,EAAE,EAAiB,MAAM,eAAe,CAAC;AACjF,OAAO,EAAS,mBAAmB,EAAE,MAAM,eAAe,CAAC;AAI3D;;;;GAIG;AACH,qBAGa,OAAQ,SAAQ,cAAc;IASvC,SAAS,CAAC,cAAc,EAAE,mBAAmB,CAAC;IAE9C;;;;;;;;;;OAUG;IAGU,cAAc,CAAU,KAAK,EAAE,MAAM;CAGrD"}
1
+ {"version":3,"file":"Profile.d.ts","sourceRoot":"","sources":["../../../../src/controllers/Users/Profile.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAiB,EAAE,EAAiB,MAAM,eAAe,CAAC;AACjF,OAAO,EAAS,mBAAmB,EAAE,MAAM,eAAe,CAAC;AAG3D;;;;GAIG;AACH,qBAGa,OAAQ,SAAQ,cAAc;IAOzC,SAAS,CAAC,cAAc,EAAE,mBAAmB,CAAC;IAE9C;;;;;;;;;;OAUG;IAGU,cAAc,CAAU,KAAK,EAAE,MAAM;CAKnD"}
@@ -35,7 +35,9 @@ let Profile = class Profile extends http_1.BaseController {
35
35
  * @response 404 User not found
36
36
  */
37
37
  async getUserProfile(login) {
38
- return new http_1.Ok(this.ProfileService.retrieve(login));
38
+ // NOTE: awaited. Handing the pending promise to `Ok` serialized as an
39
+ // empty object for every client that got JSON back.
40
+ return new http_1.Ok(await this.ProfileService.retrieve(login));
39
41
  }
40
42
  };
41
43
  exports.Profile = Profile;
@@ -1 +1 @@
1
- {"version":3,"file":"Profile.js","sourceRoot":"","sources":["../../../../src/controllers/Users/Profile.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AAAA,0DAA2D;AAC3D,wCAAiF;AACjF,wCAA2D;AAC3D,kDAA4E;AAG5E;;;;GAIG;AAII,IAAM,OAAO,GAAb,MAAM,OAAQ,SAAQ,qBAAc;IAWvC;;;;;;;;;;OAUG;IAGU,AAAN,KAAK,CAAC,cAAc,CAAU,KAAa;QAC7C,OAAO,IAAI,SAAE,CAAC,IAAI,CAAC,cAAc,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC;IACxD,CAAC;CACJ,CAAA;AA3BY,0BAAO;AASN;IADT,IAAA,iCAAiB,EAAC,mBAAmB,CAAC;8BACb,0BAAmB;+CAAC;AAejC;IAFZ,IAAA,UAAG,EAAC,QAAQ,CAAC;IACb,IAAA,sBAAU,EAAC,CAAC,SAAS,CAAC,CAAC;IACK,WAAA,IAAA,YAAK,GAAE,CAAA;;;;6CAEnC;kBA1BQ,OAAO;IAHnB,IAAA,eAAQ,EAAC,eAAe,CAAC;IACzB,IAAA,aAAM,EAAC,4BAAgB,CAAC;IACxB,IAAA,oBAAQ,EAAC,OAAO,CAAC;GACL,OAAO,CA2BnB"}
1
+ {"version":3,"file":"Profile.js","sourceRoot":"","sources":["../../../../src/controllers/Users/Profile.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AAAA,0DAA2D;AAC3D,wCAAiF;AACjF,wCAA2D;AAC3D,kDAA4E;AAE5E;;;;GAIG;AAII,IAAM,OAAO,GAAb,MAAM,OAAQ,SAAQ,qBAAc;IASzC;;;;;;;;;;OAUG;IAGU,AAAN,KAAK,CAAC,cAAc,CAAU,KAAa;QAChD,sEAAsE;QACtE,oDAAoD;QACpD,OAAO,IAAI,SAAE,CAAC,MAAM,IAAI,CAAC,cAAc,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC;IAC3D,CAAC;CACF,CAAA;AA3BY,0BAAO;AAOR;IADT,IAAA,iCAAiB,EAAC,mBAAmB,CAAC;8BACb,0BAAmB;+CAAC;AAejC;IAFZ,IAAA,UAAG,EAAC,QAAQ,CAAC;IACb,IAAA,sBAAU,EAAC,CAAC,SAAS,CAAC,CAAC;IACK,WAAA,IAAA,YAAK,GAAE,CAAA;;;;6CAInC;kBA1BU,OAAO;IAHnB,IAAA,eAAQ,EAAC,eAAe,CAAC;IACzB,IAAA,aAAM,EAAC,4BAAgB,CAAC;IACxB,IAAA,oBAAQ,EAAC,OAAO,CAAC;GACL,OAAO,CA2BnB"}
@@ -1,38 +1,45 @@
1
1
  import { BaseController, Ok } from '@spinajs/http';
2
- declare class RoleDto {
2
+ import { User } from '@spinajs/rbac';
3
+ import { RoleGuard } from '../../interfaces.js';
4
+ import '../../services/RoleGuard.js';
5
+ export declare class RoleDto {
3
6
  role: string;
4
7
  constructor(data: Partial<RoleDto>);
5
8
  }
6
9
  /**
7
10
  * User role management (admin).
8
11
  * Grants and revokes RBAC roles for user accounts.
12
+ *
13
+ * Both routes run the configured {@link RoleGuard} before touching anything: a
14
+ * role is the one thing in this API that can grant MORE than the caller has, so
15
+ * "may update users" is not by itself an answer to "may hand out this role".
9
16
  * @tags Admin Users
10
17
  */
11
18
  export declare class Roles extends BaseController {
19
+ protected RoleGuard: RoleGuard;
12
20
  /**
13
21
  * Grant role to user (admin)
14
22
  * Assigns the specified RBAC role to the user identified by login name.
15
23
  * @security cookieAuth
16
24
  * @param login User login name
17
25
  * @response 200 Role granted successfully
18
- * @response 400 Invalid role name
26
+ * @response 400 Unknown role name
19
27
  * @response 401 Unauthorized — valid session required
20
- * @response 403 Forbidden — updateAny permission required on users resource
28
+ * @response 403 Forbidden — updateAny permission required, or the role grants more than the caller holds
21
29
  * @response 404 User not found
22
30
  */
23
- addRole(login: string, roleDto: RoleDto): Promise<Ok<any>>;
31
+ addRole(actor: User, user: User, roleDto: RoleDto): Promise<Ok<any>>;
24
32
  /**
25
33
  * Revoke role from user (admin)
26
34
  * Removes the specified RBAC role from the user identified by login name.
27
35
  * @security cookieAuth
28
36
  * @param login User login name
29
37
  * @response 200 Role revoked successfully
30
- * @response 400 Invalid role name
38
+ * @response 400 Unknown role name
31
39
  * @response 401 Unauthorized — valid session required
32
- * @response 403 Forbidden — updateAny permission required on users resource
40
+ * @response 403 Forbidden — updateAny permission required, or the revocation would lock the caller or the installation out
33
41
  * @response 404 User not found
34
42
  */
35
- revokeRole(login: string, roleDto: RoleDto): Promise<Ok<any>>;
43
+ revokeRole(actor: User, user: User, roleDto: RoleDto): Promise<Ok<any>>;
36
44
  }
37
- export {};
38
45
  //# sourceMappingURL=Roles.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"Roles.d.ts","sourceRoot":"","sources":["../../../../src/controllers/Users/Roles.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAkB,EAAE,EAAwB,MAAM,eAAe,CAAC;AAMzF,cAQM,OAAO;IACF,IAAI,EAAE,MAAM,CAAC;gBAER,IAAI,EAAE,OAAO,CAAC,OAAO,CAAC;CAGrC;AAGD;;;;GAIG;AACH,qBAGa,KAAM,SAAQ,cAAc;IACrC;;;;;;;;;;OAUG;IAGU,OAAO,CAAU,KAAK,EAAE,MAAM,EAAU,OAAO,EAAE,OAAO;IAKrE;;;;;;;;;;OAUG;IAGU,UAAU,CAAU,KAAK,EAAE,MAAM,EAAU,OAAO,EAAE,OAAO;CAI3E"}
1
+ {"version":3,"file":"Roles.d.ts","sourceRoot":"","sources":["../../../../src/controllers/Users/Roles.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAkB,EAAE,EAAiB,MAAM,eAAe,CAAC;AAElF,OAAO,EAAiB,IAAI,EAAE,MAAM,eAAe,CAAC;AAIpD,OAAO,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAGhD,OAAO,6BAA6B,CAAC;AAErC,qBAQa,OAAO;IACX,IAAI,EAAE,MAAM,CAAC;gBAER,IAAI,EAAE,OAAO,CAAC,OAAO,CAAC;CAGnC;AAED;;;;;;;;GAQG;AACH,qBAGa,KAAM,SAAQ,cAAc;IAEvC,SAAS,CAAC,SAAS,EAAE,SAAS,CAAC;IAE/B;;;;;;;;;;OAUG;IAGU,OAAO,CAAgB,KAAK,EAAE,IAAI,EAAkF,IAAI,EAAE,IAAI,EAAU,OAAO,EAAE,OAAO;IAOrK;;;;;;;;;;OAUG;IAGU,UAAU,CAAgB,KAAK,EAAE,IAAI,EAAkF,IAAI,EAAE,IAAI,EAAU,OAAO,EAAE,OAAO;CAMzK"}
@@ -12,17 +12,23 @@ var __param = (this && this.__param) || function (paramIndex, decorator) {
12
12
  return function (target, key) { decorator(target, key, paramIndex); }
13
13
  };
14
14
  Object.defineProperty(exports, "__esModule", { value: true });
15
- exports.Roles = void 0;
15
+ exports.Roles = exports.RoleDto = void 0;
16
+ const configuration_1 = require("@spinajs/configuration");
16
17
  const http_1 = require("@spinajs/http");
18
+ const orm_http_1 = require("@spinajs/orm-http");
17
19
  const rbac_1 = require("@spinajs/rbac");
18
20
  const rbac_http_1 = require("@spinajs/rbac-http");
19
21
  const validation_1 = require("@spinajs/validation");
22
+ const interfaces_js_1 = require("../../interfaces.js");
23
+ // Side effect only — see the note in Users.ts.
24
+ require("../../services/RoleGuard.js");
20
25
  let RoleDto = class RoleDto {
21
26
  constructor(data) {
22
27
  Object.assign(this, data);
23
28
  }
24
29
  };
25
- RoleDto = __decorate([
30
+ exports.RoleDto = RoleDto;
31
+ exports.RoleDto = RoleDto = __decorate([
26
32
  (0, validation_1.Schema)({
27
33
  type: 'object',
28
34
  $id: 'arrow.common.roleDTO',
@@ -36,6 +42,10 @@ RoleDto = __decorate([
36
42
  /**
37
43
  * User role management (admin).
38
44
  * Grants and revokes RBAC roles for user accounts.
45
+ *
46
+ * Both routes run the configured {@link RoleGuard} before touching anything: a
47
+ * role is the one thing in this API that can grant MORE than the caller has, so
48
+ * "may update users" is not by itself an answer to "may hand out this role".
39
49
  * @tags Admin Users
40
50
  */
41
51
  let Roles = class Roles extends http_1.BaseController {
@@ -45,13 +55,14 @@ let Roles = class Roles extends http_1.BaseController {
45
55
  * @security cookieAuth
46
56
  * @param login User login name
47
57
  * @response 200 Role granted successfully
48
- * @response 400 Invalid role name
58
+ * @response 400 Unknown role name
49
59
  * @response 401 Unauthorized — valid session required
50
- * @response 403 Forbidden — updateAny permission required on users resource
60
+ * @response 403 Forbidden — updateAny permission required, or the role grants more than the caller holds
51
61
  * @response 404 User not found
52
62
  */
53
- async addRole(login, roleDto) {
54
- await (0, rbac_1.grant)(login, roleDto.role);
63
+ async addRole(actor, user, roleDto) {
64
+ await this.RoleGuard.assertCanAssignRoles(actor, user, [roleDto.role]);
65
+ await (0, rbac_1.grant)(user, roleDto.role);
55
66
  return new http_1.Ok();
56
67
  }
57
68
  /**
@@ -60,33 +71,40 @@ let Roles = class Roles extends http_1.BaseController {
60
71
  * @security cookieAuth
61
72
  * @param login User login name
62
73
  * @response 200 Role revoked successfully
63
- * @response 400 Invalid role name
74
+ * @response 400 Unknown role name
64
75
  * @response 401 Unauthorized — valid session required
65
- * @response 403 Forbidden — updateAny permission required on users resource
76
+ * @response 403 Forbidden — updateAny permission required, or the revocation would lock the caller or the installation out
66
77
  * @response 404 User not found
67
78
  */
68
- async revokeRole(login, roleDto) {
69
- await (0, rbac_1.revoke)(login, roleDto.role);
79
+ async revokeRole(actor, user, roleDto) {
80
+ await this.RoleGuard.assertCanRevokeRole(actor, user, roleDto.role);
81
+ await (0, rbac_1.revoke)(user, roleDto.role);
70
82
  return new http_1.Ok();
71
83
  }
72
84
  };
73
85
  exports.Roles = Roles;
86
+ __decorate([
87
+ (0, configuration_1.AutoinjectService)('rbac.admin.roleGuard'),
88
+ __metadata("design:type", interfaces_js_1.RoleGuard)
89
+ ], Roles.prototype, "RoleGuard", void 0);
74
90
  __decorate([
75
91
  (0, http_1.Patch)('add/:login'),
76
92
  (0, rbac_http_1.Permission)(['updateAny']),
77
- __param(0, (0, http_1.Param)()),
78
- __param(1, (0, http_1.Body)()),
93
+ __param(0, (0, rbac_http_1.User)()),
94
+ __param(1, (0, orm_http_1.FromModel)({ queryField: 'Login', paramField: 'login', include: ['Metadata'] })),
95
+ __param(2, (0, http_1.Body)()),
79
96
  __metadata("design:type", Function),
80
- __metadata("design:paramtypes", [String, RoleDto]),
97
+ __metadata("design:paramtypes", [rbac_1.User, rbac_1.User, RoleDto]),
81
98
  __metadata("design:returntype", Promise)
82
99
  ], Roles.prototype, "addRole", null);
83
100
  __decorate([
84
101
  (0, http_1.Patch)('revoke/:login'),
85
102
  (0, rbac_http_1.Permission)(['updateAny']),
86
- __param(0, (0, http_1.Param)()),
87
- __param(1, (0, http_1.Body)()),
103
+ __param(0, (0, rbac_http_1.User)()),
104
+ __param(1, (0, orm_http_1.FromModel)({ queryField: 'Login', paramField: 'login', include: ['Metadata'] })),
105
+ __param(2, (0, http_1.Body)()),
88
106
  __metadata("design:type", Function),
89
- __metadata("design:paramtypes", [String, RoleDto]),
107
+ __metadata("design:paramtypes", [rbac_1.User, rbac_1.User, RoleDto]),
90
108
  __metadata("design:returntype", Promise)
91
109
  ], Roles.prototype, "revokeRole", null);
92
110
  exports.Roles = Roles = __decorate([
@@ -1 +1 @@
1
- {"version":3,"file":"Roles.js","sourceRoot":"","sources":["../../../../src/controllers/Users/Roles.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AAAA,wCAAyF;AACzF,wCAAqD;AACrD,kDAA4E;AAC5E,oDAA6C;AAG7C,IAQM,OAAO,GARb,MAQM,OAAO;IAGT,YAAY,IAAsB;QAC9B,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;IAC9B,CAAC;CACJ,CAAA;AANK,OAAO;IARZ,IAAA,mBAAM,EAAC;QACJ,IAAI,EAAE,QAAQ;QACd,GAAG,EAAE,sBAAsB;QAC3B,UAAU,EAAE;YACR,IAAI,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,SAAS,EAAE,CAAC,EAAE,SAAS,EAAE,EAAE,EAAE,WAAW,EAAE,mCAAmC,EAAE;SAC1G;QACD,QAAQ,EAAE,CAAC,MAAM,CAAC;KACrB,CAAC;;GACI,OAAO,CAMZ;AAGD;;;;GAIG;AAII,IAAM,KAAK,GAAX,MAAM,KAAM,SAAQ,qBAAc;IACrC;;;;;;;;;;OAUG;IAGU,AAAN,KAAK,CAAC,OAAO,CAAU,KAAa,EAAU,OAAgB;QACjE,MAAM,IAAA,YAAK,EAAC,KAAK,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;QACjC,OAAO,IAAI,SAAE,EAAE,CAAA;IACnB,CAAC;IAED;;;;;;;;;;OAUG;IAGU,AAAN,KAAK,CAAC,UAAU,CAAU,KAAa,EAAU,OAAgB;QACpE,MAAM,IAAA,aAAM,EAAC,KAAK,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;QAClC,OAAO,IAAI,SAAE,EAAE,CAAA;IACnB,CAAC;CACJ,CAAA;AApCY,sBAAK;AAcD;IAFZ,IAAA,YAAK,EAAC,YAAY,CAAC;IACnB,IAAA,sBAAU,EAAC,CAAC,WAAW,CAAC,CAAC;IACJ,WAAA,IAAA,YAAK,GAAE,CAAA;IAAiB,WAAA,IAAA,WAAI,GAAE,CAAA;;6CAAU,OAAO;;oCAGpE;AAeY;IAFZ,IAAA,YAAK,EAAC,eAAe,CAAC;IACtB,IAAA,sBAAU,EAAC,CAAC,WAAW,CAAC,CAAC;IACD,WAAA,IAAA,YAAK,GAAE,CAAA;IAAiB,WAAA,IAAA,WAAI,GAAE,CAAA;;6CAAU,OAAO;;uCAGvE;gBAnCQ,KAAK;IAHjB,IAAA,eAAQ,EAAC,YAAY,CAAC;IACtB,IAAA,aAAM,EAAC,4BAAgB,CAAC;IACxB,IAAA,oBAAQ,EAAC,OAAO,CAAC;GACL,KAAK,CAoCjB"}
1
+ {"version":3,"file":"Roles.js","sourceRoot":"","sources":["../../../../src/controllers/Users/Roles.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AAAA,0DAA2D;AAC3D,wCAAkF;AAClF,gDAA8C;AAC9C,wCAAoD;AACpD,kDAAiG;AACjG,oDAA6C;AAE7C,uDAAgD;AAEhD,+CAA+C;AAC/C,uCAAqC;AAU9B,IAAM,OAAO,GAAb,MAAM,OAAO;IAGlB,YAAY,IAAsB;QAChC,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;IAC5B,CAAC;CACF,CAAA;AANY,0BAAO;kBAAP,OAAO;IARnB,IAAA,mBAAM,EAAC;QACN,IAAI,EAAE,QAAQ;QACd,GAAG,EAAE,sBAAsB;QAC3B,UAAU,EAAE;YACV,IAAI,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,SAAS,EAAE,CAAC,EAAE,SAAS,EAAE,EAAE,EAAE,WAAW,EAAE,mCAAmC,EAAE;SACxG;QACD,QAAQ,EAAE,CAAC,MAAM,CAAC;KACnB,CAAC;;GACW,OAAO,CAMnB;AAED;;;;;;;;GAQG;AAII,IAAM,KAAK,GAAX,MAAM,KAAM,SAAQ,qBAAc;IAIvC;;;;;;;;;;OAUG;IAGU,AAAN,KAAK,CAAC,OAAO,CAAgB,KAAW,EAAkF,IAAU,EAAU,OAAgB;QACnK,MAAM,IAAI,CAAC,SAAS,CAAC,oBAAoB,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;QACvE,MAAM,IAAA,YAAK,EAAC,IAAI,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;QAEhC,OAAO,IAAI,SAAE,EAAE,CAAC;IAClB,CAAC;IAED;;;;;;;;;;OAUG;IAGU,AAAN,KAAK,CAAC,UAAU,CAAgB,KAAW,EAAkF,IAAU,EAAU,OAAgB;QACtK,MAAM,IAAI,CAAC,SAAS,CAAC,mBAAmB,CAAC,KAAK,EAAE,IAAI,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;QACpE,MAAM,IAAA,aAAM,EAAC,IAAI,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;QAEjC,OAAO,IAAI,SAAE,EAAE,CAAC;IAClB,CAAC;CACF,CAAA;AA3CY,sBAAK;AAEN;IADT,IAAA,iCAAiB,EAAC,sBAAsB,CAAC;8BACrB,yBAAS;wCAAC;AAelB;IAFZ,IAAA,YAAK,EAAC,YAAY,CAAC;IACnB,IAAA,sBAAU,EAAC,CAAC,WAAW,CAAC,CAAC;IACJ,WAAA,IAAA,gBAAW,GAAE,CAAA;IAAe,WAAA,IAAA,oBAAS,EAAC,EAAE,UAAU,EAAE,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC,UAAU,CAAC,EAAE,CAAC,CAAA;IAAc,WAAA,IAAA,WAAI,GAAE,CAAA;;qCAAzG,WAAI,EAAwF,WAAI,EAAmB,OAAO;;oCAKpK;AAeY;IAFZ,IAAA,YAAK,EAAC,eAAe,CAAC;IACtB,IAAA,sBAAU,EAAC,CAAC,WAAW,CAAC,CAAC;IACD,WAAA,IAAA,gBAAW,GAAE,CAAA;IAAe,WAAA,IAAA,oBAAS,EAAC,EAAE,UAAU,EAAE,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC,UAAU,CAAC,EAAE,CAAC,CAAA;IAAc,WAAA,IAAA,WAAI,GAAE,CAAA;;qCAAzG,WAAI,EAAwF,WAAI,EAAmB,OAAO;;uCAKvK;gBA1CU,KAAK;IAHjB,IAAA,eAAQ,EAAC,YAAY,CAAC;IACtB,IAAA,aAAM,EAAC,4BAAgB,CAAC;IACxB,IAAA,oBAAQ,EAAC,OAAO,CAAC;GACL,KAAK,CA2CjB"}
@@ -1,22 +1,51 @@
1
- import { BaseController, Ok } from '@spinajs/http';
1
+ import { BaseController, NotFound, Ok } from '@spinajs/http';
2
2
  import { SessionProvider, User } from '@spinajs/rbac';
3
- declare class ChangePasswordDto {
3
+ import type { ISession } from '@spinajs/rbac';
4
+ import { Log } from '@spinajs/log';
5
+ import { RoleGuard } from '../../interfaces.js';
6
+ import '../../services/RoleGuard.js';
7
+ export declare class ChangePasswordDto {
4
8
  password: string;
5
9
  confirmPassword: string;
6
10
  constructor(data: any);
7
11
  }
12
+ export declare class BanUserDto {
13
+ reason?: string;
14
+ duration?: number;
15
+ constructor(data: Partial<BanUserDto>);
16
+ }
17
+ /** One live session of a user, as reported to an administrator. */
18
+ export interface IAdminSessionEntry {
19
+ /**
20
+ * Opaque handle for the session, NOT the session id — the id is a working
21
+ * credential and an admin listing must not hand out the means to
22
+ * impersonate the accounts it lists.
23
+ */
24
+ Handle: string;
25
+ /** ISO instant the session was opened */
26
+ Created: string;
27
+ /** ISO instant the session expires, or null when it never does */
28
+ Expires: string | null;
29
+ }
8
30
  /**
9
31
  * User account security management (admin).
10
- * Administrative controls for user account security: password changes, 2FA reset,
11
- * account activation/deactivation, and forced session logout.
32
+ * Administrative controls for user account security: passwords, 2FA, account
33
+ * activation, bans, login lockouts and live sessions.
34
+ *
35
+ * Every route that takes an account out of service goes through the configured
36
+ * {@link RoleGuard} first — an administrator must not be able to lock themselves,
37
+ * or the installation, out through this API.
12
38
  * @tags Admin Users
13
39
  */
14
40
  export declare class Security extends BaseController {
41
+ protected Log: Log;
15
42
  protected SessionProvider: SessionProvider;
43
+ protected RoleGuard: RoleGuard;
16
44
  /**
17
45
  * Change user password (admin)
18
46
  * Sets a new password for the specified user. Both password and confirmPassword must match.
19
- * Minimum length is 8 characters.
47
+ * Minimum length is 8 characters. Every session of that user is destroyed — the credential
48
+ * they were opened with no longer exists.
20
49
  * @security cookieAuth
21
50
  * @param user User UUID path parameter
22
51
  * @response 200 Password changed successfully
@@ -26,6 +55,31 @@ export declare class Security extends BaseController {
26
55
  * @response 404 User not found
27
56
  */
28
57
  changeUserPassword(user: User, dto: ChangePasswordDto): Promise<Ok<any>>;
58
+ /**
59
+ * Send a password reset link (admin)
60
+ * Issues a single-use reset token into the user's metadata and emits
61
+ * `UserPasswordChangeRequest` so the application can deliver it. The token itself is never
62
+ * returned. This is how a freshly created account is handed over to its owner — the
63
+ * temporary password generated at creation is deliberately discarded.
64
+ * @security cookieAuth
65
+ * @param user User UUID path parameter
66
+ * @response 200 Reset token issued
67
+ * @response 401 Unauthorized — valid session required
68
+ * @response 403 Forbidden — updateAny permission required on users resource
69
+ * @response 404 User not found
70
+ */
71
+ requestPasswordReset(user: User): Promise<Ok<any>>;
72
+ /**
73
+ * Expire a user password (admin)
74
+ * Marks the password as expired, which deactivates the account until a new one is set.
75
+ * @security cookieAuth
76
+ * @param user User UUID path parameter
77
+ * @response 200 Password expired
78
+ * @response 401 Unauthorized — valid session required
79
+ * @response 403 Forbidden — deleteAny permission required, or refused by the role guard
80
+ * @response 404 User not found
81
+ */
82
+ expireUserPassword(actor: User, user: User): Promise<Ok<any>>;
29
83
  /**
30
84
  * Reset user two-factor authentication (admin)
31
85
  * Clears the TOTP secret and disables 2FA for the specified user.
@@ -38,17 +92,42 @@ export declare class Security extends BaseController {
38
92
  * @response 404 User not found
39
93
  */
40
94
  reset2faToken(user: User): Promise<Ok<any>>;
95
+ /**
96
+ * Enable two-factor authentication for a user (admin)
97
+ * Initializes a TOTP secret for the account. Returns whatever the configured
98
+ * two-factor provider produces for enrolment (an otpauth url for the default provider) —
99
+ * deliver it to the user over a channel you trust.
100
+ * @security cookieAuth
101
+ * @param user User UUID path parameter
102
+ * @response 200 2FA enabled
103
+ * @response 401 Unauthorized — valid session required
104
+ * @response 403 Forbidden — updateAny permission required on users resource
105
+ * @response 404 User not found
106
+ */
107
+ enable2Fa(user: User): Promise<Ok<unknown>>;
108
+ /**
109
+ * Disable two-factor authentication for a user (admin)
110
+ * Removes the TOTP secret and turns the second factor off for the account.
111
+ * @security cookieAuth
112
+ * @param user User UUID path parameter
113
+ * @response 200 2FA disabled
114
+ * @response 401 Unauthorized — valid session required
115
+ * @response 403 Forbidden — updateAny permission required on users resource
116
+ * @response 404 User not found
117
+ */
118
+ disable2Fa(user: User): Promise<Ok<any>>;
41
119
  /**
42
120
  * Deactivate user account (admin)
43
- * Marks the user account as inactive, preventing login without deleting the record.
121
+ * Marks the user account as inactive and destroys its sessions, preventing login without
122
+ * deleting the record.
44
123
  * @security cookieAuth
45
124
  * @param user User UUID path parameter
46
125
  * @response 200 Account deactivated successfully
47
126
  * @response 401 Unauthorized — valid session required
48
- * @response 403 Forbidden — deleteAny permission required on users resource
127
+ * @response 403 Forbidden — deleteAny permission required, or refused by the role guard
49
128
  * @response 404 User not found
50
129
  */
51
- deactivateUser(user: User): Promise<Ok<any>>;
130
+ deactivateUser(actor: User, user: User): Promise<Ok<any>>;
52
131
  /**
53
132
  * Activate user account (admin)
54
133
  * Marks a previously deactivated user account as active, restoring login access.
@@ -56,10 +135,71 @@ export declare class Security extends BaseController {
56
135
  * @param user User UUID path parameter
57
136
  * @response 200 Account activated successfully
58
137
  * @response 401 Unauthorized — valid session required
59
- * @response 403 Forbidden — deleteAny permission required on users resource
138
+ * @response 403 Forbidden — updateAny permission required on users resource
60
139
  * @response 404 User not found
61
140
  */
62
141
  activateUser(user: User): Promise<Ok<any>>;
142
+ /**
143
+ * Ban a user (admin)
144
+ * Bans the account for `duration` seconds (24h when omitted), records the reason, and
145
+ * destroys every session it holds.
146
+ * @security cookieAuth
147
+ * @param user User UUID path parameter
148
+ * @response 200 Account banned
149
+ * @response 400 Account is already banned
150
+ * @response 401 Unauthorized — valid session required
151
+ * @response 403 Forbidden — deleteAny permission required, or refused by the role guard
152
+ * @response 404 User not found
153
+ */
154
+ banUser(actor: User, user: User, dto: BanUserDto): Promise<Ok<any>>;
155
+ /**
156
+ * Unban a user (admin)
157
+ * Clears the ban metadata from the account.
158
+ * @security cookieAuth
159
+ * @param user User UUID path parameter
160
+ * @response 200 Account unbanned
161
+ * @response 400 Account is not banned
162
+ * @response 401 Unauthorized — valid session required
163
+ * @response 403 Forbidden — updateAny permission required on users resource
164
+ * @response 404 User not found
165
+ */
166
+ unbanUser(user: User): Promise<Ok<any>>;
167
+ /**
168
+ * Clear a login lockout (admin)
169
+ * Removes the failed-attempt counter and the lockout window opened by the login throttle,
170
+ * letting the user try again immediately. Without this the only remedy is waiting out
171
+ * `rbac.password.lockoutTime`.
172
+ * @security cookieAuth
173
+ * @param user User UUID path parameter
174
+ * @response 200 Lockout cleared
175
+ * @response 401 Unauthorized — valid session required
176
+ * @response 403 Forbidden — updateAny permission required on users resource
177
+ * @response 404 User not found
178
+ */
179
+ unlockUser(user: User): Promise<Ok<any>>;
180
+ /**
181
+ * List sessions of a user (admin)
182
+ * Returns every live session of the account, newest first, identified by an opaque handle.
183
+ * @security cookieAuth
184
+ * @param user User UUID path parameter
185
+ * @returns {IAdminSessionEntry[]} Live sessions of the user
186
+ * @response 401 Unauthorized — valid session required
187
+ * @response 403 Forbidden — readAny permission required on users resource
188
+ * @response 404 User not found
189
+ */
190
+ listSessions(user: User): Promise<Ok<IAdminSessionEntry[]>>;
191
+ /**
192
+ * Revoke one session of a user (admin)
193
+ * Ends a single session, addressed by the handle returned from the listing.
194
+ * @security cookieAuth
195
+ * @param user User UUID path parameter
196
+ * @param handle Session handle as returned by `GET /users/security/sessions/:user`
197
+ * @response 200 Session revoked
198
+ * @response 401 Unauthorized — valid session required
199
+ * @response 403 Forbidden — updateAny permission required on users resource
200
+ * @response 404 No such session for this user
201
+ */
202
+ revokeSession(user: User, handle: string): Promise<Ok | NotFound>;
63
203
  /**
64
204
  * Force logout user (admin)
65
205
  * Invalidates all active sessions for the specified user, immediately ending any current logins.
@@ -70,7 +210,7 @@ export declare class Security extends BaseController {
70
210
  * @response 403 Forbidden — updateAny permission required on users resource
71
211
  * @response 404 User not found
72
212
  */
73
- logoutUser(user: User): Promise<Ok<any>>;
213
+ logoutUser(user: User): Promise<Ok<null>>;
214
+ protected toEntry(session: ISession): IAdminSessionEntry;
74
215
  }
75
- export {};
76
216
  //# sourceMappingURL=Security.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"Security.d.ts","sourceRoot":"","sources":["../../../../src/controllers/Users/Security.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAuB,EAAE,EAAiB,MAAM,eAAe,CAAC;AAEvF,OAAO,EAA+C,eAAe,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AAMnG,cAwBM,iBAAiB;IACZ,QAAQ,EAAE,MAAM,CAAC;IACjB,eAAe,EAAE,MAAM,CAAC;gBAEnB,IAAI,EAAE,GAAG;CAGxB;AAGD;;;;;GAKG;AACH,qBAGa,QAAS,SAAQ,cAAc;IAGxC,SAAS,CAAC,eAAe,EAAE,eAAe,CAAC;IAE3C;;;;;;;;;;;OAWG;IAGU,kBAAkB,CAAoC,IAAI,EAAE,IAAI,EAAU,GAAG,EAAE,iBAAiB;IAK7G;;;;;;;;;;OAUG;IAGU,aAAa,CAAoC,IAAI,EAAE,IAAI;IAKxE;;;;;;;;;OASG;IAGU,cAAc,CAAoC,IAAI,EAAE,IAAI;IAKzE;;;;;;;;;OASG;IAGU,YAAY,CAAoC,IAAI,EAAE,IAAI;IAKvE;;;;;;;;;OASG;IAGU,UAAU,CAAoC,IAAI,EAAE,IAAI;CAIxE"}
1
+ {"version":3,"file":"Security.d.ts","sourceRoot":"","sources":["../../../../src/controllers/Users/Security.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAA4B,QAAQ,EAAE,EAAE,EAA8B,MAAM,eAAe,CAAC;AACnH,OAAO,EAAmG,eAAe,EAAS,IAAI,EAAwB,MAAM,eAAe,CAAC;AACpL,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAK9C,OAAO,EAAE,GAAG,EAAU,MAAM,cAAc,CAAC;AAE3C,OAAO,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAGhD,OAAO,6BAA6B,CAAC;AAErC,qBAwBa,iBAAiB;IACrB,QAAQ,EAAE,MAAM,CAAC;IACjB,eAAe,EAAE,MAAM,CAAC;gBAEnB,IAAI,EAAE,GAAG;CAGtB;AAED,qBAQa,UAAU;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;gBAEb,IAAI,EAAE,OAAO,CAAC,UAAU,CAAC;CAGtC;AAED,mEAAmE;AACnE,MAAM,WAAW,kBAAkB;IACjC;;;;OAIG;IACH,MAAM,EAAE,MAAM,CAAC;IAEf,yCAAyC;IACzC,OAAO,EAAE,MAAM,CAAC;IAEhB,kEAAkE;IAClE,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;CACxB;AAED;;;;;;;;;GASG;AACH,qBAGa,QAAS,SAAQ,cAAc;IAE1C,SAAS,CAAC,GAAG,EAAE,GAAG,CAAC;IAGnB,SAAS,CAAC,eAAe,EAAE,eAAe,CAAC;IAG3C,SAAS,CAAC,SAAS,EAAE,SAAS,CAAC;IAE/B;;;;;;;;;;;;OAYG;IAGU,kBAAkB,CAA2D,IAAI,EAAE,IAAI,EAAU,GAAG,EAAE,iBAAiB;IAKpI;;;;;;;;;;;;OAYG;IAGU,oBAAoB,CAA2D,IAAI,EAAE,IAAI;IAKtG;;;;;;;;;OASG;IAGU,kBAAkB,CAAgB,KAAK,EAAE,IAAI,EAA4D,IAAI,EAAE,IAAI;IAShI;;;;;;;;;;OAUG;IAGU,aAAa,CAA2D,IAAI,EAAE,IAAI;IAK/F;;;;;;;;;;;OAWG;IAGU,SAAS,CAA2D,IAAI,EAAE,IAAI;IAI3F;;;;;;;;;OASG;IAGU,UAAU,CAA2D,IAAI,EAAE,IAAI;IAK5F;;;;;;;;;;OAUG;IAGU,cAAc,CAAgB,KAAK,EAAE,IAAI,EAA4D,IAAI,EAAE,IAAI;IAO5H;;;;;;;;;OASG;IAGU,YAAY,CAA2D,IAAI,EAAE,IAAI;IAK9F;;;;;;;;;;;OAWG;IAGU,OAAO,CAAgB,KAAK,EAAE,IAAI,EAA4D,IAAI,EAAE,IAAI,EAAU,GAAG,EAAE,UAAU;IAO9I;;;;;;;;;;OAUG;IAGU,SAAS,CAA2D,IAAI,EAAE,IAAI;IAK3F;;;;;;;;;;;OAWG;IAGU,UAAU,CAA2D,IAAI,EAAE,IAAI;IAS5F;;;;;;;;;OASG;IAGU,YAAY,CAAoC,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,EAAE,CAAC,kBAAkB,EAAE,CAAC,CAAC;IAQ3G;;;;;;;;;;OAUG;IAGU,aAAa,CAAoC,IAAI,EAAE,IAAI,EAAW,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,EAAE,GAAG,QAAQ,CAAC;IAiB1H;;;;;;;;;OASG;IAGU,UAAU,CAAoC,IAAI,EAAE,IAAI;IAQrE,SAAS,CAAC,OAAO,CAAC,OAAO,EAAE,QAAQ,GAAG,kBAAkB;CAOzD"}