@appxdigital/appx-core 0.1.121-beta.13 → 0.1.121-beta.15
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/PRERELEASES.md +27 -0
- package/dist/common/config/permissionsConfigTypes.d.ts +1 -1
- package/dist/common/config/permissionsConfigTypes.d.ts.map +1 -1
- package/dist/index.d.ts +12 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +15 -0
- package/dist/modules/auth/auth.module.d.ts +11 -0
- package/dist/modules/auth/auth.module.d.ts.map +1 -1
- package/dist/modules/auth/auth.module.js +40 -13
- package/dist/prisma/permissions-validator.d.ts +2 -1
- package/dist/prisma/permissions-validator.d.ts.map +1 -1
- package/dist/prisma/permissions-validator.js +7 -15
- package/docs/README.md +1 -0
- package/docs/authentication.md +215 -0
- package/package.json +1 -1
package/PRERELEASES.md
CHANGED
|
@@ -31,6 +31,33 @@ Prereleases are excluded from normal semver range resolution, so a project on
|
|
|
31
31
|
|
|
32
32
|
---
|
|
33
33
|
|
|
34
|
+
## [0.1.121-beta.15] — unreleased
|
|
35
|
+
|
|
36
|
+
**Library / docs. Additive — no behaviour change.** Auth is now extensible from
|
|
37
|
+
the package root instead of deep `dist/` imports.
|
|
38
|
+
|
|
39
|
+
- **Exported the auth building blocks** from `@appxdigital/appx-core`:
|
|
40
|
+
`AuthController`, `AuthService`, `RegisterDto`, `UserDto`, `AuthField`,
|
|
41
|
+
`LocalStrategy`, `JwtStrategy`, `RefreshTokenStrategy`, `LocalAuthGuard`,
|
|
42
|
+
`RefreshTokenGuard`, `SessionSerializer`, `SessionAuthGuard`. Stop importing
|
|
43
|
+
these from `@appxdigital/appx-core/dist/...` — deep paths are internal.
|
|
44
|
+
- **`AuthModule.forRoot({ controller?: boolean })`** — importing
|
|
45
|
+
`AuthModule.forRoot({ controller: false })` registers every auth provider
|
|
46
|
+
globally but **not** the built-in `AuthController`, so you can register your own
|
|
47
|
+
controller (e.g. `extends AuthController`) at the same `/auth` prefix with no
|
|
48
|
+
duplicate route. Importing the plain `AuthModule` is unchanged (still registers
|
|
49
|
+
the controller).
|
|
50
|
+
- **New doc `docs/authentication.md`** — the built-in `/auth` surface and how to
|
|
51
|
+
override framework internals (widen `RegisterDto` to accept e.g. `name`, extend
|
|
52
|
+
`AuthService`, swap a Passport strategy), wired at the same prefix in `AppModule`.
|
|
53
|
+
|
|
54
|
+
## [0.1.121-beta.14] — unreleased
|
|
55
|
+
|
|
56
|
+
**Library / types.** `RolePermissions.relations` is now usable in a properly
|
|
57
|
+
typed `PermissionsConfigType` (no `as any`) — the catch-all index signature no
|
|
58
|
+
longer collides with the `relations` key. Guarded by a type-contract test. The
|
|
59
|
+
boot validator now takes `PermissionsConfigType` directly. No runtime change.
|
|
60
|
+
|
|
34
61
|
## [0.1.121-beta.13] — unreleased
|
|
35
62
|
|
|
36
63
|
**Library.** **Relation-scoped `connect` rules.** A `connect` rule can now be
|
|
@@ -70,7 +70,7 @@ export type RolePermissions<M extends ModelKey<RuntimeClient> = ModelKey<Runtime
|
|
|
70
70
|
} & {
|
|
71
71
|
relations?: RelationConnectMap;
|
|
72
72
|
} & {
|
|
73
|
-
[custom: string]: 'ALL' | {
|
|
73
|
+
[custom: string]: 'ALL' | RelationConnectMap | {
|
|
74
74
|
conditions?: unknown | unknown[];
|
|
75
75
|
setUserIdField?: string;
|
|
76
76
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"permissionsConfigTypes.d.ts","sourceRoot":"","sources":["../../../src/common/config/permissionsConfigTypes.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAC,MAAM,EAAE,YAAY,IAAI,aAAa,EAAC,MAAM,gBAAgB,CAAC;AAC1E,OAAO,EAAC,SAAS,EAAC,MAAM,gCAAgC,CAAC;AAEzD,eAAO,MAAM,qBAAqB,EAAE;IAChC,OAAO,EAAE,GAAG,CAAC;CAGhB,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAIlD,CAAC;AAEF,gEAAgE;AAChE,KAAK,aAAa,CAAC,CAAC,IAAI;KACnB,CAAC,IAAI,MAAM,CAAC,GACb,CAAC,CAAC,CAAC,CAAC,SAAS;QAAC,QAAQ,EAAE,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,GAAG,CAAA;KAAC,GAAG,CAAC,GAAG,KAAK;CAC/D,CAAC,MAAM,CAAC,CAAC,GAAG,MAAM,CAAC;AAEpB,mDAAmD;AACnD,KAAK,iBAAiB,CAAC,CAAC,IAAI,aAAa,CAAC,CAAC,CAAC,CAAC;AAE7C,8DAA8D;AAC9D,KAAK,QAAQ,CAAC,CAAC,SAAS,aAAa,GAAG,aAAa,IACjD,iBAAiB,CAAC,CAAC,CAAC,GAAG,UAAU,CAAC,iBAAiB,CAAC,CAAC,CAAC,CAAC,CAAC;AAE5D,4EAA4E;AAC5E,KAAK,cAAc,CACf,CAAC,SAAS,aAAa,EACvB,CAAC,SAAS,QAAQ,CAAC,CAAC,CAAC,IAErB,CAAC,SAAS,iBAAiB,CAAC,CAAC,CAAC,GAAG,CAAC,GAC5B,CAAC,SAAS,UAAU,CAAC,iBAAiB,CAAC,CAAC,CAAC,CAAC,GAAG,YAAY,CAAC,CAAC,CAAC,GAAG,iBAAiB,CAAC,CAAC,CAAC,GAC/E,KAAK,CAAC;AAEpB,oDAAoD;AACpD,KAAK,WAAW,CACZ,CAAC,SAAS,aAAa,EACvB,CAAC,SAAS,QAAQ,CAAC,CAAC,CAAC,IACrB,CAAC,CAAC,cAAc,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;AAE5B,0CAA0C;AAC1C,KAAK,UAAU,CACX,CAAC,SAAS,aAAa,EACvB,CAAC,SAAS,QAAQ,CAAC,CAAC,CAAC,IACrB;KACC,CAAC,IAAI,MAAM,WAAW,CAAC,CAAC,EAAE,CAAC,CAAC,GAC7B,WAAW,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,GAAG,GAAG,CAAC,GAAG,KAAK;CACnE,CAAC,MAAM,WAAW,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC;AAEpC,iEAAiE;AACjE,KAAK,aAAa,CACd,CAAC,SAAS,aAAa,EACvB,CAAC,SAAS,QAAQ,CAAC,CAAC,CAAC,IACrB,OAAO,CAAC,UAAU,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC;AAEzC,oFAAoF;AACpF,KAAK,MAAM,CACP,CAAC,SAAS,aAAa,EACvB,CAAC,SAAS,QAAQ,CAAC,CAAC,CAAC,EACrB,CAAC,SAAS,aAAa,CAAC,CAAC,EAAE,CAAC,CAAC,IAC7B,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;AAEtC,4DAA4D;AAC5D,KAAK,OAAO,CACR,CAAC,SAAS,aAAa,EACvB,CAAC,SAAS,QAAQ,CAAC,CAAC,CAAC,EACrB,CAAC,SAAS,aAAa,CAAC,CAAC,EAAE,CAAC,CAAC,IAE7B,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,SAAS;IAAC,KAAK,CAAC,EAAE,MAAM,CAAC,CAAA;CAAC,GAAG,CAAC,GACzC,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,SAAS;IAAC,KAAK,EAAE,MAAM,CAAC,CAAA;CAAC,GAAG,CAAC,GACxC,KAAK,CAAC;AAElB,0DAA0D;AAC1D,KAAK,gBAAgB,CACjB,CAAC,SAAS,aAAa,EACvB,CAAC,SAAS,QAAQ,CAAC,CAAC,CAAC,IACrB;KACC,CAAC,IAAI,aAAa,CAAC,CAAC,EAAE,CAAC,CAAC,GACzB,OAAO,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,SAAS,KAAK,GAAG,KAAK,GAAG,CAAC;CAC7C,CAAC,aAAa,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC;AAEhC,6DAA6D;AAE7D,MAAM,MAAM,eAAe,CACvB,CAAC,SAAS,QAAQ,CAAC,aAAa,CAAC,EACjC,CAAC,SAAS,gBAAgB,CAAC,aAAa,EAAE,CAAC,CAAC,IAC5C,OAAO,CAAC,aAAa,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;AAEjC,MAAM,WAAW,gBAAgB,CAC7B,CAAC,SAAS,QAAQ,CAAC,aAAa,CAAC,GAAG,QAAQ,CAAC,aAAa,CAAC,EAC3D,CAAC,SAAS,gBAAgB,CAAC,aAAa,EAAE,CAAC,CAAC,GAAG,gBAAgB,CAAC,aAAa,EAAE,CAAC,CAAC;IAEjF,UAAU,EAAE,eAAe,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,eAAe,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC;IAC5D,cAAc,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,mBAAmB;IAChC,OAAO,EAAE,KAAK,GAAG;QAAE,UAAU,CAAC,EAAE,OAAO,GAAG,OAAO,EAAE,CAAA;KAAE,CAAC;CACzD;AACD,MAAM,MAAM,kBAAkB,GAAG;IAAE,CAAC,aAAa,EAAE,MAAM,GAAG,mBAAmB,CAAA;CAAE,CAAC;AAElF,MAAM,MAAM,eAAe,CACvB,CAAC,SAAS,QAAQ,CAAC,aAAa,CAAC,GAAG,QAAQ,CAAC,aAAa,CAAC,IAE3D;KACK,CAAC,IAAI,gBAAgB,CAAC,aAAa,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,KAAK,GAAG,gBAAgB,CAAC,CAAC,EAAE,CAAC,CAAC;CAC7E,GAAG;IACA,SAAS,CAAC,EAAE,kBAAkB,CAAC;CAClC,GAAG;
|
|
1
|
+
{"version":3,"file":"permissionsConfigTypes.d.ts","sourceRoot":"","sources":["../../../src/common/config/permissionsConfigTypes.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -6,6 +6,18 @@ export * from './graphql/graphql.module';
|
|
|
6
6
|
export * from './graphql/generic.resolver';
|
|
7
7
|
export * from './tasks/session-cleanup.service';
|
|
8
8
|
export * from './modules/auth/auth.module';
|
|
9
|
+
export * from './modules/auth/auth.controller';
|
|
10
|
+
export * from './modules/auth/auth.service';
|
|
11
|
+
export * from './modules/auth/dto/register.dto';
|
|
12
|
+
export * from './modules/auth/dto/user.dto';
|
|
13
|
+
export * from './modules/auth/auth-field.decorator';
|
|
14
|
+
export * from './modules/auth/local.strategy';
|
|
15
|
+
export * from './modules/auth/local-auth.guard';
|
|
16
|
+
export * from './modules/auth/jwt.strategy';
|
|
17
|
+
export * from './modules/auth/refresh-token.strategy';
|
|
18
|
+
export * from './modules/auth/refresh-token.guard';
|
|
19
|
+
export * from './modules/auth/session/session-serializer';
|
|
20
|
+
export * from './modules/auth/session/session-auth.guard';
|
|
9
21
|
export * from './modules/auth/session/session-store';
|
|
10
22
|
export * from './common/guards/rbac.guard';
|
|
11
23
|
export * from './common/guards/user-population.guard';
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,4BAA4B,CAAC;AAC3C,cAAc,6BAA6B,CAAC;AAC5C,cAAc,gCAAgC,CAAC;AAC/C,cAAc,yBAAyB,CAAC;AACxC,cAAc,0BAA0B,CAAC;AACzC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,iCAAiC,CAAC;AAChD,cAAc,4BAA4B,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,4BAA4B,CAAC;AAC3C,cAAc,6BAA6B,CAAC;AAC5C,cAAc,gCAAgC,CAAC;AAC/C,cAAc,yBAAyB,CAAC;AACxC,cAAc,0BAA0B,CAAC;AACzC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,iCAAiC,CAAC;AAChD,cAAc,4BAA4B,CAAC;AAI3C,cAAc,gCAAgC,CAAC;AAC/C,cAAc,6BAA6B,CAAC;AAC5C,cAAc,iCAAiC,CAAC;AAChD,cAAc,6BAA6B,CAAC;AAC5C,cAAc,qCAAqC,CAAC;AACpD,cAAc,+BAA+B,CAAC;AAC9C,cAAc,iCAAiC,CAAC;AAChD,cAAc,6BAA6B,CAAC;AAC5C,cAAc,uCAAuC,CAAC;AACtD,cAAc,oCAAoC,CAAC;AACnD,cAAc,2CAA2C,CAAC;AAC1D,cAAc,2CAA2C,CAAC;AAC1D,cAAc,sCAAsC,CAAC;AACrD,cAAc,4BAA4B,CAAC;AAC3C,cAAc,uCAAuC,CAAC;AACtD,cAAc,yBAAyB,CAAC;AACxC,cAAc,0CAA0C,CAAC;AACzD,cAAc,wCAAwC,CAAC;AACvD,cAAc,iCAAiC,CAAC;AAChD,cAAc,6CAA6C,CAAC;AAC5D,cAAc,oBAAoB,CAAC;AACnC,cAAc,mCAAmC,CAAC;AAClD,cAAc,2CAA2C,CAAC;AAC1D,cAAc,wCAAwC,CAAC;AACvD,cAAc,+CAA+C,CAAC;AAC9D,cAAc,uCAAuC,CAAC;AACtD,cAAc,oCAAoC,CAAC;AACnD,cAAc,0CAA0C,CAAC;AACzD,cAAc,oCAAoC,CAAC;AACnD,cAAc,4BAA4B,CAAC;AAC3C,cAAc,wCAAwC,CAAC;AACvD,cAAc,oCAAoC,CAAC;AACnD,cAAc,+BAA+B,CAAC;AAC9C,cAAc,qCAAqC,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -22,6 +22,21 @@ __exportStar(require("./graphql/graphql.module"), exports);
|
|
|
22
22
|
__exportStar(require("./graphql/generic.resolver"), exports);
|
|
23
23
|
__exportStar(require("./tasks/session-cleanup.service"), exports);
|
|
24
24
|
__exportStar(require("./modules/auth/auth.module"), exports);
|
|
25
|
+
// Auth building blocks — exported so consumers can extend/override them
|
|
26
|
+
// (custom AuthController, widened RegisterDto, custom Passport strategy) without
|
|
27
|
+
// deep-importing from `dist/`. See docs/authentication.md.
|
|
28
|
+
__exportStar(require("./modules/auth/auth.controller"), exports);
|
|
29
|
+
__exportStar(require("./modules/auth/auth.service"), exports);
|
|
30
|
+
__exportStar(require("./modules/auth/dto/register.dto"), exports);
|
|
31
|
+
__exportStar(require("./modules/auth/dto/user.dto"), exports);
|
|
32
|
+
__exportStar(require("./modules/auth/auth-field.decorator"), exports);
|
|
33
|
+
__exportStar(require("./modules/auth/local.strategy"), exports);
|
|
34
|
+
__exportStar(require("./modules/auth/local-auth.guard"), exports);
|
|
35
|
+
__exportStar(require("./modules/auth/jwt.strategy"), exports);
|
|
36
|
+
__exportStar(require("./modules/auth/refresh-token.strategy"), exports);
|
|
37
|
+
__exportStar(require("./modules/auth/refresh-token.guard"), exports);
|
|
38
|
+
__exportStar(require("./modules/auth/session/session-serializer"), exports);
|
|
39
|
+
__exportStar(require("./modules/auth/session/session-auth.guard"), exports);
|
|
25
40
|
__exportStar(require("./modules/auth/session/session-store"), exports);
|
|
26
41
|
__exportStar(require("./common/guards/rbac.guard"), exports);
|
|
27
42
|
__exportStar(require("./common/guards/user-population.guard"), exports);
|
|
@@ -1,3 +1,14 @@
|
|
|
1
|
+
import { DynamicModule } from '@nestjs/common';
|
|
1
2
|
export declare class AuthModule {
|
|
3
|
+
/**
|
|
4
|
+
* For overriding the auth endpoints. `AuthModule.forRoot({ controller: false })`
|
|
5
|
+
* imports every auth provider globally (AuthService, Jwt, Passport, strategies,
|
|
6
|
+
* guards) but does NOT register the built-in `AuthController` — so you can
|
|
7
|
+
* register your OWN controller (e.g. one that `extends AuthController`) at the
|
|
8
|
+
* same `/auth` prefix with no duplicate route. See docs/authentication.md.
|
|
9
|
+
*/
|
|
10
|
+
static forRoot(options?: {
|
|
11
|
+
controller?: boolean;
|
|
12
|
+
}): DynamicModule;
|
|
2
13
|
}
|
|
3
14
|
//# sourceMappingURL=auth.module.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auth.module.d.ts","sourceRoot":"","sources":["../../../src/modules/auth/auth.module.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"auth.module.d.ts","sourceRoot":"","sources":["../../../src/modules/auth/auth.module.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,aAAa,EAAiB,MAAM,gBAAgB,CAAC;AAgC7D,qBAOa,UAAU;IACnB;;;;;;OAMG;IACH,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE;QAAC,UAAU,CAAC,EAAE,OAAO,CAAA;KAAC,GAAG,aAAa;CAUlE"}
|
|
@@ -5,6 +5,7 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
|
|
|
5
5
|
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
6
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
7
|
};
|
|
8
|
+
var AuthModule_1;
|
|
8
9
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
10
|
exports.AuthModule = void 0;
|
|
10
11
|
const common_1 = require("@nestjs/common");
|
|
@@ -20,22 +21,48 @@ const jwt_auth_guard_1 = require("./jwt-auth.guard");
|
|
|
20
21
|
const authenticated_guard_1 = require("./authenticated.guard");
|
|
21
22
|
const jwt_strategy_1 = require("./jwt.strategy");
|
|
22
23
|
const refresh_token_strategy_1 = require("./refresh-token.strategy");
|
|
23
|
-
|
|
24
|
+
// Shared so the static @Module (default: registers AuthController) and the
|
|
25
|
+
// forRoot() hook (optionally skips it) provide identical wiring.
|
|
26
|
+
const authImports = [
|
|
27
|
+
config_1.ConfigModule,
|
|
28
|
+
user_module_1.UserModule,
|
|
29
|
+
passport_1.PassportModule.register({ session: true }),
|
|
30
|
+
jwt_1.JwtModule.registerAsync({
|
|
31
|
+
imports: [config_1.ConfigModule],
|
|
32
|
+
useFactory: async (config) => ({
|
|
33
|
+
secret: config.get('JWT_SECRET'),
|
|
34
|
+
signOptions: { expiresIn: config.get('JWT_EXPIRES_IN', '60m') },
|
|
35
|
+
}),
|
|
36
|
+
inject: [config_1.ConfigService],
|
|
37
|
+
}),
|
|
38
|
+
];
|
|
39
|
+
const authProviders = [auth_service_1.AuthService, local_strategy_1.LocalStrategy, session_serializer_1.SessionSerializer, jwt_strategy_1.JwtStrategy, jwt_auth_guard_1.JwtAuthGuard, authenticated_guard_1.AuthenticatedGuard, refresh_token_strategy_1.RefreshTokenStrategy];
|
|
40
|
+
const authExports = [auth_service_1.AuthService, jwt_auth_guard_1.JwtAuthGuard, authenticated_guard_1.AuthenticatedGuard, jwt_1.JwtModule];
|
|
41
|
+
let AuthModule = exports.AuthModule = AuthModule_1 = class AuthModule {
|
|
42
|
+
/**
|
|
43
|
+
* For overriding the auth endpoints. `AuthModule.forRoot({ controller: false })`
|
|
44
|
+
* imports every auth provider globally (AuthService, Jwt, Passport, strategies,
|
|
45
|
+
* guards) but does NOT register the built-in `AuthController` — so you can
|
|
46
|
+
* register your OWN controller (e.g. one that `extends AuthController`) at the
|
|
47
|
+
* same `/auth` prefix with no duplicate route. See docs/authentication.md.
|
|
48
|
+
*/
|
|
49
|
+
static forRoot(options) {
|
|
50
|
+
return {
|
|
51
|
+
module: AuthModule_1,
|
|
52
|
+
global: true,
|
|
53
|
+
imports: authImports,
|
|
54
|
+
providers: authProviders,
|
|
55
|
+
controllers: options?.controller === false ? [] : [auth_controller_1.AuthController],
|
|
56
|
+
exports: authExports,
|
|
57
|
+
};
|
|
58
|
+
}
|
|
24
59
|
};
|
|
25
|
-
exports.AuthModule = AuthModule = __decorate([
|
|
60
|
+
exports.AuthModule = AuthModule = AuthModule_1 = __decorate([
|
|
26
61
|
(0, common_1.Global)(),
|
|
27
62
|
(0, common_1.Module)({
|
|
28
|
-
imports:
|
|
29
|
-
|
|
30
|
-
imports: [config_1.ConfigModule],
|
|
31
|
-
useFactory: async (config) => ({
|
|
32
|
-
secret: config.get('JWT_SECRET'),
|
|
33
|
-
signOptions: { expiresIn: config.get('JWT_EXPIRES_IN', '60m') },
|
|
34
|
-
}),
|
|
35
|
-
inject: [config_1.ConfigService],
|
|
36
|
-
}),],
|
|
37
|
-
providers: [auth_service_1.AuthService, local_strategy_1.LocalStrategy, session_serializer_1.SessionSerializer, jwt_strategy_1.JwtStrategy, jwt_auth_guard_1.JwtAuthGuard, authenticated_guard_1.AuthenticatedGuard, refresh_token_strategy_1.RefreshTokenStrategy],
|
|
63
|
+
imports: authImports,
|
|
64
|
+
providers: authProviders,
|
|
38
65
|
controllers: [auth_controller_1.AuthController],
|
|
39
|
-
exports:
|
|
66
|
+
exports: authExports,
|
|
40
67
|
})
|
|
41
68
|
], AuthModule);
|
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
*
|
|
10
10
|
* Pure and schema-only (no database), so it is independently unit-testable.
|
|
11
11
|
*/
|
|
12
|
+
import type { PermissionsConfigType } from '../common/config/permissionsConfigTypes';
|
|
12
13
|
export type RelationKind = 'belongsTo' | 'hasMany';
|
|
13
14
|
export interface RelationMeta {
|
|
14
15
|
/** The relation navigation field name on the owning model. */
|
|
@@ -46,5 +47,5 @@ export interface ValidationIssue {
|
|
|
46
47
|
* - **warning** `missing-connect-optional` — an *optional* belongsTo FK's target
|
|
47
48
|
* has no `connect` rule for the role. Only denied when the payload sets it.
|
|
48
49
|
*/
|
|
49
|
-
export declare function validatePermissionsConfig(config:
|
|
50
|
+
export declare function validatePermissionsConfig(config: PermissionsConfigType, relations: SchemaRelations): ValidationIssue[];
|
|
50
51
|
//# sourceMappingURL=permissions-validator.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"permissions-validator.d.ts","sourceRoot":"","sources":["../../src/prisma/permissions-validator.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;
|
|
1
|
+
{"version":3,"file":"permissions-validator.d.ts","sourceRoot":"","sources":["../../src/prisma/permissions-validator.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,yCAAyC,CAAC;AAErF,MAAM,MAAM,YAAY,GAAG,WAAW,GAAG,SAAS,CAAC;AAEnD,MAAM,WAAW,YAAY;IACzB,8DAA8D;IAC9D,KAAK,EAAE,MAAM,CAAC;IACd,iEAAiE;IACjE,KAAK,EAAE,MAAM,CAAC;IACd,4DAA4D;IAC5D,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,UAAU,EAAE,OAAO,CAAC;IACpB,IAAI,EAAE,YAAY,CAAC;IACnB,wGAAwG;IACxG,UAAU,CAAC,EAAE,OAAO,CAAC;CACxB;AAED,gEAAgE;AAChE,MAAM,MAAM,eAAe,GAAG,MAAM,CAAC,MAAM,EAAE,YAAY,EAAE,CAAC,CAAC;AAE7D,MAAM,MAAM,UAAU,GAAG,OAAO,GAAG,SAAS,CAAC;AAE7C,MAAM,MAAM,SAAS,GACf,8BAA8B,GAC9B,0BAA0B,GAC1B,iBAAiB,GACjB,uBAAuB,GACvB,kBAAkB,CAAC;AAEzB,MAAM,WAAW,eAAe;IAC5B,KAAK,EAAE,UAAU,CAAC;IAClB,IAAI,EAAE,SAAS,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACnB;AAmBD;;;;;;;;;;;;GAYG;AACH,wBAAgB,yBAAyB,CACrC,MAAM,EAAE,qBAAqB,EAC7B,SAAS,EAAE,eAAe,GAC3B,eAAe,EAAE,CAmHnB"}
|
|
@@ -1,15 +1,4 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
/**
|
|
3
|
-
* Static validation of a `PermissionsConfig` against the Prisma schema.
|
|
4
|
-
*
|
|
5
|
-
* Runs at boot (in the PrismaService constructor). It encodes the Option A
|
|
6
|
-
* authorization model: a create condition judges a model's own scalar fields
|
|
7
|
-
* only, and every foreign-key reference a create establishes is authorized by
|
|
8
|
-
* the target model's `connect` rule. Misconfigurations that would break at
|
|
9
|
-
* runtime are surfaced here — errors reject boot, warnings are advisory.
|
|
10
|
-
*
|
|
11
|
-
* Pure and schema-only (no database), so it is independently unit-testable.
|
|
12
|
-
*/
|
|
13
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
14
3
|
exports.validatePermissionsConfig = void 0;
|
|
15
4
|
/** Collects condition keys that name a relation (skips AND/OR/NOT, which recurse). */
|
|
@@ -46,9 +35,12 @@ function findRelationKeys(cond, relationFields, found = new Set()) {
|
|
|
46
35
|
*/
|
|
47
36
|
function validatePermissionsConfig(config, relations) {
|
|
48
37
|
const issues = [];
|
|
38
|
+
// Iterate the typed config structurally — model/role keys are dynamic, and
|
|
39
|
+
// condition/rule shapes are inspected at runtime.
|
|
40
|
+
const cfg = (config || {});
|
|
49
41
|
const byModel = {};
|
|
50
|
-
for (const m of Object.keys(
|
|
51
|
-
byModel[m.toLowerCase()] =
|
|
42
|
+
for (const m of Object.keys(cfg))
|
|
43
|
+
byModel[m.toLowerCase()] = cfg[m];
|
|
52
44
|
const hasConnectRule = (targetModel, role) => {
|
|
53
45
|
const rules = byModel[targetModel.toLowerCase()]?.[role];
|
|
54
46
|
return !!rules && rules.connect !== undefined && rules.connect !== null;
|
|
@@ -58,8 +50,8 @@ function validatePermissionsConfig(config, relations) {
|
|
|
58
50
|
const hasRelationConnect = (sourceRules, field) => !!sourceRules?.relations?.[field]?.connect;
|
|
59
51
|
const canCreate = (rules) => !!rules && (rules.create !== undefined || rules.createMany !== undefined);
|
|
60
52
|
const canUpdate = (rules) => !!rules && (rules.update !== undefined || rules.updateMany !== undefined);
|
|
61
|
-
for (const modelKey of Object.keys(
|
|
62
|
-
const roles =
|
|
53
|
+
for (const modelKey of Object.keys(cfg)) {
|
|
54
|
+
const roles = cfg[modelKey] || {};
|
|
63
55
|
const rels = relations[modelKey.toLowerCase()] || [];
|
|
64
56
|
const belongsTo = rels.filter((r) => r.kind === 'belongsTo' && r.referencingColumn);
|
|
65
57
|
const relationFieldNames = new Set(rels.map((r) => r.field));
|
package/docs/README.md
CHANGED
|
@@ -7,6 +7,7 @@ Authoritative usage documentation for `@appxdigital/appx-core`. **This folder is
|
|
|
7
7
|
- **[permissions.md](./permissions.md)** — the authorization model: the `@Permission` and `@ExposeModels` decorators, the `permissions.config.ts` shape, roles/actions, row-level `conditions`, field-level control, action fallbacks, and the `GUEST` (unauthenticated) flow.
|
|
8
8
|
- **[dtos.md](./dtos.md)** — the generated CRUD validation DTOs: their two-file structure, **how to remove a field** (`OmitType` / `@NoWrite`), how to add validation, and why nested relation writes don't belong on generic CRUD.
|
|
9
9
|
- **[data-access.md](./data-access.md)** — how you talk to the database: the Prisma proxy (`prisma.model.*`), how ABAC filtering and field omission are enforced on every call, the redirected single-record methods, relation behaviour, bypass hatches, and transactions.
|
|
10
|
+
- **[authentication.md](./authentication.md)** — the built-in `/auth` surface, and **how to override framework internals** (extend the exported `AuthController`/`AuthService`/`RegisterDto`/Passport strategies and register your own at the same prefix via `AuthModule.forRoot({ controller: false })`) — e.g. adding `name` to registration.
|
|
10
11
|
- **[graphql.md](./graphql.md)** — the **read-only** GraphQL API generated from your schema: queries, nested selections, and how ABAC filters them.
|
|
11
12
|
- **[limitations.md](./limitations.md)** — **known limitations and features that are NOT ready for use** (e.g. `aggregate`, GraphQL writes). Read this before relying on any method not covered in the guides above.
|
|
12
13
|
|
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
# Authentication & overriding framework internals
|
|
2
|
+
|
|
3
|
+
The framework ships a working auth surface. When you need to change part of it —
|
|
4
|
+
add a field to registration, add endpoints, swap a Passport strategy — you don't
|
|
5
|
+
fork it: you **extend the exported classes and register your own versions**. This
|
|
6
|
+
page shows the pattern (auth is the main example, but it applies to any exported
|
|
7
|
+
framework class).
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## What `AuthModule` provides
|
|
12
|
+
|
|
13
|
+
Importing `AuthModule` registers, under the `/auth` prefix:
|
|
14
|
+
|
|
15
|
+
| Route | Guard | Body |
|
|
16
|
+
|---|---|---|
|
|
17
|
+
| `POST /auth/register` | — | `RegisterDto` (`email`, `password`) |
|
|
18
|
+
| `POST /auth/login` | `LocalAuthGuard` | credentials |
|
|
19
|
+
| `POST /auth/login/jwt` | `LocalAuthGuard` | credentials → tokens |
|
|
20
|
+
| `POST /auth/refresh` | `RefreshTokenGuard` | refresh token |
|
|
21
|
+
| `POST /auth/logout` · `logout/jwt` | `AuthenticatedGuard` | — |
|
|
22
|
+
| `GET /auth/me`, `GET/POST /auth/sessions…` | `AuthenticatedGuard` | — |
|
|
23
|
+
|
|
24
|
+
plus the providers (all **global**): `AuthService`, the Passport strategies
|
|
25
|
+
(`LocalStrategy`, `JwtStrategy`, `RefreshTokenStrategy`), the guards
|
|
26
|
+
(`LocalAuthGuard`, `JwtAuthGuard`, `AuthenticatedGuard`, `RefreshTokenGuard`,
|
|
27
|
+
`SessionAuthGuard`), and `SessionSerializer`.
|
|
28
|
+
|
|
29
|
+
**Registration is intentionally narrow.** `RegisterDto` accepts only `email` +
|
|
30
|
+
`password`, and `AuthService.register` creates the user with `BYPASS_FILTERING`
|
|
31
|
+
(it's an unauthenticated flow, so ABAC create-enforcement can't gate it). The
|
|
32
|
+
`RegisterDto` whitelist is therefore the *only* thing controlling which fields a
|
|
33
|
+
sign-up may set — which is exactly why widening it is a deliberate override, not
|
|
34
|
+
a config toggle.
|
|
35
|
+
|
|
36
|
+
All of these are exported from the package root — **import from
|
|
37
|
+
`@appxdigital/appx-core`, never from `@appxdigital/appx-core/dist/...`** (deep
|
|
38
|
+
paths are internal and can move between versions):
|
|
39
|
+
|
|
40
|
+
```ts
|
|
41
|
+
import {
|
|
42
|
+
AuthModule, AuthController, AuthService,
|
|
43
|
+
RegisterDto, UserDto, AuthField,
|
|
44
|
+
LocalStrategy, JwtStrategy, RefreshTokenStrategy,
|
|
45
|
+
} from '@appxdigital/appx-core';
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
---
|
|
49
|
+
|
|
50
|
+
## The override pattern
|
|
51
|
+
|
|
52
|
+
To replace or extend an auth endpoint **at the same `/auth` prefix**:
|
|
53
|
+
|
|
54
|
+
1. **Extend** the framework class (controller / service / strategy).
|
|
55
|
+
2. Put your version in **your own module**.
|
|
56
|
+
3. Import **`AuthModule.forRoot({ controller: false })`** — this keeps every auth
|
|
57
|
+
provider global but drops the built-in `AuthController`, so *your* controller
|
|
58
|
+
owns `/auth` with no duplicate route.
|
|
59
|
+
4. Register your module in `AppModule` (in place of a bare `AuthModule`).
|
|
60
|
+
|
|
61
|
+
```ts
|
|
62
|
+
// app.module.ts
|
|
63
|
+
@Module({
|
|
64
|
+
imports: [
|
|
65
|
+
AppxCoreModule.forRoot(PermissionsConfig),
|
|
66
|
+
AuthModule.forRoot({ controller: false }), // providers only, no built-in controller
|
|
67
|
+
MyAuthModule, // your controller/service live here
|
|
68
|
+
// …
|
|
69
|
+
],
|
|
70
|
+
})
|
|
71
|
+
export class AppModule {}
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
```ts
|
|
75
|
+
// my-auth.module.ts
|
|
76
|
+
@Module({
|
|
77
|
+
controllers: [MyAuthController],
|
|
78
|
+
providers: [/* MyAuthService, MyLocalStrategy, … as needed */],
|
|
79
|
+
})
|
|
80
|
+
export class MyAuthModule {}
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
> **Why `forRoot({ controller: false })`?** If you import the plain `AuthModule`
|
|
84
|
+
> *and* register your own `/auth` controller, you get two handlers for the same
|
|
85
|
+
> routes. Skipping the built-in controller — while keeping its providers — is what
|
|
86
|
+
> lets your controller take over cleanly. (Importing the plain `AuthModule` is
|
|
87
|
+
> still correct when you're *not* overriding the controller.)
|
|
88
|
+
|
|
89
|
+
---
|
|
90
|
+
|
|
91
|
+
## Recipe 1 — add a field to registration (e.g. `name`)
|
|
92
|
+
|
|
93
|
+
Extend `RegisterDto`, then override the inherited `register` handler:
|
|
94
|
+
|
|
95
|
+
```ts
|
|
96
|
+
// register-local.dto.ts
|
|
97
|
+
import { RegisterDto } from '@appxdigital/appx-core';
|
|
98
|
+
import { IsOptional, IsString } from 'class-validator';
|
|
99
|
+
|
|
100
|
+
export class RegisterLocalDto extends RegisterDto {
|
|
101
|
+
@IsOptional()
|
|
102
|
+
@IsString()
|
|
103
|
+
name?: string;
|
|
104
|
+
}
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
```ts
|
|
108
|
+
// my-auth.controller.ts
|
|
109
|
+
import { Body, Controller, Post } from '@nestjs/common';
|
|
110
|
+
import { AuthController } from '@appxdigital/appx-core';
|
|
111
|
+
import { RegisterLocalDto } from './register-local.dto';
|
|
112
|
+
|
|
113
|
+
@Controller('auth')
|
|
114
|
+
export class MyAuthController extends AuthController {
|
|
115
|
+
@Post('register')
|
|
116
|
+
async register(@Body() dto: RegisterLocalDto) {
|
|
117
|
+
return this.authService.register(dto); // authService is `protected` on AuthController
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
`AuthService.register` spreads the DTO straight into the user create, so `name`
|
|
123
|
+
persists (your `User` model must have the column). Everything else on
|
|
124
|
+
`AuthController` — login, refresh, sessions — is inherited unchanged. The global
|
|
125
|
+
validation pipe now validates the body against `RegisterLocalDto`, so `name` is
|
|
126
|
+
accepted and any *other* unknown field still `400`s.
|
|
127
|
+
|
|
128
|
+
> Keep registration a **narrow allowlist** — only add fields a self-service
|
|
129
|
+
> sign-up should legitimately set. Never widen it to privileged columns (`role`,
|
|
130
|
+
> tenant, ownership ids); mark those `/// @NoWrite` and set them server-side.
|
|
131
|
+
|
|
132
|
+
---
|
|
133
|
+
|
|
134
|
+
## Recipe 2 — extend the service (add methods / change behaviour)
|
|
135
|
+
|
|
136
|
+
Extend `AuthService` and forward its constructor. Its signature is
|
|
137
|
+
`(userService, prisma, jwtService, configService)`:
|
|
138
|
+
|
|
139
|
+
```ts
|
|
140
|
+
import { Injectable } from '@nestjs/common';
|
|
141
|
+
import { AuthService, PrismaService } from '@appxdigital/appx-core';
|
|
142
|
+
import { UserService } from '../user/user.service';
|
|
143
|
+
import { ConfigService } from '@nestjs/config';
|
|
144
|
+
import { JwtService } from '@nestjs/jwt';
|
|
145
|
+
|
|
146
|
+
@Injectable()
|
|
147
|
+
export class MyAuthService extends AuthService {
|
|
148
|
+
constructor(
|
|
149
|
+
userService: UserService,
|
|
150
|
+
prisma: PrismaService,
|
|
151
|
+
jwtService: JwtService,
|
|
152
|
+
configService: ConfigService,
|
|
153
|
+
) {
|
|
154
|
+
super(userService, prisma, jwtService, configService);
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
async handleForgotPassword(email: string) { /* … */ }
|
|
158
|
+
}
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
Provide `MyAuthService` in your module and inject it in your controller
|
|
162
|
+
(`super(myAuthService)` if the controller extends `AuthController`). Because you
|
|
163
|
+
imported `AuthModule.forRoot({ controller: false })`, `UserService`, `JwtService`,
|
|
164
|
+
`PrismaService`, and `ConfigService` are all already available to inject.
|
|
165
|
+
|
|
166
|
+
---
|
|
167
|
+
|
|
168
|
+
## Recipe 3 — override a Passport strategy
|
|
169
|
+
|
|
170
|
+
The built-in `LocalStrategy` reads the username/password field names from
|
|
171
|
+
`@AuthField(...)` metadata on `UserDto` and delegates to
|
|
172
|
+
`AuthService.validateUser`. To change credential validation, extend it (or
|
|
173
|
+
`JwtStrategy` / `RefreshTokenStrategy`) and provide your version:
|
|
174
|
+
|
|
175
|
+
```ts
|
|
176
|
+
import { Injectable } from '@nestjs/common';
|
|
177
|
+
import { LocalStrategy } from '@appxdigital/appx-core';
|
|
178
|
+
|
|
179
|
+
@Injectable()
|
|
180
|
+
export class MyLocalStrategy extends LocalStrategy {
|
|
181
|
+
async validate(username: string, password: string) {
|
|
182
|
+
// custom checks, then fall back to the framework behaviour:
|
|
183
|
+
return super.validate(username, password);
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
```ts
|
|
189
|
+
@Module({
|
|
190
|
+
controllers: [MyAuthController],
|
|
191
|
+
providers: [MyLocalStrategy], // Passport picks up the last-registered strategy of this name
|
|
192
|
+
})
|
|
193
|
+
export class MyAuthModule {}
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
> Passport registers strategies by name. Providing your own `LocalStrategy`
|
|
197
|
+
> subclass in your module (with `AuthModule.forRoot({ controller: false })` for
|
|
198
|
+
> the rest) makes yours the active `local` strategy.
|
|
199
|
+
|
|
200
|
+
---
|
|
201
|
+
|
|
202
|
+
## The general principle
|
|
203
|
+
|
|
204
|
+
This isn't auth-specific. Every framework class you might need to specialise is
|
|
205
|
+
exported from `@appxdigital/appx-core`. To override inner functionality:
|
|
206
|
+
|
|
207
|
+
1. **Extend** the exported class.
|
|
208
|
+
2. **Provide** your subclass in your own module (a subclass provider shadows the
|
|
209
|
+
base where you inject it).
|
|
210
|
+
3. When the framework module would *also* register the thing you're replacing
|
|
211
|
+
(a controller, a route), import it in a mode that omits that piece — e.g.
|
|
212
|
+
`AuthModule.forRoot({ controller: false })` — so there's no duplicate.
|
|
213
|
+
|
|
214
|
+
If a class you need to extend isn't exported, that's a framework gap — open it
|
|
215
|
+
rather than deep-importing from `dist/`.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@appxdigital/appx-core",
|
|
3
|
-
"version": "0.1.121-beta.
|
|
3
|
+
"version": "0.1.121-beta.15",
|
|
4
4
|
"description": "Appx Core is a library that provides a set of tools to help you build your application faster.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|