@kyro-cms/core 0.9.0 → 0.9.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +57 -589
- package/dist/{WebhookService-118ZTFis.d.ts → WebhookService-CUTb9XOy.d.ts} +1 -1
- package/dist/{WebhookService-AefJfqX0.d.cts → WebhookService-Yg2UEOB4.d.cts} +1 -1
- package/dist/api-handler-graphql.cjs +44 -0
- package/dist/api-handler-graphql.cjs.map +1 -0
- package/dist/api-handler-graphql.d.cts +6 -0
- package/dist/api-handler-graphql.d.ts +6 -0
- package/dist/api-handler-graphql.js +41 -0
- package/dist/api-handler-graphql.js.map +1 -0
- package/dist/api-handler-trpc.cjs +38 -0
- package/dist/api-handler-trpc.cjs.map +1 -0
- package/dist/api-handler-trpc.d.cts +5 -0
- package/dist/api-handler-trpc.d.ts +5 -0
- package/dist/api-handler-trpc.js +36 -0
- package/dist/api-handler-trpc.js.map +1 -0
- package/dist/api-handler.cjs +31 -97
- package/dist/api-handler.cjs.map +1 -1
- package/dist/api-handler.d.cts +2 -1
- package/dist/api-handler.d.ts +2 -1
- package/dist/api-handler.js +19 -95
- package/dist/api-handler.js.map +1 -1
- package/dist/{tenant-B1YB0Jy8.d.ts → base-B71y_EAF.d.cts} +6 -12
- package/dist/{tenant-Cpeveji6.d.cts → base-DaqY2GhA.d.ts} +6 -12
- package/dist/bootstrap-5NLASFOG.cjs +32 -0
- package/dist/{bootstrap-AKAUP6F6.cjs.map → bootstrap-5NLASFOG.cjs.map} +1 -1
- package/dist/bootstrap-T5BK77LD.js +7 -0
- package/dist/{bootstrap-JCML6NFO.js.map → bootstrap-T5BK77LD.js.map} +1 -1
- package/dist/{chunk-35U3FROB.js → chunk-22M4O4ZJ.js} +607 -63
- package/dist/chunk-22M4O4ZJ.js.map +1 -0
- package/dist/chunk-2HZRBATX.cjs +253 -0
- package/dist/chunk-2HZRBATX.cjs.map +1 -0
- package/dist/{chunk-VJT6P4N6.cjs → chunk-3HR772HI.cjs} +199 -32
- package/dist/chunk-3HR772HI.cjs.map +1 -0
- package/dist/chunk-3KTWGODI.cjs +178 -0
- package/dist/chunk-3KTWGODI.cjs.map +1 -0
- package/dist/{chunk-QXIQWPAP.js → chunk-3UK5XBVJ.js} +4 -134
- package/dist/chunk-3UK5XBVJ.js.map +1 -0
- package/dist/{chunk-FXYP2HA6.js → chunk-4AO3A3JM.js} +48 -4
- package/dist/chunk-4AO3A3JM.js.map +1 -0
- package/dist/chunk-4M7X5HAB.cjs +173 -0
- package/dist/chunk-4M7X5HAB.cjs.map +1 -0
- package/dist/chunk-5EPFQUQD.js +3243 -0
- package/dist/chunk-5EPFQUQD.js.map +1 -0
- package/dist/{chunk-Y3N7UUDO.js → chunk-7OGPN7MP.js} +5 -2
- package/dist/chunk-7OGPN7MP.js.map +1 -0
- package/dist/{chunk-WOWUL7ZY.js → chunk-AL5KX63J.js} +4 -3
- package/dist/chunk-AL5KX63J.js.map +1 -0
- package/dist/{chunk-2OL4O2TH.cjs → chunk-C36TMDTY.cjs} +66 -61
- package/dist/chunk-C36TMDTY.cjs.map +1 -0
- package/dist/{chunk-ES5HNFFT.js → chunk-CF7OL6HR.js} +4 -2
- package/dist/chunk-CF7OL6HR.js.map +1 -0
- package/dist/chunk-CJONKRHJ.js +162 -0
- package/dist/chunk-CJONKRHJ.js.map +1 -0
- package/dist/{chunk-2KVHZE6O.cjs → chunk-COIASRDK.cjs} +202 -46
- package/dist/chunk-COIASRDK.cjs.map +1 -0
- package/dist/chunk-DEVFAKCQ.cjs +3291 -0
- package/dist/chunk-DEVFAKCQ.cjs.map +1 -0
- package/dist/{chunk-3ZFYL34R.js → chunk-DYTZ6FQ7.js} +12 -185
- package/dist/chunk-DYTZ6FQ7.js.map +1 -0
- package/dist/{chunk-QPPDLRNR.js → chunk-EJN2PAOE.js} +197 -41
- package/dist/chunk-EJN2PAOE.js.map +1 -0
- package/dist/chunk-FAXU7BMP.js +220 -0
- package/dist/chunk-FAXU7BMP.js.map +1 -0
- package/dist/{chunk-OHVB4AJ7.js → chunk-FOPGUM27.js} +22 -17
- package/dist/chunk-FOPGUM27.js.map +1 -0
- package/dist/chunk-GAOXD3XT.js +175 -0
- package/dist/chunk-GAOXD3XT.js.map +1 -0
- package/dist/{chunk-4DA7QPLA.cjs → chunk-GXFOGU7N.cjs} +5 -2
- package/dist/chunk-GXFOGU7N.cjs.map +1 -0
- package/dist/{chunk-I7HHI6QV.cjs → chunk-IDVRRRAK.cjs} +17 -9
- package/dist/chunk-IDVRRRAK.cjs.map +1 -0
- package/dist/{chunk-WQBRWOQT.cjs → chunk-JOPVMWTM.cjs} +3 -2
- package/dist/chunk-JOPVMWTM.cjs.map +1 -0
- package/dist/chunk-KC2GDBLS.cjs +84 -0
- package/dist/chunk-KC2GDBLS.cjs.map +1 -0
- package/dist/{chunk-K7JPTH3G.cjs → chunk-KNRSROWB.cjs} +132 -74
- package/dist/chunk-KNRSROWB.cjs.map +1 -0
- package/dist/{chunk-3AJE4SEG.js → chunk-KPA4AN4R.js} +125 -67
- package/dist/chunk-KPA4AN4R.js.map +1 -0
- package/dist/{chunk-QUW2RZTM.cjs → chunk-L46ROHUS.cjs} +51 -7
- package/dist/chunk-L46ROHUS.cjs.map +1 -0
- package/dist/chunk-L4EZKIEX.js +185 -0
- package/dist/chunk-L4EZKIEX.js.map +1 -0
- package/dist/{chunk-REK7AYOC.js → chunk-L5UKKZQN.js} +199 -32
- package/dist/chunk-L5UKKZQN.js.map +1 -0
- package/dist/chunk-NKPKR5BW.cjs +188 -0
- package/dist/chunk-NKPKR5BW.cjs.map +1 -0
- package/dist/{chunk-Y3QQN7PN.js → chunk-P2HKJ7P5.js} +13 -4
- package/dist/chunk-P2HKJ7P5.js.map +1 -0
- package/dist/{chunk-SA7NSSIQ.cjs → chunk-PI73NNOK.cjs} +13 -187
- package/dist/chunk-PI73NNOK.cjs.map +1 -0
- package/dist/{chunk-HXRD4B37.js → chunk-PU2Z5VWF.js} +1279 -556
- package/dist/chunk-PU2Z5VWF.js.map +1 -0
- package/dist/{chunk-H727JIG7.js → chunk-Q72BOAPK.js} +16 -8
- package/dist/chunk-Q72BOAPK.js.map +1 -0
- package/dist/{chunk-IBG6V56E.cjs → chunk-QFLB4EIJ.cjs} +2 -139
- package/dist/chunk-QFLB4EIJ.cjs.map +1 -0
- package/dist/{chunk-YVUJBEXE.cjs → chunk-RAMGUDJN.cjs} +16 -7
- package/dist/chunk-RAMGUDJN.cjs.map +1 -0
- package/dist/{chunk-LINKCEG4.cjs → chunk-ROJHKAQ4.cjs} +617 -73
- package/dist/chunk-ROJHKAQ4.cjs.map +1 -0
- package/dist/{chunk-5KVM3WEY.cjs → chunk-RSF3UU7H.cjs} +1330 -602
- package/dist/chunk-RSF3UU7H.cjs.map +1 -0
- package/dist/{chunk-V3LKPM3O.cjs → chunk-SHTTJMLT.cjs} +4 -2
- package/dist/chunk-SHTTJMLT.cjs.map +1 -0
- package/dist/chunk-SPBTLUN6.js +92 -0
- package/dist/chunk-SPBTLUN6.js.map +1 -0
- package/dist/{chunk-57P6MJKC.js → chunk-TXSZFA4G.js} +3 -3
- package/dist/chunk-TXSZFA4G.js.map +1 -0
- package/dist/chunk-UERVXYVK.cjs +99 -0
- package/dist/chunk-UERVXYVK.cjs.map +1 -0
- package/dist/{chunk-PDYFVNUX.cjs → chunk-V2TVSCV5.cjs} +16 -23
- package/dist/chunk-V2TVSCV5.cjs.map +1 -0
- package/dist/{chunk-DXHRBMGB.js → chunk-VO35MNPH.js} +12 -19
- package/dist/chunk-VO35MNPH.js.map +1 -0
- package/dist/{chunk-IA6AU5PI.cjs → chunk-WNCYAKF3.cjs} +3 -3
- package/dist/chunk-WNCYAKF3.cjs.map +1 -0
- package/dist/chunk-XEB7PH2E.js +81 -0
- package/dist/chunk-XEB7PH2E.js.map +1 -0
- package/dist/cli/index.cjs +5 -5
- package/dist/cli/index.cjs.map +1 -1
- package/dist/cli/index.js +5 -5
- package/dist/cli/index.js.map +1 -1
- package/dist/client.cjs +3 -3
- package/dist/client.d.cts +3 -3
- package/dist/client.d.ts +3 -3
- package/dist/client.js +1 -1
- package/dist/drizzle/index.cjs +14 -13
- package/dist/drizzle/index.d.cts +9 -7
- package/dist/drizzle/index.d.ts +9 -7
- package/dist/drizzle/index.js +5 -4
- package/dist/fields/index.cjs +21 -37
- package/dist/fields/index.d.cts +2 -22
- package/dist/fields/index.d.ts +2 -22
- package/dist/fields/index.js +1 -1
- package/dist/graphql/index.cjs +5 -4
- package/dist/graphql/index.d.cts +5 -3
- package/dist/graphql/index.d.ts +5 -3
- package/dist/graphql/index.js +3 -2
- package/dist/index-CJXPB_ot.d.ts +276 -0
- package/dist/index-CaTNnLGd.d.cts +276 -0
- package/dist/index.cjs +304 -162
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +129 -205
- package/dist/index.d.ts +129 -205
- package/dist/index.js +172 -33
- package/dist/index.js.map +1 -1
- package/dist/integration.cjs +2 -2
- package/dist/integration.js +1 -1
- package/dist/mongo-auth-adapter-ISOM7FSS.cjs +17 -0
- package/dist/{mongo-auth-adapter-NHHUJHVH.cjs.map → mongo-auth-adapter-ISOM7FSS.cjs.map} +1 -1
- package/dist/mongo-auth-adapter-MO6STCV3.js +4 -0
- package/dist/{mongo-auth-adapter-NJQUUCTP.js.map → mongo-auth-adapter-MO6STCV3.js.map} +1 -1
- package/dist/mongodb/index.cjs +8 -7
- package/dist/mongodb/index.d.cts +5 -7
- package/dist/mongodb/index.d.ts +5 -7
- package/dist/mongodb/index.js +4 -3
- package/dist/postgres-auth-adapter-DWDR7P5G.js +5 -0
- package/dist/{postgres-auth-adapter-3T2NKTSE.js.map → postgres-auth-adapter-DWDR7P5G.js.map} +1 -1
- package/dist/postgres-auth-adapter-WRWSJD4E.cjs +14 -0
- package/dist/{postgres-auth-adapter-7IEENCKQ.cjs.map → postgres-auth-adapter-WRWSJD4E.cjs.map} +1 -1
- package/dist/redis-adapter-HGTPWIGV.js +4 -0
- package/dist/{redis-adapter-VQXD7ESY.js.map → redis-adapter-HGTPWIGV.js.map} +1 -1
- package/dist/redis-adapter-KJ3YOOT6.cjs +13 -0
- package/dist/{redis-adapter-D2E2S3GB.cjs.map → redis-adapter-KJ3YOOT6.cjs.map} +1 -1
- package/dist/rest/index.cjs +15 -14
- package/dist/rest/index.d.cts +4 -4
- package/dist/rest/index.d.ts +4 -4
- package/dist/rest/index.js +13 -12
- package/dist/{schema-5PHL5IVB.js → schema-6I5OFR4Z.js} +3 -3
- package/dist/{schema-5PHL5IVB.js.map → schema-6I5OFR4Z.js.map} +1 -1
- package/dist/{schema-37SE2F4B.cjs → schema-TTFE4467.cjs} +14 -14
- package/dist/{schema-37SE2F4B.cjs.map → schema-TTFE4467.cjs.map} +1 -1
- package/dist/sqlite-adapter-6GEUSVXQ.js +4 -0
- package/dist/{sqlite-adapter-TR3U3W6Q.js.map → sqlite-adapter-6GEUSVXQ.js.map} +1 -1
- package/dist/sqlite-adapter-CSIZE5SX.cjs +13 -0
- package/dist/{sqlite-adapter-LVK5PS4T.cjs.map → sqlite-adapter-CSIZE5SX.cjs.map} +1 -1
- package/dist/templates/index.cjs +133 -31
- package/dist/templates/index.d.cts +52 -9
- package/dist/templates/index.d.ts +52 -9
- package/dist/templates/index.js +3 -1
- package/dist/trpc/index.cjs +13 -12
- package/dist/trpc/index.d.cts +55 -49
- package/dist/trpc/index.d.ts +55 -49
- package/dist/trpc/index.js +4 -3
- package/dist/{types-D6ZLRGbH.d.cts → types-CpjuXbe7.d.cts} +2 -0
- package/dist/{types-D6ZLRGbH.d.ts → types-CpjuXbe7.d.ts} +2 -0
- package/dist/{types-Bs1up4yP.d.ts → types-CyCQ6SAI.d.ts} +28 -2
- package/dist/{types-J3R9nVsZ.d.cts → types-DJxD9394.d.cts} +28 -2
- package/dist/{types-VtjUxIMp.d.cts → types-Z6FBiqa2.d.cts} +35 -14
- package/dist/{types-VtjUxIMp.d.ts → types-Z6FBiqa2.d.ts} +35 -14
- package/package.json +22 -4
- package/dist/bootstrap-AKAUP6F6.cjs +0 -32
- package/dist/bootstrap-JCML6NFO.js +0 -7
- package/dist/chunk-2KVHZE6O.cjs.map +0 -1
- package/dist/chunk-2OL4O2TH.cjs.map +0 -1
- package/dist/chunk-35U3FROB.js.map +0 -1
- package/dist/chunk-3AJE4SEG.js.map +0 -1
- package/dist/chunk-3J4MFTI3.js +0 -3872
- package/dist/chunk-3J4MFTI3.js.map +0 -1
- package/dist/chunk-3ZFYL34R.js.map +0 -1
- package/dist/chunk-4DA7QPLA.cjs.map +0 -1
- package/dist/chunk-57P6MJKC.js.map +0 -1
- package/dist/chunk-5KVM3WEY.cjs.map +0 -1
- package/dist/chunk-6IMPH6WV.cjs +0 -3897
- package/dist/chunk-6IMPH6WV.cjs.map +0 -1
- package/dist/chunk-ATBOUGQP.cjs +0 -513
- package/dist/chunk-ATBOUGQP.cjs.map +0 -1
- package/dist/chunk-DXHRBMGB.js.map +0 -1
- package/dist/chunk-ES5HNFFT.js.map +0 -1
- package/dist/chunk-FXYP2HA6.js.map +0 -1
- package/dist/chunk-H727JIG7.js.map +0 -1
- package/dist/chunk-HXRD4B37.js.map +0 -1
- package/dist/chunk-I7HHI6QV.cjs.map +0 -1
- package/dist/chunk-IA6AU5PI.cjs.map +0 -1
- package/dist/chunk-IBG6V56E.cjs.map +0 -1
- package/dist/chunk-K7JPTH3G.cjs.map +0 -1
- package/dist/chunk-LINKCEG4.cjs.map +0 -1
- package/dist/chunk-OHVB4AJ7.js.map +0 -1
- package/dist/chunk-PDYFVNUX.cjs.map +0 -1
- package/dist/chunk-Q23JB3KL.js +0 -488
- package/dist/chunk-Q23JB3KL.js.map +0 -1
- package/dist/chunk-QPPDLRNR.js.map +0 -1
- package/dist/chunk-QUW2RZTM.cjs.map +0 -1
- package/dist/chunk-QXIQWPAP.js.map +0 -1
- package/dist/chunk-R3XIBBAW.cjs +0 -34
- package/dist/chunk-R3XIBBAW.cjs.map +0 -1
- package/dist/chunk-REK7AYOC.js.map +0 -1
- package/dist/chunk-SA7NSSIQ.cjs.map +0 -1
- package/dist/chunk-SDMNUYVU.js +0 -30
- package/dist/chunk-SDMNUYVU.js.map +0 -1
- package/dist/chunk-V3LKPM3O.cjs.map +0 -1
- package/dist/chunk-VJT6P4N6.cjs.map +0 -1
- package/dist/chunk-WOWUL7ZY.js.map +0 -1
- package/dist/chunk-WQBRWOQT.cjs.map +0 -1
- package/dist/chunk-Y3N7UUDO.js.map +0 -1
- package/dist/chunk-Y3QQN7PN.js.map +0 -1
- package/dist/chunk-YVUJBEXE.cjs.map +0 -1
- package/dist/index-CLp-DRKA.d.ts +0 -64
- package/dist/index-DfO7G4kN.d.cts +0 -64
- package/dist/mongo-auth-adapter-NHHUJHVH.cjs +0 -17
- package/dist/mongo-auth-adapter-NJQUUCTP.js +0 -4
- package/dist/postgres-auth-adapter-3T2NKTSE.js +0 -5
- package/dist/postgres-auth-adapter-7IEENCKQ.cjs +0 -14
- package/dist/redis-adapter-D2E2S3GB.cjs +0 -13
- package/dist/redis-adapter-VQXD7ESY.js +0 -4
- package/dist/sqlite-adapter-LVK5PS4T.cjs +0 -13
- package/dist/sqlite-adapter-TR3U3W6Q.js +0 -4
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
// src/auth/rbac/roles.ts
|
|
2
|
+
var DEFAULT_ROLES = [
|
|
3
|
+
{
|
|
4
|
+
name: "super_admin",
|
|
5
|
+
level: 100,
|
|
6
|
+
inherits: [],
|
|
7
|
+
description: "Full system access across all tenants"
|
|
8
|
+
},
|
|
9
|
+
{
|
|
10
|
+
name: "admin",
|
|
11
|
+
level: 90,
|
|
12
|
+
inherits: ["editor"],
|
|
13
|
+
description: "Full tenant access with all content permissions"
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
name: "editor",
|
|
17
|
+
level: 70,
|
|
18
|
+
inherits: ["author"],
|
|
19
|
+
description: "Edit and publish all content"
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
name: "author",
|
|
23
|
+
level: 50,
|
|
24
|
+
inherits: ["customer"],
|
|
25
|
+
description: "Create and edit own content"
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
name: "customer",
|
|
29
|
+
level: 30,
|
|
30
|
+
inherits: [],
|
|
31
|
+
description: "Access own data and make purchases"
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
name: "guest",
|
|
35
|
+
level: 10,
|
|
36
|
+
inherits: [],
|
|
37
|
+
description: "Public read-only access"
|
|
38
|
+
}
|
|
39
|
+
];
|
|
40
|
+
var ROLE_PERMISSIONS = {
|
|
41
|
+
super_admin: ["*"],
|
|
42
|
+
admin: [
|
|
43
|
+
"users:admin",
|
|
44
|
+
"users:read",
|
|
45
|
+
"users:update",
|
|
46
|
+
"audit_logs:read",
|
|
47
|
+
"posts:admin",
|
|
48
|
+
"posts:read",
|
|
49
|
+
"posts:create",
|
|
50
|
+
"posts:update",
|
|
51
|
+
"posts:delete",
|
|
52
|
+
"pages:admin",
|
|
53
|
+
"pages:read",
|
|
54
|
+
"pages:create",
|
|
55
|
+
"pages:update",
|
|
56
|
+
"pages:delete",
|
|
57
|
+
"media:admin",
|
|
58
|
+
"media:read",
|
|
59
|
+
"media:create",
|
|
60
|
+
"media:update",
|
|
61
|
+
"media:delete",
|
|
62
|
+
"categories:admin",
|
|
63
|
+
"categories:read",
|
|
64
|
+
"categories:create",
|
|
65
|
+
"categories:update",
|
|
66
|
+
"categories:delete",
|
|
67
|
+
"products:admin",
|
|
68
|
+
"products:read",
|
|
69
|
+
"products:create",
|
|
70
|
+
"products:update",
|
|
71
|
+
"products:delete",
|
|
72
|
+
"orders:admin",
|
|
73
|
+
"orders:read",
|
|
74
|
+
"orders:update",
|
|
75
|
+
"customers:admin",
|
|
76
|
+
"customers:read",
|
|
77
|
+
"customers:update",
|
|
78
|
+
"coupons:admin",
|
|
79
|
+
"coupons:read",
|
|
80
|
+
"coupons:create",
|
|
81
|
+
"coupons:update",
|
|
82
|
+
"coupons:delete",
|
|
83
|
+
"navigation:admin",
|
|
84
|
+
"navigation:read",
|
|
85
|
+
"navigation:create",
|
|
86
|
+
"navigation:update",
|
|
87
|
+
"navigation:delete",
|
|
88
|
+
"settings:admin",
|
|
89
|
+
"settings:read",
|
|
90
|
+
"settings:update",
|
|
91
|
+
"profile:admin",
|
|
92
|
+
"profile:read",
|
|
93
|
+
"profile:update"
|
|
94
|
+
],
|
|
95
|
+
editor: [
|
|
96
|
+
"posts:admin",
|
|
97
|
+
"posts:read",
|
|
98
|
+
"posts:create",
|
|
99
|
+
"posts:update",
|
|
100
|
+
"posts:delete",
|
|
101
|
+
"pages:admin",
|
|
102
|
+
"pages:read",
|
|
103
|
+
"pages:create",
|
|
104
|
+
"pages:update",
|
|
105
|
+
"pages:delete",
|
|
106
|
+
"media:read",
|
|
107
|
+
"media:create",
|
|
108
|
+
"media:update",
|
|
109
|
+
"categories:read",
|
|
110
|
+
"categories:create",
|
|
111
|
+
"categories:update",
|
|
112
|
+
"products:read",
|
|
113
|
+
"orders:read",
|
|
114
|
+
"orders:update",
|
|
115
|
+
"navigation:read",
|
|
116
|
+
"navigation:create",
|
|
117
|
+
"navigation:update",
|
|
118
|
+
"profile:read",
|
|
119
|
+
"profile:update"
|
|
120
|
+
],
|
|
121
|
+
author: [
|
|
122
|
+
"posts:read",
|
|
123
|
+
"posts:create",
|
|
124
|
+
"posts:update",
|
|
125
|
+
"media:read",
|
|
126
|
+
"media:create",
|
|
127
|
+
"categories:read",
|
|
128
|
+
"profile:read",
|
|
129
|
+
"profile:update"
|
|
130
|
+
],
|
|
131
|
+
customer: ["profile:read", "profile:update", "orders:read", "orders:create"],
|
|
132
|
+
guest: ["posts:read", "pages:read", "products:read"]
|
|
133
|
+
};
|
|
134
|
+
function getRoleHierarchy(role, roles = DEFAULT_ROLES) {
|
|
135
|
+
const hierarchy = [role];
|
|
136
|
+
const roleMap = new Map(roles.map((r) => [r.name, r]));
|
|
137
|
+
const addInherited = (r) => {
|
|
138
|
+
const roleData = roleMap.get(r);
|
|
139
|
+
if (roleData && roleData.inherits) {
|
|
140
|
+
for (const inherited of roleData.inherits) {
|
|
141
|
+
if (!hierarchy.includes(inherited)) {
|
|
142
|
+
hierarchy.push(inherited);
|
|
143
|
+
addInherited(inherited);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
};
|
|
148
|
+
addInherited(role);
|
|
149
|
+
return hierarchy;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
// src/auth/rbac/checker.ts
|
|
153
|
+
function hasPermission(user, permission, rolePermissions = ROLE_PERMISSIONS) {
|
|
154
|
+
if (!user || !user.role) return false;
|
|
155
|
+
const userPermissions = getUserPermissions(user, rolePermissions);
|
|
156
|
+
if (userPermissions.includes("*")) return true;
|
|
157
|
+
if (userPermissions.includes(permission)) return true;
|
|
158
|
+
const [resource, action] = permission.split(":");
|
|
159
|
+
if (userPermissions.includes(`${resource}:*`)) return true;
|
|
160
|
+
if (userPermissions.includes(`${resource}:admin`)) return true;
|
|
161
|
+
return false;
|
|
162
|
+
}
|
|
163
|
+
function hasAnyRole(user, checkRoles) {
|
|
164
|
+
if (!user || !user.role) return false;
|
|
165
|
+
const hierarchy = getRoleHierarchy(user.role);
|
|
166
|
+
return checkRoles.some((role) => hierarchy.includes(role));
|
|
167
|
+
}
|
|
168
|
+
function getUserPermissions(user, rolePermissions = ROLE_PERMISSIONS) {
|
|
169
|
+
if (!user || !user.role) return [];
|
|
170
|
+
const hierarchy = getRoleHierarchy(user.role);
|
|
171
|
+
const permissions = /* @__PURE__ */ new Set();
|
|
172
|
+
for (const role of hierarchy) {
|
|
173
|
+
const rolePerms = rolePermissions[role];
|
|
174
|
+
if (rolePerms) {
|
|
175
|
+
for (const perm of rolePerms) {
|
|
176
|
+
permissions.add(perm);
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
return Array.from(permissions);
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
export { hasAnyRole, hasPermission };
|
|
184
|
+
//# sourceMappingURL=chunk-L4EZKIEX.js.map
|
|
185
|
+
//# sourceMappingURL=chunk-L4EZKIEX.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/auth/rbac/roles.ts","../src/auth/rbac/checker.ts"],"names":[],"mappings":"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","file":"chunk-L4EZKIEX.js","sourcesContent":["export interface Role {\n name: string;\n level: number;\n inherits: string[];\n description: string;\n createdAt?: string;\n updatedAt?: string;\n}\n\nexport interface Permission {\n resource: string;\n action: \"create\" | \"read\" | \"update\" | \"delete\" | \"admin\";\n conditions?: Condition[];\n}\n\nexport interface Condition {\n field: string;\n operator:\n | \"eq\"\n | \"neq\"\n | \"in\"\n | \"nin\"\n | \"gt\"\n | \"lt\"\n | \"gte\"\n | \"lte\"\n | \"contains\";\n value: any;\n}\n\nexport interface RolePermission {\n role: string;\n permissions: Permission[];\n}\n\nexport const DEFAULT_ROLES: Role[] = [\n {\n name: \"super_admin\",\n level: 100,\n inherits: [],\n description: \"Full system access across all tenants\",\n },\n {\n name: \"admin\",\n level: 90,\n inherits: [\"editor\"],\n description: \"Full tenant access with all content permissions\",\n },\n {\n name: \"editor\",\n level: 70,\n inherits: [\"author\"],\n description: \"Edit and publish all content\",\n },\n {\n name: \"author\",\n level: 50,\n inherits: [\"customer\"],\n description: \"Create and edit own content\",\n },\n {\n name: \"customer\",\n level: 30,\n inherits: [],\n description: \"Access own data and make purchases\",\n },\n {\n name: \"guest\",\n level: 10,\n inherits: [],\n description: \"Public read-only access\",\n },\n];\n\nexport const DEFAULT_PERMISSIONS: Permission[] = [\n { resource: \"users\", action: \"admin\" },\n { resource: \"users\", action: \"read\" },\n { resource: \"users\", action: \"create\" },\n { resource: \"users\", action: \"update\" },\n { resource: \"users\", action: \"delete\" },\n\n { resource: \"audit_logs\", action: \"admin\" },\n { resource: \"audit_logs\", action: \"read\" },\n\n { resource: \"posts\", action: \"admin\" },\n { resource: \"posts\", action: \"read\" },\n { resource: \"posts\", action: \"create\" },\n { resource: \"posts\", action: \"update\" },\n { resource: \"posts\", action: \"delete\" },\n\n { resource: \"pages\", action: \"admin\" },\n { resource: \"pages\", action: \"read\" },\n { resource: \"pages\", action: \"create\" },\n { resource: \"pages\", action: \"update\" },\n { resource: \"pages\", action: \"delete\" },\n\n { resource: \"media\", action: \"admin\" },\n { resource: \"media\", action: \"read\" },\n { resource: \"media\", action: \"create\" },\n { resource: \"media\", action: \"update\" },\n { resource: \"media\", action: \"delete\" },\n\n { resource: \"categories\", action: \"admin\" },\n { resource: \"categories\", action: \"read\" },\n { resource: \"categories\", action: \"create\" },\n { resource: \"categories\", action: \"update\" },\n { resource: \"categories\", action: \"delete\" },\n\n { resource: \"products\", action: \"admin\" },\n { resource: \"products\", action: \"read\" },\n { resource: \"products\", action: \"create\" },\n { resource: \"products\", action: \"update\" },\n { resource: \"products\", action: \"delete\" },\n\n { resource: \"orders\", action: \"admin\" },\n { resource: \"orders\", action: \"read\" },\n { resource: \"orders\", action: \"create\" },\n { resource: \"orders\", action: \"update\" },\n { resource: \"orders\", action: \"delete\" },\n\n { resource: \"customers\", action: \"admin\" },\n { resource: \"customers\", action: \"read\" },\n { resource: \"customers\", action: \"create\" },\n { resource: \"customers\", action: \"update\" },\n { resource: \"customers\", action: \"delete\" },\n\n { resource: \"coupons\", action: \"admin\" },\n { resource: \"coupons\", action: \"read\" },\n { resource: \"coupons\", action: \"create\" },\n { resource: \"coupons\", action: \"update\" },\n { resource: \"coupons\", action: \"delete\" },\n\n { resource: \"menu\", action: \"admin\" },\n { resource: \"menu\", action: \"read\" },\n { resource: \"menu\", action: \"create\" },\n { resource: \"menu\", action: \"update\" },\n { resource: \"menu\", action: \"delete\" },\n\n { resource: \"settings\", action: \"admin\" },\n { resource: \"settings\", action: \"read\" },\n { resource: \"settings\", action: \"update\" },\n\n { resource: \"profile\", action: \"admin\" },\n { resource: \"profile\", action: \"read\" },\n { resource: \"profile\", action: \"update\" },\n];\n\nexport const ROLE_PERMISSIONS: Record<string, string[]> = {\n super_admin: [\"*\"],\n\n admin: [\n \"users:admin\",\n \"users:read\",\n \"users:update\",\n \"audit_logs:read\",\n \"posts:admin\",\n \"posts:read\",\n \"posts:create\",\n \"posts:update\",\n \"posts:delete\",\n \"pages:admin\",\n \"pages:read\",\n \"pages:create\",\n \"pages:update\",\n \"pages:delete\",\n \"media:admin\",\n \"media:read\",\n \"media:create\",\n \"media:update\",\n \"media:delete\",\n \"categories:admin\",\n \"categories:read\",\n \"categories:create\",\n \"categories:update\",\n \"categories:delete\",\n \"products:admin\",\n \"products:read\",\n \"products:create\",\n \"products:update\",\n \"products:delete\",\n \"orders:admin\",\n \"orders:read\",\n \"orders:update\",\n \"customers:admin\",\n \"customers:read\",\n \"customers:update\",\n \"coupons:admin\",\n \"coupons:read\",\n \"coupons:create\",\n \"coupons:update\",\n \"coupons:delete\",\n \"navigation:admin\",\n \"navigation:read\",\n \"navigation:create\",\n \"navigation:update\",\n \"navigation:delete\",\n \"settings:admin\",\n \"settings:read\",\n \"settings:update\",\n \"profile:admin\",\n \"profile:read\",\n \"profile:update\",\n ],\n\n editor: [\n \"posts:admin\",\n \"posts:read\",\n \"posts:create\",\n \"posts:update\",\n \"posts:delete\",\n \"pages:admin\",\n \"pages:read\",\n \"pages:create\",\n \"pages:update\",\n \"pages:delete\",\n \"media:read\",\n \"media:create\",\n \"media:update\",\n \"categories:read\",\n \"categories:create\",\n \"categories:update\",\n \"products:read\",\n \"orders:read\",\n \"orders:update\",\n \"navigation:read\",\n \"navigation:create\",\n \"navigation:update\",\n \"profile:read\",\n \"profile:update\",\n ],\n\n author: [\n \"posts:read\",\n \"posts:create\",\n \"posts:update\",\n \"media:read\",\n \"media:create\",\n \"categories:read\",\n \"profile:read\",\n \"profile:update\",\n ],\n\n customer: [\"profile:read\", \"profile:update\", \"orders:read\", \"orders:create\"],\n\n guest: [\"posts:read\", \"pages:read\", \"products:read\"],\n};\n\nexport function getRoleHierarchy(\n role: string,\n roles: Role[] = DEFAULT_ROLES,\n): string[] {\n const hierarchy: string[] = [role];\n const roleMap = new Map(roles.map((r) => [r.name, r]));\n\n const addInherited = (r: string) => {\n const roleData = roleMap.get(r);\n if (roleData && roleData.inherits) {\n for (const inherited of roleData.inherits) {\n if (!hierarchy.includes(inherited)) {\n hierarchy.push(inherited);\n addInherited(inherited);\n }\n }\n }\n };\n\n addInherited(role);\n return hierarchy;\n}\n\nexport function getRoleLevel(\n role: string,\n roles: Role[] = DEFAULT_ROLES,\n): number {\n const roleMap = new Map(roles.map((r) => [r.name, r]));\n const roleData = roleMap.get(role);\n return roleData?.level ?? 0;\n}\n\nexport function isRoleHigherOrEqual(\n role1: string,\n role2: string,\n roles: Role[] = DEFAULT_ROLES,\n): boolean {\n return getRoleLevel(role1, roles) >= getRoleLevel(role2, roles);\n}\n\nexport function canInheritRole(\n role: string,\n targetRole: string,\n roles: Role[] = DEFAULT_ROLES,\n): boolean {\n const hierarchy = getRoleHierarchy(role, roles);\n return hierarchy.includes(targetRole);\n}\n","import type { AuthUser } from \"../types.js\";\nimport {\n ROLE_PERMISSIONS,\n getRoleHierarchy,\n type Permission,\n type Condition,\n} from \"./roles.js\";\n\nexport interface PermissionContext {\n user: AuthUser;\n resource?: string;\n action?: string;\n doc?: Record<string, any>;\n data?: Record<string, any>;\n tenantId?: string;\n}\n\nexport function hasPermission(\n user: AuthUser,\n permission: string,\n rolePermissions: Record<string, string[]> = ROLE_PERMISSIONS,\n): boolean {\n if (!user || !user.role) return false;\n\n const userPermissions = getUserPermissions(user, rolePermissions);\n\n if (userPermissions.includes(\"*\")) return true;\n if (userPermissions.includes(permission)) return true;\n\n const [resource, action] = permission.split(\":\");\n if (userPermissions.includes(`${resource}:*`)) return true;\n if (userPermissions.includes(`${resource}:admin`)) return true;\n\n return false;\n}\n\nexport function hasRole(\n user: AuthUser,\n role: string,\n roles: string[] = [],\n): boolean {\n if (!user || !user.role) return false;\n\n const hierarchy = getRoleHierarchy(user.role);\n return hierarchy.includes(role);\n}\n\nexport function hasAnyRole(user: AuthUser, checkRoles: string[]): boolean {\n if (!user || !user.role) return false;\n\n const hierarchy = getRoleHierarchy(user.role);\n return checkRoles.some((role) => hierarchy.includes(role));\n}\n\nexport function hasAllRoles(user: AuthUser, checkRoles: string[]): boolean {\n if (!user || !user.role) return false;\n\n const hierarchy = getRoleHierarchy(user.role);\n return checkRoles.every((role) => hierarchy.includes(role));\n}\n\nexport function getUserPermissions(\n user: AuthUser,\n rolePermissions: Record<string, string[]> = ROLE_PERMISSIONS,\n): string[] {\n if (!user || !user.role) return [];\n\n const hierarchy = getRoleHierarchy(user.role);\n const permissions = new Set<string>();\n\n for (const role of hierarchy) {\n const rolePerms = rolePermissions[role];\n if (rolePerms) {\n for (const perm of rolePerms) {\n permissions.add(perm);\n }\n }\n }\n\n return Array.from(permissions);\n}\n\nexport function getEffectivePermissions(\n user: AuthUser,\n rolePermissions: Record<string, string[]> = ROLE_PERMISSIONS,\n): string[] {\n return getUserPermissions(user, rolePermissions);\n}\n\nexport function canAccessResource(\n user: AuthUser,\n resource: string,\n action: string,\n rolePermissions: Record<string, string[]> = ROLE_PERMISSIONS,\n): boolean {\n return hasPermission(user, `${resource}:${action}`, rolePermissions);\n}\n\nexport function filterPermissions(\n permissions: string[],\n resource?: string,\n): string[] {\n if (!resource) return permissions;\n\n return permissions.filter((perm) => {\n const [permResource] = perm.split(\":\");\n return permResource === resource || permResource === \"*\";\n });\n}\n\nexport function parsePermission(permission: string): {\n resource: string;\n action: string;\n condition?: Condition;\n} {\n const [resource, action, ...rest] = permission.split(\":\");\n return {\n resource,\n action,\n condition: rest.length > 0 ? JSON.parse(rest.join(\":\")) : undefined,\n };\n}\n\nexport function buildPermission(\n resource: string,\n action: string,\n condition?: Condition,\n): string {\n if (condition) {\n return `${resource}:${action}:${JSON.stringify(condition)}`;\n }\n return `${resource}:${action}`;\n}\n\nexport function evaluateCondition(\n condition: Condition,\n context: Record<string, any>,\n): boolean {\n const { field, operator, value } = condition;\n const fieldValue = context[field];\n\n if (fieldValue === undefined) return false;\n\n switch (operator) {\n case \"eq\":\n return fieldValue === value;\n case \"neq\":\n return fieldValue !== value;\n case \"in\":\n return Array.isArray(value) && value.includes(fieldValue);\n case \"nin\":\n return Array.isArray(value) && !value.includes(fieldValue);\n case \"gt\":\n return fieldValue > value;\n case \"lt\":\n return fieldValue < value;\n case \"gte\":\n return fieldValue >= value;\n case \"lte\":\n return fieldValue <= value;\n case \"contains\":\n if (typeof fieldValue === \"string\") {\n return fieldValue.includes(value);\n }\n if (Array.isArray(fieldValue)) {\n return fieldValue.includes(value);\n }\n return false;\n default:\n return false;\n }\n}\n\nexport function evaluateConditions(\n conditions: Condition[],\n context: Record<string, any>,\n): boolean {\n if (!conditions || conditions.length === 0) return true;\n\n return conditions.every((condition) => evaluateCondition(condition, context));\n}\n\nexport function resolveConditionValue(\n value: any,\n context: Record<string, any>,\n): any {\n if (typeof value !== \"string\") return value;\n\n if (value.startsWith(\"${\") && value.endsWith(\"}\")) {\n const path = value.slice(2, -1);\n const keys = path.split(\".\");\n let resolved = context;\n\n for (const key of keys) {\n if (resolved === undefined || resolved === null) return undefined;\n resolved = resolved[key];\n }\n\n return resolved;\n }\n\n return value;\n}\n\nexport function evaluateConditionWithContext(\n condition: Condition,\n context: Record<string, any>,\n): boolean {\n const resolvedCondition = {\n ...condition,\n value: resolveConditionValue(condition.value, context),\n };\n\n return evaluateCondition(resolvedCondition, context);\n}\n\nexport class PermissionChecker {\n private rolePermissions: Record<string, string[]>;\n\n constructor(rolePermissions: Record<string, string[]> = ROLE_PERMISSIONS) {\n this.rolePermissions = rolePermissions;\n }\n\n check(user: AuthUser, permission: string): boolean {\n return hasPermission(user, permission, this.rolePermissions);\n }\n\n checkRole(user: AuthUser, role: string): boolean {\n return hasRole(user, role);\n }\n\n checkAnyRole(user: AuthUser, roles: string[]): boolean {\n return hasAnyRole(user, roles);\n }\n\n checkAllRoles(user: AuthUser, roles: string[]): boolean {\n return hasAllRoles(user, roles);\n }\n\n getPermissions(user: AuthUser): string[] {\n return getUserPermissions(user, this.rolePermissions);\n }\n\n canAccess(user: AuthUser, resource: string, action: string): boolean {\n return canAccessResource(user, resource, action, this.rolePermissions);\n }\n\n filterByResource(permissions: string[], resource: string): string[] {\n return filterPermissions(permissions, resource);\n }\n}\n"]}
|
|
@@ -1,8 +1,52 @@
|
|
|
1
|
-
import { evaluateAccess } from './chunk-
|
|
2
|
-
import {
|
|
1
|
+
import { hasApiKeyPermission, evaluateAccess } from './chunk-CJONKRHJ.js';
|
|
2
|
+
import { hasPermission } from './chunk-L4EZKIEX.js';
|
|
3
|
+
import { GraphQLObjectType, GraphQLString, GraphQLInputObjectType, GraphQLBoolean, GraphQLInt, GraphQLList, GraphQLNonNull, GraphQLSchema, GraphQLFloat } from 'graphql';
|
|
3
4
|
|
|
4
5
|
async function checkGraphQLAccess(collection, operation, context) {
|
|
5
6
|
const accessRule = collection.access?.[operation];
|
|
7
|
+
if (context.apiKey?.permissions?.length > 0) {
|
|
8
|
+
const resource = collection.slug;
|
|
9
|
+
const action = operation === "read" ? "read" : operation === "create" ? "create" : "update";
|
|
10
|
+
const permission = `${resource}:${action}`;
|
|
11
|
+
if (!hasApiKeyPermission(context.apiKey.permissions, permission) && !hasApiKeyPermission(context.apiKey.permissions, `${resource}:admin`)) {
|
|
12
|
+
return { allowed: false };
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
if (context.user) {
|
|
16
|
+
const resource = collection.slug;
|
|
17
|
+
const action = operation === "read" ? "read" : operation === "create" ? "create" : operation === "update" ? "update" : "delete";
|
|
18
|
+
const permission = `${resource}:${action}`;
|
|
19
|
+
const userHasPermission = hasPermission(
|
|
20
|
+
{ id: context.user.id, email: context.user.email, role: context.user.role },
|
|
21
|
+
permission
|
|
22
|
+
);
|
|
23
|
+
if (!userHasPermission && !hasPermission(
|
|
24
|
+
{ id: context.user.id, email: context.user.email, role: context.user.role },
|
|
25
|
+
`${resource}:admin`
|
|
26
|
+
)) {
|
|
27
|
+
if (!accessRule) {
|
|
28
|
+
return { allowed: false };
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
if (!accessRule) {
|
|
33
|
+
if (!context.user && !context.apiKey) {
|
|
34
|
+
return { allowed: false };
|
|
35
|
+
}
|
|
36
|
+
return { allowed: true };
|
|
37
|
+
}
|
|
38
|
+
const result = await evaluateAccess(accessRule, {
|
|
39
|
+
req: context.req,
|
|
40
|
+
user: context.user,
|
|
41
|
+
tenantID: context.tenantID
|
|
42
|
+
});
|
|
43
|
+
if (typeof result === "boolean") {
|
|
44
|
+
return { allowed: result };
|
|
45
|
+
}
|
|
46
|
+
return { allowed: true, extraWhere: result };
|
|
47
|
+
}
|
|
48
|
+
async function checkGlobalAccess(global, operation, context) {
|
|
49
|
+
const accessRule = global.access?.[operation];
|
|
6
50
|
if (!accessRule) {
|
|
7
51
|
if (!context.user) {
|
|
8
52
|
return { allowed: false };
|
|
@@ -21,9 +65,9 @@ async function checkGraphQLAccess(collection, operation, context) {
|
|
|
21
65
|
if (typeof result === "boolean") {
|
|
22
66
|
return { allowed: result };
|
|
23
67
|
}
|
|
24
|
-
return { allowed: true
|
|
68
|
+
return { allowed: true };
|
|
25
69
|
}
|
|
26
|
-
function fieldToGraphQLType(field, registry) {
|
|
70
|
+
function fieldToGraphQLType(field, registry, collectionTypes, isInputType = false) {
|
|
27
71
|
switch (field.type) {
|
|
28
72
|
case "text":
|
|
29
73
|
case "email":
|
|
@@ -47,13 +91,19 @@ function fieldToGraphQLType(field, registry) {
|
|
|
47
91
|
// JSON as string
|
|
48
92
|
case "relationship":
|
|
49
93
|
if (typeof field.relationTo === "string") {
|
|
94
|
+
if (isInputType) {
|
|
95
|
+
return GraphQLString;
|
|
96
|
+
}
|
|
97
|
+
if (collectionTypes?.[field.relationTo]) {
|
|
98
|
+
return collectionTypes[field.relationTo];
|
|
99
|
+
}
|
|
50
100
|
const relatedCollection = registry.getCollection(field.relationTo);
|
|
51
101
|
if (relatedCollection) {
|
|
52
102
|
return new GraphQLObjectType({
|
|
53
103
|
name: `${field.relationTo}_ref`,
|
|
54
104
|
fields: () => ({
|
|
55
105
|
id: { type: GraphQLString },
|
|
56
|
-
...buildFieldsFromCollection(relatedCollection, registry)
|
|
106
|
+
...buildFieldsFromCollection(relatedCollection, registry, collectionTypes)
|
|
57
107
|
})
|
|
58
108
|
});
|
|
59
109
|
}
|
|
@@ -76,12 +126,12 @@ function fieldToGraphQLType(field, registry) {
|
|
|
76
126
|
return GraphQLString;
|
|
77
127
|
}
|
|
78
128
|
}
|
|
79
|
-
function buildFieldsFromCollection(config, registry) {
|
|
129
|
+
function buildFieldsFromCollection(config, registry, collectionTypes) {
|
|
80
130
|
const fields = {};
|
|
81
131
|
for (const field of config.fields) {
|
|
82
132
|
if (field.name && field.admin?.hidden !== true) {
|
|
83
133
|
fields[field.name] = {
|
|
84
|
-
type: field.required ? new GraphQLNonNull(fieldToGraphQLType(field, registry)) : fieldToGraphQLType(field, registry),
|
|
134
|
+
type: field.required ? new GraphQLNonNull(fieldToGraphQLType(field, registry, collectionTypes)) : fieldToGraphQLType(field, registry, collectionTypes),
|
|
85
135
|
description: field.admin?.description || field.label
|
|
86
136
|
};
|
|
87
137
|
}
|
|
@@ -89,7 +139,7 @@ function buildFieldsFromCollection(config, registry) {
|
|
|
89
139
|
return fields;
|
|
90
140
|
}
|
|
91
141
|
function buildGraphQLSchema(options) {
|
|
92
|
-
const { registry, db, user, req, tenantID, settings } = options;
|
|
142
|
+
const { registry, db, user, req, tenantID, apiKey, settings } = options;
|
|
93
143
|
const apiAccess = settings?.access?.apiAccess;
|
|
94
144
|
if (apiAccess?.graphqlEnabled === false) {
|
|
95
145
|
throw new Error("GraphQL API is disabled");
|
|
@@ -103,7 +153,7 @@ function buildGraphQLSchema(options) {
|
|
|
103
153
|
name: `${collection.slug.replace(/-/g, "_")}_type`,
|
|
104
154
|
fields: () => ({
|
|
105
155
|
id: { type: GraphQLString },
|
|
106
|
-
...buildFieldsFromCollection(collection, registry),
|
|
156
|
+
...buildFieldsFromCollection(collection, registry, collectionTypes),
|
|
107
157
|
...collection.timestamps ? {
|
|
108
158
|
createdAt: { type: GraphQLString },
|
|
109
159
|
updatedAt: { type: GraphQLString }
|
|
@@ -117,7 +167,7 @@ function buildGraphQLSchema(options) {
|
|
|
117
167
|
for (const field of collection.fields) {
|
|
118
168
|
if (field.name && field.name !== "id") {
|
|
119
169
|
inputFields[field.name] = {
|
|
120
|
-
type: fieldToGraphQLType(field, registry)
|
|
170
|
+
type: fieldToGraphQLType(field, registry, collectionTypes, true)
|
|
121
171
|
};
|
|
122
172
|
}
|
|
123
173
|
}
|
|
@@ -127,6 +177,7 @@ function buildGraphQLSchema(options) {
|
|
|
127
177
|
});
|
|
128
178
|
}
|
|
129
179
|
const globalTypes = {};
|
|
180
|
+
const globalInputTypes = {};
|
|
130
181
|
for (const global of globals) {
|
|
131
182
|
globalTypes[global.slug] = new GraphQLObjectType({
|
|
132
183
|
name: `${global.slug.replace(/-/g, "_")}_global_type`,
|
|
@@ -134,16 +185,31 @@ function buildGraphQLSchema(options) {
|
|
|
134
185
|
id: { type: GraphQLString },
|
|
135
186
|
...buildFieldsFromCollection(
|
|
136
187
|
{ slug: global.slug, fields: global.fields },
|
|
137
|
-
registry
|
|
188
|
+
registry,
|
|
189
|
+
collectionTypes
|
|
138
190
|
)
|
|
139
191
|
})
|
|
140
192
|
});
|
|
193
|
+
globalInputTypes[global.slug] = new GraphQLInputObjectType({
|
|
194
|
+
name: `${global.slug.replace(/-/g, "_")}_global_input`,
|
|
195
|
+
fields: () => {
|
|
196
|
+
const inputFields = {};
|
|
197
|
+
for (const field of global.fields) {
|
|
198
|
+
if (field.name && field.name !== "id") {
|
|
199
|
+
inputFields[field.name] = {
|
|
200
|
+
type: fieldToGraphQLType(field, registry, collectionTypes, true)
|
|
201
|
+
};
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
return inputFields;
|
|
205
|
+
}
|
|
206
|
+
});
|
|
141
207
|
}
|
|
142
208
|
const queryFields = {};
|
|
143
209
|
for (const collection of collections) {
|
|
144
210
|
const type = collectionTypes[collection.slug];
|
|
145
211
|
if (!type) continue;
|
|
146
|
-
queryFields[`${collection.slug}Find`] = {
|
|
212
|
+
queryFields[`${collection.slug.replace(/-/g, "_")}Find`] = {
|
|
147
213
|
type: new GraphQLObjectType({
|
|
148
214
|
name: `${collection.slug.replace(/-/g, "_")}_find_result`,
|
|
149
215
|
fields: {
|
|
@@ -159,17 +225,22 @@ function buildGraphQLSchema(options) {
|
|
|
159
225
|
where: { type: GraphQLString },
|
|
160
226
|
sort: { type: GraphQLString },
|
|
161
227
|
limit: { type: GraphQLInt },
|
|
162
|
-
page: { type: GraphQLInt }
|
|
228
|
+
page: { type: GraphQLInt },
|
|
229
|
+
draft: { type: GraphQLBoolean }
|
|
163
230
|
},
|
|
164
231
|
resolve: async (_, args, context) => {
|
|
165
232
|
const access = await checkGraphQLAccess(collection, "read", {
|
|
166
233
|
user,
|
|
167
234
|
req,
|
|
168
|
-
tenantID
|
|
235
|
+
tenantID,
|
|
236
|
+
apiKey
|
|
169
237
|
});
|
|
170
238
|
if (!access.allowed) {
|
|
171
239
|
throw new Error("Access denied");
|
|
172
240
|
}
|
|
241
|
+
if (tenantID) {
|
|
242
|
+
db.setTenantContext({ tenantId: tenantID, userId: user?.id ?? "", role: user?.role, isSuperAdmin: user?.role === "super_admin" });
|
|
243
|
+
}
|
|
173
244
|
let where = {};
|
|
174
245
|
if (args.where) {
|
|
175
246
|
try {
|
|
@@ -180,39 +251,48 @@ function buildGraphQLSchema(options) {
|
|
|
180
251
|
if (access.extraWhere) {
|
|
181
252
|
where = { ...where, ...access.extraWhere };
|
|
182
253
|
}
|
|
254
|
+
const isDraft = args.draft ?? !!user;
|
|
183
255
|
return db.find({
|
|
184
256
|
collection: collection.slug,
|
|
185
257
|
where,
|
|
186
258
|
sort: args.sort,
|
|
187
259
|
limit: args.limit || 10,
|
|
188
260
|
page: args.page || 1,
|
|
189
|
-
tenantID
|
|
261
|
+
tenantID,
|
|
262
|
+
draft: isDraft
|
|
190
263
|
});
|
|
191
264
|
}
|
|
192
265
|
};
|
|
193
|
-
queryFields[`${collection.slug}FindByID`] = {
|
|
266
|
+
queryFields[`${collection.slug.replace(/-/g, "_")}FindByID`] = {
|
|
194
267
|
type,
|
|
195
268
|
args: {
|
|
196
|
-
id: { type: new GraphQLNonNull(GraphQLString) }
|
|
269
|
+
id: { type: new GraphQLNonNull(GraphQLString) },
|
|
270
|
+
draft: { type: GraphQLBoolean }
|
|
197
271
|
},
|
|
198
272
|
resolve: async (_, args, context) => {
|
|
199
273
|
const access = await checkGraphQLAccess(collection, "read", {
|
|
200
274
|
user,
|
|
201
275
|
req,
|
|
202
|
-
tenantID
|
|
276
|
+
tenantID,
|
|
277
|
+
apiKey
|
|
203
278
|
});
|
|
204
279
|
if (!access.allowed) {
|
|
205
280
|
throw new Error("Access denied");
|
|
206
281
|
}
|
|
282
|
+
if (tenantID) {
|
|
283
|
+
db.setTenantContext({ tenantId: tenantID, userId: user?.id ?? "", role: user?.role, isSuperAdmin: user?.role === "super_admin" });
|
|
284
|
+
}
|
|
285
|
+
const isDraft = args.draft ?? !!user;
|
|
207
286
|
const doc = await db.findByID({
|
|
208
287
|
collection: collection.slug,
|
|
209
288
|
id: args.id,
|
|
210
|
-
tenantID
|
|
289
|
+
tenantID,
|
|
290
|
+
draft: isDraft
|
|
211
291
|
});
|
|
212
292
|
return doc;
|
|
213
293
|
}
|
|
214
294
|
};
|
|
215
|
-
queryFields[`${collection.slug}Count`] = {
|
|
295
|
+
queryFields[`${collection.slug.replace(/-/g, "_")}Count`] = {
|
|
216
296
|
type: new GraphQLObjectType({
|
|
217
297
|
name: `${collection.slug.replace(/-/g, "_")}_count`,
|
|
218
298
|
fields: {
|
|
@@ -226,7 +306,8 @@ function buildGraphQLSchema(options) {
|
|
|
226
306
|
const access = await checkGraphQLAccess(collection, "read", {
|
|
227
307
|
user,
|
|
228
308
|
req,
|
|
229
|
-
tenantID
|
|
309
|
+
tenantID,
|
|
310
|
+
apiKey
|
|
230
311
|
});
|
|
231
312
|
if (!access.allowed) {
|
|
232
313
|
return { totalDocs: 0 };
|
|
@@ -250,9 +331,20 @@ function buildGraphQLSchema(options) {
|
|
|
250
331
|
for (const global of globals) {
|
|
251
332
|
const type = globalTypes[global.slug];
|
|
252
333
|
if (!type) continue;
|
|
253
|
-
queryFields[`${global.slug}Get`] = {
|
|
334
|
+
queryFields[`${global.slug.replace(/-/g, "_")}Get`] = {
|
|
254
335
|
type,
|
|
255
336
|
resolve: async () => {
|
|
337
|
+
const access = await checkGlobalAccess(global, "read", {
|
|
338
|
+
user,
|
|
339
|
+
req,
|
|
340
|
+
tenantID
|
|
341
|
+
});
|
|
342
|
+
if (!access.allowed) {
|
|
343
|
+
throw new Error("Access denied: cannot read global");
|
|
344
|
+
}
|
|
345
|
+
if (tenantID) {
|
|
346
|
+
db.setTenantContext({ tenantId: tenantID, userId: user?.id ?? "", role: user?.role, isSuperAdmin: user?.role === "super_admin" });
|
|
347
|
+
}
|
|
256
348
|
return db.findOne({
|
|
257
349
|
collection: `_globals_${global.slug}`,
|
|
258
350
|
where: {},
|
|
@@ -270,7 +362,7 @@ function buildGraphQLSchema(options) {
|
|
|
270
362
|
const type = collectionTypes[collection.slug];
|
|
271
363
|
const inputType = collectionInputTypes[collection.slug];
|
|
272
364
|
if (!type || !inputType) continue;
|
|
273
|
-
mutationFields[`${collection.slug}Create`] = {
|
|
365
|
+
mutationFields[`${collection.slug.replace(/-/g, "_")}Create`] = {
|
|
274
366
|
type: new GraphQLObjectType({
|
|
275
367
|
name: `${collection.slug.replace(/-/g, "_")}_create_result`,
|
|
276
368
|
fields: {
|
|
@@ -285,11 +377,15 @@ function buildGraphQLSchema(options) {
|
|
|
285
377
|
const access = await checkGraphQLAccess(collection, "create", {
|
|
286
378
|
user,
|
|
287
379
|
req,
|
|
288
|
-
tenantID
|
|
380
|
+
tenantID,
|
|
381
|
+
apiKey
|
|
289
382
|
});
|
|
290
383
|
if (!access.allowed) {
|
|
291
384
|
throw new Error("Access denied: cannot create");
|
|
292
385
|
}
|
|
386
|
+
if (tenantID) {
|
|
387
|
+
db.setTenantContext({ tenantId: tenantID, userId: user?.id ?? "", role: user?.role, isSuperAdmin: user?.role === "super_admin" });
|
|
388
|
+
}
|
|
293
389
|
const schema = registry.getCreateZodSchema(collection.slug);
|
|
294
390
|
const validated = schema.parse(args.data);
|
|
295
391
|
const doc = await db.create({
|
|
@@ -300,7 +396,7 @@ function buildGraphQLSchema(options) {
|
|
|
300
396
|
return { doc, message: "Created successfully" };
|
|
301
397
|
}
|
|
302
398
|
};
|
|
303
|
-
mutationFields[`${collection.slug}Update`] = {
|
|
399
|
+
mutationFields[`${collection.slug.replace(/-/g, "_")}Update`] = {
|
|
304
400
|
type: new GraphQLObjectType({
|
|
305
401
|
name: `${collection.slug.replace(/-/g, "_")}_update_result`,
|
|
306
402
|
fields: {
|
|
@@ -310,17 +406,33 @@ function buildGraphQLSchema(options) {
|
|
|
310
406
|
}),
|
|
311
407
|
args: {
|
|
312
408
|
id: { type: new GraphQLNonNull(GraphQLString) },
|
|
313
|
-
data: { type: new GraphQLNonNull(inputType) }
|
|
409
|
+
data: { type: new GraphQLNonNull(inputType) },
|
|
410
|
+
baseUpdatedAt: { type: GraphQLString }
|
|
314
411
|
},
|
|
315
412
|
resolve: async (_, args, context) => {
|
|
316
413
|
const access = await checkGraphQLAccess(collection, "update", {
|
|
317
414
|
user,
|
|
318
415
|
req,
|
|
319
|
-
tenantID
|
|
416
|
+
tenantID,
|
|
417
|
+
apiKey
|
|
320
418
|
});
|
|
321
419
|
if (!access.allowed) {
|
|
322
420
|
throw new Error("Access denied: cannot update");
|
|
323
421
|
}
|
|
422
|
+
if (tenantID) {
|
|
423
|
+
db.setTenantContext({ tenantId: tenantID, userId: user?.id ?? "", role: user?.role, isSuperAdmin: user?.role === "super_admin" });
|
|
424
|
+
}
|
|
425
|
+
if (args.baseUpdatedAt) {
|
|
426
|
+
const originalDoc = await db.findByID({
|
|
427
|
+
collection: collection.slug,
|
|
428
|
+
id: args.id,
|
|
429
|
+
tenantID,
|
|
430
|
+
draft: true
|
|
431
|
+
});
|
|
432
|
+
if (originalDoc && originalDoc.updatedAt && args.baseUpdatedAt !== originalDoc.updatedAt) {
|
|
433
|
+
throw new Error(`Revision conflict: document has changed since ${args.baseUpdatedAt}. Current updatedAt: ${originalDoc.updatedAt}`);
|
|
434
|
+
}
|
|
435
|
+
}
|
|
324
436
|
const schema = registry.getUpdateZodSchema(collection.slug);
|
|
325
437
|
const validated = schema.parse(args.data);
|
|
326
438
|
const doc = await db.update({
|
|
@@ -332,7 +444,7 @@ function buildGraphQLSchema(options) {
|
|
|
332
444
|
return { doc, message: "Updated successfully" };
|
|
333
445
|
}
|
|
334
446
|
};
|
|
335
|
-
mutationFields[`${collection.slug}Delete`] = {
|
|
447
|
+
mutationFields[`${collection.slug.replace(/-/g, "_")}Delete`] = {
|
|
336
448
|
type: new GraphQLObjectType({
|
|
337
449
|
name: `${collection.slug.replace(/-/g, "_")}_delete_result`,
|
|
338
450
|
fields: {
|
|
@@ -347,11 +459,15 @@ function buildGraphQLSchema(options) {
|
|
|
347
459
|
const access = await checkGraphQLAccess(collection, "delete", {
|
|
348
460
|
user,
|
|
349
461
|
req,
|
|
350
|
-
tenantID
|
|
462
|
+
tenantID,
|
|
463
|
+
apiKey
|
|
351
464
|
});
|
|
352
465
|
if (!access.allowed) {
|
|
353
466
|
throw new Error("Access denied: cannot delete");
|
|
354
467
|
}
|
|
468
|
+
if (tenantID) {
|
|
469
|
+
db.setTenantContext({ tenantId: tenantID, userId: user?.id ?? "", role: user?.role, isSuperAdmin: user?.role === "super_admin" });
|
|
470
|
+
}
|
|
355
471
|
const doc = await db.delete({
|
|
356
472
|
collection: collection.slug,
|
|
357
473
|
id: args.id,
|
|
@@ -361,6 +477,56 @@ function buildGraphQLSchema(options) {
|
|
|
361
477
|
}
|
|
362
478
|
};
|
|
363
479
|
}
|
|
480
|
+
for (const global of globals) {
|
|
481
|
+
const inputType = globalInputTypes[global.slug];
|
|
482
|
+
if (!inputType) continue;
|
|
483
|
+
mutationFields[`${global.slug.replace(/-/g, "_")}Update`] = {
|
|
484
|
+
type: new GraphQLObjectType({
|
|
485
|
+
name: `${global.slug.replace(/-/g, "_")}_update_result`,
|
|
486
|
+
fields: {
|
|
487
|
+
doc: { type: globalTypes[global.slug] || GraphQLString },
|
|
488
|
+
message: { type: GraphQLString }
|
|
489
|
+
}
|
|
490
|
+
}),
|
|
491
|
+
args: {
|
|
492
|
+
data: { type: new GraphQLNonNull(inputType) }
|
|
493
|
+
},
|
|
494
|
+
resolve: async (_, args, context) => {
|
|
495
|
+
const access = await checkGlobalAccess(global, "update", {
|
|
496
|
+
user,
|
|
497
|
+
req,
|
|
498
|
+
tenantID
|
|
499
|
+
});
|
|
500
|
+
if (!access.allowed) {
|
|
501
|
+
throw new Error("Access denied: cannot update global");
|
|
502
|
+
}
|
|
503
|
+
if (tenantID) {
|
|
504
|
+
db.setTenantContext({ tenantId: tenantID, userId: user?.id ?? "", role: user?.role, isSuperAdmin: user?.role === "super_admin" });
|
|
505
|
+
}
|
|
506
|
+
const doc = await db.findOne({
|
|
507
|
+
collection: `_globals_${global.slug}`,
|
|
508
|
+
where: {},
|
|
509
|
+
tenantID
|
|
510
|
+
});
|
|
511
|
+
let result;
|
|
512
|
+
if (doc) {
|
|
513
|
+
result = await db.update({
|
|
514
|
+
collection: `_globals_${global.slug}`,
|
|
515
|
+
id: doc.id,
|
|
516
|
+
data: args.data,
|
|
517
|
+
tenantID
|
|
518
|
+
});
|
|
519
|
+
} else {
|
|
520
|
+
result = await db.create({
|
|
521
|
+
collection: `_globals_${global.slug}`,
|
|
522
|
+
data: args.data,
|
|
523
|
+
tenantID
|
|
524
|
+
});
|
|
525
|
+
}
|
|
526
|
+
return { doc: result, message: "Updated successfully" };
|
|
527
|
+
}
|
|
528
|
+
};
|
|
529
|
+
}
|
|
364
530
|
const Mutation = new GraphQLObjectType({
|
|
365
531
|
name: "Mutation",
|
|
366
532
|
fields: mutationFields
|
|
@@ -376,10 +542,11 @@ function createGraphQLSchema(registry, db, options) {
|
|
|
376
542
|
db,
|
|
377
543
|
user: options?.user,
|
|
378
544
|
req: options?.req,
|
|
379
|
-
tenantID: options?.tenantID
|
|
545
|
+
tenantID: options?.tenantID,
|
|
546
|
+
apiKey: options?.apiKey
|
|
380
547
|
});
|
|
381
548
|
}
|
|
382
549
|
|
|
383
550
|
export { buildGraphQLSchema, createGraphQLSchema };
|
|
384
|
-
//# sourceMappingURL=chunk-
|
|
385
|
-
//# sourceMappingURL=chunk-
|
|
551
|
+
//# sourceMappingURL=chunk-L5UKKZQN.js.map
|
|
552
|
+
//# sourceMappingURL=chunk-L5UKKZQN.js.map
|