aboutsummaryrefslogtreecommitdiffstats
path: root/app
diff options
context:
space:
mode:
authorLibravatar mhatvan <markus_hatvan@aon.at>2021-08-04 17:44:54 +0200
committerLibravatar Vijay Raghavan Aravamudhan <vraravam@users.noreply.github.com>2021-08-04 15:57:58 +0000
commit13f6d34cefb3bc5e3ba65a959304d4465f0ee92a (patch)
tree7739098f6f25140fa96877e2d05f98b5929f90f2 /app
parentBump tar from 4.4.10 to 4.4.15 (diff)
downloadferdium-server-13f6d34cefb3bc5e3ba65a959304d4465f0ee92a.tar.gz
ferdium-server-13f6d34cefb3bc5e3ba65a959304d4465f0ee92a.tar.zst
ferdium-server-13f6d34cefb3bc5e3ba65a959304d4465f0ee92a.zip
chore: improve dev setup
- upgrade uuid, eslint, husky - improve .eslintrc.js and correct lint script - update uuid imports to conform to v8 - add .prettierrc.js for consistent formatting - file changes due to lint --fix
Diffstat (limited to 'app')
-rw-r--r--app/Controllers/Http/DashboardController.js128
-rw-r--r--app/Controllers/Http/RecipeController.js1
-rw-r--r--app/Controllers/Http/ServiceController.js175
-rw-r--r--app/Controllers/Http/StaticController.js1
-rw-r--r--app/Controllers/Http/UserController.js150
-rw-r--r--app/Controllers/Http/WorkspaceController.js71
-rw-r--r--app/Exceptions/Handler.js1
-rw-r--r--app/Middleware/ConvertEmptyStringsToNull.js1
-rw-r--r--app/Models/Recipe.js1
-rw-r--r--app/Models/Service.js1
-rw-r--r--app/Models/Token.js1
-rw-r--r--app/Models/Traits/NoTimestamp.js1
-rw-r--r--app/Models/User.js1
-rw-r--r--app/Models/Workspace.js1
14 files changed, 253 insertions, 281 deletions
diff --git a/app/Controllers/Http/DashboardController.js b/app/Controllers/Http/DashboardController.js
index a588c75..84a88a9 100644
--- a/app/Controllers/Http/DashboardController.js
+++ b/app/Controllers/Http/DashboardController.js
@@ -1,40 +1,34 @@
1 1const { validateAll } = use('Validator');
2const {
3 validateAll,
4} = use('Validator');
5 2
6const Service = use('App/Models/Service'); 3const Service = use('App/Models/Service');
7const Workspace = use('App/Models/Workspace'); 4const Workspace = use('App/Models/Workspace');
8const Persona = use('Persona'); 5const Persona = use('Persona');
9 6
10const crypto = require('crypto'); 7const crypto = require('crypto');
11const uuid = require('uuid/v4'); 8const { v4: uuid } = require('uuid');
12 9
13class DashboardController { 10class DashboardController {
14 async login({ 11 async login({ request, response, auth, session }) {
15 request,
16 response,
17 auth,
18 session,
19 }) {
20 const validation = await validateAll(request.all(), { 12 const validation = await validateAll(request.all(), {
21 mail: 'required|email', 13 mail: 'required|email',
22 password: 'required', 14 password: 'required',
23 }); 15 });
24 if (validation.fails()) { 16 if (validation.fails()) {
25 session.withErrors({ 17 session
26 type: 'danger', 18 .withErrors({
27 message: 'Invalid mail or password', 19 type: 'danger',
28 }).flashExcept(['password']); 20 message: 'Invalid mail or password',
21 })
22 .flashExcept(['password']);
29 return response.redirect('back'); 23 return response.redirect('back');
30 } 24 }
31 25
32 const { 26 const { mail, password } = request.all();
33 mail,
34 password,
35 } = request.all();
36 27
37 const hashedPassword = crypto.createHash('sha256').update(password).digest('base64'); 28 const hashedPassword = crypto
29 .createHash('sha256')
30 .update(password)
31 .digest('base64');
38 32
39 try { 33 try {
40 await auth.authenticator('session').attempt(mail, hashedPassword); 34 await auth.authenticator('session').attempt(mail, hashedPassword);
@@ -48,10 +42,7 @@ class DashboardController {
48 return response.redirect('/user/account'); 42 return response.redirect('/user/account');
49 } 43 }
50 44
51 async forgotPassword({ 45 async forgotPassword({ request, view }) {
52 request,
53 view,
54 }) {
55 const validation = await validateAll(request.all(), { 46 const validation = await validateAll(request.all(), {
56 mail: 'required|email', 47 mail: 'required|email',
57 }); 48 });
@@ -63,7 +54,7 @@ class DashboardController {
63 } 54 }
64 try { 55 try {
65 await Persona.forgotPassword(request.input('mail')); 56 await Persona.forgotPassword(request.input('mail'));
66 // eslint-disable-next-line no-empty 57 // eslint-disable-next-line no-empty
67 } catch (e) {} 58 } catch (e) {}
68 59
69 return view.render('others.message', { 60 return view.render('others.message', {
@@ -72,10 +63,7 @@ class DashboardController {
72 }); 63 });
73 } 64 }
74 65
75 async resetPassword({ 66 async resetPassword({ request, view }) {
76 request,
77 view,
78 }) {
79 const validation = await validateAll(request.all(), { 67 const validation = await validateAll(request.all(), {
80 password: 'required', 68 password: 'required',
81 password_confirmation: 'required', 69 password_confirmation: 'required',
@@ -90,8 +78,14 @@ class DashboardController {
90 } 78 }
91 79
92 const payload = { 80 const payload = {
93 password: crypto.createHash('sha256').update(request.input('password')).digest('base64'), 81 password: crypto
94 password_confirmation: crypto.createHash('sha256').update(request.input('password_confirmation')).digest('base64'), 82 .createHash('sha256')
83 .update(request.input('password'))
84 .digest('base64'),
85 password_confirmation: crypto
86 .createHash('sha256')
87 .update(request.input('password_confirmation'))
88 .digest('base64'),
95 }; 89 };
96 90
97 try { 91 try {
@@ -109,11 +103,7 @@ class DashboardController {
109 }); 103 });
110 } 104 }
111 105
112 async account({ 106 async account({ auth, view, response }) {
113 auth,
114 view,
115 response,
116 }) {
117 try { 107 try {
118 await auth.check(); 108 await auth.check();
119 } catch (error) { 109 } catch (error) {
@@ -127,13 +117,7 @@ class DashboardController {
127 }); 117 });
128 } 118 }
129 119
130 async edit({ 120 async edit({ auth, request, session, view, response }) {
131 auth,
132 request,
133 session,
134 view,
135 response,
136 }) {
137 let validation = await validateAll(request.all(), { 121 let validation = await validateAll(request.all(), {
138 username: 'required', 122 username: 'required',
139 email: 'required', 123 email: 'required',
@@ -174,7 +158,10 @@ class DashboardController {
174 user.lastname = request.input('lastname'); 158 user.lastname = request.input('lastname');
175 user.email = request.input('email'); 159 user.email = request.input('email');
176 if (request.input('password')) { 160 if (request.input('password')) {
177 const hashedPassword = crypto.createHash('sha256').update(request.input('password')).digest('base64'); 161 const hashedPassword = crypto
162 .createHash('sha256')
163 .update(request.input('password'))
164 .digest('base64');
178 user.password = hashedPassword; 165 user.password = hashedPassword;
179 } 166 }
180 user.save(); 167 user.save();
@@ -186,10 +173,7 @@ class DashboardController {
186 }); 173 });
187 } 174 }
188 175
189 async data({ 176 async data({ auth, view }) {
190 auth,
191 view,
192 }) {
193 const general = auth.user; 177 const general = auth.user;
194 const services = (await auth.user.services().fetch()).toJSON(); 178 const services = (await auth.user.services().fetch()).toJSON();
195 const workspaces = (await auth.user.workspaces().fetch()).toJSON(); 179 const workspaces = (await auth.user.workspaces().fetch()).toJSON();
@@ -206,10 +190,7 @@ class DashboardController {
206 }); 190 });
207 } 191 }
208 192
209 async export({ 193 async export({ auth, response }) {
210 auth,
211 response,
212 }) {
213 const general = auth.user; 194 const general = auth.user;
214 const services = (await auth.user.services().fetch()).toJSON(); 195 const services = (await auth.user.services().fetch()).toJSON();
215 const workspaces = (await auth.user.workspaces().fetch()).toJSON(); 196 const workspaces = (await auth.user.workspaces().fetch()).toJSON();
@@ -228,13 +209,7 @@ class DashboardController {
228 .send(exportData); 209 .send(exportData);
229 } 210 }
230 211
231 async import({ 212 async import({ auth, request, session, response, view }) {
232 auth,
233 request,
234 session,
235 response,
236 view,
237 }) {
238 const validation = await validateAll(request.all(), { 213 const validation = await validateAll(request.all(), {
239 file: 'required', 214 file: 'required',
240 }); 215 });
@@ -252,7 +227,10 @@ class DashboardController {
252 } 227 }
253 228
254 if (!file || !file.services || !file.workspaces) { 229 if (!file || !file.services || !file.workspaces) {
255 session.flash({ type: 'danger', message: 'Invalid Ferdi account file (2)' }); 230 session.flash({
231 type: 'danger',
232 message: 'Invalid Ferdi account file (2)',
233 });
256 return response.redirect('back'); 234 return response.redirect('back');
257 } 235 }
258 236
@@ -265,9 +243,13 @@ class DashboardController {
265 let serviceId; 243 let serviceId;
266 do { 244 do {
267 serviceId = uuid(); 245 serviceId = uuid();
268 } while ((await Service.query().where('serviceId', serviceId).fetch()).rows.length > 0); // eslint-disable-line no-await-in-loop 246 } while (
247 (await Service.query().where('serviceId', serviceId).fetch()).rows
248 .length > 0
249 ); // eslint-disable-line no-await-in-loop
269 250
270 await Service.create({ // eslint-disable-line no-await-in-loop 251 await Service.create({
252 // eslint-disable-line no-await-in-loop
271 userId: auth.user.id, 253 userId: auth.user.id,
272 serviceId, 254 serviceId,
273 name: service.name, 255 name: service.name,
@@ -291,11 +273,17 @@ class DashboardController {
291 let workspaceId; 273 let workspaceId;
292 do { 274 do {
293 workspaceId = uuid(); 275 workspaceId = uuid();
294 } while ((await Workspace.query().where('workspaceId', workspaceId).fetch()).rows.length > 0); // eslint-disable-line no-await-in-loop 276 } while (
277 (await Workspace.query().where('workspaceId', workspaceId).fetch())
278 .rows.length > 0
279 ); // eslint-disable-line no-await-in-loop
295 280
296 const services = workspace.services.map((service) => serviceIdTranslation[service]); 281 const services = workspace.services.map(
282 service => serviceIdTranslation[service],
283 );
297 284
298 await Workspace.create({ // eslint-disable-line no-await-in-loop 285 await Workspace.create({
286 // eslint-disable-line no-await-in-loop
299 userId: auth.user.id, 287 userId: auth.user.id,
300 workspaceId, 288 workspaceId,
301 name: workspace.name, 289 name: workspace.name,
@@ -318,18 +306,12 @@ class DashboardController {
318 }); 306 });
319 } 307 }
320 308
321 logout({ 309 logout({ auth, response }) {
322 auth,
323 response,
324 }) {
325 auth.authenticator('session').logout(); 310 auth.authenticator('session').logout();
326 return response.redirect('/user/login'); 311 return response.redirect('/user/login');
327 } 312 }
328 313
329 delete({ 314 delete({ auth, response }) {
330 auth,
331 response,
332 }) {
333 auth.user.delete(); 315 auth.user.delete();
334 auth.authenticator('session').logout(); 316 auth.authenticator('session').logout();
335 return response.redirect('/user/login'); 317 return response.redirect('/user/login');
diff --git a/app/Controllers/Http/RecipeController.js b/app/Controllers/Http/RecipeController.js
index 9d58708..344548c 100644
--- a/app/Controllers/Http/RecipeController.js
+++ b/app/Controllers/Http/RecipeController.js
@@ -1,4 +1,3 @@
1
2const Recipe = use('App/Models/Recipe'); 1const Recipe = use('App/Models/Recipe');
3const Helpers = use('Helpers'); 2const Helpers = use('Helpers');
4const Drive = use('Drive'); 3const Drive = use('Drive');
diff --git a/app/Controllers/Http/ServiceController.js b/app/Controllers/Http/ServiceController.js
index 4aa611c..ef8b168 100644
--- a/app/Controllers/Http/ServiceController.js
+++ b/app/Controllers/Http/ServiceController.js
@@ -1,21 +1,15 @@
1const Service = use('App/Models/Service'); 1const Service = use('App/Models/Service');
2const { 2const { validateAll } = use('Validator');
3 validateAll,
4} = use('Validator');
5const Env = use('Env'); 3const Env = use('Env');
6const Helpers = use('Helpers'); 4const Helpers = use('Helpers');
7 5
8const uuid = require('uuid/v4'); 6const { v4: uuid } = require('uuid');
9const path = require('path'); 7const path = require('path');
10const fs = require('fs-extra'); 8const fs = require('fs-extra');
11 9
12class ServiceController { 10class ServiceController {
13 // Create a new service for user 11 // Create a new service for user
14 async create({ 12 async create({ request, response, auth }) {
15 request,
16 response,
17 auth,
18 }) {
19 try { 13 try {
20 await auth.getUser(); 14 await auth.getUser();
21 } catch (error) { 15 } catch (error) {
@@ -41,7 +35,10 @@ class ServiceController {
41 let serviceId; 35 let serviceId;
42 do { 36 do {
43 serviceId = uuid(); 37 serviceId = uuid();
44 } while ((await Service.query().where('serviceId', serviceId).fetch()).rows.length > 0); // eslint-disable-line no-await-in-loop 38 } while (
39 (await Service.query().where('serviceId', serviceId).fetch()).rows
40 .length > 0
41 ); // eslint-disable-line no-await-in-loop
45 42
46 await Service.create({ 43 await Service.create({
47 userId: auth.user.id, 44 userId: auth.user.id,
@@ -73,10 +70,7 @@ class ServiceController {
73 } 70 }
74 71
75 // List all services a user has created 72 // List all services a user has created
76 async list({ 73 async list({ response, auth }) {
77 response,
78 auth,
79 }) {
80 try { 74 try {
81 await auth.getUser(); 75 await auth.getUser();
82 } catch (error) { 76 } catch (error) {
@@ -85,8 +79,11 @@ class ServiceController {
85 79
86 const services = (await auth.user.services().fetch()).rows; 80 const services = (await auth.user.services().fetch()).rows;
87 // Convert to array with all data Franz wants 81 // Convert to array with all data Franz wants
88 const servicesArray = services.map((service) => { 82 const servicesArray = services.map(service => {
89 const settings = typeof service.settings === 'string' ? JSON.parse(service.settings) : service.settings; 83 const settings =
84 typeof service.settings === 'string'
85 ? JSON.parse(service.settings)
86 : service.settings;
90 87
91 return { 88 return {
92 customRecipe: false, 89 customRecipe: false,
@@ -100,7 +97,9 @@ class ServiceController {
100 spellcheckerLanguage: '', 97 spellcheckerLanguage: '',
101 workspaces: [], 98 workspaces: [],
102 ...settings, 99 ...settings,
103 iconUrl: settings.iconId ? `${Env.get('APP_URL')}/v1/icon/${settings.iconId}` : null, 100 iconUrl: settings.iconId
101 ? `${Env.get('APP_URL')}/v1/icon/${settings.iconId}`
102 : null,
104 id: service.serviceId, 103 id: service.serviceId,
105 name: service.name, 104 name: service.name,
106 recipeId: service.recipeId, 105 recipeId: service.recipeId,
@@ -111,12 +110,7 @@ class ServiceController {
111 return response.send(servicesArray); 110 return response.send(servicesArray);
112 } 111 }
113 112
114 async edit({ 113 async edit({ request, response, auth, params }) {
115 request,
116 response,
117 auth,
118 params,
119 }) {
120 try { 114 try {
121 await auth.getUser(); 115 await auth.getUser();
122 } catch (error) { 116 } catch (error) {
@@ -129,18 +123,22 @@ class ServiceController {
129 types: ['image'], 123 types: ['image'],
130 size: '2mb', 124 size: '2mb',
131 }); 125 });
132 const { 126 const { id } = params;
133 id, 127 const service = (
134 } = params; 128 await Service.query()
135 const service = (await Service.query() 129 .where('serviceId', id)
136 .where('serviceId', id) 130 .where('userId', auth.user.id)
137 .where('userId', auth.user.id).fetch()).rows[0]; 131 .fetch()
138 const settings = typeof service.settings === 'string' ? JSON.parse(service.settings) : service.settings; 132 ).rows[0];
133 const settings =
134 typeof service.settings === 'string'
135 ? JSON.parse(service.settings)
136 : service.settings;
139 137
140 let iconId; 138 let iconId;
141 do { 139 do {
142 iconId = uuid() + uuid(); 140 iconId = uuid() + uuid();
143 // eslint-disable-next-line no-await-in-loop 141 // eslint-disable-next-line no-await-in-loop
144 } while (await fs.exists(path.join(Helpers.tmpPath('uploads'), iconId))); 142 } while (await fs.exists(path.join(Helpers.tmpPath('uploads'), iconId)));
145 iconId = `${iconId}.${icon.extname}`; 143 iconId = `${iconId}.${icon.extname}`;
146 144
@@ -157,17 +155,21 @@ class ServiceController {
157 ...settings, 155 ...settings,
158 ...{ 156 ...{
159 iconId, 157 iconId,
160 customIconVersion: settings && settings.customIconVersion ? settings.customIconVersion + 1 : 1, 158 customIconVersion:
159 settings && settings.customIconVersion
160 ? settings.customIconVersion + 1
161 : 1,
161 }, 162 },
162 }; 163 };
163 164
164 // Update data in database 165 // Update data in database
165 await (Service.query() 166 await Service.query()
166 .where('serviceId', id) 167 .where('serviceId', id)
167 .where('userId', auth.user.id)).update({ 168 .where('userId', auth.user.id)
168 name: service.name, 169 .update({
169 settings: JSON.stringify(newSettings), 170 name: service.name,
170 }); 171 settings: JSON.stringify(newSettings),
172 });
171 173
172 return response.send({ 174 return response.send({
173 data: { 175 data: {
@@ -182,32 +184,39 @@ class ServiceController {
182 } 184 }
183 // Update service info 185 // Update service info
184 const data = request.all(); 186 const data = request.all();
185 const { 187 const { id } = params;
186 id,
187 } = params;
188 188
189 // Get current settings from db 189 // Get current settings from db
190 const serviceData = (await Service.query() 190 const serviceData = (
191 .where('serviceId', id) 191 await Service.query()
192 .where('userId', auth.user.id).fetch()).rows[0]; 192 .where('serviceId', id)
193 .where('userId', auth.user.id)
194 .fetch()
195 ).rows[0];
193 196
194 const settings = { 197 const settings = {
195 ...typeof serviceData.settings === 'string' ? JSON.parse(serviceData.settings) : serviceData.settings, 198 ...(typeof serviceData.settings === 'string'
199 ? JSON.parse(serviceData.settings)
200 : serviceData.settings),
196 ...data, 201 ...data,
197 }; 202 };
198 203
199 // Update data in database 204 // Update data in database
200 await (Service.query() 205 await Service.query()
201 .where('serviceId', id) 206 .where('serviceId', id)
202 .where('userId', auth.user.id)).update({ 207 .where('userId', auth.user.id)
203 name: data.name, 208 .update({
204 settings: JSON.stringify(settings), 209 name: data.name,
205 }); 210 settings: JSON.stringify(settings),
211 });
206 212
207 // Get updated row 213 // Get updated row
208 const service = (await Service.query() 214 const service = (
209 .where('serviceId', id) 215 await Service.query()
210 .where('userId', auth.user.id).fetch()).rows[0]; 216 .where('serviceId', id)
217 .where('userId', auth.user.id)
218 .fetch()
219 ).rows[0];
211 220
212 return response.send({ 221 return response.send({
213 data: { 222 data: {
@@ -221,46 +230,42 @@ class ServiceController {
221 }); 230 });
222 } 231 }
223 232
224 async icon({ 233 async icon({ params, response }) {
225 params, 234 const { id } = params;
226 response,
227 }) {
228 const {
229 id,
230 } = params;
231 235
232 const iconPath = path.join(Helpers.tmpPath('uploads'), id); 236 const iconPath = path.join(Helpers.tmpPath('uploads'), id);
233 if (!await fs.exists(iconPath)) { 237 if (!(await fs.exists(iconPath))) {
234 return response.status(404).send({ 238 return response.status(404).send({
235 status: 'Icon doesn\'t exist', 239 status: "Icon doesn't exist",
236 }); 240 });
237 } 241 }
238 242
239 return response.download(iconPath); 243 return response.download(iconPath);
240 } 244 }
241 245
242 async reorder({ 246 async reorder({ request, response, auth }) {
243 request,
244 response,
245 auth,
246 }) {
247 const data = request.all(); 247 const data = request.all();
248 248
249 for (const service of Object.keys(data)) { 249 for (const service of Object.keys(data)) {
250 // Get current settings from db 250 // Get current settings from db
251 const serviceData = (await Service.query() // eslint-disable-line no-await-in-loop 251 const serviceData = (
252 .where('serviceId', service) 252 await Service.query() // eslint-disable-line no-await-in-loop
253 .where('userId', auth.user.id).fetch()).rows[0]; 253 .where('serviceId', service)
254 .where('userId', auth.user.id)
255 .fetch()
256 ).rows[0];
254 257
255 const settings = { 258 const settings = {
256 ...typeof serviceData.settings === 'string' ? JSON.parse(serviceData.settings) : serviceData.settings, 259 ...(typeof serviceData.settings === 'string'
260 ? JSON.parse(serviceData.settings)
261 : serviceData.settings),
257 order: data[service], 262 order: data[service],
258 }; 263 };
259 264
260 // Update data in database 265 // Update data in database
261 await (Service.query() // eslint-disable-line no-await-in-loop 266 await Service.query() // eslint-disable-line no-await-in-loop
262 .where('serviceId', service) 267 .where('serviceId', service)
263 .where('userId', auth.user.id)) 268 .where('userId', auth.user.id)
264 .update({ 269 .update({
265 settings: JSON.stringify(settings), 270 settings: JSON.stringify(settings),
266 }); 271 });
@@ -269,8 +274,11 @@ class ServiceController {
269 // Get new services 274 // Get new services
270 const services = (await auth.user.services().fetch()).rows; 275 const services = (await auth.user.services().fetch()).rows;
271 // Convert to array with all data Franz wants 276 // Convert to array with all data Franz wants
272 const servicesArray = services.map((service) => { 277 const servicesArray = services.map(service => {
273 const settings = typeof service.settings === 'string' ? JSON.parse(service.settings) : service.settings; 278 const settings =
279 typeof service.settings === 'string'
280 ? JSON.parse(service.settings)
281 : service.settings;
274 282
275 return { 283 return {
276 customRecipe: false, 284 customRecipe: false,
@@ -284,7 +292,9 @@ class ServiceController {
284 spellcheckerLanguage: '', 292 spellcheckerLanguage: '',
285 workspaces: [], 293 workspaces: [],
286 ...settings, 294 ...settings,
287 iconUrl: settings.iconId ? `${Env.get('APP_URL')}/v1/icon/${settings.iconId}` : null, 295 iconUrl: settings.iconId
296 ? `${Env.get('APP_URL')}/v1/icon/${settings.iconId}`
297 : null,
288 id: service.serviceId, 298 id: service.serviceId,
289 name: service.name, 299 name: service.name,
290 recipeId: service.recipeId, 300 recipeId: service.recipeId,
@@ -295,21 +305,16 @@ class ServiceController {
295 return response.send(servicesArray); 305 return response.send(servicesArray);
296 } 306 }
297 307
298 update({ 308 update({ response }) {
299 response,
300 }) {
301 return response.send([]); 309 return response.send([]);
302 } 310 }
303 311
304 async delete({ 312 async delete({ params, auth, response }) {
305 params,
306 auth,
307 response,
308 }) {
309 // Update data in database 313 // Update data in database
310 await (Service.query() 314 await Service.query()
311 .where('serviceId', params.id) 315 .where('serviceId', params.id)
312 .where('userId', auth.user.id)).delete(); 316 .where('userId', auth.user.id)
317 .delete();
313 318
314 return response.send({ 319 return response.send({
315 message: 'Sucessfully deleted service', 320 message: 'Sucessfully deleted service',
diff --git a/app/Controllers/Http/StaticController.js b/app/Controllers/Http/StaticController.js
index 114e369..4e604df 100644
--- a/app/Controllers/Http/StaticController.js
+++ b/app/Controllers/Http/StaticController.js
@@ -1,4 +1,3 @@
1
2/** 1/**
3 * Controller for routes with static responses 2 * Controller for routes with static responses
4 */ 3 */
diff --git a/app/Controllers/Http/UserController.js b/app/Controllers/Http/UserController.js
index 0d768a9..99336cb 100644
--- a/app/Controllers/Http/UserController.js
+++ b/app/Controllers/Http/UserController.js
@@ -1,44 +1,41 @@
1const User = use('App/Models/User'); 1const User = use('App/Models/User');
2const Service = use('App/Models/Service'); 2const Service = use('App/Models/Service');
3const Workspace = use('App/Models/Workspace'); 3const Workspace = use('App/Models/Workspace');
4const { 4const { validateAll } = use('Validator');
5 validateAll,
6} = use('Validator');
7const Env = use('Env'); 5const Env = use('Env');
8 6
9const atob = require('atob'); 7const atob = require('atob');
10const btoa = require('btoa'); 8const btoa = require('btoa');
11const fetch = require('node-fetch'); 9const fetch = require('node-fetch');
12const uuid = require('uuid/v4'); 10const { v4: uuid } = require('uuid');
13const crypto = require('crypto'); 11const crypto = require('crypto');
14 12
15const franzRequest = (route, method, auth) => new Promise((resolve, reject) => { 13const franzRequest = (route, method, auth) =>
16 const base = 'https://api.franzinfra.com/v1/'; 14 new Promise((resolve, reject) => {
17 const user = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Ferdi/5.3.0-beta.1 Chrome/69.0.3497.128 Electron/4.2.4 Safari/537.36'; 15 const base = 'https://api.franzinfra.com/v1/';
16 const user =
17 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Ferdi/5.3.0-beta.1 Chrome/69.0.3497.128 Electron/4.2.4 Safari/537.36';
18 18
19 try { 19 try {
20 fetch(base + route, { 20 fetch(base + route, {
21 method, 21 method,
22 headers: { 22 headers: {
23 Authorization: `Bearer ${auth}`, 23 Authorization: `Bearer ${auth}`,
24 'User-Agent': user, 24 'User-Agent': user,
25 }, 25 },
26 }) 26 })
27 .then((data) => data.json()) 27 .then(data => data.json())
28 .then((json) => resolve(json)); 28 .then(json => resolve(json));
29 } catch (e) { 29 } catch (e) {
30 reject(); 30 reject();
31 } 31 }
32}); 32 });
33 33
34class UserController { 34class UserController {
35 // Register a new user 35 // Register a new user
36 async signup({ 36 async signup({ request, response, auth }) {
37 request, 37 if (Env.get('IS_REGISTRATION_ENABLED') == 'false') {
38 response, 38 // eslint-disable-line eqeqeq
39 auth,
40 }) {
41 if (Env.get('IS_REGISTRATION_ENABLED') == 'false') { // eslint-disable-line eqeqeq
42 return response.status(401).send({ 39 return response.status(401).send({
43 message: 'Registration is disabled on this server', 40 message: 'Registration is disabled on this server',
44 status: 401, 41 status: 401,
@@ -89,11 +86,7 @@ class UserController {
89 } 86 }
90 87
91 // Login using an existing user 88 // Login using an existing user
92 async login({ 89 async login({ request, response, auth }) {
93 request,
94 response,
95 auth,
96 }) {
97 if (!request.header('Authorization')) { 90 if (!request.header('Authorization')) {
98 return response.status(401).send({ 91 return response.status(401).send({
99 message: 'Please provide authorization', 92 message: 'Please provide authorization',
@@ -102,10 +95,12 @@ class UserController {
102 } 95 }
103 96
104 // Get auth data from auth token 97 // Get auth data from auth token
105 const authHeader = atob(request.header('Authorization').replace('Basic ', '')).split(':'); 98 const authHeader = atob(
99 request.header('Authorization').replace('Basic ', ''),
100 ).split(':');
106 101
107 // Check if user with email exists 102 // Check if user with email exists
108 const user = (await User.query().where('email', authHeader[0]).first()); 103 const user = await User.query().where('email', authHeader[0]).first();
109 if (!user || !user.email) { 104 if (!user || !user.email) {
110 return response.status(401).send({ 105 return response.status(401).send({
111 message: 'User credentials not valid (Invalid mail)', 106 message: 'User credentials not valid (Invalid mail)',
@@ -133,17 +128,17 @@ class UserController {
133 } 128 }
134 129
135 // Return information about the current user 130 // Return information about the current user
136 async me({ 131 async me({ response, auth }) {
137 response,
138 auth,
139 }) {
140 try { 132 try {
141 await auth.getUser(); 133 await auth.getUser();
142 } catch (error) { 134 } catch (error) {
143 response.send('Missing or invalid api token'); 135 response.send('Missing or invalid api token');
144 } 136 }
145 137
146 const settings = typeof auth.user.settings === 'string' ? JSON.parse(auth.user.settings) : auth.user.settings; 138 const settings =
139 typeof auth.user.settings === 'string'
140 ? JSON.parse(auth.user.settings)
141 : auth.user.settings;
147 142
148 return response.send({ 143 return response.send({
149 accountType: 'individual', 144 accountType: 'individual',
@@ -158,15 +153,11 @@ class UserController {
158 isSubscriptionOwner: true, 153 isSubscriptionOwner: true,
159 lastname: auth.user.lastname, 154 lastname: auth.user.lastname,
160 locale: 'en-US', 155 locale: 'en-US',
161 ...settings || {}, 156 ...(settings || {}),
162 }); 157 });
163 } 158 }
164 159
165 async updateMe({ 160 async updateMe({ request, response, auth }) {
166 request,
167 response,
168 auth,
169 }) {
170 let settings = auth.user.settings || {}; 161 let settings = auth.user.settings || {};
171 if (typeof settings === 'string') { 162 if (typeof settings === 'string') {
172 settings = JSON.parse(settings); 163 settings = JSON.parse(settings);
@@ -195,21 +186,15 @@ class UserController {
195 isSubscriptionOwner: true, 186 isSubscriptionOwner: true,
196 lastname: auth.user.lastname, 187 lastname: auth.user.lastname,
197 locale: 'en-US', 188 locale: 'en-US',
198 ...newSettings || {}, 189 ...(newSettings || {}),
199 }, 190 },
200 status: [ 191 status: ['data-updated'],
201 'data-updated',
202 ],
203 }); 192 });
204 } 193 }
205 194
206 195 async import({ request, response, view }) {
207 async import({ 196 if (Env.get('IS_REGISTRATION_ENABLED') == 'false') {
208 request, 197 // eslint-disable-line eqeqeq
209 response,
210 view,
211 }) {
212 if (Env.get('IS_REGISTRATION_ENABLED') == 'false') { // eslint-disable-line eqeqeq
213 return response.status(401).send({ 198 return response.status(401).send({
214 message: 'Registration is disabled on this server', 199 message: 'Registration is disabled on this server',
215 status: 401, 200 status: 401,
@@ -222,7 +207,8 @@ class UserController {
222 password: 'required', 207 password: 'required',
223 }); 208 });
224 if (validation.fails()) { 209 if (validation.fails()) {
225 let errorMessage = 'There was an error while trying to import your account:\n'; 210 let errorMessage =
211 'There was an error while trying to import your account:\n';
226 for (const message of validation.messages()) { 212 for (const message of validation.messages()) {
227 if (message.validation === 'required') { 213 if (message.validation === 'required') {
228 errorMessage += `- Please make sure to supply your ${message.field}\n`; 214 errorMessage += `- Please make sure to supply your ${message.field}\n`;
@@ -238,14 +224,15 @@ class UserController {
238 }); 224 });
239 } 225 }
240 226
241 const { 227 const { email, password } = request.all();
242 email,
243 password,
244 } = request.all();
245 228
246 const hashedPassword = crypto.createHash('sha256').update(password).digest('base64'); 229 const hashedPassword = crypto
230 .createHash('sha256')
231 .update(password)
232 .digest('base64');
247 233
248 if (Env.get('CONNECT_WITH_FRANZ') == 'false') { // eslint-disable-line eqeqeq 234 if (Env.get('CONNECT_WITH_FRANZ') == 'false') {
235 // eslint-disable-line eqeqeq
249 await User.create({ 236 await User.create({
250 email, 237 email,
251 password: hashedPassword, 238 password: hashedPassword,
@@ -253,11 +240,14 @@ class UserController {
253 lastname: 'Franz', 240 lastname: 'Franz',
254 }); 241 });
255 242
256 return response.send('Your account has been created but due to this server\'s configuration, we could not import your Franz account data.\n\nIf you are the server owner, please set CONNECT_WITH_FRANZ to true to enable account imports.'); 243 return response.send(
244 "Your account has been created but due to this server's configuration, we could not import your Franz account data.\n\nIf you are the server owner, please set CONNECT_WITH_FRANZ to true to enable account imports.",
245 );
257 } 246 }
258 247
259 const base = 'https://api.franzinfra.com/v1/'; 248 const base = 'https://api.franzinfra.com/v1/';
260 const userAgent = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Ferdi/5.3.0-beta.1 Chrome/69.0.3497.128 Electron/4.2.4 Safari/537.36'; 249 const userAgent =
250 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Ferdi/5.3.0-beta.1 Chrome/69.0.3497.128 Electron/4.2.4 Safari/537.36';
261 251
262 // Try to get an authentication token 252 // Try to get an authentication token
263 let token; 253 let token;
@@ -281,7 +271,8 @@ class UserController {
281 const content = await rawResponse.json(); 271 const content = await rawResponse.json();
282 272
283 if (!content.message || content.message !== 'Successfully logged in') { 273 if (!content.message || content.message !== 'Successfully logged in') {
284 const errorMessage = 'Could not login into Franz with your supplied credentials. Please check and try again'; 274 const errorMessage =
275 'Could not login into Franz with your supplied credentials. Please check and try again';
285 return response.status(401).send(errorMessage); 276 return response.status(401).send(errorMessage);
286 } 277 }
287 278
@@ -302,7 +293,8 @@ class UserController {
302 return response.status(401).send(errorMessage); 293 return response.status(401).send(errorMessage);
303 } 294 }
304 if (!userInf) { 295 if (!userInf) {
305 const errorMessage = 'Could not get your user info from Franz. Please check your credentials or try again later'; 296 const errorMessage =
297 'Could not get your user info from Franz. Please check your credentials or try again later';
306 return response.status(401).send(errorMessage); 298 return response.status(401).send(errorMessage);
307 } 299 }
308 300
@@ -331,9 +323,13 @@ class UserController {
331 let serviceId; 323 let serviceId;
332 do { 324 do {
333 serviceId = uuid(); 325 serviceId = uuid();
334 } while ((await Service.query().where('serviceId', serviceId).fetch()).rows.length > 0); // eslint-disable-line no-await-in-loop 326 } while (
327 (await Service.query().where('serviceId', serviceId).fetch()).rows
328 .length > 0
329 ); // eslint-disable-line no-await-in-loop
335 330
336 await Service.create({ // eslint-disable-line no-await-in-loop 331 await Service.create({
332 // eslint-disable-line no-await-in-loop
337 userId: user.id, 333 userId: user.id,
338 serviceId, 334 serviceId,
339 name: service.name, 335 name: service.name,
@@ -356,11 +352,17 @@ class UserController {
356 let workspaceId; 352 let workspaceId;
357 do { 353 do {
358 workspaceId = uuid(); 354 workspaceId = uuid();
359 } while ((await Workspace.query().where('workspaceId', workspaceId).fetch()).rows.length > 0); // eslint-disable-line no-await-in-loop 355 } while (
356 (await Workspace.query().where('workspaceId', workspaceId).fetch())
357 .rows.length > 0
358 ); // eslint-disable-line no-await-in-loop
360 359
361 const services = workspace.services.map((service) => serviceIdTranslation[service]); 360 const services = workspace.services.map(
361 service => serviceIdTranslation[service],
362 );
362 363
363 await Workspace.create({ // eslint-disable-line no-await-in-loop 364 await Workspace.create({
365 // eslint-disable-line no-await-in-loop
364 userId: user.id, 366 userId: user.id,
365 workspaceId, 367 workspaceId,
366 name: workspace.name, 368 name: workspace.name,
@@ -374,7 +376,9 @@ class UserController {
374 return response.status(401).send(errorMessage); 376 return response.status(401).send(errorMessage);
375 } 377 }
376 378
377 return response.send('Your account has been imported. You can now use your Franz account in Ferdi.'); 379 return response.send(
380 'Your account has been imported. You can now use your Franz account in Ferdi.',
381 );
378 } 382 }
379} 383}
380 384
diff --git a/app/Controllers/Http/WorkspaceController.js b/app/Controllers/Http/WorkspaceController.js
index 496912e..3734345 100644
--- a/app/Controllers/Http/WorkspaceController.js
+++ b/app/Controllers/Http/WorkspaceController.js
@@ -1,18 +1,11 @@
1
2const Workspace = use('App/Models/Workspace'); 1const Workspace = use('App/Models/Workspace');
3const { 2const { validateAll } = use('Validator');
4 validateAll,
5} = use('Validator');
6 3
7const uuid = require('uuid/v4'); 4const { v4: uuid } = require('uuid');
8 5
9class WorkspaceController { 6class WorkspaceController {
10 // Create a new workspace for user 7 // Create a new workspace for user
11 async create({ 8 async create({ request, response, auth }) {
12 request,
13 response,
14 auth,
15 }) {
16 try { 9 try {
17 await auth.getUser(); 10 await auth.getUser();
18 } catch (error) { 11 } catch (error) {
@@ -37,7 +30,10 @@ class WorkspaceController {
37 let workspaceId; 30 let workspaceId;
38 do { 31 do {
39 workspaceId = uuid(); 32 workspaceId = uuid();
40 } while ((await Workspace.query().where('workspaceId', workspaceId).fetch()).rows.length > 0); // eslint-disable-line no-await-in-loop 33 } while (
34 (await Workspace.query().where('workspaceId', workspaceId).fetch()).rows
35 .length > 0
36 ); // eslint-disable-line no-await-in-loop
41 37
42 const order = (await auth.user.workspaces().fetch()).rows.length; 38 const order = (await auth.user.workspaces().fetch()).rows.length;
43 39
@@ -59,12 +55,7 @@ class WorkspaceController {
59 }); 55 });
60 } 56 }
61 57
62 async edit({ 58 async edit({ request, response, auth, params }) {
63 request,
64 response,
65 auth,
66 params,
67 }) {
68 try { 59 try {
69 await auth.getUser(); 60 await auth.getUser();
70 } catch (error) { 61 } catch (error) {
@@ -85,22 +76,24 @@ class WorkspaceController {
85 } 76 }
86 77
87 const data = request.all(); 78 const data = request.all();
88 const { 79 const { id } = params;
89 id,
90 } = params;
91 80
92 // Update data in database 81 // Update data in database
93 await (Workspace.query() 82 await Workspace.query()
94 .where('workspaceId', id) 83 .where('workspaceId', id)
95 .where('userId', auth.user.id)).update({ 84 .where('userId', auth.user.id)
96 name: data.name, 85 .update({
97 services: JSON.stringify(data.services), 86 name: data.name,
98 }); 87 services: JSON.stringify(data.services),
88 });
99 89
100 // Get updated row 90 // Get updated row
101 const workspace = (await Workspace.query() 91 const workspace = (
102 .where('workspaceId', id) 92 await Workspace.query()
103 .where('userId', auth.user.id).fetch()).rows[0]; 93 .where('workspaceId', id)
94 .where('userId', auth.user.id)
95 .fetch()
96 ).rows[0];
104 97
105 return response.send({ 98 return response.send({
106 id: workspace.workspaceId, 99 id: workspace.workspaceId,
@@ -136,14 +129,13 @@ class WorkspaceController {
136 }); 129 });
137 } 130 }
138 131
139 const { 132 const { id } = params;
140 id,
141 } = params;
142 133
143 // Update data in database 134 // Update data in database
144 await (Workspace.query() 135 await Workspace.query()
145 .where('workspaceId', id) 136 .where('workspaceId', id)
146 .where('userId', auth.user.id)).delete(); 137 .where('userId', auth.user.id)
138 .delete();
147 139
148 return response.send({ 140 return response.send({
149 message: 'Successfully deleted workspace', 141 message: 'Successfully deleted workspace',
@@ -151,10 +143,7 @@ class WorkspaceController {
151 } 143 }
152 144
153 // List all workspaces a user has created 145 // List all workspaces a user has created
154 async list({ 146 async list({ response, auth }) {
155 response,
156 auth,
157 }) {
158 try { 147 try {
159 await auth.getUser(); 148 await auth.getUser();
160 } catch (error) { 149 } catch (error) {
@@ -165,16 +154,18 @@ class WorkspaceController {
165 // Convert to array with all data Franz wants 154 // Convert to array with all data Franz wants
166 let workspacesArray = []; 155 let workspacesArray = [];
167 if (workspaces) { 156 if (workspaces) {
168 workspacesArray = workspaces.map((workspace) => ({ 157 workspacesArray = workspaces.map(workspace => ({
169 id: workspace.workspaceId, 158 id: workspace.workspaceId,
170 name: workspace.name, 159 name: workspace.name,
171 order: workspace.order, 160 order: workspace.order,
172 services: typeof workspace.services === 'string' ? JSON.parse(workspace.services) : workspace.services, 161 services:
162 typeof workspace.services === 'string'
163 ? JSON.parse(workspace.services)
164 : workspace.services,
173 userId: auth.user.id, 165 userId: auth.user.id,
174 })); 166 }));
175 } 167 }
176 168
177
178 return response.send(workspacesArray); 169 return response.send(workspacesArray);
179 } 170 }
180} 171}
diff --git a/app/Exceptions/Handler.js b/app/Exceptions/Handler.js
index 14b840e..43c3ef1 100644
--- a/app/Exceptions/Handler.js
+++ b/app/Exceptions/Handler.js
@@ -1,4 +1,3 @@
1
2const BaseExceptionHandler = use('BaseExceptionHandler'); 1const BaseExceptionHandler = use('BaseExceptionHandler');
3const Sentry = require('@sentry/node'); 2const Sentry = require('@sentry/node');
4 3
diff --git a/app/Middleware/ConvertEmptyStringsToNull.js b/app/Middleware/ConvertEmptyStringsToNull.js
index 556f223..af6379a 100644
--- a/app/Middleware/ConvertEmptyStringsToNull.js
+++ b/app/Middleware/ConvertEmptyStringsToNull.js
@@ -1,4 +1,3 @@
1
2class ConvertEmptyStringsToNull { 1class ConvertEmptyStringsToNull {
3 async handle({ request }, next) { 2 async handle({ request }, next) {
4 if (Object.keys(request.body).length) { 3 if (Object.keys(request.body).length) {
diff --git a/app/Models/Recipe.js b/app/Models/Recipe.js
index da3618b..bd97411 100644
--- a/app/Models/Recipe.js
+++ b/app/Models/Recipe.js
@@ -1,4 +1,3 @@
1
2/** @type {typeof import('@adonisjs/lucid/src/Lucid/Model')} */ 1/** @type {typeof import('@adonisjs/lucid/src/Lucid/Model')} */
3const Model = use('Model'); 2const Model = use('Model');
4 3
diff --git a/app/Models/Service.js b/app/Models/Service.js
index 0a13ec1..cf3e6f4 100644
--- a/app/Models/Service.js
+++ b/app/Models/Service.js
@@ -1,4 +1,3 @@
1
2/** @type {typeof import('@adonisjs/lucid/src/Lucid/Model')} */ 1/** @type {typeof import('@adonisjs/lucid/src/Lucid/Model')} */
3const Model = use('Model'); 2const Model = use('Model');
4 3
diff --git a/app/Models/Token.js b/app/Models/Token.js
index 4a6c286..7965a7a 100644
--- a/app/Models/Token.js
+++ b/app/Models/Token.js
@@ -1,4 +1,3 @@
1
2/** @type {typeof import('@adonisjs/lucid/src/Lucid/Model')} */ 1/** @type {typeof import('@adonisjs/lucid/src/Lucid/Model')} */
3const Model = use('Model'); 2const Model = use('Model');
4 3
diff --git a/app/Models/Traits/NoTimestamp.js b/app/Models/Traits/NoTimestamp.js
index c647428..914f542 100644
--- a/app/Models/Traits/NoTimestamp.js
+++ b/app/Models/Traits/NoTimestamp.js
@@ -1,4 +1,3 @@
1
2class NoTimestamp { 1class NoTimestamp {
3 register(Model) { 2 register(Model) {
4 Object.defineProperties(Model, { 3 Object.defineProperties(Model, {
diff --git a/app/Models/User.js b/app/Models/User.js
index 3a40347..4472017 100644
--- a/app/Models/User.js
+++ b/app/Models/User.js
@@ -1,4 +1,3 @@
1
2/** @type {typeof import('@adonisjs/lucid/src/Lucid/Model')} */ 1/** @type {typeof import('@adonisjs/lucid/src/Lucid/Model')} */
3const Model = use('Model'); 2const Model = use('Model');
4 3
diff --git a/app/Models/Workspace.js b/app/Models/Workspace.js
index b155e09..e3a3285 100644
--- a/app/Models/Workspace.js
+++ b/app/Models/Workspace.js
@@ -1,4 +1,3 @@
1
2/** @type {typeof import('@adonisjs/lucid/src/Lucid/Model')} */ 1/** @type {typeof import('@adonisjs/lucid/src/Lucid/Model')} */
3const Model = use('Model'); 2const Model = use('Model');
4 3