nextjs-cms 0.5.90 → 0.5.92

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.
Files changed (55) hide show
  1. package/dist/api/index.d.ts +57 -0
  2. package/dist/api/index.d.ts.map +1 -1
  3. package/dist/api/lib/serverActions.d.ts +2 -1
  4. package/dist/api/lib/serverActions.d.ts.map +1 -1
  5. package/dist/api/lib/serverActions.js +49 -15
  6. package/dist/api/root.d.ts +114 -0
  7. package/dist/api/root.d.ts.map +1 -1
  8. package/dist/api/root.js +2 -0
  9. package/dist/api/routers/accountSettings.d.ts.map +1 -1
  10. package/dist/api/routers/accountSettings.js +65 -3
  11. package/dist/api/routers/admins.d.ts.map +1 -1
  12. package/dist/api/routers/admins.js +54 -2
  13. package/dist/api/routers/auth.d.ts.map +1 -1
  14. package/dist/api/routers/auth.js +27 -2
  15. package/dist/api/routers/categorySection.d.ts.map +1 -1
  16. package/dist/api/routers/categorySection.js +3 -1
  17. package/dist/api/routers/hasItemsSection.d.ts.map +1 -1
  18. package/dist/api/routers/hasItemsSection.js +3 -1
  19. package/dist/api/routers/logs.d.ts +59 -0
  20. package/dist/api/routers/logs.d.ts.map +1 -0
  21. package/dist/api/routers/logs.js +75 -0
  22. package/dist/core/fields/photo.d.ts +6 -6
  23. package/dist/core/fields/richText.d.ts +9 -9
  24. package/dist/core/fields/select.d.ts +1 -1
  25. package/dist/core/sections/category.d.ts +6 -6
  26. package/dist/core/sections/hasItems.d.ts +12 -12
  27. package/dist/core/sections/section.d.ts +3 -3
  28. package/dist/core/sections/simple.d.ts +4 -4
  29. package/dist/core/submit/ItemEditSubmit.d.ts +7 -0
  30. package/dist/core/submit/ItemEditSubmit.d.ts.map +1 -1
  31. package/dist/core/submit/ItemEditSubmit.js +32 -0
  32. package/dist/core/submit/NewItemSubmit.d.ts +2 -0
  33. package/dist/core/submit/NewItemSubmit.d.ts.map +1 -1
  34. package/dist/core/submit/NewItemSubmit.js +3 -0
  35. package/dist/core/submit/submit.d.ts +8 -4
  36. package/dist/core/submit/submit.d.ts.map +1 -1
  37. package/dist/core/submit/submit.js +58 -8
  38. package/dist/db/schema.d.ts +231 -0
  39. package/dist/db/schema.d.ts.map +1 -1
  40. package/dist/db/schema.js +25 -0
  41. package/dist/index.d.ts +1 -0
  42. package/dist/index.d.ts.map +1 -1
  43. package/dist/index.js +1 -0
  44. package/dist/logging/audit.d.ts +20 -0
  45. package/dist/logging/audit.d.ts.map +1 -0
  46. package/dist/logging/audit.js +48 -0
  47. package/dist/logging/index.d.ts +2 -0
  48. package/dist/logging/index.d.ts.map +1 -0
  49. package/dist/logging/index.js +1 -0
  50. package/dist/logging/log.d.ts +20 -0
  51. package/dist/logging/log.d.ts.map +1 -0
  52. package/dist/logging/log.js +48 -0
  53. package/dist/translations/dictionaries/ar.json +6 -0
  54. package/dist/translations/dictionaries/en.json +6 -0
  55. package/package.json +7 -3
@@ -732,6 +732,63 @@ declare const createCaller: import("@trpc/server").TRPCRouterCaller<{
732
732
  meta: object;
733
733
  }>;
734
734
  }>>;
735
+ logs: import("@trpc/server").TRPCBuiltRouter<{
736
+ ctx: {
737
+ headers: Headers;
738
+ db: import("drizzle-orm/mysql2").MySql2Database<typeof import("../db/schema.js")> & {
739
+ $client: import("mysql2/promise").Pool;
740
+ };
741
+ session: import("../index.js").Session | null;
742
+ };
743
+ meta: object;
744
+ errorShape: {
745
+ data: {
746
+ zodError: import("zod").ZodFlattenedError<unknown, string> | null;
747
+ code: import("@trpc/server").TRPC_ERROR_CODE_KEY;
748
+ httpStatus: number;
749
+ path?: string;
750
+ stack?: string;
751
+ };
752
+ message: string;
753
+ code: import("@trpc/server").TRPC_ERROR_CODE_NUMBER;
754
+ };
755
+ transformer: true;
756
+ }, import("@trpc/server").TRPCDecorateCreateRouterOptions<{
757
+ list: import("@trpc/server").TRPCQueryProcedure<{
758
+ input: {
759
+ limit?: number | undefined;
760
+ offset?: number | undefined;
761
+ eventType?: string | undefined;
762
+ actorId?: string | undefined;
763
+ sectionName?: string | undefined;
764
+ entityType?: string | undefined;
765
+ entityId?: string | undefined;
766
+ from?: string | undefined;
767
+ to?: string | undefined;
768
+ } | undefined;
769
+ output: {
770
+ items: {
771
+ id: number;
772
+ eventType: string;
773
+ actorId: string | null;
774
+ actorUsername: string | null;
775
+ entityType: string | null;
776
+ entityId: string | null;
777
+ entityLabel: string | null;
778
+ sectionName: string | null;
779
+ metadata: string | null;
780
+ ipAddress: string | null;
781
+ userAgent: string | null;
782
+ source: string | null;
783
+ createdAt: Date;
784
+ }[];
785
+ total: number;
786
+ limit: number;
787
+ offset: number;
788
+ };
789
+ meta: object;
790
+ }>;
791
+ }>>;
735
792
  plugins: import("@trpc/server").TRPCBuiltRouter<{
736
793
  ctx: {
737
794
  headers: Headers;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/api/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAA;AAEzE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,WAAW,CAAA;AAC1C,OAAO,EAAE,SAAS,EAAE,uBAAuB,EAAE,YAAY,EAAE,MAAM,WAAW,CAAA;AAC5E,OAAO,EAEH,iBAAiB,EACjB,gBAAgB,EAChB,eAAe,EACf,MAAM,EACN,eAAe,EAClB,MAAM,WAAW,CAAA;AAElB;;;;;;GAMG;AACH,QAAA,MAAM,YAAY;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAAiC,CAAA;AAEnD;;;;;IAKI;AACJ,KAAK,YAAY,GAAG,iBAAiB,CAAC,SAAS,CAAC,CAAA;AAEhD;;;;;IAKI;AACJ,KAAK,aAAa,GAAG,kBAAkB,CAAC,SAAS,CAAC,CAAA;AAElD,OAAO,EAAE,iBAAiB,EAAE,SAAS,EAAE,YAAY,EAAE,uBAAuB,EAAE,YAAY,EAAE,CAAA;AAC5F,OAAO,EAAE,MAAM,EAAE,eAAe,EAAE,gBAAgB,EAAE,eAAe,EAAE,CAAA;AACrE,YAAY,EAAE,SAAS,EAAE,YAAY,EAAE,aAAa,EAAE,CAAA;AACtD,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/api/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAA;AAEzE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,WAAW,CAAA;AAC1C,OAAO,EAAE,SAAS,EAAE,uBAAuB,EAAE,YAAY,EAAE,MAAM,WAAW,CAAA;AAC5E,OAAO,EAEH,iBAAiB,EACjB,gBAAgB,EAChB,eAAe,EACf,MAAM,EACN,eAAe,EAClB,MAAM,WAAW,CAAA;AAElB;;;;;;GAMG;AACH,QAAA,MAAM,YAAY;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAAiC,CAAA;AAEnD;;;;;IAKI;AACJ,KAAK,YAAY,GAAG,iBAAiB,CAAC,SAAS,CAAC,CAAA;AAEhD;;;;;IAKI;AACJ,KAAK,aAAa,GAAG,kBAAkB,CAAC,SAAS,CAAC,CAAA;AAElD,OAAO,EAAE,iBAAiB,EAAE,SAAS,EAAE,YAAY,EAAE,uBAAuB,EAAE,YAAY,EAAE,CAAA;AAC5F,OAAO,EAAE,MAAM,EAAE,eAAe,EAAE,gBAAgB,EAAE,eAAe,EAAE,CAAA;AACrE,YAAY,EAAE,SAAS,EAAE,YAAY,EAAE,aAAa,EAAE,CAAA;AACtD,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAA"}
@@ -1,4 +1,5 @@
1
1
  import type { Session } from '../../auth/index.js';
2
+ import { type RequestMetadata } from '../../logging/index.js';
2
3
  export declare const isAccessAllowed: ({ sectionName, role, userId, }: {
3
4
  sectionName: string;
4
5
  role?: "C" | "U" | "D";
@@ -88,7 +89,7 @@ export declare const createSimpleSectionPage: (session: Session, sectionName: st
88
89
  }[] | undefined;
89
90
  error?: undefined;
90
91
  }>;
91
- export declare const deleteSectionItem: (session: Session, sectionName: string, sectionItemId: string | number, recursive?: boolean) => Promise<true | {
92
+ export declare const deleteSectionItem: (session: Session, sectionName: string, sectionItemId: string | number, recursive?: boolean, requestMetadata?: RequestMetadata) => Promise<true | {
92
93
  error: {
93
94
  message: string;
94
95
  };
@@ -1 +1 @@
1
- {"version":3,"file":"serverActions.d.ts","sourceRoot":"","sources":["../../../src/api/lib/serverActions.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"serverActions.d.ts","sourceRoot":"","sources":["../../../src/api/lib/serverActions.ts"],"names":[],"mappings":"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"}
@@ -15,6 +15,7 @@ import { fileTypeFromBuffer } from 'file-type';
15
15
  import { getCMSConfig } from '../../core/config/index.js';
16
16
  import { getPluginRoutes } from '../../plugins/loader.js';
17
17
  import through2 from 'through2';
18
+ import { recordLog } from '../../logging/index.js';
18
19
  export const isAccessAllowed = async ({ sectionName, role, userId, }) => {
19
20
  /**
20
21
  * Check admin privileges
@@ -56,6 +57,12 @@ export const getDocument = async (session, input) => {
56
57
  });
57
58
  }
58
59
  const fieldConfig = section.fields.find((field) => field.name === fieldName);
60
+ if (!fieldConfig || typeof fieldConfig.build !== 'function') {
61
+ throw new TRPCError({
62
+ code: 'BAD_REQUEST',
63
+ message: 'Invalid request',
64
+ });
65
+ }
59
66
  const field = fieldConfig.build();
60
67
  /**
61
68
  * If field is not found, throw an error
@@ -341,7 +348,7 @@ export const createSimpleSectionPage = async (session, sectionName) => {
341
348
  };
342
349
  }
343
350
  };
344
- export const deleteSectionItem = async (session, sectionName, sectionItemId, recursive) => {
351
+ export const deleteSectionItem = async (session, sectionName, sectionItemId, recursive, requestMetadata) => {
345
352
  /**
346
353
  * Convert the section item id to string
347
354
  */
@@ -388,21 +395,29 @@ export const deleteSectionItem = async (session, sectionName, sectionItemId, rec
388
395
  */
389
396
  const fileFieldConfigs = section.fieldConfigs.filter((fieldConfig) => fieldConfig.type === 'document' || fieldConfig.type === 'photo' || fieldConfig.type === 'video');
390
397
  const uploadsFolder = (await getCMSConfig()).media.upload.path;
391
- for (const field of fileFieldConfigs) {
392
- // @ts-ignore
393
- const value = sectionItemRow[field.name];
394
- if (value) {
395
- if (field.type === 'document') {
396
- await fs.promises.unlink(path.join(uploadsFolder, '.documents', section.name, value));
397
- }
398
- else {
399
- try {
400
- await fs.promises.unlink(path.join(uploadsFolder, '.photos', section.name, value));
401
- await fs.promises.unlink(path.join(uploadsFolder, '.thumbs', section.name, value));
398
+ if (sectionItemRow) {
399
+ for (const field of fileFieldConfigs) {
400
+ // @ts-ignore
401
+ const value = sectionItemRow[field.name];
402
+ if (value) {
403
+ if (field.type === 'document') {
404
+ try {
405
+ await fs.promises.unlink(path.join(uploadsFolder, '.documents', section.name, value));
406
+ }
407
+ catch (error) {
408
+ // Log but continue - file may not exist or already deleted
409
+ console.error('Error deleting document', error);
410
+ }
402
411
  }
403
- catch (error) {
404
- // Log but continue - file may not exist or already deleted
405
- console.error('Error deleting photo', error);
412
+ else {
413
+ try {
414
+ await fs.promises.unlink(path.join(uploadsFolder, '.photos', section.name, value));
415
+ await fs.promises.unlink(path.join(uploadsFolder, '.thumbs', section.name, value));
416
+ }
417
+ catch (error) {
418
+ // Log but continue - file may not exist or already deleted
419
+ console.error('Error deleting photo', error);
420
+ }
406
421
  }
407
422
  }
408
423
  }
@@ -496,6 +511,25 @@ export const deleteSectionItem = async (session, sectionName, sectionItemId, rec
496
511
  console.error('onDelete hook failed:', error);
497
512
  }
498
513
  }
514
+ const headingFieldName = section.headingField.name;
515
+ const entityLabel = headingFieldName && sectionItemRow
516
+ // @ts-ignore
517
+ ? String(sectionItemRow[headingFieldName] ?? '')
518
+ : null;
519
+ await recordLog({
520
+ eventType: 'section.item.delete',
521
+ actorId: session.user.id,
522
+ actorUsername: session.user.name,
523
+ entityType: 'section_item',
524
+ entityId: sectionItemId,
525
+ entityLabel: entityLabel?.trim() ? entityLabel : null,
526
+ sectionName: section.name,
527
+ metadata: {
528
+ sectionType: section.type,
529
+ recursive: Boolean(recursive),
530
+ },
531
+ requestMetadata,
532
+ });
499
533
  return true;
500
534
  }
501
535
  catch (err) {
@@ -723,6 +723,63 @@ export declare const appRouter: import("@trpc/server").TRPCBuiltRouter<{
723
723
  meta: object;
724
724
  }>;
725
725
  }>>;
726
+ logs: import("@trpc/server").TRPCBuiltRouter<{
727
+ ctx: {
728
+ headers: Headers;
729
+ db: import("drizzle-orm/mysql2").MySql2Database<typeof import("../db/schema.js")> & {
730
+ $client: import("mysql2/promise").Pool;
731
+ };
732
+ session: import("../index.js").Session | null;
733
+ };
734
+ meta: object;
735
+ errorShape: {
736
+ data: {
737
+ zodError: z.core.$ZodFlattenedError<unknown, string> | null;
738
+ code: import("@trpc/server").TRPC_ERROR_CODE_KEY;
739
+ httpStatus: number;
740
+ path?: string;
741
+ stack?: string;
742
+ };
743
+ message: string;
744
+ code: import("@trpc/server").TRPC_ERROR_CODE_NUMBER;
745
+ };
746
+ transformer: true;
747
+ }, import("@trpc/server").TRPCDecorateCreateRouterOptions<{
748
+ list: import("@trpc/server").TRPCQueryProcedure<{
749
+ input: {
750
+ limit?: number | undefined;
751
+ offset?: number | undefined;
752
+ eventType?: string | undefined;
753
+ actorId?: string | undefined;
754
+ sectionName?: string | undefined;
755
+ entityType?: string | undefined;
756
+ entityId?: string | undefined;
757
+ from?: string | undefined;
758
+ to?: string | undefined;
759
+ } | undefined;
760
+ output: {
761
+ items: {
762
+ id: number;
763
+ eventType: string;
764
+ actorId: string | null;
765
+ actorUsername: string | null;
766
+ entityType: string | null;
767
+ entityId: string | null;
768
+ entityLabel: string | null;
769
+ sectionName: string | null;
770
+ metadata: string | null;
771
+ ipAddress: string | null;
772
+ userAgent: string | null;
773
+ source: string | null;
774
+ createdAt: Date;
775
+ }[];
776
+ total: number;
777
+ limit: number;
778
+ offset: number;
779
+ };
780
+ meta: object;
781
+ }>;
782
+ }>>;
726
783
  plugins: import("@trpc/server").TRPCBuiltRouter<{
727
784
  ctx: {
728
785
  headers: Headers;
@@ -1501,6 +1558,63 @@ export declare const createCaller: import("@trpc/server").TRPCRouterCaller<{
1501
1558
  meta: object;
1502
1559
  }>;
1503
1560
  }>>;
1561
+ logs: import("@trpc/server").TRPCBuiltRouter<{
1562
+ ctx: {
1563
+ headers: Headers;
1564
+ db: import("drizzle-orm/mysql2").MySql2Database<typeof import("../db/schema.js")> & {
1565
+ $client: import("mysql2/promise").Pool;
1566
+ };
1567
+ session: import("../index.js").Session | null;
1568
+ };
1569
+ meta: object;
1570
+ errorShape: {
1571
+ data: {
1572
+ zodError: z.core.$ZodFlattenedError<unknown, string> | null;
1573
+ code: import("@trpc/server").TRPC_ERROR_CODE_KEY;
1574
+ httpStatus: number;
1575
+ path?: string;
1576
+ stack?: string;
1577
+ };
1578
+ message: string;
1579
+ code: import("@trpc/server").TRPC_ERROR_CODE_NUMBER;
1580
+ };
1581
+ transformer: true;
1582
+ }, import("@trpc/server").TRPCDecorateCreateRouterOptions<{
1583
+ list: import("@trpc/server").TRPCQueryProcedure<{
1584
+ input: {
1585
+ limit?: number | undefined;
1586
+ offset?: number | undefined;
1587
+ eventType?: string | undefined;
1588
+ actorId?: string | undefined;
1589
+ sectionName?: string | undefined;
1590
+ entityType?: string | undefined;
1591
+ entityId?: string | undefined;
1592
+ from?: string | undefined;
1593
+ to?: string | undefined;
1594
+ } | undefined;
1595
+ output: {
1596
+ items: {
1597
+ id: number;
1598
+ eventType: string;
1599
+ actorId: string | null;
1600
+ actorUsername: string | null;
1601
+ entityType: string | null;
1602
+ entityId: string | null;
1603
+ entityLabel: string | null;
1604
+ sectionName: string | null;
1605
+ metadata: string | null;
1606
+ ipAddress: string | null;
1607
+ userAgent: string | null;
1608
+ source: string | null;
1609
+ createdAt: Date;
1610
+ }[];
1611
+ total: number;
1612
+ limit: number;
1613
+ offset: number;
1614
+ };
1615
+ meta: object;
1616
+ }>;
1617
+ }>>;
1504
1618
  plugins: import("@trpc/server").TRPCBuiltRouter<{
1505
1619
  ctx: {
1506
1620
  headers: Headers;
@@ -1 +1 @@
1
- {"version":3,"file":"root.d.ts","sourceRoot":"","sources":["../../src/api/root.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,WAAW,CAAA;AAa5C,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AA2FvB,eAAO,MAAM,SAAS;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAAsB,CAAA;AAU5C,wBAAsB,YAAY;;;;;;;;;;;;;;;;;;;;;4GAEjC;AAED,wBAAsB,uBAAuB,CAAC,GAAG,EAAE,WAAW,4LAG7D;AAGD,MAAM,MAAM,SAAS,GAAG,OAAO,SAAS,CAAA;AAGxC,eAAO,MAAM,YAAY;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAAiC,CAAA"}
1
+ {"version":3,"file":"root.d.ts","sourceRoot":"","sources":["../../src/api/root.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,WAAW,CAAA;AAc5C,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AA4FvB,eAAO,MAAM,SAAS;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAAsB,CAAA;AAU5C,wBAAsB,YAAY;;;;;;;;;;;;;;;;;;;;;4GAEjC;AAED,wBAAsB,uBAAuB,CAAC,GAAG,EAAE,WAAW,4LAG7D;AAGD,MAAM,MAAM,SAAS,GAAG,OAAO,SAAS,CAAA;AAGxC,eAAO,MAAM,YAAY;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAAiC,CAAA"}
package/dist/api/root.js CHANGED
@@ -8,6 +8,7 @@ import { simpleSectionRouter } from './routers/simpleSection.js';
8
8
  import { categorySectionRouter } from './routers/categorySection.js';
9
9
  import { accountSettings } from './routers/accountSettings.js';
10
10
  import { galleryRouter } from './routers/gallery.js';
11
+ import { logsRouter } from './routers/logs.js';
11
12
  import { getConfigImportVersion } from '../core/config/index.js';
12
13
  import { getPluginRoutes, loadPlugins } from '../plugins/loader.js';
13
14
  import { z } from 'zod';
@@ -47,6 +48,7 @@ const coreRouters = {
47
48
  gallery: galleryRouter,
48
49
  navigation: navRouter,
49
50
  accountSettings: accountSettings,
51
+ logs: logsRouter,
50
52
  plugins: pluginsRouter,
51
53
  };
52
54
  // Lazy router creation - cache the result
@@ -1 +1 @@
1
- {"version":3,"file":"accountSettings.d.ts","sourceRoot":"","sources":["../../../src/api/routers/accountSettings.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,CAAC,MAAM,KAAK,CAAA;AAIxB,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IAkBxB;;;OAGG;;;;;;;;;;;;;;;;;;;GA4FL,CAAA"}
1
+ {"version":3,"file":"accountSettings.d.ts","sourceRoot":"","sources":["../../../src/api/routers/accountSettings.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,CAAC,MAAM,KAAK,CAAA;AAKxB,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IAkBxB;;;OAGG;;;;;;;;;;;;;;;;;;;GAsKL,CAAA"}
@@ -5,6 +5,7 @@ import { eq } from 'drizzle-orm';
5
5
  import * as z from 'zod';
6
6
  import bcrypt from 'bcrypt';
7
7
  import { TRPCError } from '@trpc/server';
8
+ import { getRequestMetadataFromHeaders, recordLog } from '../../logging/index.js';
8
9
  export const accountSettings = router({
9
10
  get: privateProcedure.query(async ({ ctx }) => {
10
11
  const admin = await db
@@ -32,15 +33,61 @@ export const accountSettings = router({
32
33
  phoneNumber: z.string(),
33
34
  }))
34
35
  .mutation(async ({ ctx, input }) => {
36
+ const requestMetadata = getRequestMetadataFromHeaders(ctx.headers);
37
+ const existing = await db
38
+ .select({
39
+ emailAddress: AdminsTable.emailAddress,
40
+ fullName: AdminsTable.fullName,
41
+ phoneNumber: AdminsTable.phoneNumber,
42
+ username: AdminsTable.user,
43
+ })
44
+ .from(AdminsTable)
45
+ .where(eq(AdminsTable.id, ctx.session.user.id))
46
+ .limit(1);
47
+ const admin = existing[0];
48
+ if (!admin) {
49
+ throw new TRPCError({
50
+ code: 'NOT_FOUND',
51
+ message: 'Admin not found',
52
+ });
53
+ }
54
+ const updates = {};
55
+ const changedFields = [];
56
+ if (admin.emailAddress !== input.emailAddress) {
57
+ updates.emailAddress = input.emailAddress;
58
+ changedFields.push('emailAddress');
59
+ }
60
+ if (admin.fullName !== input.fullName) {
61
+ updates.fullName = input.fullName;
62
+ changedFields.push('fullName');
63
+ }
64
+ if (admin.phoneNumber !== input.phoneNumber) {
65
+ updates.phoneNumber = input.phoneNumber;
66
+ changedFields.push('phoneNumber');
67
+ }
68
+ if (changedFields.length === 0) {
69
+ return true;
70
+ }
35
71
  await db
36
72
  .update(AdminsTable)
37
73
  .set({
38
- emailAddress: input.emailAddress,
39
- fullName: input.fullName,
40
- phoneNumber: input.phoneNumber,
74
+ ...updates,
41
75
  })
42
76
  .where(eq(AdminsTable.id, ctx.session.user.id))
43
77
  .execute();
78
+ await recordLog({
79
+ eventType: 'admin.settings.change',
80
+ actorId: ctx.session.user.id,
81
+ actorUsername: ctx.session.user.name ?? admin.username ?? null,
82
+ entityType: 'admin',
83
+ entityId: ctx.session.user.id,
84
+ entityLabel: admin.username ?? null,
85
+ sectionName: 'settings',
86
+ metadata: {
87
+ fields: changedFields,
88
+ },
89
+ requestMetadata,
90
+ });
44
91
  return true;
45
92
  }),
46
93
  changePassword: privateProcedure
@@ -50,12 +97,14 @@ export const accountSettings = router({
50
97
  confirmPassword: z.string(),
51
98
  }))
52
99
  .mutation(async ({ ctx, input }) => {
100
+ const requestMetadata = getRequestMetadataFromHeaders(ctx.headers);
53
101
  /**
54
102
  * Check if old password is correct
55
103
  */
56
104
  const result = await db
57
105
  .select({
58
106
  password: AdminsTable.pass,
107
+ username: AdminsTable.user,
59
108
  })
60
109
  .from(AdminsTable)
61
110
  .where(eq(AdminsTable.id, ctx.session.user.id))
@@ -103,6 +152,19 @@ export const accountSettings = router({
103
152
  })
104
153
  .where(eq(AdminsTable.id, ctx.session.user.id))
105
154
  .execute();
155
+ await recordLog({
156
+ eventType: 'admin.settings.change',
157
+ actorId: ctx.session.user.id,
158
+ actorUsername: ctx.session.user.name ?? admin.username ?? null,
159
+ entityType: 'admin',
160
+ entityId: ctx.session.user.id,
161
+ entityLabel: admin.username ?? null,
162
+ sectionName: 'settings',
163
+ metadata: {
164
+ fields: ['password'],
165
+ },
166
+ requestMetadata,
167
+ });
106
168
  return true;
107
169
  }),
108
170
  });
@@ -1 +1 @@
1
- {"version":3,"file":"admins.d.ts","sourceRoot":"","sources":["../../../src/api/routers/admins.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,CAAC,MAAM,KAAK,CAAA;AAaxB,eAAO,MAAM,YAAY;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmSvB,CAAA"}
1
+ {"version":3,"file":"admins.d.ts","sourceRoot":"","sources":["../../../src/api/routers/admins.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,CAAC,MAAM,KAAK,CAAA;AAcxB,eAAO,MAAM,YAAY;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyVvB,CAAA"}
@@ -11,6 +11,7 @@ import getString from '../../translations/index.js';
11
11
  import path from 'path';
12
12
  import fs from 'fs';
13
13
  import { getCMSConfig } from '../../core/config/index.js';
14
+ import { getRequestMetadataFromHeaders, recordLog } from '../../logging/index.js';
14
15
  export const adminsRouter = router({
15
16
  list: privateProcedure.query(async ({ ctx }) => {
16
17
  const accessAllowed = await isAccessAllowed({
@@ -88,6 +89,7 @@ export const adminsRouter = router({
88
89
  })),
89
90
  }))
90
91
  .mutation(async ({ ctx, input }) => {
92
+ const requestMetadata = getRequestMetadataFromHeaders(ctx.headers);
91
93
  const accessAllowed = await isAccessAllowed({
92
94
  sectionName: 'admins',
93
95
  userId: ctx.session.user.id,
@@ -147,6 +149,23 @@ export const adminsRouter = router({
147
149
  * Insert the privileges into the admin_privileges table
148
150
  */
149
151
  await db.insert(AdminPrivilegesTable).values(rows);
152
+ await recordLog({
153
+ eventType: 'admin.section.create',
154
+ actorId: ctx.session.user.id,
155
+ actorUsername: ctx.session.user.name ?? null,
156
+ entityType: 'admin',
157
+ entityId: id,
158
+ entityLabel: input.username,
159
+ sectionName: 'admins',
160
+ metadata: {
161
+ privileges: rows.map((privilege) => ({
162
+ sectionName: privilege.sectionName,
163
+ operations: privilege.operations,
164
+ publisher: privilege.publisher,
165
+ })),
166
+ },
167
+ requestMetadata,
168
+ });
150
169
  return {
151
170
  status: 'success',
152
171
  };
@@ -161,6 +180,7 @@ export const adminsRouter = router({
161
180
  })),
162
181
  }))
163
182
  .mutation(async ({ ctx, input }) => {
183
+ const requestMetadata = getRequestMetadataFromHeaders(ctx.headers);
164
184
  const accessAllowed = await isAccessAllowed({
165
185
  sectionName: 'admins',
166
186
  userId: ctx.session.user.id,
@@ -174,11 +194,12 @@ export const adminsRouter = router({
174
194
  /**
175
195
  * First, let's check if the admin exists
176
196
  */
177
- const usernameExists = await db.select().from(AdminsTable).where(eq(AdminsTable.id, input.id));
197
+ const adminRows = await db.select().from(AdminsTable).where(eq(AdminsTable.id, input.id));
198
+ const admin = adminRows[0];
178
199
  /**
179
200
  * If the admin doens't exist, throw an error
180
201
  */
181
- if (usernameExists.length === 0) {
202
+ if (!admin) {
182
203
  throw new TRPCError({
183
204
  code: 'BAD_REQUEST',
184
205
  message: getString('adminDoesNotExist'),
@@ -211,6 +232,23 @@ export const adminsRouter = router({
211
232
  */
212
233
  await db.delete(AdminPrivilegesTable).where(eq(AdminPrivilegesTable.adminId, input.id));
213
234
  await db.insert(AdminPrivilegesTable).values(rows);
235
+ await recordLog({
236
+ eventType: 'admin.section.update',
237
+ actorId: ctx.session.user.id,
238
+ actorUsername: ctx.session.user.name ?? null,
239
+ entityType: 'admin',
240
+ entityId: input.id,
241
+ entityLabel: admin.user ?? null,
242
+ sectionName: 'admins',
243
+ metadata: {
244
+ privileges: rows.map((privilege) => ({
245
+ sectionName: privilege.sectionName,
246
+ operations: privilege.operations,
247
+ publisher: privilege.publisher,
248
+ })),
249
+ },
250
+ requestMetadata,
251
+ });
214
252
  return {
215
253
  status: 'success',
216
254
  };
@@ -220,6 +258,7 @@ export const adminsRouter = router({
220
258
  id: z.string(),
221
259
  }))
222
260
  .mutation(async ({ ctx, input }) => {
261
+ const requestMetadata = getRequestMetadataFromHeaders(ctx.headers);
223
262
  const accessAllowed = await isAccessAllowed({
224
263
  sectionName: 'admins',
225
264
  userId: ctx.session.user.id,
@@ -265,6 +304,19 @@ export const adminsRouter = router({
265
304
  if (admin.coverphoto) {
266
305
  await fs.promises.unlink(path.join(uploadsFolder, '.thumbs', 'admins', admin.coverphoto));
267
306
  }
307
+ await recordLog({
308
+ eventType: 'admin.section.delete',
309
+ actorId: ctx.session.user.id,
310
+ actorUsername: ctx.session.user.name ?? null,
311
+ entityType: 'admin',
312
+ entityId: input.id,
313
+ entityLabel: admin.user ?? null,
314
+ sectionName: 'admins',
315
+ metadata: {
316
+ hadAvatar: Boolean(admin.coverphoto),
317
+ },
318
+ requestMetadata,
319
+ });
268
320
  return true;
269
321
  }),
270
322
  });
@@ -1 +1 @@
1
- {"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../../src/api/routers/auth.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,CAAC,MAAM,KAAK,CAAA;AAIxB,eAAO,MAAM,UAAU;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsBrB,CAAA"}
1
+ {"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../../src/api/routers/auth.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,CAAC,MAAM,KAAK,CAAA;AAKxB,eAAO,MAAM,UAAU;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkDrB,CAAA"}
@@ -2,6 +2,7 @@ import { privateProcedure, publicProcedure, router } from '../trpc.js';
2
2
  import * as z from 'zod';
3
3
  import { TRPCError } from '@trpc/server';
4
4
  import { deleteSession, login } from '../../auth/lib/index.js';
5
+ import { getRequestMetadataFromHeaders, recordLog } from '../../logging/index.js';
5
6
  export const authRouter = router({
6
7
  login: publicProcedure
7
8
  .input(z.object({
@@ -10,7 +11,19 @@ export const authRouter = router({
10
11
  }))
11
12
  .mutation(async (opts) => {
12
13
  try {
13
- return await login(opts.input);
14
+ const requestMetadata = getRequestMetadataFromHeaders(opts.ctx.headers);
15
+ const result = await login(opts.input);
16
+ await recordLog({
17
+ eventType: 'auth.login',
18
+ actorId: result.user?.id ?? null,
19
+ actorUsername: result.user?.username ?? null,
20
+ entityType: 'admin',
21
+ entityId: result.user?.id ?? null,
22
+ entityLabel: result.user?.username ?? null,
23
+ sectionName: 'auth',
24
+ requestMetadata,
25
+ });
26
+ return result;
14
27
  }
15
28
  catch (error) {
16
29
  throw new TRPCError({
@@ -20,6 +33,18 @@ export const authRouter = router({
20
33
  }
21
34
  }),
22
35
  logout: privateProcedure.mutation(async (opts) => {
23
- return await deleteSession(opts.ctx.session);
36
+ const requestMetadata = getRequestMetadataFromHeaders(opts.ctx.headers);
37
+ const result = await deleteSession(opts.ctx.session);
38
+ await recordLog({
39
+ eventType: 'auth.logout',
40
+ actorId: opts.ctx.session.user.id,
41
+ actorUsername: opts.ctx.session.user.name ?? null,
42
+ entityType: 'admin',
43
+ entityId: opts.ctx.session.user.id,
44
+ entityLabel: opts.ctx.session.user.name ?? null,
45
+ sectionName: 'auth',
46
+ requestMetadata,
47
+ });
48
+ return result;
24
49
  }),
25
50
  });
@@ -1 +1 @@
1
- {"version":3,"file":"categorySection.d.ts","sourceRoot":"","sources":["../../../src/api/routers/categorySection.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,CAAC,MAAM,KAAK,CAAA;AAGxB,eAAO,MAAM,qBAAqB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0ChC,CAAA"}
1
+ {"version":3,"file":"categorySection.d.ts","sourceRoot":"","sources":["../../../src/api/routers/categorySection.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,CAAC,MAAM,KAAK,CAAA;AAIxB,eAAO,MAAM,qBAAqB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiDhC,CAAA"}