@nlabs/metropolisjs 0.1.2 → 0.3.0

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 (329) hide show
  1. package/.github/copilot-instructions.md +167 -0
  2. package/AGENTS.md +13 -0
  3. package/CHANGELOG.md +112 -0
  4. package/GRAPHQL_VALIDATION_RESULTS.md +158 -0
  5. package/PERMISSION_GRAPHQL_INTEGRATION.md +293 -0
  6. package/PERMISSION_IMPLEMENTATION_SUMMARY.md +243 -0
  7. package/README.md +1123 -112
  8. package/SIGNIN_GRAPHQL_VALIDATION.md +125 -0
  9. package/VAULT_GRAPHQL_API_FINDINGS.md +312 -0
  10. package/docs/ACTIONS.md +63 -0
  11. package/docs/COLLECTIONS.md +1038 -0
  12. package/docs/CONNECTIONS.md +1367 -0
  13. package/docs/CRUD_INTEGRATION.md +702 -0
  14. package/examples/connections-usage.tsx +909 -0
  15. package/examples/content-actions-usage.ts +144 -0
  16. package/examples/crud-usage.tsx +847 -0
  17. package/examples/extensibility-usage.tsx +889 -0
  18. package/examples/i18n-import-examples.ts +86 -0
  19. package/examples/i18n-namespace-usage.ts +118 -0
  20. package/examples/i18next-singleton-demo.ts +187 -0
  21. package/examples/permission-system-usage.tsx +415 -0
  22. package/examples/project-details.tsx +397 -0
  23. package/examples/shared-i18n-usage.tsx +203 -0
  24. package/examples/signup-error-handling.ts +100 -0
  25. package/examples/translation-types.ts +86 -0
  26. package/examples/translation-usage.tsx +336 -0
  27. package/index.js +1 -0
  28. package/jest.config.mjs +28 -0
  29. package/lex.config.mjs +11 -2
  30. package/lib/__tests__/e2e/helpers/testGraphQLServer.d.ts +22 -0
  31. package/lib/__tests__/e2e/helpers/testGraphQLServer.d.ts.map +1 -0
  32. package/lib/__tests__/e2e/helpers/testGraphQLServer.js +197 -0
  33. package/lib/__tests__/e2e/helpers/testGraphQLServerSimple.d.ts +3 -0
  34. package/lib/__tests__/e2e/helpers/testGraphQLServerSimple.d.ts.map +1 -0
  35. package/lib/__tests__/e2e/helpers/testGraphQLServerSimple.js +52 -0
  36. package/lib/actions/appActions/appActions.d.ts +29 -0
  37. package/lib/actions/appActions/appActions.d.ts.map +1 -0
  38. package/lib/actions/appActions/appActions.js +159 -0
  39. package/lib/actions/connectionActions/connectionActions.d.ts +19 -0
  40. package/lib/actions/connectionActions/connectionActions.d.ts.map +1 -0
  41. package/lib/actions/connectionActions/connectionActions.js +131 -0
  42. package/lib/actions/contentActions/contentActions.d.ts +34 -0
  43. package/lib/actions/contentActions/contentActions.d.ts.map +1 -0
  44. package/lib/actions/contentActions/contentActions.js +314 -0
  45. package/lib/actions/conversationActions/conversationActions.d.ts +30 -0
  46. package/lib/actions/conversationActions/conversationActions.d.ts.map +1 -0
  47. package/lib/actions/conversationActions/conversationActions.js +225 -0
  48. package/lib/actions/eventActions/eventActions.d.ts +27 -7
  49. package/lib/actions/eventActions/eventActions.d.ts.map +1 -0
  50. package/lib/actions/eventActions/eventActions.js +436 -2
  51. package/lib/actions/groupActions/groupActions.d.ts +30 -0
  52. package/lib/actions/groupActions/groupActions.d.ts.map +1 -0
  53. package/lib/actions/groupActions/groupActions.js +229 -0
  54. package/lib/actions/imageActions/imageActions.d.ts +16 -10
  55. package/lib/actions/imageActions/imageActions.d.ts.map +1 -0
  56. package/lib/actions/imageActions/imageActions.js +593 -2
  57. package/lib/actions/index.d.ts +21 -9
  58. package/lib/actions/index.d.ts.map +1 -0
  59. package/lib/actions/index.js +22 -2
  60. package/lib/actions/locationActions/locationActions.d.ts +11 -9
  61. package/lib/actions/locationActions/locationActions.d.ts.map +1 -0
  62. package/lib/actions/locationActions/locationActions.js +388 -2
  63. package/lib/actions/messageActions/messageActions.d.ts +16 -32
  64. package/lib/actions/messageActions/messageActions.d.ts.map +1 -0
  65. package/lib/actions/messageActions/messageActions.js +235 -2
  66. package/lib/actions/permissionActions/permissionActions.d.ts +34 -0
  67. package/lib/actions/permissionActions/permissionActions.d.ts.map +1 -0
  68. package/lib/actions/permissionActions/permissionActions.js +330 -0
  69. package/lib/actions/personaActions/personaActions.d.ts +65 -0
  70. package/lib/actions/personaActions/personaActions.d.ts.map +1 -0
  71. package/lib/actions/personaActions/personaActions.js +572 -0
  72. package/lib/actions/postActions/postActions.d.ts +12 -32
  73. package/lib/actions/postActions/postActions.d.ts.map +1 -0
  74. package/lib/actions/postActions/postActions.js +447 -2
  75. package/lib/actions/reactionActions/reactionActions.d.ts +13 -27
  76. package/lib/actions/reactionActions/reactionActions.d.ts.map +1 -0
  77. package/lib/actions/reactionActions/reactionActions.js +413 -2
  78. package/lib/actions/sseActions/sseActions.d.ts +1 -0
  79. package/lib/actions/sseActions/sseActions.d.ts.map +1 -0
  80. package/lib/actions/sseActions/sseActions.js +148 -2
  81. package/lib/actions/subscriptionActions/subscriptionActions.d.ts +24 -0
  82. package/lib/actions/subscriptionActions/subscriptionActions.d.ts.map +1 -0
  83. package/lib/actions/subscriptionActions/subscriptionActions.js +329 -0
  84. package/lib/actions/tagActions/tagActions.d.ts +13 -31
  85. package/lib/actions/tagActions/tagActions.d.ts.map +1 -0
  86. package/lib/actions/tagActions/tagActions.js +347 -2
  87. package/lib/actions/translationActions/translationActions.d.ts +38 -0
  88. package/lib/actions/translationActions/translationActions.d.ts.map +1 -0
  89. package/lib/actions/translationActions/translationActions.js +189 -0
  90. package/lib/actions/userActions/userActions.d.ts +44 -95
  91. package/lib/actions/userActions/userActions.d.ts.map +1 -0
  92. package/lib/actions/userActions/userActions.js +870 -2
  93. package/lib/actions/videoActions/videoActions.d.ts +41 -0
  94. package/lib/actions/videoActions/videoActions.d.ts.map +1 -0
  95. package/lib/actions/videoActions/videoActions.js +532 -0
  96. package/lib/actions/websocketActions/websocketActions.d.ts +20 -21
  97. package/lib/actions/websocketActions/websocketActions.d.ts.map +1 -0
  98. package/lib/actions/websocketActions/websocketActions.js +377 -2
  99. package/lib/adapters/appAdapter/appAdapter.d.ts +8 -0
  100. package/lib/adapters/appAdapter/appAdapter.d.ts.map +1 -0
  101. package/lib/adapters/appAdapter/appAdapter.js +90 -0
  102. package/lib/adapters/arangoAdapter/arangoAdapter.d.ts +3 -2
  103. package/lib/adapters/arangoAdapter/arangoAdapter.d.ts.map +1 -0
  104. package/lib/adapters/arangoAdapter/arangoAdapter.js +75 -2
  105. package/lib/adapters/contentAdapter/contentAdapter.d.ts +3 -2
  106. package/lib/adapters/contentAdapter/contentAdapter.d.ts.map +1 -0
  107. package/lib/adapters/contentAdapter/contentAdapter.js +107 -2
  108. package/lib/adapters/conversationAdapter/conversationAdapter.d.ts +3 -2
  109. package/lib/adapters/conversationAdapter/conversationAdapter.d.ts.map +1 -0
  110. package/lib/adapters/conversationAdapter/conversationAdapter.js +75 -2
  111. package/lib/adapters/eventAdapter/eventAdapter.d.ts +5 -2
  112. package/lib/adapters/eventAdapter/eventAdapter.d.ts.map +1 -0
  113. package/lib/adapters/eventAdapter/eventAdapter.js +162 -2
  114. package/lib/adapters/fileAdapter/fileAdapter.d.ts +3 -2
  115. package/lib/adapters/fileAdapter/fileAdapter.d.ts.map +1 -0
  116. package/lib/adapters/fileAdapter/fileAdapter.js +118 -2
  117. package/lib/adapters/groupAdapter/groupAdapter.d.ts +28 -0
  118. package/lib/adapters/groupAdapter/groupAdapter.d.ts.map +1 -0
  119. package/lib/adapters/groupAdapter/groupAdapter.js +66 -0
  120. package/lib/adapters/imageAdapter/imageAdapter.d.ts +9 -2
  121. package/lib/adapters/imageAdapter/imageAdapter.d.ts.map +1 -0
  122. package/lib/adapters/imageAdapter/imageAdapter.js +134 -2
  123. package/lib/adapters/index.d.ts +34 -16
  124. package/lib/adapters/index.d.ts.map +1 -0
  125. package/lib/adapters/index.js +19 -2
  126. package/lib/adapters/locationAdapter/locationAdapter.d.ts +3 -2
  127. package/lib/adapters/locationAdapter/locationAdapter.d.ts.map +1 -0
  128. package/lib/adapters/locationAdapter/locationAdapter.js +95 -2
  129. package/lib/adapters/messageAdapter/messageAdapter.d.ts +23 -19
  130. package/lib/adapters/messageAdapter/messageAdapter.d.ts.map +1 -0
  131. package/lib/adapters/messageAdapter/messageAdapter.js +82 -2
  132. package/lib/adapters/permissionAdapter/permissionAdapter.d.ts +41 -0
  133. package/lib/adapters/permissionAdapter/permissionAdapter.d.ts.map +1 -0
  134. package/lib/adapters/permissionAdapter/permissionAdapter.js +120 -0
  135. package/lib/adapters/personaAdapter/personaAdapter.d.ts +28 -2
  136. package/lib/adapters/personaAdapter/personaAdapter.d.ts.map +1 -0
  137. package/lib/adapters/personaAdapter/personaAdapter.js +161 -2
  138. package/lib/adapters/postAdapter/postAdapter.d.ts +3 -2
  139. package/lib/adapters/postAdapter/postAdapter.d.ts.map +1 -0
  140. package/lib/adapters/postAdapter/postAdapter.js +115 -2
  141. package/lib/adapters/reactionAdapter/reactionAdapter.d.ts +5 -2
  142. package/lib/adapters/reactionAdapter/reactionAdapter.d.ts.map +1 -0
  143. package/lib/adapters/reactionAdapter/reactionAdapter.js +81 -2
  144. package/lib/adapters/reaktorAdapter/reaktorAdapter.d.ts +3 -2
  145. package/lib/adapters/reaktorAdapter/reaktorAdapter.d.ts.map +1 -0
  146. package/lib/adapters/reaktorAdapter/reaktorAdapter.js +58 -2
  147. package/lib/adapters/sessionAdapter/sessionAdapter.d.ts +3 -2
  148. package/lib/adapters/sessionAdapter/sessionAdapter.d.ts.map +1 -0
  149. package/lib/adapters/sessionAdapter/sessionAdapter.js +80 -2
  150. package/lib/adapters/tagAdapter/tagAdapter.d.ts +3 -2
  151. package/lib/adapters/tagAdapter/tagAdapter.d.ts.map +1 -0
  152. package/lib/adapters/tagAdapter/tagAdapter.js +98 -2
  153. package/lib/adapters/translationAdapter/translationAdapter.d.ts +21 -0
  154. package/lib/adapters/translationAdapter/translationAdapter.d.ts.map +1 -0
  155. package/lib/adapters/translationAdapter/translationAdapter.js +55 -0
  156. package/lib/adapters/userAdapter/userAdapter.d.ts +18 -6
  157. package/lib/adapters/userAdapter/userAdapter.d.ts.map +1 -0
  158. package/lib/adapters/userAdapter/userAdapter.js +302 -2
  159. package/lib/adapters/videoAdapter/videoAdapter.d.ts +8 -0
  160. package/lib/adapters/videoAdapter/videoAdapter.d.ts.map +1 -0
  161. package/lib/adapters/videoAdapter/videoAdapter.js +194 -0
  162. package/lib/config/index.d.ts +19 -6
  163. package/lib/config/index.d.ts.map +1 -0
  164. package/lib/config/index.js +97 -2
  165. package/lib/constants/Collections.d.ts +44 -0
  166. package/lib/constants/Collections.d.ts.map +1 -0
  167. package/lib/constants/Collections.js +40 -0
  168. package/lib/constants/MetropolisConstants.d.ts +1 -0
  169. package/lib/constants/MetropolisConstants.d.ts.map +1 -0
  170. package/lib/constants/MetropolisConstants.js +15 -2
  171. package/lib/graphql/message.d.ts +1 -0
  172. package/lib/graphql/message.d.ts.map +1 -0
  173. package/lib/graphql/message.js +6 -4
  174. package/lib/graphql/notification.d.ts +1 -0
  175. package/lib/graphql/notification.d.ts.map +1 -0
  176. package/lib/graphql/notification.js +6 -4
  177. package/lib/graphql/session.d.ts +1 -0
  178. package/lib/graphql/session.d.ts.map +1 -0
  179. package/lib/graphql/session.js +4 -3
  180. package/lib/index.d.ts +45 -22
  181. package/lib/index.d.ts.map +1 -0
  182. package/lib/index.js +248 -2
  183. package/lib/stores/appStore.d.ts +1 -0
  184. package/lib/stores/appStore.d.ts.map +1 -0
  185. package/lib/stores/appStore.js +23 -2
  186. package/lib/stores/contentStore.d.ts +36 -0
  187. package/lib/stores/contentStore.d.ts.map +1 -0
  188. package/lib/stores/contentStore.js +139 -0
  189. package/lib/stores/conversationStore.d.ts +38 -0
  190. package/lib/stores/conversationStore.d.ts.map +1 -0
  191. package/lib/stores/conversationStore.js +117 -0
  192. package/lib/stores/eventStore.d.ts +4 -1
  193. package/lib/stores/eventStore.d.ts.map +1 -0
  194. package/lib/stores/eventStore.js +47 -2
  195. package/lib/stores/groupStore.d.ts +37 -0
  196. package/lib/stores/groupStore.d.ts.map +1 -0
  197. package/lib/stores/groupStore.js +68 -0
  198. package/lib/stores/imageStore.d.ts +6 -1
  199. package/lib/stores/imageStore.d.ts.map +1 -0
  200. package/lib/stores/imageStore.js +53 -2
  201. package/lib/stores/index.d.ts +20 -11
  202. package/lib/stores/index.d.ts.map +1 -0
  203. package/lib/stores/index.js +24 -2
  204. package/lib/stores/locationStore.d.ts +2 -1
  205. package/lib/stores/locationStore.d.ts.map +1 -0
  206. package/lib/stores/locationStore.js +42 -2
  207. package/lib/stores/messageStore.d.ts +19 -4
  208. package/lib/stores/messageStore.d.ts.map +1 -0
  209. package/lib/stores/messageStore.js +137 -2
  210. package/lib/stores/notificationStore.d.ts +33 -0
  211. package/lib/stores/notificationStore.d.ts.map +1 -0
  212. package/lib/stores/notificationStore.js +55 -0
  213. package/lib/stores/permissionStore.d.ts +37 -0
  214. package/lib/stores/permissionStore.d.ts.map +1 -0
  215. package/lib/stores/permissionStore.js +117 -0
  216. package/lib/stores/personaStore.d.ts +26 -0
  217. package/lib/stores/personaStore.d.ts.map +1 -0
  218. package/lib/stores/personaStore.js +118 -0
  219. package/lib/stores/postStore.d.ts +2 -1
  220. package/lib/stores/postStore.d.ts.map +1 -0
  221. package/lib/stores/postStore.js +53 -2
  222. package/lib/stores/reactionStore.d.ts +1 -0
  223. package/lib/stores/reactionStore.d.ts.map +1 -0
  224. package/lib/stores/reactionStore.js +28 -2
  225. package/lib/stores/subscriptionStore.d.ts +41 -0
  226. package/lib/stores/subscriptionStore.d.ts.map +1 -0
  227. package/lib/stores/subscriptionStore.js +85 -0
  228. package/lib/stores/tagStore.d.ts +8 -5
  229. package/lib/stores/tagStore.d.ts.map +1 -0
  230. package/lib/stores/tagStore.js +87 -2
  231. package/lib/stores/translationStore.d.ts +42 -0
  232. package/lib/stores/translationStore.d.ts.map +1 -0
  233. package/lib/stores/translationStore.js +122 -0
  234. package/lib/stores/userStore.d.ts +5 -4
  235. package/lib/stores/userStore.d.ts.map +1 -0
  236. package/lib/stores/userStore.js +319 -2
  237. package/lib/stores/videoStore.d.ts +39 -0
  238. package/lib/stores/videoStore.d.ts.map +1 -0
  239. package/lib/stores/videoStore.js +132 -0
  240. package/lib/stores/websocketStore.d.ts +1 -0
  241. package/lib/stores/websocketStore.d.ts.map +1 -0
  242. package/lib/stores/websocketStore.js +51 -2
  243. package/lib/types/apps.types.d.ts +17 -0
  244. package/lib/types/apps.types.d.ts.map +1 -0
  245. package/lib/types/apps.types.js +6 -0
  246. package/lib/types/common.types.d.ts +31 -0
  247. package/lib/types/common.types.d.ts.map +1 -0
  248. package/lib/types/common.types.js +6 -0
  249. package/lib/types/conversations.types.d.ts +17 -0
  250. package/lib/types/conversations.types.d.ts.map +1 -0
  251. package/lib/types/conversations.types.js +6 -0
  252. package/lib/types/edges.types.d.ts +38 -0
  253. package/lib/types/edges.types.d.ts.map +1 -0
  254. package/lib/types/edges.types.js +6 -0
  255. package/lib/types/groups.types.d.ts +19 -0
  256. package/lib/types/groups.types.d.ts.map +1 -0
  257. package/lib/types/groups.types.js +6 -0
  258. package/lib/types/index.d.ts +12 -0
  259. package/lib/types/index.d.ts.map +1 -0
  260. package/lib/types/index.js +12 -0
  261. package/lib/types/subscriptions.types.d.ts +32 -0
  262. package/lib/types/subscriptions.types.d.ts.map +1 -0
  263. package/lib/types/subscriptions.types.js +6 -0
  264. package/lib/types/videos.types.d.ts +61 -0
  265. package/lib/types/videos.types.d.ts.map +1 -0
  266. package/lib/types/videos.types.js +6 -0
  267. package/lib/utils/MetropolisProvider.d.ts +39 -15
  268. package/lib/utils/MetropolisProvider.d.ts.map +1 -0
  269. package/lib/utils/MetropolisProvider.js +31 -2
  270. package/lib/utils/actionFactory.d.ts +21 -19
  271. package/lib/utils/actionFactory.d.ts.map +1 -0
  272. package/lib/utils/actionFactory.js +95 -2
  273. package/lib/utils/api.d.ts +5 -4
  274. package/lib/utils/api.d.ts.map +1 -0
  275. package/lib/utils/api.js +252 -6
  276. package/lib/utils/app.d.ts +1 -0
  277. package/lib/utils/app.d.ts.map +1 -0
  278. package/lib/utils/app.js +15 -2
  279. package/lib/utils/baseActionFactory.d.ts +5 -23
  280. package/lib/utils/baseActionFactory.d.ts.map +1 -0
  281. package/lib/utils/baseActionFactory.js +72 -2
  282. package/lib/utils/configUtils.d.ts +11 -0
  283. package/lib/utils/configUtils.d.ts.map +1 -0
  284. package/lib/utils/configUtils.js +20 -0
  285. package/lib/utils/dateUtils.d.ts +1 -0
  286. package/lib/utils/dateUtils.d.ts.map +1 -0
  287. package/lib/utils/dateUtils.js +11 -2
  288. package/lib/utils/file.d.ts +3 -1
  289. package/lib/utils/file.d.ts.map +1 -0
  290. package/lib/utils/file.js +156 -2
  291. package/lib/utils/i18n.d.ts +7 -0
  292. package/lib/utils/i18n.d.ts.map +1 -0
  293. package/lib/utils/i18n.js +96 -0
  294. package/lib/utils/index.d.ts +20 -0
  295. package/lib/utils/index.d.ts.map +1 -0
  296. package/lib/utils/index.js +26 -0
  297. package/lib/utils/location.d.ts +4 -3
  298. package/lib/utils/location.d.ts.map +1 -0
  299. package/lib/utils/location.js +82 -2
  300. package/lib/utils/permissionUtils.d.ts +22 -0
  301. package/lib/utils/permissionUtils.d.ts.map +1 -0
  302. package/lib/utils/permissionUtils.js +72 -0
  303. package/lib/utils/requestCache.d.ts +8 -0
  304. package/lib/utils/requestCache.d.ts.map +1 -0
  305. package/lib/utils/requestCache.js +53 -0
  306. package/lib/utils/session.d.ts +14 -0
  307. package/lib/utils/session.d.ts.map +1 -0
  308. package/lib/utils/session.js +107 -0
  309. package/lib/utils/useConversationTyping.d.ts +26 -0
  310. package/lib/utils/useConversationTyping.d.ts.map +1 -0
  311. package/lib/utils/useConversationTyping.js +117 -0
  312. package/lib/utils/useMetropolis.d.ts +67 -12
  313. package/lib/utils/useMetropolis.d.ts.map +1 -0
  314. package/lib/utils/useMetropolis.js +311 -2
  315. package/lib/utils/useTranslations.d.ts +16 -0
  316. package/lib/utils/useTranslations.d.ts.map +1 -0
  317. package/lib/utils/useTranslations.js +105 -0
  318. package/lib/utils/validatorFactory.d.ts +3 -2
  319. package/lib/utils/validatorFactory.d.ts.map +1 -0
  320. package/lib/utils/validatorFactory.js +95 -2
  321. package/package.json +58 -17
  322. package/temp_signin.ts +73 -0
  323. package/lib/actions/profileActions/profileActions.d.ts +0 -50
  324. package/lib/actions/profileActions/profileActions.js +0 -2
  325. package/lib/adapters/profileAdapter/profileAdapter.d.ts +0 -32
  326. package/lib/adapters/profileAdapter/profileAdapter.js +0 -2
  327. package/lib/stores/profileStore.d.ts +0 -24
  328. package/lib/stores/profileStore.js +0 -2
  329. /package/{FACTORY_PATTERN_GUIDE.md → factoryPatternGuide.md} +0 -0
@@ -0,0 +1,293 @@
1
+ # Permission System GraphQL Integration
2
+
3
+ This document describes how the MetropolisJS permission system integrates with the Reaktor backend via GraphQL.
4
+
5
+ ## GraphQL Schema
6
+
7
+ The Reaktor backend should implement the following GraphQL schema for permissions:
8
+
9
+ ### Types
10
+
11
+ ```graphql
12
+ type Permission {
13
+ permissionId: ID!
14
+ userId: ID
15
+ roleId: ID
16
+ name: String!
17
+ description: String
18
+ level: Int!
19
+ resource: String
20
+ type: String
21
+ added: Float
22
+ updated: Float
23
+ }
24
+
25
+ input PermissionInput {
26
+ permissionId: ID
27
+ userId: ID
28
+ roleId: ID
29
+ name: String
30
+ description: String
31
+ level: Int!
32
+ resource: String
33
+ type: String
34
+ }
35
+ ```
36
+
37
+ ### Queries
38
+
39
+ ```graphql
40
+ type Query {
41
+ permissions: PermissionQueries!
42
+ }
43
+
44
+ type PermissionQueries {
45
+ # Check if a user has permission for a resource
46
+ check(userId: ID!, resource: String!, requiredLevel: Int!): Boolean!
47
+
48
+ # Get a specific permission by ID
49
+ itemById(permissionId: ID!): Permission
50
+
51
+ # List all permissions with pagination
52
+ list(from: Int, to: Int): [Permission!]!
53
+
54
+ # List all permissions for a specific user
55
+ listByUser(userId: ID!): [Permission!]!
56
+ }
57
+ ```
58
+
59
+ ### Mutations
60
+
61
+ ```graphql
62
+ type Mutation {
63
+ permissions: PermissionMutations!
64
+ }
65
+
66
+ type PermissionMutations {
67
+ # Grant a new permission
68
+ add(permission: PermissionInput!): Permission!
69
+
70
+ # Update an existing permission
71
+ update(permission: PermissionInput!): Permission!
72
+
73
+ # Revoke a permission
74
+ remove(permissionId: ID!): Permission!
75
+ }
76
+ ```
77
+
78
+ ## Implementation Notes
79
+
80
+ ### Permission Levels
81
+
82
+ The backend should enforce the following permission levels:
83
+
84
+ - **0** - Guest: Unauthenticated users
85
+ - **1** - User: Authenticated users
86
+ - **2** - Moderator: Content moderators
87
+ - **3** - Admin: Application administrators
88
+ - **4** - Super Admin: System administrators
89
+
90
+ ### Permission Checking
91
+
92
+ When implementing the `check` query, the backend should:
93
+
94
+ 1. First check if the user has a specific permission for the resource
95
+ 2. If no resource-specific permission exists, fall back to the user's `userAccess` level
96
+ 3. Return `true` if the user's level is >= the required level
97
+
98
+ Example backend logic:
99
+
100
+ ```typescript
101
+ async check(userId: string, resource: string, requiredLevel: number): Promise<boolean> {
102
+ // Check resource-specific permission
103
+ const permission = await db.permissions.findOne({
104
+ userId,
105
+ resource
106
+ });
107
+
108
+ if (permission) {
109
+ return permission.level >= requiredLevel;
110
+ }
111
+
112
+ // Fall back to user's userAccess level
113
+ const user = await db.users.findOne({ userId });
114
+ return (user?.userAccess ?? 0) >= requiredLevel;
115
+ }
116
+ ```
117
+
118
+ ### Backward Compatibility
119
+
120
+ The permission system is designed to work with the existing `userAccess` field in the User model:
121
+
122
+ ```graphql
123
+ type User {
124
+ userId: ID!
125
+ username: String!
126
+ userAccess: Int # 0-4, maps to PermissionLevel
127
+ # ... other fields
128
+ }
129
+ ```
130
+
131
+ Users without explicit permission records will use their `userAccess` value as their default permission level.
132
+
133
+ ## GraphQL Mutation Examples
134
+
135
+ ### Grant Permission
136
+
137
+ ```graphql
138
+ mutation GrantModeratorPermission {
139
+ permissions {
140
+ add(permission: {
141
+ userId: "user123"
142
+ name: "Moderator Role"
143
+ level: 2
144
+ resource: "posts"
145
+ description: "Can moderate posts and comments"
146
+ }) {
147
+ permissionId
148
+ name
149
+ level
150
+ resource
151
+ userId
152
+ }
153
+ }
154
+ }
155
+ ```
156
+
157
+ ### Check Permission
158
+
159
+ ```graphql
160
+ query CheckUserPermission {
161
+ permissions {
162
+ check(
163
+ userId: "user123"
164
+ resource: "posts"
165
+ requiredLevel: 2
166
+ )
167
+ }
168
+ }
169
+ ```
170
+
171
+ ### List User Permissions
172
+
173
+ ```graphql
174
+ query GetUserPermissions {
175
+ permissions {
176
+ listByUser(userId: "user123") {
177
+ permissionId
178
+ name
179
+ level
180
+ resource
181
+ description
182
+ added
183
+ updated
184
+ }
185
+ }
186
+ }
187
+ ```
188
+
189
+ ### Update Permission
190
+
191
+ ```graphql
192
+ mutation UpdatePermission {
193
+ permissions {
194
+ update(permission: {
195
+ permissionId: "perm123"
196
+ level: 3
197
+ description: "Upgraded to admin level"
198
+ }) {
199
+ permissionId
200
+ level
201
+ description
202
+ }
203
+ }
204
+ }
205
+ ```
206
+
207
+ ### Revoke Permission
208
+
209
+ ```graphql
210
+ mutation RevokePermission {
211
+ permissions {
212
+ remove(permissionId: "perm123") {
213
+ permissionId
214
+ name
215
+ }
216
+ }
217
+ }
218
+ ```
219
+
220
+ ## Database Schema
221
+
222
+ The backend should store permissions in a collection/table with the following structure:
223
+
224
+ ```typescript
225
+ interface PermissionRecord {
226
+ _id: string; // ArangoDB ID
227
+ _key: string; // ArangoDB key
228
+ permissionId: string; // Unique permission ID
229
+ userId?: string; // User this permission is granted to
230
+ roleId?: string; // Optional role-based permission
231
+ name: string; // Human-readable name
232
+ description?: string; // Optional description
233
+ level: number; // Permission level (0-4)
234
+ resource?: string; // Optional resource scope
235
+ type?: string; // Optional type classifier
236
+ added: number; // Timestamp when granted
237
+ updated: number; // Timestamp when last updated
238
+ }
239
+ ```
240
+
241
+ ### Indexes
242
+
243
+ Recommended indexes for optimal performance:
244
+
245
+ - `userId` - For quick lookup of user permissions
246
+ - `resource` - For resource-specific queries
247
+ - `level` - For level-based filtering
248
+ - Composite index on `(userId, resource)` - For permission checking
249
+
250
+ ## Security Considerations
251
+
252
+ 1. **Authorization**: Only admins (level >= 3) should be able to grant/revoke permissions
253
+ 2. **Validation**: Backend should validate that permission levels are within 0-4 range
254
+ 3. **Audit Trail**: Consider logging all permission changes for security auditing
255
+ 4. **Resource Validation**: Validate that resource names match expected values
256
+ 5. **Self-Service**: Users should not be able to grant themselves higher permissions
257
+
258
+ ## Error Handling
259
+
260
+ The backend should return appropriate errors:
261
+
262
+ ```graphql
263
+ type PermissionError {
264
+ code: String!
265
+ message: String!
266
+ field: String
267
+ }
268
+
269
+ # Example error responses
270
+ {
271
+ "errors": [
272
+ {
273
+ "message": "Insufficient permissions to grant admin access",
274
+ "extensions": {
275
+ "code": "FORBIDDEN",
276
+ "field": "level"
277
+ }
278
+ }
279
+ ]
280
+ }
281
+ ```
282
+
283
+ ## Testing
284
+
285
+ The backend should include tests for:
286
+
287
+ 1. Granting permissions to users
288
+ 2. Checking permissions with and without resource scope
289
+ 3. Listing user permissions
290
+ 4. Updating and revoking permissions
291
+ 5. Permission inheritance from userAccess field
292
+ 6. Authorization checks (only admins can manage permissions)
293
+ 7. Edge cases (invalid levels, non-existent users, etc.)
@@ -0,0 +1,243 @@
1
+ # Permission System Implementation Summary
2
+
3
+ ## Overview
4
+
5
+ This document summarizes the complete implementation of the 5-level RBAC (Role-Based Access Control) permission system for MetropolisJS.
6
+
7
+ ## What Was Implemented
8
+
9
+ ### 1. Core Permission Infrastructure
10
+
11
+ #### Permission Adapter (`src/adapters/permissionAdapter/`)
12
+ - **TypeScript Types**: Complete type definitions for Permission objects
13
+ - **Validation**: Zod schema validation for permission data
14
+ - **Utility Functions**:
15
+ - `hasPermission()` - Check if a user level meets requirements
16
+ - `getPermissionLevelName()` - Get human-readable level names
17
+ - Level checking helpers: `isGuest()`, `isUser()`, `isModerator()`, `isAdmin()`, `isSuperAdmin()`
18
+ - **Tests**: Comprehensive test suite (100% coverage)
19
+
20
+ #### Permission Store (`src/stores/permissionStore.ts`)
21
+ - ArkhamJS store for permission state management
22
+ - Handles all CRUD operations (add, get, list, update, remove)
23
+ - Stores user-specific permissions
24
+ - Error handling
25
+ - Comprehensive tests
26
+
27
+ #### Permission Actions (`src/actions/permissionActions/`)
28
+ - Factory-based action creation following MetropolisJS patterns
29
+ - GraphQL integration for Reaktor backend
30
+ - Methods:
31
+ - `add()` - Grant permissions
32
+ - `check()` - Verify user access
33
+ - `itemById()` - Get specific permission
34
+ - `list()` - List all permissions
35
+ - `listByUser()` - Get user's permissions
36
+ - `remove()` - Revoke permissions
37
+ - `update()` - Modify permissions
38
+ - Custom adapter support
39
+ - Tests
40
+
41
+ ### 2. React Integration
42
+
43
+ #### Permission Hooks (`src/utils/permissionUtils.tsx`)
44
+ - **`usePermissions()`**: Main hook for permission checking
45
+ - Returns current user level
46
+ - Boolean helpers for level checking
47
+ - Resource-specific permission checking
48
+ - Reactive to user state changes
49
+
50
+ - **`usePermissionActions()`**: Hook for managing permissions
51
+ - Created via existing `useMetropolis()` infrastructure
52
+ - Specialized hook for better performance
53
+
54
+ #### Permission Guard Component
55
+ - **`<PermissionGuard>`**: Declarative permission-based rendering
56
+ - Required level specification
57
+ - Optional resource-specific checking
58
+ - Fallback content for unauthorized users
59
+ - Clean, React-friendly API
60
+
61
+ ### 3. Integration with MetropolisJS
62
+
63
+ - Added permission store to Metropolis initialization
64
+ - Integrated into action factory (`src/utils/actionFactory.ts`)
65
+ - Updated hooks infrastructure (`src/utils/useMetropolis.ts`)
66
+ - Added to MetropolisProvider types (`src/utils/MetropolisProvider.tsx`)
67
+ - Exported all utilities from main package
68
+
69
+ ### 4. Documentation
70
+
71
+ #### README.md
72
+ - New comprehensive Permission System section
73
+ - Usage examples
74
+ - API documentation
75
+ - Best practices
76
+ - Integration guide
77
+ - Updated "Available Actions" section
78
+ - Updated "Adapters" section
79
+
80
+ #### Examples
81
+ - `examples/permission-system-usage.tsx`: 10 comprehensive examples covering:
82
+ - Basic permission checking
83
+ - Permission Guard usage
84
+ - Creating and managing permissions
85
+ - Resource-specific permissions
86
+ - Listing user permissions
87
+ - Protected API calls
88
+ - Permission levels reference
89
+ - Conditional rendering
90
+ - Testing permissions
91
+
92
+ #### GraphQL Integration Guide
93
+ - `PERMISSION_GRAPHQL_INTEGRATION.md`: Complete backend integration guide
94
+ - GraphQL schema definitions
95
+ - Query and mutation examples
96
+ - Implementation notes
97
+ - Database schema
98
+ - Security considerations
99
+ - Testing requirements
100
+
101
+ ## Permission Levels
102
+
103
+ The system implements 5 hierarchical levels:
104
+
105
+ | Level | Name | Value | Description |
106
+ |-------|------|-------|-------------|
107
+ | 0 | Guest | `PermissionLevel.GUEST` | Unauthenticated users |
108
+ | 1 | User | `PermissionLevel.USER` | Authenticated users |
109
+ | 2 | Moderator | `PermissionLevel.MODERATOR` | Content moderators |
110
+ | 3 | Admin | `PermissionLevel.ADMIN` | Application admins |
111
+ | 4 | Super Admin | `PermissionLevel.SUPER_ADMIN` | System administrators |
112
+
113
+ ## Backward Compatibility
114
+
115
+ The system is **100% backward compatible**:
116
+ - Uses existing `userAccess` field (0-4) in User model
117
+ - No breaking changes to existing APIs
118
+ - Graceful fallback to `userAccess` when permissions don't exist
119
+ - All new features are opt-in
120
+
121
+ ## Key Features
122
+
123
+ 1. **Type Safety**: Full TypeScript support throughout
124
+ 2. **Validation**: Zod schema validation for data integrity
125
+ 3. **Flexibility**: Resource-specific permissions for fine-grained control
126
+ 4. **Performance**: Optimized hooks and specialized action creators
127
+ 5. **Developer Experience**: Clean, intuitive API with comprehensive docs
128
+ 6. **Testing**: Complete test coverage for all components
129
+ 7. **Security**: CodeQL scan passed with 0 vulnerabilities
130
+
131
+ ## Usage Example
132
+
133
+ ```tsx
134
+ import {
135
+ Metropolis,
136
+ usePermissions,
137
+ usePermissionActions,
138
+ PermissionGuard,
139
+ PermissionLevel
140
+ } from '@nlabs/metropolisjs';
141
+
142
+ const App = () => {
143
+ return (
144
+ <Metropolis config={{/* config */}}>
145
+ <Dashboard />
146
+ </Metropolis>
147
+ );
148
+ };
149
+
150
+ const Dashboard = () => {
151
+ const { isAdmin, userLevel, checkResource } = usePermissions();
152
+ const permissionActions = usePermissionActions();
153
+
154
+ const grantModerator = async (userId: string) => {
155
+ await permissionActions.add({
156
+ userId,
157
+ level: PermissionLevel.MODERATOR,
158
+ resource: 'posts',
159
+ name: 'Post Moderator'
160
+ });
161
+ };
162
+
163
+ return (
164
+ <div>
165
+ <h1>Dashboard (Level: {userLevel})</h1>
166
+
167
+ <PermissionGuard
168
+ requiredLevel={PermissionLevel.USER}
169
+ fallback={<p>Please log in</p>}
170
+ >
171
+ <UserContent />
172
+ </PermissionGuard>
173
+
174
+ {isAdmin && <AdminPanel />}
175
+
176
+ <PermissionGuard
177
+ requiredLevel={PermissionLevel.MODERATOR}
178
+ resource="posts"
179
+ >
180
+ <ModeratePostsButton />
181
+ </PermissionGuard>
182
+ </div>
183
+ );
184
+ };
185
+ ```
186
+
187
+ ## Files Created/Modified
188
+
189
+ ### New Files
190
+ - `src/adapters/permissionAdapter/permissionAdapter.ts`
191
+ - `src/adapters/permissionAdapter/permissionAdapter.test.ts`
192
+ - `src/stores/permissionStore.ts`
193
+ - `src/stores/permissionStore.test.ts`
194
+ - `src/actions/permissionActions/permissionActions.ts`
195
+ - `src/actions/permissionActions/permissionActions.test.ts`
196
+ - `src/utils/permissionUtils.tsx`
197
+ - `examples/permission-system-usage.tsx`
198
+ - `PERMISSION_GRAPHQL_INTEGRATION.md`
199
+ - `PERMISSION_IMPLEMENTATION_SUMMARY.md` (this file)
200
+
201
+ ### Modified Files
202
+ - `src/adapters/index.ts` - Export permission adapter
203
+ - `src/stores/index.ts` - Export permission store
204
+ - `src/actions/index.ts` - Export permission actions
205
+ - `src/utils/index.ts` - Export permission utilities
206
+ - `src/utils/actionFactory.ts` - Add permission to action factory
207
+ - `src/utils/useMetropolis.ts` - Add permission hooks
208
+ - `src/utils/MetropolisProvider.tsx` - Add permission adapter type
209
+ - `src/index.tsx` - Add permission store to initialization
210
+ - `README.md` - Add comprehensive permission documentation
211
+
212
+ ## Testing
213
+
214
+ All components include comprehensive tests:
215
+ - ✅ Permission adapter validation
216
+ - ✅ Permission level checking functions
217
+ - ✅ Permission store state management
218
+ - ✅ Permission actions factory creation
219
+ - ✅ Hook initialization
220
+
221
+ ## Security
222
+
223
+ - ✅ CodeQL security scan: 0 alerts
224
+ - ✅ Input validation with Zod schemas
225
+ - ✅ Type safety throughout
226
+ - ✅ No hardcoded credentials or secrets
227
+ - ✅ Proper error handling
228
+
229
+ ## Next Steps for Backend Integration
230
+
231
+ 1. Implement GraphQL schema in Reaktor backend (see `PERMISSION_GRAPHQL_INTEGRATION.md`)
232
+ 2. Create database collection for permissions
233
+ 3. Add authorization middleware for admin-only operations
234
+ 4. Implement permission checking logic
235
+ 5. Add audit logging for permission changes
236
+ 6. Write backend tests
237
+
238
+ ## Notes
239
+
240
+ - The system is designed to work with both user-level permissions (`userAccess`) and resource-specific permissions
241
+ - Permission checking is hierarchical - higher levels include all lower level permissions
242
+ - Resource-specific permissions override the default `userAccess` level
243
+ - The system is extensible - new permission types and resources can be added without breaking changes