@gnar-engine/cli 1.0.0 → 1.0.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/assets/gnar-engine-logo-white.svg +9 -0
- package/bootstrap/deploy.localdev.yml +51 -0
- package/bootstrap/secrets.localdev.yml +27 -0
- package/bootstrap/services/agent/Dockerfile +23 -0
- package/bootstrap/services/agent/notes.md +28 -0
- package/bootstrap/services/agent/package.json +16 -0
- package/bootstrap/services/agent/src/app.js +52 -0
- package/bootstrap/services/agent/src/commands/agent.handler.js +104 -0
- package/bootstrap/services/agent/src/config.js +52 -0
- package/bootstrap/services/agent/src/controllers/http.controller.js +44 -0
- package/bootstrap/services/agent/src/controllers/message.controller.js +51 -0
- package/bootstrap/services/agent/src/db/migrations/01-init.js +50 -0
- package/bootstrap/services/agent/src/db/migrations/02-agent-service-init.js +36 -0
- package/bootstrap/services/agent/src/policies/agent.policy.js +13 -0
- package/bootstrap/services/agent/src/schema/Agent.schema.js +17 -0
- package/bootstrap/services/agent/src/services/agent.service.js +259 -0
- package/bootstrap/services/agent/src/services/chatgpt.service.js +46 -0
- package/bootstrap/services/agent/src/services/manifest.service.js +21 -0
- package/bootstrap/services/control/Dockerfile +23 -0
- package/bootstrap/services/control/Dockerfile.prod +37 -0
- package/bootstrap/services/control/README.md +25 -0
- package/bootstrap/services/control/package.json +16 -0
- package/bootstrap/services/control/src/app.js +45 -0
- package/bootstrap/services/control/src/commands/control.handler.js +231 -0
- package/bootstrap/services/control/src/commands/service.handler.js +81 -0
- package/bootstrap/services/control/src/commands/task.handler.js +247 -0
- package/bootstrap/services/control/src/config.js +55 -0
- package/bootstrap/services/control/src/controllers/http.controller.js +228 -0
- package/bootstrap/services/control/src/controllers/message.controller.js +40 -0
- package/bootstrap/services/control/src/db/migrations/01-init.js +50 -0
- package/bootstrap/services/control/src/db/migrations/02-control-service-init.js +60 -0
- package/bootstrap/services/control/src/db/migrations/03-alter-tasks.js +29 -0
- package/bootstrap/services/control/src/policies/task.policy.js +53 -0
- package/bootstrap/services/control/src/schema/control.schema.js +42 -0
- package/bootstrap/services/control/src/services/registry.service.js +83 -0
- package/bootstrap/services/control/src/services/reset.service.js +28 -0
- package/bootstrap/services/control/src/services/task.service.js +153 -0
- package/bootstrap/services/control/src/tests/control.test.js +50 -0
- package/bootstrap/services/notification/Dockerfile +23 -0
- package/bootstrap/services/notification/Dockerfile.prod +37 -0
- package/bootstrap/services/notification/README.md +3 -0
- package/bootstrap/services/notification/package.json +34 -0
- package/bootstrap/services/notification/src/app.js +51 -0
- package/bootstrap/services/notification/src/commands/command-bus.js +20 -0
- package/bootstrap/services/notification/src/commands/handlers/control.handler.js +18 -0
- package/bootstrap/services/notification/src/commands/handlers/notification.handler.js +157 -0
- package/bootstrap/services/notification/src/config.js +15 -0
- package/bootstrap/services/notification/src/controllers/message.controller.js +82 -0
- package/bootstrap/services/notification/src/services/logger.service.js +16 -0
- package/bootstrap/services/notification/src/services/ses.service.js +23 -0
- package/bootstrap/services/notification/src/templates/admin-order-recieved.hbs +136 -0
- package/bootstrap/services/notification/src/templates/admin-subscription-failed.hbs +87 -0
- package/bootstrap/services/notification/src/templates/customer-order-recieved.hbs +132 -0
- package/bootstrap/services/notification/src/templates/customer-subscription-failed.hbs +77 -0
- package/bootstrap/services/notification/src/tests/notification.test.js +0 -0
- package/bootstrap/services/portal/Dockerfile +23 -0
- package/bootstrap/services/portal/Dockerfile.remote +40 -0
- package/bootstrap/services/portal/README.md +22 -0
- package/bootstrap/services/portal/nginx.conf +12 -0
- package/bootstrap/services/portal/package.json +59 -0
- package/bootstrap/services/portal/public/favicon.ico +0 -0
- package/bootstrap/services/portal/public/gnar-white.png +0 -0
- package/bootstrap/services/portal/public/gnarengine-logo-black.png +0 -0
- package/bootstrap/services/portal/public/index.html +43 -0
- package/bootstrap/services/portal/public/logo192.png +0 -0
- package/bootstrap/services/portal/public/logo512.png +0 -0
- package/bootstrap/services/portal/public/manifest.json +25 -0
- package/bootstrap/services/portal/public/robots.txt +3 -0
- package/bootstrap/services/portal/src/App.js +56 -0
- package/bootstrap/services/portal/src/assets/Logo_Anchord_Black.svg +1 -0
- package/bootstrap/services/portal/src/assets/Logo_Anchord_Black_Green.svg +1 -0
- package/bootstrap/services/portal/src/assets/Logo_Anchord_White_Green.svg +1 -0
- package/bootstrap/services/portal/src/assets/activity.svg +3 -0
- package/bootstrap/services/portal/src/assets/arrow.svg +3 -0
- package/bootstrap/services/portal/src/assets/bin-white.svg +3 -0
- package/bootstrap/services/portal/src/assets/bin.svg +3 -0
- package/bootstrap/services/portal/src/assets/check.svg +3 -0
- package/bootstrap/services/portal/src/assets/chevron.svg +3 -0
- package/bootstrap/services/portal/src/assets/contact.svg +3 -0
- package/bootstrap/services/portal/src/assets/dots-vertical.svg +5 -0
- package/bootstrap/services/portal/src/assets/eye-off.svg +3 -0
- package/bootstrap/services/portal/src/assets/eye.svg +4 -0
- package/bootstrap/services/portal/src/assets/gnar-engine-black.svg +47 -0
- package/bootstrap/services/portal/src/assets/gnar-engine-white.svg +47 -0
- package/bootstrap/services/portal/src/assets/gnar_engine.svg +3 -0
- package/bootstrap/services/portal/src/assets/gnarengine-logo-black.png +0 -0
- package/bootstrap/services/portal/src/assets/home.svg +3 -0
- package/bootstrap/services/portal/src/assets/link.svg +3 -0
- package/bootstrap/services/portal/src/assets/lock.svg +3 -0
- package/bootstrap/services/portal/src/assets/package.svg +4 -0
- package/bootstrap/services/portal/src/assets/raffle.svg +3 -0
- package/bootstrap/services/portal/src/assets/settings.svg +4 -0
- package/bootstrap/services/portal/src/assets/shopping-bag.svg +3 -0
- package/bootstrap/services/portal/src/assets/user-black.svg +3 -0
- package/bootstrap/services/portal/src/assets/user.svg +3 -0
- package/bootstrap/services/portal/src/assets/users.svg +3 -0
- package/bootstrap/services/portal/src/assets/wallet.svg +3 -0
- package/bootstrap/services/portal/src/css/style.css +1007 -0
- package/bootstrap/services/portal/src/data/data.js +70 -0
- package/bootstrap/services/portal/src/features/attributeFormRow/AttributeFormRow.jsx +32 -0
- package/bootstrap/services/portal/src/features/billingShipping/BillingShipping.jsx +160 -0
- package/bootstrap/services/portal/src/features/crud/crudEdit.less +230 -0
- package/bootstrap/services/portal/src/features/crud/crudList.less +134 -0
- package/bootstrap/services/portal/src/features/crud/crudPage.less +31 -0
- package/bootstrap/services/portal/src/features/crudContact/CrudContactList.jsx +108 -0
- package/bootstrap/services/portal/src/features/crudContact/CrudContactSingle.jsx +243 -0
- package/bootstrap/services/portal/src/features/crudOrder/CrudOrderList.jsx +109 -0
- package/bootstrap/services/portal/src/features/crudOrder/CrudOrderSingle.jsx +315 -0
- package/bootstrap/services/portal/src/features/crudProducts/CrudProductList.jsx +104 -0
- package/bootstrap/services/portal/src/features/crudProducts/CrudProductSingle.jsx +388 -0
- package/bootstrap/services/portal/src/features/crudRaffles/CrudRafflesList.jsx +104 -0
- package/bootstrap/services/portal/src/features/crudRaffles/CrudRafflesSingle.jsx +208 -0
- package/bootstrap/services/portal/src/features/crudSubscription/CrudSubscriptionList.jsx +110 -0
- package/bootstrap/services/portal/src/features/crudSubscription/CrudSubscriptionSingle.jsx +261 -0
- package/bootstrap/services/portal/src/features/crudUser/CrudUserList.jsx +107 -0
- package/bootstrap/services/portal/src/features/crudUser/CrudUserSingle.jsx +402 -0
- package/bootstrap/services/portal/src/features/inventoryFormRow/InventoryFormRow.jsx +30 -0
- package/bootstrap/services/portal/src/features/lineItems/LineItems.jsx +113 -0
- package/bootstrap/services/portal/src/features/loginForm/LoginForm.jsx +56 -0
- package/bootstrap/services/portal/src/features/loginForm/loginForm.less +56 -0
- package/bootstrap/services/portal/src/features/notes/Notes.jsx +18 -0
- package/bootstrap/services/portal/src/features/passwordReset/PasswordResetForm.jsx +96 -0
- package/bootstrap/services/portal/src/features/passwordReset/PasswordResetRequestForm.jsx +74 -0
- package/bootstrap/services/portal/src/features/priceFormRow/PriceFormRow.jsx +102 -0
- package/bootstrap/services/portal/src/features/priceFormRow/priceFormRow.less +24 -0
- package/bootstrap/services/portal/src/features/raffleEntriesList/RaffleEntriesList.jsx +99 -0
- package/bootstrap/services/portal/src/features/raffleProductFormRow/RaffleProductFormRow.jsx +46 -0
- package/bootstrap/services/portal/src/features/sidebar/Sidebar.jsx +64 -0
- package/bootstrap/services/portal/src/features/sidebar/sidebar.less +49 -0
- package/bootstrap/services/portal/src/features/skus/Skus.jsx +109 -0
- package/bootstrap/services/portal/src/features/subscriptionSchedule/SubscriptionSchedule.jsx +44 -0
- package/bootstrap/services/portal/src/features/taxonomyFormRow/TaxonomyFormRow.jsx +32 -0
- package/bootstrap/services/portal/src/features/user/User.jsx +54 -0
- package/bootstrap/services/portal/src/features/user/user.less +57 -0
- package/bootstrap/services/portal/src/includes/utilities.js +259 -0
- package/bootstrap/services/portal/src/index.js +14 -0
- package/bootstrap/services/portal/src/layouts/CrudLayout.jsx +50 -0
- package/bootstrap/services/portal/src/layouts/LoginLayout.jsx +17 -0
- package/bootstrap/services/portal/src/layouts/PortalLayout.jsx +48 -0
- package/bootstrap/services/portal/src/layouts/loginLayout.less +33 -0
- package/bootstrap/services/portal/src/layouts/portalLayout.less +67 -0
- package/bootstrap/services/portal/src/pages/contacts/Contacts.jsx +199 -0
- package/bootstrap/services/portal/src/pages/dashboard/Dashboard.jsx +17 -0
- package/bootstrap/services/portal/src/pages/integrations/Integrations.jsx +10 -0
- package/bootstrap/services/portal/src/pages/login/Login.jsx +15 -0
- package/bootstrap/services/portal/src/pages/login/login.less +10 -0
- package/bootstrap/services/portal/src/pages/orders/Orders.jsx +199 -0
- package/bootstrap/services/portal/src/pages/passwordReset/PasswordResetPage.jsx +15 -0
- package/bootstrap/services/portal/src/pages/passwordResetRequest/PasswordResetRequestPage.jsx +15 -0
- package/bootstrap/services/portal/src/pages/payments/Payments.jsx +10 -0
- package/bootstrap/services/portal/src/pages/portal/Portal.jsx +43 -0
- package/bootstrap/services/portal/src/pages/products/Products.jsx +212 -0
- package/bootstrap/services/portal/src/pages/raffleEntries/RaffleEntries.jsx +124 -0
- package/bootstrap/services/portal/src/pages/raffles/Raffles.jsx +186 -0
- package/bootstrap/services/portal/src/pages/reports/Reports.jsx +10 -0
- package/bootstrap/services/portal/src/pages/settings/Settings.jsx +10 -0
- package/bootstrap/services/portal/src/pages/subscriptions/Subscriptions.jsx +199 -0
- package/bootstrap/services/portal/src/pages/users/Users.jsx +193 -0
- package/bootstrap/services/portal/src/pages/users/users.less +25 -0
- package/bootstrap/services/portal/src/slices/authSlice.js +71 -0
- package/bootstrap/services/portal/src/store/configureStore.js +12 -0
- package/bootstrap/services/portal/src/styles/global.less +159 -0
- package/bootstrap/services/portal/src/styles/inputs.less +157 -0
- package/bootstrap/services/portal/src/styles/main.less +26 -0
- package/bootstrap/services/portal/src/ui/collapsible/Collapsible.jsx +97 -0
- package/bootstrap/services/portal/src/ui/collapsible/collapsible.less +23 -0
- package/bootstrap/services/portal/src/ui/customCheckbox/CustomCheckbox.jsx +17 -0
- package/bootstrap/services/portal/src/ui/customCheckbox/customCheckbox.less +42 -0
- package/bootstrap/services/portal/src/ui/customMultiSelect/CustomMultiSelect.jsx +63 -0
- package/bootstrap/services/portal/src/ui/customMultiSelect/CustomMultiSelectPeriod.jsx +63 -0
- package/bootstrap/services/portal/src/ui/customSelect/CustomSelect.jsx +63 -0
- package/bootstrap/services/portal/src/ui/customSelect/customSelect.less +92 -0
- package/bootstrap/services/portal/src/ui/goBack/GoBack.jsx +19 -0
- package/bootstrap/services/portal/src/ui/loader/Loader.jsx +12 -0
- package/bootstrap/services/portal/src/ui/pagination/Pagination.jsx +23 -0
- package/bootstrap/services/portal/src/ui/repeater/Repeater.jsx +29 -0
- package/bootstrap/services/portal/src/ui/saveButton/SaveButton.jsx +69 -0
- package/bootstrap/services/portal/src/ui/saveButton/saveButton.less +0 -0
- package/bootstrap/services/rabbit-mq/Dockerfile.prod +9 -0
- package/bootstrap/services/user/Dockerfile +23 -0
- package/bootstrap/services/user/Dockerfile.prod +37 -0
- package/bootstrap/services/user/README.md +8 -0
- package/bootstrap/services/user/package.json +16 -0
- package/bootstrap/services/user/src/app.js +45 -0
- package/bootstrap/services/user/src/commands/session.handler.js +23 -0
- package/bootstrap/services/user/src/commands/user.handler.js +286 -0
- package/bootstrap/services/user/src/config.js +73 -0
- package/bootstrap/services/user/src/controllers/http.controller.js +156 -0
- package/bootstrap/services/user/src/controllers/message.controller.js +51 -0
- package/bootstrap/services/user/src/db/migrations/01-init.js +50 -0
- package/bootstrap/services/user/src/db/migrations/02-user-service-init.js +63 -0
- package/bootstrap/services/user/src/db/migrations/03-unauth-sessions.js +43 -0
- package/bootstrap/services/user/src/db/seeders/development/01-root-user.js +29 -0
- package/bootstrap/services/user/src/db/seeders/development/02-portal-admin-user.js +27 -0
- package/bootstrap/services/user/src/db/seeders/production/01-root-user.js +29 -0
- package/bootstrap/services/user/src/policies/user.policy.js +81 -0
- package/bootstrap/services/user/src/schema/user.schema.js +69 -0
- package/bootstrap/services/user/src/services/authentication.service.js +127 -0
- package/bootstrap/services/user/src/services/session.service.js +58 -0
- package/bootstrap/services/user/src/services/user.service.js +130 -0
- package/bootstrap/services/user/src/tests/user.test.js +126 -0
- package/package.json +3 -7
- package/src/agent/agent.client.js +28 -0
- package/src/agent/commands.js +48 -0
- package/src/cli.js +30 -0
- package/src/config.js +8 -0
- package/src/control/commands.js +156 -0
- package/src/control/control.client.js +127 -0
- package/src/dev/commands.js +71 -0
- package/src/dev/dev.service.js +320 -0
- package/src/engine/infra.js +142 -0
- package/src/helpers/helpers.js +63 -0
- package/src/profiles/command.js +170 -0
- package/src/profiles/profiles.client.js +101 -0
- package/src/scaffolder/commands.js +123 -0
- package/src/scaffolder/scaffolder.handler.js +252 -0
- package/src/services/client.js +174 -0
- package/templates/service/Dockerfile.hbs +20 -0
- package/templates/service/app.js.hbs +38 -0
- package/templates/service/commands/{{serviceName}}.handler.js.hbs +97 -0
- package/templates/service/config.js.hbs +48 -0
- package/templates/service/controllers/http.controller.js.hbs +87 -0
- package/templates/service/controllers/message.controller.js.hbs +51 -0
- package/templates/service/db/migrations/01-init.js.hbs +50 -0
- package/templates/service/db/migrations/02-{{lowerCase serviceName}}-service-init.js.hbs +23 -0
- package/templates/service/package.json.hbs +18 -0
- package/templates/service/policies/{{serviceName}}.policy.js.hbs +49 -0
- package/templates/service/schema/{{serviceName}}.schema.js.hbs +14 -0
- package/templates/service/services/{{serviceName}}.service.js.hbs +32 -0
- 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);
|