@sqrzro/server 2.0.0-bz.1 → 2.0.0-bz.11
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 +1 -1
- package/README.md +25 -1
- package/auth.d.ts +1 -0
- package/auth.js +1 -0
- package/cache.d.ts +1 -0
- package/cache.js +1 -0
- package/dist/auth.d.ts +100 -0
- package/dist/auth.js +891 -0
- package/dist/cache.d.ts +4 -0
- package/dist/cache.js +46 -0
- package/dist/forms.d.ts +46 -0
- package/dist/forms.js +327 -0
- package/dist/lists.d.ts +18 -0
- package/dist/lists.js +61 -0
- package/dist/mail.d.ts +12 -0
- package/dist/mail.js +97 -0
- package/dist/middleware.d.ts +5 -0
- package/dist/middleware.js +66 -0
- package/dist/schema.d.ts +288 -0
- package/dist/schema.js +77 -0
- package/dist/url.d.ts +28 -0
- package/dist/url.js +56 -0
- package/forms.d.ts +1 -0
- package/forms.js +1 -0
- package/lists.d.ts +1 -0
- package/lists.js +1 -0
- package/mail.d.ts +1 -0
- package/mail.js +1 -0
- package/middleware.d.ts +1 -0
- package/middleware.js +1 -0
- package/package.json +67 -44
- package/schema.d.ts +1 -0
- package/schema.js +1 -0
- package/url.d.ts +1 -0
- package/url.js +1 -0
- package/dist/AuthService.d.ts +0 -10
- package/dist/AuthService.js +0 -36
- package/dist/DataService.d.ts +0 -29
- package/dist/DataService.js +0 -64
- package/dist/LoginRequest.d.ts +0 -4
- package/dist/LoginRequest.js +0 -11
- package/dist/PasswordService.d.ts +0 -6
- package/dist/PasswordService.js +0 -63
- package/dist/RequestService.d.ts +0 -21
- package/dist/RequestService.js +0 -121
- package/dist/SessionService.d.ts +0 -5
- package/dist/SessionService.js +0 -56
- package/dist/index.d.ts +0 -7
- package/dist/index.js +0 -10
- package/dist/interfaces.d.ts +0 -11
- package/dist/interfaces.js +0 -2
package/dist/auth.js
ADDED
|
@@ -0,0 +1,891 @@
|
|
|
1
|
+
var __create = Object.create;
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
6
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
7
|
+
var __export = (target, all) => {
|
|
8
|
+
for (var name in all)
|
|
9
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
10
|
+
};
|
|
11
|
+
var __copyProps = (to, from, except, desc) => {
|
|
12
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
13
|
+
for (let key of __getOwnPropNames(from))
|
|
14
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
15
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
16
|
+
}
|
|
17
|
+
return to;
|
|
18
|
+
};
|
|
19
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
20
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
21
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
22
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
23
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
24
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
25
|
+
mod
|
|
26
|
+
));
|
|
27
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
28
|
+
|
|
29
|
+
// src/auth/index.ts
|
|
30
|
+
var auth_exports = {};
|
|
31
|
+
__export(auth_exports, {
|
|
32
|
+
checkMFAEnabled: () => checkMFAEnabled,
|
|
33
|
+
checkPasswordComplexity: () => checkPasswordComplexity,
|
|
34
|
+
checkRouteAllowed: () => checkRouteAllowed,
|
|
35
|
+
checkSessionExists: () => checkSessionExists,
|
|
36
|
+
checkUserHasMFA: () => checkUserHasMFA,
|
|
37
|
+
createUserSession: () => createUserSession,
|
|
38
|
+
generateID: () => generateID,
|
|
39
|
+
generateMFA: () => generateMFA,
|
|
40
|
+
getAllowedRoles: () => getAllowedRoles,
|
|
41
|
+
getClientByID: () => getClientByID,
|
|
42
|
+
getPasswordComplexity: () => getPasswordComplexity,
|
|
43
|
+
getScopeByID: () => getScopeByID,
|
|
44
|
+
getScopes: () => getScopes,
|
|
45
|
+
getSessionID: () => getSessionID,
|
|
46
|
+
getSessionUser: () => getSessionUser,
|
|
47
|
+
handleClientAuth: () => handleClientAuth,
|
|
48
|
+
handleLoginForm: () => handleLoginForm,
|
|
49
|
+
handleLogout: () => handleLogout,
|
|
50
|
+
handleMFAForm: () => handleMFAForm,
|
|
51
|
+
handlePasswordForm: () => handlePasswordForm,
|
|
52
|
+
handlePasswordResetForm: () => handlePasswordResetForm,
|
|
53
|
+
handleSession: () => handleSession,
|
|
54
|
+
hashPassword: () => hashPassword,
|
|
55
|
+
invalidateSession: () => invalidateSession,
|
|
56
|
+
invalidateUserSessions: () => invalidateUserSessions,
|
|
57
|
+
lucia: () => lucia,
|
|
58
|
+
registerClient: () => registerClient,
|
|
59
|
+
registerUser: () => registerUser,
|
|
60
|
+
setScopes: () => setScopes,
|
|
61
|
+
verifyPassword: () => verifyPassword
|
|
62
|
+
});
|
|
63
|
+
module.exports = __toCommonJS(auth_exports);
|
|
64
|
+
|
|
65
|
+
// src/auth/AuthService.ts
|
|
66
|
+
var import_drizzle_orm2 = require("drizzle-orm");
|
|
67
|
+
|
|
68
|
+
// src/database/DatabaseService.ts
|
|
69
|
+
var import_postgres_js = require("drizzle-orm/postgres-js");
|
|
70
|
+
var import_postgres = __toESM(require("postgres"));
|
|
71
|
+
function createSingleton() {
|
|
72
|
+
if (!process.env.DATABASE_URL) {
|
|
73
|
+
throw new Error("DATABASE_URL is not defined");
|
|
74
|
+
}
|
|
75
|
+
return (0, import_postgres_js.drizzle)((0, import_postgres.default)(process.env.DATABASE_URL, { prepare: false }));
|
|
76
|
+
}
|
|
77
|
+
var db = globalThis.db ?? createSingleton();
|
|
78
|
+
if (!process.env.VERCEL_ENV) {
|
|
79
|
+
globalThis.db = db;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// src/database/schema.ts
|
|
83
|
+
var import_pg_core = require("drizzle-orm/pg-core");
|
|
84
|
+
var DEFAULT_ROLE = 10;
|
|
85
|
+
var mfaType = (0, import_pg_core.pgEnum)("mfaType", ["TOTP", "HARDWARE"]);
|
|
86
|
+
var scope = (0, import_pg_core.pgEnum)("scope", ["ANON", "MFA", "AUTHED"]);
|
|
87
|
+
var authSchema = (0, import_pg_core.pgSchema)("auth");
|
|
88
|
+
var authUserTable = authSchema.table("user_credentials", {
|
|
89
|
+
id: (0, import_pg_core.text)("id").primaryKey(),
|
|
90
|
+
email: (0, import_pg_core.text)("email").notNull().unique(),
|
|
91
|
+
password: (0, import_pg_core.text)("password"),
|
|
92
|
+
role: (0, import_pg_core.integer)("role").notNull().default(DEFAULT_ROLE)
|
|
93
|
+
});
|
|
94
|
+
var authSessionTable = authSchema.table("sessions", {
|
|
95
|
+
id: (0, import_pg_core.text)("id").primaryKey(),
|
|
96
|
+
userId: (0, import_pg_core.text)("userId").notNull().references(() => authUserTable.id),
|
|
97
|
+
scope: scope("scope").notNull().default("ANON"),
|
|
98
|
+
expiresAt: (0, import_pg_core.timestamp)("expiresAt").notNull()
|
|
99
|
+
});
|
|
100
|
+
var authResetTable = authSchema.table("resets", {
|
|
101
|
+
id: (0, import_pg_core.text)("id").primaryKey(),
|
|
102
|
+
userId: (0, import_pg_core.text)("userId").notNull().references(() => authUserTable.id),
|
|
103
|
+
expiresAt: (0, import_pg_core.timestamp)("expiresAt").notNull()
|
|
104
|
+
});
|
|
105
|
+
var authMFATable = authSchema.table("mfas", {
|
|
106
|
+
id: (0, import_pg_core.text)("id").primaryKey(),
|
|
107
|
+
name: (0, import_pg_core.text)("name").notNull(),
|
|
108
|
+
userId: (0, import_pg_core.text)("userId").notNull().references(() => authUserTable.id),
|
|
109
|
+
type: mfaType("type").notNull().default("TOTP"),
|
|
110
|
+
secret: (0, import_pg_core.text)("secret").notNull(),
|
|
111
|
+
verifiedAt: (0, import_pg_core.timestamp)("verifiedAt")
|
|
112
|
+
});
|
|
113
|
+
var authClientTable = authSchema.table("client_credentials", {
|
|
114
|
+
id: (0, import_pg_core.text)("id").primaryKey(),
|
|
115
|
+
alias: (0, import_pg_core.text)("alias").notNull().unique(),
|
|
116
|
+
secret: (0, import_pg_core.text)("secret").notNull().unique()
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
// src/forms/ValidationError.ts
|
|
120
|
+
var ValidationError = class extends Error {
|
|
121
|
+
constructor(messages2) {
|
|
122
|
+
super(JSON.stringify(messages2));
|
|
123
|
+
this.name = "ValidationError";
|
|
124
|
+
}
|
|
125
|
+
};
|
|
126
|
+
var ValidationError_default = ValidationError;
|
|
127
|
+
|
|
128
|
+
// src/forms/ValidationService.ts
|
|
129
|
+
var import_joi = __toESM(require("joi"));
|
|
130
|
+
|
|
131
|
+
// src/forms/lang.ts
|
|
132
|
+
var messages = {
|
|
133
|
+
"alternatives.all": "",
|
|
134
|
+
"alternatives.any": "",
|
|
135
|
+
"alternatives.match": "",
|
|
136
|
+
"alternatives.one": "",
|
|
137
|
+
"alternatives.types": "",
|
|
138
|
+
"any.custom": "",
|
|
139
|
+
"any.default": "",
|
|
140
|
+
"any.failover": "",
|
|
141
|
+
"any.invalid": "",
|
|
142
|
+
"any.only": "",
|
|
143
|
+
"any.ref": "",
|
|
144
|
+
"any.required": "{{#label}} is required",
|
|
145
|
+
"any.unknown": "",
|
|
146
|
+
"array.base": "",
|
|
147
|
+
"array.excludes": "",
|
|
148
|
+
"array.includesRequiredBoth": "",
|
|
149
|
+
"array.includesRequiredKnowns": "",
|
|
150
|
+
"array.includesRequiredUnknowns": "",
|
|
151
|
+
"array.includes": "",
|
|
152
|
+
"array.length": "",
|
|
153
|
+
"array.max": "",
|
|
154
|
+
"array.min": "",
|
|
155
|
+
"array.orderedLength": "",
|
|
156
|
+
"array.sort": "",
|
|
157
|
+
"array.sort.mismatching": "",
|
|
158
|
+
"array.sort.unsupported": "",
|
|
159
|
+
"array.sparse": "",
|
|
160
|
+
"array.unique": "",
|
|
161
|
+
"array.hasKnown": "",
|
|
162
|
+
"array.hasUnknown": "",
|
|
163
|
+
"binary.base": "",
|
|
164
|
+
"binary.length": "",
|
|
165
|
+
"binary.max": "",
|
|
166
|
+
"binary.min": "",
|
|
167
|
+
"boolean.base": "",
|
|
168
|
+
"date.base": "",
|
|
169
|
+
"date.format": "",
|
|
170
|
+
"date.greater": "",
|
|
171
|
+
"date.less": "",
|
|
172
|
+
"date.max": "",
|
|
173
|
+
"date.min": "",
|
|
174
|
+
"date.strict": "",
|
|
175
|
+
"function.arity": "",
|
|
176
|
+
"function.class": "",
|
|
177
|
+
"function.maxArity": "",
|
|
178
|
+
"function.minArity": "",
|
|
179
|
+
"number.base": "{{#label}} should be a number",
|
|
180
|
+
"number.greater": "",
|
|
181
|
+
"number.infinity": "",
|
|
182
|
+
"number.integer": "",
|
|
183
|
+
"number.less": "",
|
|
184
|
+
"number.max": "",
|
|
185
|
+
"number.min": "{{#label}} should be greater than or equal to {{#limit}}",
|
|
186
|
+
"number.multiple": "",
|
|
187
|
+
"number.negative": "",
|
|
188
|
+
"number.port": "",
|
|
189
|
+
"number.positive": "",
|
|
190
|
+
"number.precision": "",
|
|
191
|
+
"number.unsafe": "",
|
|
192
|
+
"object.unknown": "",
|
|
193
|
+
"object.and": "",
|
|
194
|
+
"object.assert": "",
|
|
195
|
+
"object.base": "",
|
|
196
|
+
"object.length": "",
|
|
197
|
+
"object.max": "",
|
|
198
|
+
"object.min": "",
|
|
199
|
+
"object.missing": "",
|
|
200
|
+
"object.nand": "",
|
|
201
|
+
"object.pattern.match": "",
|
|
202
|
+
"object.refType": "",
|
|
203
|
+
"object.regex": "",
|
|
204
|
+
"object.rename.multiple": "",
|
|
205
|
+
"object.rename.override": "",
|
|
206
|
+
"object.schema": "",
|
|
207
|
+
"object.instance": "",
|
|
208
|
+
"object.with": "",
|
|
209
|
+
"object.without": "",
|
|
210
|
+
"object.xor": "",
|
|
211
|
+
"object.oxor": "",
|
|
212
|
+
"string.alphanum": "",
|
|
213
|
+
"string.base64": "",
|
|
214
|
+
"string.base": "",
|
|
215
|
+
"string.creditCard": "",
|
|
216
|
+
"string.dataUri": "",
|
|
217
|
+
"string.domain": "",
|
|
218
|
+
"string.email": "",
|
|
219
|
+
"string.empty": "{{#label}} is required",
|
|
220
|
+
"string.guid": "",
|
|
221
|
+
"string.hexAlign": "",
|
|
222
|
+
"string.hex": "",
|
|
223
|
+
"string.hostname": "",
|
|
224
|
+
"string.ipVersion": "",
|
|
225
|
+
"string.ip": "",
|
|
226
|
+
"string.isoDate": "",
|
|
227
|
+
"string.isoDuration": "",
|
|
228
|
+
"string.length": "",
|
|
229
|
+
"string.lowercase": "",
|
|
230
|
+
"string.max": "",
|
|
231
|
+
"string.min": "",
|
|
232
|
+
"string.normalize": "",
|
|
233
|
+
"string.pattern.base": "",
|
|
234
|
+
"string.pattern.name": "",
|
|
235
|
+
"string.pattern.invert.base": "",
|
|
236
|
+
"string.pattern.invert.name": "",
|
|
237
|
+
"string.token": "",
|
|
238
|
+
"string.trim": "",
|
|
239
|
+
"string.uppercase": "",
|
|
240
|
+
"string.uri": "",
|
|
241
|
+
"string.uriCustomScheme": "",
|
|
242
|
+
"string.uriRelativeOnly": "",
|
|
243
|
+
"symbol.base": "",
|
|
244
|
+
"symbol.map": ""
|
|
245
|
+
};
|
|
246
|
+
var lang_default = messages;
|
|
247
|
+
|
|
248
|
+
// src/forms/ValidationService.ts
|
|
249
|
+
function getErrorMessages() {
|
|
250
|
+
return Object.entries(lang_default).reduce((acc, [key, value]) => {
|
|
251
|
+
if (!value) {
|
|
252
|
+
return acc;
|
|
253
|
+
}
|
|
254
|
+
return {
|
|
255
|
+
...acc,
|
|
256
|
+
[key]: value
|
|
257
|
+
};
|
|
258
|
+
}, {});
|
|
259
|
+
}
|
|
260
|
+
function transformErrors(error) {
|
|
261
|
+
const messages2 = error.details.reduce(
|
|
262
|
+
(acc, cur) => ({
|
|
263
|
+
...acc,
|
|
264
|
+
[cur.path.join(".")]: cur.message.replace(/"/gu, "")
|
|
265
|
+
}),
|
|
266
|
+
{}
|
|
267
|
+
);
|
|
268
|
+
return new ValidationError_default(messages2);
|
|
269
|
+
}
|
|
270
|
+
async function validateSchema(formData, validation) {
|
|
271
|
+
try {
|
|
272
|
+
const validated = await validation.validateAsync(formData, {
|
|
273
|
+
abortEarly: false,
|
|
274
|
+
messages: getErrorMessages()
|
|
275
|
+
});
|
|
276
|
+
return [validated, null];
|
|
277
|
+
} catch (err) {
|
|
278
|
+
if (err instanceof import_joi.default.ValidationError) {
|
|
279
|
+
return [null, transformErrors(err)];
|
|
280
|
+
}
|
|
281
|
+
if (err instanceof Error) {
|
|
282
|
+
return [null, err];
|
|
283
|
+
}
|
|
284
|
+
return [null, new Error("Unknown validation error occured")];
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
function createSchema(schema) {
|
|
288
|
+
return import_joi.default.object(schema);
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
// src/forms/FormService.ts
|
|
292
|
+
function serializeError(err) {
|
|
293
|
+
return {
|
|
294
|
+
cause: err.cause,
|
|
295
|
+
message: err.message,
|
|
296
|
+
name: err.name,
|
|
297
|
+
stack: err.stack
|
|
298
|
+
};
|
|
299
|
+
}
|
|
300
|
+
function hasFn(args) {
|
|
301
|
+
return Boolean(Object.prototype.hasOwnProperty.call(args, "fn"));
|
|
302
|
+
}
|
|
303
|
+
async function submitForm(args) {
|
|
304
|
+
let data = { ...args.formData };
|
|
305
|
+
if (args.request) {
|
|
306
|
+
const [validated, validationError] = await validateSchema(args.formData, args.request);
|
|
307
|
+
if (validationError !== null) {
|
|
308
|
+
if (validationError instanceof ValidationError_default) {
|
|
309
|
+
args.onValidationError?.(validationError);
|
|
310
|
+
}
|
|
311
|
+
return [null, serializeError(validationError)];
|
|
312
|
+
}
|
|
313
|
+
data = validated;
|
|
314
|
+
}
|
|
315
|
+
if (!hasFn(args)) {
|
|
316
|
+
try {
|
|
317
|
+
await args.onSuccess?.(data);
|
|
318
|
+
} catch (err) {
|
|
319
|
+
if (err instanceof Error) {
|
|
320
|
+
return [null, serializeError(err)];
|
|
321
|
+
}
|
|
322
|
+
return [
|
|
323
|
+
null,
|
|
324
|
+
serializeError(
|
|
325
|
+
new Error("The submitForm onSuccess function encountered an unknown error")
|
|
326
|
+
)
|
|
327
|
+
];
|
|
328
|
+
}
|
|
329
|
+
return [data, null];
|
|
330
|
+
}
|
|
331
|
+
let model = null;
|
|
332
|
+
try {
|
|
333
|
+
model = await args.fn(data);
|
|
334
|
+
} catch (err) {
|
|
335
|
+
if (err instanceof ValidationError_default) {
|
|
336
|
+
args.onValidationError?.(err);
|
|
337
|
+
return [null, serializeError(err)];
|
|
338
|
+
}
|
|
339
|
+
if (err instanceof Error) {
|
|
340
|
+
return [null, serializeError(err)];
|
|
341
|
+
}
|
|
342
|
+
return [
|
|
343
|
+
null,
|
|
344
|
+
serializeError(
|
|
345
|
+
new Error("The function supplied to submitForm encountered an unknown error")
|
|
346
|
+
)
|
|
347
|
+
];
|
|
348
|
+
}
|
|
349
|
+
if (!model) {
|
|
350
|
+
return [
|
|
351
|
+
null,
|
|
352
|
+
serializeError(
|
|
353
|
+
new Error("No model has been returned from the function supplied to submitForm")
|
|
354
|
+
)
|
|
355
|
+
];
|
|
356
|
+
}
|
|
357
|
+
try {
|
|
358
|
+
await args.onSuccess?.(model);
|
|
359
|
+
} catch (err) {
|
|
360
|
+
if (err instanceof Error) {
|
|
361
|
+
return [null, serializeError(err)];
|
|
362
|
+
}
|
|
363
|
+
return [
|
|
364
|
+
null,
|
|
365
|
+
serializeError(
|
|
366
|
+
new Error("The submitForm onSuccess function encountered an unknown error")
|
|
367
|
+
)
|
|
368
|
+
];
|
|
369
|
+
}
|
|
370
|
+
return [model, null];
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
// src/auth/MFAService.ts
|
|
374
|
+
var import_drizzle_orm = require("drizzle-orm");
|
|
375
|
+
var import_qrcode = __toESM(require("qrcode"));
|
|
376
|
+
var import_otplib = require("otplib");
|
|
377
|
+
|
|
378
|
+
// src/auth/MFARequest.ts
|
|
379
|
+
var import_joi2 = __toESM(require("joi"));
|
|
380
|
+
var MFARequest = createSchema({
|
|
381
|
+
token: import_joi2.default.string().pattern(/^[0-9]{6}$/u).required()
|
|
382
|
+
});
|
|
383
|
+
var MFARequest_default = MFARequest;
|
|
384
|
+
|
|
385
|
+
// src/auth/SessionService.ts
|
|
386
|
+
var import_adapter_drizzle = require("@lucia-auth/adapter-drizzle");
|
|
387
|
+
var import_lucia = require("lucia");
|
|
388
|
+
var import_headers2 = require("next/headers");
|
|
389
|
+
var import_server = require("next/server");
|
|
390
|
+
var import_path_to_regexp = require("path-to-regexp");
|
|
391
|
+
|
|
392
|
+
// src/cache/CacheService.ts
|
|
393
|
+
var import_redis = require("redis");
|
|
394
|
+
async function getClient() {
|
|
395
|
+
const client = (0, import_redis.createClient)();
|
|
396
|
+
await client.connect();
|
|
397
|
+
return client;
|
|
398
|
+
}
|
|
399
|
+
async function getFromCache(key) {
|
|
400
|
+
const client = await getClient();
|
|
401
|
+
return client.get(key);
|
|
402
|
+
}
|
|
403
|
+
async function setToCache(key, value) {
|
|
404
|
+
const client = await getClient();
|
|
405
|
+
await client.set(key, value);
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
// src/url/URLService.ts
|
|
409
|
+
var import_headers = require("next/headers");
|
|
410
|
+
function getOrigin() {
|
|
411
|
+
const origin = (0, import_headers.headers)().get("x-origin");
|
|
412
|
+
if (origin) {
|
|
413
|
+
return origin;
|
|
414
|
+
}
|
|
415
|
+
const proto = (0, import_headers.headers)().get("x-forwarded-proto");
|
|
416
|
+
const host = (0, import_headers.headers)().get("x-forwarded-host");
|
|
417
|
+
if (proto && host) {
|
|
418
|
+
return `${proto}://${host}`;
|
|
419
|
+
}
|
|
420
|
+
throw new Error("No origin could be determined");
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
// src/auth/SessionService.ts
|
|
424
|
+
var import_utility = require("@sqrzro/utility");
|
|
425
|
+
var DEFAULT_REDIRECT = "/auth/login";
|
|
426
|
+
var ID_LENGTH = 16;
|
|
427
|
+
var DEFAULT_SCOPES = {
|
|
428
|
+
ANON: {
|
|
429
|
+
allowedRoute: "/auth/(login|password)",
|
|
430
|
+
redirectOnUnauth: DEFAULT_REDIRECT
|
|
431
|
+
},
|
|
432
|
+
MFA: {
|
|
433
|
+
allowedRoute: "/auth/mfa",
|
|
434
|
+
redirectOnUnauth: "/auth/mfa"
|
|
435
|
+
},
|
|
436
|
+
AUTHED: {
|
|
437
|
+
allowedRoute: "*",
|
|
438
|
+
redirectOnAuth: "/"
|
|
439
|
+
}
|
|
440
|
+
};
|
|
441
|
+
var adapter = new import_adapter_drizzle.DrizzlePostgreSQLAdapter(db, authSessionTable, authUserTable);
|
|
442
|
+
var lucia = new import_lucia.Lucia(adapter, {
|
|
443
|
+
sessionCookie: {
|
|
444
|
+
attributes: {
|
|
445
|
+
secure: process.env.NODE_ENV === "production"
|
|
446
|
+
},
|
|
447
|
+
name: process.env.AUTH_COOKIE_NAME || "auth_session"
|
|
448
|
+
},
|
|
449
|
+
getSessionAttributes: (attributes) => ({
|
|
450
|
+
scope: attributes.scope
|
|
451
|
+
}),
|
|
452
|
+
getUserAttributes: (attributes) => ({
|
|
453
|
+
email: attributes.email,
|
|
454
|
+
role: attributes.role
|
|
455
|
+
})
|
|
456
|
+
});
|
|
457
|
+
function generateID(length = ID_LENGTH) {
|
|
458
|
+
return (0, import_lucia.generateId)(length);
|
|
459
|
+
}
|
|
460
|
+
async function invalidateSession(id) {
|
|
461
|
+
const cookie = lucia.createBlankSessionCookie();
|
|
462
|
+
(0, import_headers2.cookies)().set(cookie.name, cookie.value, cookie.attributes);
|
|
463
|
+
return lucia.invalidateSession(id);
|
|
464
|
+
}
|
|
465
|
+
async function invalidateUserSessions(id) {
|
|
466
|
+
return lucia.invalidateUserSessions(id);
|
|
467
|
+
}
|
|
468
|
+
async function createUserSession(id, scope2 = "ANON") {
|
|
469
|
+
const session = await lucia.createSession(id, { scope: scope2 });
|
|
470
|
+
const sessionCookie = lucia.createSessionCookie(session.id);
|
|
471
|
+
(0, import_headers2.cookies)().set(sessionCookie.name, sessionCookie.value, sessionCookie.attributes);
|
|
472
|
+
return true;
|
|
473
|
+
}
|
|
474
|
+
function getSessionID() {
|
|
475
|
+
return (0, import_headers2.cookies)().get(lucia.sessionCookieName)?.value ?? null;
|
|
476
|
+
}
|
|
477
|
+
function checkSessionExists() {
|
|
478
|
+
return Boolean(getSessionID());
|
|
479
|
+
}
|
|
480
|
+
async function getSessionUser() {
|
|
481
|
+
const sessionID = getSessionID();
|
|
482
|
+
if (!sessionID) {
|
|
483
|
+
return null;
|
|
484
|
+
}
|
|
485
|
+
const { user } = await lucia.validateSession(sessionID);
|
|
486
|
+
if (!user?.role || !getAllowedRoles().includes(user.role)) {
|
|
487
|
+
return null;
|
|
488
|
+
}
|
|
489
|
+
return (0, import_utility.getFromObject)(user, ["id", "email", "role"]);
|
|
490
|
+
}
|
|
491
|
+
function checkRouteAllowed(pathname, route) {
|
|
492
|
+
if (!route) {
|
|
493
|
+
return false;
|
|
494
|
+
}
|
|
495
|
+
if (route === "*") {
|
|
496
|
+
return true;
|
|
497
|
+
}
|
|
498
|
+
return (0, import_path_to_regexp.match)(route)(pathname) !== false;
|
|
499
|
+
}
|
|
500
|
+
async function getScopes() {
|
|
501
|
+
const scopes = await getFromCache(`${getOrigin()}:scopes`);
|
|
502
|
+
return scopes ? JSON.parse(scopes) : DEFAULT_SCOPES;
|
|
503
|
+
}
|
|
504
|
+
async function getScopeByID(id) {
|
|
505
|
+
const scopes = await getScopes();
|
|
506
|
+
return scopes[id];
|
|
507
|
+
}
|
|
508
|
+
async function setScopes(customScopes) {
|
|
509
|
+
const scopes = {
|
|
510
|
+
ANON: {
|
|
511
|
+
...DEFAULT_SCOPES.ANON,
|
|
512
|
+
...customScopes?.ANON
|
|
513
|
+
},
|
|
514
|
+
MFA: {
|
|
515
|
+
...DEFAULT_SCOPES.MFA,
|
|
516
|
+
...customScopes?.MFA
|
|
517
|
+
},
|
|
518
|
+
AUTHED: {
|
|
519
|
+
...DEFAULT_SCOPES.AUTHED,
|
|
520
|
+
...customScopes?.AUTHED
|
|
521
|
+
}
|
|
522
|
+
};
|
|
523
|
+
return setToCache(`${getOrigin()}:scopes`, JSON.stringify(scopes));
|
|
524
|
+
}
|
|
525
|
+
async function validateSessionFromID(sessionID, pathname) {
|
|
526
|
+
const scopes = await getScopes();
|
|
527
|
+
const { session, user } = await lucia.validateSession(sessionID);
|
|
528
|
+
const scope2 = scopes[session && getAllowedRoles().includes(user?.role) ? session.scope : "ANON"];
|
|
529
|
+
return checkRouteAllowed(pathname, scope2.allowedRoute) ? null : scope2.redirectOnUnauth || DEFAULT_REDIRECT;
|
|
530
|
+
}
|
|
531
|
+
async function handleSession(request, customScopes) {
|
|
532
|
+
const sessionID = request.nextUrl.searchParams.get("id") || "";
|
|
533
|
+
const pathname = request.nextUrl.searchParams.get("pathname") || "/";
|
|
534
|
+
await setScopes(customScopes);
|
|
535
|
+
return import_server.NextResponse.json({
|
|
536
|
+
redirect: await validateSessionFromID(sessionID, pathname)
|
|
537
|
+
});
|
|
538
|
+
}
|
|
539
|
+
|
|
540
|
+
// src/auth/MFAService.ts
|
|
541
|
+
function checkMFAEnabled() {
|
|
542
|
+
return process.env.AUTH_MFA_ENABLED !== "false";
|
|
543
|
+
}
|
|
544
|
+
async function generateMFA(name, email) {
|
|
545
|
+
if (!checkMFAEnabled() || !email) {
|
|
546
|
+
return null;
|
|
547
|
+
}
|
|
548
|
+
const [user] = await db.select().from(authUserTable).where((0, import_drizzle_orm.eq)(authUserTable.email, email)).limit(1);
|
|
549
|
+
if (!user) {
|
|
550
|
+
return null;
|
|
551
|
+
}
|
|
552
|
+
const secret = import_otplib.authenticator.generateSecret();
|
|
553
|
+
const otpauth = import_otplib.authenticator.keyuri(email, name, secret);
|
|
554
|
+
await db.delete(authMFATable).where((0, import_drizzle_orm.and)((0, import_drizzle_orm.eq)(authMFATable.userId, user.id), (0, import_drizzle_orm.isNull)(authMFATable.verifiedAt)));
|
|
555
|
+
await db.insert(authMFATable).values({
|
|
556
|
+
id: generateID(),
|
|
557
|
+
name: "Default",
|
|
558
|
+
secret,
|
|
559
|
+
userId: user.id
|
|
560
|
+
});
|
|
561
|
+
return new Promise((resolve, reject) => {
|
|
562
|
+
import_qrcode.default.toDataURL(
|
|
563
|
+
otpauth,
|
|
564
|
+
{ rendererOpts: { quality: 1 }, margin: 0, scale: 2 },
|
|
565
|
+
(err, data) => {
|
|
566
|
+
if (err) {
|
|
567
|
+
reject(err);
|
|
568
|
+
}
|
|
569
|
+
resolve(data);
|
|
570
|
+
}
|
|
571
|
+
);
|
|
572
|
+
});
|
|
573
|
+
}
|
|
574
|
+
async function checkUserHasMFA(user) {
|
|
575
|
+
if (!checkMFAEnabled()) {
|
|
576
|
+
return false;
|
|
577
|
+
}
|
|
578
|
+
const [mfa] = await db.select().from(authMFATable).where((0, import_drizzle_orm.and)((0, import_drizzle_orm.eq)(authMFATable.userId, user.id), (0, import_drizzle_orm.isNotNull)(authMFATable.verifiedAt))).limit(1);
|
|
579
|
+
return Boolean(mfa);
|
|
580
|
+
}
|
|
581
|
+
async function markAsVerified(userID) {
|
|
582
|
+
if (!checkMFAEnabled()) {
|
|
583
|
+
return;
|
|
584
|
+
}
|
|
585
|
+
await db.update(authMFATable).set({ verifiedAt: /* @__PURE__ */ new Date() }).where((0, import_drizzle_orm.eq)(authMFATable.userId, userID));
|
|
586
|
+
}
|
|
587
|
+
async function validateUserToken(userID, token) {
|
|
588
|
+
if (!checkMFAEnabled()) {
|
|
589
|
+
return false;
|
|
590
|
+
}
|
|
591
|
+
const [mfa] = await db.select().from(authMFATable).where((0, import_drizzle_orm.eq)(authMFATable.userId, userID)).limit(1);
|
|
592
|
+
if (!mfa) {
|
|
593
|
+
return false;
|
|
594
|
+
}
|
|
595
|
+
return import_otplib.authenticator.check(token, mfa.secret);
|
|
596
|
+
}
|
|
597
|
+
async function handleMFA(formData) {
|
|
598
|
+
if (!checkMFAEnabled()) {
|
|
599
|
+
return false;
|
|
600
|
+
}
|
|
601
|
+
const user = await getSessionUser();
|
|
602
|
+
if (!user) {
|
|
603
|
+
return false;
|
|
604
|
+
}
|
|
605
|
+
const isValid = await validateUserToken(user.id, formData.token);
|
|
606
|
+
if (!isValid) {
|
|
607
|
+
return false;
|
|
608
|
+
}
|
|
609
|
+
await markAsVerified(user.id);
|
|
610
|
+
return createUserSession(user.id, "AUTHED");
|
|
611
|
+
}
|
|
612
|
+
async function handleMFAForm(formData) {
|
|
613
|
+
if (!checkMFAEnabled()) {
|
|
614
|
+
return [null, new Error("MFA is not enabled")];
|
|
615
|
+
}
|
|
616
|
+
const response = await submitForm({
|
|
617
|
+
fn: handleMFA,
|
|
618
|
+
formData,
|
|
619
|
+
request: MFARequest_default
|
|
620
|
+
});
|
|
621
|
+
return response;
|
|
622
|
+
}
|
|
623
|
+
|
|
624
|
+
// src/auth/PasswordService.ts
|
|
625
|
+
var import_bcryptjs = __toESM(require("bcryptjs"));
|
|
626
|
+
var PW_SALT_ROUNDS = 12;
|
|
627
|
+
var PASSWORD_RULES = {
|
|
628
|
+
min: 8,
|
|
629
|
+
upper: 1,
|
|
630
|
+
lower: 1,
|
|
631
|
+
number: 1,
|
|
632
|
+
symbol: 1
|
|
633
|
+
};
|
|
634
|
+
function checkPasswordMin(password, value) {
|
|
635
|
+
return password.length >= value;
|
|
636
|
+
}
|
|
637
|
+
function checkPasswordUpper(password, value) {
|
|
638
|
+
return password.replace(/[^A-Z]/gu, "").length >= value;
|
|
639
|
+
}
|
|
640
|
+
function checkPasswordLower(password, value) {
|
|
641
|
+
return password.replace(/[^a-z]/gu, "").length >= value;
|
|
642
|
+
}
|
|
643
|
+
function checkPasswordNumber(password, value) {
|
|
644
|
+
return password.replace(/[^0-9]/gu, "").length >= value;
|
|
645
|
+
}
|
|
646
|
+
function checkPasswordSymbol(password, value) {
|
|
647
|
+
return password.replace(/[^$]/gu, "").length >= value;
|
|
648
|
+
}
|
|
649
|
+
var PASSWORD_FUNCTIONS = {
|
|
650
|
+
min: checkPasswordMin,
|
|
651
|
+
upper: checkPasswordUpper,
|
|
652
|
+
lower: checkPasswordLower,
|
|
653
|
+
number: checkPasswordNumber,
|
|
654
|
+
symbol: checkPasswordSymbol
|
|
655
|
+
};
|
|
656
|
+
async function hashPassword(password) {
|
|
657
|
+
const hash = await import_bcryptjs.default.hash(password, PW_SALT_ROUNDS);
|
|
658
|
+
return hash;
|
|
659
|
+
}
|
|
660
|
+
async function verifyPassword(data, encrypted) {
|
|
661
|
+
if (!data || !encrypted) {
|
|
662
|
+
return false;
|
|
663
|
+
}
|
|
664
|
+
const verified = await import_bcryptjs.default.compare(data, encrypted);
|
|
665
|
+
return verified;
|
|
666
|
+
}
|
|
667
|
+
async function getPasswordComplexity(password, rules = PASSWORD_RULES) {
|
|
668
|
+
const entries = Object.entries(rules);
|
|
669
|
+
const validity = entries.reduce((acc, [rule, value]) => {
|
|
670
|
+
acc[rule] = PASSWORD_FUNCTIONS[rule](password, value);
|
|
671
|
+
return acc;
|
|
672
|
+
}, {});
|
|
673
|
+
return Promise.resolve(validity);
|
|
674
|
+
}
|
|
675
|
+
async function checkPasswordComplexity(password, rules = PASSWORD_RULES) {
|
|
676
|
+
const validity = await getPasswordComplexity(password, rules);
|
|
677
|
+
return Promise.resolve(Object.values(validity).every(Boolean));
|
|
678
|
+
}
|
|
679
|
+
|
|
680
|
+
// src/auth/LoginRequest.ts
|
|
681
|
+
var import_joi3 = __toESM(require("joi"));
|
|
682
|
+
var LoginRequest = createSchema({
|
|
683
|
+
email: import_joi3.default.string().email({ minDomainSegments: 2, tlds: false }).required(),
|
|
684
|
+
password: import_joi3.default.string().min(8).required()
|
|
685
|
+
});
|
|
686
|
+
var LoginRequest_default = LoginRequest;
|
|
687
|
+
|
|
688
|
+
// src/auth/PasswordRequest.ts
|
|
689
|
+
var import_joi4 = __toESM(require("joi"));
|
|
690
|
+
var PasswordRequest = createSchema({
|
|
691
|
+
email: import_joi4.default.string().max(60).email({ minDomainSegments: 2, tlds: false }).required().messages({
|
|
692
|
+
"any.required": "Please provide your email address, so we can send you a reset link",
|
|
693
|
+
"string.empty": "Please provide your email address, so we can send you a reset link",
|
|
694
|
+
"string.email": "Please make sure your email address is valid",
|
|
695
|
+
"string.max": "Please make sure your email address is valid"
|
|
696
|
+
})
|
|
697
|
+
});
|
|
698
|
+
var PasswordRequest_default = PasswordRequest;
|
|
699
|
+
|
|
700
|
+
// src/auth/PasswordResetRequest.ts
|
|
701
|
+
var import_joi5 = __toESM(require("joi"));
|
|
702
|
+
var PasswordResetRequest = createSchema({
|
|
703
|
+
token: import_joi5.default.string().pattern(/[a-z0-9]{40}/u).required(),
|
|
704
|
+
password: import_joi5.default.string().required().messages({
|
|
705
|
+
"any.required": "Please provide your new password",
|
|
706
|
+
"string.empty": "Please provide your new password"
|
|
707
|
+
})
|
|
708
|
+
});
|
|
709
|
+
var PasswordResetRequest_default = PasswordResetRequest;
|
|
710
|
+
|
|
711
|
+
// src/auth/AuthService.ts
|
|
712
|
+
var RESET_TOKEN_LENGTH = 40;
|
|
713
|
+
var RESET_TOKEN_EXPIRY = 36e5;
|
|
714
|
+
async function handleLogout() {
|
|
715
|
+
const id = getSessionID();
|
|
716
|
+
if (id) {
|
|
717
|
+
await invalidateSession(id);
|
|
718
|
+
}
|
|
719
|
+
}
|
|
720
|
+
function getAllowedRoles() {
|
|
721
|
+
const roles = process.env.AUTH_ALLOWED_ROLES;
|
|
722
|
+
if (!roles) {
|
|
723
|
+
throw new Error("AUTH_ALLOWED_ROLES is not defined. Authentication will not be possible.");
|
|
724
|
+
}
|
|
725
|
+
return roles.split(",").map((role) => Number(role)).filter((role) => !isNaN(role));
|
|
726
|
+
}
|
|
727
|
+
async function handleUserSession(userID) {
|
|
728
|
+
await createUserSession(userID, checkMFAEnabled() ? "MFA" : "AUTHED");
|
|
729
|
+
const scope2 = await getScopeByID("AUTHED");
|
|
730
|
+
return scope2?.redirectOnAuth || null;
|
|
731
|
+
}
|
|
732
|
+
async function getUserByEmail(email) {
|
|
733
|
+
const [user] = await db.select().from(authUserTable).where((0, import_drizzle_orm2.and)((0, import_drizzle_orm2.eq)(authUserTable.email, email), (0, import_drizzle_orm2.inArray)(authUserTable.role, getAllowedRoles()))).limit(1);
|
|
734
|
+
return user;
|
|
735
|
+
}
|
|
736
|
+
async function loginUser({ email, password }) {
|
|
737
|
+
const user = await getUserByEmail(email);
|
|
738
|
+
if (!user?.password || !await verifyPassword(password, user.password)) {
|
|
739
|
+
throw new ValidationError_default({ email: "", password: "" });
|
|
740
|
+
}
|
|
741
|
+
const session = await handleUserSession(user.id);
|
|
742
|
+
if (!session) {
|
|
743
|
+
throw new ValidationError_default({ email: "", password: "" });
|
|
744
|
+
}
|
|
745
|
+
return session;
|
|
746
|
+
}
|
|
747
|
+
async function handleLoginForm(formData) {
|
|
748
|
+
const response = await submitForm({
|
|
749
|
+
fn: loginUser,
|
|
750
|
+
formData,
|
|
751
|
+
request: LoginRequest_default
|
|
752
|
+
});
|
|
753
|
+
return response;
|
|
754
|
+
}
|
|
755
|
+
async function registerUser({
|
|
756
|
+
email,
|
|
757
|
+
password,
|
|
758
|
+
role
|
|
759
|
+
}) {
|
|
760
|
+
const hash = password ? await hashPassword(password) : null;
|
|
761
|
+
const [user] = await db.insert(authUserTable).values({ id: generateID(), email, password: hash, role }).returning();
|
|
762
|
+
return user;
|
|
763
|
+
}
|
|
764
|
+
async function createPasswordResetToken(email) {
|
|
765
|
+
const user = await getUserByEmail(email);
|
|
766
|
+
if (!user) {
|
|
767
|
+
return null;
|
|
768
|
+
}
|
|
769
|
+
await db.delete(authResetTable).where((0, import_drizzle_orm2.eq)(authResetTable.userId, user.id));
|
|
770
|
+
const id = generateID(RESET_TOKEN_LENGTH);
|
|
771
|
+
await db.insert(authResetTable).values({
|
|
772
|
+
id,
|
|
773
|
+
userId: user.id,
|
|
774
|
+
expiresAt: new Date((/* @__PURE__ */ new Date()).getTime() + RESET_TOKEN_EXPIRY)
|
|
775
|
+
});
|
|
776
|
+
return id;
|
|
777
|
+
}
|
|
778
|
+
async function handlePasswordForm(formData, mailFn) {
|
|
779
|
+
async function mutateFn(data) {
|
|
780
|
+
const token = await createPasswordResetToken(data.email);
|
|
781
|
+
if (!token) {
|
|
782
|
+
return true;
|
|
783
|
+
}
|
|
784
|
+
return mailFn(data.email, token);
|
|
785
|
+
}
|
|
786
|
+
const response = await submitForm({
|
|
787
|
+
fn: mutateFn,
|
|
788
|
+
formData,
|
|
789
|
+
request: PasswordRequest_default
|
|
790
|
+
});
|
|
791
|
+
return response;
|
|
792
|
+
}
|
|
793
|
+
async function validatePasswordResetToken(password, token) {
|
|
794
|
+
const [result] = await db.select().from(authResetTable).where((0, import_drizzle_orm2.eq)(authResetTable.id, token)).limit(1);
|
|
795
|
+
if (!result) {
|
|
796
|
+
return null;
|
|
797
|
+
}
|
|
798
|
+
await db.delete(authResetTable).where((0, import_drizzle_orm2.eq)(authResetTable.id, token));
|
|
799
|
+
if (!result || result.expiresAt < /* @__PURE__ */ new Date()) {
|
|
800
|
+
return null;
|
|
801
|
+
}
|
|
802
|
+
await invalidateUserSessions(result.userId);
|
|
803
|
+
await db.update(authUserTable).set({ password: await hashPassword(password) }).where(
|
|
804
|
+
(0, import_drizzle_orm2.and)((0, import_drizzle_orm2.eq)(authUserTable.id, result.userId), (0, import_drizzle_orm2.inArray)(authUserTable.role, getAllowedRoles()))
|
|
805
|
+
);
|
|
806
|
+
return result.userId;
|
|
807
|
+
}
|
|
808
|
+
async function handlePasswordResetForm(formData) {
|
|
809
|
+
async function mutateFn(data) {
|
|
810
|
+
const userID = await validatePasswordResetToken(data.password, data.token);
|
|
811
|
+
if (!userID) {
|
|
812
|
+
return null;
|
|
813
|
+
}
|
|
814
|
+
return handleUserSession(userID);
|
|
815
|
+
}
|
|
816
|
+
const response = await submitForm({
|
|
817
|
+
fn: mutateFn,
|
|
818
|
+
formData,
|
|
819
|
+
request: PasswordResetRequest_default
|
|
820
|
+
});
|
|
821
|
+
return response;
|
|
822
|
+
}
|
|
823
|
+
|
|
824
|
+
// src/auth/ClientService.ts
|
|
825
|
+
var import_drizzle_orm3 = require("drizzle-orm");
|
|
826
|
+
var ID_LENGTH2 = 16;
|
|
827
|
+
var SECRET_LENGTH = 64;
|
|
828
|
+
async function getClientByID(id) {
|
|
829
|
+
const [client] = await db.select().from(authClientTable).where((0, import_drizzle_orm3.eq)(authClientTable.id, id)).limit(1);
|
|
830
|
+
return client;
|
|
831
|
+
}
|
|
832
|
+
async function registerClient({
|
|
833
|
+
alias,
|
|
834
|
+
id,
|
|
835
|
+
secret
|
|
836
|
+
}) {
|
|
837
|
+
const [client] = await db.insert(authClientTable).values({
|
|
838
|
+
alias,
|
|
839
|
+
id: id || generateID(ID_LENGTH2),
|
|
840
|
+
secret: await hashPassword(secret || generateID(SECRET_LENGTH))
|
|
841
|
+
}).returning();
|
|
842
|
+
return client;
|
|
843
|
+
}
|
|
844
|
+
async function handleClientAuth(request) {
|
|
845
|
+
const { headers: headers2 } = request;
|
|
846
|
+
const header = headers2.get("authorization");
|
|
847
|
+
if (!header) {
|
|
848
|
+
return null;
|
|
849
|
+
}
|
|
850
|
+
const auth = Buffer.from(header.replace("Basic ", ""), "base64").toString("utf-8").replace(/:$/u, "");
|
|
851
|
+
const [id, ...secret] = auth.split("-");
|
|
852
|
+
const [client] = await db.select().from(authClientTable).where((0, import_drizzle_orm3.eq)(authClientTable.id, id)).limit(1);
|
|
853
|
+
if (!client) {
|
|
854
|
+
return null;
|
|
855
|
+
}
|
|
856
|
+
const isVerified = await verifyPassword(secret.join(""), client.secret);
|
|
857
|
+
return isVerified ? client : null;
|
|
858
|
+
}
|
|
859
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
860
|
+
0 && (module.exports = {
|
|
861
|
+
checkMFAEnabled,
|
|
862
|
+
checkPasswordComplexity,
|
|
863
|
+
checkRouteAllowed,
|
|
864
|
+
checkSessionExists,
|
|
865
|
+
checkUserHasMFA,
|
|
866
|
+
createUserSession,
|
|
867
|
+
generateID,
|
|
868
|
+
generateMFA,
|
|
869
|
+
getAllowedRoles,
|
|
870
|
+
getClientByID,
|
|
871
|
+
getPasswordComplexity,
|
|
872
|
+
getScopeByID,
|
|
873
|
+
getScopes,
|
|
874
|
+
getSessionID,
|
|
875
|
+
getSessionUser,
|
|
876
|
+
handleClientAuth,
|
|
877
|
+
handleLoginForm,
|
|
878
|
+
handleLogout,
|
|
879
|
+
handleMFAForm,
|
|
880
|
+
handlePasswordForm,
|
|
881
|
+
handlePasswordResetForm,
|
|
882
|
+
handleSession,
|
|
883
|
+
hashPassword,
|
|
884
|
+
invalidateSession,
|
|
885
|
+
invalidateUserSessions,
|
|
886
|
+
lucia,
|
|
887
|
+
registerClient,
|
|
888
|
+
registerUser,
|
|
889
|
+
setScopes,
|
|
890
|
+
verifyPassword
|
|
891
|
+
});
|