@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
|
@@ -17,7 +17,11 @@
|
|
|
17
17
|
// database, no `(action, subject)` pairing to get wrong, and no conditions — which in turn means
|
|
18
18
|
// there is no such thing as a rule the route guard can only *partially* evaluate. What a slug
|
|
19
19
|
// means is decided entirely by which routes name it.
|
|
20
|
-
import {
|
|
20
|
+
import {
|
|
21
|
+
AbilityBuilder,
|
|
22
|
+
createMongoAbility,
|
|
23
|
+
type MongoAbility,
|
|
24
|
+
} from "@casl/ability";
|
|
21
25
|
|
|
22
26
|
/**
|
|
23
27
|
* The subject every rule is written against. CASL needs one; this model does not use subjects, so
|
|
@@ -37,7 +41,9 @@ export type AppAbility = MongoAbility<[string, typeof ABILITY_SUBJECT]>;
|
|
|
37
41
|
* answer for "we could not resolve any permissions", and the same answer as "this user genuinely
|
|
38
42
|
* has none". There is no default-allow branch anywhere in this file.
|
|
39
43
|
*/
|
|
40
|
-
export function defineAbilitiesFor(
|
|
44
|
+
export function defineAbilitiesFor(
|
|
45
|
+
permissions: readonly string[] = [],
|
|
46
|
+
): AppAbility {
|
|
41
47
|
const { can, build } = new AbilityBuilder<AppAbility>(createMongoAbility);
|
|
42
48
|
for (const permission of permissions) can(permission, ABILITY_SUBJECT);
|
|
43
49
|
return build();
|
package/registry/combos/nestjs-drizzle/shared/src/{permission-cache.ts → cache/permission-cache.ts}
RENAMED
|
@@ -36,7 +36,7 @@
|
|
|
36
36
|
// Negative results are not cached either: "not a member of this workspace" is re-read every time,
|
|
37
37
|
// so being added to a workspace is effective immediately rather than after a TTL.
|
|
38
38
|
import { Inject, Injectable } from "@nestjs/common";
|
|
39
|
-
import { AUTH_CONFIG, AuthConfig } from "
|
|
39
|
+
import { AUTH_CONFIG, AuthConfig } from "../config/auth.config.js";
|
|
40
40
|
|
|
41
41
|
/** DI token for the store. Provide your own to `AuthModule.forRoot({ permissionCacheStore })`. */
|
|
42
42
|
export const PERMISSION_CACHE_STORE = Symbol("PERMISSION_CACHE_STORE");
|
|
@@ -70,7 +70,10 @@ export interface PermissionCacheStore {
|
|
|
70
70
|
*/
|
|
71
71
|
export class InMemoryPermissionCacheStore implements PermissionCacheStore {
|
|
72
72
|
readonly stats = { hits: 0, misses: 0, writes: 0 };
|
|
73
|
-
private readonly entries = new Map<
|
|
73
|
+
private readonly entries = new Map<
|
|
74
|
+
string,
|
|
75
|
+
{ value: string; expiresAt: number }
|
|
76
|
+
>();
|
|
74
77
|
|
|
75
78
|
async get(key: string): Promise<string | undefined> {
|
|
76
79
|
const entry = this.entries.get(key);
|
|
@@ -103,10 +106,14 @@ export class InMemoryPermissionCacheStore implements PermissionCacheStore {
|
|
|
103
106
|
|
|
104
107
|
async bump(key: string): Promise<number> {
|
|
105
108
|
const entry = this.entries.get(key);
|
|
106
|
-
const next =
|
|
109
|
+
const next =
|
|
110
|
+
Number(entry && entry.expiresAt > Date.now() ? entry.value : 0) + 1;
|
|
107
111
|
// Version counters outlive entries on purpose: a counter that expired back to 0 would make
|
|
108
112
|
// every superseded entry reachable again.
|
|
109
|
-
this.entries.set(key, {
|
|
113
|
+
this.entries.set(key, {
|
|
114
|
+
value: String(next),
|
|
115
|
+
expiresAt: Number.MAX_SAFE_INTEGER,
|
|
116
|
+
});
|
|
110
117
|
return next;
|
|
111
118
|
}
|
|
112
119
|
}
|
|
@@ -118,8 +125,10 @@ export class InMemoryPermissionCacheStore implements PermissionCacheStore {
|
|
|
118
125
|
* write is picked up when the entry expires (`permissionCacheTtlSeconds`), not immediately.
|
|
119
126
|
*/
|
|
120
127
|
export const POLICY_VERSION_KEY = `${CACHE_NAMESPACE}:policy-version`;
|
|
121
|
-
export const subjectVersionKey = (subject: string) =>
|
|
122
|
-
|
|
128
|
+
export const subjectVersionKey = (subject: string) =>
|
|
129
|
+
`${CACHE_NAMESPACE}:subject-version:${subject}`;
|
|
130
|
+
const entryKey = (subject: string, policy: string, subjectVersion: string) =>
|
|
131
|
+
`${CACHE_NAMESPACE}:entry:${subject}:p${policy}:s${subjectVersion}`;
|
|
123
132
|
|
|
124
133
|
/**
|
|
125
134
|
* Reads through to the database, once per (principal, policy version, subject version).
|
|
@@ -131,7 +140,8 @@ const entryKey = (subject: string, policy: string, subjectVersion: string) => `$
|
|
|
131
140
|
@Injectable()
|
|
132
141
|
export class PermissionCache {
|
|
133
142
|
constructor(
|
|
134
|
-
@Inject(PERMISSION_CACHE_STORE)
|
|
143
|
+
@Inject(PERMISSION_CACHE_STORE)
|
|
144
|
+
private readonly store: PermissionCacheStore,
|
|
135
145
|
@Inject(AUTH_CONFIG) private readonly config: AuthConfig,
|
|
136
146
|
) {}
|
|
137
147
|
|
|
@@ -149,11 +159,17 @@ export class PermissionCache {
|
|
|
149
159
|
* @param subject the identity these permissions belong to — the cache key's principal
|
|
150
160
|
* @param load resolves from the database on a miss. Returning `null` is not cached.
|
|
151
161
|
*/
|
|
152
|
-
async resolve<T>(
|
|
162
|
+
async resolve<T>(
|
|
163
|
+
subject: string,
|
|
164
|
+
load: () => Promise<T | null>,
|
|
165
|
+
): Promise<T | null> {
|
|
153
166
|
const ttl = this.config.permissionCacheTtlSeconds;
|
|
154
167
|
if (ttl <= 0) return load(); // caching off; the semantics are identical, only the cost differs
|
|
155
168
|
|
|
156
|
-
const [policy = "0", version = "0"] = await this.store.getMany([
|
|
169
|
+
const [policy = "0", version = "0"] = await this.store.getMany([
|
|
170
|
+
POLICY_VERSION_KEY,
|
|
171
|
+
subjectVersionKey(subject),
|
|
172
|
+
]);
|
|
157
173
|
const key = entryKey(subject, policy, version);
|
|
158
174
|
|
|
159
175
|
const cached = await this.store.get(key);
|
|
@@ -165,7 +181,8 @@ export class PermissionCache {
|
|
|
165
181
|
const pending = (async () => {
|
|
166
182
|
const resolved = await load();
|
|
167
183
|
// A negative result is not written: see the module comment. Only a real answer is cached.
|
|
168
|
-
if (resolved !== null)
|
|
184
|
+
if (resolved !== null)
|
|
185
|
+
await this.store.set(key, JSON.stringify(resolved), ttl);
|
|
169
186
|
return resolved;
|
|
170
187
|
})();
|
|
171
188
|
|
|
@@ -8,7 +8,10 @@ import type { RateLimitDeps } from "@/lib/auth/core/rate-limit.js";
|
|
|
8
8
|
*/
|
|
9
9
|
@Injectable()
|
|
10
10
|
export class InMemoryRateLimitStore implements RateLimitDeps {
|
|
11
|
-
private readonly windows = new Map<
|
|
11
|
+
private readonly windows = new Map<
|
|
12
|
+
string,
|
|
13
|
+
{ count: number; resetAt: number }
|
|
14
|
+
>();
|
|
12
15
|
|
|
13
16
|
async increment(key: string, windowMs: number): Promise<number> {
|
|
14
17
|
const now = Date.now();
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
// style, which is required (not just stylistic) for DI to keep working under esbuild-based
|
|
6
6
|
// tooling like tsx that skips `emitDecoratorMetadata`'s runtime type reflection.
|
|
7
7
|
import type { NodePgDatabase } from "drizzle-orm/node-postgres";
|
|
8
|
-
import type * as schema from "
|
|
8
|
+
import type * as schema from "../schema.js";
|
|
9
9
|
|
|
10
10
|
export const DRIZZLE_DB = Symbol("DRIZZLE_DB");
|
|
11
11
|
|
package/registry/combos/nestjs-drizzle/shared/src/{key-provider.ts → config/key-provider.ts}
RENAMED
|
@@ -10,11 +10,15 @@ const MIN_SECRET_BYTES = 32; // 256 bits, HS256's own minimum
|
|
|
10
10
|
function loadSecret(): Uint8Array {
|
|
11
11
|
const raw = process.env[ENV_VAR];
|
|
12
12
|
if (!raw) {
|
|
13
|
-
throw new Error(
|
|
13
|
+
throw new Error(
|
|
14
|
+
`${ENV_VAR} is not set. Generate one and set it before starting the app — e.g.: openssl rand -base64 32`,
|
|
15
|
+
);
|
|
14
16
|
}
|
|
15
17
|
const secret = Buffer.from(raw, "base64");
|
|
16
18
|
if (secret.length < MIN_SECRET_BYTES) {
|
|
17
|
-
throw new Error(
|
|
19
|
+
throw new Error(
|
|
20
|
+
`${ENV_VAR} decodes to ${secret.length} bytes — needs at least ${MIN_SECRET_BYTES} (256 bits) for HS256.`,
|
|
21
|
+
);
|
|
18
22
|
}
|
|
19
23
|
return secret;
|
|
20
24
|
}
|
|
@@ -22,7 +22,7 @@ import {
|
|
|
22
22
|
ApiTags,
|
|
23
23
|
} from "@nestjs/swagger";
|
|
24
24
|
import type { Request } from "express";
|
|
25
|
-
import { AUTH_CONFIG, AuthConfig } from "../auth.config.js";
|
|
25
|
+
import { AUTH_CONFIG, AuthConfig } from "../config/auth.config.js";
|
|
26
26
|
import { AuthGuard } from "../guards/auth.guard.js";
|
|
27
27
|
import { AuthService } from "../services/auth.service.js";
|
|
28
28
|
import { AuthzGuard } from "../guards/authz.guard.js";
|
|
@@ -6,7 +6,7 @@ import {
|
|
|
6
6
|
UnauthorizedException,
|
|
7
7
|
} from "@nestjs/common";
|
|
8
8
|
import { verifyAccessToken } from "@/lib/auth/core/token-service.js";
|
|
9
|
-
import { KeyProviderService } from "../key-provider.js";
|
|
9
|
+
import { KeyProviderService } from "../config/key-provider.js";
|
|
10
10
|
import "../request-context.js";
|
|
11
11
|
import { SessionRepository } from "../repositories/session.repository.js";
|
|
12
12
|
|
|
@@ -11,12 +11,16 @@ export function toId(value: string | number | bigint): bigint {
|
|
|
11
11
|
}
|
|
12
12
|
}
|
|
13
13
|
|
|
14
|
-
export function toIdOrUndefined(
|
|
14
|
+
export function toIdOrUndefined(
|
|
15
|
+
value: string | number | bigint | null | undefined,
|
|
16
|
+
): bigint | undefined {
|
|
15
17
|
if (value === null || value === undefined || value === "") return undefined;
|
|
16
18
|
return toId(value);
|
|
17
19
|
}
|
|
18
20
|
|
|
19
|
-
export function toIdOrNull(
|
|
21
|
+
export function toIdOrNull(
|
|
22
|
+
value: string | number | bigint | null | undefined,
|
|
23
|
+
): bigint | null {
|
|
20
24
|
if (value === null || value === undefined || value === "") return null;
|
|
21
25
|
return toId(value);
|
|
22
26
|
}
|
|
@@ -21,10 +21,24 @@ export function normalizePage(page: number | undefined): number {
|
|
|
21
21
|
}
|
|
22
22
|
|
|
23
23
|
export function normalizeLimit(limit: number | undefined): number {
|
|
24
|
-
return Math.min(
|
|
24
|
+
return Math.min(
|
|
25
|
+
limit && limit > 0 ? Math.floor(limit) : DEFAULT_PAGE_SIZE,
|
|
26
|
+
MAX_PAGE_SIZE,
|
|
27
|
+
);
|
|
25
28
|
}
|
|
26
29
|
|
|
27
|
-
export function buildPageMeta(
|
|
30
|
+
export function buildPageMeta(
|
|
31
|
+
page: number,
|
|
32
|
+
limit: number,
|
|
33
|
+
total: number,
|
|
34
|
+
): PageMeta {
|
|
28
35
|
const pageCount = Math.ceil(total / limit);
|
|
29
|
-
return {
|
|
36
|
+
return {
|
|
37
|
+
page,
|
|
38
|
+
limit,
|
|
39
|
+
total,
|
|
40
|
+
pageCount,
|
|
41
|
+
hasPreviousPage: page > 1,
|
|
42
|
+
hasNextPage: page < pageCount,
|
|
43
|
+
};
|
|
30
44
|
}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { BadRequestException, Inject, Injectable } from "@nestjs/common";
|
|
2
2
|
import { and, eq } from "drizzle-orm";
|
|
3
3
|
import type { OAuthStoreDeps } from "@/lib/auth/core/oauth.js";
|
|
4
|
-
import { DRIZZLE_DB, type Database } from "../db.js";
|
|
4
|
+
import { DRIZZLE_DB, type Database } from "../config/db.js";
|
|
5
5
|
import { oauthAccounts, users } from "../schema.js";
|
|
6
|
-
import { toId } from "../id.helper.js";
|
|
6
|
+
import { toId } from "../helpers/id.helper.js";
|
|
7
7
|
|
|
8
8
|
@Injectable()
|
|
9
9
|
export class OAuthRepository implements OAuthStoreDeps {
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { Inject, Injectable } from "@nestjs/common";
|
|
2
2
|
import { eq } from "drizzle-orm";
|
|
3
3
|
import type { PasswordResetStoreDeps } from "@/lib/auth/core/password-reset.js";
|
|
4
|
-
import { DRIZZLE_DB, type Database } from "../db.js";
|
|
4
|
+
import { DRIZZLE_DB, type Database } from "../config/db.js";
|
|
5
5
|
import { passwordResetTokens, users } from "../schema.js";
|
|
6
|
-
import { toId } from "../id.helper.js";
|
|
6
|
+
import { toId } from "../helpers/id.helper.js";
|
|
7
7
|
|
|
8
8
|
@Injectable()
|
|
9
9
|
export class PasswordResetRepository implements PasswordResetStoreDeps {
|
|
@@ -14,18 +14,14 @@ export class PasswordResetRepository implements PasswordResetStoreDeps {
|
|
|
14
14
|
tokenHash: string;
|
|
15
15
|
expiresAt: string;
|
|
16
16
|
}): Promise<void> {
|
|
17
|
-
await this.db
|
|
18
|
-
.
|
|
19
|
-
.
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
expiresAt: new Date(input.expiresAt),
|
|
23
|
-
});
|
|
17
|
+
await this.db.insert(passwordResetTokens).values({
|
|
18
|
+
userId: toId(input.userId),
|
|
19
|
+
tokenHash: input.tokenHash,
|
|
20
|
+
expiresAt: new Date(input.expiresAt),
|
|
21
|
+
});
|
|
24
22
|
}
|
|
25
23
|
|
|
26
|
-
async findValidResetToken(
|
|
27
|
-
tokenHash: string,
|
|
28
|
-
): Promise<{
|
|
24
|
+
async findValidResetToken(tokenHash: string): Promise<{
|
|
29
25
|
userId: string;
|
|
30
26
|
expiresAt: string;
|
|
31
27
|
consumedAt: string | null;
|
|
@@ -8,10 +8,10 @@ import type {
|
|
|
8
8
|
SessionRecord,
|
|
9
9
|
} from "@/lib/auth/core/types.js";
|
|
10
10
|
import { AuditLogRepository } from "./audit-log.repository.js";
|
|
11
|
-
import { AUTH_CONFIG, AuthConfig } from "../auth.config.js";
|
|
12
|
-
import { DRIZZLE_DB, type Database } from "../db.js";
|
|
11
|
+
import { AUTH_CONFIG, AuthConfig } from "../config/auth.config.js";
|
|
12
|
+
import { DRIZZLE_DB, type Database } from "../config/db.js";
|
|
13
13
|
import { denylistedAccessTokens, sessions } from "../schema.js";
|
|
14
|
-
import { toId, toIdOrNull } from "../id.helper.js";
|
|
14
|
+
import { toId, toIdOrNull } from "../helpers/id.helper.js";
|
|
15
15
|
|
|
16
16
|
function toSessionRecord(row: typeof sessions.$inferSelect): SessionRecord {
|
|
17
17
|
return {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Inject, Injectable } from "@nestjs/common";
|
|
2
2
|
import { and, eq, isNull } from "drizzle-orm";
|
|
3
3
|
import { verifyBackupCode } from "@/lib/auth/core/two-factor.js";
|
|
4
|
-
import { DRIZZLE_DB, type Database } from "../db.js";
|
|
4
|
+
import { DRIZZLE_DB, type Database } from "../config/db.js";
|
|
5
5
|
import { twoFactorBackupCodes } from "../schema.js";
|
|
6
6
|
|
|
7
7
|
// Takes bigint directly, not string: every caller already has the user row's id in hand from
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
// authorization was decided, only what it decided — see authz.guard.ts. Importing this module
|
|
14
14
|
// for its side effect installs the Express `Request` augmentation.
|
|
15
15
|
import type { AccessTokenClaims } from "@/lib/auth/core/types.js";
|
|
16
|
-
import type { AppAbility } from "./ability.js";
|
|
16
|
+
import type { AppAbility } from "./ability/ability.js";
|
|
17
17
|
import type { AuthzContext } from "./guards/authz.guard.js";
|
|
18
18
|
|
|
19
19
|
declare module "express" {
|
|
@@ -2,7 +2,7 @@ import "reflect-metadata";
|
|
|
2
2
|
import { Module } from "@nestjs/common";
|
|
3
3
|
import { NestFactory } from "@nestjs/core";
|
|
4
4
|
import { AuthModule } from "../src/auth.module.js";
|
|
5
|
-
import { InMemoryPermissionCacheStore } from "../src/permission-cache.js";
|
|
5
|
+
import { InMemoryPermissionCacheStore } from "../src/cache/permission-cache.js";
|
|
6
6
|
|
|
7
7
|
// No mailer is wired up for the proof, so this stands in for one — prove-cycle.ts reads the
|
|
8
8
|
// raw token back out of here the same way a test inbox would, to exercise the reset flow.
|
|
@@ -11,7 +11,7 @@ import "dotenv/config";
|
|
|
11
11
|
import { randomUUID } from "node:crypto";
|
|
12
12
|
import { Get } from "@nestjs/common";
|
|
13
13
|
import { generateTotpCode } from "@/lib/auth/core/two-factor.js";
|
|
14
|
-
import { ABILITY_SUBJECT, defineAbilitiesFor } from "../src/ability.js";
|
|
14
|
+
import { ABILITY_SUBJECT, defineAbilitiesFor } from "../src/ability/ability.js";
|
|
15
15
|
import { AuthController } from "../src/controllers/auth.controller.js";
|
|
16
16
|
import { bootstrap, capturedResetTokens } from "./bootstrap.js";
|
|
17
17
|
import {
|
|
@@ -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 } 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";
|
|
@@ -23,7 +23,7 @@ import {
|
|
|
23
23
|
ApiTags,
|
|
24
24
|
} from "@nestjs/swagger";
|
|
25
25
|
import type { Request } from "express";
|
|
26
|
-
import { AbilityGuard } from "../
|
|
26
|
+
import { AbilityGuard } from "../ability/ability.guard.js";
|
|
27
27
|
import { AuthGuard } from "../guards/auth.guard.js";
|
|
28
28
|
import { AuthService } from "../services/auth.service.js";
|
|
29
29
|
import { AuthzGuard } from "../guards/authz.guard.js";
|
|
@@ -4,8 +4,8 @@ import {
|
|
|
4
4
|
Inject,
|
|
5
5
|
Injectable,
|
|
6
6
|
} from "@nestjs/common";
|
|
7
|
-
import { defineAbilitiesFor } from "../ability.js";
|
|
8
|
-
import { PermissionCache } from "../permission-cache.js";
|
|
7
|
+
import { defineAbilitiesFor } from "../ability/ability.js";
|
|
8
|
+
import { PermissionCache } from "../cache/permission-cache.js";
|
|
9
9
|
import { RbacRepository } from "../repositories/rbac.repository.js";
|
|
10
10
|
|
|
11
11
|
/**
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
// Callers: `src/seed.ts` (`npm run seed`, the only bootstrap in this variant) and
|
|
23
23
|
// `variants/base/test/variant-hooks.ts`.
|
|
24
24
|
import { inArray } from "drizzle-orm";
|
|
25
|
-
import type { Database } from "./db.js";
|
|
25
|
+
import type { Database } from "./config/db.js";
|
|
26
26
|
import { permissionRole, permissions, roles } from "./schema.js";
|
|
27
27
|
|
|
28
28
|
/** The display metadata a seeded permission carries. `group`/`order` exist so an admin console can render a stable matrix. */
|
|
@@ -44,40 +44,65 @@ export interface PermissionSeed {
|
|
|
44
44
|
* evaluate.
|
|
45
45
|
*/
|
|
46
46
|
export const PERMISSION_CATALOG = {
|
|
47
|
-
"users:read": {
|
|
48
|
-
|
|
47
|
+
"users:read": {
|
|
48
|
+
displayName: "List users",
|
|
49
|
+
description: "GET /auth/admin/users",
|
|
50
|
+
group: "Users",
|
|
51
|
+
order: 1,
|
|
52
|
+
},
|
|
53
|
+
"users:block": {
|
|
54
|
+
displayName: "Block and unblock users",
|
|
55
|
+
description: "POST /auth/admin/users/:userId/block, .../unblock",
|
|
56
|
+
group: "Users",
|
|
57
|
+
order: 2,
|
|
58
|
+
},
|
|
49
59
|
"users:manage": {
|
|
50
60
|
displayName: "Edit and delete users",
|
|
51
|
-
description:
|
|
61
|
+
description:
|
|
62
|
+
"Edit a user's profile or delete their account — PATCH /auth/admin/users/:userId, DELETE /auth/admin/users/:userId",
|
|
52
63
|
group: "Users",
|
|
53
64
|
order: 3,
|
|
54
65
|
},
|
|
55
66
|
"roles:manage": {
|
|
56
67
|
displayName: "Define roles",
|
|
57
|
-
description:
|
|
68
|
+
description:
|
|
69
|
+
"Create, edit, or delete roles and say what they carry — POST/PATCH/DELETE /auth/admin/roles(/:roleId), POST /auth/admin/roles/:roleId/permissions",
|
|
58
70
|
group: "Roles",
|
|
59
71
|
order: 1,
|
|
60
72
|
},
|
|
61
73
|
"roles:assign": {
|
|
62
74
|
displayName: "Assign roles",
|
|
63
|
-
description:
|
|
75
|
+
description:
|
|
76
|
+
"Assign and revoke a user's roles — POST /auth/admin/users/:userId/roles, .../roles/:roleSlug/revoke",
|
|
64
77
|
group: "Roles",
|
|
65
78
|
order: 2,
|
|
66
79
|
},
|
|
67
|
-
"permissions:read": {
|
|
80
|
+
"permissions:read": {
|
|
81
|
+
displayName: "Read the permission catalog",
|
|
82
|
+
description: "GET /auth/admin/permissions",
|
|
83
|
+
group: "Permissions",
|
|
84
|
+
order: 1,
|
|
85
|
+
},
|
|
68
86
|
"permissions:define": {
|
|
69
87
|
displayName: "Define permissions",
|
|
70
|
-
description:
|
|
88
|
+
description:
|
|
89
|
+
"Create a permission, rename it, or deactivate it — POST /auth/admin/permissions. The authority that defines all the others.",
|
|
71
90
|
group: "Permissions",
|
|
72
91
|
order: 2,
|
|
73
92
|
},
|
|
74
93
|
"permissions:grant": {
|
|
75
94
|
displayName: "Grant permissions directly",
|
|
76
|
-
description:
|
|
95
|
+
description:
|
|
96
|
+
"Grant and revoke a permission straight to a user, bypassing roles — POST /auth/admin/users/:userId/permissions, .../permissions/:slug/revoke",
|
|
77
97
|
group: "Permissions",
|
|
78
98
|
order: 3,
|
|
79
99
|
},
|
|
80
|
-
"audit-log:read": {
|
|
100
|
+
"audit-log:read": {
|
|
101
|
+
displayName: "Read the audit log",
|
|
102
|
+
description: "GET /auth/admin/audit-log",
|
|
103
|
+
group: "Audit",
|
|
104
|
+
order: 1,
|
|
105
|
+
},
|
|
81
106
|
} as const satisfies Record<string, PermissionSeed>;
|
|
82
107
|
|
|
83
108
|
/**
|
|
@@ -89,10 +114,14 @@ export const PERMISSION_CATALOG = {
|
|
|
89
114
|
*/
|
|
90
115
|
export type PermissionSlug = keyof typeof PERMISSION_CATALOG;
|
|
91
116
|
|
|
92
|
-
export const PERMISSION_SLUGS = Object.keys(
|
|
117
|
+
export const PERMISSION_SLUGS = Object.keys(
|
|
118
|
+
PERMISSION_CATALOG,
|
|
119
|
+
) as PermissionSlug[];
|
|
93
120
|
|
|
94
121
|
/** Groups, in the order an admin console should render them. Derived from the catalog so it cannot drift from it. */
|
|
95
|
-
export const PERMISSION_GROUP_ORDER: string[] = [
|
|
122
|
+
export const PERMISSION_GROUP_ORDER: string[] = [
|
|
123
|
+
...new Set(PERMISSION_SLUGS.map((slug) => PERMISSION_CATALOG[slug].group)),
|
|
124
|
+
];
|
|
96
125
|
|
|
97
126
|
/** The display metadata a seeded role carries, plus what it starts out granting. */
|
|
98
127
|
export interface RoleSeed {
|
|
@@ -177,12 +206,17 @@ export async function provisionDefaultRoles(db: RbacWriter): Promise<void> {
|
|
|
177
206
|
displayName: PERMISSION_CATALOG[slug].displayName,
|
|
178
207
|
description: PERMISSION_CATALOG[slug].description,
|
|
179
208
|
group: PERMISSION_CATALOG[slug].group,
|
|
180
|
-
groupOrder: PERMISSION_GROUP_ORDER.indexOf(
|
|
209
|
+
groupOrder: PERMISSION_GROUP_ORDER.indexOf(
|
|
210
|
+
PERMISSION_CATALOG[slug].group,
|
|
211
|
+
),
|
|
181
212
|
order: PERMISSION_CATALOG[slug].order,
|
|
182
213
|
})),
|
|
183
214
|
)
|
|
184
215
|
.onConflictDoNothing({ target: permissions.slug });
|
|
185
|
-
const permissionRows = await db
|
|
216
|
+
const permissionRows = await db
|
|
217
|
+
.select({ id: permissions.id, slug: permissions.slug })
|
|
218
|
+
.from(permissions)
|
|
219
|
+
.where(inArray(permissions.slug, PERMISSION_SLUGS));
|
|
186
220
|
const permissionId = new Map(permissionRows.map((p) => [p.slug, p.id]));
|
|
187
221
|
|
|
188
222
|
await db
|
|
@@ -210,9 +244,17 @@ export async function provisionDefaultRoles(db: RbacWriter): Promise<void> {
|
|
|
210
244
|
const seedBySlug = new Map(DEFAULT_ROLES.map((role) => [role.slug, role]));
|
|
211
245
|
|
|
212
246
|
const pairs = roleRows.flatMap((role) =>
|
|
213
|
-
(seedBySlug.get(role.slug)?.permissions ?? []).map((slug) => ({
|
|
247
|
+
(seedBySlug.get(role.slug)?.permissions ?? []).map((slug) => ({
|
|
248
|
+
roleId: role.id,
|
|
249
|
+
permissionId: permissionId.get(slug)!,
|
|
250
|
+
})),
|
|
214
251
|
);
|
|
215
252
|
if (pairs.length) {
|
|
216
|
-
await db
|
|
253
|
+
await db
|
|
254
|
+
.insert(permissionRole)
|
|
255
|
+
.values(pairs)
|
|
256
|
+
.onConflictDoNothing({
|
|
257
|
+
target: [permissionRole.permissionId, permissionRole.roleId],
|
|
258
|
+
});
|
|
217
259
|
}
|
|
218
260
|
}
|
package/registry/combos/nestjs-drizzle/variants/base/src/repositories/audit-log.repository.ts
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
import { Inject, Injectable } from "@nestjs/common";
|
|
2
2
|
import { and, count, desc, eq, gte, lte, type SQL } from "drizzle-orm";
|
|
3
3
|
import type { AuditEvent } from "@/lib/auth/core/types.js";
|
|
4
|
-
import { DRIZZLE_DB, type Database } from "../db.js";
|
|
4
|
+
import { DRIZZLE_DB, type Database } from "../config/db.js";
|
|
5
5
|
import {
|
|
6
6
|
buildPageMeta,
|
|
7
7
|
normalizeLimit,
|
|
8
8
|
normalizePage,
|
|
9
9
|
type Paginated,
|
|
10
|
-
} from "../pagination.js";
|
|
10
|
+
} from "../helpers/pagination.js";
|
|
11
11
|
import { auditLogs } from "../schema.js";
|
|
12
|
-
import { toIdOrNull, toIdOrUndefined } from "../id.helper.js";
|
|
12
|
+
import { toIdOrNull, toIdOrUndefined } from "../helpers/id.helper.js";
|
|
13
13
|
|
|
14
14
|
export interface AuditLogEntry {
|
|
15
15
|
id: string;
|
|
@@ -15,14 +15,14 @@ import {
|
|
|
15
15
|
type SQL,
|
|
16
16
|
} from "drizzle-orm";
|
|
17
17
|
import { resolvePermissions } from "@/lib/auth/core/rbac.js";
|
|
18
|
-
import { DRIZZLE_DB, type Database } from "../db.js";
|
|
18
|
+
import { DRIZZLE_DB, type Database } from "../config/db.js";
|
|
19
19
|
import {
|
|
20
20
|
buildPageMeta,
|
|
21
21
|
normalizeLimit,
|
|
22
22
|
normalizePage,
|
|
23
23
|
type Paginated,
|
|
24
|
-
} from "../pagination.js";
|
|
25
|
-
import { PermissionCache } from "../permission-cache.js";
|
|
24
|
+
} from "../helpers/pagination.js";
|
|
25
|
+
import { PermissionCache } from "../cache/permission-cache.js";
|
|
26
26
|
import {
|
|
27
27
|
permissionRole,
|
|
28
28
|
permissionUser,
|
|
@@ -31,7 +31,7 @@ import {
|
|
|
31
31
|
roles,
|
|
32
32
|
users,
|
|
33
33
|
} from "../schema.js";
|
|
34
|
-
import { toId, toIdOrNull } from "../id.helper.js";
|
|
34
|
+
import { toId, toIdOrNull } from "../helpers/id.helper.js";
|
|
35
35
|
|
|
36
36
|
export interface UserSummary {
|
|
37
37
|
id: string;
|