@gnar-engine/cli 1.0.0 → 1.0.2

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 (230) hide show
  1. package/assets/gnar-engine-logo-white.svg +9 -0
  2. package/bootstrap/deploy.localdev.yml +51 -0
  3. package/bootstrap/secrets.localdev.yml +27 -0
  4. package/bootstrap/services/agent/Dockerfile +23 -0
  5. package/bootstrap/services/agent/notes.md +28 -0
  6. package/bootstrap/services/agent/package.json +16 -0
  7. package/bootstrap/services/agent/src/app.js +52 -0
  8. package/bootstrap/services/agent/src/commands/agent.handler.js +104 -0
  9. package/bootstrap/services/agent/src/config.js +52 -0
  10. package/bootstrap/services/agent/src/controllers/http.controller.js +44 -0
  11. package/bootstrap/services/agent/src/controllers/message.controller.js +51 -0
  12. package/bootstrap/services/agent/src/db/migrations/01-init.js +50 -0
  13. package/bootstrap/services/agent/src/db/migrations/02-agent-service-init.js +36 -0
  14. package/bootstrap/services/agent/src/policies/agent.policy.js +13 -0
  15. package/bootstrap/services/agent/src/schema/Agent.schema.js +17 -0
  16. package/bootstrap/services/agent/src/services/agent.service.js +259 -0
  17. package/bootstrap/services/agent/src/services/chatgpt.service.js +46 -0
  18. package/bootstrap/services/agent/src/services/manifest.service.js +21 -0
  19. package/bootstrap/services/control/Dockerfile +23 -0
  20. package/bootstrap/services/control/Dockerfile.prod +37 -0
  21. package/bootstrap/services/control/README.md +25 -0
  22. package/bootstrap/services/control/package.json +16 -0
  23. package/bootstrap/services/control/src/app.js +45 -0
  24. package/bootstrap/services/control/src/commands/control.handler.js +231 -0
  25. package/bootstrap/services/control/src/commands/service.handler.js +81 -0
  26. package/bootstrap/services/control/src/commands/task.handler.js +247 -0
  27. package/bootstrap/services/control/src/config.js +55 -0
  28. package/bootstrap/services/control/src/controllers/http.controller.js +228 -0
  29. package/bootstrap/services/control/src/controllers/message.controller.js +40 -0
  30. package/bootstrap/services/control/src/db/migrations/01-init.js +50 -0
  31. package/bootstrap/services/control/src/db/migrations/02-control-service-init.js +60 -0
  32. package/bootstrap/services/control/src/db/migrations/03-alter-tasks.js +29 -0
  33. package/bootstrap/services/control/src/policies/task.policy.js +53 -0
  34. package/bootstrap/services/control/src/schema/control.schema.js +42 -0
  35. package/bootstrap/services/control/src/services/registry.service.js +83 -0
  36. package/bootstrap/services/control/src/services/reset.service.js +28 -0
  37. package/bootstrap/services/control/src/services/task.service.js +153 -0
  38. package/bootstrap/services/control/src/tests/control.test.js +50 -0
  39. package/bootstrap/services/notification/Dockerfile +23 -0
  40. package/bootstrap/services/notification/Dockerfile.prod +37 -0
  41. package/bootstrap/services/notification/README.md +3 -0
  42. package/bootstrap/services/notification/package.json +34 -0
  43. package/bootstrap/services/notification/src/app.js +51 -0
  44. package/bootstrap/services/notification/src/commands/command-bus.js +20 -0
  45. package/bootstrap/services/notification/src/commands/handlers/control.handler.js +18 -0
  46. package/bootstrap/services/notification/src/commands/handlers/notification.handler.js +157 -0
  47. package/bootstrap/services/notification/src/config.js +15 -0
  48. package/bootstrap/services/notification/src/controllers/message.controller.js +82 -0
  49. package/bootstrap/services/notification/src/services/logger.service.js +16 -0
  50. package/bootstrap/services/notification/src/services/ses.service.js +23 -0
  51. package/bootstrap/services/notification/src/templates/admin-order-recieved.hbs +136 -0
  52. package/bootstrap/services/notification/src/templates/admin-subscription-failed.hbs +87 -0
  53. package/bootstrap/services/notification/src/templates/customer-order-recieved.hbs +132 -0
  54. package/bootstrap/services/notification/src/templates/customer-subscription-failed.hbs +77 -0
  55. package/bootstrap/services/notification/src/tests/notification.test.js +0 -0
  56. package/bootstrap/services/portal/Dockerfile +23 -0
  57. package/bootstrap/services/portal/Dockerfile.remote +40 -0
  58. package/bootstrap/services/portal/README.md +22 -0
  59. package/bootstrap/services/portal/nginx.conf +12 -0
  60. package/bootstrap/services/portal/package.json +59 -0
  61. package/bootstrap/services/portal/public/favicon.ico +0 -0
  62. package/bootstrap/services/portal/public/gnar-white.png +0 -0
  63. package/bootstrap/services/portal/public/gnarengine-logo-black.png +0 -0
  64. package/bootstrap/services/portal/public/index.html +43 -0
  65. package/bootstrap/services/portal/public/logo192.png +0 -0
  66. package/bootstrap/services/portal/public/logo512.png +0 -0
  67. package/bootstrap/services/portal/public/manifest.json +25 -0
  68. package/bootstrap/services/portal/public/robots.txt +3 -0
  69. package/bootstrap/services/portal/src/App.js +56 -0
  70. package/bootstrap/services/portal/src/assets/Logo_Anchord_Black.svg +1 -0
  71. package/bootstrap/services/portal/src/assets/Logo_Anchord_Black_Green.svg +1 -0
  72. package/bootstrap/services/portal/src/assets/Logo_Anchord_White_Green.svg +1 -0
  73. package/bootstrap/services/portal/src/assets/activity.svg +3 -0
  74. package/bootstrap/services/portal/src/assets/arrow.svg +3 -0
  75. package/bootstrap/services/portal/src/assets/bin-white.svg +3 -0
  76. package/bootstrap/services/portal/src/assets/bin.svg +3 -0
  77. package/bootstrap/services/portal/src/assets/check.svg +3 -0
  78. package/bootstrap/services/portal/src/assets/chevron.svg +3 -0
  79. package/bootstrap/services/portal/src/assets/contact.svg +3 -0
  80. package/bootstrap/services/portal/src/assets/dots-vertical.svg +5 -0
  81. package/bootstrap/services/portal/src/assets/eye-off.svg +3 -0
  82. package/bootstrap/services/portal/src/assets/eye.svg +4 -0
  83. package/bootstrap/services/portal/src/assets/gnar-engine-black.svg +47 -0
  84. package/bootstrap/services/portal/src/assets/gnar-engine-white.svg +47 -0
  85. package/bootstrap/services/portal/src/assets/gnar_engine.svg +3 -0
  86. package/bootstrap/services/portal/src/assets/gnarengine-logo-black.png +0 -0
  87. package/bootstrap/services/portal/src/assets/home.svg +3 -0
  88. package/bootstrap/services/portal/src/assets/link.svg +3 -0
  89. package/bootstrap/services/portal/src/assets/lock.svg +3 -0
  90. package/bootstrap/services/portal/src/assets/package.svg +4 -0
  91. package/bootstrap/services/portal/src/assets/raffle.svg +3 -0
  92. package/bootstrap/services/portal/src/assets/settings.svg +4 -0
  93. package/bootstrap/services/portal/src/assets/shopping-bag.svg +3 -0
  94. package/bootstrap/services/portal/src/assets/user-black.svg +3 -0
  95. package/bootstrap/services/portal/src/assets/user.svg +3 -0
  96. package/bootstrap/services/portal/src/assets/users.svg +3 -0
  97. package/bootstrap/services/portal/src/assets/wallet.svg +3 -0
  98. package/bootstrap/services/portal/src/css/style.css +1007 -0
  99. package/bootstrap/services/portal/src/data/data.js +70 -0
  100. package/bootstrap/services/portal/src/features/attributeFormRow/AttributeFormRow.jsx +32 -0
  101. package/bootstrap/services/portal/src/features/billingShipping/BillingShipping.jsx +160 -0
  102. package/bootstrap/services/portal/src/features/crud/crudEdit.less +230 -0
  103. package/bootstrap/services/portal/src/features/crud/crudList.less +134 -0
  104. package/bootstrap/services/portal/src/features/crud/crudPage.less +31 -0
  105. package/bootstrap/services/portal/src/features/crudContact/CrudContactList.jsx +108 -0
  106. package/bootstrap/services/portal/src/features/crudContact/CrudContactSingle.jsx +243 -0
  107. package/bootstrap/services/portal/src/features/crudOrder/CrudOrderList.jsx +109 -0
  108. package/bootstrap/services/portal/src/features/crudOrder/CrudOrderSingle.jsx +315 -0
  109. package/bootstrap/services/portal/src/features/crudProducts/CrudProductList.jsx +104 -0
  110. package/bootstrap/services/portal/src/features/crudProducts/CrudProductSingle.jsx +388 -0
  111. package/bootstrap/services/portal/src/features/crudRaffles/CrudRafflesList.jsx +104 -0
  112. package/bootstrap/services/portal/src/features/crudRaffles/CrudRafflesSingle.jsx +208 -0
  113. package/bootstrap/services/portal/src/features/crudSubscription/CrudSubscriptionList.jsx +110 -0
  114. package/bootstrap/services/portal/src/features/crudSubscription/CrudSubscriptionSingle.jsx +261 -0
  115. package/bootstrap/services/portal/src/features/crudUser/CrudUserList.jsx +107 -0
  116. package/bootstrap/services/portal/src/features/crudUser/CrudUserSingle.jsx +402 -0
  117. package/bootstrap/services/portal/src/features/inventoryFormRow/InventoryFormRow.jsx +30 -0
  118. package/bootstrap/services/portal/src/features/lineItems/LineItems.jsx +113 -0
  119. package/bootstrap/services/portal/src/features/loginForm/LoginForm.jsx +56 -0
  120. package/bootstrap/services/portal/src/features/loginForm/loginForm.less +56 -0
  121. package/bootstrap/services/portal/src/features/notes/Notes.jsx +18 -0
  122. package/bootstrap/services/portal/src/features/passwordReset/PasswordResetForm.jsx +96 -0
  123. package/bootstrap/services/portal/src/features/passwordReset/PasswordResetRequestForm.jsx +74 -0
  124. package/bootstrap/services/portal/src/features/priceFormRow/PriceFormRow.jsx +102 -0
  125. package/bootstrap/services/portal/src/features/priceFormRow/priceFormRow.less +24 -0
  126. package/bootstrap/services/portal/src/features/raffleEntriesList/RaffleEntriesList.jsx +99 -0
  127. package/bootstrap/services/portal/src/features/raffleProductFormRow/RaffleProductFormRow.jsx +46 -0
  128. package/bootstrap/services/portal/src/features/sidebar/Sidebar.jsx +64 -0
  129. package/bootstrap/services/portal/src/features/sidebar/sidebar.less +49 -0
  130. package/bootstrap/services/portal/src/features/skus/Skus.jsx +109 -0
  131. package/bootstrap/services/portal/src/features/subscriptionSchedule/SubscriptionSchedule.jsx +44 -0
  132. package/bootstrap/services/portal/src/features/taxonomyFormRow/TaxonomyFormRow.jsx +32 -0
  133. package/bootstrap/services/portal/src/features/user/User.jsx +54 -0
  134. package/bootstrap/services/portal/src/features/user/user.less +57 -0
  135. package/bootstrap/services/portal/src/includes/utilities.js +259 -0
  136. package/bootstrap/services/portal/src/index.js +14 -0
  137. package/bootstrap/services/portal/src/layouts/CrudLayout.jsx +50 -0
  138. package/bootstrap/services/portal/src/layouts/LoginLayout.jsx +17 -0
  139. package/bootstrap/services/portal/src/layouts/PortalLayout.jsx +48 -0
  140. package/bootstrap/services/portal/src/layouts/loginLayout.less +33 -0
  141. package/bootstrap/services/portal/src/layouts/portalLayout.less +67 -0
  142. package/bootstrap/services/portal/src/pages/contacts/Contacts.jsx +199 -0
  143. package/bootstrap/services/portal/src/pages/dashboard/Dashboard.jsx +17 -0
  144. package/bootstrap/services/portal/src/pages/integrations/Integrations.jsx +10 -0
  145. package/bootstrap/services/portal/src/pages/login/Login.jsx +15 -0
  146. package/bootstrap/services/portal/src/pages/login/login.less +10 -0
  147. package/bootstrap/services/portal/src/pages/orders/Orders.jsx +199 -0
  148. package/bootstrap/services/portal/src/pages/passwordReset/PasswordResetPage.jsx +15 -0
  149. package/bootstrap/services/portal/src/pages/passwordResetRequest/PasswordResetRequestPage.jsx +15 -0
  150. package/bootstrap/services/portal/src/pages/payments/Payments.jsx +10 -0
  151. package/bootstrap/services/portal/src/pages/portal/Portal.jsx +43 -0
  152. package/bootstrap/services/portal/src/pages/products/Products.jsx +212 -0
  153. package/bootstrap/services/portal/src/pages/raffleEntries/RaffleEntries.jsx +124 -0
  154. package/bootstrap/services/portal/src/pages/raffles/Raffles.jsx +186 -0
  155. package/bootstrap/services/portal/src/pages/reports/Reports.jsx +10 -0
  156. package/bootstrap/services/portal/src/pages/settings/Settings.jsx +10 -0
  157. package/bootstrap/services/portal/src/pages/subscriptions/Subscriptions.jsx +199 -0
  158. package/bootstrap/services/portal/src/pages/users/Users.jsx +193 -0
  159. package/bootstrap/services/portal/src/pages/users/users.less +25 -0
  160. package/bootstrap/services/portal/src/slices/authSlice.js +71 -0
  161. package/bootstrap/services/portal/src/store/configureStore.js +12 -0
  162. package/bootstrap/services/portal/src/styles/global.less +159 -0
  163. package/bootstrap/services/portal/src/styles/inputs.less +157 -0
  164. package/bootstrap/services/portal/src/styles/main.less +26 -0
  165. package/bootstrap/services/portal/src/ui/collapsible/Collapsible.jsx +97 -0
  166. package/bootstrap/services/portal/src/ui/collapsible/collapsible.less +23 -0
  167. package/bootstrap/services/portal/src/ui/customCheckbox/CustomCheckbox.jsx +17 -0
  168. package/bootstrap/services/portal/src/ui/customCheckbox/customCheckbox.less +42 -0
  169. package/bootstrap/services/portal/src/ui/customMultiSelect/CustomMultiSelect.jsx +63 -0
  170. package/bootstrap/services/portal/src/ui/customMultiSelect/CustomMultiSelectPeriod.jsx +63 -0
  171. package/bootstrap/services/portal/src/ui/customSelect/CustomSelect.jsx +63 -0
  172. package/bootstrap/services/portal/src/ui/customSelect/customSelect.less +92 -0
  173. package/bootstrap/services/portal/src/ui/goBack/GoBack.jsx +19 -0
  174. package/bootstrap/services/portal/src/ui/loader/Loader.jsx +12 -0
  175. package/bootstrap/services/portal/src/ui/pagination/Pagination.jsx +23 -0
  176. package/bootstrap/services/portal/src/ui/repeater/Repeater.jsx +29 -0
  177. package/bootstrap/services/portal/src/ui/saveButton/SaveButton.jsx +69 -0
  178. package/bootstrap/services/portal/src/ui/saveButton/saveButton.less +0 -0
  179. package/bootstrap/services/rabbit-mq/Dockerfile.prod +9 -0
  180. package/bootstrap/services/user/Dockerfile +23 -0
  181. package/bootstrap/services/user/Dockerfile.prod +37 -0
  182. package/bootstrap/services/user/README.md +8 -0
  183. package/bootstrap/services/user/package.json +16 -0
  184. package/bootstrap/services/user/src/app.js +45 -0
  185. package/bootstrap/services/user/src/commands/session.handler.js +23 -0
  186. package/bootstrap/services/user/src/commands/user.handler.js +286 -0
  187. package/bootstrap/services/user/src/config.js +73 -0
  188. package/bootstrap/services/user/src/controllers/http.controller.js +156 -0
  189. package/bootstrap/services/user/src/controllers/message.controller.js +51 -0
  190. package/bootstrap/services/user/src/db/migrations/01-init.js +50 -0
  191. package/bootstrap/services/user/src/db/migrations/02-user-service-init.js +63 -0
  192. package/bootstrap/services/user/src/db/migrations/03-unauth-sessions.js +43 -0
  193. package/bootstrap/services/user/src/db/seeders/development/01-root-user.js +29 -0
  194. package/bootstrap/services/user/src/db/seeders/development/02-portal-admin-user.js +27 -0
  195. package/bootstrap/services/user/src/db/seeders/production/01-root-user.js +29 -0
  196. package/bootstrap/services/user/src/policies/user.policy.js +81 -0
  197. package/bootstrap/services/user/src/schema/user.schema.js +69 -0
  198. package/bootstrap/services/user/src/services/authentication.service.js +127 -0
  199. package/bootstrap/services/user/src/services/session.service.js +58 -0
  200. package/bootstrap/services/user/src/services/user.service.js +130 -0
  201. package/bootstrap/services/user/src/tests/user.test.js +126 -0
  202. package/package.json +3 -7
  203. package/src/agent/agent.client.js +28 -0
  204. package/src/agent/commands.js +48 -0
  205. package/src/cli.js +30 -0
  206. package/src/config.js +8 -0
  207. package/src/control/commands.js +156 -0
  208. package/src/control/control.client.js +127 -0
  209. package/src/dev/commands.js +71 -0
  210. package/src/dev/dev.service.js +320 -0
  211. package/src/engine/infra.js +142 -0
  212. package/src/helpers/helpers.js +63 -0
  213. package/src/profiles/command.js +170 -0
  214. package/src/profiles/profiles.client.js +101 -0
  215. package/src/scaffolder/commands.js +123 -0
  216. package/src/scaffolder/scaffolder.handler.js +252 -0
  217. package/src/services/client.js +174 -0
  218. package/templates/service/Dockerfile.hbs +20 -0
  219. package/templates/service/app.js.hbs +38 -0
  220. package/templates/service/commands/{{serviceName}}.handler.js.hbs +97 -0
  221. package/templates/service/config.js.hbs +48 -0
  222. package/templates/service/controllers/http.controller.js.hbs +87 -0
  223. package/templates/service/controllers/message.controller.js.hbs +51 -0
  224. package/templates/service/db/migrations/01-init.js.hbs +50 -0
  225. package/templates/service/db/migrations/02-{{lowerCase serviceName}}-service-init.js.hbs +23 -0
  226. package/templates/service/package.json.hbs +18 -0
  227. package/templates/service/policies/{{serviceName}}.policy.js.hbs +49 -0
  228. package/templates/service/schema/{{serviceName}}.schema.js.hbs +14 -0
  229. package/templates/service/services/{{serviceName}}.service.js.hbs +32 -0
  230. package/dist/cli.js +0 -18
@@ -0,0 +1,156 @@
1
+ import { commands } from '@gnar-engine/core';
2
+ import { authorise } from '../policies/user.policy.js';
3
+
4
+
5
+ /**
6
+ * HTTP controller
7
+ */
8
+ export const httpController = {
9
+
10
+ /**
11
+ * Authenticate
12
+ */
13
+ authenticate: {
14
+ method: 'POST',
15
+ url: '/authenticate/',
16
+ handler: async (request, reply) => {
17
+ // params from request
18
+ const params = {
19
+ username: request.body.username || null,
20
+ password: request.body.password || null,
21
+ email: request.body.email || null,
22
+ apiKey: request.body.apiKey || null
23
+ };
24
+
25
+ // execute
26
+ const token = await commands.execute('authenticate', params);
27
+
28
+ if (!token) {
29
+ return reply.code(401).send({ error: 'Authentication failed' });
30
+ }
31
+
32
+ // Get user data using token
33
+ const user = await commands.execute('getAuthenticatedUser', { token });
34
+
35
+ // handle response
36
+ reply.code(200).send({
37
+ token,
38
+ user
39
+ });
40
+ }
41
+ },
42
+
43
+ /**
44
+ * Get single user
45
+ */
46
+ getSingle: {
47
+ method: 'GET',
48
+ url: '/users/:id',
49
+ preHandler: async (request, reply) => authorise.getSingle(request, reply),
50
+ handler: async (request, reply) => {
51
+ // params from request
52
+ const params = {
53
+ id: request.params.id
54
+ };
55
+
56
+ // execute
57
+ const user = await commands.execute('getSingleUser', params);
58
+
59
+ // handle response
60
+ reply.code(200).send(
61
+ { user: user }
62
+ );
63
+ }
64
+ },
65
+
66
+ /**
67
+ * Get multiple users
68
+ */
69
+ getMany: {
70
+ method: 'GET',
71
+ url: '/users/',
72
+ preHandler: async (request, reply) => authorise.getMany(request, reply),
73
+ handler: async (request, reply) => {
74
+ // params from request
75
+ const params = {};
76
+
77
+ // execute
78
+ const users = await commands.execute('getManyUsers', params);
79
+
80
+ // handle response
81
+ reply.code(200).send(
82
+ { users: users }
83
+ );
84
+ }
85
+ },
86
+
87
+ /**
88
+ * Create new user
89
+ */
90
+ create: {
91
+ method: 'POST',
92
+ url: '/users/',
93
+ preHandler: async (request, reply) => authorise.create(request, reply),
94
+ handler: async (request, reply) => {
95
+ // params from request
96
+ const params = {
97
+ users: [request.body.user]
98
+ };
99
+
100
+ // execute
101
+ const users = await commands.execute('createUsers', params);
102
+
103
+ // handle response
104
+ reply.code(200).send(
105
+ { users: users }
106
+ );
107
+ },
108
+ },
109
+
110
+ /**
111
+ * Update user
112
+ */
113
+ update: {
114
+ method: 'POST',
115
+ url: '/users/:id',
116
+ preHandler: async (request, reply) => authorise.update(request, reply),
117
+ handler: async (request, reply) => {
118
+ // params from request
119
+ const params = {
120
+ id: request.params.id,
121
+ newUserData: request.body
122
+ };
123
+
124
+ // execute
125
+ const user = await commands.execute('updateUser', params);
126
+
127
+ // handle response
128
+ reply.code(200).send(
129
+ { user: user }
130
+ );
131
+ },
132
+ },
133
+
134
+ /**
135
+ * Delete user
136
+ */
137
+ delete: {
138
+ method: 'DELETE',
139
+ url: '/users/:id',
140
+ preHandler: async (request, reply) => authorise.delete(request, reply),
141
+ handler: async (request, reply) => {
142
+ // params from request
143
+ const params = {
144
+ id: request.params.id
145
+ };
146
+
147
+ // execute
148
+ await commands.execute('deleteUser', params);
149
+
150
+ // handle response
151
+ reply.code(200).send(
152
+ { 'message': 'User deleted' }
153
+ );
154
+ },
155
+ },
156
+ }
@@ -0,0 +1,51 @@
1
+ import { commands } from '@gnar-engine/core';
2
+
3
+
4
+ export const messageHandlers = {
5
+
6
+ getAuthenticatedUser: async (payload) => {
7
+ console.log('getAuthenticatedUser payload:', payload);
8
+ const user = await commands.execute('getAuthenticatedUser', {
9
+ token: payload.data.token
10
+ });
11
+
12
+ return { user };
13
+ },
14
+
15
+ createUnauthenticatedSessionToken: async (payload) => {
16
+ const unauthenticatedSessionToken = await commands.execute('createUnauthenticatedSessionToken');
17
+
18
+ return { unauthenticatedSessionToken };
19
+ },
20
+
21
+ createUserWithRandomPassword: async (payload) => {
22
+ const user = await commands.execute('createUserWithRandomPassword', {
23
+ user: payload.data.user
24
+ });
25
+
26
+ return { user };
27
+ },
28
+
29
+ getUser: async (payload) => {
30
+ let user;
31
+
32
+ if (payload.data?.id) {
33
+ user = await commands.execute('getSingleUser', {
34
+ id: payload.data.id
35
+ });
36
+ } else if (payload.data?.email) {
37
+ user = await commands.execute('getSingleUser', {
38
+ email: payload.data.email
39
+ });
40
+ } else {
41
+ throw new Error('No user ID or email provided');
42
+ }
43
+
44
+ if (!user) {
45
+ throw new Error('User not found');
46
+ }
47
+
48
+ return { user };
49
+ },
50
+
51
+ };
@@ -0,0 +1,50 @@
1
+ import { logger, db } from '@gnar-engine/core';
2
+
3
+ /**
4
+ * Up
5
+ */
6
+ export const up = async () => {
7
+ await initDatabaseTables();
8
+ }
9
+
10
+ /**
11
+ * Down
12
+ */
13
+ export const down = async () => {
14
+ await dropDatabaseTables();
15
+ }
16
+
17
+ /**
18
+ * Create all tables
19
+ */
20
+ export const initDatabaseTables = async () => {
21
+
22
+ // Migrations table
23
+ logger.info("Creating migrations table");
24
+ const createMigrationsTableQuery = `
25
+ CREATE TABLE migrations (
26
+ id INT AUTO_INCREMENT PRIMARY KEY,
27
+ name VARCHAR(255) NOT NULL UNIQUE,
28
+ created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
29
+ )`;
30
+ await db.query(createMigrationsTableQuery);
31
+
32
+ // Seeders table
33
+ logger.info("Creating seeders table");
34
+ const createSeedersTableQuery = `
35
+ CREATE TABLE seeders (
36
+ id INT AUTO_INCREMENT PRIMARY KEY,
37
+ name VARCHAR(255) NOT NULL UNIQUE,
38
+ created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
39
+ )`;
40
+ await db.query(createSeedersTableQuery);
41
+ }
42
+
43
+ /**
44
+ * Drop all tables
45
+ */
46
+ export const dropDatabaseTables = async () => {
47
+ logger.info('Dropping tables');
48
+ await db.query('DROP TABLE IF EXISTS migrations');
49
+ await db.query('DROP TABLE IF EXISTS seeders');
50
+ }
@@ -0,0 +1,63 @@
1
+ import { logger, db } from '@gnar-engine/core';
2
+ import { config } from '../../config.js';
3
+
4
+
5
+ /**
6
+ * Up
7
+ */
8
+ export const up = async () => {
9
+ await initDatabaseTables();
10
+ }
11
+
12
+ /**
13
+ * Down
14
+ */
15
+ export const down = async () => {
16
+ await dropDatabaseTables();
17
+ }
18
+
19
+ /**
20
+ * Create tables
21
+ *
22
+ * @param {*} db
23
+ */
24
+ export const initDatabaseTables = async () => {
25
+
26
+ // create users table
27
+ logger.info('Creating users table');
28
+ const createUserTableQuery = `
29
+ CREATE TABLE users (
30
+ id CHAR(36) PRIMARY KEY,
31
+ username VARCHAR(255),
32
+ email VARCHAR(255) NOT NULL UNIQUE,
33
+ password VARCHAR(255),
34
+ api_key VARCHAR(255),
35
+ role ENUM(${config.userRoles.map(role => `'${role}'`).join(',')}) NOT NULL,
36
+ created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
37
+ updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
38
+ )
39
+ `;
40
+ await db.query(createUserTableQuery, [config.userRoles.join(',')]);
41
+
42
+ // create sessions table
43
+ logger.info('Creating sessions table');
44
+ const createSessionsTableQuery = `
45
+ CREATE TABLE sessions (
46
+ token VARCHAR(255) PRIMARY KEY,
47
+ user_id CHAR(36) NOT NULL,
48
+ created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
49
+ expires_at TIMESTAMP GENERATED ALWAYS AS (created_at + INTERVAL 1 HOUR) VIRTUAL,
50
+ FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
51
+ )
52
+ `;
53
+ await db.query(createSessionsTableQuery);
54
+ }
55
+
56
+ /**
57
+ * Drop all tables
58
+ */
59
+ export const dropDatabaseTables = async () => {
60
+ logger.info('Dropping tables');
61
+ await db.query('DROP TABLE IF EXISTS sessions');
62
+ await db.query('DROP TABLE IF EXISTS users');
63
+ }
@@ -0,0 +1,43 @@
1
+ import { logger, db } from '@gnar-engine/core';
2
+
3
+
4
+ /**
5
+ * Up
6
+ */
7
+ export const up = async () => {
8
+ await initDatabaseTables();
9
+ }
10
+
11
+ /**
12
+ * Down
13
+ */
14
+ export const down = async () => {
15
+ await dropDatabaseTables();
16
+ }
17
+
18
+ /**
19
+ * Create tables
20
+ *
21
+ * @param {*} db
22
+ */
23
+ export const initDatabaseTables = async () => {
24
+
25
+ // create unauth sessions table
26
+ logger.info('Creating sessions table');
27
+ const createUnauthSessionsTableQuery = `
28
+ CREATE TABLE unauthenticated_sessions (
29
+ token VARCHAR(255) PRIMARY KEY,
30
+ created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
31
+ expires_at TIMESTAMP GENERATED ALWAYS AS (created_at + INTERVAL 1 DAY) VIRTUAL
32
+ )
33
+ `;
34
+ await db.query(createUnauthSessionsTableQuery);
35
+ }
36
+
37
+ /**
38
+ * Drop all tables
39
+ */
40
+ export const dropDatabaseTables = async () => {
41
+ logger.info('Dropping tables');
42
+ await db.query('DROP TABLE IF EXISTS unauthenticated_sessions');
43
+ }
@@ -0,0 +1,29 @@
1
+ import { logger } from '@gnar-engine/core';
2
+ import { user } from '../../../services/user.service.js';
3
+
4
+
5
+ /**
6
+ * Up seeder
7
+ */
8
+ export const up = async () => {
9
+
10
+ // create root users using user service
11
+ const users = [];
12
+
13
+ users.push(await user.create({
14
+ email: process.env.USER_ROOT_ADMIN_EMAIL,
15
+ username: process.env.USER_ROOT_ADMIN_USERNAME,
16
+ password: process.env.USER_ROOT_ADMIN_PASSWORD,
17
+ apiKey: process.env.USER_ROOT_ADMIN_API_KEY,
18
+ role: 'service_admin'
19
+ }));
20
+
21
+ logger.info('Completed seeding root user data ' + JSON.stringify(users));
22
+ }
23
+
24
+ /**
25
+ * Down seeder
26
+ */
27
+ export const down = async () => {
28
+ logger.info('Down seeder not implemented');
29
+ }
@@ -0,0 +1,27 @@
1
+ import { logger } from '@gnar-engine/core';
2
+ import { user } from '../../../services/user.service.js';
3
+
4
+ /**
5
+ * Up seeder
6
+ */
7
+ export const up = async () => {
8
+
9
+ // create root users using user service
10
+ const users = [];
11
+
12
+ users.push(await user.create({
13
+ email: 'alex@gnar.co.uk',
14
+ username: 'alexgnar',
15
+ password: 'gnarlybulkwash',
16
+ role: 'admin'
17
+ }));
18
+
19
+ logger.info('Completed seeding root user data ' + JSON.stringify(users));
20
+ }
21
+
22
+ /**
23
+ * Down seeder
24
+ */
25
+ export const down = async () => {
26
+ logger.info('Down seeder not implemented');
27
+ }
@@ -0,0 +1,29 @@
1
+ import { logger } from '@gnar-engine/core';
2
+ import { user } from '../../../services/user.service.js';
3
+
4
+
5
+ /**
6
+ * Up seeder
7
+ */
8
+ export const up = async () => {
9
+
10
+ // create root users using user service
11
+ const users = [];
12
+
13
+ users.push(await user.create({
14
+ email: process.env.USER_ROOT_ADMIN_EMAIL,
15
+ username: process.env.USER_ROOT_ADMIN_USERNAME,
16
+ password: process.env.USER_ROOT_ADMIN_PASSWORD,
17
+ apiKey: process.env.USER_ROOT_ADMIN_API_KEY,
18
+ role: 'service_admin'
19
+ }));
20
+
21
+ logger.info('Completed seeding root user data ' + JSON.stringify(users));
22
+ }
23
+
24
+ /**
25
+ * Down seeder
26
+ */
27
+ export const down = async () => {
28
+ logger.info('Down seeder not implemented');
29
+ }
@@ -0,0 +1,81 @@
1
+ import { config } from '../config.js';
2
+
3
+
4
+ export const authorise = {
5
+
6
+ /**
7
+ * Authorise get single user
8
+ *
9
+ * @param {} request
10
+ * @param {*} reply
11
+ */
12
+ getSingle: async (request, reply) => {
13
+ if (!request.user) {
14
+ reply.code(403).send({error: 'not authorised'});
15
+ }
16
+
17
+ if (request.user.role !== 'service_admin' && request.user.id !== request.params.id) {
18
+ reply.code(403).send({error: 'not authorised'});
19
+ }
20
+ },
21
+
22
+ /**
23
+ * Authorise get many users
24
+ */
25
+ getMany: async (request, reply) => {
26
+ if (!request.user || request.user.role !== 'service_admin') {
27
+ reply.code(403).send({error: 'not authorised'});
28
+ }
29
+ },
30
+
31
+ /**
32
+ * Authorise create users
33
+ */
34
+ create: async (request, reply) => {
35
+ // If no role is provided check if default role is publicly creatable
36
+ if (request.body.user?.role && config.publicCanCreateRoles.includes(request.body.user?.role)) {
37
+ return;
38
+ }
39
+
40
+ // allow anyone to create default role or roles that don't require admin rights
41
+ if (config.publicCanCreateRoles.includes(config.defaultUserRole)) {
42
+ return;
43
+ }
44
+
45
+ // only admins can create other admin users
46
+ if (!request.user || request.user.role !== 'service_admin') {
47
+ reply.code(403).send({error: 'not authorised'});
48
+ }
49
+ },
50
+
51
+ /**
52
+ * Authorise update user
53
+ */
54
+ update: async (request, reply) => {
55
+ // users can update their own user
56
+ if (request.user?.id === request.params.id) {
57
+ // ensure the user is not trying to update their role to a non-publicly creatable role
58
+ if (request.body?.role && !config.publicCanCreateRoles.includes(request.body?.role)) {
59
+ reply.code(403).send({error: 'not authorised'});
60
+ }
61
+
62
+ // otherwise authorised
63
+ return;
64
+ }
65
+
66
+ // only admins can update other users
67
+ if (!request.user || request.user.role !== 'service_admin') {
68
+ reply.code(403).send({error: 'not authorised'});
69
+ }
70
+ },
71
+
72
+ /**
73
+ * Authorise delete user
74
+ */
75
+ delete: async (request, reply) => {
76
+ // only admins can delete users
77
+ if (!request.user || request.user.role !== 'service_admin') {
78
+ reply.code(403).send({error: 'not authorised'});
79
+ }
80
+ }
81
+ }
@@ -0,0 +1,69 @@
1
+ import { schema } from '@gnar-engine/core';
2
+ import { config } from '../config.js';
3
+
4
+
5
+ // User create schema
6
+ const userSchema = {
7
+ schemaName: 'userService.userSchema',
8
+ schema: {
9
+ type: 'object',
10
+ properties: {
11
+ email: { type: 'string', format: 'email' },
12
+ password: { type: 'string', minLength: 8 },
13
+ role: { type: 'string', enum: config.allowedUserRoles, default: config.defaultUserRole },
14
+ contactId: { type: 'string' },
15
+ username: { type: 'string' }
16
+ },
17
+ required: ['email', 'password'],
18
+ additionalProperties: false
19
+ }
20
+ };
21
+
22
+ // Service admin user create schema
23
+ const serviceAdminUserSchema = {
24
+ schemaName: 'userService.serviceAdminUserSchema',
25
+ schema: {
26
+ type: 'object',
27
+ properties: {
28
+ email: { type: 'string', format: 'email' },
29
+ role: { type: 'string', enum: ['service_admin'] },
30
+ contactId: { type: 'string' }
31
+ },
32
+ required: ['email'],
33
+ additionalProperties: false
34
+ }
35
+ };
36
+
37
+ // User update schema
38
+ const userUpdateSchema = {
39
+ schemaName: 'userService.userUpdateSchema',
40
+ schema: {
41
+ type: 'object',
42
+ properties: {
43
+ email: { type: 'string', format: 'email' },
44
+ role: { type: 'string', enum: config.allowedUserRoles, default: config.defaultUserRole },
45
+ contactId: { type: 'string' }
46
+ },
47
+ additionalProperties: false
48
+ }
49
+ };
50
+
51
+ // Service admin user update schema
52
+ const serviceAdminUserUpdateSchema = {
53
+ schemaName: 'userService.serviceAdminUserUpdateSchema',
54
+ schema: {
55
+ type: 'object',
56
+ properties: {
57
+ email: { type: 'string', format: 'email' },
58
+ role: { type: 'string', enum: ['service_admin'] },
59
+ contactId: { type: 'string' }
60
+ },
61
+ additionalProperties: false
62
+ }
63
+ };
64
+
65
+ // Compile schemas
66
+ export const validateUser = schema.compile(userSchema);
67
+ export const validateServiceAdminUser = schema.compile(serviceAdminUserSchema);
68
+ export const validateUserUpdate = schema.compile(userUpdateSchema);
69
+ export const validateServiceAdminUserUpdate = schema.compile(serviceAdminUserUpdateSchema);