@appxdigital/appx-core 0.1.88 → 0.1.90

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.
@@ -1,18 +1,61 @@
1
- export interface FieldConditions {
2
- [key: string]: any;
3
- }
4
- export interface RolePermissions {
5
- [action: string]: 'ALL' | ActionPermission;
6
- }
7
- export interface ActionPermission {
8
- conditions: FieldConditions | FieldConditions[];
1
+ import type { Prisma, PrismaClient as RuntimeClient } from '.prisma/client';
2
+ import { Operation } from '@prisma/client/runtime/library';
3
+ export declare const PermissionPlaceholder: {
4
+ USER_ID: any;
5
+ };
6
+ /** Detect delegate keys on an arbitrary Prisma client type C */
7
+ type DelegateKeyOf<C> = {
8
+ [K in keyof C]: C[K] extends {
9
+ findMany: (...args: any[]) => any;
10
+ } ? K : never;
11
+ }[keyof C] & string;
12
+ /** Client-specific lowercase delegate key union */
13
+ type ClientDelegateKey<C> = DelegateKeyOf<C>;
14
+ /** Accept case-insensitive model keys for a given client C */
15
+ type ModelKey<C extends RuntimeClient = RuntimeClient> = ClientDelegateKey<C> | Capitalize<ClientDelegateKey<C>>;
16
+ /** Normalize to the exact lowercase delegate key of C (provably keyof C) */
17
+ type NormalizeModel<C extends RuntimeClient, M extends ModelKey<C>> = M extends ClientDelegateKey<C> ? M : M extends Capitalize<ClientDelegateKey<C>> ? Uncapitalize<M> & ClientDelegateKey<C> : never;
18
+ /** The delegate instance for a model on client C */
19
+ type DelegateFor<C extends RuntimeClient, M extends ModelKey<C>> = C[NormalizeModel<C, M>];
20
+ /** Only callable keys on that delegate */
21
+ type MethodKeys<C extends RuntimeClient, M extends ModelKey<C>> = {
22
+ [K in keyof DelegateFor<C, M>]: DelegateFor<C, M>[K] extends (...args: any[]) => any ? K : never;
23
+ }[keyof DelegateFor<C, M>] & string;
24
+ /** Restrict to Prisma operations that Prisma.Args understands */
25
+ type OperationKeys<C extends RuntimeClient, M extends ModelKey<C>> = Extract<MethodKeys<C, M>, Operation>;
26
+ /** Canonical args via Prisma helper (now K is guaranteed to be Prisma.Operation) */
27
+ type ArgsOf<C extends RuntimeClient, M extends ModelKey<C>, K extends OperationKeys<C, M>> = Prisma.Args<DelegateFor<C, M>, K>;
28
+ /** Extract the method's `where` type from canonical args */
29
+ type WhereOf<C extends RuntimeClient, M extends ModelKey<C>, K extends OperationKeys<C, M>> = ArgsOf<C, M, K> extends {
30
+ where?: infer W;
31
+ } ? W : ArgsOf<C, M, K> extends {
32
+ where: infer W;
33
+ } ? W : never;
34
+ /** Keep only operations that actually accept a `where` */
35
+ type MethodsWithWhere<C extends RuntimeClient, M extends ModelKey<C>> = {
36
+ [K in OperationKeys<C, M>]: WhereOf<C, M, K> extends never ? never : K;
37
+ }[OperationKeys<C, M>] & string;
38
+ /** ===== Adapted types (client-aware, method-aware) ===== */
39
+ export type FieldConditions<M extends ModelKey<RuntimeClient>, A extends MethodsWithWhere<RuntimeClient, M>> = WhereOf<RuntimeClient, M, A>;
40
+ export interface ActionPermission<M extends ModelKey<RuntimeClient> = ModelKey<RuntimeClient>, A extends MethodsWithWhere<RuntimeClient, M> = MethodsWithWhere<RuntimeClient, M>> {
41
+ conditions: FieldConditions<M, A> | FieldConditions<M, A>[];
9
42
  setUserIdField?: string;
10
43
  restrictedFields?: string[];
11
44
  }
12
- export interface ModelPermissions {
13
- [role: string]: RolePermissions;
14
- }
15
- export interface PermissionsConfigType {
16
- [model: string]: ModelPermissions;
17
- }
45
+ export type RolePermissions<M extends ModelKey<RuntimeClient> = ModelKey<RuntimeClient>> = {
46
+ [A in MethodsWithWhere<RuntimeClient, M>]?: 'ALL' | ActionPermission<M, A>;
47
+ } & {
48
+ [custom: string]: 'ALL' | {
49
+ conditions?: unknown | unknown[];
50
+ setUserIdField?: string;
51
+ restrictedFields?: string[];
52
+ };
53
+ };
54
+ export type ModelPermissions<M extends ModelKey<RuntimeClient> = ModelKey<RuntimeClient>> = {
55
+ [role: string]: RolePermissions<M>;
56
+ };
57
+ export type PermissionsConfigType<M extends ModelKey<RuntimeClient> = ModelKey<RuntimeClient>> = {
58
+ [model in M]?: ModelPermissions<model>;
59
+ };
60
+ export {};
18
61
  //# sourceMappingURL=permissionsConfigTypes.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"permissionsConfigTypes.d.ts","sourceRoot":"","sources":["../../../src/common/config/permissionsConfigTypes.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,eAAe;IAC5B,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC;CACtB;AAED,MAAM,WAAW,eAAe;IAC5B,CAAC,MAAM,EAAE,MAAM,GAAG,KAAK,GAAG,gBAAgB,CAAC;CAC9C;AAED,MAAM,WAAW,gBAAgB;IAC7B,UAAU,EAAE,eAAe,GAAG,eAAe,EAAE,CAAC;IAChD,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,gBAAgB,CAAC,EAAE,MAAM,EAAE,CAAC;CAC/B;AAED,MAAM,WAAW,gBAAgB;IAC7B,CAAC,IAAI,EAAE,MAAM,GAAG,eAAe,CAAC;CACnC;AAED,MAAM,WAAW,qBAAqB;IAClC,CAAC,KAAK,EAAE,MAAM,GAAG,gBAAgB,CAAC;CACrC"}
1
+ {"version":3,"file":"permissionsConfigTypes.d.ts","sourceRoot":"","sources":["../../../src/common/config/permissionsConfigTypes.ts"],"names":[],"mappings":"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"}
@@ -1,2 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.PermissionPlaceholder = void 0;
4
+ exports.PermissionPlaceholder = {
5
+ USER_ID: '$USER_ID',
6
+ };
@@ -1,2 +1,2 @@
1
- export declare const adminJsModuleCode = "\nimport {DynamicModule} from '@nestjs/common';\nimport {addBasicFilters, createActions, createPermissionHandler, dynamicImport, getAdminJSResources} from './utils';\nimport {initializeComponents} from './component-loader';\nimport {readFileSync} from 'fs';\nimport {getDMMF} from '@prisma/sdk';\nimport {PrismaService} from '@appxdigital/appx-core';\nimport {PrismaModule} from \"../prisma/prisma.module\";\n\nconst DEFAULT_ADMIN = {\n email: 'joao.duvido@appx.pt',\n password: 'password',\n};\n\nconst authenticate = async (email: string, password: string) => {\n if (email === DEFAULT_ADMIN.email && password === DEFAULT_ADMIN.password) {\n return Promise.resolve(DEFAULT_ADMIN);\n }\n return null;\n};\n\nexport async function createAdminJsModule(): Promise<DynamicModule> {\n const {default: AdminJS} = await dynamicImport('adminjs');\n const {Database, Resource} = await dynamicImport('@adminjs/prisma');\n const {AdminModule} = await dynamicImport('@adminjs/nestjs');\n const {default: importExportFeature} = await dynamicImport('@adminjs/import-export');\n const {default: passwordFeature} = await dynamicImport('@adminjs/passwords');\n const argon2 = await dynamicImport('argon2');\n\n const resources = getAdminJSResources();\n const {componentLoader, Components} = await initializeComponents();\n const schemaPath = './prisma/schema.prisma';\n const schema = readFileSync(schemaPath, 'utf-8');\n const dmmf = await getDMMF({datamodel: schema});\n\n const models = [];\n\n for (const resource of resources) {\n const model = dmmf.datamodel.models.find(\n (model) => model.name === resource.name,\n );\n\n models.push({\n model,\n options: resource.options,\n features: model.name === 'User' ? [\n passwordFeature({\n properties: {\n encryptedPassword: 'password',\n password: 'plainPassword',\n },\n hash: argon2.hash,\n componentLoader,\n }),\n ] : [],\n });\n }\n\n AdminJS.registerAdapter({Database, Resource});\n\n return AdminModule.createAdminAsync({\n imports: [PrismaModule],\n inject: [PrismaService],\n useFactory: async (prisma: PrismaService) => {\n const authenticate = async (email: string, password: string) => {\n const user = await prisma.user.findUnique({\n where: {\n email\n }\n });\n\n if (!user || user.role !== 'ADMIN') {\n return null;\n }\n\n const isPasswordValid = await argon2.verify(user.password, password);\n\n return isPasswordValid ? Promise.resolve({email: user.email, role: user.role, id: user.id}) : null;\n }\n\n return {\n adminJsOptions: {\n rootPath: '/admin',\n dashboard: {\n component: Components.Dashboard,\n handler: async () => {\n return {some: 'output'};\n },\n },\n branding: {\n companyName: 'AppX Core Wizard',\n withMadeWithLove: false,\n logo: 'https://i.ibb.co/XZNRS5m/appxdigitalcom-logo.jpg',\n },\n resources: models.map((m) => {\n return {\n resource: {model: m.model, client: prisma},\n options: {\n ...m.options,\n actions: createActions(),\n },\n features: [...(m.features || []), importExportFeature({\n componentLoader\n })],\n };\n }),\n componentLoader,\n },\n auth: {\n authenticate,\n cookieName: process.env.SESSION_COOKIE_NAME,\n cookiePassword: process.env.SESSION_SECRET,\n },\n sessionOptions: {\n resave: false,\n saveUninitialized: true,\n secret: process.env.SESSION_SECRET,\n cookie: {\n httpOnly: process.env.NODE_ENV === 'production',\n secure: false,\n },\n name: process.env.SESSION_COOKIE_NAME,\n },\n };\n },\n });\n}\n";
1
+ export declare const adminJsModuleCode = "\nimport {DynamicModule} from '@nestjs/common';\nimport {addBasicFilters, createActions, createPermissionHandler, dynamicImport, getAdminJSResources} from './utils';\nimport {initializeComponents} from './component-loader';\nimport {readFileSync} from 'fs';\nimport {getDMMF} from '@prisma/sdk';\nimport {PrismaService} from '@appxdigital/appx-core';\nimport {PrismaModule} from \"../prisma/prisma.module\";\n\nconst DEFAULT_ADMIN = {\n email: 'joao.duvido@appx.pt',\n password: 'password',\n};\n\nconst authenticate = async (email: string, password: string) => {\n if (email === DEFAULT_ADMIN.email && password === DEFAULT_ADMIN.password) {\n return Promise.resolve(DEFAULT_ADMIN);\n }\n return null;\n};\n\nexport async function createAdminJsModule(): Promise<DynamicModule> {\n const {default: AdminJS} = await dynamicImport('adminjs');\n const {Database, Resource} = await dynamicImport('@adminjs/prisma');\n const {AdminModule} = await dynamicImport('@adminjs/nestjs');\n const {default: importExportFeature} = await dynamicImport('@adminjs/import-export');\n const {default: passwordFeature} = await dynamicImport('@adminjs/passwords');\n const argon2 = await dynamicImport('argon2');\n\n const resources = getAdminJSResources();\n const {componentLoader, Components} = await initializeComponents();\n const schemaPath = './prisma/schema.prisma';\n const schema = readFileSync(schemaPath, 'utf-8');\n const dmmf = await getDMMF({datamodel: schema});\n\n const models = [];\n\n for (const resource of resources) {\n const model = dmmf.datamodel.models.find(\n (model) => model.name === resource.name,\n );\n\n models.push({\n model,\n options: resource.options,\n features: model.name === 'User' ? [\n passwordFeature({\n properties: {\n encryptedPassword: 'password',\n password: 'plainPassword',\n },\n hash: argon2.hash,\n componentLoader,\n }),\n ] : [],\n });\n }\n\n AdminJS.registerAdapter({Database, Resource});\n\n return AdminModule.createAdminAsync({\n imports: [PrismaModule],\n inject: [PrismaService],\n useFactory: async (prisma: PrismaService) => {\n const authenticate = async (email: string, password: string) => {\n const user = await prisma.user.findFirst({\n where: {\n email\n }\n });\n\n if (!user || user.role !== 'ADMIN') {\n return null;\n }\n\n const isPasswordValid = await argon2.verify(user.password, password);\n\n return isPasswordValid ? Promise.resolve({email: user.email, role: user.role, id: user.id}) : null;\n }\n\n return {\n adminJsOptions: {\n rootPath: '/admin',\n dashboard: {\n component: Components.Dashboard,\n handler: async () => {\n return {some: 'output'};\n },\n },\n branding: {\n companyName: 'AppX Core Wizard',\n withMadeWithLove: false,\n logo: 'https://i.ibb.co/XZNRS5m/appxdigitalcom-logo.jpg',\n },\n resources: models.map((m) => {\n return {\n resource: {model: m.model, client: prisma},\n options: {\n ...m.options,\n actions: createActions(),\n },\n features: [...(m.features || []), importExportFeature({\n componentLoader\n })],\n };\n }),\n componentLoader,\n },\n auth: {\n authenticate,\n cookieName: process.env.SESSION_COOKIE_NAME,\n cookiePassword: process.env.SESSION_SECRET,\n },\n sessionOptions: {\n resave: false,\n saveUninitialized: true,\n secret: process.env.SESSION_SECRET,\n cookie: {\n httpOnly: process.env.NODE_ENV === 'production',\n secure: false,\n },\n name: process.env.SESSION_COOKIE_NAME,\n },\n };\n },\n });\n}\n";
2
2
  //# sourceMappingURL=admin.template.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"admin.template.d.ts","sourceRoot":"","sources":["../../../../src/config/admin/templates/admin.template.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,iBAAiB,gwJA+H7B,CAAC"}
1
+ {"version":3,"file":"admin.template.d.ts","sourceRoot":"","sources":["../../../../src/config/admin/templates/admin.template.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,iBAAiB,+vJA+H7B,CAAC"}
@@ -66,7 +66,7 @@ export async function createAdminJsModule(): Promise<DynamicModule> {
66
66
  inject: [PrismaService],
67
67
  useFactory: async (prisma: PrismaService) => {
68
68
  const authenticate = async (email: string, password: string) => {
69
- const user = await prisma.user.findUnique({
69
+ const user = await prisma.user.findFirst({
70
70
  where: {
71
71
  email
72
72
  }
@@ -37,7 +37,7 @@ function GenericResolverFactory(model, returnType, createInputType, updateInputT
37
37
  async findOne(where, info) {
38
38
  const select = new plugins_1.PrismaSelect(info).value;
39
39
  const modelDelegate = this.prisma.getModelDelegate(model);
40
- return modelDelegate.findUnique({
40
+ return modelDelegate.findFirst({
41
41
  where,
42
42
  ...select,
43
43
  });
@@ -138,7 +138,7 @@ let AuthService = class AuthService {
138
138
  if (!req?.user?.id) {
139
139
  throw new common_1.UnauthorizedException('Please log-in');
140
140
  }
141
- return this.prisma.user.findUnique({
141
+ return this.prisma.user.findFirst({
142
142
  where: {
143
143
  id: req?.user?.id,
144
144
  },
@@ -186,7 +186,7 @@ let AuthService = class AuthService {
186
186
  });
187
187
  }
188
188
  async closeSpecificSession(sessionId) {
189
- const deleted = await this.prisma.session.delete({
189
+ const deleted = await this.prisma.session.deleteMany({
190
190
  where: { id: sessionId },
191
191
  }).catch(() => null);
192
192
  return !!deleted;
@@ -232,7 +232,7 @@ let AuthService = class AuthService {
232
232
  const currentTokenId = userFromRefreshTokenGuard.refreshTokenId;
233
233
  const providedTokenString = userFromRefreshTokenGuard.currentRefreshToken;
234
234
  // Invalidate the used refresh token
235
- await this.prisma.userRefreshToken.update({
235
+ await this.prisma.userRefreshToken.updateMany({
236
236
  where: { id: currentTokenId },
237
237
  data: { revokedAt: new Date() },
238
238
  },
@@ -39,7 +39,7 @@ let RefreshTokenStrategy = class RefreshTokenStrategy extends (0, passport_1.Pas
39
39
  if (!user) {
40
40
  throw new common_1.UnauthorizedException('User not found');
41
41
  }
42
- const tokenRecord = await this.prisma.userRefreshToken.findUnique({
42
+ const tokenRecord = await this.prisma.userRefreshToken.findFirst({
43
43
  where: { token: refreshToken },
44
44
  });
45
45
  if (!tokenRecord) {
@@ -26,7 +26,7 @@ let SessionSerializer = class SessionSerializer extends passport_1.PassportSeria
26
26
  return done(new Error('No userId provided'), null);
27
27
  }
28
28
  try {
29
- const user = await this.prisma.user.findUniqueOrThrow({
29
+ const user = await this.prisma.user.findFirstOrThrow({
30
30
  where: { id: Number(userId) },
31
31
  select: {
32
32
  id: true,
@@ -9,12 +9,12 @@ class CorePrismaSessionStore extends express_session_1.Store {
9
9
  super();
10
10
  this.get = async (sid, callback) => {
11
11
  try {
12
- const record = await this.prisma.session.findUnique({ where: { sid } }, { BYPASS_FILTERING: true });
12
+ const record = await this.prisma.session.findFirst({ where: { sid } }, { BYPASS_FILTERING: true });
13
13
  if (!record) {
14
14
  return callback(null, null);
15
15
  }
16
16
  if (record.expiresAt && record.expiresAt <= new Date()) {
17
- await this.prisma.session.delete({ where: { sid } }, { BYPASS_FILTERING: true });
17
+ await this.prisma.session.deleteMany({ where: { sid } }, { BYPASS_FILTERING: true });
18
18
  return callback(null, null);
19
19
  }
20
20
  const session = JSON.parse(record.data);
@@ -60,7 +60,7 @@ class CorePrismaSessionStore extends express_session_1.Store {
60
60
  };
61
61
  this.destroy = async (sid, callback) => {
62
62
  try {
63
- await this.prisma.session.delete({ where: { sid } }, { BYPASS_FILTERING: true });
63
+ await this.prisma.session.deleteMany({ where: { sid } }, { BYPASS_FILTERING: true });
64
64
  callback?.();
65
65
  }
66
66
  catch (err) {
@@ -82,7 +82,7 @@ class CorePrismaSessionStore extends express_session_1.Store {
82
82
  else {
83
83
  expiresAt = new Date(Date.now() + this.options.ttl * 1000);
84
84
  }
85
- await this.prisma.session.update({
85
+ await this.prisma.session.updateMany({
86
86
  where: { sid },
87
87
  data: { expiresAt },
88
88
  }, { BYPASS_FILTERING: true });
@@ -7,8 +7,10 @@ export declare abstract class CoreController<T> {
7
7
  protected readonly permissionsService: PermissionsService;
8
8
  findAll(): Promise<T[]>;
9
9
  findOne(id: string): Promise<T>;
10
- create(data: any): Promise<T>;
11
- update(id: string, data: any): Promise<T>;
10
+ create(data: Partial<T> & {
11
+ [key: string]: any;
12
+ }): Promise<T>;
13
+ update(id: string, data: Partial<T>): Promise<T>;
12
14
  delete(id: string): Promise<T>;
13
15
  }
14
16
  //# sourceMappingURL=core.controller.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"core.controller.d.ts","sourceRoot":"","sources":["../../../src/modules/core/core.controller.ts"],"names":[],"mappings":"AASA,OAAO,EAAC,WAAW,EAAC,MAAM,gBAAgB,CAAC;AAI3C,OAAO,EAAC,kBAAkB,EAAC,MAAM,yCAAyC,CAAC;AAE3E,8BACsB,cAAc,CAAC,CAAC;IAM9B,SAAS,CAAC,QAAQ,CAAC,OAAO,EAAE,WAAW,CAAC,CAAC,CAAC;IAL9C,MAAM,KAAK,UAAU,IAAI,MAAM,CAE9B;IAED,SAAS,aACc,OAAO,EAAE,WAAW,CAAC,CAAC,CAAC;IAK9C,SAAS,CAAC,QAAQ,CAAC,kBAAkB,EAAG,kBAAkB,CAAC;IAIrD,OAAO;IAMP,OAAO,CAAc,EAAE,EAAE,MAAM;IAM/B,MAAM,CAAS,IAAI,EAAE,GAAG;IAoBxB,MAAM,CAAc,EAAE,EAAE,MAAM,EAAU,IAAI,EAAE,GAAG;IAoBjD,MAAM,CAAc,EAAE,EAAE,MAAM;CAGvC"}
1
+ {"version":3,"file":"core.controller.d.ts","sourceRoot":"","sources":["../../../src/modules/core/core.controller.ts"],"names":[],"mappings":"AACA,OAAO,EAAC,WAAW,EAAC,MAAM,gBAAgB,CAAC;AAI3C,OAAO,EAAC,kBAAkB,EAAC,MAAM,yCAAyC,CAAC;AAQ3E,8BACsB,cAAc,CAAC,CAAC;IAM9B,SAAS,CAAC,QAAQ,CAAC,OAAO,EAAE,WAAW,CAAC,CAAC,CAAC;IAL9C,MAAM,KAAK,UAAU,IAAI,MAAM,CAE9B;IAED,SAAS,aACc,OAAO,EAAE,WAAW,CAAC,CAAC,CAAC;IAK9C,SAAS,CAAC,QAAQ,CAAC,kBAAkB,EAAG,kBAAkB,CAAC;IAIrD,OAAO;IAMP,OAAO,CAAc,EAAE,EAAE,MAAM;IAM/B,MAAM,CAAS,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC,GAAG;QAAC,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAA;KAAC;IAoBtD,MAAM,CAAc,EAAE,EAAE,MAAM,EAAU,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC;IAoBxD,MAAM,CAAc,EAAE,EAAE,MAAM;CAGvC"}
@@ -1,7 +1,7 @@
1
1
  import type { PrismaClient } from '.prisma/client';
2
2
  export declare class CoreService<T> {
3
- protected readonly modelDelegate: PrismaClient[keyof PrismaClient];
4
- constructor(modelDelegate: PrismaClient[keyof PrismaClient]);
3
+ protected readonly modelDelegate: PrismaClient[T];
4
+ constructor(modelDelegate: PrismaClient[T]);
5
5
  /**
6
6
  * Find all records with optional parameters and permission conditions.
7
7
  * @param params - Additional query parameters (e.g., filters, order, etc.)
@@ -1 +1 @@
1
- {"version":3,"file":"core.service.d.ts","sourceRoot":"","sources":["../../../src/modules/core/core.service.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAC,YAAY,EAAC,MAAM,gBAAgB,CAAC;AAGjD,qBACa,WAAW,CAAC,CAAC;IAElB,SAAS,CAAC,QAAQ,CAAC,aAAa,EAAE,YAAY,CAAC,MAAM,YAAY,CAAC;gBAA/C,aAAa,EAAE,YAAY,CAAC,MAAM,YAAY,CAAC;IAItE;;;;OAIG;IACG,OAAO,CAAC,MAAM,GAAE,GAAQ,GAAG,OAAO,CAAC,CAAC,EAAE,CAAC;IAQ7C;;;;;OAKG;IACG,OAAO,CAAC,KAAK,EAAE,GAAG,EAAE,OAAO,GAAE,GAAQ,GAAG,OAAO,CAAC,CAAC,CAAC;IAYxD;;;;OAIG;IACG,QAAQ,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC;IAUtC;;;;OAIG;IACG,MAAM,CAAC,IAAI,EAAE,GAAG,GAAG,OAAO,CAAC,CAAC,CAAC;IAQnC;;;;;OAKG;IACG,UAAU,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,EAAE,IAAI,EAAE,GAAG,GAAG,OAAO,CAAC,CAAC,CAAC;IAW5D;;;;OAIG;IACG,UAAU,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC;IAajD,OAAO,CAAC,yBAAyB;CAUpC"}
1
+ {"version":3,"file":"core.service.d.ts","sourceRoot":"","sources":["../../../src/modules/core/core.service.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAC,YAAY,EAAC,MAAM,gBAAgB,CAAC;AAEjD,qBACa,WAAW,CAAC,CAAC;IAElB,SAAS,CAAC,QAAQ,CAAC,aAAa,EAAE,YAAY,CAAC,CAAC,CAAC;gBAA9B,aAAa,EAAE,YAAY,CAAC,CAAC,CAAC;IAIrD;;;;OAIG;IACG,OAAO,CAAC,MAAM,GAAE,GAAQ,GAAG,OAAO,CAAC,CAAC,EAAE,CAAC;IAQ7C;;;;;OAKG;IACG,OAAO,CAAC,KAAK,EAAE,GAAG,EAAE,OAAO,GAAE,GAAQ,GAAG,OAAO,CAAC,CAAC,CAAC;IAYxD;;;;OAIG;IACG,QAAQ,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC;IAUtC;;;;OAIG;IACG,MAAM,CAAC,IAAI,EAAE,GAAG,GAAG,OAAO,CAAC,CAAC,CAAC;IAQnC;;;;;OAKG;IACG,UAAU,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,EAAE,IAAI,EAAE,GAAG,GAAG,OAAO,CAAC,CAAC,CAAC;IAW5D;;;;OAIG;IACG,UAAU,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC;IAajD,OAAO,CAAC,yBAAyB;CAUpC"}
@@ -36,7 +36,7 @@ let CoreService = class CoreService {
36
36
  * @returns A promise of the record
37
37
  */
38
38
  async findOne(where, options = {}) {
39
- const record = this.modelDelegate.findUnique({
39
+ const record = this.modelDelegate.findFirst({
40
40
  where,
41
41
  ...options
42
42
  });
@@ -51,7 +51,7 @@ let CoreService = class CoreService {
51
51
  * @returns A promise of the record
52
52
  */
53
53
  async findById(id) {
54
- const record = await this.modelDelegate.findUnique({
54
+ const record = await this.modelDelegate.findFirst({
55
55
  where: this._generateWhereFromIdField(id)
56
56
  });
57
57
  if (!record) {
@@ -80,10 +80,10 @@ let CoreService = class CoreService {
80
80
  */
81
81
  async updateById(id, data) {
82
82
  try {
83
- return await this.modelDelegate.update({
83
+ return (await this.modelDelegate.updateMany({
84
84
  where: this._generateWhereFromIdField(id),
85
85
  data,
86
- });
86
+ }))[0];
87
87
  }
88
88
  catch (error) {
89
89
  (0, error_handler_1.handleError)(error);
@@ -96,9 +96,9 @@ let CoreService = class CoreService {
96
96
  */
97
97
  async deleteById(id) {
98
98
  try {
99
- return await this.modelDelegate.delete({
99
+ return (await this.modelDelegate.deleteMany({
100
100
  where: this._generateWhereFromIdField(id)
101
- });
101
+ }))[0];
102
102
  }
103
103
  catch (error) {
104
104
  (0, error_handler_1.handleError)(error);
@@ -32,7 +32,7 @@ let UserService = class UserService extends core_service_1.CoreService {
32
32
  });
33
33
  }
34
34
  async findByEmail(email) {
35
- return this.prisma.user.findUnique({
35
+ return this.prisma.user.findFirst({
36
36
  where: { email },
37
37
  select: {
38
38
  id: true,
@@ -2,6 +2,11 @@ import { Prisma, PrismaClient } from '@prisma/client';
2
2
  import { PermissionsConfigType } from '../common/config/permissionsConfigTypes';
3
3
  import type { PrismaClient as RuntimeClient } from '.prisma/client';
4
4
  type ModelKey = keyof RuntimeClient;
5
+ /** Extra options available on every model method */
6
+ export type CorePrismaOptions = {
7
+ BYPASS_OMISSION?: boolean;
8
+ BYPASS_FILTERING?: boolean;
9
+ };
5
10
  export declare class PrismaService {
6
11
  private readonly permissionsConfig;
7
12
  private fieldConfigs;
@@ -1 +1 @@
1
- {"version":3,"file":"prisma.service.d.ts","sourceRoot":"","sources":["../../src/prisma/prisma.service.ts"],"names":[],"mappings":"AACA,OAAO,EAAC,MAAM,EAAE,YAAY,EAAC,MAAM,gBAAgB,CAAC;AACpD,OAAO,EAAC,qBAAqB,EAAC,MAAM,yCAAyC,CAAC;AAE9E,OAAO,KAAK,EAAC,YAAY,IAAI,aAAa,EAAC,MAAM,gBAAgB,CAAC;AAGlE,KAAK,QAAQ,GAAG,MAAM,aAAa,CAAC;AAEpC,qBACa,aAAa;IAMY,OAAO,CAAC,QAAQ,CAAC,iBAAiB;IALpE,OAAO,CAAC,YAAY,CAA2B;IAC/C,YAAY,EAAE,YAAY,CAAC;gBAGvB,YAAY,EAAE,YAAY,EACqB,iBAAiB,EAAE,qBAAqB;IAO3F,YAAY,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,iBAAiB,KAAK,OAAO,CAAC,CAAC,CAAC;IAIpE,WAAW;IA6CX;;;;OAIG;IACH,gBAAgB,CAAC,CAAC,SAAS,QAAQ,EAAE,KAAK,EAAE,CAAC,GAAG,aAAa,CAAC,CAAC,CAAC;IAYhE,IAAI,KAAK,IAAI,aAAa,CAUzB;IAED,IAAI,IAAI,IAAI,aAAa,CAAC,MAAM,CAAC,CAEhC;IAED,IAAI,OAAO,IAAI,aAAa,CAAC,SAAS,CAAC,CAEtC;IAED,IAAI,gBAAgB,QAEnB;IAED;;;OAGG;IACH,WAAW;IAoDX;;;;;;;;OAQG;IACH,OAAO,CAAC,kBAAkB;IAiC1B,IAAI,2BAA2B,QAM9B;IAED;;;;;;;;;;;OAWG;IACH,OAAO,CAAC,oBAAoB;IAiG5B,eAAe,CAAC,WAAW,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM;IAYzD;;;;;;;OAOG;IACH,OAAO,CAAC,eAAe;IAgBvB;;;;;;;OAOG;IACH,OAAO,CAAC,mBAAmB;IA2B3B;;;;;;;OAOG;IACH,OAAO,CAAC,eAAe;IAQvB;;;;;;;;;OASG;IACH,OAAO,CAAC,iBAAiB;IAkDzB;;;;;;;;OAQG;IACH,OAAO,CAAC,mBAAmB;CAgB9B"}
1
+ {"version":3,"file":"prisma.service.d.ts","sourceRoot":"","sources":["../../src/prisma/prisma.service.ts"],"names":[],"mappings":"AACA,OAAO,EAAC,MAAM,EAAE,YAAY,EAAC,MAAM,gBAAgB,CAAC;AACpD,OAAO,EAAC,qBAAqB,EAAC,MAAM,yCAAyC,CAAC;AAE9E,OAAO,KAAK,EAAC,YAAY,IAAI,aAAa,EAAC,MAAM,gBAAgB,CAAC;AAGlE,KAAK,QAAQ,GAAG,MAAM,aAAa,CAAC;AAEpC,oDAAoD;AACpD,MAAM,MAAM,iBAAiB,GAAG;IAC5B,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC9B,CAAC;AAEF,qBACa,aAAa;IAMY,OAAO,CAAC,QAAQ,CAAC,iBAAiB;IALpE,OAAO,CAAC,YAAY,CAA2B;IAC/C,YAAY,EAAE,YAAY,CAAC;gBAGvB,YAAY,EAAE,YAAY,EACqB,iBAAiB,EAAE,qBAAqB;IAO3F,YAAY,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,iBAAiB,KAAK,OAAO,CAAC,CAAC,CAAC;IAIpE,WAAW;IAgDX;;;;OAIG;IACH,gBAAgB,CAAC,CAAC,SAAS,QAAQ,EAAE,KAAK,EAAE,CAAC,GAAG,aAAa,CAAC,CAAC,CAAC;IAYhE,IAAI,KAAK,IAAI,aAAa,CAUzB;IAED,IAAI,IAAI,IAAI,aAAa,CAAC,MAAM,CAAC,CAEhC;IAED,IAAI,OAAO,IAAI,aAAa,CAAC,SAAS,CAAC,CAEtC;IAED,IAAI,gBAAgB,QAEnB;IAED;;;OAGG;IACH,WAAW;IAoDX;;;;;;;;OAQG;IACH,OAAO,CAAC,kBAAkB;IAiC1B,IAAI,2BAA2B,QAM9B;IAED;;;;;;;;;;;OAWG;IACH,OAAO,CAAC,oBAAoB;IAqG5B,eAAe,CAAC,WAAW,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM;IAYzD;;;;;;;OAOG;IACH,OAAO,CAAC,eAAe;IAgBvB;;;;;;;OAOG;IACH,OAAO,CAAC,mBAAmB;IA2B3B;;;;;;;OAOG;IACH,OAAO,CAAC,eAAe;IAQvB;;;;;;;;;OASG;IACH,OAAO,CAAC,iBAAiB;IAkDzB;;;;;;;;OAQG;IACH,OAAO,CAAC,mBAAmB;CAgB9B"}
@@ -40,21 +40,22 @@ let PrismaService = class PrismaService {
40
40
  const userRole = user?.role || 'GUEST';
41
41
  if (typeof model[methodKey] === 'function' && !methodKey.toString().startsWith('_') && !methodKey.toString().startsWith('$')) {
42
42
  const contextModel = nestjs_request_context_1.RequestContext.currentContext?.req.prisma?.[propKey] || model;
43
- return async (params, options) => {
43
+ return async (params = {}, options) => {
44
+ // Blacklisted methods, should not be used to ensure permission filtering is applied
45
+ let blacklist = {
46
+ findUnique: 'findFirst',
47
+ findUniqueOrThrow: 'findFirstOrThrow',
48
+ delete: 'deleteMany',
49
+ update: 'updateMany',
50
+ };
51
+ if (blacklist[methodKey.toString()]) {
52
+ throw new Error(`The method ${methodKey.toString()} is not compatible with permission filtering and is not allowed. Please use ${blacklist[methodKey.toString()]}} instead.`);
53
+ }
44
54
  // delete, deleteMany, update and updateMany methods should not apply field omission because they are not selecting fields
45
55
  if (!options?.BYPASS_OMISSION && !['delete', 'deleteMany', 'update', 'updateMany', 'create', 'createMany'].includes(methodKey.toString()))
46
56
  params = this.applyFieldOmission(String(propKey), userRole, params);
47
57
  if (!options?.BYPASS_FILTERING && !['create', 'createMany'].includes(methodKey.toString())) {
48
58
  params = this.applyWhereConditions(String(propKey), userRole, params, user, methodKey);
49
- // findUnique should be findFirst for where conditions to work properly
50
- if (methodKey === 'findUnique')
51
- methodKey = 'findFirst';
52
- // delete should become deleteMany for where conditions to work properly
53
- if (methodKey === 'delete')
54
- methodKey = 'deleteMany';
55
- // update should become updateMany for where conditions to work properly
56
- if (methodKey === 'update')
57
- methodKey = 'updateMany';
58
59
  }
59
60
  if (methodKey === 'count' && !!params.select) {
60
61
  delete params.select;
@@ -249,7 +250,10 @@ let PrismaService = class PrismaService {
249
250
  throw new common_1.HttpException(`No permissions found for model ${modelName} and role ${userRole}`, common_1.HttpStatus.FORBIDDEN);
250
251
  }
251
252
  const actionPermissions = permissions[action];
252
- if (!actionPermissions || (actionPermissions === 'ALL' && !belongsToQueue?.length) || action === 'create') {
253
+ if (!actionPermissions) {
254
+ throw new common_1.HttpException(`No permissions found for action ${String(action)} on model ${modelName} and role ${userRole}`, common_1.HttpStatus.FORBIDDEN);
255
+ }
256
+ if (actionPermissions === 'ALL' && belongsToQueue.length === 0 || action.toString().startsWith('create')) {
253
257
  return args;
254
258
  }
255
259
  const whereClause = this.buildConditions(actionPermissions.conditions, user);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@appxdigital/appx-core",
3
- "version": "0.1.88",
3
+ "version": "0.1.90",
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",