@azlib/identity 0.2.0
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/LICENSE +201 -0
- package/README.md +387 -0
- package/dist/errors-BGMwaW5s.d.mts +481 -0
- package/dist/errors-BGMwaW5s.d.mts.map +1 -0
- package/dist/errors-Bcjx9o6g.cjs +111 -0
- package/dist/errors-C2xZAatu.d.cts +481 -0
- package/dist/errors-C2xZAatu.d.cts.map +1 -0
- package/dist/errors-CEmnZxIn.mjs +66 -0
- package/dist/errors-CEmnZxIn.mjs.map +1 -0
- package/dist/express.cjs +405 -0
- package/dist/express.d.cts +87 -0
- package/dist/express.d.cts.map +1 -0
- package/dist/express.d.mts +87 -0
- package/dist/express.d.mts.map +1 -0
- package/dist/express.mjs +401 -0
- package/dist/express.mjs.map +1 -0
- package/dist/identity-4eP45YIP.cjs +461 -0
- package/dist/identity-Bz9RDOvT.mjs +410 -0
- package/dist/identity-Bz9RDOvT.mjs.map +1 -0
- package/dist/identity-router-DBL20UWT.d.mts +115 -0
- package/dist/identity-router-DBL20UWT.d.mts.map +1 -0
- package/dist/identity-router-Dib30Waj.d.cts +115 -0
- package/dist/identity-router-Dib30Waj.d.cts.map +1 -0
- package/dist/identity-service-B9zrvE9z.d.mts +128 -0
- package/dist/identity-service-B9zrvE9z.d.mts.map +1 -0
- package/dist/identity-service-CLzKx8Z7.d.cts +128 -0
- package/dist/identity-service-CLzKx8Z7.d.cts.map +1 -0
- package/dist/identity-store-BRRahxcS.d.cts +272 -0
- package/dist/identity-store-BRRahxcS.d.cts.map +1 -0
- package/dist/identity-store-BRRahxcS.d.mts +272 -0
- package/dist/identity-store-BRRahxcS.d.mts.map +1 -0
- package/dist/index-CpufYgyn.d.cts +30 -0
- package/dist/index-CpufYgyn.d.cts.map +1 -0
- package/dist/index-CpufYgyn.d.mts +30 -0
- package/dist/index-CpufYgyn.d.mts.map +1 -0
- package/dist/index.cjs +18 -0
- package/dist/index.d.cts +4 -0
- package/dist/index.d.mts +4 -0
- package/dist/index.mjs +3 -0
- package/dist/logger-Be1wDzBC.cjs +48 -0
- package/dist/logger-CcCHJVVe.mjs +33 -0
- package/dist/logger-CcCHJVVe.mjs.map +1 -0
- package/dist/nestjs.cjs +516 -0
- package/dist/nestjs.d.cts +102 -0
- package/dist/nestjs.d.cts.map +1 -0
- package/dist/nestjs.d.mts +102 -0
- package/dist/nestjs.d.mts.map +1 -0
- package/dist/nestjs.mjs +500 -0
- package/dist/nestjs.mjs.map +1 -0
- package/dist/node.cjs +946 -0
- package/dist/node.d.cts +260 -0
- package/dist/node.d.cts.map +1 -0
- package/dist/node.d.mts +260 -0
- package/dist/node.d.mts.map +1 -0
- package/dist/node.mjs +890 -0
- package/dist/node.mjs.map +1 -0
- package/dist/test-utils.cjs +169 -0
- package/dist/test-utils.d.cts +12 -0
- package/dist/test-utils.d.cts.map +1 -0
- package/dist/test-utils.d.mts +12 -0
- package/dist/test-utils.d.mts.map +1 -0
- package/dist/test-utils.mjs +170 -0
- package/dist/test-utils.mjs.map +1 -0
- package/package.json +92 -0
- package/schema/model.ts +100 -0
- package/schema/mysql.sql +102 -0
- package/schema/postgres.sql +92 -0
- package/schema/prisma.schema +122 -0
- package/schema/sqlite.sql +92 -0
package/dist/nestjs.cjs
ADDED
|
@@ -0,0 +1,516 @@
|
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
+
const require_errors = require("./errors-Bcjx9o6g.cjs");
|
|
3
|
+
let _nestjs_common = require("@nestjs/common");
|
|
4
|
+
let _nestjs_core = require("@nestjs/core");
|
|
5
|
+
//#region \0@oxc-project+runtime@0.132.0/helpers/decorateMetadata.js
|
|
6
|
+
function __decorateMetadata(k, v) {
|
|
7
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
8
|
+
}
|
|
9
|
+
//#endregion
|
|
10
|
+
//#region \0@oxc-project+runtime@0.132.0/helpers/decorateParam.js
|
|
11
|
+
function __decorateParam(paramIndex, decorator) {
|
|
12
|
+
return function(target, key) {
|
|
13
|
+
decorator(target, key, paramIndex);
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
//#endregion
|
|
17
|
+
//#region \0@oxc-project+runtime@0.132.0/helpers/decorate.js
|
|
18
|
+
function __decorate(decorators, target, key, desc) {
|
|
19
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
20
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
21
|
+
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;
|
|
22
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
23
|
+
}
|
|
24
|
+
//#endregion
|
|
25
|
+
//#region core/nestjs/identity-controller.ts
|
|
26
|
+
/**
|
|
27
|
+
* Pre-built NestJS controller for `@azlib/identity`.
|
|
28
|
+
*
|
|
29
|
+
* Register it automatically via `IdentityModule.forRoot({ routes: true })`.
|
|
30
|
+
* `@nestjs/common` is an optional peer dependency — only required when this file is used.
|
|
31
|
+
*/
|
|
32
|
+
function resolveCookieName(opts) {
|
|
33
|
+
return opts.name ?? "azlib_rt";
|
|
34
|
+
}
|
|
35
|
+
function rethrowAsHttp(err) {
|
|
36
|
+
if (err instanceof require_errors.IdentityError) throw new _nestjs_common.HttpException({
|
|
37
|
+
code: err.code,
|
|
38
|
+
message: err.message
|
|
39
|
+
}, err.statusCode);
|
|
40
|
+
throw err;
|
|
41
|
+
}
|
|
42
|
+
function setCookieAndStripRefreshToken(res, tokens, opts) {
|
|
43
|
+
const maxAge = tokens.refreshTokenExpiresAt.getTime() - Date.now();
|
|
44
|
+
res.cookie(resolveCookieName(opts), tokens.refreshToken, {
|
|
45
|
+
httpOnly: opts.httpOnly ?? true,
|
|
46
|
+
secure: opts.secure ?? process.env.NODE_ENV === "production",
|
|
47
|
+
sameSite: opts.sameSite ?? "lax",
|
|
48
|
+
path: opts.path ?? "/",
|
|
49
|
+
domain: opts.domain,
|
|
50
|
+
maxAge
|
|
51
|
+
});
|
|
52
|
+
const { refreshToken: _rt, refreshTokenExpiresAt: _exp, ...bodyTokens } = tokens;
|
|
53
|
+
return bodyTokens;
|
|
54
|
+
}
|
|
55
|
+
function buildAuthResponse(result, cookieOpts, res) {
|
|
56
|
+
if (cookieOpts) {
|
|
57
|
+
const tokens = setCookieAndStripRefreshToken(res, result.tokens, cookieOpts);
|
|
58
|
+
return {
|
|
59
|
+
user: result.user,
|
|
60
|
+
tokens
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
return result;
|
|
64
|
+
}
|
|
65
|
+
function buildLoginResponse(result, cookieOpts, res) {
|
|
66
|
+
if ("mfaToken" in result) return result;
|
|
67
|
+
return buildAuthResponse(result, cookieOpts, res);
|
|
68
|
+
}
|
|
69
|
+
function readRefreshTokenFromRequest(req, cookieOpts) {
|
|
70
|
+
if (cookieOpts) return req.cookies?.[resolveCookieName(cookieOpts)];
|
|
71
|
+
const token = req.body?.["refreshToken"];
|
|
72
|
+
return typeof token === "string" ? token : void 0;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Returns a dynamically created NestJS controller class with all standard identity
|
|
76
|
+
* routes pre-wired. The class is registered directly in `IdentityModule.forRoot()`
|
|
77
|
+
* when `routes` is configured — consumers do not need to define this controller.
|
|
78
|
+
*
|
|
79
|
+
* Pre-wired routes (relative to the module prefix, default `"auth"`):
|
|
80
|
+
*
|
|
81
|
+
* | Method | Path | Description |
|
|
82
|
+
* |--------|------|-------------|
|
|
83
|
+
* | POST | `/register` | Create a new account |
|
|
84
|
+
* | POST | `/login` | Email + password login; may return MFA challenge |
|
|
85
|
+
* | POST | `/refresh` | Rotate the refresh token |
|
|
86
|
+
* | POST | `/logout` | Revoke the current session |
|
|
87
|
+
* | GET | `/me` | Return the authenticated principal (requires auth) |
|
|
88
|
+
* | POST | `/request-email-verification` | Re-send verification link (requires auth) |
|
|
89
|
+
* | POST | `/verify-email` | Consume an email verification token |
|
|
90
|
+
* | POST | `/request-password-reset` | Send a password reset link |
|
|
91
|
+
* | POST | `/reset-password` | Set a new password using a reset token |
|
|
92
|
+
* | POST | `/mfa/verify` | Complete an MFA challenge after login |
|
|
93
|
+
* | POST | `/2fa/setup` | Begin TOTP 2FA setup (requires auth) |
|
|
94
|
+
* | POST | `/2fa/enable` | Confirm and enable 2FA (requires auth) |
|
|
95
|
+
* | POST | `/2fa/disable` | Disable 2FA (requires auth) |
|
|
96
|
+
* | POST | `/admin/lock/:userId` | Lock an account |
|
|
97
|
+
* | POST | `/admin/unlock/:userId` | Unlock an account |
|
|
98
|
+
* | POST | `/admin/disable/:userId` | Disable an account |
|
|
99
|
+
*/
|
|
100
|
+
function createIdentityController(prefix, controllerOptions = {}) {
|
|
101
|
+
const cookieOpts = controllerOptions.cookie;
|
|
102
|
+
let IdentityController = class IdentityController {
|
|
103
|
+
service;
|
|
104
|
+
constructor(service) {
|
|
105
|
+
this.service = service;
|
|
106
|
+
}
|
|
107
|
+
async register(body, res) {
|
|
108
|
+
try {
|
|
109
|
+
return buildAuthResponse(await this.service.register(body), cookieOpts, res);
|
|
110
|
+
} catch (err) {
|
|
111
|
+
rethrowAsHttp(err);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
async login(body, res) {
|
|
115
|
+
try {
|
|
116
|
+
return buildLoginResponse(await this.service.login(body), cookieOpts, res);
|
|
117
|
+
} catch (err) {
|
|
118
|
+
rethrowAsHttp(err);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
async refresh(req, res) {
|
|
122
|
+
try {
|
|
123
|
+
const token = readRefreshTokenFromRequest(req, cookieOpts);
|
|
124
|
+
if (!token) throw new require_errors.UnauthenticatedError("Refresh token is missing.");
|
|
125
|
+
return buildAuthResponse(await this.service.refresh(token), cookieOpts, res);
|
|
126
|
+
} catch (err) {
|
|
127
|
+
rethrowAsHttp(err);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
async logout(req, res) {
|
|
131
|
+
try {
|
|
132
|
+
const token = readRefreshTokenFromRequest(req, cookieOpts);
|
|
133
|
+
if (token) await this.service.logout(token);
|
|
134
|
+
if (cookieOpts) res.clearCookie(resolveCookieName(cookieOpts), { path: cookieOpts.path ?? "/" });
|
|
135
|
+
} catch (err) {
|
|
136
|
+
rethrowAsHttp(err);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
getMe(req) {
|
|
140
|
+
return req.identity;
|
|
141
|
+
}
|
|
142
|
+
async requestEmailVerification(req) {
|
|
143
|
+
try {
|
|
144
|
+
await this.service.requestEmailVerification(req.identity.userId);
|
|
145
|
+
} catch (err) {
|
|
146
|
+
rethrowAsHttp(err);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
async verifyEmail(body) {
|
|
150
|
+
try {
|
|
151
|
+
if (!body.token) throw new require_errors.UnauthenticatedError("token is required.");
|
|
152
|
+
await this.service.verifyEmail(body.token);
|
|
153
|
+
} catch (err) {
|
|
154
|
+
rethrowAsHttp(err);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
async requestPasswordReset(body) {
|
|
158
|
+
try {
|
|
159
|
+
if (!body.email) throw new require_errors.UnauthenticatedError("email is required.");
|
|
160
|
+
await this.service.requestPasswordReset(body.email);
|
|
161
|
+
} catch (err) {
|
|
162
|
+
rethrowAsHttp(err);
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
async resetPassword(body) {
|
|
166
|
+
try {
|
|
167
|
+
if (!body.token || !body.newPassword) throw new require_errors.UnauthenticatedError("token and newPassword are required.");
|
|
168
|
+
await this.service.resetPassword(body.token, body.newPassword);
|
|
169
|
+
} catch (err) {
|
|
170
|
+
rethrowAsHttp(err);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
async verifyMfaChallenge(body, res) {
|
|
174
|
+
try {
|
|
175
|
+
if (!body.mfaToken || !body.code) throw new require_errors.UnauthenticatedError("mfaToken and code are required.");
|
|
176
|
+
return buildAuthResponse(await this.service.verifyMfaChallenge(body.mfaToken, body.code), cookieOpts, res);
|
|
177
|
+
} catch (err) {
|
|
178
|
+
rethrowAsHttp(err);
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
async setup2FA(req) {
|
|
182
|
+
try {
|
|
183
|
+
return await this.service.setup2FA(req.identity.userId);
|
|
184
|
+
} catch (err) {
|
|
185
|
+
rethrowAsHttp(err);
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
async enable2FA(req, body) {
|
|
189
|
+
try {
|
|
190
|
+
if (!body.code) throw new require_errors.UnauthenticatedError("code is required.");
|
|
191
|
+
await this.service.enable2FA(req.identity.userId, body.code);
|
|
192
|
+
} catch (err) {
|
|
193
|
+
rethrowAsHttp(err);
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
async disable2FA(req, body) {
|
|
197
|
+
try {
|
|
198
|
+
if (!body.code) throw new require_errors.UnauthenticatedError("code is required.");
|
|
199
|
+
await this.service.disable2FA(req.identity.userId, body.code);
|
|
200
|
+
} catch (err) {
|
|
201
|
+
rethrowAsHttp(err);
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
async lockAccount(userId) {
|
|
205
|
+
try {
|
|
206
|
+
await this.service.lockAccount(userId);
|
|
207
|
+
} catch (err) {
|
|
208
|
+
rethrowAsHttp(err);
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
async unlockAccount(userId) {
|
|
212
|
+
try {
|
|
213
|
+
await this.service.unlockAccount(userId);
|
|
214
|
+
} catch (err) {
|
|
215
|
+
rethrowAsHttp(err);
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
async disableAccount(userId) {
|
|
219
|
+
try {
|
|
220
|
+
await this.service.disableAccount(userId);
|
|
221
|
+
} catch (err) {
|
|
222
|
+
rethrowAsHttp(err);
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
};
|
|
226
|
+
__decorate([
|
|
227
|
+
(0, _nestjs_common.Post)("register"),
|
|
228
|
+
__decorateParam(0, (0, _nestjs_common.Body)()),
|
|
229
|
+
__decorateParam(1, (0, _nestjs_common.Res)({ passthrough: true })),
|
|
230
|
+
__decorateMetadata("design:type", Function),
|
|
231
|
+
__decorateMetadata("design:paramtypes", [Object, Object]),
|
|
232
|
+
__decorateMetadata("design:returntype", Promise)
|
|
233
|
+
], IdentityController.prototype, "register", null);
|
|
234
|
+
__decorate([
|
|
235
|
+
(0, _nestjs_common.Post)("login"),
|
|
236
|
+
__decorateParam(0, (0, _nestjs_common.Body)()),
|
|
237
|
+
__decorateParam(1, (0, _nestjs_common.Res)({ passthrough: true })),
|
|
238
|
+
__decorateMetadata("design:type", Function),
|
|
239
|
+
__decorateMetadata("design:paramtypes", [Object, Object]),
|
|
240
|
+
__decorateMetadata("design:returntype", Promise)
|
|
241
|
+
], IdentityController.prototype, "login", null);
|
|
242
|
+
__decorate([
|
|
243
|
+
(0, _nestjs_common.Post)("refresh"),
|
|
244
|
+
__decorateParam(0, (0, _nestjs_common.Req)()),
|
|
245
|
+
__decorateParam(1, (0, _nestjs_common.Res)({ passthrough: true })),
|
|
246
|
+
__decorateMetadata("design:type", Function),
|
|
247
|
+
__decorateMetadata("design:paramtypes", [Object, Object]),
|
|
248
|
+
__decorateMetadata("design:returntype", Promise)
|
|
249
|
+
], IdentityController.prototype, "refresh", null);
|
|
250
|
+
__decorate([
|
|
251
|
+
(0, _nestjs_common.Post)("logout"),
|
|
252
|
+
(0, _nestjs_common.HttpCode)(204),
|
|
253
|
+
__decorateParam(0, (0, _nestjs_common.Req)()),
|
|
254
|
+
__decorateParam(1, (0, _nestjs_common.Res)({ passthrough: true })),
|
|
255
|
+
__decorateMetadata("design:type", Function),
|
|
256
|
+
__decorateMetadata("design:paramtypes", [Object, Object]),
|
|
257
|
+
__decorateMetadata("design:returntype", Promise)
|
|
258
|
+
], IdentityController.prototype, "logout", null);
|
|
259
|
+
__decorate([
|
|
260
|
+
(0, _nestjs_common.Get)("me"),
|
|
261
|
+
(0, _nestjs_common.UseGuards)(IdentityAuthGuard),
|
|
262
|
+
__decorateParam(0, (0, _nestjs_common.Req)()),
|
|
263
|
+
__decorateMetadata("design:type", Function),
|
|
264
|
+
__decorateMetadata("design:paramtypes", [Object]),
|
|
265
|
+
__decorateMetadata("design:returntype", void 0)
|
|
266
|
+
], IdentityController.prototype, "getMe", null);
|
|
267
|
+
__decorate([
|
|
268
|
+
(0, _nestjs_common.Post)("request-email-verification"),
|
|
269
|
+
(0, _nestjs_common.HttpCode)(204),
|
|
270
|
+
(0, _nestjs_common.UseGuards)(IdentityAuthGuard),
|
|
271
|
+
__decorateParam(0, (0, _nestjs_common.Req)()),
|
|
272
|
+
__decorateMetadata("design:type", Function),
|
|
273
|
+
__decorateMetadata("design:paramtypes", [Object]),
|
|
274
|
+
__decorateMetadata("design:returntype", Promise)
|
|
275
|
+
], IdentityController.prototype, "requestEmailVerification", null);
|
|
276
|
+
__decorate([
|
|
277
|
+
(0, _nestjs_common.Post)("verify-email"),
|
|
278
|
+
(0, _nestjs_common.HttpCode)(204),
|
|
279
|
+
__decorateParam(0, (0, _nestjs_common.Body)()),
|
|
280
|
+
__decorateMetadata("design:type", Function),
|
|
281
|
+
__decorateMetadata("design:paramtypes", [Object]),
|
|
282
|
+
__decorateMetadata("design:returntype", Promise)
|
|
283
|
+
], IdentityController.prototype, "verifyEmail", null);
|
|
284
|
+
__decorate([
|
|
285
|
+
(0, _nestjs_common.Post)("request-password-reset"),
|
|
286
|
+
(0, _nestjs_common.HttpCode)(204),
|
|
287
|
+
__decorateParam(0, (0, _nestjs_common.Body)()),
|
|
288
|
+
__decorateMetadata("design:type", Function),
|
|
289
|
+
__decorateMetadata("design:paramtypes", [Object]),
|
|
290
|
+
__decorateMetadata("design:returntype", Promise)
|
|
291
|
+
], IdentityController.prototype, "requestPasswordReset", null);
|
|
292
|
+
__decorate([
|
|
293
|
+
(0, _nestjs_common.Post)("reset-password"),
|
|
294
|
+
(0, _nestjs_common.HttpCode)(204),
|
|
295
|
+
__decorateParam(0, (0, _nestjs_common.Body)()),
|
|
296
|
+
__decorateMetadata("design:type", Function),
|
|
297
|
+
__decorateMetadata("design:paramtypes", [Object]),
|
|
298
|
+
__decorateMetadata("design:returntype", Promise)
|
|
299
|
+
], IdentityController.prototype, "resetPassword", null);
|
|
300
|
+
__decorate([
|
|
301
|
+
(0, _nestjs_common.Post)("mfa/verify"),
|
|
302
|
+
__decorateParam(0, (0, _nestjs_common.Body)()),
|
|
303
|
+
__decorateParam(1, (0, _nestjs_common.Res)({ passthrough: true })),
|
|
304
|
+
__decorateMetadata("design:type", Function),
|
|
305
|
+
__decorateMetadata("design:paramtypes", [Object, Object]),
|
|
306
|
+
__decorateMetadata("design:returntype", Promise)
|
|
307
|
+
], IdentityController.prototype, "verifyMfaChallenge", null);
|
|
308
|
+
__decorate([
|
|
309
|
+
(0, _nestjs_common.Post)("2fa/setup"),
|
|
310
|
+
(0, _nestjs_common.UseGuards)(IdentityAuthGuard),
|
|
311
|
+
__decorateParam(0, (0, _nestjs_common.Req)()),
|
|
312
|
+
__decorateMetadata("design:type", Function),
|
|
313
|
+
__decorateMetadata("design:paramtypes", [Object]),
|
|
314
|
+
__decorateMetadata("design:returntype", Promise)
|
|
315
|
+
], IdentityController.prototype, "setup2FA", null);
|
|
316
|
+
__decorate([
|
|
317
|
+
(0, _nestjs_common.Post)("2fa/enable"),
|
|
318
|
+
(0, _nestjs_common.HttpCode)(204),
|
|
319
|
+
(0, _nestjs_common.UseGuards)(IdentityAuthGuard),
|
|
320
|
+
__decorateParam(0, (0, _nestjs_common.Req)()),
|
|
321
|
+
__decorateParam(1, (0, _nestjs_common.Body)()),
|
|
322
|
+
__decorateMetadata("design:type", Function),
|
|
323
|
+
__decorateMetadata("design:paramtypes", [Object, Object]),
|
|
324
|
+
__decorateMetadata("design:returntype", Promise)
|
|
325
|
+
], IdentityController.prototype, "enable2FA", null);
|
|
326
|
+
__decorate([
|
|
327
|
+
(0, _nestjs_common.Post)("2fa/disable"),
|
|
328
|
+
(0, _nestjs_common.HttpCode)(204),
|
|
329
|
+
(0, _nestjs_common.UseGuards)(IdentityAuthGuard),
|
|
330
|
+
__decorateParam(0, (0, _nestjs_common.Req)()),
|
|
331
|
+
__decorateParam(1, (0, _nestjs_common.Body)()),
|
|
332
|
+
__decorateMetadata("design:type", Function),
|
|
333
|
+
__decorateMetadata("design:paramtypes", [Object, Object]),
|
|
334
|
+
__decorateMetadata("design:returntype", Promise)
|
|
335
|
+
], IdentityController.prototype, "disable2FA", null);
|
|
336
|
+
__decorate([
|
|
337
|
+
(0, _nestjs_common.Post)("admin/lock/:userId"),
|
|
338
|
+
(0, _nestjs_common.HttpCode)(204),
|
|
339
|
+
__decorateParam(0, (0, _nestjs_common.Param)("userId")),
|
|
340
|
+
__decorateMetadata("design:type", Function),
|
|
341
|
+
__decorateMetadata("design:paramtypes", [String]),
|
|
342
|
+
__decorateMetadata("design:returntype", Promise)
|
|
343
|
+
], IdentityController.prototype, "lockAccount", null);
|
|
344
|
+
__decorate([
|
|
345
|
+
(0, _nestjs_common.Post)("admin/unlock/:userId"),
|
|
346
|
+
(0, _nestjs_common.HttpCode)(204),
|
|
347
|
+
__decorateParam(0, (0, _nestjs_common.Param)("userId")),
|
|
348
|
+
__decorateMetadata("design:type", Function),
|
|
349
|
+
__decorateMetadata("design:paramtypes", [String]),
|
|
350
|
+
__decorateMetadata("design:returntype", Promise)
|
|
351
|
+
], IdentityController.prototype, "unlockAccount", null);
|
|
352
|
+
__decorate([
|
|
353
|
+
(0, _nestjs_common.Post)("admin/disable/:userId"),
|
|
354
|
+
(0, _nestjs_common.HttpCode)(204),
|
|
355
|
+
__decorateParam(0, (0, _nestjs_common.Param)("userId")),
|
|
356
|
+
__decorateMetadata("design:type", Function),
|
|
357
|
+
__decorateMetadata("design:paramtypes", [String]),
|
|
358
|
+
__decorateMetadata("design:returntype", Promise)
|
|
359
|
+
], IdentityController.prototype, "disableAccount", null);
|
|
360
|
+
IdentityController = __decorate([
|
|
361
|
+
(0, _nestjs_common.Controller)(prefix),
|
|
362
|
+
__decorateParam(0, (0, _nestjs_common.Inject)(IDENTITY_SERVICE)),
|
|
363
|
+
__decorateMetadata("design:paramtypes", [Object])
|
|
364
|
+
], IdentityController);
|
|
365
|
+
return IdentityController;
|
|
366
|
+
}
|
|
367
|
+
//#endregion
|
|
368
|
+
//#region core/nestjs/identity.module.ts
|
|
369
|
+
/**
|
|
370
|
+
* NestJS integration for `@azlib/identity`.
|
|
371
|
+
*
|
|
372
|
+
* Provides a configurable module, an authentication guard, an authorization guard driven
|
|
373
|
+
* by metadata decorators, and a `@CurrentUser()` param decorator. `@nestjs/common` and
|
|
374
|
+
* `reflect-metadata` are optional peer dependencies — only required when this entry is used.
|
|
375
|
+
*/
|
|
376
|
+
var _ref;
|
|
377
|
+
/** Token used to inject the configured {@link IdentityService} in Nest providers. */
|
|
378
|
+
const IDENTITY_SERVICE = Symbol.for("azlib.identity.service");
|
|
379
|
+
/** Metadata key holding the authorization requirement for a route. */
|
|
380
|
+
const IDENTITY_REQUIREMENT = Symbol.for("azlib.identity.requirement");
|
|
381
|
+
const extractBearerToken = (req) => {
|
|
382
|
+
const header = req.headers.authorization;
|
|
383
|
+
const value = Array.isArray(header) ? header[0] : header;
|
|
384
|
+
if (!value || !value.startsWith("Bearer ")) return null;
|
|
385
|
+
const token = value.slice(7).trim();
|
|
386
|
+
return token.length > 0 ? token : null;
|
|
387
|
+
};
|
|
388
|
+
let IdentityAuthGuard = class IdentityAuthGuard {
|
|
389
|
+
service;
|
|
390
|
+
constructor(service) {
|
|
391
|
+
this.service = service;
|
|
392
|
+
}
|
|
393
|
+
async canActivate(context) {
|
|
394
|
+
const req = context.switchToHttp().getRequest();
|
|
395
|
+
const token = extractBearerToken(req);
|
|
396
|
+
if (!token) throw new _nestjs_common.UnauthorizedException("Missing bearer token.");
|
|
397
|
+
try {
|
|
398
|
+
req.identity = await this.service.authenticate(token);
|
|
399
|
+
} catch {
|
|
400
|
+
throw new _nestjs_common.UnauthorizedException("Invalid or expired token.");
|
|
401
|
+
}
|
|
402
|
+
return true;
|
|
403
|
+
}
|
|
404
|
+
};
|
|
405
|
+
IdentityAuthGuard = __decorate([
|
|
406
|
+
(0, _nestjs_common.Injectable)(),
|
|
407
|
+
__decorateParam(0, (0, _nestjs_common.Inject)(IDENTITY_SERVICE)),
|
|
408
|
+
__decorateMetadata("design:paramtypes", [Object])
|
|
409
|
+
], IdentityAuthGuard);
|
|
410
|
+
let IdentityAuthorizationGuard = class IdentityAuthorizationGuard {
|
|
411
|
+
service;
|
|
412
|
+
reflector;
|
|
413
|
+
constructor(service, reflector) {
|
|
414
|
+
this.service = service;
|
|
415
|
+
this.reflector = reflector;
|
|
416
|
+
}
|
|
417
|
+
async canActivate(context) {
|
|
418
|
+
const requirement = this.reflector.getAllAndOverride(IDENTITY_REQUIREMENT, [context.getHandler(), context.getClass()]);
|
|
419
|
+
if (!requirement) return true;
|
|
420
|
+
const principal = context.switchToHttp().getRequest().identity;
|
|
421
|
+
if (!principal) throw new _nestjs_common.UnauthorizedException("Not authenticated.");
|
|
422
|
+
if (!(await this.service.authorize(requirement, {
|
|
423
|
+
principal,
|
|
424
|
+
action: requirement.permission ?? "custom"
|
|
425
|
+
})).allowed) throw new _nestjs_common.ForbiddenException();
|
|
426
|
+
return true;
|
|
427
|
+
}
|
|
428
|
+
};
|
|
429
|
+
IdentityAuthorizationGuard = __decorate([
|
|
430
|
+
(0, _nestjs_common.Injectable)(),
|
|
431
|
+
__decorateParam(0, (0, _nestjs_common.Inject)(IDENTITY_SERVICE)),
|
|
432
|
+
__decorateMetadata("design:paramtypes", [Object, typeof (_ref = typeof _nestjs_core.Reflector !== "undefined" && _nestjs_core.Reflector) === "function" ? _ref : Object])
|
|
433
|
+
], IdentityAuthorizationGuard);
|
|
434
|
+
/** Declares the authorization requirement for a route or controller. */
|
|
435
|
+
const RequireAuthorization = (requirement) => (0, _nestjs_common.SetMetadata)(IDENTITY_REQUIREMENT, requirement);
|
|
436
|
+
/** Convenience: declare a single required permission for a route or controller. */
|
|
437
|
+
const RequirePermission = (permission) => (0, _nestjs_common.SetMetadata)(IDENTITY_REQUIREMENT, { permission });
|
|
438
|
+
/** Param decorator that resolves the authenticated principal from the request. */
|
|
439
|
+
const CurrentUser = (0, _nestjs_common.createParamDecorator)((_data, context) => {
|
|
440
|
+
return context.switchToHttp().getRequest().identity;
|
|
441
|
+
});
|
|
442
|
+
/**
|
|
443
|
+
* NestJS module exposing the identity service plus guards. Register once at the root:
|
|
444
|
+
*
|
|
445
|
+
* ```ts
|
|
446
|
+
* IdentityModule.forRoot({ service: createIdentityService(config, store) })
|
|
447
|
+
* ```
|
|
448
|
+
*/
|
|
449
|
+
function buildControllers(routes) {
|
|
450
|
+
if (!routes) return [];
|
|
451
|
+
const routesOpts = routes === true ? {} : routes;
|
|
452
|
+
return [createIdentityController(routesOpts.prefix ?? "auth", { cookie: routesOpts.cookie })];
|
|
453
|
+
}
|
|
454
|
+
var IdentityModule = class IdentityModule {
|
|
455
|
+
static forRoot(options) {
|
|
456
|
+
return {
|
|
457
|
+
module: IdentityModule,
|
|
458
|
+
global: true,
|
|
459
|
+
controllers: buildControllers(options.routes),
|
|
460
|
+
providers: [
|
|
461
|
+
{
|
|
462
|
+
provide: IDENTITY_SERVICE,
|
|
463
|
+
useValue: options.service
|
|
464
|
+
},
|
|
465
|
+
IdentityAuthGuard,
|
|
466
|
+
IdentityAuthorizationGuard
|
|
467
|
+
],
|
|
468
|
+
exports: [
|
|
469
|
+
IDENTITY_SERVICE,
|
|
470
|
+
IdentityAuthGuard,
|
|
471
|
+
IdentityAuthorizationGuard
|
|
472
|
+
]
|
|
473
|
+
};
|
|
474
|
+
}
|
|
475
|
+
static forRootAsync(options) {
|
|
476
|
+
return {
|
|
477
|
+
module: IdentityModule,
|
|
478
|
+
global: true,
|
|
479
|
+
imports: options.imports ?? [],
|
|
480
|
+
controllers: buildControllers(options.routes),
|
|
481
|
+
providers: [
|
|
482
|
+
{
|
|
483
|
+
provide: IDENTITY_SERVICE,
|
|
484
|
+
useFactory: options.useFactory,
|
|
485
|
+
inject: options.inject
|
|
486
|
+
},
|
|
487
|
+
IdentityAuthGuard,
|
|
488
|
+
IdentityAuthorizationGuard
|
|
489
|
+
],
|
|
490
|
+
exports: [
|
|
491
|
+
IDENTITY_SERVICE,
|
|
492
|
+
IdentityAuthGuard,
|
|
493
|
+
IdentityAuthorizationGuard
|
|
494
|
+
]
|
|
495
|
+
};
|
|
496
|
+
}
|
|
497
|
+
};
|
|
498
|
+
//#endregion
|
|
499
|
+
exports.CurrentUser = CurrentUser;
|
|
500
|
+
exports.IDENTITY_REQUIREMENT = IDENTITY_REQUIREMENT;
|
|
501
|
+
exports.IDENTITY_SERVICE = IDENTITY_SERVICE;
|
|
502
|
+
Object.defineProperty(exports, "IdentityAuthGuard", {
|
|
503
|
+
enumerable: true,
|
|
504
|
+
get: function() {
|
|
505
|
+
return IdentityAuthGuard;
|
|
506
|
+
}
|
|
507
|
+
});
|
|
508
|
+
Object.defineProperty(exports, "IdentityAuthorizationGuard", {
|
|
509
|
+
enumerable: true,
|
|
510
|
+
get: function() {
|
|
511
|
+
return IdentityAuthorizationGuard;
|
|
512
|
+
}
|
|
513
|
+
});
|
|
514
|
+
exports.IdentityModule = IdentityModule;
|
|
515
|
+
exports.RequireAuthorization = RequireAuthorization;
|
|
516
|
+
exports.RequirePermission = RequirePermission;
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import { V as AuthorizationRequirement } from "./errors-C2xZAatu.cjs";
|
|
2
|
+
import { t as IdentityService } from "./identity-service-CLzKx8Z7.cjs";
|
|
3
|
+
import { t as CookieRefreshOptions } from "./identity-router-Dib30Waj.cjs";
|
|
4
|
+
import { Request, Response } from "express";
|
|
5
|
+
import { CanActivate, DynamicModule, ExecutionContext } from "@nestjs/common";
|
|
6
|
+
import { Reflector } from "@nestjs/core";
|
|
7
|
+
|
|
8
|
+
//#region core/nestjs/identity-controller.d.ts
|
|
9
|
+
/** Options accepted by {@link createIdentityController}. */
|
|
10
|
+
interface IdentityControllerOptions {
|
|
11
|
+
/**
|
|
12
|
+
* Cookie-based refresh-token transport. When set, the refresh token is stored in an
|
|
13
|
+
* `HttpOnly` cookie instead of the response body. Omit for body mode.
|
|
14
|
+
*/
|
|
15
|
+
cookie?: CookieRefreshOptions;
|
|
16
|
+
}
|
|
17
|
+
//#endregion
|
|
18
|
+
//#region core/nestjs/identity.module.d.ts
|
|
19
|
+
/** Token used to inject the configured {@link IdentityService} in Nest providers. */
|
|
20
|
+
declare const IDENTITY_SERVICE: unique symbol;
|
|
21
|
+
/** Metadata key holding the authorization requirement for a route. */
|
|
22
|
+
declare const IDENTITY_REQUIREMENT: unique symbol;
|
|
23
|
+
/**
|
|
24
|
+
* Options for enabling the pre-built REST routes in {@link IdentityModule}.
|
|
25
|
+
*/
|
|
26
|
+
interface IdentityRoutesOptions extends IdentityControllerOptions {
|
|
27
|
+
/**
|
|
28
|
+
* URL prefix for the built-in controller. Default: `"auth"`.
|
|
29
|
+
*
|
|
30
|
+
* The controller is mounted at this prefix relative to the application's global
|
|
31
|
+
* prefix (if any).
|
|
32
|
+
*/
|
|
33
|
+
prefix?: string;
|
|
34
|
+
}
|
|
35
|
+
interface IdentityModuleOptions {
|
|
36
|
+
/** A fully wired identity service (see `createIdentityService`). */
|
|
37
|
+
service: IdentityService;
|
|
38
|
+
/**
|
|
39
|
+
* When set, the module automatically registers a built-in REST controller with all
|
|
40
|
+
* standard auth endpoints (`POST /register`, `POST /login`, `POST /refresh`,
|
|
41
|
+
* `POST /logout`, `GET /me`).
|
|
42
|
+
*
|
|
43
|
+
* Pass `true` to use the defaults (`prefix: "auth"`, body-mode refresh tokens), or
|
|
44
|
+
* supply an `IdentityRoutesOptions` object to customise the prefix and cookie behaviour.
|
|
45
|
+
*
|
|
46
|
+
* @example
|
|
47
|
+
* ```ts
|
|
48
|
+
* // Minimal — everything works out of the box
|
|
49
|
+
* IdentityModule.forRoot({ service, routes: true })
|
|
50
|
+
*
|
|
51
|
+
* // With a custom prefix and HttpOnly refresh-token cookie
|
|
52
|
+
* IdentityModule.forRoot({
|
|
53
|
+
* service,
|
|
54
|
+
* routes: { prefix: "v1/auth", cookie: { name: "rt", secure: true } },
|
|
55
|
+
* })
|
|
56
|
+
* ```
|
|
57
|
+
*/
|
|
58
|
+
routes?: true | IdentityRoutesOptions;
|
|
59
|
+
}
|
|
60
|
+
interface IdentityModuleAsyncOptions {
|
|
61
|
+
imports?: DynamicModule["imports"];
|
|
62
|
+
/** Factory returning the configured identity service. */
|
|
63
|
+
useFactory: (...args: never[]) => IdentityService | Promise<IdentityService>;
|
|
64
|
+
inject?: unknown[];
|
|
65
|
+
/**
|
|
66
|
+
* Same as {@link IdentityModuleOptions.routes} — enable built-in REST routes
|
|
67
|
+
* alongside the async service factory.
|
|
68
|
+
*/
|
|
69
|
+
routes?: true | IdentityRoutesOptions;
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Authentication guard: verifies the Bearer access token and attaches the hydrated
|
|
73
|
+
* principal to `request.identity`. Apply with `@UseGuards(IdentityAuthGuard)`.
|
|
74
|
+
*/
|
|
75
|
+
declare class IdentityAuthGuard implements CanActivate {
|
|
76
|
+
private readonly service;
|
|
77
|
+
constructor(service: IdentityService);
|
|
78
|
+
canActivate(context: ExecutionContext): Promise<boolean>;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Authorization guard: enforces the requirement declared by `@RequireAuthorization()`
|
|
82
|
+
* (or `@RequirePermission()`). Must run after {@link IdentityAuthGuard}. Deny-by-default.
|
|
83
|
+
*/
|
|
84
|
+
declare class IdentityAuthorizationGuard implements CanActivate {
|
|
85
|
+
private readonly service;
|
|
86
|
+
private readonly reflector;
|
|
87
|
+
constructor(service: IdentityService, reflector: Reflector);
|
|
88
|
+
canActivate(context: ExecutionContext): Promise<boolean>;
|
|
89
|
+
}
|
|
90
|
+
/** Declares the authorization requirement for a route or controller. */
|
|
91
|
+
declare const RequireAuthorization: (requirement: AuthorizationRequirement) => import("@nestjs/common").CustomDecorator<typeof IDENTITY_REQUIREMENT>;
|
|
92
|
+
/** Convenience: declare a single required permission for a route or controller. */
|
|
93
|
+
declare const RequirePermission: (permission: string) => import("@nestjs/common").CustomDecorator<typeof IDENTITY_REQUIREMENT>;
|
|
94
|
+
/** Param decorator that resolves the authenticated principal from the request. */
|
|
95
|
+
declare const CurrentUser: (...dataOrPipes: unknown[]) => ParameterDecorator;
|
|
96
|
+
declare class IdentityModule {
|
|
97
|
+
static forRoot(options: IdentityModuleOptions): DynamicModule;
|
|
98
|
+
static forRootAsync(options: IdentityModuleAsyncOptions): DynamicModule;
|
|
99
|
+
}
|
|
100
|
+
//#endregion
|
|
101
|
+
export { CurrentUser, IDENTITY_REQUIREMENT, IDENTITY_SERVICE, IdentityAuthGuard, IdentityAuthorizationGuard, type IdentityControllerOptions, IdentityModule, IdentityModuleAsyncOptions, IdentityModuleOptions, IdentityRoutesOptions, RequireAuthorization, RequirePermission };
|
|
102
|
+
//# sourceMappingURL=nestjs.d.cts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"nestjs.d.cts","names":[],"sources":["../core/nestjs/identity-controller.ts","../core/nestjs/identity.module.ts"],"mappings":";;;;;;;;;UAkGiB,yBAAA;;;AAAjB;;EAKE,MAAA,GAAS,oBAAoB;AAAA;;;AAAA;AAAA,cC1ElB,gBAAA;;cAGA,oBAAA;AAHb;;;AAAA,UAQiB,qBAAA,SAA8B,yBAAyB;EARJ;AAGpE;;;;AAA4E;EAY1E,MAAM;AAAA;AAAA,UAGS,qBAAA;EAV8B;EAY7C,OAAA,EAAS,eAAA;EAFM;;;;;;;;;AAuBsB;AAGvC;;;;;;;;;;EAHE,MAAA,UAAgB,qBAAqB;AAAA;AAAA,UAGtB,0BAAA;EACf,OAAA,GAAU,aAAA;EAEwB;EAAlC,UAAA,MAAgB,IAAA,cAAkB,eAAA,GAAkB,OAAA,CAAQ,eAAA;EAC5D,MAAA;EAAA;;;;EAKA,MAAA,UAAgB,qBAAA;AAAA;;;;;cAqBL,iBAAA,YAA6B,WAAA;EAAA,iBACe,OAAA;cAAA,OAAA,EAAS,eAAA;EAE1D,WAAA,CAAY,OAAA,EAAS,gBAAA,GAAmB,OAAA;AAAA;;;;;cAoBnC,0BAAA,YAAsC,WAAA;EAAA,iBAEJ,OAAA;EAAA,iBAC1B,SAAA;cAD0B,OAAA,EAAS,eAAA,EACnC,SAAA,EAAW,SAAA;EAGxB,WAAA,CAAY,OAAA,EAAS,gBAAA,GAAmB,OAAA;AAAA;AAPhD;AAAA,cAgCa,oBAAA,GAAoB,WAAA,EAAiB,wBAAA,8BAAwB,eAAA,QAAA,oBAAA;;cAI7D,iBAAA,GAAiB,UAAA,sCAAsB,eAAA,QAAA,oBAAA;;cAIvC,WAAA,MAAW,WAAA,gBAAA,kBAKvB;AAAA,cAiBY,cAAA;EAAA,OACJ,OAAA,CAAQ,OAAA,EAAS,qBAAA,GAAwB,aAAA;EAAA,OAczC,YAAA,CAAa,OAAA,EAAS,0BAAA,GAA6B,aAAA;AAAA"}
|