@spinajs/rbac-http-token 2.0.507
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.
- package/README.md +152 -0
- package/lib/cjs/actions.d.ts +119 -0
- package/lib/cjs/actions.d.ts.map +1 -0
- package/lib/cjs/actions.js +257 -0
- package/lib/cjs/actions.js.map +1 -0
- package/lib/cjs/cli/CreateToken.d.ts +13 -0
- package/lib/cjs/cli/CreateToken.d.ts.map +1 -0
- package/lib/cjs/cli/CreateToken.js +56 -0
- package/lib/cjs/cli/CreateToken.js.map +1 -0
- package/lib/cjs/cli/DeleteExpiredTokens.d.ts +11 -0
- package/lib/cjs/cli/DeleteExpiredTokens.d.ts.map +1 -0
- package/lib/cjs/cli/DeleteExpiredTokens.js +39 -0
- package/lib/cjs/cli/DeleteExpiredTokens.js.map +1 -0
- package/lib/cjs/cli/DeleteToken.d.ts +7 -0
- package/lib/cjs/cli/DeleteToken.d.ts.map +1 -0
- package/lib/cjs/cli/DeleteToken.js +36 -0
- package/lib/cjs/cli/DeleteToken.js.map +1 -0
- package/lib/cjs/cli/GrantTokenRole.d.ts +7 -0
- package/lib/cjs/cli/GrantTokenRole.d.ts.map +1 -0
- package/lib/cjs/cli/GrantTokenRole.js +37 -0
- package/lib/cjs/cli/GrantTokenRole.js.map +1 -0
- package/lib/cjs/cli/RevokeTokenRole.d.ts +12 -0
- package/lib/cjs/cli/RevokeTokenRole.d.ts.map +1 -0
- package/lib/cjs/cli/RevokeTokenRole.js +42 -0
- package/lib/cjs/cli/RevokeTokenRole.js.map +1 -0
- package/lib/cjs/config/rbac-http-token.d.ts +71 -0
- package/lib/cjs/config/rbac-http-token.d.ts.map +1 -0
- package/lib/cjs/config/rbac-http-token.js +98 -0
- package/lib/cjs/config/rbac-http-token.js.map +1 -0
- package/lib/cjs/controllers/AccessTokenController.d.ts +139 -0
- package/lib/cjs/controllers/AccessTokenController.d.ts.map +1 -0
- package/lib/cjs/controllers/AccessTokenController.js +264 -0
- package/lib/cjs/controllers/AccessTokenController.js.map +1 -0
- package/lib/cjs/dto/create-token-dto.d.ts +34 -0
- package/lib/cjs/dto/create-token-dto.d.ts.map +1 -0
- package/lib/cjs/dto/create-token-dto.js +35 -0
- package/lib/cjs/dto/create-token-dto.js.map +1 -0
- package/lib/cjs/events/AccessTokenCreated.d.ts +4 -0
- package/lib/cjs/events/AccessTokenCreated.d.ts.map +1 -0
- package/lib/cjs/events/AccessTokenCreated.js +18 -0
- package/lib/cjs/events/AccessTokenCreated.js.map +1 -0
- package/lib/cjs/events/AccessTokenDeleted.d.ts +4 -0
- package/lib/cjs/events/AccessTokenDeleted.d.ts.map +1 -0
- package/lib/cjs/events/AccessTokenDeleted.js +18 -0
- package/lib/cjs/events/AccessTokenDeleted.js.map +1 -0
- package/lib/cjs/events/AccessTokenEvent.d.ts +10 -0
- package/lib/cjs/events/AccessTokenEvent.d.ts.map +1 -0
- package/lib/cjs/events/AccessTokenEvent.js +26 -0
- package/lib/cjs/events/AccessTokenEvent.js.map +1 -0
- package/lib/cjs/events/AccessTokenRoleGranted.d.ts +7 -0
- package/lib/cjs/events/AccessTokenRoleGranted.d.ts.map +1 -0
- package/lib/cjs/events/AccessTokenRoleGranted.js +27 -0
- package/lib/cjs/events/AccessTokenRoleGranted.js.map +1 -0
- package/lib/cjs/events/AccessTokenRoleRevoked.d.ts +7 -0
- package/lib/cjs/events/AccessTokenRoleRevoked.d.ts.map +1 -0
- package/lib/cjs/events/AccessTokenRoleRevoked.js +27 -0
- package/lib/cjs/events/AccessTokenRoleRevoked.js.map +1 -0
- package/lib/cjs/events/index.d.ts +6 -0
- package/lib/cjs/events/index.d.ts.map +1 -0
- package/lib/cjs/events/index.js +22 -0
- package/lib/cjs/events/index.js.map +1 -0
- package/lib/cjs/generator.d.ts +12 -0
- package/lib/cjs/generator.d.ts.map +1 -0
- package/lib/cjs/generator.js +42 -0
- package/lib/cjs/generator.js.map +1 -0
- package/lib/cjs/index.d.ts +20 -0
- package/lib/cjs/index.d.ts.map +1 -0
- package/lib/cjs/index.js +39 -0
- package/lib/cjs/index.js.map +1 -0
- package/lib/cjs/interfaces.d.ts +57 -0
- package/lib/cjs/interfaces.d.ts.map +1 -0
- package/lib/cjs/interfaces.js +11 -0
- package/lib/cjs/interfaces.js.map +1 -0
- package/lib/cjs/middlewares.d.ts +76 -0
- package/lib/cjs/middlewares.d.ts.map +1 -0
- package/lib/cjs/middlewares.js +181 -0
- package/lib/cjs/middlewares.js.map +1 -0
- package/lib/cjs/migrations/RbacHttpTokenInitial_2026_08_11_01_00_00.d.ts +6 -0
- package/lib/cjs/migrations/RbacHttpTokenInitial_2026_08_11_01_00_00.d.ts.map +1 -0
- package/lib/cjs/migrations/RbacHttpTokenInitial_2026_08_11_01_00_00.js +38 -0
- package/lib/cjs/migrations/RbacHttpTokenInitial_2026_08_11_01_00_00.js.map +1 -0
- package/lib/cjs/models/AccessToken.d.ts +55 -0
- package/lib/cjs/models/AccessToken.d.ts.map +1 -0
- package/lib/cjs/models/AccessToken.js +73 -0
- package/lib/cjs/models/AccessToken.js.map +1 -0
- package/lib/cjs/package.json +1 -0
- package/lib/cjs/policies/NoImpersonationPolicy.d.ts +28 -0
- package/lib/cjs/policies/NoImpersonationPolicy.d.ts.map +1 -0
- package/lib/cjs/policies/NoImpersonationPolicy.js +45 -0
- package/lib/cjs/policies/NoImpersonationPolicy.js.map +1 -0
- package/lib/cjs/policies/NoTokenAuthPolicy.d.ts +12 -0
- package/lib/cjs/policies/NoTokenAuthPolicy.d.ts.map +1 -0
- package/lib/cjs/policies/NoTokenAuthPolicy.js +24 -0
- package/lib/cjs/policies/NoTokenAuthPolicy.js.map +1 -0
- package/lib/cjs/policies/TokenPolicy.d.ts +49 -0
- package/lib/cjs/policies/TokenPolicy.d.ts.map +1 -0
- package/lib/cjs/policies/TokenPolicy.js +79 -0
- package/lib/cjs/policies/TokenPolicy.js.map +1 -0
- package/lib/mjs/actions.d.ts +119 -0
- package/lib/mjs/actions.d.ts.map +1 -0
- package/lib/mjs/actions.js +242 -0
- package/lib/mjs/actions.js.map +1 -0
- package/lib/mjs/cli/CreateToken.d.ts +13 -0
- package/lib/mjs/cli/CreateToken.d.ts.map +1 -0
- package/lib/mjs/cli/CreateToken.js +53 -0
- package/lib/mjs/cli/CreateToken.js.map +1 -0
- package/lib/mjs/cli/DeleteExpiredTokens.d.ts +11 -0
- package/lib/mjs/cli/DeleteExpiredTokens.d.ts.map +1 -0
- package/lib/mjs/cli/DeleteExpiredTokens.js +36 -0
- package/lib/mjs/cli/DeleteExpiredTokens.js.map +1 -0
- package/lib/mjs/cli/DeleteToken.d.ts +7 -0
- package/lib/mjs/cli/DeleteToken.d.ts.map +1 -0
- package/lib/mjs/cli/DeleteToken.js +33 -0
- package/lib/mjs/cli/DeleteToken.js.map +1 -0
- package/lib/mjs/cli/GrantTokenRole.d.ts +7 -0
- package/lib/mjs/cli/GrantTokenRole.d.ts.map +1 -0
- package/lib/mjs/cli/GrantTokenRole.js +34 -0
- package/lib/mjs/cli/GrantTokenRole.js.map +1 -0
- package/lib/mjs/cli/RevokeTokenRole.d.ts +12 -0
- package/lib/mjs/cli/RevokeTokenRole.d.ts.map +1 -0
- package/lib/mjs/cli/RevokeTokenRole.js +39 -0
- package/lib/mjs/cli/RevokeTokenRole.js.map +1 -0
- package/lib/mjs/config/rbac-http-token.d.ts +71 -0
- package/lib/mjs/config/rbac-http-token.d.ts.map +1 -0
- package/lib/mjs/config/rbac-http-token.js +96 -0
- package/lib/mjs/config/rbac-http-token.js.map +1 -0
- package/lib/mjs/controllers/AccessTokenController.d.ts +139 -0
- package/lib/mjs/controllers/AccessTokenController.d.ts.map +1 -0
- package/lib/mjs/controllers/AccessTokenController.js +261 -0
- package/lib/mjs/controllers/AccessTokenController.js.map +1 -0
- package/lib/mjs/dto/create-token-dto.d.ts +34 -0
- package/lib/mjs/dto/create-token-dto.d.ts.map +1 -0
- package/lib/mjs/dto/create-token-dto.js +32 -0
- package/lib/mjs/dto/create-token-dto.js.map +1 -0
- package/lib/mjs/events/AccessTokenCreated.d.ts +4 -0
- package/lib/mjs/events/AccessTokenCreated.d.ts.map +1 -0
- package/lib/mjs/events/AccessTokenCreated.js +15 -0
- package/lib/mjs/events/AccessTokenCreated.js.map +1 -0
- package/lib/mjs/events/AccessTokenDeleted.d.ts +4 -0
- package/lib/mjs/events/AccessTokenDeleted.d.ts.map +1 -0
- package/lib/mjs/events/AccessTokenDeleted.js +15 -0
- package/lib/mjs/events/AccessTokenDeleted.js.map +1 -0
- package/lib/mjs/events/AccessTokenEvent.d.ts +10 -0
- package/lib/mjs/events/AccessTokenEvent.d.ts.map +1 -0
- package/lib/mjs/events/AccessTokenEvent.js +23 -0
- package/lib/mjs/events/AccessTokenEvent.js.map +1 -0
- package/lib/mjs/events/AccessTokenRoleGranted.d.ts +7 -0
- package/lib/mjs/events/AccessTokenRoleGranted.d.ts.map +1 -0
- package/lib/mjs/events/AccessTokenRoleGranted.js +24 -0
- package/lib/mjs/events/AccessTokenRoleGranted.js.map +1 -0
- package/lib/mjs/events/AccessTokenRoleRevoked.d.ts +7 -0
- package/lib/mjs/events/AccessTokenRoleRevoked.d.ts.map +1 -0
- package/lib/mjs/events/AccessTokenRoleRevoked.js +24 -0
- package/lib/mjs/events/AccessTokenRoleRevoked.js.map +1 -0
- package/lib/mjs/events/index.d.ts +6 -0
- package/lib/mjs/events/index.d.ts.map +1 -0
- package/lib/mjs/events/index.js +6 -0
- package/lib/mjs/events/index.js.map +1 -0
- package/lib/mjs/generator.d.ts +12 -0
- package/lib/mjs/generator.d.ts.map +1 -0
- package/lib/mjs/generator.js +39 -0
- package/lib/mjs/generator.js.map +1 -0
- package/lib/mjs/index.d.ts +20 -0
- package/lib/mjs/index.d.ts.map +1 -0
- package/lib/mjs/index.js +23 -0
- package/lib/mjs/index.js.map +1 -0
- package/lib/mjs/interfaces.d.ts +57 -0
- package/lib/mjs/interfaces.d.ts.map +1 -0
- package/lib/mjs/interfaces.js +7 -0
- package/lib/mjs/interfaces.js.map +1 -0
- package/lib/mjs/middlewares.d.ts +76 -0
- package/lib/mjs/middlewares.d.ts.map +1 -0
- package/lib/mjs/middlewares.js +178 -0
- package/lib/mjs/middlewares.js.map +1 -0
- package/lib/mjs/migrations/RbacHttpTokenInitial_2026_08_11_01_00_00.d.ts +6 -0
- package/lib/mjs/migrations/RbacHttpTokenInitial_2026_08_11_01_00_00.d.ts.map +1 -0
- package/lib/mjs/migrations/RbacHttpTokenInitial_2026_08_11_01_00_00.js +35 -0
- package/lib/mjs/migrations/RbacHttpTokenInitial_2026_08_11_01_00_00.js.map +1 -0
- package/lib/mjs/models/AccessToken.d.ts +55 -0
- package/lib/mjs/models/AccessToken.d.ts.map +1 -0
- package/lib/mjs/models/AccessToken.js +70 -0
- package/lib/mjs/models/AccessToken.js.map +1 -0
- package/lib/mjs/package.json +1 -0
- package/lib/mjs/policies/NoImpersonationPolicy.d.ts +28 -0
- package/lib/mjs/policies/NoImpersonationPolicy.d.ts.map +1 -0
- package/lib/mjs/policies/NoImpersonationPolicy.js +41 -0
- package/lib/mjs/policies/NoImpersonationPolicy.js.map +1 -0
- package/lib/mjs/policies/NoTokenAuthPolicy.d.ts +12 -0
- package/lib/mjs/policies/NoTokenAuthPolicy.d.ts.map +1 -0
- package/lib/mjs/policies/NoTokenAuthPolicy.js +20 -0
- package/lib/mjs/policies/NoTokenAuthPolicy.js.map +1 -0
- package/lib/mjs/policies/TokenPolicy.d.ts +49 -0
- package/lib/mjs/policies/TokenPolicy.d.ts.map +1 -0
- package/lib/mjs/policies/TokenPolicy.js +75 -0
- package/lib/mjs/policies/TokenPolicy.js.map +1 -0
- package/lib/tsconfig.cjs.tsbuildinfo +1 -0
- package/lib/tsconfig.mjs.tsbuildinfo +1 -0
- package/package.json +78 -0
|
@@ -0,0 +1,242 @@
|
|
|
1
|
+
import _ from 'lodash';
|
|
2
|
+
import { DateTime } from 'luxon';
|
|
3
|
+
import { User } from '@spinajs/rbac';
|
|
4
|
+
import { _chain, _check_arg, _tap, _trim, _non_empty, _non_nil, _max_length } from '@spinajs/util';
|
|
5
|
+
import { _service } from '@spinajs/configuration';
|
|
6
|
+
import { _ev } from '@spinajs/queue';
|
|
7
|
+
import { ErrorCode } from '@spinajs/exceptions';
|
|
8
|
+
import { AccessToken } from './models/AccessToken.js';
|
|
9
|
+
import { AccessTokenGenerationProvider } from './interfaces.js';
|
|
10
|
+
import { AccessTokenCreated, AccessTokenDeleted, AccessTokenRoleGranted, AccessTokenRoleRevoked } from './events/index.js';
|
|
11
|
+
/**
|
|
12
|
+
* Failure codes carried by every {@link ErrorCode} this module throws.
|
|
13
|
+
*
|
|
14
|
+
* Named `E_TOKEN_CODES` rather than the shorter `E_CODES` on purpose:
|
|
15
|
+
* `@spinajs/rbac` exports an enum called `E_CODES` too, and both are re-exported
|
|
16
|
+
* from their package index. A downstream barrel that does
|
|
17
|
+
* `export * from '@spinajs/rbac'; export * from '@spinajs/rbac-http-token';`
|
|
18
|
+
* would collide on the NAME while the members underneath carry different
|
|
19
|
+
* numeric values - the kind of clash that resolves silently in a barrel and
|
|
20
|
+
* makes an `err.code === E_CODES.X` comparison answer the wrong question.
|
|
21
|
+
*/
|
|
22
|
+
export var E_TOKEN_CODES;
|
|
23
|
+
(function (E_TOKEN_CODES) {
|
|
24
|
+
E_TOKEN_CODES[E_TOKEN_CODES["E_TOKEN_NOT_FOUND"] = 0] = "E_TOKEN_NOT_FOUND";
|
|
25
|
+
E_TOKEN_CODES[E_TOKEN_CODES["E_TOKEN_EXPIRED"] = 1] = "E_TOKEN_EXPIRED";
|
|
26
|
+
E_TOKEN_CODES[E_TOKEN_CODES["E_TOKEN_OWNER_INVALID"] = 2] = "E_TOKEN_OWNER_INVALID";
|
|
27
|
+
E_TOKEN_CODES[E_TOKEN_CODES["E_TOKEN_ROLE_NOT_ALLOWED"] = 3] = "E_TOKEN_ROLE_NOT_ALLOWED";
|
|
28
|
+
})(E_TOKEN_CODES || (E_TOKEN_CODES = {}));
|
|
29
|
+
/**
|
|
30
|
+
* Resolves an AccessToken from an instance or its uuid.
|
|
31
|
+
*/
|
|
32
|
+
export function _token(token) {
|
|
33
|
+
if (_.isString(token)) {
|
|
34
|
+
return () => AccessToken.where('Uuid', token).firstOrFail();
|
|
35
|
+
}
|
|
36
|
+
return () => Promise.resolve(token);
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Resolves the owning user by instance, numeric id or uuid, with metadata
|
|
40
|
+
* populated ( needed for IsBanned checks downstream ).
|
|
41
|
+
*/
|
|
42
|
+
export function _owner(user) {
|
|
43
|
+
if (_.isString(user)) {
|
|
44
|
+
return () => User.where('Uuid', user).populate('Metadata').firstOrFail();
|
|
45
|
+
}
|
|
46
|
+
if (_.isNumber(user)) {
|
|
47
|
+
return () => User.where('Id', user).populate('Metadata').firstOrFail();
|
|
48
|
+
}
|
|
49
|
+
return () => Promise.resolve(user);
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Emits a token-related event through the queue service and forwards the token.
|
|
53
|
+
*
|
|
54
|
+
* @param event - constructor of the {@link AccessTokenEvent} subclass to emit
|
|
55
|
+
* @param args - additional arguments forwarded to the event constructor
|
|
56
|
+
*/
|
|
57
|
+
function _token_ev(event, ...args) {
|
|
58
|
+
return async (t) => {
|
|
59
|
+
await _ev(new event(t, ...args))();
|
|
60
|
+
return t;
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Ensures every role in `roles` is currently held by `owner`.
|
|
65
|
+
* A token must never carry a role its owner does not have.
|
|
66
|
+
*/
|
|
67
|
+
function _assert_roles_subset(owner, roles) {
|
|
68
|
+
const missing = roles.filter((r) => !owner.Role.includes(r));
|
|
69
|
+
if (missing.length !== 0) {
|
|
70
|
+
throw new ErrorCode(E_TOKEN_CODES.E_TOKEN_ROLE_NOT_ALLOWED, `Owner does not hold role(s): ${missing.join(', ')}`, { roles: missing });
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Creates a new access token for a user.
|
|
75
|
+
*
|
|
76
|
+
* Roles must be a non-empty subset of the owner's current roles. `expiresAt`
|
|
77
|
+
* null means the token never expires. The plaintext is returned once and
|
|
78
|
+
* never persisted - only its hash is stored.
|
|
79
|
+
*
|
|
80
|
+
* @param user - owner: {@link User} instance, numeric id or uuid
|
|
81
|
+
* @param name - human readable label
|
|
82
|
+
* @param roles - roles carried by the token, subset of the owner's roles
|
|
83
|
+
* @param expiresAt - absolute expiration, or null for a token that never expires
|
|
84
|
+
*/
|
|
85
|
+
export async function createToken(user, name, roles, expiresAt) {
|
|
86
|
+
name = _check_arg(_trim(), _non_empty(), _max_length(128))(name, 'name');
|
|
87
|
+
roles = _check_arg(_non_nil(), _non_empty())(roles, 'roles');
|
|
88
|
+
const generator = await _service('rbac.token.generation', AccessTokenGenerationProvider)();
|
|
89
|
+
const generated = await generator.generate();
|
|
90
|
+
return _chain(_owner(user), _tap(async (u) => _assert_roles_subset(u, roles)), async (u) => {
|
|
91
|
+
const token = new AccessToken({
|
|
92
|
+
Name: name,
|
|
93
|
+
Token: generated.Hash,
|
|
94
|
+
Roles: _.uniq(roles),
|
|
95
|
+
// `ExpiresAt` is optional rather than nullable ( see the model ), so a
|
|
96
|
+
// "never expires" token leaves the property unset instead of holding null.
|
|
97
|
+
ExpiresAt: expiresAt ?? undefined,
|
|
98
|
+
user_id: u.Id,
|
|
99
|
+
});
|
|
100
|
+
await token.insert();
|
|
101
|
+
return token;
|
|
102
|
+
}, _token_ev(AccessTokenCreated), (t) => ({ Token: t, Plaintext: generated.Plaintext }));
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Permanently deletes ( revokes ) a token.
|
|
106
|
+
*
|
|
107
|
+
* @param token - {@link AccessToken} instance or its uuid
|
|
108
|
+
*/
|
|
109
|
+
export async function deleteToken(token) {
|
|
110
|
+
return _chain(_token(token), _tap((t) => t.destroy()), _token_ev(AccessTokenDeleted), () => undefined);
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Adds a role to a token. The role must be held by the token owner.
|
|
114
|
+
*
|
|
115
|
+
* @param token - {@link AccessToken} instance or its uuid
|
|
116
|
+
* @param role - role name to grant
|
|
117
|
+
*/
|
|
118
|
+
export async function grantTokenRole(token, role) {
|
|
119
|
+
role = _check_arg(_trim(), _non_empty())(role, 'role');
|
|
120
|
+
return _chain(_token(token), _tap(async (t) => {
|
|
121
|
+
const owner = await _owner(t.user_id)();
|
|
122
|
+
_assert_roles_subset(owner, [role]);
|
|
123
|
+
t.Roles = _.uniq([...t.Roles, role]);
|
|
124
|
+
await t.update();
|
|
125
|
+
}), _token_ev(AccessTokenRoleGranted, role));
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Removes a role from a token.
|
|
129
|
+
*
|
|
130
|
+
* Not symmetric with {@link grantTokenRole}: revoking only ever narrows what a
|
|
131
|
+
* token may do, so it needs no owner check.
|
|
132
|
+
*
|
|
133
|
+
* A token must always keep at least one role - revoking the last one is
|
|
134
|
+
* refused, and full revocation means deleting the token. Beyond being
|
|
135
|
+
* meaningless ( a role-less token authorises nothing ), an empty list is
|
|
136
|
+
* actively corrupting: `@Set()` columns round-trip through `SqlSetConverter`,
|
|
137
|
+
* which stores `[]` as `''` and reads `''` back as `['']`. That phantom empty
|
|
138
|
+
* role then survives every later grant, permanently.
|
|
139
|
+
*
|
|
140
|
+
* @param token - {@link AccessToken} instance or its uuid
|
|
141
|
+
* @param role - role name to revoke
|
|
142
|
+
* @throws ErrorCode E_TOKEN_ROLE_NOT_ALLOWED when `role` is the token's last role
|
|
143
|
+
*/
|
|
144
|
+
export async function revokeTokenRole(token, role) {
|
|
145
|
+
role = _check_arg(_trim(), _non_empty())(role, 'role');
|
|
146
|
+
return _chain(_token(token), _tap(async (t) => {
|
|
147
|
+
const remaining = t.Roles.filter((r) => r !== role);
|
|
148
|
+
// checked BEFORE mutating, so a refused revoke leaves the instance and
|
|
149
|
+
// the row exactly as they were
|
|
150
|
+
if (remaining.length === 0) {
|
|
151
|
+
throw new ErrorCode(E_TOKEN_CODES.E_TOKEN_ROLE_NOT_ALLOWED, 'Cannot revoke the last role from a token - delete the token instead', { token: t.Uuid });
|
|
152
|
+
}
|
|
153
|
+
t.Roles = remaining;
|
|
154
|
+
await t.update();
|
|
155
|
+
}), _token_ev(AccessTokenRoleRevoked, role));
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* Validates a presented plaintext token.
|
|
159
|
+
*
|
|
160
|
+
* Checks, in order: token exists ( by hash ), token not expired, owner active /
|
|
161
|
+
* not soft-deleted / not banned, effective role intersection non-empty.
|
|
162
|
+
* Throws ErrorCode with {@link E_TOKEN_CODES} on every failure path.
|
|
163
|
+
*
|
|
164
|
+
* The owner checks are spelled out instead of reusing the `isActiveUser` query
|
|
165
|
+
* scope on purpose - a single "no such active user" result cannot say WHY, and
|
|
166
|
+
* callers need to tell an expired token from a banned account.
|
|
167
|
+
*
|
|
168
|
+
* @param plaintext - token exactly as presented by the client
|
|
169
|
+
*/
|
|
170
|
+
export async function validateToken(plaintext) {
|
|
171
|
+
// Degenerate input is a failed authentication like any other, so it has to
|
|
172
|
+
// leave through the same door. `_check_arg(_trim(), _non_empty())` would
|
|
173
|
+
// throw a raw InvalidArgument here - and a bare TypeError for nil, since
|
|
174
|
+
// `_non_empty` dereferences `.length` - breaking the "always an ErrorCode"
|
|
175
|
+
// contract this function is called under. Reported as E_TOKEN_NOT_FOUND with
|
|
176
|
+
// the unknown-token message on purpose: a caller must not learn WHY.
|
|
177
|
+
if (!_.isString(plaintext) || plaintext.trim().length === 0) {
|
|
178
|
+
throw new ErrorCode(E_TOKEN_CODES.E_TOKEN_NOT_FOUND, 'Access token not found');
|
|
179
|
+
}
|
|
180
|
+
plaintext = plaintext.trim();
|
|
181
|
+
const generator = await _service('rbac.token.generation', AccessTokenGenerationProvider)();
|
|
182
|
+
const hash = generator.hash(plaintext);
|
|
183
|
+
const token = await AccessToken.where('Token', hash).first();
|
|
184
|
+
if (!token) {
|
|
185
|
+
throw new ErrorCode(E_TOKEN_CODES.E_TOKEN_NOT_FOUND, 'Access token not found');
|
|
186
|
+
}
|
|
187
|
+
if (token.IsExpired) {
|
|
188
|
+
throw new ErrorCode(E_TOKEN_CODES.E_TOKEN_EXPIRED, 'Access token expired', { token: token.Uuid });
|
|
189
|
+
}
|
|
190
|
+
// Metadata carries the ban flag, so it must be populated - without it
|
|
191
|
+
// `IsBanned` silently answers false and every banned owner authenticates.
|
|
192
|
+
const owner = await User.where('Id', token.user_id).populate('Metadata').first();
|
|
193
|
+
// `DeletedAt` is defence in depth: the orm's soft-delete scope already appends
|
|
194
|
+
// `DeletedAt IS NULL` to User selects, so a deleted owner arrives as undefined.
|
|
195
|
+
if (!owner || !owner.IsActive || owner.DeletedAt || owner.IsBanned) {
|
|
196
|
+
throw new ErrorCode(E_TOKEN_CODES.E_TOKEN_OWNER_INVALID, 'Access token owner is not allowed to authenticate', { token: token.Uuid });
|
|
197
|
+
}
|
|
198
|
+
// roles are re-intersected on every request rather than trusted from the row:
|
|
199
|
+
// a role revoked on the user must take effect immediately, without having to
|
|
200
|
+
// hunt down every token that still carries it
|
|
201
|
+
const effective = token.Roles.filter((r) => owner.Role.includes(r));
|
|
202
|
+
if (effective.length === 0) {
|
|
203
|
+
throw new ErrorCode(E_TOKEN_CODES.E_TOKEN_ROLE_NOT_ALLOWED, 'Access token has no effective roles', { token: token.Uuid });
|
|
204
|
+
}
|
|
205
|
+
return { User: owner, Token: token, EffectiveRoles: effective };
|
|
206
|
+
}
|
|
207
|
+
/**
|
|
208
|
+
* Deletes every token whose expiration has passed. Returns the deleted count.
|
|
209
|
+
*
|
|
210
|
+
* Intended for cyclic execution from a worker ( see `rbac:token-delete-expired` ).
|
|
211
|
+
* Expired tokens are already refused by {@link validateToken}, so this is
|
|
212
|
+
* housekeeping, not enforcement.
|
|
213
|
+
*/
|
|
214
|
+
export async function deleteExpiredTokens() {
|
|
215
|
+
// `whereNotNull` is not redundant next to `<=`: a null expiry means "never
|
|
216
|
+
// expires", and null comparisons must not sweep those rows away.
|
|
217
|
+
const expired = await AccessToken.where('ExpiresAt', '<=', DateTime.now()).whereNotNull('ExpiresAt');
|
|
218
|
+
for (const t of expired) {
|
|
219
|
+
await t.destroy();
|
|
220
|
+
}
|
|
221
|
+
return expired.length;
|
|
222
|
+
}
|
|
223
|
+
/**
|
|
224
|
+
* Updates `LastUsedAt`, throttled: writes only when the stamp is absent or
|
|
225
|
+
* older than `intervalSeconds`.
|
|
226
|
+
*
|
|
227
|
+
* Every authenticated request would otherwise write to the token row; the stamp
|
|
228
|
+
* only needs to be accurate enough to spot unused tokens. Callers may
|
|
229
|
+
* fire-and-forget.
|
|
230
|
+
*
|
|
231
|
+
* @param token - token to stamp
|
|
232
|
+
* @param intervalSeconds - minimum time between two writes
|
|
233
|
+
*/
|
|
234
|
+
export async function touchToken(token, intervalSeconds) {
|
|
235
|
+
const now = DateTime.now();
|
|
236
|
+
if (token.LastUsedAt && token.LastUsedAt > now.minus({ seconds: intervalSeconds })) {
|
|
237
|
+
return;
|
|
238
|
+
}
|
|
239
|
+
token.LastUsedAt = now;
|
|
240
|
+
await token.update();
|
|
241
|
+
}
|
|
242
|
+
//# sourceMappingURL=actions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"actions.js","sourceRoot":"","sources":["../../src/actions.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { Log } from '@spinajs/log';
|
|
2
|
+
import { CliCommand } from '@spinajs/cli';
|
|
3
|
+
interface ICreateTokenOptions {
|
|
4
|
+
name: string;
|
|
5
|
+
roles: string;
|
|
6
|
+
expires?: string;
|
|
7
|
+
}
|
|
8
|
+
export declare class CreateToken extends CliCommand {
|
|
9
|
+
protected Log: Log;
|
|
10
|
+
execute(userIdOrUuid: string, options: ICreateTokenOptions): Promise<void>;
|
|
11
|
+
}
|
|
12
|
+
export {};
|
|
13
|
+
//# sourceMappingURL=CreateToken.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CreateToken.d.ts","sourceRoot":"","sources":["../../../src/cli/CreateToken.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAU,MAAM,cAAc,CAAC;AAC3C,OAAO,EAAY,UAAU,EAAmB,MAAM,cAAc,CAAC;AAKrE,UAAU,mBAAmB;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,qBAKa,WAAY,SAAQ,UAAU;IAEzC,SAAS,CAAC,GAAG,EAAE,GAAG,CAAC;IAEN,OAAO,CAAC,YAAY,EAAE,MAAM,EAAE,OAAO,EAAE,mBAAmB,GAAG,OAAO,CAAC,IAAI,CAAC,CA0BtF;CACF"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
2
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
+
};
|
|
7
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
8
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
9
|
+
};
|
|
10
|
+
import { Log, Logger } from '@spinajs/log';
|
|
11
|
+
import { Argument, CliCommand, Command, Option } from '@spinajs/cli';
|
|
12
|
+
import { DateTime } from 'luxon';
|
|
13
|
+
import { createToken } from '../actions.js';
|
|
14
|
+
let CreateToken = class CreateToken extends CliCommand {
|
|
15
|
+
async execute(userIdOrUuid, options) {
|
|
16
|
+
try {
|
|
17
|
+
// Nil means the flag was not given at all - a token that never expires.
|
|
18
|
+
// Anything else, empty string included, is a value the user meant to be a
|
|
19
|
+
// date and must be validated: a truthiness check here would quietly turn
|
|
20
|
+
// `--expires ""` into an infinite token.
|
|
21
|
+
const expiresAt = options.expires === undefined || options.expires === null ? null : DateTime.fromISO(options.expires);
|
|
22
|
+
if (expiresAt && !expiresAt.isValid) {
|
|
23
|
+
this.Log.error(`Invalid --expires value: ${options.expires}`);
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
const roles = options.roles
|
|
27
|
+
.split(',')
|
|
28
|
+
.map((r) => r.trim())
|
|
29
|
+
.filter((r) => r.length > 0);
|
|
30
|
+
const owner = /^\d+$/.test(userIdOrUuid) ? parseInt(userIdOrUuid, 10) : userIdOrUuid;
|
|
31
|
+
const { Token, Plaintext } = await createToken(owner, options.name, roles, expiresAt);
|
|
32
|
+
this.Log.success(`Token created: ${Token.Uuid}`);
|
|
33
|
+
// The single moment the plaintext exists outside the caller's hands.
|
|
34
|
+
this.Log.success(`Token ( copy now, it will not be shown again ): ${Plaintext}`);
|
|
35
|
+
}
|
|
36
|
+
catch (e) {
|
|
37
|
+
this.Log.error(`Error while creating token: ${e.message}`);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
__decorate([
|
|
42
|
+
Logger('rbac-http-token'),
|
|
43
|
+
__metadata("design:type", Log)
|
|
44
|
+
], CreateToken.prototype, "Log", void 0);
|
|
45
|
+
CreateToken = __decorate([
|
|
46
|
+
Command('rbac:token-create', 'Creates an access token for a user'),
|
|
47
|
+
Argument('userIdOrUuid', true, 'numeric id or uuid of the owner'),
|
|
48
|
+
Option('-n, --name <name>', true, 'token label'),
|
|
49
|
+
Option('-r, --roles <roles>', true, 'token roles, comma separated, must be subset of owner roles'),
|
|
50
|
+
Option('-e, --expires <expires>', false, 'ISO expiration instant; omit for a token that never expires')
|
|
51
|
+
], CreateToken);
|
|
52
|
+
export { CreateToken };
|
|
53
|
+
//# sourceMappingURL=CreateToken.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CreateToken.js","sourceRoot":"","sources":["../../../src/cli/CreateToken.ts"],"names":[],"mappings":";;;;;;;;;AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAC3C,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AACrE,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAEjC,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAarC,IAAM,WAAW,GAAjB,MAAM,WAAY,SAAQ,UAAU;IAIlC,KAAK,CAAC,OAAO,CAAC,YAAoB,EAAE,OAA4B;QACrE,IAAI,CAAC;YACH,wEAAwE;YACxE,0EAA0E;YAC1E,yEAAyE;YACzE,yCAAyC;YACzC,MAAM,SAAS,GAAG,OAAO,CAAC,OAAO,KAAK,SAAS,IAAI,OAAO,CAAC,OAAO,KAAK,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;YACvH,IAAI,SAAS,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,CAAC;gBACpC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,4BAA4B,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC;gBAC9D,OAAO;YACT,CAAC;YAED,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK;iBACxB,KAAK,CAAC,GAAG,CAAC;iBACV,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;iBACpB,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;YAC/B,MAAM,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,YAAY,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC;YAErF,MAAM,EAAE,KAAK,EAAE,SAAS,EAAE,GAAG,MAAM,WAAW,CAAC,KAAK,EAAE,OAAO,CAAC,IAAI,EAAE,KAAK,EAAE,SAAS,CAAC,CAAC;YAEtF,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,kBAAkB,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC;YACjD,qEAAqE;YACrE,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,mDAAmD,SAAS,EAAE,CAAC,CAAC;QACnF,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,+BAAgC,CAAW,CAAC,OAAO,EAAE,CAAC,CAAC;QACxE,CAAC;IACH,CAAC;CACF,CAAA;AA7BW;IADT,MAAM,CAAC,iBAAiB,CAAC;8BACX,GAAG;wCAAC;AAFR,WAAW;IALvB,OAAO,CAAC,mBAAmB,EAAE,oCAAoC,CAAC;IAClE,QAAQ,CAAC,cAAc,EAAE,IAAI,EAAE,iCAAiC,CAAC;IACjE,MAAM,CAAC,mBAAmB,EAAE,IAAI,EAAE,aAAa,CAAC;IAChD,MAAM,CAAC,qBAAqB,EAAE,IAAI,EAAE,6DAA6D,CAAC;IAClG,MAAM,CAAC,yBAAyB,EAAE,KAAK,EAAE,6DAA6D,CAAC;GAC3F,WAAW,CA+BvB"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { Log } from '@spinajs/log';
|
|
2
|
+
import { CliCommand } from '@spinajs/cli';
|
|
3
|
+
/**
|
|
4
|
+
* Intended for cyclic execution from a worker process
|
|
5
|
+
* ( eg. cron / task scheduler ) to keep the token table clean.
|
|
6
|
+
*/
|
|
7
|
+
export declare class DeleteExpiredTokens extends CliCommand {
|
|
8
|
+
protected Log: Log;
|
|
9
|
+
execute(): Promise<void>;
|
|
10
|
+
}
|
|
11
|
+
//# sourceMappingURL=DeleteExpiredTokens.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DeleteExpiredTokens.d.ts","sourceRoot":"","sources":["../../../src/cli/DeleteExpiredTokens.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAU,MAAM,cAAc,CAAC;AAC3C,OAAO,EAAE,UAAU,EAAW,MAAM,cAAc,CAAC;AAInD;;;GAGG;AACH,qBACa,mBAAoB,SAAQ,UAAU;IAEjD,SAAS,CAAC,GAAG,EAAE,GAAG,CAAC;IAEN,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,CAOpC;CACF"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
2
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
+
};
|
|
7
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
8
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
9
|
+
};
|
|
10
|
+
import { Log, Logger } from '@spinajs/log';
|
|
11
|
+
import { CliCommand, Command } from '@spinajs/cli';
|
|
12
|
+
import { deleteExpiredTokens } from '../actions.js';
|
|
13
|
+
/**
|
|
14
|
+
* Intended for cyclic execution from a worker process
|
|
15
|
+
* ( eg. cron / task scheduler ) to keep the token table clean.
|
|
16
|
+
*/
|
|
17
|
+
let DeleteExpiredTokens = class DeleteExpiredTokens extends CliCommand {
|
|
18
|
+
async execute() {
|
|
19
|
+
try {
|
|
20
|
+
const count = await deleteExpiredTokens();
|
|
21
|
+
this.Log.success(`Deleted ${count} expired token(s)`);
|
|
22
|
+
}
|
|
23
|
+
catch (e) {
|
|
24
|
+
this.Log.error(`Error while deleting expired tokens: ${e.message}`);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
};
|
|
28
|
+
__decorate([
|
|
29
|
+
Logger('rbac-http-token'),
|
|
30
|
+
__metadata("design:type", Log)
|
|
31
|
+
], DeleteExpiredTokens.prototype, "Log", void 0);
|
|
32
|
+
DeleteExpiredTokens = __decorate([
|
|
33
|
+
Command('rbac:token-delete-expired', 'Deletes all expired access tokens')
|
|
34
|
+
], DeleteExpiredTokens);
|
|
35
|
+
export { DeleteExpiredTokens };
|
|
36
|
+
//# sourceMappingURL=DeleteExpiredTokens.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DeleteExpiredTokens.js","sourceRoot":"","sources":["../../../src/cli/DeleteExpiredTokens.ts"],"names":[],"mappings":";;;;;;;;;AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAC3C,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAEnD,OAAO,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AAEpD;;;GAGG;AAEI,IAAM,mBAAmB,GAAzB,MAAM,mBAAoB,SAAQ,UAAU;IAI1C,KAAK,CAAC,OAAO;QAClB,IAAI,CAAC;YACH,MAAM,KAAK,GAAG,MAAM,mBAAmB,EAAE,CAAC;YAC1C,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,WAAW,KAAK,mBAAmB,CAAC,CAAC;QACxD,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,wCAAyC,CAAW,CAAC,OAAO,EAAE,CAAC,CAAC;QACjF,CAAC;IACH,CAAC;CACF,CAAA;AAVW;IADT,MAAM,CAAC,iBAAiB,CAAC;8BACX,GAAG;gDAAC;AAFR,mBAAmB;IAD/B,OAAO,CAAC,2BAA2B,EAAE,mCAAmC,CAAC;GAC7D,mBAAmB,CAY/B"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DeleteToken.d.ts","sourceRoot":"","sources":["../../../src/cli/DeleteToken.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAU,MAAM,cAAc,CAAC;AAC3C,OAAO,EAAY,UAAU,EAAW,MAAM,cAAc,CAAC;AAI7D,qBAEa,WAAY,SAAQ,UAAU;IAEzC,SAAS,CAAC,GAAG,EAAE,GAAG,CAAC;IAEN,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAOhD;CACF"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
2
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
+
};
|
|
7
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
8
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
9
|
+
};
|
|
10
|
+
import { Log, Logger } from '@spinajs/log';
|
|
11
|
+
import { Argument, CliCommand, Command } from '@spinajs/cli';
|
|
12
|
+
import { deleteToken } from '../actions.js';
|
|
13
|
+
let DeleteToken = class DeleteToken extends CliCommand {
|
|
14
|
+
async execute(uuid) {
|
|
15
|
+
try {
|
|
16
|
+
await deleteToken(uuid);
|
|
17
|
+
this.Log.success(`Token ${uuid} deleted`);
|
|
18
|
+
}
|
|
19
|
+
catch (e) {
|
|
20
|
+
this.Log.error(`Error while deleting token ${uuid}: ${e.message}`);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
};
|
|
24
|
+
__decorate([
|
|
25
|
+
Logger('rbac-http-token'),
|
|
26
|
+
__metadata("design:type", Log)
|
|
27
|
+
], DeleteToken.prototype, "Log", void 0);
|
|
28
|
+
DeleteToken = __decorate([
|
|
29
|
+
Command('rbac:token-delete', 'Deletes ( revokes ) an access token'),
|
|
30
|
+
Argument('uuid', true, 'token uuid')
|
|
31
|
+
], DeleteToken);
|
|
32
|
+
export { DeleteToken };
|
|
33
|
+
//# sourceMappingURL=DeleteToken.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DeleteToken.js","sourceRoot":"","sources":["../../../src/cli/DeleteToken.ts"],"names":[],"mappings":";;;;;;;;;AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAC3C,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAE7D,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAIrC,IAAM,WAAW,GAAjB,MAAM,WAAY,SAAQ,UAAU;IAIlC,KAAK,CAAC,OAAO,CAAC,IAAY;QAC/B,IAAI,CAAC;YACH,MAAM,WAAW,CAAC,IAAI,CAAC,CAAC;YACxB,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,SAAS,IAAI,UAAU,CAAC,CAAC;QAC5C,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,8BAA8B,IAAI,KAAM,CAAW,CAAC,OAAO,EAAE,CAAC,CAAC;QAChF,CAAC;IACH,CAAC;CACF,CAAA;AAVW;IADT,MAAM,CAAC,iBAAiB,CAAC;8BACX,GAAG;wCAAC;AAFR,WAAW;IAFvB,OAAO,CAAC,mBAAmB,EAAE,qCAAqC,CAAC;IACnE,QAAQ,CAAC,MAAM,EAAE,IAAI,EAAE,YAAY,CAAC;GACxB,WAAW,CAYvB"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"GrantTokenRole.d.ts","sourceRoot":"","sources":["../../../src/cli/GrantTokenRole.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAU,MAAM,cAAc,CAAC;AAC3C,OAAO,EAAY,UAAU,EAAW,MAAM,cAAc,CAAC;AAI7D,qBAGa,cAAe,SAAQ,UAAU;IAE5C,SAAS,CAAC,GAAG,EAAE,GAAG,CAAC;IAEN,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAO9D;CACF"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
2
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
+
};
|
|
7
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
8
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
9
|
+
};
|
|
10
|
+
import { Log, Logger } from '@spinajs/log';
|
|
11
|
+
import { Argument, CliCommand, Command } from '@spinajs/cli';
|
|
12
|
+
import { grantTokenRole } from '../actions.js';
|
|
13
|
+
let GrantTokenRole = class GrantTokenRole extends CliCommand {
|
|
14
|
+
async execute(uuid, role) {
|
|
15
|
+
try {
|
|
16
|
+
await grantTokenRole(uuid, role);
|
|
17
|
+
this.Log.success(`Role ${role} granted to token ${uuid}`);
|
|
18
|
+
}
|
|
19
|
+
catch (e) {
|
|
20
|
+
this.Log.error(`Error while granting role ${role} to token ${uuid}: ${e.message}`);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
};
|
|
24
|
+
__decorate([
|
|
25
|
+
Logger('rbac-http-token'),
|
|
26
|
+
__metadata("design:type", Log)
|
|
27
|
+
], GrantTokenRole.prototype, "Log", void 0);
|
|
28
|
+
GrantTokenRole = __decorate([
|
|
29
|
+
Command('rbac:token-grant', 'Grants a role to an access token'),
|
|
30
|
+
Argument('uuid', true, 'token uuid'),
|
|
31
|
+
Argument('role', true, 'role to grant, must be held by token owner')
|
|
32
|
+
], GrantTokenRole);
|
|
33
|
+
export { GrantTokenRole };
|
|
34
|
+
//# sourceMappingURL=GrantTokenRole.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"GrantTokenRole.js","sourceRoot":"","sources":["../../../src/cli/GrantTokenRole.ts"],"names":[],"mappings":";;;;;;;;;AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAC3C,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAE7D,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAKxC,IAAM,cAAc,GAApB,MAAM,cAAe,SAAQ,UAAU;IAIrC,KAAK,CAAC,OAAO,CAAC,IAAY,EAAE,IAAY;QAC7C,IAAI,CAAC;YACH,MAAM,cAAc,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;YACjC,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,QAAQ,IAAI,qBAAqB,IAAI,EAAE,CAAC,CAAC;QAC5D,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,6BAA6B,IAAI,aAAa,IAAI,KAAM,CAAW,CAAC,OAAO,EAAE,CAAC,CAAC;QAChG,CAAC;IACH,CAAC;CACF,CAAA;AAVW;IADT,MAAM,CAAC,iBAAiB,CAAC;8BACX,GAAG;2CAAC;AAFR,cAAc;IAH1B,OAAO,CAAC,kBAAkB,EAAE,kCAAkC,CAAC;IAC/D,QAAQ,CAAC,MAAM,EAAE,IAAI,EAAE,YAAY,CAAC;IACpC,QAAQ,CAAC,MAAM,EAAE,IAAI,EAAE,4CAA4C,CAAC;GACxD,cAAc,CAY1B"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { Log } from '@spinajs/log';
|
|
2
|
+
import { CliCommand } from '@spinajs/cli';
|
|
3
|
+
export declare class RevokeTokenRole extends CliCommand {
|
|
4
|
+
protected Log: Log;
|
|
5
|
+
/**
|
|
6
|
+
* Refusals arrive as thrown errors ( eg. revoking a token's last role ) and
|
|
7
|
+
* are reported on the error channel like any other failure - the row is left
|
|
8
|
+
* exactly as it was.
|
|
9
|
+
*/
|
|
10
|
+
execute(uuid: string, role: string): Promise<void>;
|
|
11
|
+
}
|
|
12
|
+
//# sourceMappingURL=RevokeTokenRole.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"RevokeTokenRole.d.ts","sourceRoot":"","sources":["../../../src/cli/RevokeTokenRole.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAU,MAAM,cAAc,CAAC;AAC3C,OAAO,EAAY,UAAU,EAAW,MAAM,cAAc,CAAC;AAI7D,qBAGa,eAAgB,SAAQ,UAAU;IAE7C,SAAS,CAAC,GAAG,EAAE,GAAG,CAAC;IAEnB;;;;OAIG;IACU,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAO9D;CACF"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
2
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
+
};
|
|
7
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
8
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
9
|
+
};
|
|
10
|
+
import { Log, Logger } from '@spinajs/log';
|
|
11
|
+
import { Argument, CliCommand, Command } from '@spinajs/cli';
|
|
12
|
+
import { revokeTokenRole } from '../actions.js';
|
|
13
|
+
let RevokeTokenRole = class RevokeTokenRole extends CliCommand {
|
|
14
|
+
/**
|
|
15
|
+
* Refusals arrive as thrown errors ( eg. revoking a token's last role ) and
|
|
16
|
+
* are reported on the error channel like any other failure - the row is left
|
|
17
|
+
* exactly as it was.
|
|
18
|
+
*/
|
|
19
|
+
async execute(uuid, role) {
|
|
20
|
+
try {
|
|
21
|
+
await revokeTokenRole(uuid, role);
|
|
22
|
+
this.Log.success(`Role ${role} revoked from token ${uuid}`);
|
|
23
|
+
}
|
|
24
|
+
catch (e) {
|
|
25
|
+
this.Log.error(`Error while revoking role ${role} from token ${uuid}: ${e.message}`);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
__decorate([
|
|
30
|
+
Logger('rbac-http-token'),
|
|
31
|
+
__metadata("design:type", Log)
|
|
32
|
+
], RevokeTokenRole.prototype, "Log", void 0);
|
|
33
|
+
RevokeTokenRole = __decorate([
|
|
34
|
+
Command('rbac:token-revoke', 'Revokes a role from an access token'),
|
|
35
|
+
Argument('uuid', true, 'token uuid'),
|
|
36
|
+
Argument('role', true, 'role to revoke')
|
|
37
|
+
], RevokeTokenRole);
|
|
38
|
+
export { RevokeTokenRole };
|
|
39
|
+
//# sourceMappingURL=RevokeTokenRole.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"RevokeTokenRole.js","sourceRoot":"","sources":["../../../src/cli/RevokeTokenRole.ts"],"names":[],"mappings":";;;;;;;;;AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAC3C,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAE7D,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAKzC,IAAM,eAAe,GAArB,MAAM,eAAgB,SAAQ,UAAU;IAI7C;;;;OAIG;IACI,KAAK,CAAC,OAAO,CAAC,IAAY,EAAE,IAAY;QAC7C,IAAI,CAAC;YACH,MAAM,eAAe,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;YAClC,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,QAAQ,IAAI,uBAAuB,IAAI,EAAE,CAAC,CAAC;QAC9D,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,6BAA6B,IAAI,eAAe,IAAI,KAAM,CAAW,CAAC,OAAO,EAAE,CAAC,CAAC;QAClG,CAAC;IACH,CAAC;CACF,CAAA;AAfW;IADT,MAAM,CAAC,iBAAiB,CAAC;8BACX,GAAG;4CAAC;AAFR,eAAe;IAH3B,OAAO,CAAC,mBAAmB,EAAE,qCAAqC,CAAC;IACnE,QAAQ,CAAC,MAAM,EAAE,IAAI,EAAE,YAAY,CAAC;IACpC,QAAQ,CAAC,MAAM,EAAE,IAAI,EAAE,gBAAgB,CAAC;GAC5B,eAAe,CAiB3B"}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
declare const rbacHttpToken: {
|
|
2
|
+
system: {
|
|
3
|
+
dirs: {
|
|
4
|
+
cli: string[];
|
|
5
|
+
controllers: string[];
|
|
6
|
+
};
|
|
7
|
+
};
|
|
8
|
+
queue: {
|
|
9
|
+
routing: {
|
|
10
|
+
AccessTokenCreated: {
|
|
11
|
+
connection: string;
|
|
12
|
+
};
|
|
13
|
+
AccessTokenDeleted: {
|
|
14
|
+
connection: string;
|
|
15
|
+
};
|
|
16
|
+
AccessTokenRoleGranted: {
|
|
17
|
+
connection: string;
|
|
18
|
+
};
|
|
19
|
+
AccessTokenRoleRevoked: {
|
|
20
|
+
connection: string;
|
|
21
|
+
};
|
|
22
|
+
};
|
|
23
|
+
};
|
|
24
|
+
rbac: {
|
|
25
|
+
token: {
|
|
26
|
+
/**
|
|
27
|
+
* Token generation algorithm. Swap for your own implementation of
|
|
28
|
+
* AccessTokenGenerationProvider registered under this name.
|
|
29
|
+
*/
|
|
30
|
+
generation: {
|
|
31
|
+
service: string;
|
|
32
|
+
};
|
|
33
|
+
/**
|
|
34
|
+
* Stable plaintext prefix - lets secret scanners recognise leaked tokens.
|
|
35
|
+
*/
|
|
36
|
+
prefix: string;
|
|
37
|
+
/**
|
|
38
|
+
* Random bytes per token ( 32 = 256 bit entropy ).
|
|
39
|
+
*/
|
|
40
|
+
length: number;
|
|
41
|
+
/**
|
|
42
|
+
* Fallback header checked when no `Authorization: Bearer` is present.
|
|
43
|
+
*/
|
|
44
|
+
headerName: string;
|
|
45
|
+
/**
|
|
46
|
+
* Seconds between LastUsedAt writes for a busy token.
|
|
47
|
+
*/
|
|
48
|
+
lastUsedUpdateInterval: number;
|
|
49
|
+
};
|
|
50
|
+
grants: {
|
|
51
|
+
user: {
|
|
52
|
+
'user.tokens': {
|
|
53
|
+
'create:own': string[];
|
|
54
|
+
'read:own': string[];
|
|
55
|
+
'update:own': string[];
|
|
56
|
+
'delete:own': string[];
|
|
57
|
+
};
|
|
58
|
+
};
|
|
59
|
+
'admin.users': {
|
|
60
|
+
'user.tokens': {
|
|
61
|
+
'create:any': string[];
|
|
62
|
+
'read:any': string[];
|
|
63
|
+
'update:any': string[];
|
|
64
|
+
'delete:any': string[];
|
|
65
|
+
};
|
|
66
|
+
};
|
|
67
|
+
};
|
|
68
|
+
};
|
|
69
|
+
};
|
|
70
|
+
export default rbacHttpToken;
|
|
71
|
+
//# sourceMappingURL=rbac-http-token.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rbac-http-token.d.ts","sourceRoot":"","sources":["../../../src/config/rbac-http-token.ts"],"names":[],"mappings":"AAYA,QAAA,MAAM,aAAa;IACjB,MAAM;QACJ,IAAI;YAIF,GAAG;YACH,WAAW;;;IAqBf,KAAK;QAKH,OAAO;YACL,kBAAkB;gBAAI,UAAU;;YAChC,kBAAkB;gBAAI,UAAU;;YAChC,sBAAsB;gBAAI,UAAU;;YACpC,sBAAsB;gBAAI,UAAU;;;;IAGxC,IAAI;QACF,KAAK;YACH;;;eAGG;YACH,UAAU;gBACR,OAAO;;YAGT;;eAEG;YACH,MAAM;YAEN;;eAEG;YACH,MAAM;YAEN;;eAEG;YACH,UAAU;YAEV;;eAEG;YACH,sBAAsB;;QAExB,MAAM;YACJ,IAAI;gBACF,aAAa;oBAAI,YAAY;oBAAS,UAAU;oBAAS,YAAY;oBAAS,YAAY;;;YAa5F,aAAa;gBACX,aAAa;oBAAI,YAAY;oBAAS,UAAU;oBAAS,YAAY;oBAAS,YAAY;;;;;CAIjG,CAAC;eAEa,aAAa"}
|