@simple-auth-kit/cli 1.5.1 → 1.6.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/package.json +1 -1
- package/registry/combos/express-drizzle/shared/src/{ability.ts → ability/ability.ts} +8 -2
- package/registry/combos/express-drizzle/shared/src/{permission-cache.ts → cache/permission-cache.ts} +25 -9
- package/registry/combos/express-drizzle/shared/src/{rate-limit.store.ts → cache/rate-limit.store.ts} +4 -1
- package/registry/combos/{express-prisma/shared/src → express-drizzle/shared/src/config}/auth.config.ts +1 -1
- package/registry/combos/express-drizzle/shared/src/{db.ts → config/db.ts} +1 -1
- package/registry/combos/express-drizzle/shared/src/{key-provider.ts → config/key-provider.ts} +6 -2
- package/registry/combos/express-drizzle/shared/src/{id.helper.ts → helpers/id.helper.ts} +6 -2
- package/registry/combos/{nestjs-drizzle/shared/src → express-drizzle/shared/src/helpers}/pagination.ts +17 -3
- package/registry/combos/express-drizzle/shared/src/middleware/auth-core-error.middleware.ts +6 -8
- package/registry/combos/express-drizzle/shared/src/middleware/auth.middleware.ts +6 -8
- package/registry/combos/{express-prisma/shared/src → express-drizzle/shared/src/openapi}/openapi-fragment.ts +13 -4
- package/registry/combos/express-drizzle/shared/src/{openapi-spec.ts → openapi/openapi-spec.ts} +251 -52
- package/registry/combos/express-drizzle/shared/src/repositories/oauth.repository.ts +2 -2
- package/registry/combos/express-drizzle/shared/src/repositories/password-reset.repository.ts +2 -4
- package/registry/combos/express-drizzle/shared/src/repositories/session.repository.ts +3 -3
- package/registry/combos/express-drizzle/shared/src/request-context.ts +1 -1
- package/registry/combos/express-drizzle/shared/src/route-tiers.ts +52 -11
- package/registry/combos/express-drizzle/shared/src/routers/auth.router.ts +2 -2
- package/registry/combos/express-drizzle/test/bootstrap.ts +4 -2
- package/registry/combos/express-drizzle/test/prove-cycle.ts +1095 -308
- package/registry/combos/express-drizzle/variants/base/src/create-auth-app.ts +5 -5
- package/registry/combos/express-drizzle/variants/base/src/index.ts +8 -0
- package/registry/combos/express-drizzle/variants/base/src/middleware/authz.middleware.ts +2 -2
- package/registry/combos/express-drizzle/variants/base/src/openapi/openapi-admin.ts +1082 -0
- package/registry/combos/express-drizzle/variants/base/src/rbac.defaults.ts +60 -17
- package/registry/combos/express-drizzle/variants/base/src/repositories/audit-log.repository.ts +2 -2
- package/registry/combos/express-drizzle/variants/base/src/repositories/rbac.repository.ts +5 -5
- package/registry/combos/express-drizzle/variants/base/src/routers/admin.router.ts +18 -22
- package/registry/combos/express-drizzle/variants/base/src/seed.ts +76 -17
- package/registry/combos/express-drizzle/variants/base/src/services/auth.service.ts +7 -9
- package/registry/combos/express-drizzle/variants/base/test/variant-hooks.ts +167 -45
- package/registry/combos/express-drizzle/variants/workspaces/src/create-auth-app.ts +5 -5
- package/registry/combos/express-drizzle/variants/workspaces/src/index.ts +8 -0
- package/registry/combos/express-drizzle/variants/workspaces/src/middleware/authz.middleware.ts +3 -3
- package/registry/combos/express-drizzle/variants/workspaces/src/openapi/openapi-admin.ts +1176 -0
- package/registry/combos/express-drizzle/variants/workspaces/src/openapi-workspace.ts +1 -1
- package/registry/combos/express-drizzle/variants/workspaces/src/rbac.defaults.ts +66 -19
- package/registry/combos/express-drizzle/variants/workspaces/src/repositories/audit-log.repository.ts +2 -2
- package/registry/combos/express-drizzle/variants/workspaces/src/repositories/rbac.repository.ts +5 -5
- package/registry/combos/express-drizzle/variants/workspaces/src/repositories/workspace.repository.ts +9 -11
- package/registry/combos/express-drizzle/variants/workspaces/src/routers/admin.router.ts +18 -22
- package/registry/combos/express-drizzle/variants/workspaces/src/routers/workspace.router.ts +1 -1
- package/registry/combos/express-drizzle/variants/workspaces/src/seed.ts +168 -35
- package/registry/combos/express-drizzle/variants/workspaces/src/services/auth.service.ts +7 -9
- package/registry/combos/express-drizzle/variants/workspaces/test/variant-hooks.ts +539 -133
- package/registry/combos/express-prisma/shared/src/{ability.ts → ability/ability.ts} +8 -2
- package/registry/combos/express-prisma/shared/src/{permission-cache.ts → cache/permission-cache.ts} +25 -9
- package/registry/combos/express-prisma/shared/src/{rate-limit.store.ts → cache/rate-limit.store.ts} +4 -1
- package/registry/combos/{express-drizzle/shared/src → express-prisma/shared/src/config}/auth.config.ts +1 -1
- package/registry/combos/express-prisma/shared/src/{key-provider.ts → config/key-provider.ts} +6 -2
- package/registry/combos/{nestjs-prisma/shared/src → express-prisma/shared/src/helpers}/id.helper.ts +6 -2
- package/registry/combos/{express-drizzle/shared/src → express-prisma/shared/src/helpers}/pagination.ts +17 -3
- package/registry/combos/express-prisma/shared/src/middleware/auth-core-error.middleware.ts +6 -8
- package/registry/combos/express-prisma/shared/src/middleware/auth.middleware.ts +6 -8
- package/registry/combos/{express-drizzle/shared/src → express-prisma/shared/src/openapi}/openapi-fragment.ts +13 -4
- package/registry/combos/express-prisma/shared/src/{openapi-spec.ts → openapi/openapi-spec.ts} +313 -55
- package/registry/combos/express-prisma/shared/src/repositories/oauth.repository.ts +2 -2
- package/registry/combos/express-prisma/shared/src/repositories/password-reset.repository.ts +2 -4
- package/registry/combos/express-prisma/shared/src/repositories/session.repository.ts +2 -2
- package/registry/combos/express-prisma/shared/src/request-context.ts +1 -1
- package/registry/combos/express-prisma/shared/src/route-tiers.ts +52 -11
- package/registry/combos/express-prisma/shared/src/routers/auth.router.ts +2 -2
- package/registry/combos/express-prisma/test/bootstrap.ts +7 -3
- package/registry/combos/express-prisma/test/prove-cycle.ts +1095 -308
- package/registry/combos/express-prisma/variants/base/src/create-auth-app.ts +6 -6
- package/registry/combos/express-prisma/variants/base/src/index.ts +8 -0
- package/registry/combos/express-prisma/variants/base/src/middleware/authz.middleware.ts +2 -2
- package/registry/combos/express-prisma/variants/base/src/openapi/openapi-admin.ts +1102 -0
- package/registry/combos/express-prisma/variants/base/src/rbac.defaults.ts +1 -1
- package/registry/combos/express-prisma/variants/base/src/repositories/audit-log.repository.ts +2 -2
- package/registry/combos/express-prisma/variants/base/src/repositories/rbac.repository.ts +4 -4
- package/registry/combos/express-prisma/variants/base/src/routers/admin.router.ts +18 -22
- package/registry/combos/express-prisma/variants/base/src/seed.ts +1 -1
- package/registry/combos/express-prisma/variants/base/src/services/auth.service.ts +6 -8
- package/registry/combos/express-prisma/variants/base/test/variant-hooks.ts +176 -47
- package/registry/combos/express-prisma/variants/workspaces/src/create-auth-app.ts +6 -6
- package/registry/combos/express-prisma/variants/workspaces/src/index.ts +8 -0
- package/registry/combos/express-prisma/variants/workspaces/src/middleware/authz.middleware.ts +3 -3
- package/registry/combos/express-prisma/variants/workspaces/src/openapi/openapi-admin.ts +1218 -0
- package/registry/combos/express-prisma/variants/workspaces/src/openapi-workspace.ts +1 -1
- package/registry/combos/express-prisma/variants/workspaces/src/rbac.defaults.ts +1 -1
- package/registry/combos/express-prisma/variants/workspaces/src/repositories/audit-log.repository.ts +2 -2
- package/registry/combos/express-prisma/variants/workspaces/src/repositories/rbac.repository.ts +4 -4
- package/registry/combos/express-prisma/variants/workspaces/src/repositories/workspace.repository.ts +2 -2
- package/registry/combos/express-prisma/variants/workspaces/src/routers/admin.router.ts +18 -22
- package/registry/combos/express-prisma/variants/workspaces/src/routers/workspace.router.ts +1 -1
- package/registry/combos/express-prisma/variants/workspaces/src/seed.ts +1 -1
- package/registry/combos/express-prisma/variants/workspaces/src/services/auth.service.ts +6 -8
- package/registry/combos/express-prisma/variants/workspaces/test/variant-hooks.ts +538 -134
- package/registry/combos/nestjs-drizzle/shared/src/{guards → ability}/ability.guard.ts +1 -1
- package/registry/combos/nestjs-drizzle/shared/src/{ability.ts → ability/ability.ts} +8 -2
- package/registry/combos/nestjs-drizzle/shared/src/{permission-cache.ts → cache/permission-cache.ts} +27 -10
- package/registry/combos/{nestjs-prisma/shared/src → nestjs-drizzle/shared/src/cache}/rate-limit.store.ts +4 -1
- package/registry/combos/nestjs-drizzle/shared/src/{auth.config.ts → config/auth.config.ts} +1 -1
- package/registry/combos/nestjs-drizzle/shared/src/{db.ts → config/db.ts} +1 -1
- package/registry/combos/nestjs-drizzle/shared/src/{key-provider.ts → config/key-provider.ts} +6 -2
- package/registry/combos/nestjs-drizzle/shared/src/controllers/auth.controller.ts +1 -1
- package/registry/combos/nestjs-drizzle/shared/src/guards/auth.guard.ts +1 -1
- package/registry/combos/nestjs-drizzle/shared/src/{id.helper.ts → helpers/id.helper.ts} +6 -2
- package/registry/combos/{express-prisma/shared/src → nestjs-drizzle/shared/src/helpers}/pagination.ts +17 -3
- package/registry/combos/nestjs-drizzle/shared/src/repositories/oauth.repository.ts +2 -2
- package/registry/combos/nestjs-drizzle/shared/src/repositories/password-reset.repository.ts +8 -12
- package/registry/combos/nestjs-drizzle/shared/src/repositories/session.repository.ts +3 -3
- package/registry/combos/nestjs-drizzle/shared/src/repositories/two-factor.repository.ts +1 -1
- package/registry/combos/nestjs-drizzle/shared/src/request-context.ts +1 -1
- package/registry/combos/nestjs-drizzle/test/bootstrap.ts +1 -1
- package/registry/combos/nestjs-drizzle/test/prove-cycle.ts +1 -1
- package/registry/combos/nestjs-drizzle/variants/base/src/auth.module.ts +10 -6
- package/registry/combos/nestjs-drizzle/variants/base/src/controllers/admin.controller.ts +1 -1
- package/registry/combos/nestjs-drizzle/variants/base/src/guards/authz.guard.ts +2 -2
- package/registry/combos/nestjs-drizzle/variants/base/src/index.ts +9 -0
- package/registry/combos/nestjs-drizzle/variants/base/src/rbac.defaults.ts +58 -16
- package/registry/combos/nestjs-drizzle/variants/base/src/repositories/audit-log.repository.ts +3 -3
- package/registry/combos/nestjs-drizzle/variants/base/src/repositories/rbac.repository.ts +4 -4
- package/registry/combos/nestjs-drizzle/variants/base/src/seed.ts +76 -17
- package/registry/combos/nestjs-drizzle/variants/base/src/services/auth.service.ts +7 -9
- package/registry/combos/nestjs-drizzle/variants/base/test/variant-hooks.ts +167 -45
- package/registry/combos/nestjs-drizzle/variants/workspaces/src/auth.module.ts +10 -6
- package/registry/combos/nestjs-drizzle/variants/workspaces/src/controllers/admin.controller.ts +1 -1
- package/registry/combos/nestjs-drizzle/variants/workspaces/src/controllers/workspace.controller.ts +1 -1
- package/registry/combos/nestjs-drizzle/variants/workspaces/src/guards/authz.guard.ts +2 -2
- package/registry/combos/nestjs-drizzle/variants/workspaces/src/index.ts +9 -0
- package/registry/combos/nestjs-drizzle/variants/workspaces/src/rbac.defaults.ts +64 -18
- package/registry/combos/nestjs-drizzle/variants/workspaces/src/repositories/audit-log.repository.ts +3 -3
- package/registry/combos/nestjs-drizzle/variants/workspaces/src/repositories/rbac.repository.ts +4 -4
- package/registry/combos/nestjs-drizzle/variants/workspaces/src/repositories/workspace.repository.ts +8 -10
- package/registry/combos/nestjs-drizzle/variants/workspaces/src/seed.ts +171 -36
- package/registry/combos/nestjs-drizzle/variants/workspaces/src/services/auth.service.ts +7 -9
- package/registry/combos/nestjs-drizzle/variants/workspaces/test/variant-hooks.ts +539 -133
- package/registry/combos/nestjs-prisma/shared/src/{guards → ability}/ability.guard.ts +1 -1
- package/registry/combos/nestjs-prisma/shared/src/{ability.ts → ability/ability.ts} +8 -2
- package/registry/combos/nestjs-prisma/shared/src/{permission-cache.ts → cache/permission-cache.ts} +27 -10
- package/registry/combos/{nestjs-drizzle/shared/src → nestjs-prisma/shared/src/cache}/rate-limit.store.ts +4 -1
- package/registry/combos/nestjs-prisma/shared/src/{auth.config.ts → config/auth.config.ts} +1 -1
- package/registry/combos/nestjs-prisma/shared/src/{key-provider.ts → config/key-provider.ts} +6 -2
- package/registry/combos/nestjs-prisma/shared/src/controllers/auth.controller.ts +1 -1
- package/registry/combos/nestjs-prisma/shared/src/guards/auth.guard.ts +1 -1
- package/registry/combos/{express-prisma/shared/src → nestjs-prisma/shared/src/helpers}/id.helper.ts +6 -2
- package/registry/combos/nestjs-prisma/shared/src/{pagination.ts → helpers/pagination.ts} +17 -3
- package/registry/combos/nestjs-prisma/shared/src/repositories/oauth.repository.ts +1 -1
- package/registry/combos/nestjs-prisma/shared/src/repositories/password-reset.repository.ts +2 -4
- package/registry/combos/nestjs-prisma/shared/src/repositories/session.repository.ts +2 -2
- package/registry/combos/nestjs-prisma/shared/src/request-context.ts +1 -1
- package/registry/combos/nestjs-prisma/test/bootstrap.ts +1 -1
- package/registry/combos/nestjs-prisma/test/prove-cycle.ts +1 -1
- package/registry/combos/nestjs-prisma/variants/base/src/auth.module.ts +10 -6
- package/registry/combos/nestjs-prisma/variants/base/src/controllers/admin.controller.ts +1 -1
- package/registry/combos/nestjs-prisma/variants/base/src/gateways/audit-log.gateway.ts +1 -1
- package/registry/combos/nestjs-prisma/variants/base/src/guards/authz.guard.ts +2 -2
- package/registry/combos/nestjs-prisma/variants/base/src/index.ts +9 -0
- package/registry/combos/nestjs-prisma/variants/base/src/{docs.ts → openapi/docs.ts} +23 -6
- package/registry/combos/nestjs-prisma/variants/base/src/rbac.defaults.ts +1 -1
- package/registry/combos/nestjs-prisma/variants/base/src/repositories/audit-log.repository.ts +2 -2
- package/registry/combos/nestjs-prisma/variants/base/src/repositories/country.repository.ts +2 -2
- package/registry/combos/nestjs-prisma/variants/base/src/repositories/customer.repository.ts +6 -5
- package/registry/combos/nestjs-prisma/variants/base/src/repositories/language.repository.ts +2 -2
- package/registry/combos/nestjs-prisma/variants/base/src/repositories/rbac.repository.ts +3 -3
- package/registry/combos/nestjs-prisma/variants/base/src/seed.ts +1 -1
- package/registry/combos/nestjs-prisma/variants/base/src/services/auth.service.ts +6 -8
- package/registry/combos/nestjs-prisma/variants/base/test/variant-hooks.ts +176 -47
- package/registry/combos/nestjs-prisma/variants/workspaces/src/auth.module.ts +10 -6
- package/registry/combos/nestjs-prisma/variants/workspaces/src/controllers/admin.controller.ts +1 -1
- package/registry/combos/nestjs-prisma/variants/workspaces/src/controllers/workspace.controller.ts +1 -1
- package/registry/combos/nestjs-prisma/variants/workspaces/src/guards/authz.guard.ts +2 -2
- package/registry/combos/nestjs-prisma/variants/workspaces/src/index.ts +9 -0
- package/registry/combos/nestjs-prisma/variants/workspaces/src/rbac.defaults.ts +1 -1
- package/registry/combos/nestjs-prisma/variants/workspaces/src/repositories/audit-log.repository.ts +2 -2
- package/registry/combos/nestjs-prisma/variants/workspaces/src/repositories/country.repository.ts +2 -2
- package/registry/combos/nestjs-prisma/variants/workspaces/src/repositories/customer.repository.ts +6 -5
- package/registry/combos/nestjs-prisma/variants/workspaces/src/repositories/language.repository.ts +2 -2
- package/registry/combos/nestjs-prisma/variants/workspaces/src/repositories/rbac.repository.ts +3 -3
- package/registry/combos/nestjs-prisma/variants/workspaces/src/repositories/workspace.repository.ts +1 -1
- package/registry/combos/nestjs-prisma/variants/workspaces/src/seed.ts +1 -1
- package/registry/combos/nestjs-prisma/variants/workspaces/src/services/auth.service.ts +6 -8
- package/registry/combos/nestjs-prisma/variants/workspaces/test/variant-hooks.ts +538 -134
- package/registry/combos/express-drizzle/variants/base/src/openapi-admin.ts +0 -565
- package/registry/combos/express-drizzle/variants/workspaces/src/openapi-admin.ts +0 -596
- package/registry/combos/express-prisma/variants/base/src/openapi-admin.ts +0 -569
- package/registry/combos/express-prisma/variants/workspaces/src/openapi-admin.ts +0 -601
- /package/registry/combos/express-drizzle/shared/src/{http-error.ts → errors/http-error.ts} +0 -0
- /package/registry/combos/express-prisma/shared/src/{http-error.ts → errors/http-error.ts} +0 -0
|
@@ -24,14 +24,23 @@ import { eq, inArray, notInArray } from "drizzle-orm";
|
|
|
24
24
|
import { drizzle } from "drizzle-orm/node-postgres";
|
|
25
25
|
import { Pool } from "pg";
|
|
26
26
|
import { hashPassword } from "@/lib/auth/core/crypto.js";
|
|
27
|
-
import type { Database } from "./db.js";
|
|
28
|
-
import {
|
|
27
|
+
import type { Database } from "./config/db.js";
|
|
28
|
+
import {
|
|
29
|
+
DEFAULT_ROLES,
|
|
30
|
+
PERMISSION_SLUGS,
|
|
31
|
+
SEED_ADMIN_ROLES,
|
|
32
|
+
SEED_SUPERADMIN_ROLES,
|
|
33
|
+
provisionDefaultRoles,
|
|
34
|
+
} from "./rbac.defaults.js";
|
|
29
35
|
import * as schema from "./schema.js";
|
|
30
36
|
import { permissions, roleUser, roles, users } from "./schema.js";
|
|
31
37
|
|
|
32
38
|
function requireEnv(name: string): string {
|
|
33
39
|
const value = process.env[name];
|
|
34
|
-
if (!value)
|
|
40
|
+
if (!value)
|
|
41
|
+
throw new Error(
|
|
42
|
+
`${name} is not set — the seeder cannot reach the database without it`,
|
|
43
|
+
);
|
|
35
44
|
return value;
|
|
36
45
|
}
|
|
37
46
|
|
|
@@ -39,7 +48,10 @@ function requireEnv(name: string): string {
|
|
|
39
48
|
async function seedRbacDefaults(db: Database): Promise<void> {
|
|
40
49
|
await provisionDefaultRoles(db);
|
|
41
50
|
console.log(`permissions: ${PERMISSION_SLUGS.length} slug(s) in the catalog`);
|
|
42
|
-
for (const role of DEFAULT_ROLES)
|
|
51
|
+
for (const role of DEFAULT_ROLES)
|
|
52
|
+
console.log(
|
|
53
|
+
`role "${role.slug}": ${role.permissions.length} permission(s)${role.isDefault ? " (signup default)" : ""}`,
|
|
54
|
+
);
|
|
43
55
|
|
|
44
56
|
// Slugs that exist in the database but not in this build's catalog. They are not an error —
|
|
45
57
|
// `POST /auth/admin/permissions` exists so a deployment can define its own, and a grant can
|
|
@@ -49,9 +61,18 @@ async function seedRbacDefaults(db: Database): Promise<void> {
|
|
|
49
61
|
.select({ slug: permissions.slug })
|
|
50
62
|
.from(permissions)
|
|
51
63
|
.where(notInArray(permissions.slug, PERMISSION_SLUGS));
|
|
52
|
-
if (unknown.length)
|
|
53
|
-
|
|
54
|
-
|
|
64
|
+
if (unknown.length)
|
|
65
|
+
console.log(
|
|
66
|
+
`permissions: ${unknown.length} slug(s) outside this build's catalog (no route names them): ${unknown.map((r) => r.slug).join(", ")}`,
|
|
67
|
+
);
|
|
68
|
+
const inactive = await db
|
|
69
|
+
.select({ slug: permissions.slug })
|
|
70
|
+
.from(permissions)
|
|
71
|
+
.where(eq(permissions.isActive, false));
|
|
72
|
+
if (inactive.length)
|
|
73
|
+
console.log(
|
|
74
|
+
`permissions: ${inactive.length} deactivated, granting nothing: ${inactive.map((r) => r.slug).join(", ")}`,
|
|
75
|
+
);
|
|
55
76
|
}
|
|
56
77
|
|
|
57
78
|
/** Roles are global here, so administrative authority is a property of the user row itself. */
|
|
@@ -59,15 +80,32 @@ async function seedAdminUser(db: Database): Promise<void> {
|
|
|
59
80
|
const email = process.env["SEED_ADMIN_EMAIL"];
|
|
60
81
|
const password = process.env["SEED_ADMIN_PASSWORD"];
|
|
61
82
|
if (!email || !password) {
|
|
62
|
-
console.log(
|
|
83
|
+
console.log(
|
|
84
|
+
"admin: skipped — set SEED_ADMIN_EMAIL and SEED_ADMIN_PASSWORD to create one (there is no default password)",
|
|
85
|
+
);
|
|
63
86
|
return;
|
|
64
87
|
}
|
|
65
88
|
|
|
66
89
|
// Their password may have been changed since; rewriting it here would silently reset it.
|
|
67
|
-
const [existing] = await db
|
|
90
|
+
const [existing] = await db
|
|
91
|
+
.select({ id: users.id })
|
|
92
|
+
.from(users)
|
|
93
|
+
.where(eq(users.email, email))
|
|
94
|
+
.limit(1);
|
|
68
95
|
// Hashed by the same function signup uses, so the seeded admin can actually log in.
|
|
69
|
-
const user =
|
|
70
|
-
|
|
96
|
+
const user =
|
|
97
|
+
existing ??
|
|
98
|
+
(
|
|
99
|
+
await db
|
|
100
|
+
.insert(users)
|
|
101
|
+
.values({ email, passwordHash: await hashPassword(password) })
|
|
102
|
+
.returning({ id: users.id })
|
|
103
|
+
)[0];
|
|
104
|
+
console.log(
|
|
105
|
+
existing
|
|
106
|
+
? `admin: ${email} already exists — password left unchanged`
|
|
107
|
+
: `admin: created ${email}`,
|
|
108
|
+
);
|
|
71
109
|
|
|
72
110
|
const adminRoles = await db
|
|
73
111
|
.select({ id: roles.id, slug: roles.slug })
|
|
@@ -87,16 +125,33 @@ async function seedSuperAdminUser(db: Database): Promise<void> {
|
|
|
87
125
|
const email = process.env["SEED_SUPERADMIN_EMAIL"];
|
|
88
126
|
const password = process.env["SEED_SUPERADMIN_PASSWORD"];
|
|
89
127
|
if (!email || !password) {
|
|
90
|
-
console.log(
|
|
128
|
+
console.log(
|
|
129
|
+
"super admin: skipped — set SEED_SUPERADMIN_EMAIL and SEED_SUPERADMIN_PASSWORD to create one (there is no default password)",
|
|
130
|
+
);
|
|
91
131
|
return;
|
|
92
132
|
}
|
|
93
133
|
const username = process.env["SEED_SUPERADMIN_USERNAME"] || undefined;
|
|
94
134
|
|
|
95
135
|
// Their password may have been changed since; rewriting it here would silently reset it.
|
|
96
|
-
const [existing] = await db
|
|
136
|
+
const [existing] = await db
|
|
137
|
+
.select({ id: users.id })
|
|
138
|
+
.from(users)
|
|
139
|
+
.where(eq(users.email, email))
|
|
140
|
+
.limit(1);
|
|
97
141
|
// Hashed by the same function signup uses, so the seeded super admin can actually log in.
|
|
98
|
-
const user =
|
|
99
|
-
|
|
142
|
+
const user =
|
|
143
|
+
existing ??
|
|
144
|
+
(
|
|
145
|
+
await db
|
|
146
|
+
.insert(users)
|
|
147
|
+
.values({ email, username, passwordHash: await hashPassword(password) })
|
|
148
|
+
.returning({ id: users.id })
|
|
149
|
+
)[0];
|
|
150
|
+
console.log(
|
|
151
|
+
existing
|
|
152
|
+
? `super admin: ${email} already exists — password left unchanged`
|
|
153
|
+
: `super admin: created ${email}${username ? ` (username ${username})` : ""}`,
|
|
154
|
+
);
|
|
100
155
|
|
|
101
156
|
const superAdminRoles = await db
|
|
102
157
|
.select({ id: roles.id, slug: roles.slug })
|
|
@@ -105,10 +160,14 @@ async function seedSuperAdminUser(db: Database): Promise<void> {
|
|
|
105
160
|
if (superAdminRoles.length) {
|
|
106
161
|
await db
|
|
107
162
|
.insert(roleUser)
|
|
108
|
-
.values(
|
|
163
|
+
.values(
|
|
164
|
+
superAdminRoles.map((role) => ({ userId: user.id, roleId: role.id })),
|
|
165
|
+
)
|
|
109
166
|
.onConflictDoNothing({ target: [roleUser.userId, roleUser.roleId] });
|
|
110
167
|
}
|
|
111
|
-
console.log(
|
|
168
|
+
console.log(
|
|
169
|
+
`super admin: holds roles ${superAdminRoles.map((r) => r.slug).join(", ")}`,
|
|
170
|
+
);
|
|
112
171
|
}
|
|
113
172
|
|
|
114
173
|
async function main(): Promise<void> {
|
|
@@ -52,19 +52,19 @@ import {
|
|
|
52
52
|
generateTotpSecret,
|
|
53
53
|
verifyTotpCode,
|
|
54
54
|
} from "@/lib/auth/core/two-factor.js";
|
|
55
|
-
import { AUTH_CONFIG, AuthConfig } from "../auth.config.js";
|
|
55
|
+
import { AUTH_CONFIG, AuthConfig } from "../config/auth.config.js";
|
|
56
56
|
import {
|
|
57
57
|
AuditLogEntry,
|
|
58
58
|
AuditLogListFilter,
|
|
59
59
|
AuditLogRepository,
|
|
60
60
|
toAuditLogEntry,
|
|
61
61
|
} from "../repositories/audit-log.repository.js";
|
|
62
|
-
import type { Paginated } from "../pagination.js";
|
|
63
|
-
import { DRIZZLE_DB, type Database } from "../db.js";
|
|
64
|
-
import { KeyProviderService } from "../key-provider.js";
|
|
62
|
+
import type { Paginated } from "../helpers/pagination.js";
|
|
63
|
+
import { DRIZZLE_DB, type Database } from "../config/db.js";
|
|
64
|
+
import { KeyProviderService } from "../config/key-provider.js";
|
|
65
65
|
import { OAuthRepository } from "../repositories/oauth.repository.js";
|
|
66
66
|
import { PasswordResetRepository } from "../repositories/password-reset.repository.js";
|
|
67
|
-
import { RATE_LIMIT_STORE } from "../rate-limit.store.js";
|
|
67
|
+
import { RATE_LIMIT_STORE } from "../cache/rate-limit.store.js";
|
|
68
68
|
import type { Revoker } from "@/lib/auth/core/types.js";
|
|
69
69
|
import {
|
|
70
70
|
PermissionInput,
|
|
@@ -79,7 +79,7 @@ import {
|
|
|
79
79
|
import { sessions, users } from "../schema.js";
|
|
80
80
|
import { SessionRepository } from "../repositories/session.repository.js";
|
|
81
81
|
import { TwoFactorRepository } from "../repositories/two-factor.repository.js";
|
|
82
|
-
import { toId, toIdOrNull } from "../id.helper.js";
|
|
82
|
+
import { toId, toIdOrNull } from "../helpers/id.helper.js";
|
|
83
83
|
|
|
84
84
|
export interface AuthTokens {
|
|
85
85
|
accessToken: string;
|
|
@@ -490,9 +490,7 @@ export class AuthService {
|
|
|
490
490
|
return { twoFactorEnabled: user.twoFactorEnabled };
|
|
491
491
|
}
|
|
492
492
|
|
|
493
|
-
async listActiveSessions(
|
|
494
|
-
userId: string,
|
|
495
|
-
): Promise<
|
|
493
|
+
async listActiveSessions(userId: string): Promise<
|
|
496
494
|
Array<{
|
|
497
495
|
id: string;
|
|
498
496
|
createdAt: string;
|
|
@@ -7,14 +7,24 @@ import "dotenv/config";
|
|
|
7
7
|
import { eq, inArray } from "drizzle-orm";
|
|
8
8
|
import { drizzle } from "drizzle-orm/node-postgres";
|
|
9
9
|
import { Pool } from "pg";
|
|
10
|
-
import type { Database } from "../src/db.js";
|
|
11
|
-
import { toId } from "../src/id.helper.js";
|
|
12
|
-
import { POLICY_VERSION_KEY } from "../src/permission-cache.js";
|
|
13
|
-
import {
|
|
10
|
+
import type { Database } from "../src/config/db.js";
|
|
11
|
+
import { toId } from "../src/helpers/id.helper.js";
|
|
12
|
+
import { POLICY_VERSION_KEY } from "../src/cache/permission-cache.js";
|
|
13
|
+
import {
|
|
14
|
+
provisionDefaultRoles,
|
|
15
|
+
SEED_ADMIN_ROLES,
|
|
16
|
+
} from "../src/rbac.defaults.js";
|
|
14
17
|
import * as schema from "../src/schema.js";
|
|
15
18
|
import { permissions, roleUser, roles } from "../src/schema.js";
|
|
16
19
|
import { permissionCacheStore } from "./bootstrap.js";
|
|
17
|
-
import {
|
|
20
|
+
import {
|
|
21
|
+
renewingToken,
|
|
22
|
+
type AdminSession,
|
|
23
|
+
type AuthTokens,
|
|
24
|
+
type Principal,
|
|
25
|
+
type ProofContext,
|
|
26
|
+
type VariantHooks,
|
|
27
|
+
} from "./harness.js";
|
|
18
28
|
|
|
19
29
|
/** One short-lived pool per call, closed on the way out, so the proof process has no lingering handle to wait on. */
|
|
20
30
|
async function withDb<T>(fn: (db: Database) => Promise<T>): Promise<T> {
|
|
@@ -32,7 +42,10 @@ let adminCredentials: { identifier: string; password: string } | undefined;
|
|
|
32
42
|
export const hooks: VariantHooks = {
|
|
33
43
|
variant: "base",
|
|
34
44
|
|
|
35
|
-
async makeAdmin(
|
|
45
|
+
async makeAdmin(
|
|
46
|
+
ctx: ProofContext,
|
|
47
|
+
principal: Principal,
|
|
48
|
+
): Promise<AdminSession> {
|
|
36
49
|
// The role slug on its own confers nothing — no guard checks for the string "admin". Authority
|
|
37
50
|
// comes from the permission_role rows behind it, and in this variant the seeder is the only
|
|
38
51
|
// thing that writes them, so the hook does what `npm run seed` does: calls the same
|
|
@@ -46,24 +59,36 @@ export const hooks: VariantHooks = {
|
|
|
46
59
|
.where(inArray(roles.slug, SEED_ADMIN_ROLES));
|
|
47
60
|
await db
|
|
48
61
|
.insert(roleUser)
|
|
49
|
-
.values(
|
|
62
|
+
.values(
|
|
63
|
+
adminRoles.map((role) => ({
|
|
64
|
+
userId: toId(principal.userId),
|
|
65
|
+
roleId: role.id,
|
|
66
|
+
})),
|
|
67
|
+
)
|
|
50
68
|
.onConflictDoNothing({ target: [roleUser.userId, roleUser.roleId] });
|
|
51
69
|
});
|
|
52
70
|
|
|
53
|
-
adminCredentials = {
|
|
71
|
+
adminCredentials = {
|
|
72
|
+
identifier: principal.email,
|
|
73
|
+
password: principal.password,
|
|
74
|
+
};
|
|
54
75
|
// Those writes went straight to the database, behind the running app's back, so nothing
|
|
55
76
|
// bumped a version counter and the caller's already-cached (empty) permissions would still be
|
|
56
77
|
// served. Bumping the policy counter is exactly what an out-of-band writer is supposed to do —
|
|
57
78
|
// see permission-cache.ts. Logging in would not have helped: nothing about authorization is
|
|
58
79
|
// in the token.
|
|
59
80
|
await permissionCacheStore.bump(POLICY_VERSION_KEY);
|
|
60
|
-
const login = await ctx.call("POST", "/auth/login", {
|
|
81
|
+
const login = await ctx.call("POST", "/auth/login", {
|
|
82
|
+
body: { identifier: principal.email, password: principal.password },
|
|
83
|
+
});
|
|
61
84
|
const token = (login.body as AuthTokens).accessToken;
|
|
62
85
|
ctx.assert(!!token, `the seeded admin can log in (got ${login.status})`);
|
|
63
86
|
return {
|
|
64
87
|
token,
|
|
65
88
|
freshToken: renewingToken(async () => {
|
|
66
|
-
const res = await ctx.call("POST", "/auth/login", {
|
|
89
|
+
const res = await ctx.call("POST", "/auth/login", {
|
|
90
|
+
body: adminCredentials!,
|
|
91
|
+
});
|
|
67
92
|
return (res.body as AuthTokens).accessToken;
|
|
68
93
|
}),
|
|
69
94
|
};
|
|
@@ -73,16 +98,37 @@ export const hooks: VariantHooks = {
|
|
|
73
98
|
// Nothing to do: admin endpoints operate on the whole deployment.
|
|
74
99
|
},
|
|
75
100
|
|
|
76
|
-
async proveVariantProperties(
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
101
|
+
async proveVariantProperties(
|
|
102
|
+
ctx: ProofContext,
|
|
103
|
+
admin: AdminSession,
|
|
104
|
+
): Promise<void> {
|
|
105
|
+
const listed = await ctx.call("GET", "/auth/admin/users", {
|
|
106
|
+
token: await admin.freshToken(),
|
|
107
|
+
});
|
|
108
|
+
ctx.assert(
|
|
109
|
+
listed.status === 200,
|
|
110
|
+
`admin can list every user in the deployment (got ${listed.status})`,
|
|
111
|
+
);
|
|
112
|
+
ctx.assert(
|
|
113
|
+
Array.isArray(listed.body?.items) && listed.body.items.length > 0,
|
|
114
|
+
"the user list is non-empty",
|
|
115
|
+
);
|
|
80
116
|
|
|
81
|
-
const workspaces = await ctx.call("GET", "/workspaces", {
|
|
82
|
-
|
|
117
|
+
const workspaces = await ctx.call("GET", "/workspaces", {
|
|
118
|
+
token: await admin.freshToken(),
|
|
119
|
+
});
|
|
120
|
+
ctx.assert(
|
|
121
|
+
workspaces.status === 404,
|
|
122
|
+
`no workspace endpoints exist in this variant (got ${workspaces.status})`,
|
|
123
|
+
);
|
|
83
124
|
|
|
84
|
-
const me = await ctx.call("GET", "/auth/me", {
|
|
85
|
-
|
|
125
|
+
const me = await ctx.call("GET", "/auth/me", {
|
|
126
|
+
token: await admin.freshToken(),
|
|
127
|
+
});
|
|
128
|
+
ctx.assert(
|
|
129
|
+
me.body?.roles?.includes("admin"),
|
|
130
|
+
"roles are global: they apply to every request this user makes",
|
|
131
|
+
);
|
|
86
132
|
|
|
87
133
|
// --- authorization is not in the token, so a change lands on the next *request* ---
|
|
88
134
|
//
|
|
@@ -96,24 +142,55 @@ export const hooks: VariantHooks = {
|
|
|
96
142
|
const email = ctx.uniqueEmail("immediate");
|
|
97
143
|
const password = "immediate-pw-12345";
|
|
98
144
|
const tokens = await ctx.signup(email, password);
|
|
99
|
-
const userId = (
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
ctx.assert(beforeGrant.status === 403, `a user with no grant is refused (got ${beforeGrant.status})`);
|
|
145
|
+
const userId = (
|
|
146
|
+
await ctx.call("GET", "/auth/me", { token: tokens.accessToken })
|
|
147
|
+
).body.sub as string;
|
|
103
148
|
|
|
104
|
-
const
|
|
105
|
-
|
|
149
|
+
const beforeGrant = await ctx.call("GET", "/auth/admin/users", {
|
|
150
|
+
token: tokens.accessToken,
|
|
151
|
+
});
|
|
152
|
+
ctx.assert(
|
|
153
|
+
beforeGrant.status === 403,
|
|
154
|
+
`a user with no grant is refused (got ${beforeGrant.status})`,
|
|
155
|
+
);
|
|
106
156
|
|
|
107
|
-
const
|
|
108
|
-
|
|
157
|
+
const granted = await ctx.call(
|
|
158
|
+
"POST",
|
|
159
|
+
`/auth/admin/users/${userId}/permissions`,
|
|
160
|
+
{ token: await admin.freshToken(), body: { permission: "users:read" } },
|
|
161
|
+
);
|
|
162
|
+
ctx.assert(
|
|
163
|
+
granted.status === 200 || granted.status === 201,
|
|
164
|
+
`admin can grant a permission directly (got ${granted.status})`,
|
|
165
|
+
);
|
|
109
166
|
|
|
110
|
-
const
|
|
111
|
-
token:
|
|
167
|
+
const afterGrant = await ctx.call("GET", "/auth/admin/users", {
|
|
168
|
+
token: tokens.accessToken,
|
|
112
169
|
});
|
|
113
|
-
ctx.assert(
|
|
170
|
+
ctx.assert(
|
|
171
|
+
afterGrant.status === 200,
|
|
172
|
+
`…and the grant is in effect on the very next request, on the token they already held (got ${afterGrant.status})`,
|
|
173
|
+
);
|
|
114
174
|
|
|
115
|
-
const
|
|
116
|
-
|
|
175
|
+
const revoked = await ctx.call(
|
|
176
|
+
"POST",
|
|
177
|
+
`/auth/admin/users/${userId}/permissions/${encodeURIComponent("users:read")}/revoke`,
|
|
178
|
+
{
|
|
179
|
+
token: await admin.freshToken(),
|
|
180
|
+
},
|
|
181
|
+
);
|
|
182
|
+
ctx.assert(
|
|
183
|
+
revoked.status === 200 || revoked.status === 201,
|
|
184
|
+
`admin can revoke the direct grant (got ${revoked.status})`,
|
|
185
|
+
);
|
|
186
|
+
|
|
187
|
+
const afterRevoke = await ctx.call("GET", "/auth/admin/users", {
|
|
188
|
+
token: tokens.accessToken,
|
|
189
|
+
});
|
|
190
|
+
ctx.assert(
|
|
191
|
+
afterRevoke.status === 403,
|
|
192
|
+
`and the revocation lands on the very next request too, on the same token (got ${afterRevoke.status})`,
|
|
193
|
+
);
|
|
117
194
|
|
|
118
195
|
await proveTheCacheIsReal(ctx, admin, tokens.accessToken);
|
|
119
196
|
await proveARawDatabaseEditChangesEnforcement(ctx, admin);
|
|
@@ -125,7 +202,11 @@ export const hooks: VariantHooks = {
|
|
|
125
202
|
* app resolves through (`test/bootstrap.ts` hands it to `AuthModule.forRoot`), so "the second
|
|
126
203
|
* request did not touch the database" is a measurement rather than a claim.
|
|
127
204
|
*/
|
|
128
|
-
async function proveTheCacheIsReal(
|
|
205
|
+
async function proveTheCacheIsReal(
|
|
206
|
+
ctx: ProofContext,
|
|
207
|
+
admin: AdminSession,
|
|
208
|
+
token: string,
|
|
209
|
+
): Promise<void> {
|
|
129
210
|
const N = 8;
|
|
130
211
|
await ctx.call("GET", "/auth/me", { token }); // warm, so the measurement is of the steady state
|
|
131
212
|
const before = { ...permissionCacheStore.stats };
|
|
@@ -137,16 +218,27 @@ async function proveTheCacheIsReal(ctx: ProofContext, admin: AdminSession, token
|
|
|
137
218
|
`${N} identical authorized requests resolve permissions 0 further times — all ${N} were cache hits (misses +${after.misses - before.misses}, hits +${after.hits - before.hits})`,
|
|
138
219
|
);
|
|
139
220
|
|
|
140
|
-
const userId = (await ctx.call("GET", "/auth/me", { token })).body
|
|
221
|
+
const userId = (await ctx.call("GET", "/auth/me", { token })).body
|
|
222
|
+
.sub as string;
|
|
141
223
|
const beforeGrant = { ...permissionCacheStore.stats };
|
|
142
|
-
await ctx.call("POST", `/auth/admin/users/${userId}/permissions`, {
|
|
224
|
+
await ctx.call("POST", `/auth/admin/users/${userId}/permissions`, {
|
|
225
|
+
token: await admin.freshToken(),
|
|
226
|
+
body: { permission: "probe:cache" },
|
|
227
|
+
});
|
|
143
228
|
const afterGrantCall = await ctx.call("GET", "/auth/me", { token });
|
|
144
229
|
ctx.assert(
|
|
145
230
|
permissionCacheStore.stats.misses > beforeGrant.misses,
|
|
146
231
|
"a grant bumps this user's version counter, so the next request misses the cache and re-resolves rather than serving a stale entry",
|
|
147
232
|
);
|
|
148
|
-
ctx.assert(
|
|
149
|
-
|
|
233
|
+
ctx.assert(
|
|
234
|
+
(afterGrantCall.body?.permissions ?? []).includes("probe:cache"),
|
|
235
|
+
"…and the freshly resolved answer contains the new permission",
|
|
236
|
+
);
|
|
237
|
+
await ctx.call(
|
|
238
|
+
"POST",
|
|
239
|
+
`/auth/admin/users/${userId}/permissions/${encodeURIComponent("probe:cache")}/revoke`,
|
|
240
|
+
{ token: await admin.freshToken() },
|
|
241
|
+
);
|
|
150
242
|
}
|
|
151
243
|
|
|
152
244
|
/**
|
|
@@ -154,26 +246,56 @@ async function proveTheCacheIsReal(ctx: ProofContext, admin: AdminSession, token
|
|
|
154
246
|
* doing the writing — this rules out any possibility that it is also doing something in memory.
|
|
155
247
|
* A `psql` session would look exactly like this.
|
|
156
248
|
*/
|
|
157
|
-
async function proveARawDatabaseEditChangesEnforcement(
|
|
249
|
+
async function proveARawDatabaseEditChangesEnforcement(
|
|
250
|
+
ctx: ProofContext,
|
|
251
|
+
admin: AdminSession,
|
|
252
|
+
): Promise<void> {
|
|
158
253
|
const email = ctx.uniqueEmail("rawedit");
|
|
159
254
|
const tokens = await ctx.signup(email, "rawedit-pw-12345");
|
|
160
|
-
const userId = (
|
|
161
|
-
|
|
162
|
-
|
|
255
|
+
const userId = (
|
|
256
|
+
await ctx.call("GET", "/auth/me", { token: tokens.accessToken })
|
|
257
|
+
).body.sub as string;
|
|
258
|
+
await ctx.call("POST", `/auth/admin/users/${userId}/permissions`, {
|
|
259
|
+
token: await admin.freshToken(),
|
|
260
|
+
body: { permission: "audit-log:read" },
|
|
261
|
+
});
|
|
262
|
+
ctx.assert(
|
|
263
|
+
(
|
|
264
|
+
await ctx.call("GET", "/auth/admin/audit-log", {
|
|
265
|
+
token: tokens.accessToken,
|
|
266
|
+
})
|
|
267
|
+
).status === 200,
|
|
268
|
+
"a direct grant opens the audit log",
|
|
269
|
+
);
|
|
163
270
|
|
|
164
271
|
const setActive = async (isActive: boolean) => {
|
|
165
272
|
// Written straight to the table, with no code change and no redeploy. The bump that follows is
|
|
166
273
|
// the out-of-band writer's half of the cache contract (permission-cache.ts) — without it the
|
|
167
274
|
// edit would still land, but only once the cached entry expired.
|
|
168
|
-
await withDb((db) =>
|
|
275
|
+
await withDb((db) =>
|
|
276
|
+
db
|
|
277
|
+
.update(permissions)
|
|
278
|
+
.set({ isActive })
|
|
279
|
+
.where(eq(permissions.slug, "audit-log:read")),
|
|
280
|
+
);
|
|
169
281
|
await permissionCacheStore.bump(POLICY_VERSION_KEY);
|
|
170
282
|
};
|
|
171
283
|
|
|
172
284
|
await setActive(false);
|
|
173
|
-
const denied = await ctx.call("GET", "/auth/admin/audit-log", {
|
|
174
|
-
|
|
285
|
+
const denied = await ctx.call("GET", "/auth/admin/audit-log", {
|
|
286
|
+
token: tokens.accessToken,
|
|
287
|
+
});
|
|
288
|
+
ctx.assert(
|
|
289
|
+
denied.status === 403,
|
|
290
|
+
`a permission deactivated by a raw database write stops opening its route (got ${denied.status})`,
|
|
291
|
+
);
|
|
175
292
|
|
|
176
293
|
await setActive(true);
|
|
177
|
-
const restored = await ctx.call("GET", "/auth/admin/audit-log", {
|
|
178
|
-
|
|
294
|
+
const restored = await ctx.call("GET", "/auth/admin/audit-log", {
|
|
295
|
+
token: tokens.accessToken,
|
|
296
|
+
});
|
|
297
|
+
ctx.assert(
|
|
298
|
+
restored.status === 200,
|
|
299
|
+
`…and reactivating it in the database opens the route again (got ${restored.status})`,
|
|
300
|
+
);
|
|
179
301
|
}
|
|
@@ -2,28 +2,32 @@ import { Pool } from "pg";
|
|
|
2
2
|
import { drizzle } from "drizzle-orm/node-postgres";
|
|
3
3
|
import { DynamicModule, Module } from "@nestjs/common";
|
|
4
4
|
import { APP_FILTER, APP_INTERCEPTOR } from "@nestjs/core";
|
|
5
|
-
import { AbilityGuard } from "./
|
|
5
|
+
import { AbilityGuard } from "./ability/ability.guard.js";
|
|
6
6
|
import { AdminController } from "./controllers/admin.controller.js";
|
|
7
7
|
import { AuditLogRepository } from "./repositories/audit-log.repository.js";
|
|
8
8
|
import { AuthCoreErrorFilter } from "./filters/auth-core-error.filter.js";
|
|
9
|
-
import {
|
|
9
|
+
import {
|
|
10
|
+
AUTH_CONFIG,
|
|
11
|
+
AuthConfig,
|
|
12
|
+
defaultAuthConfig,
|
|
13
|
+
} from "./config/auth.config.js";
|
|
10
14
|
import { AuthController } from "./controllers/auth.controller.js";
|
|
11
15
|
import { AuthGuard } from "./guards/auth.guard.js";
|
|
12
16
|
import { AuthService } from "./services/auth.service.js";
|
|
13
17
|
import { AuthzGuard, WorkspaceGuard } from "./guards/authz.guard.js";
|
|
14
|
-
import { DRIZZLE_DB } from "./db.js";
|
|
15
|
-
import { KeyProviderService } from "./key-provider.js";
|
|
18
|
+
import { DRIZZLE_DB } from "./config/db.js";
|
|
19
|
+
import { KeyProviderService } from "./config/key-provider.js";
|
|
16
20
|
import { OAuthRepository } from "./repositories/oauth.repository.js";
|
|
17
21
|
import { PasswordResetRepository } from "./repositories/password-reset.repository.js";
|
|
18
22
|
import {
|
|
19
23
|
InMemoryPermissionCacheStore,
|
|
20
24
|
PERMISSION_CACHE_STORE,
|
|
21
25
|
PermissionCache,
|
|
22
|
-
} from "./permission-cache.js";
|
|
26
|
+
} from "./cache/permission-cache.js";
|
|
23
27
|
import {
|
|
24
28
|
InMemoryRateLimitStore,
|
|
25
29
|
RATE_LIMIT_STORE,
|
|
26
|
-
} from "./rate-limit.store.js";
|
|
30
|
+
} from "./cache/rate-limit.store.js";
|
|
27
31
|
import { RbacRepository } from "./repositories/rbac.repository.js";
|
|
28
32
|
import { ResponseInterceptor } from "./interceptors/response.interceptor.js";
|
|
29
33
|
import { assertEveryRouteDeclaresATier } from "./route-tiers.js";
|
package/registry/combos/nestjs-drizzle/variants/workspaces/src/controllers/admin.controller.ts
CHANGED
|
@@ -25,7 +25,7 @@ import {
|
|
|
25
25
|
ApiTags,
|
|
26
26
|
} from "@nestjs/swagger";
|
|
27
27
|
import type { Request } from "express";
|
|
28
|
-
import { AbilityGuard } from "../
|
|
28
|
+
import { AbilityGuard } from "../ability/ability.guard.js";
|
|
29
29
|
import { AuthGuard } from "../guards/auth.guard.js";
|
|
30
30
|
import { AuthService } from "../services/auth.service.js";
|
|
31
31
|
import { WORKSPACE_HEADER, WorkspaceGuard } from "../guards/authz.guard.js";
|
package/registry/combos/nestjs-drizzle/variants/workspaces/src/controllers/workspace.controller.ts
CHANGED
|
@@ -22,7 +22,7 @@ import {
|
|
|
22
22
|
ApiTags,
|
|
23
23
|
} from "@nestjs/swagger";
|
|
24
24
|
import type { Request } from "express";
|
|
25
|
-
import { AbilityGuard } from "../
|
|
25
|
+
import { AbilityGuard } from "../ability/ability.guard.js";
|
|
26
26
|
import { AuthGuard } from "../guards/auth.guard.js";
|
|
27
27
|
import { WORKSPACE_HEADER, WorkspaceGuard } from "../guards/authz.guard.js";
|
|
28
28
|
import { Authenticated, CheckAbility } from "../route-tiers.js";
|
|
@@ -5,8 +5,8 @@ import {
|
|
|
5
5
|
Inject,
|
|
6
6
|
Injectable,
|
|
7
7
|
} from "@nestjs/common";
|
|
8
|
-
import { defineAbilitiesFor } from "../ability.js";
|
|
9
|
-
import { PermissionCache } from "../permission-cache.js";
|
|
8
|
+
import { defineAbilitiesFor } from "../ability/ability.js";
|
|
9
|
+
import { PermissionCache } from "../cache/permission-cache.js";
|
|
10
10
|
import {
|
|
11
11
|
memberCacheKey,
|
|
12
12
|
RbacRepository,
|