@fonderie/auth 7.7.4 → 7.8.1
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/brain/outcomes.md +7 -0
- package/brain/signatures.md +11 -0
- package/dist/index.cjs +126 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +15 -4
- package/dist/index.d.ts +15 -4
- package/dist/index.js +124 -0
- package/dist/index.js.map +1 -1
- package/dist/middlewares/index.cjs +9 -0
- package/dist/middlewares/index.cjs.map +1 -1
- package/dist/middlewares/index.js +9 -0
- package/dist/middlewares/index.js.map +1 -1
- package/package.json +5 -5
package/dist/index.d.cts
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
import { IUser } from './types.cjs';
|
|
2
|
+
export { IMfaChallenge, ISession } from './types.cjs';
|
|
3
|
+
import { IFonderieModule, IAdminDescription, IReadinessProblem, IFonderieApp, IAdminRoute } from '@fonderie/core';
|
|
3
4
|
import { IStoreAdapter } from '@fonderie/store';
|
|
4
5
|
import { EventBus } from '@fonderie/events';
|
|
5
6
|
import { I as IAuthConfig } from './session-Bv4qu9xV.cjs';
|
|
6
7
|
export { A as AUTH_CONFIG_KEYS, a as AuthLimitedRoute, b as AuthMessageKey, c as IAuthRateLimitConfig, d as IAuthRuntimeConfig, e as IAuthSecrets, f as IDataExportContributor, M as MESSAGE_KEYS, g as buildAuthAccountLimiter, h as buildAuthIpLimiter, w as withSession } from './session-Bv4qu9xV.cjs';
|
|
7
|
-
|
|
8
|
+
import { IUserDTO } from './dtos/user.cjs';
|
|
9
|
+
export { toUserDTO } from './dtos/user.cjs';
|
|
8
10
|
export { requireAuth, validate } from '@fonderie/core/middlewares';
|
|
9
11
|
import { z } from 'zod';
|
|
10
12
|
import '@fonderie/rate-limit';
|
|
@@ -15,6 +17,7 @@ declare class AuthModule implements IFonderieModule {
|
|
|
15
17
|
private bus?;
|
|
16
18
|
readonly name = "@fonderie/auth";
|
|
17
19
|
constructor(store: IStoreAdapter, config: IAuthConfig, bus?: EventBus | undefined);
|
|
20
|
+
describeAdmin(): IAdminDescription;
|
|
18
21
|
checkReadiness(): IReadinessProblem[];
|
|
19
22
|
install(app: IFonderieApp): void;
|
|
20
23
|
}
|
|
@@ -233,4 +236,12 @@ declare function startUserRetention(store: IStoreAdapter, options: IUserRetentio
|
|
|
233
236
|
|
|
234
237
|
declare function validateAuthConfig(config: IAuthConfig): void;
|
|
235
238
|
|
|
236
|
-
|
|
239
|
+
interface IAdminUserDTO extends IUserDTO {
|
|
240
|
+
suspended: boolean;
|
|
241
|
+
deletedAt: string | null;
|
|
242
|
+
createdAt: string;
|
|
243
|
+
}
|
|
244
|
+
declare function toAdminUserDTO(user: IUser): IAdminUserDTO;
|
|
245
|
+
declare function describeAuthAdminRoutes(store: IStoreAdapter): IAdminRoute[];
|
|
246
|
+
|
|
247
|
+
export { AuthModule, type ChangePasswordInput, DEFAULT_TEMPLATES, type IAdminUserDTO, IAuthConfig, type IImportUser, type ILoginEventDTO, type ILoginHistoryPageDTO, type IPurgeOptions, type ISessionDTO, IUser, IUserDTO, type IUserRetentionScheduleOptions, type LoginInput, type RegisterInput, type ResetPasswordInput, describeAuthAdminRoutes, importUser, normalizeEmail, normalizeEmailSafe, purgeSoftDeletedUsers, schemas, startUserRetention, toAdminUserDTO, validateAuthConfig };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
import { IUser } from './types.js';
|
|
2
|
+
export { IMfaChallenge, ISession } from './types.js';
|
|
3
|
+
import { IFonderieModule, IAdminDescription, IReadinessProblem, IFonderieApp, IAdminRoute } from '@fonderie/core';
|
|
3
4
|
import { IStoreAdapter } from '@fonderie/store';
|
|
4
5
|
import { EventBus } from '@fonderie/events';
|
|
5
6
|
import { I as IAuthConfig } from './session-Bv4qu9xV.js';
|
|
6
7
|
export { A as AUTH_CONFIG_KEYS, a as AuthLimitedRoute, b as AuthMessageKey, c as IAuthRateLimitConfig, d as IAuthRuntimeConfig, e as IAuthSecrets, f as IDataExportContributor, M as MESSAGE_KEYS, g as buildAuthAccountLimiter, h as buildAuthIpLimiter, w as withSession } from './session-Bv4qu9xV.js';
|
|
7
|
-
|
|
8
|
+
import { IUserDTO } from './dtos/user.js';
|
|
9
|
+
export { toUserDTO } from './dtos/user.js';
|
|
8
10
|
export { requireAuth, validate } from '@fonderie/core/middlewares';
|
|
9
11
|
import { z } from 'zod';
|
|
10
12
|
import '@fonderie/rate-limit';
|
|
@@ -15,6 +17,7 @@ declare class AuthModule implements IFonderieModule {
|
|
|
15
17
|
private bus?;
|
|
16
18
|
readonly name = "@fonderie/auth";
|
|
17
19
|
constructor(store: IStoreAdapter, config: IAuthConfig, bus?: EventBus | undefined);
|
|
20
|
+
describeAdmin(): IAdminDescription;
|
|
18
21
|
checkReadiness(): IReadinessProblem[];
|
|
19
22
|
install(app: IFonderieApp): void;
|
|
20
23
|
}
|
|
@@ -233,4 +236,12 @@ declare function startUserRetention(store: IStoreAdapter, options: IUserRetentio
|
|
|
233
236
|
|
|
234
237
|
declare function validateAuthConfig(config: IAuthConfig): void;
|
|
235
238
|
|
|
236
|
-
|
|
239
|
+
interface IAdminUserDTO extends IUserDTO {
|
|
240
|
+
suspended: boolean;
|
|
241
|
+
deletedAt: string | null;
|
|
242
|
+
createdAt: string;
|
|
243
|
+
}
|
|
244
|
+
declare function toAdminUserDTO(user: IUser): IAdminUserDTO;
|
|
245
|
+
declare function describeAuthAdminRoutes(store: IStoreAdapter): IAdminRoute[];
|
|
246
|
+
|
|
247
|
+
export { AuthModule, type ChangePasswordInput, DEFAULT_TEMPLATES, type IAdminUserDTO, IAuthConfig, type IImportUser, type ILoginEventDTO, type ILoginHistoryPageDTO, type IPurgeOptions, type ISessionDTO, IUser, IUserDTO, type IUserRetentionScheduleOptions, type LoginInput, type RegisterInput, type ResetPasswordInput, describeAuthAdminRoutes, importUser, normalizeEmail, normalizeEmailSafe, purgeSoftDeletedUsers, schemas, startUserRetention, toAdminUserDTO, validateAuthConfig };
|
package/dist/index.js
CHANGED
|
@@ -646,6 +646,15 @@ var UserModel = class {
|
|
|
646
646
|
[id]
|
|
647
647
|
);
|
|
648
648
|
}
|
|
649
|
+
// The operator's lock: login, refresh and the session middleware all refuse a
|
|
650
|
+
// suspended user. Returns false when there is no such user.
|
|
651
|
+
async setSuspended(id, suspended) {
|
|
652
|
+
const rows = await this.store.query(
|
|
653
|
+
`UPDATE fonderie_users SET suspended = $2, updated_at = now() WHERE id = $1 AND deleted_at IS NULL RETURNING id`,
|
|
654
|
+
[id, suspended]
|
|
655
|
+
);
|
|
656
|
+
return rows.length > 0;
|
|
657
|
+
}
|
|
649
658
|
async softDelete(id) {
|
|
650
659
|
await this.store.query(
|
|
651
660
|
`UPDATE fonderie_users SET deleted_at = now(), updated_at = now() WHERE id = $1`,
|
|
@@ -3182,6 +3191,115 @@ function extractToken(request) {
|
|
|
3182
3191
|
return match?.[1] ?? null;
|
|
3183
3192
|
}
|
|
3184
3193
|
|
|
3194
|
+
// src/admin.ts
|
|
3195
|
+
import { HTTP as HTTP7, setApiResponse as setApiResponse7 } from "@fonderie/core";
|
|
3196
|
+
function toAdminUserDTO(user) {
|
|
3197
|
+
return {
|
|
3198
|
+
...toUserDTO(user),
|
|
3199
|
+
suspended: Boolean(user.suspended),
|
|
3200
|
+
deletedAt: user.deletedAt ? user.deletedAt.toISOString() : null,
|
|
3201
|
+
createdAt: user.createdAt.toISOString()
|
|
3202
|
+
};
|
|
3203
|
+
}
|
|
3204
|
+
var ADMIN_PREFIX = "/_admin";
|
|
3205
|
+
var idOf = (ctx) => ctx.meta.params?.["id"] ?? "";
|
|
3206
|
+
var NOT_FOUND = () => setApiResponse7(HTTP7.NOT_FOUND, "NOT_FOUND", "No such user");
|
|
3207
|
+
function adminRouteTable(store) {
|
|
3208
|
+
const users = new UserModel(store);
|
|
3209
|
+
const sessions = new SessionModel(store);
|
|
3210
|
+
const events = new LoginEventModel(store);
|
|
3211
|
+
const setSuspended = (suspended) => async (ctx) => {
|
|
3212
|
+
const ok = await users.setSuspended(idOf(ctx), suspended);
|
|
3213
|
+
if (!ok) return NOT_FOUND();
|
|
3214
|
+
const user = await users.findById(idOf(ctx));
|
|
3215
|
+
return user ? setApiResponse7(
|
|
3216
|
+
HTTP7.OK,
|
|
3217
|
+
suspended ? "USER_SUSPENDED" : "USER_UNSUSPENDED",
|
|
3218
|
+
suspended ? "User suspended" : "User unsuspended",
|
|
3219
|
+
toAdminUserDTO(user)
|
|
3220
|
+
) : NOT_FOUND();
|
|
3221
|
+
};
|
|
3222
|
+
return [
|
|
3223
|
+
[
|
|
3224
|
+
"GET",
|
|
3225
|
+
"/_admin/users",
|
|
3226
|
+
async (ctx) => {
|
|
3227
|
+
const email2 = new URL(ctx.request.url).searchParams.get("email")?.trim().toLowerCase();
|
|
3228
|
+
if (!email2)
|
|
3229
|
+
return setApiResponse7(HTTP7.UNPROCESSABLE, "INVALID_PARAMETER", "email is required");
|
|
3230
|
+
const user = await users.findByEmail(email2);
|
|
3231
|
+
return user ? setApiResponse7(HTTP7.OK, "USER", "User", toAdminUserDTO(user)) : NOT_FOUND();
|
|
3232
|
+
}
|
|
3233
|
+
],
|
|
3234
|
+
[
|
|
3235
|
+
"GET",
|
|
3236
|
+
"/_admin/users/:id",
|
|
3237
|
+
async (ctx) => {
|
|
3238
|
+
const user = await users.findById(idOf(ctx));
|
|
3239
|
+
return user ? setApiResponse7(HTTP7.OK, "USER", "User", toAdminUserDTO(user)) : NOT_FOUND();
|
|
3240
|
+
}
|
|
3241
|
+
],
|
|
3242
|
+
[
|
|
3243
|
+
"GET",
|
|
3244
|
+
"/_admin/users/:id/sessions",
|
|
3245
|
+
async (ctx) => {
|
|
3246
|
+
if (!await users.findById(idOf(ctx))) return NOT_FOUND();
|
|
3247
|
+
const rows = await sessions.listLiveByUser(idOf(ctx));
|
|
3248
|
+
return setApiResponse7(
|
|
3249
|
+
HTTP7.OK,
|
|
3250
|
+
"SESSIONS",
|
|
3251
|
+
"Live sessions",
|
|
3252
|
+
rows.map((r) => toSessionDTO(r, null))
|
|
3253
|
+
);
|
|
3254
|
+
}
|
|
3255
|
+
],
|
|
3256
|
+
// Signs the user out everywhere. The one write support reaches for first.
|
|
3257
|
+
[
|
|
3258
|
+
"DELETE",
|
|
3259
|
+
"/_admin/users/:id/sessions",
|
|
3260
|
+
async (ctx) => {
|
|
3261
|
+
if (!await users.findById(idOf(ctx))) return NOT_FOUND();
|
|
3262
|
+
await sessions.deleteByUser(idOf(ctx));
|
|
3263
|
+
return setApiResponse7(HTTP7.OK, "SESSIONS_REVOKED", "All sessions revoked");
|
|
3264
|
+
}
|
|
3265
|
+
],
|
|
3266
|
+
[
|
|
3267
|
+
"GET",
|
|
3268
|
+
"/_admin/users/:id/login-history",
|
|
3269
|
+
async (ctx) => {
|
|
3270
|
+
if (!await users.findById(idOf(ctx))) return NOT_FOUND();
|
|
3271
|
+
const params = new URL(ctx.request.url).searchParams;
|
|
3272
|
+
const rawLimit = Number(params.get("limit") ?? 50);
|
|
3273
|
+
const limit = Number.isFinite(rawLimit) ? Math.min(Math.max(Math.trunc(rawLimit), 1), 200) : 50;
|
|
3274
|
+
const cursorParam = params.get("cursor");
|
|
3275
|
+
const cursor = cursorParam ? decodeLoginCursor(cursorParam) : null;
|
|
3276
|
+
if (cursorParam && !cursor)
|
|
3277
|
+
return setApiResponse7(HTTP7.UNPROCESSABLE, "INVALID_PARAMETER", "Invalid cursor");
|
|
3278
|
+
const page = await events.listByUser({
|
|
3279
|
+
userId: idOf(ctx),
|
|
3280
|
+
limit,
|
|
3281
|
+
...cursor ? { cursor } : {}
|
|
3282
|
+
});
|
|
3283
|
+
return setApiResponse7(
|
|
3284
|
+
HTTP7.OK,
|
|
3285
|
+
"LOGIN_HISTORY",
|
|
3286
|
+
"Login history",
|
|
3287
|
+
toLoginHistoryPageDTO(page)
|
|
3288
|
+
);
|
|
3289
|
+
}
|
|
3290
|
+
],
|
|
3291
|
+
["POST", "/_admin/users/:id/suspend", setSuspended(true)],
|
|
3292
|
+
["POST", "/_admin/users/:id/unsuspend", setSuspended(false)]
|
|
3293
|
+
];
|
|
3294
|
+
}
|
|
3295
|
+
function describeAuthAdminRoutes(store) {
|
|
3296
|
+
return adminRouteTable(store).map(([method, path, h]) => ({
|
|
3297
|
+
method,
|
|
3298
|
+
path: path.slice(ADMIN_PREFIX.length),
|
|
3299
|
+
handlers: [h]
|
|
3300
|
+
}));
|
|
3301
|
+
}
|
|
3302
|
+
|
|
3185
3303
|
// src/module.ts
|
|
3186
3304
|
var AuthModule = class {
|
|
3187
3305
|
constructor(store, config, bus) {
|
|
@@ -3194,6 +3312,10 @@ var AuthModule = class {
|
|
|
3194
3312
|
config;
|
|
3195
3313
|
bus;
|
|
3196
3314
|
name = "@fonderie/auth";
|
|
3315
|
+
// Users, sessions, login history, suspend — only through @fonderie/admin.
|
|
3316
|
+
describeAdmin() {
|
|
3317
|
+
return { routes: describeAuthAdminRoutes(this.store) };
|
|
3318
|
+
}
|
|
3197
3319
|
// Report config problems for app.checkProductionReadiness() (data, not throw).
|
|
3198
3320
|
checkReadiness() {
|
|
3199
3321
|
return collectAuthConfigProblems(this.config);
|
|
@@ -3460,6 +3582,7 @@ export {
|
|
|
3460
3582
|
MESSAGE_KEYS,
|
|
3461
3583
|
buildAuthAccountLimiter,
|
|
3462
3584
|
buildAuthIpLimiter,
|
|
3585
|
+
describeAuthAdminRoutes,
|
|
3463
3586
|
importUser,
|
|
3464
3587
|
normalizeEmail,
|
|
3465
3588
|
normalizeEmailSafe,
|
|
@@ -3467,6 +3590,7 @@ export {
|
|
|
3467
3590
|
requireAuth2 as requireAuth,
|
|
3468
3591
|
schemas_exports as schemas,
|
|
3469
3592
|
startUserRetention,
|
|
3593
|
+
toAdminUserDTO,
|
|
3470
3594
|
toUserDTO,
|
|
3471
3595
|
validate,
|
|
3472
3596
|
validateAuthConfig,
|