speexjs 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/README.md +555 -0
- package/dist/cli/index.d.ts +1 -0
- package/dist/cli/index.js +1017 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/client/index.d.ts +73 -0
- package/dist/client/index.js +927 -0
- package/dist/client/index.js.map +1 -0
- package/dist/client/signals/index.d.ts +62 -0
- package/dist/client/signals/index.js +248 -0
- package/dist/client/signals/index.js.map +1 -0
- package/dist/client/vdom/index.d.ts +50 -0
- package/dist/client/vdom/index.js +540 -0
- package/dist/client/vdom/index.js.map +1 -0
- package/dist/client/vdom/jsx-runtime.d.ts +9 -0
- package/dist/client/vdom/jsx-runtime.js +203 -0
- package/dist/client/vdom/jsx-runtime.js.map +1 -0
- package/dist/index-CMkhSDh7.d.ts +97 -0
- package/dist/index.d.ts +18 -0
- package/dist/index.js +6402 -0
- package/dist/index.js.map +1 -0
- package/dist/jsx-DGrnv8QB.d.ts +8 -0
- package/dist/response-Ca8KWK5_.d.ts +173 -0
- package/dist/rpc/index.d.ts +70 -0
- package/dist/rpc/index.js +136 -0
- package/dist/rpc/index.js.map +1 -0
- package/dist/schema/index.d.ts +231 -0
- package/dist/schema/index.js +1160 -0
- package/dist/schema/index.js.map +1 -0
- package/dist/server/auth/index.d.ts +61 -0
- package/dist/server/auth/index.js +462 -0
- package/dist/server/auth/index.js.map +1 -0
- package/dist/server/cache/index.d.ts +45 -0
- package/dist/server/cache/index.js +238 -0
- package/dist/server/cache/index.js.map +1 -0
- package/dist/server/container/index.d.ts +20 -0
- package/dist/server/container/index.js +62 -0
- package/dist/server/container/index.js.map +1 -0
- package/dist/server/controller/index.d.ts +37 -0
- package/dist/server/controller/index.js +139 -0
- package/dist/server/controller/index.js.map +1 -0
- package/dist/server/database/index.d.ts +461 -0
- package/dist/server/database/index.js +1977 -0
- package/dist/server/database/index.js.map +1 -0
- package/dist/server/events/index.d.ts +29 -0
- package/dist/server/events/index.js +159 -0
- package/dist/server/events/index.js.map +1 -0
- package/dist/server/gate/index.d.ts +36 -0
- package/dist/server/gate/index.js +169 -0
- package/dist/server/gate/index.js.map +1 -0
- package/dist/server/http/index.d.ts +45 -0
- package/dist/server/http/index.js +871 -0
- package/dist/server/http/index.js.map +1 -0
- package/dist/server/index.d.ts +79 -0
- package/dist/server/index.js +4185 -0
- package/dist/server/index.js.map +1 -0
- package/dist/server/middleware/index.d.ts +5 -0
- package/dist/server/middleware/index.js +416 -0
- package/dist/server/middleware/index.js.map +1 -0
- package/dist/server/router/index.d.ts +5 -0
- package/dist/server/router/index.js +231 -0
- package/dist/server/router/index.js.map +1 -0
- package/dist/server/storage/index.d.ts +66 -0
- package/dist/server/storage/index.js +244 -0
- package/dist/server/storage/index.js.map +1 -0
- package/dist/session-guard-CZeN87L9.d.ts +48 -0
- package/dist/types-CXH8hPei.d.ts +38 -0
- package/package.json +138 -0
|
@@ -0,0 +1,462 @@
|
|
|
1
|
+
// src/server/http/status.ts
|
|
2
|
+
var HttpStatus = {
|
|
3
|
+
OK: 200,
|
|
4
|
+
CREATED: 201,
|
|
5
|
+
ACCEPTED: 202,
|
|
6
|
+
NO_CONTENT: 204,
|
|
7
|
+
RESET_CONTENT: 205,
|
|
8
|
+
PARTIAL_CONTENT: 206,
|
|
9
|
+
MOVED_PERMANENTLY: 301,
|
|
10
|
+
FOUND: 302,
|
|
11
|
+
SEE_OTHER: 303,
|
|
12
|
+
NOT_MODIFIED: 304,
|
|
13
|
+
TEMPORARY_REDIRECT: 307,
|
|
14
|
+
PERMANENT_REDIRECT: 308,
|
|
15
|
+
BAD_REQUEST: 400,
|
|
16
|
+
UNAUTHORIZED: 401,
|
|
17
|
+
PAYMENT_REQUIRED: 402,
|
|
18
|
+
FORBIDDEN: 403,
|
|
19
|
+
NOT_FOUND: 404,
|
|
20
|
+
METHOD_NOT_ALLOWED: 405,
|
|
21
|
+
NOT_ACCEPTABLE: 406,
|
|
22
|
+
REQUEST_TIMEOUT: 408,
|
|
23
|
+
CONFLICT: 409,
|
|
24
|
+
GONE: 410,
|
|
25
|
+
LENGTH_REQUIRED: 411,
|
|
26
|
+
PRECONDITION_FAILED: 412,
|
|
27
|
+
PAYLOAD_TOO_LARGE: 413,
|
|
28
|
+
URI_TOO_LONG: 414,
|
|
29
|
+
UNSUPPORTED_MEDIA_TYPE: 415,
|
|
30
|
+
UNPROCESSABLE_ENTITY: 422,
|
|
31
|
+
TOO_MANY_REQUESTS: 429,
|
|
32
|
+
INTERNAL_SERVER_ERROR: 500,
|
|
33
|
+
NOT_IMPLEMENTED: 501,
|
|
34
|
+
BAD_GATEWAY: 502,
|
|
35
|
+
SERVICE_UNAVAILABLE: 503,
|
|
36
|
+
GATEWAY_TIMEOUT: 504,
|
|
37
|
+
HTTP_VERSION_NOT_SUPPORTED: 505
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
// src/native/hashing.ts
|
|
41
|
+
import * as nodeCrypto2 from "crypto";
|
|
42
|
+
|
|
43
|
+
// src/native/crypto.ts
|
|
44
|
+
import * as nodeCrypto from "crypto";
|
|
45
|
+
function encrypt(data, key) {
|
|
46
|
+
const keyBuffer = Buffer.from(key, "base64");
|
|
47
|
+
if (keyBuffer.length !== 32) {
|
|
48
|
+
throw new Error("Key must be 32 bytes (256 bits) for AES-256-GCM");
|
|
49
|
+
}
|
|
50
|
+
const iv = nodeCrypto.randomBytes(16);
|
|
51
|
+
const cipher = nodeCrypto.createCipheriv("aes-256-gcm", keyBuffer, iv);
|
|
52
|
+
let encrypted = cipher.update(data, "utf8", "base64");
|
|
53
|
+
encrypted += cipher.final("base64");
|
|
54
|
+
const tag = cipher.getAuthTag().toString("base64");
|
|
55
|
+
return { encrypted, iv: iv.toString("base64"), tag };
|
|
56
|
+
}
|
|
57
|
+
function decrypt(encrypted, key) {
|
|
58
|
+
const keyBuffer = Buffer.from(key, "base64");
|
|
59
|
+
if (keyBuffer.length !== 32) {
|
|
60
|
+
throw new Error("Key must be 32 bytes (256 bits) for AES-256-GCM");
|
|
61
|
+
}
|
|
62
|
+
const decipher = nodeCrypto.createDecipheriv(
|
|
63
|
+
"aes-256-gcm",
|
|
64
|
+
keyBuffer,
|
|
65
|
+
Buffer.from(encrypted.iv, "base64")
|
|
66
|
+
);
|
|
67
|
+
decipher.setAuthTag(Buffer.from(encrypted.tag, "base64"));
|
|
68
|
+
let decrypted = decipher.update(encrypted.encrypted, "base64", "utf8");
|
|
69
|
+
decrypted += decipher.final("utf8");
|
|
70
|
+
return decrypted;
|
|
71
|
+
}
|
|
72
|
+
function hash(data, algorithm = "sha256") {
|
|
73
|
+
return nodeCrypto.createHash(algorithm).update(data, "utf8").digest("hex");
|
|
74
|
+
}
|
|
75
|
+
function constantTimeEqual(a, b) {
|
|
76
|
+
const bufA = Buffer.from(a);
|
|
77
|
+
const bufB = Buffer.from(b);
|
|
78
|
+
if (bufA.length !== bufB.length) {
|
|
79
|
+
nodeCrypto.timingSafeEqual(bufA, bufA);
|
|
80
|
+
return false;
|
|
81
|
+
}
|
|
82
|
+
return nodeCrypto.timingSafeEqual(bufA, bufB);
|
|
83
|
+
}
|
|
84
|
+
function randomHex(bytes = 32) {
|
|
85
|
+
return nodeCrypto.randomBytes(bytes).toString("hex");
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// src/native/hashing.ts
|
|
89
|
+
var SCRYPT_N = 16384;
|
|
90
|
+
var SCRYPT_R = 8;
|
|
91
|
+
var SCRYPT_P = 1;
|
|
92
|
+
var SCRYPT_KEYLEN = 64;
|
|
93
|
+
function verifyPassword(password, hash2) {
|
|
94
|
+
const parts = hash2.split("$");
|
|
95
|
+
if (parts.length !== 7 || parts[1] !== "scrypt") {
|
|
96
|
+
throw new Error("Invalid scrypt hash format");
|
|
97
|
+
}
|
|
98
|
+
const N = Number(parts[2]);
|
|
99
|
+
const r = Number(parts[3]);
|
|
100
|
+
const p = Number(parts[4]);
|
|
101
|
+
const salt = parts[5];
|
|
102
|
+
const storedHash = parts[6];
|
|
103
|
+
const derivedKey = nodeCrypto2.scryptSync(password, salt, SCRYPT_KEYLEN, {
|
|
104
|
+
N,
|
|
105
|
+
r,
|
|
106
|
+
p
|
|
107
|
+
});
|
|
108
|
+
const derivedHash = derivedKey.toString("base64");
|
|
109
|
+
return constantTimeEqual(storedHash, derivedHash);
|
|
110
|
+
}
|
|
111
|
+
var PBKDF2_ITERATIONS = 6e5;
|
|
112
|
+
var CURRENT_SCRYPT_PREFIX = `$scrypt$${SCRYPT_N}$${SCRYPT_R}$${SCRYPT_P}`;
|
|
113
|
+
var CURRENT_PBKDF2_PREFIX = `$pbkdf2$${PBKDF2_ITERATIONS}`;
|
|
114
|
+
|
|
115
|
+
// src/server/auth/session-guard.ts
|
|
116
|
+
var SessionGuard = class {
|
|
117
|
+
config;
|
|
118
|
+
req = null;
|
|
119
|
+
res = null;
|
|
120
|
+
cachedPayload = null;
|
|
121
|
+
constructor(config) {
|
|
122
|
+
this.config = {
|
|
123
|
+
cookieName: "speedx_session",
|
|
124
|
+
lifetime: 120,
|
|
125
|
+
table: "users",
|
|
126
|
+
identifier: "email",
|
|
127
|
+
password: "password",
|
|
128
|
+
provider: void 0,
|
|
129
|
+
encryptionKey: config?.encryptionKey ?? process.env.APP_KEY ?? randomHex(32),
|
|
130
|
+
...config
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
setContext(req, res) {
|
|
134
|
+
this.req = req;
|
|
135
|
+
this.res = res;
|
|
136
|
+
this.cachedPayload = null;
|
|
137
|
+
return this;
|
|
138
|
+
}
|
|
139
|
+
async attempt(credentials, remember) {
|
|
140
|
+
if (this.config.provider === void 0) return false;
|
|
141
|
+
const identifierValue = credentials[this.config.identifier];
|
|
142
|
+
if (identifierValue === void 0 || typeof identifierValue !== "string") {
|
|
143
|
+
return false;
|
|
144
|
+
}
|
|
145
|
+
const user = await this.config.provider.findByCredential(
|
|
146
|
+
this.config.identifier,
|
|
147
|
+
identifierValue
|
|
148
|
+
);
|
|
149
|
+
if (user === null) return false;
|
|
150
|
+
const hash2 = user[this.config.password];
|
|
151
|
+
if (typeof hash2 !== "string") return false;
|
|
152
|
+
if (!verifyPassword(credentials.password, hash2)) return false;
|
|
153
|
+
this.createSession(user, remember);
|
|
154
|
+
return true;
|
|
155
|
+
}
|
|
156
|
+
async login(userId, remember) {
|
|
157
|
+
if (this.config.provider !== void 0) {
|
|
158
|
+
const user = await this.config.provider.findById(userId);
|
|
159
|
+
if (user !== null) {
|
|
160
|
+
this.createSession(user, remember);
|
|
161
|
+
return;
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
const payload = {
|
|
165
|
+
userId,
|
|
166
|
+
data: {},
|
|
167
|
+
expiresAt: this.calculateExpiry(remember)
|
|
168
|
+
};
|
|
169
|
+
this.writeSessionCookie(payload);
|
|
170
|
+
}
|
|
171
|
+
async loginUser(user) {
|
|
172
|
+
const payload = {
|
|
173
|
+
userId: user.id,
|
|
174
|
+
user,
|
|
175
|
+
data: {},
|
|
176
|
+
expiresAt: this.calculateExpiry(false)
|
|
177
|
+
};
|
|
178
|
+
this.writeSessionCookie(payload);
|
|
179
|
+
}
|
|
180
|
+
async logout() {
|
|
181
|
+
if (this.res !== null) {
|
|
182
|
+
this.res.clearCookie(this.config.cookieName, { path: "/" });
|
|
183
|
+
}
|
|
184
|
+
this.cachedPayload = null;
|
|
185
|
+
}
|
|
186
|
+
async user() {
|
|
187
|
+
const payload = this.readSession();
|
|
188
|
+
if (payload === null) return null;
|
|
189
|
+
if (payload.user !== void 0) return payload.user;
|
|
190
|
+
if (this.config.provider !== void 0) {
|
|
191
|
+
const user = await this.config.provider.findById(payload.userId);
|
|
192
|
+
if (user !== null) return user;
|
|
193
|
+
}
|
|
194
|
+
return { id: payload.userId };
|
|
195
|
+
}
|
|
196
|
+
async check() {
|
|
197
|
+
return this.readSession() !== null;
|
|
198
|
+
}
|
|
199
|
+
async guest() {
|
|
200
|
+
return !await this.check();
|
|
201
|
+
}
|
|
202
|
+
async id() {
|
|
203
|
+
const payload = this.readSession();
|
|
204
|
+
return payload?.userId ?? null;
|
|
205
|
+
}
|
|
206
|
+
async set(key, value) {
|
|
207
|
+
const payload = this.readSession();
|
|
208
|
+
if (payload === null) return;
|
|
209
|
+
payload.data[key] = value;
|
|
210
|
+
this.writeSessionCookie(payload);
|
|
211
|
+
}
|
|
212
|
+
async get(key) {
|
|
213
|
+
const payload = this.readSession();
|
|
214
|
+
if (payload === null) return void 0;
|
|
215
|
+
return payload.data[key];
|
|
216
|
+
}
|
|
217
|
+
createSession(user, remember) {
|
|
218
|
+
const payload = {
|
|
219
|
+
userId: user.id,
|
|
220
|
+
user,
|
|
221
|
+
data: {},
|
|
222
|
+
expiresAt: this.calculateExpiry(remember)
|
|
223
|
+
};
|
|
224
|
+
this.writeSessionCookie(payload);
|
|
225
|
+
}
|
|
226
|
+
readSession() {
|
|
227
|
+
if (this.cachedPayload !== null) {
|
|
228
|
+
if (this.cachedPayload.expiresAt > Date.now()) {
|
|
229
|
+
return this.cachedPayload;
|
|
230
|
+
}
|
|
231
|
+
this.cachedPayload = null;
|
|
232
|
+
return null;
|
|
233
|
+
}
|
|
234
|
+
if (this.req === null) return null;
|
|
235
|
+
const cookieValue = this.req.cookie(this.config.cookieName);
|
|
236
|
+
if (cookieValue === void 0) return null;
|
|
237
|
+
try {
|
|
238
|
+
const decrypted = this.decryptSession(cookieValue);
|
|
239
|
+
const payload = JSON.parse(decrypted);
|
|
240
|
+
if (payload.expiresAt <= Date.now()) return null;
|
|
241
|
+
this.cachedPayload = payload;
|
|
242
|
+
return payload;
|
|
243
|
+
} catch {
|
|
244
|
+
return null;
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
writeSessionCookie(payload) {
|
|
248
|
+
if (this.res === null) return;
|
|
249
|
+
this.cachedPayload = payload;
|
|
250
|
+
const serialized = JSON.stringify(payload);
|
|
251
|
+
const encrypted = this.encryptSession(serialized);
|
|
252
|
+
const maxAge = Math.max(1, Math.floor((payload.expiresAt - Date.now()) / 1e3));
|
|
253
|
+
this.res.cookie(this.config.cookieName, encrypted, {
|
|
254
|
+
maxAge,
|
|
255
|
+
httpOnly: true,
|
|
256
|
+
sameSite: "lax",
|
|
257
|
+
path: "/"
|
|
258
|
+
});
|
|
259
|
+
}
|
|
260
|
+
calculateExpiry(remember) {
|
|
261
|
+
const lifetimeMs = this.config.lifetime * 60 * 1e3;
|
|
262
|
+
if (remember) {
|
|
263
|
+
const maxRemember = 5 * 365 * 24 * 60 * 60 * 1e3;
|
|
264
|
+
return Date.now() + Math.max(lifetimeMs, maxRemember);
|
|
265
|
+
}
|
|
266
|
+
return Date.now() + lifetimeMs;
|
|
267
|
+
}
|
|
268
|
+
encryptSession(data) {
|
|
269
|
+
const result = encrypt(data, this.config.encryptionKey);
|
|
270
|
+
return JSON.stringify(result);
|
|
271
|
+
}
|
|
272
|
+
decryptSession(cookie) {
|
|
273
|
+
const parsed = JSON.parse(cookie);
|
|
274
|
+
return decrypt(parsed, this.config.encryptionKey);
|
|
275
|
+
}
|
|
276
|
+
};
|
|
277
|
+
|
|
278
|
+
// src/server/auth/token-guard.ts
|
|
279
|
+
var TokenGuard = class {
|
|
280
|
+
config;
|
|
281
|
+
constructor(config) {
|
|
282
|
+
this.config = {
|
|
283
|
+
table: "personal_access_tokens",
|
|
284
|
+
tokenLength: 64,
|
|
285
|
+
hashTokens: true,
|
|
286
|
+
tokenName: "api-token",
|
|
287
|
+
provider: void 0,
|
|
288
|
+
userLookup: void 0,
|
|
289
|
+
...config
|
|
290
|
+
};
|
|
291
|
+
}
|
|
292
|
+
async createToken(userId, name, abilities) {
|
|
293
|
+
if (this.config.provider === void 0) {
|
|
294
|
+
throw new Error(
|
|
295
|
+
"TokenProvider is required to create tokens. Configure a provider in TokenGuardConfig."
|
|
296
|
+
);
|
|
297
|
+
}
|
|
298
|
+
const plaintext = randomHex(this.config.tokenLength);
|
|
299
|
+
const tokenHash = this.config.hashTokens ? hash(plaintext) : plaintext;
|
|
300
|
+
await this.config.provider.create(
|
|
301
|
+
userId,
|
|
302
|
+
tokenHash,
|
|
303
|
+
name ?? this.config.tokenName,
|
|
304
|
+
abilities
|
|
305
|
+
);
|
|
306
|
+
return plaintext;
|
|
307
|
+
}
|
|
308
|
+
async user(token) {
|
|
309
|
+
const record = await this.findTokenRecord(token);
|
|
310
|
+
if (record === null) return null;
|
|
311
|
+
if (this.config.userLookup !== void 0) {
|
|
312
|
+
return this.config.userLookup.findById(record.userId);
|
|
313
|
+
}
|
|
314
|
+
return { id: record.userId };
|
|
315
|
+
}
|
|
316
|
+
async validate(token) {
|
|
317
|
+
const record = await this.findTokenRecord(token);
|
|
318
|
+
return record !== null;
|
|
319
|
+
}
|
|
320
|
+
async abilities(token) {
|
|
321
|
+
const record = await this.findTokenRecord(token);
|
|
322
|
+
if (record === null) return [];
|
|
323
|
+
return record.abilities;
|
|
324
|
+
}
|
|
325
|
+
async can(token, ability) {
|
|
326
|
+
const record = await this.findTokenRecord(token);
|
|
327
|
+
if (record === null) return false;
|
|
328
|
+
if (record.abilities.length === 0) return true;
|
|
329
|
+
return record.abilities.includes(ability);
|
|
330
|
+
}
|
|
331
|
+
async revokeToken(token) {
|
|
332
|
+
if (this.config.provider === void 0) return;
|
|
333
|
+
const tokenHash = this.config.hashTokens ? hash(token) : token;
|
|
334
|
+
await this.config.provider.delete(tokenHash);
|
|
335
|
+
}
|
|
336
|
+
async revokeAllTokens(userId) {
|
|
337
|
+
if (this.config.provider === void 0) return;
|
|
338
|
+
await this.config.provider.deleteAllForUser(userId);
|
|
339
|
+
}
|
|
340
|
+
async findTokenRecord(token) {
|
|
341
|
+
if (this.config.provider === void 0) return null;
|
|
342
|
+
const tokenHash = this.config.hashTokens ? hash(token) : token;
|
|
343
|
+
return this.config.provider.find(tokenHash);
|
|
344
|
+
}
|
|
345
|
+
};
|
|
346
|
+
|
|
347
|
+
// src/server/auth/middleware.ts
|
|
348
|
+
function authMiddleware(guardName) {
|
|
349
|
+
return async (ctx, next) => {
|
|
350
|
+
const authManager = ctx.container.resolve("auth");
|
|
351
|
+
const guard = authManager.guard(guardName);
|
|
352
|
+
let user = null;
|
|
353
|
+
if (guard instanceof SessionGuard) {
|
|
354
|
+
guard.setContext(ctx.request, ctx.response);
|
|
355
|
+
user = await guard.user();
|
|
356
|
+
} else if (guard instanceof TokenGuard) {
|
|
357
|
+
const token = ctx.request.bearerToken();
|
|
358
|
+
if (token !== void 0) {
|
|
359
|
+
user = await guard.user(token);
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
if (user === null) {
|
|
363
|
+
const ctxAny2 = ctx;
|
|
364
|
+
ctxAny2.user = null;
|
|
365
|
+
if (ctx.request.wantsJson()) {
|
|
366
|
+
ctx.response.status(HttpStatus.UNAUTHORIZED).json({
|
|
367
|
+
error: "Unauthenticated",
|
|
368
|
+
message: "Authentication is required to access this resource"
|
|
369
|
+
});
|
|
370
|
+
return;
|
|
371
|
+
}
|
|
372
|
+
if (authManager.getLoginPath() !== void 0) {
|
|
373
|
+
ctx.response.redirect(authManager.getLoginPath(), HttpStatus.FOUND);
|
|
374
|
+
return;
|
|
375
|
+
}
|
|
376
|
+
ctx.response.status(HttpStatus.UNAUTHORIZED).json({
|
|
377
|
+
error: "Unauthenticated",
|
|
378
|
+
message: "Authentication is required to access this resource"
|
|
379
|
+
});
|
|
380
|
+
return;
|
|
381
|
+
}
|
|
382
|
+
const ctxAny = ctx;
|
|
383
|
+
ctxAny.user = user;
|
|
384
|
+
ctxAny.auth = guard;
|
|
385
|
+
await next();
|
|
386
|
+
};
|
|
387
|
+
}
|
|
388
|
+
function guestMiddleware() {
|
|
389
|
+
return async (ctx, next) => {
|
|
390
|
+
const authManager = ctx.container.resolve("auth");
|
|
391
|
+
const guard = authManager.guard();
|
|
392
|
+
let user = null;
|
|
393
|
+
if (guard instanceof SessionGuard) {
|
|
394
|
+
guard.setContext(ctx.request, ctx.response);
|
|
395
|
+
user = await guard.user();
|
|
396
|
+
}
|
|
397
|
+
if (user !== null) {
|
|
398
|
+
if (ctx.request.wantsJson()) {
|
|
399
|
+
ctx.response.status(HttpStatus.FORBIDDEN).json({
|
|
400
|
+
error: "Forbidden",
|
|
401
|
+
message: "Already authenticated"
|
|
402
|
+
});
|
|
403
|
+
return;
|
|
404
|
+
}
|
|
405
|
+
ctx.response.redirect("/", HttpStatus.FOUND);
|
|
406
|
+
return;
|
|
407
|
+
}
|
|
408
|
+
await next();
|
|
409
|
+
};
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
// src/server/auth/index.ts
|
|
413
|
+
var AuthManager = class {
|
|
414
|
+
guards = /* @__PURE__ */ new Map();
|
|
415
|
+
defaultGuardName = "web";
|
|
416
|
+
loginPath = "/login";
|
|
417
|
+
guard(name, guardInstance) {
|
|
418
|
+
if (guardInstance !== void 0) {
|
|
419
|
+
this.guards.set(name, guardInstance);
|
|
420
|
+
return this;
|
|
421
|
+
}
|
|
422
|
+
const guardName = name ?? this.defaultGuardName;
|
|
423
|
+
const found = this.guards.get(guardName);
|
|
424
|
+
if (found === void 0) {
|
|
425
|
+
throw new Error(`Auth guard "${guardName}" not registered. Call authManager.guard("${guardName}", guard) first.`);
|
|
426
|
+
}
|
|
427
|
+
return found;
|
|
428
|
+
}
|
|
429
|
+
defaultGuard(name) {
|
|
430
|
+
this.defaultGuardName = name;
|
|
431
|
+
return this;
|
|
432
|
+
}
|
|
433
|
+
setLoginPath(path) {
|
|
434
|
+
this.loginPath = path;
|
|
435
|
+
return this;
|
|
436
|
+
}
|
|
437
|
+
getLoginPath() {
|
|
438
|
+
return this.loginPath;
|
|
439
|
+
}
|
|
440
|
+
hasGuard(name) {
|
|
441
|
+
return this.guards.has(name);
|
|
442
|
+
}
|
|
443
|
+
removeGuard(name) {
|
|
444
|
+
this.guards.delete(name);
|
|
445
|
+
return this;
|
|
446
|
+
}
|
|
447
|
+
getGuardNames() {
|
|
448
|
+
return Array.from(this.guards.keys());
|
|
449
|
+
}
|
|
450
|
+
};
|
|
451
|
+
function auth(guardName) {
|
|
452
|
+
return authMiddleware(guardName);
|
|
453
|
+
}
|
|
454
|
+
export {
|
|
455
|
+
AuthManager,
|
|
456
|
+
SessionGuard,
|
|
457
|
+
TokenGuard,
|
|
458
|
+
auth,
|
|
459
|
+
authMiddleware,
|
|
460
|
+
guestMiddleware
|
|
461
|
+
};
|
|
462
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/server/http/status.ts","../../../src/native/hashing.ts","../../../src/native/crypto.ts","../../../src/server/auth/session-guard.ts","../../../src/server/auth/token-guard.ts","../../../src/server/auth/middleware.ts","../../../src/server/auth/index.ts"],"sourcesContent":["export const HttpStatus = {\n OK: 200,\n CREATED: 201,\n ACCEPTED: 202,\n NO_CONTENT: 204,\n RESET_CONTENT: 205,\n PARTIAL_CONTENT: 206,\n\n MOVED_PERMANENTLY: 301,\n FOUND: 302,\n SEE_OTHER: 303,\n NOT_MODIFIED: 304,\n TEMPORARY_REDIRECT: 307,\n PERMANENT_REDIRECT: 308,\n\n BAD_REQUEST: 400,\n UNAUTHORIZED: 401,\n PAYMENT_REQUIRED: 402,\n FORBIDDEN: 403,\n NOT_FOUND: 404,\n METHOD_NOT_ALLOWED: 405,\n NOT_ACCEPTABLE: 406,\n REQUEST_TIMEOUT: 408,\n CONFLICT: 409,\n GONE: 410,\n LENGTH_REQUIRED: 411,\n PRECONDITION_FAILED: 412,\n PAYLOAD_TOO_LARGE: 413,\n URI_TOO_LONG: 414,\n UNSUPPORTED_MEDIA_TYPE: 415,\n UNPROCESSABLE_ENTITY: 422,\n TOO_MANY_REQUESTS: 429,\n\n INTERNAL_SERVER_ERROR: 500,\n NOT_IMPLEMENTED: 501,\n BAD_GATEWAY: 502,\n SERVICE_UNAVAILABLE: 503,\n GATEWAY_TIMEOUT: 504,\n HTTP_VERSION_NOT_SUPPORTED: 505,\n} as const\n\nexport type HttpStatusCode = (typeof HttpStatus)[keyof typeof HttpStatus]\n\nconst statusTextMap: Record<number, string> = {\n 200: 'OK',\n 201: 'Created',\n 202: 'Accepted',\n 204: 'No Content',\n 205: 'Reset Content',\n 206: 'Partial Content',\n 301: 'Moved Permanently',\n 302: 'Found',\n 303: 'See Other',\n 304: 'Not Modified',\n 307: 'Temporary Redirect',\n 308: 'Permanent Redirect',\n 400: 'Bad Request',\n 401: 'Unauthorized',\n 402: 'Payment Required',\n 403: 'Forbidden',\n 404: 'Not Found',\n 405: 'Method Not Allowed',\n 406: 'Not Acceptable',\n 408: 'Request Timeout',\n 409: 'Conflict',\n 410: 'Gone',\n 411: 'Length Required',\n 412: 'Precondition Failed',\n 413: 'Payload Too Large',\n 414: 'URI Too Long',\n 415: 'Unsupported Media Type',\n 422: 'Unprocessable Entity',\n 429: 'Too Many Requests',\n 500: 'Internal Server Error',\n 501: 'Not Implemented',\n 502: 'Bad Gateway',\n 503: 'Service Unavailable',\n 504: 'Gateway Timeout',\n 505: 'HTTP Version Not Supported',\n}\n\nexport function statusText(code: number): string {\n const text = statusTextMap[code]\n if (text !== undefined) return text\n if (code >= 100 && code < 200) return 'Informational'\n if (code >= 200 && code < 300) return 'Success'\n if (code >= 300 && code < 400) return 'Redirection'\n if (code >= 400 && code < 500) return 'Client Error'\n if (code >= 500 && code < 600) return 'Server Error'\n return 'Unknown'\n}\n","import * as nodeCrypto from 'crypto'\nimport { constantTimeEqual } from './crypto.js'\n\n// ─── Scrypt (OWASP recommended) ──────────────────────────\n\nconst SCRYPT_N = 16384\nconst SCRYPT_R = 8\nconst SCRYPT_P = 1\nconst SCRYPT_KEYLEN = 64\nconst SCRYPT_SALT_BYTES = 32\n\nexport function hashPassword(password: string): string {\n const salt = nodeCrypto.randomBytes(SCRYPT_SALT_BYTES).toString('base64')\n const derivedKey = nodeCrypto.scryptSync(password, salt, SCRYPT_KEYLEN, {\n N: SCRYPT_N,\n r: SCRYPT_R,\n p: SCRYPT_P,\n })\n return `$scrypt$${SCRYPT_N}$${SCRYPT_R}$${SCRYPT_P}$${salt}$${derivedKey.toString('base64')}`\n}\n\nexport function verifyPassword(password: string, hash: string): boolean {\n const parts = hash.split('$')\n if (parts.length !== 7 || parts[1] !== 'scrypt') {\n throw new Error('Invalid scrypt hash format')\n }\n const N = Number(parts[2])\n const r = Number(parts[3])\n const p = Number(parts[4])\n const salt = parts[5]!\n const storedHash = parts[6]!\n const derivedKey = nodeCrypto.scryptSync(password, salt, SCRYPT_KEYLEN, {\n N,\n r,\n p,\n })\n const derivedHash = derivedKey.toString('base64')\n return constantTimeEqual(storedHash, derivedHash)\n}\n\n// ─── PBKDF2 (faster, for non-critical use) ──────────────\n\nconst PBKDF2_ITERATIONS = 600000\nconst PBKDF2_KEYLEN = 64\nconst PBKDF2_SALT_BYTES = 32\n\nexport function hashPasswordFast(password: string): string {\n const salt = nodeCrypto.randomBytes(PBKDF2_SALT_BYTES).toString('base64')\n const derivedKey = nodeCrypto.pbkdf2Sync(\n password,\n salt,\n PBKDF2_ITERATIONS,\n PBKDF2_KEYLEN,\n 'sha512',\n )\n return `$pbkdf2$${PBKDF2_ITERATIONS}$${salt}$${derivedKey.toString('base64')}`\n}\n\nexport function verifyPasswordFast(password: string, hash: string): boolean {\n const parts = hash.split('$')\n if (parts.length !== 5 || parts[1] !== 'pbkdf2') {\n throw new Error('Invalid pbkdf2 hash format')\n }\n const iterations = Number(parts[2])\n const salt = parts[3]!\n const storedHash = parts[4]!\n const derivedKey = nodeCrypto.pbkdf2Sync(\n password,\n salt,\n iterations,\n PBKDF2_KEYLEN,\n 'sha512',\n )\n const derivedHash = derivedKey.toString('base64')\n return constantTimeEqual(storedHash, derivedHash)\n}\n\n// ─── Rehash Detection ────────────────────────────────────\n\nconst CURRENT_SCRYPT_PREFIX = `$scrypt$${SCRYPT_N}$${SCRYPT_R}$${SCRYPT_P}`\nconst CURRENT_PBKDF2_PREFIX = `$pbkdf2$${PBKDF2_ITERATIONS}`\n\nexport function needsRehash(hash: string): boolean {\n if (hash.startsWith('$scrypt$')) {\n const prefix = hash.split('$').slice(0, 5).join('$')\n return prefix !== CURRENT_SCRYPT_PREFIX\n }\n if (hash.startsWith('$pbkdf2$')) {\n const prefix = hash.split('$').slice(0, 3).join('$')\n return prefix !== CURRENT_PBKDF2_PREFIX\n }\n return true\n}\n","import * as nodeCrypto from 'crypto'\n\n// ─── Encryption (AES-256-GCM) ──────────────────────────\n\nexport interface EncryptedData {\n encrypted: string\n iv: string\n tag: string\n}\n\nexport function encrypt(data: string, key: string): EncryptedData {\n const keyBuffer = Buffer.from(key, 'base64')\n if (keyBuffer.length !== 32) {\n throw new Error('Key must be 32 bytes (256 bits) for AES-256-GCM')\n }\n const iv = nodeCrypto.randomBytes(16)\n const cipher = nodeCrypto.createCipheriv('aes-256-gcm', keyBuffer, iv)\n let encrypted = cipher.update(data, 'utf8', 'base64')\n encrypted += cipher.final('base64')\n const tag = cipher.getAuthTag().toString('base64')\n return { encrypted, iv: iv.toString('base64'), tag }\n}\n\nexport function decrypt(encrypted: EncryptedData, key: string): string {\n const keyBuffer = Buffer.from(key, 'base64')\n if (keyBuffer.length !== 32) {\n throw new Error('Key must be 32 bytes (256 bits) for AES-256-GCM')\n }\n const decipher = nodeCrypto.createDecipheriv(\n 'aes-256-gcm',\n keyBuffer,\n Buffer.from(encrypted.iv, 'base64'),\n )\n decipher.setAuthTag(Buffer.from(encrypted.tag, 'base64'))\n let decrypted = decipher.update(encrypted.encrypted, 'base64', 'utf8')\n decrypted += decipher.final('utf8')\n return decrypted\n}\n\n// ─── Hashing ────────────────────────────────────────────\n\nexport function hash(\n data: string,\n algorithm: 'sha256' | 'sha384' | 'sha512' = 'sha256',\n): string {\n return nodeCrypto.createHash(algorithm).update(data, 'utf8').digest('hex')\n}\n\nexport function hmac(\n data: string,\n secret: string,\n algorithm: 'sha256' | 'sha384' = 'sha256',\n): string {\n return nodeCrypto\n .createHmac(algorithm, secret)\n .update(data, 'utf8')\n .digest('hex')\n}\n\nexport function constantTimeEqual(a: string, b: string): boolean {\n const bufA = Buffer.from(a)\n const bufB = Buffer.from(b)\n if (bufA.length !== bufB.length) {\n nodeCrypto.timingSafeEqual(bufA, bufA)\n return false\n }\n return nodeCrypto.timingSafeEqual(bufA, bufB)\n}\n\n// ─── Random ─────────────────────────────────────────────\n\nexport function randomHex(bytes: number = 32): string {\n return nodeCrypto.randomBytes(bytes).toString('hex')\n}\n\nexport function generateToken(bytes: number = 48): string {\n return nodeCrypto.randomBytes(bytes).toString('base64url')\n}\n\nexport function generateOTP(length: number = 6): string {\n const bytes = nodeCrypto.randomBytes(Math.ceil(length * 0.5))\n let otp = ''\n for (const b of bytes) {\n otp += (b % 10).toString()\n if (otp.length >= length) break\n }\n return otp\n}\n\nexport function uuid(): string {\n return nodeCrypto.randomUUID()\n}\n\n// ─── Encoding ───────────────────────────────────────────\n\nexport function base64Encode(data: string): string {\n return Buffer.from(data, 'utf8').toString('base64')\n}\n\nexport function base64Decode(data: string): string {\n return Buffer.from(data, 'base64').toString('utf8')\n}\n\nexport function checksum(data: string): string {\n return nodeCrypto\n .createHash('sha256')\n .update(data, 'utf8')\n .digest('base64')\n .slice(0, 8)\n}\n\n// ─── Key Generation ────────────────────────────────────\n\nexport function generateEncryptionKey(): string {\n return nodeCrypto.randomBytes(32).toString('base64')\n}\n\nexport function deriveKey(\n password: string,\n salt?: string,\n iterations: number = 600000,\n): { key: string; salt: string } {\n const actualSalt = salt ?? nodeCrypto.randomBytes(32).toString('hex')\n const derivedKey = nodeCrypto.pbkdf2Sync(\n password,\n actualSalt,\n iterations,\n 32,\n 'sha512',\n )\n return { key: derivedKey.toString('base64'), salt: actualSalt }\n}\n","import type { SuperRequest } from '../http/request.js'\nimport type { SuperResponse } from '../http/response.js'\nimport { verifyPassword } from '../../native/hashing.js'\nimport { encrypt, decrypt, randomHex } from '../../native/crypto.js'\n\nexport interface AuthUser {\n id: string | number\n [key: string]: unknown\n}\n\nexport interface UserProvider {\n findById(id: string | number): Promise<AuthUser | null>\n findByCredential(field: string, value: string): Promise<AuthUser | null>\n}\n\nexport interface SessionGuardConfig {\n cookieName?: string\n lifetime?: number\n table?: string\n identifier?: string\n password?: string\n provider?: UserProvider\n encryptionKey?: string\n}\n\ninterface SessionPayload {\n userId: string | number\n user?: AuthUser\n data: Record<string, unknown>\n expiresAt: number\n}\n\nexport class SessionGuard {\n private config: Required<\n Omit<SessionGuardConfig, 'provider' | 'encryptionKey'>\n > & { provider: UserProvider | undefined; encryptionKey: string }\n private req: SuperRequest | null = null\n private res: SuperResponse | null = null\n private cachedPayload: SessionPayload | null = null\n\n constructor(config?: SessionGuardConfig) {\n this.config = {\n cookieName: 'speedx_session',\n lifetime: 120,\n table: 'users',\n identifier: 'email',\n password: 'password',\n provider: undefined,\n encryptionKey: config?.encryptionKey ?? process.env.APP_KEY ?? randomHex(32),\n ...config,\n }\n }\n\n setContext(req: SuperRequest, res: SuperResponse): this {\n this.req = req\n this.res = res\n this.cachedPayload = null\n return this\n }\n\n async attempt(\n credentials: { email: string; password: string },\n remember?: boolean,\n ): Promise<boolean> {\n if (this.config.provider === undefined) return false\n\n const identifierValue =\n credentials[this.config.identifier as keyof typeof credentials]\n if (identifierValue === undefined || typeof identifierValue !== 'string') {\n return false\n }\n\n const user = await this.config.provider.findByCredential(\n this.config.identifier,\n identifierValue,\n )\n if (user === null) return false\n\n const hash = user[this.config.password]\n if (typeof hash !== 'string') return false\n\n if (!verifyPassword(credentials.password, hash)) return false\n\n this.createSession(user, remember)\n return true\n }\n\n async login(userId: string | number, remember?: boolean): Promise<void> {\n if (this.config.provider !== undefined) {\n const user = await this.config.provider.findById(userId)\n if (user !== null) {\n this.createSession(user, remember)\n return\n }\n }\n\n const payload: SessionPayload = {\n userId,\n data: {},\n expiresAt: this.calculateExpiry(remember),\n }\n this.writeSessionCookie(payload)\n }\n\n async loginUser(user: AuthUser): Promise<void> {\n const payload: SessionPayload = {\n userId: user.id,\n user,\n data: {},\n expiresAt: this.calculateExpiry(false),\n }\n this.writeSessionCookie(payload)\n }\n\n async logout(): Promise<void> {\n if (this.res !== null) {\n this.res.clearCookie(this.config.cookieName, { path: '/' })\n }\n this.cachedPayload = null\n }\n\n async user(): Promise<AuthUser | null> {\n const payload = this.readSession()\n if (payload === null) return null\n\n if (payload.user !== undefined) return payload.user\n\n if (this.config.provider !== undefined) {\n const user = await this.config.provider.findById(payload.userId)\n if (user !== null) return user\n }\n\n return { id: payload.userId }\n }\n\n async check(): Promise<boolean> {\n return this.readSession() !== null\n }\n\n async guest(): Promise<boolean> {\n return !(await this.check())\n }\n\n async id(): Promise<string | number | null> {\n const payload = this.readSession()\n return payload?.userId ?? null\n }\n\n async set(key: string, value: unknown): Promise<void> {\n const payload = this.readSession()\n if (payload === null) return\n payload.data[key] = value\n this.writeSessionCookie(payload)\n }\n\n async get(key: string): Promise<unknown> {\n const payload = this.readSession()\n if (payload === null) return undefined\n return payload.data[key]\n }\n\n private createSession(user: AuthUser, remember?: boolean): void {\n const payload: SessionPayload = {\n userId: user.id,\n user,\n data: {},\n expiresAt: this.calculateExpiry(remember),\n }\n this.writeSessionCookie(payload)\n }\n\n private readSession(): SessionPayload | null {\n if (this.cachedPayload !== null) {\n if (this.cachedPayload.expiresAt > Date.now()) {\n return this.cachedPayload\n }\n this.cachedPayload = null\n return null\n }\n\n if (this.req === null) return null\n\n const cookieValue = this.req.cookie(this.config.cookieName)\n if (cookieValue === undefined) return null\n\n try {\n const decrypted = this.decryptSession(cookieValue)\n const payload = JSON.parse(decrypted) as SessionPayload\n if (payload.expiresAt <= Date.now()) return null\n this.cachedPayload = payload\n return payload\n } catch {\n return null\n }\n }\n\n private writeSessionCookie(payload: SessionPayload): void {\n if (this.res === null) return\n this.cachedPayload = payload\n const serialized = JSON.stringify(payload)\n const encrypted = this.encryptSession(serialized)\n const maxAge = Math.max(1, Math.floor((payload.expiresAt - Date.now()) / 1000))\n this.res.cookie(this.config.cookieName, encrypted, {\n maxAge,\n httpOnly: true,\n sameSite: 'lax',\n path: '/',\n })\n }\n\n private calculateExpiry(remember?: boolean): number {\n const lifetimeMs = this.config.lifetime * 60 * 1000\n if (remember) {\n const maxRemember = 5 * 365 * 24 * 60 * 60 * 1000\n return Date.now() + Math.max(lifetimeMs, maxRemember)\n }\n return Date.now() + lifetimeMs\n }\n\n private encryptSession(data: string): string {\n const result = encrypt(data, this.config.encryptionKey)\n return JSON.stringify(result)\n }\n\n private decryptSession(cookie: string): string {\n const parsed = JSON.parse(cookie)\n return decrypt(parsed, this.config.encryptionKey)\n }\n}\n","import type { AuthUser } from './session-guard.js'\nimport { hash, randomHex } from '../../native/crypto.js'\n\nexport interface TokenProvider {\n create(\n userId: string | number,\n tokenHash: string,\n name?: string,\n abilities?: string[],\n ): Promise<void>\n find(\n tokenHash: string,\n ): Promise<{\n userId: string | number\n abilities: string[]\n } | null>\n delete(tokenHash: string): Promise<void>\n deleteAllForUser(userId: string | number): Promise<void>\n}\n\nexport interface UserLookup {\n findById(id: string | number): Promise<AuthUser | null>\n}\n\nexport interface TokenGuardConfig {\n table?: string\n tokenLength?: number\n hashTokens?: boolean\n tokenName?: string\n provider?: TokenProvider\n userLookup?: UserLookup\n}\n\ninterface TokenRecord {\n userId: string | number\n abilities: string[]\n}\n\nexport class TokenGuard {\n private config: Required<\n Omit<TokenGuardConfig, 'provider' | 'userLookup'>\n > & { provider: TokenProvider | undefined; userLookup: UserLookup | undefined }\n\n constructor(config?: TokenGuardConfig) {\n this.config = {\n table: 'personal_access_tokens',\n tokenLength: 64,\n hashTokens: true,\n tokenName: 'api-token',\n provider: undefined,\n userLookup: undefined,\n ...config,\n }\n }\n\n async createToken(\n userId: string | number,\n name?: string,\n abilities?: string[],\n ): Promise<string> {\n if (this.config.provider === undefined) {\n throw new Error(\n 'TokenProvider is required to create tokens. Configure a provider in TokenGuardConfig.',\n )\n }\n\n const plaintext = randomHex(this.config.tokenLength)\n const tokenHash = this.config.hashTokens\n ? hash(plaintext)\n : plaintext\n await this.config.provider.create(\n userId,\n tokenHash,\n name ?? this.config.tokenName,\n abilities,\n )\n return plaintext\n }\n\n async user(token: string): Promise<AuthUser | null> {\n const record = await this.findTokenRecord(token)\n if (record === null) return null\n\n if (this.config.userLookup !== undefined) {\n return this.config.userLookup.findById(record.userId)\n }\n\n return { id: record.userId }\n }\n\n async validate(token: string): Promise<boolean> {\n const record = await this.findTokenRecord(token)\n return record !== null\n }\n\n async abilities(token: string): Promise<string[]> {\n const record = await this.findTokenRecord(token)\n if (record === null) return []\n return record.abilities\n }\n\n async can(token: string, ability: string): Promise<boolean> {\n const record = await this.findTokenRecord(token)\n if (record === null) return false\n if (record.abilities.length === 0) return true\n return record.abilities.includes(ability)\n }\n\n async revokeToken(token: string): Promise<void> {\n if (this.config.provider === undefined) return\n const tokenHash = this.config.hashTokens ? hash(token) : token\n await this.config.provider.delete(tokenHash)\n }\n\n async revokeAllTokens(userId: string | number): Promise<void> {\n if (this.config.provider === undefined) return\n await this.config.provider.deleteAllForUser(userId)\n }\n\n private async findTokenRecord(\n token: string,\n ): Promise<TokenRecord | null> {\n if (this.config.provider === undefined) return null\n const tokenHash = this.config.hashTokens ? hash(token) : token\n return this.config.provider.find(tokenHash)\n }\n}\n","import type { Middleware } from '../middleware/index.js'\nimport { HttpStatus } from '../http/status.js'\nimport type { AuthManager } from './index.js'\nimport { SessionGuard } from './session-guard.js'\nimport { TokenGuard } from './token-guard.js'\n\nexport function authMiddleware(guardName?: string): Middleware {\n return async (ctx, next) => {\n const authManager = ctx.container.resolve('auth') as AuthManager\n const guard = authManager.guard(guardName)\n\n let user = null\n\n if (guard instanceof SessionGuard) {\n guard.setContext(ctx.request, ctx.response)\n user = await guard.user()\n } else if (guard instanceof TokenGuard) {\n const token = ctx.request.bearerToken()\n if (token !== undefined) {\n user = await guard.user(token)\n }\n }\n\n if (user === null) {\n const ctxAny = ctx as unknown as Record<string, unknown>\n ctxAny.user = null\n\n if (ctx.request.wantsJson()) {\n ctx.response.status(HttpStatus.UNAUTHORIZED).json({\n error: 'Unauthenticated',\n message: 'Authentication is required to access this resource',\n })\n return\n }\n\n if (authManager.getLoginPath() !== undefined) {\n ctx.response.redirect(authManager.getLoginPath()!, HttpStatus.FOUND)\n return\n }\n\n ctx.response.status(HttpStatus.UNAUTHORIZED).json({\n error: 'Unauthenticated',\n message: 'Authentication is required to access this resource',\n })\n return\n }\n\n const ctxAny = ctx as unknown as Record<string, unknown>\n ctxAny.user = user\n ctxAny.auth = guard\n\n await next()\n }\n}\n\nexport function guestMiddleware(): Middleware {\n return async (ctx, next) => {\n const authManager = ctx.container.resolve('auth') as AuthManager\n const guard = authManager.guard()\n\n let user = null\n\n if (guard instanceof SessionGuard) {\n guard.setContext(ctx.request, ctx.response)\n user = await guard.user()\n }\n\n if (user !== null) {\n if (ctx.request.wantsJson()) {\n ctx.response.status(HttpStatus.FORBIDDEN).json({\n error: 'Forbidden',\n message: 'Already authenticated',\n })\n return\n }\n\n ctx.response.redirect('/', HttpStatus.FOUND)\n return\n }\n\n await next()\n }\n}\n","import { SessionGuard } from './session-guard.js'\nimport { TokenGuard } from './token-guard.js'\nimport { authMiddleware } from './middleware.js'\nimport type { Middleware } from '../middleware/index.js'\n\nexport type Guard = SessionGuard | TokenGuard\n\nexport class AuthManager {\n private guards = new Map<string, Guard>()\n private defaultGuardName = 'web'\n private loginPath: string | undefined = '/login'\n\n guard(name: string, guardInstance: Guard): this\n guard(name?: string): Guard\n guard(name?: string, guardInstance?: Guard): this | Guard {\n if (guardInstance !== undefined) {\n this.guards.set(name!, guardInstance)\n return this\n }\n\n const guardName = name ?? this.defaultGuardName\n const found = this.guards.get(guardName)\n if (found === undefined) {\n throw new Error(`Auth guard \"${guardName}\" not registered. Call authManager.guard(\"${guardName}\", guard) first.`)\n }\n return found\n }\n\n defaultGuard(name: string): this {\n this.defaultGuardName = name\n return this\n }\n\n setLoginPath(path: string | undefined): this {\n this.loginPath = path\n return this\n }\n\n getLoginPath(): string | undefined {\n return this.loginPath\n }\n\n hasGuard(name: string): boolean {\n return this.guards.has(name)\n }\n\n removeGuard(name: string): this {\n this.guards.delete(name)\n return this\n }\n\n getGuardNames(): string[] {\n return Array.from(this.guards.keys())\n }\n}\n\nexport function auth(guardName?: string): Middleware {\n return authMiddleware(guardName)\n}\n\nexport { SessionGuard } from './session-guard.js'\nexport type { AuthUser, UserProvider, SessionGuardConfig } from './session-guard.js'\nexport { TokenGuard } from './token-guard.js'\nexport type { TokenProvider, TokenGuardConfig } from './token-guard.js'\nexport { authMiddleware, guestMiddleware } from './middleware.js'\n"],"mappings":"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","names":["nodeCrypto","hash","hash","ctxAny"]}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { M as Middleware } from '../../index-CMkhSDh7.js';
|
|
2
|
+
import '../container/index.js';
|
|
3
|
+
import '../../response-Ca8KWK5_.js';
|
|
4
|
+
import 'node:http';
|
|
5
|
+
import 'node:stream';
|
|
6
|
+
|
|
7
|
+
interface CacheConfig {
|
|
8
|
+
store?: "memory" | "file";
|
|
9
|
+
path?: string;
|
|
10
|
+
ttl?: number;
|
|
11
|
+
prefix?: string;
|
|
12
|
+
}
|
|
13
|
+
declare class Cache {
|
|
14
|
+
private store;
|
|
15
|
+
private config;
|
|
16
|
+
private hits;
|
|
17
|
+
private misses;
|
|
18
|
+
constructor(config?: CacheConfig);
|
|
19
|
+
get<T>(key: string): Promise<T | null>;
|
|
20
|
+
remember<T>(key: string, ttl: number | undefined, callback: () => Promise<T>): Promise<T>;
|
|
21
|
+
set(key: string, value: unknown, ttl?: number): Promise<void>;
|
|
22
|
+
add(key: string, value: unknown, ttl?: number): Promise<boolean>;
|
|
23
|
+
delete(key: string): Promise<boolean>;
|
|
24
|
+
clear(): Promise<void>;
|
|
25
|
+
has(key: string): Promise<boolean>;
|
|
26
|
+
getMultiple(keys: string[]): Promise<Record<string, unknown>>;
|
|
27
|
+
setMultiple(items: Record<string, unknown>, ttl?: number): Promise<void>;
|
|
28
|
+
increment(key: string, value?: number): Promise<number>;
|
|
29
|
+
decrement(key: string, value?: number): Promise<number>;
|
|
30
|
+
forever(key: string, value: unknown): Promise<void>;
|
|
31
|
+
stats(): {
|
|
32
|
+
hits: number;
|
|
33
|
+
misses: number;
|
|
34
|
+
keys: number;
|
|
35
|
+
size: string;
|
|
36
|
+
};
|
|
37
|
+
private getFilePath;
|
|
38
|
+
private isExpired;
|
|
39
|
+
private fileGet;
|
|
40
|
+
private fileSet;
|
|
41
|
+
private fileDelete;
|
|
42
|
+
}
|
|
43
|
+
declare function cacheResponse(ttl?: number): Middleware;
|
|
44
|
+
|
|
45
|
+
export { Cache, type CacheConfig, cacheResponse };
|