From 21ba7b89c0b185ef1e6878ebd02df21af8c51ed6 Mon Sep 17 00:00:00 2001 From: Michal Kostewicz Date: Sat, 6 Feb 2021 19:55:27 +0100 Subject: Add lastname column to User DB table and update API logic to save,return and update this data. --- app/Controllers/Http/DashboardController.js | 5 +++++ app/Controllers/Http/UserController.js | 19 ++++++++++++------- 2 files changed, 17 insertions(+), 7 deletions(-) (limited to 'app/Controllers') diff --git a/app/Controllers/Http/DashboardController.js b/app/Controllers/Http/DashboardController.js index 3de4816..2f06961 100644 --- a/app/Controllers/Http/DashboardController.js +++ b/app/Controllers/Http/DashboardController.js @@ -122,6 +122,7 @@ class DashboardController { return view.render('dashboard.account', { username: auth.user.username, email: auth.user.email, + lastname: auth.user.lastname }); } @@ -135,6 +136,7 @@ class DashboardController { let validation = await validateAll(request.all(), { username: 'required', email: 'required', + lastname: 'required' }); if (validation.fails()) { session.withErrors(validation.messages()).flashExcept(['password']); @@ -168,6 +170,7 @@ class DashboardController { // Update user account const { user } = auth; user.username = request.input('username'); + user.lastname = request.input('lastname'); user.email = request.input('email'); if (request.input('password')) { const hashedPassword = crypto.createHash('sha256').update(request.input('password')).digest('base64'); @@ -192,6 +195,7 @@ class DashboardController { return view.render('dashboard.data', { username: general.username, + lastname: general.lastname, mail: general.email, created: general.created_at, updated: general.updated_at, @@ -211,6 +215,7 @@ class DashboardController { const exportData = { username: general.username, + lastname: general.lastname, mail: general.email, services, workspaces, diff --git a/app/Controllers/Http/UserController.js b/app/Controllers/Http/UserController.js index e367d99..dc92b21 100644 --- a/app/Controllers/Http/UserController.js +++ b/app/Controllers/Http/UserController.js @@ -48,9 +48,11 @@ class UserController { // Validate user input const validation = await validateAll(request.all(), { firstname: 'required', + lastname: 'required', email: 'required|email|unique:users,email', password: 'required', }); + if (validation.fails()) { return response.status(401).send({ message: 'Invalid POST arguments', @@ -59,7 +61,7 @@ class UserController { }); } - const data = request.only(['firstname', 'email', 'password']); + const data = request.only(['firstname', 'lastname', 'email', 'password']); // Create user in DB let user; @@ -68,6 +70,7 @@ class UserController { email: data.email, password: data.password, username: data.firstname, + lastname: data.lastname, }); } catch (e) { return response.status(401).send({ @@ -149,13 +152,13 @@ class UserController { email: auth.user.email, emailValidated: true, features: {}, - firstname: 'Franz', + firstname: auth.user.username, id: '82c1cf9d-ab58-4da2-b55e-aaa41d2142d8', isPremium: true, isSubscriptionOwner: true, - lastname: 'Franz', + lastname: auth.user.lastname, locale: 'en-US', - ...settings || {}, + ...settings || {}, }); } @@ -185,13 +188,13 @@ class UserController { email: auth.user.email, emailValidated: true, features: {}, - firstname: 'Franz', + firstname: auth.user.username, id: '82c1cf9d-ab58-4da2-b55e-aaa41d2142d8', isPremium: true, isSubscriptionOwner: true, - lastname: 'Franz', + lastname: auth.user.lastname, locale: 'en-US', - ...newSettings || {}, + ...newSettings || {}, }, status: [ 'data-updated', @@ -246,6 +249,7 @@ class UserController { email, password: hashedPassword, username: 'Franz', + lastname: 'Franz' }); 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.'); @@ -301,6 +305,7 @@ class UserController { email: userInf.email, password: hashedPassword, username: userInf.firstname, + lastname: userInf.lastname }); } catch (e) { const errorMessage = `Could not create your user in our system.\nError: ${e}`; -- cgit v1.2.3-70-g09d2 From 07be43b09308c609fe3d3c9efa2c7a2cab34173f Mon Sep 17 00:00:00 2001 From: Michal Kostewicz Date: Thu, 11 Feb 2021 22:03:59 +0100 Subject: Fix import from Franz by adding additional headers and body to login request --- app/Controllers/Http/UserController.js | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'app/Controllers') diff --git a/app/Controllers/Http/UserController.js b/app/Controllers/Http/UserController.js index e367d99..09da261 100644 --- a/app/Controllers/Http/UserController.js +++ b/app/Controllers/Http/UserController.js @@ -258,12 +258,19 @@ class UserController { let token; try { const basicToken = btoa(`${email}:${hashedPassword}`); + const loginBody = { + isZendeskLogin: false + }; const rawResponse = await fetch(`${base}auth/login`, { method: 'POST', + body: JSON.stringify(loginBody), headers: { Authorization: `Basic ${basicToken}`, 'User-Agent': userAgent, + 'Content-Type': 'application/json', + 'accept': '*/*', + 'x-franz-source': 'Web' }, }); const content = await rawResponse.json(); -- cgit v1.2.3-70-g09d2 From 9a93be2752ec81ed1f634adbb63aef2d1c5272de Mon Sep 17 00:00:00 2001 From: Vijay A Date: Wed, 19 May 2021 11:28:09 +0530 Subject: Applied linter fixes. --- .eslintignore | 1 + .eslintrc.js | 8 ++++++- app/Controllers/Http/DashboardController.js | 11 ++++----- app/Controllers/Http/ServiceController.js | 1 + app/Controllers/Http/StaticController.js | 9 ++++---- app/Controllers/Http/UserController.js | 11 ++++----- app/Controllers/Http/WorkspaceController.js | 3 ++- app/Middleware/HandleDoubleSlash.js | 6 ++--- app/Models/Token.js | 2 +- config/mail.js | 20 ++++++++--------- config/persona.js | 8 ++----- .../1612629845398_users_update_schema.js | 26 ++++++++++------------ start/events.js | 14 +++++++----- start/routes.js | 25 ++++++++++----------- 14 files changed, 75 insertions(+), 70 deletions(-) create mode 100644 .eslintignore (limited to 'app/Controllers') diff --git a/.eslintignore b/.eslintignore new file mode 100644 index 0000000..49e45f9 --- /dev/null +++ b/.eslintignore @@ -0,0 +1 @@ +officialrecipes/ diff --git a/.eslintrc.js b/.eslintrc.js index d02f489..066d415 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -10,7 +10,12 @@ module.exports = { globals: { Atomics: 'readonly', SharedArrayBuffer: 'readonly', - use: 'readonly' + use: 'readonly', + window: 'readonly', + document: 'readonly', + ENV: 'readonly', + session: 'readonly', + response: 'readonly', }, parserOptions: { ecmaVersion: 2018, @@ -18,5 +23,6 @@ module.exports = { rules: { "class-methods-use-this": 'off', "no-restricted-syntax": 'off', + "max-len": 0, }, }; diff --git a/app/Controllers/Http/DashboardController.js b/app/Controllers/Http/DashboardController.js index 2f06961..a588c75 100644 --- a/app/Controllers/Http/DashboardController.js +++ b/app/Controllers/Http/DashboardController.js @@ -63,7 +63,8 @@ class DashboardController { } try { await Persona.forgotPassword(request.input('mail')); - } catch(e) {} + // eslint-disable-next-line no-empty + } catch (e) {} return view.render('others.message', { heading: 'Reset password', @@ -91,11 +92,11 @@ class DashboardController { const payload = { password: crypto.createHash('sha256').update(request.input('password')).digest('base64'), password_confirmation: crypto.createHash('sha256').update(request.input('password_confirmation')).digest('base64'), - } + }; try { await Persona.updatePasswordByToken(request.input('token'), payload); - } catch(e) { + } catch (e) { return view.render('others.message', { heading: 'Cannot reset your password', text: 'Please make sure you are using a valid and recent link to reset your password and that your passwords entered match.', @@ -122,7 +123,7 @@ class DashboardController { return view.render('dashboard.account', { username: auth.user.username, email: auth.user.email, - lastname: auth.user.lastname + lastname: auth.user.lastname, }); } @@ -136,7 +137,7 @@ class DashboardController { let validation = await validateAll(request.all(), { username: 'required', email: 'required', - lastname: 'required' + lastname: 'required', }); if (validation.fails()) { session.withErrors(validation.messages()).flashExcept(['password']); diff --git a/app/Controllers/Http/ServiceController.js b/app/Controllers/Http/ServiceController.js index a1d26cb..05d093b 100644 --- a/app/Controllers/Http/ServiceController.js +++ b/app/Controllers/Http/ServiceController.js @@ -140,6 +140,7 @@ class ServiceController { let iconId; do { iconId = uuid() + uuid(); + // eslint-disable-next-line no-await-in-loop } while (await fs.exists(path.join(Helpers.tmpPath('uploads'), iconId))); await icon.move(Helpers.tmpPath('uploads'), { diff --git a/app/Controllers/Http/StaticController.js b/app/Controllers/Http/StaticController.js index d1a1179..114e369 100644 --- a/app/Controllers/Http/StaticController.js +++ b/app/Controllers/Http/StaticController.js @@ -34,7 +34,6 @@ class StaticController { defaultTrialPlan: 'franz-pro-yearly', subscribeURL: 'https://getferdi.com', planSelectionURL: 'https://getferdi.com', - isMagicBarEnabled: true, hasInlineCheckout: true, isPlanSelectionEnabled: false, isTrialStatusBarEnabled: false, @@ -101,9 +100,11 @@ class StaticController { }) { return response.send( fs - .readJsonSync(path.join( - Helpers.appRoot(), "officialrecipes", "recipes", "all.json")) - .filter((recipe) => recipe.featured)); + .readJsonSync(path.join( + Helpers.appRoot(), 'officialrecipes', 'recipes', 'all.json', + )) + .filter((recipe) => recipe.featured), + ); } // Show announcements diff --git a/app/Controllers/Http/UserController.js b/app/Controllers/Http/UserController.js index e19e15e..0d768a9 100644 --- a/app/Controllers/Http/UserController.js +++ b/app/Controllers/Http/UserController.js @@ -177,6 +177,7 @@ class UserController { ...request.all(), }; + // eslint-disable-next-line no-param-reassign auth.user.settings = JSON.stringify(newSettings); await auth.user.save(); @@ -249,7 +250,7 @@ class UserController { email, password: hashedPassword, username: 'Franz', - lastname: 'Franz' + lastname: 'Franz', }); 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.'); @@ -263,7 +264,7 @@ class UserController { try { const basicToken = btoa(`${email}:${hashedPassword}`); const loginBody = { - isZendeskLogin: false + isZendeskLogin: false, }; const rawResponse = await fetch(`${base}auth/login`, { @@ -273,8 +274,8 @@ class UserController { Authorization: `Basic ${basicToken}`, 'User-Agent': userAgent, 'Content-Type': 'application/json', - 'accept': '*/*', - 'x-franz-source': 'Web' + accept: '*/*', + 'x-franz-source': 'Web', }, }); const content = await rawResponse.json(); @@ -312,7 +313,7 @@ class UserController { email: userInf.email, password: hashedPassword, username: userInf.firstname, - lastname: userInf.lastname + lastname: userInf.lastname, }); } catch (e) { const errorMessage = `Could not create your user in our system.\nError: ${e}`; diff --git a/app/Controllers/Http/WorkspaceController.js b/app/Controllers/Http/WorkspaceController.js index cbb6873..496912e 100644 --- a/app/Controllers/Http/WorkspaceController.js +++ b/app/Controllers/Http/WorkspaceController.js @@ -112,7 +112,8 @@ class WorkspaceController { } async delete({ - request, + // eslint-disable-next-line no-unused-vars + _request, response, auth, params, diff --git a/app/Middleware/HandleDoubleSlash.js b/app/Middleware/HandleDoubleSlash.js index 456b774..c4bc053 100644 --- a/app/Middleware/HandleDoubleSlash.js +++ b/app/Middleware/HandleDoubleSlash.js @@ -1,4 +1,3 @@ -'use strict' /** @typedef {import('@adonisjs/framework/src/Request')} Request */ /** @typedef {import('@adonisjs/framework/src/Response')} Response */ /** @typedef {import('@adonisjs/framework/src/View')} View */ @@ -9,7 +8,8 @@ class HandleDoubleSlash { * @param {Request} ctx.request * @param {Function} next */ - async handle ({ request, response }, next) { + // eslint-disable-next-line consistent-return + async handle({ request, response }, next) { // Redirect requests that contain duplicate slashes to the right path if (request.url().includes('//')) { return response.redirect( @@ -21,4 +21,4 @@ class HandleDoubleSlash { } } -module.exports = HandleDoubleSlash +module.exports = HandleDoubleSlash; diff --git a/app/Models/Token.js b/app/Models/Token.js index 50bcf1d..4a6c286 100644 --- a/app/Models/Token.js +++ b/app/Models/Token.js @@ -4,7 +4,7 @@ const Model = use('Model'); class Token extends Model { user() { - return this.belongsTo('App/Models/User') + return this.belongsTo('App/Models/User'); } } diff --git a/config/mail.js b/config/mail.js index b876f19..1f11a8e 100644 --- a/config/mail.js +++ b/config/mail.js @@ -1,6 +1,4 @@ -'use strict' - -const Env = use('Env') +const Env = use('Env'); module.exports = { /* @@ -30,15 +28,15 @@ module.exports = { name: Env.get('EXTERNAL_DOMAIN'), port: Env.get('SMTP_PORT', 2525), host: Env.get('SMTP_HOST'), - secure: JSON.parse(Env.get("MAIL_SSL", Env.get('SSL', false))), + secure: JSON.parse(Env.get('MAIL_SSL', Env.get('SSL', false))), authMethod: 'LOGIN', auth: { user: Env.get('MAIL_USERNAME'), - pass: Env.get('MAIL_PASSWORD') + pass: Env.get('MAIL_PASSWORD'), }, maxConnections: 5, maxMessages: 100, - rateLimit: 10 + rateLimit: 10, }, /* @@ -60,7 +58,7 @@ module.exports = { sparkpost: { driver: 'sparkpost', apiKey: Env.get('SPARKPOST_API_KEY'), - extras: {} + extras: {}, }, /* @@ -85,7 +83,7 @@ module.exports = { domain: Env.get('MAILGUN_DOMAIN'), region: Env.get('MAILGUN_API_REGION'), apiKey: Env.get('MAILGUN_API_KEY'), - extras: {} + extras: {}, }, /* @@ -100,6 +98,6 @@ module.exports = { | */ ethereal: { - driver: 'ethereal' - } -} + driver: 'ethereal', + }, +}; diff --git a/config/persona.js b/config/persona.js index 71fbc3f..c259a06 100644 --- a/config/persona.js +++ b/config/persona.js @@ -1,5 +1,3 @@ -'use strict' - /* |-------------------------------------------------------------------------- | Persona @@ -92,7 +90,5 @@ module.exports = { | An object of validation messages to be used when validation fails. | */ - validationMessages: () => { - return {} - } -} + validationMessages: () => ({}), +}; diff --git a/database/migrations/1612629845398_users_update_schema.js b/database/migrations/1612629845398_users_update_schema.js index d07f66d..10b82aa 100644 --- a/database/migrations/1612629845398_users_update_schema.js +++ b/database/migrations/1612629845398_users_update_schema.js @@ -1,20 +1,18 @@ -'use strict' - /** @type {import('@adonisjs/lucid/src/Schema')} */ -const Schema = use('Schema') +const Schema = use('Schema'); class UsersUpdateSchema extends Schema { - up() { - this.table('users', (table) => { - table.string('lastname', 80).notNullable().default(''); - }) - } + up() { + this.table('users', (table) => { + table.string('lastname', 80).notNullable().default(''); + }); + } - down() { - this.table('users', (table) => { - table.dropColumn('lastname') - }) - } + down() { + this.table('users', (table) => { + table.dropColumn('lastname'); + }); + } } -module.exports = UsersUpdateSchema \ No newline at end of file +module.exports = UsersUpdateSchema; diff --git a/start/events.js b/start/events.js index 1e4ed5f..c4076cc 100644 --- a/start/events.js +++ b/start/events.js @@ -12,12 +12,14 @@ ${Env.get('APP_URL')}/user/reset?token=${encodeURIComponent(token)} This message was sent automatically. Please do not reply. `; -console.log('Sending message', body); + console.log('Sending message', body); try { await Mail.raw(body, (message) => { - message.subject('[Ferdi] Reset your password') - message.from(Env.get('MAIL_SENDER')) - message.to(user.email) + message.subject('[Ferdi] Reset your password'); + message.from(Env.get('MAIL_SENDER')); + message.to(user.email); }); - } catch(e) {} -}); \ No newline at end of file + } catch (e) { + console.log(`Couldn't send mail: ${e}`); + } +}); diff --git a/start/routes.js b/start/routes.js index 1c2d4f3..05bc538 100644 --- a/start/routes.js +++ b/start/routes.js @@ -60,26 +60,25 @@ Route.group(() => { }).prefix('v1'); // User dashboard -if (Env.get('IS_DASHBOARD_ENABLED') != 'false') { +if (Env.get('IS_DASHBOARD_ENABLED') !== 'false') { Route.group(() => { // Auth Route.get('login', ({ view }) => view.render('dashboard.login')).middleware('guest'); Route.post('login', 'DashboardController.login').middleware('guest').as('login'); - + // Reset password Route.get('forgot', ({ view }) => view.render('dashboard.forgotPassword')).middleware('guest'); Route.post('forgot', 'DashboardController.forgotPassword').middleware('guest'); Route.get('reset', ({ view, request }) => { - const token = request.get().token; + const { token } = request.get(); if (token) { - return view.render('dashboard.resetPassword', { token }) - } else { - return view.render('others.message', { - heading: 'Invalid token', - text: 'Please make sure you are using a valid and recent link to reset your password.', - }); + return view.render('dashboard.resetPassword', { token }); } + return view.render('others.message', { + heading: 'Invalid token', + text: 'Please make sure you are using a valid and recent link to reset your password.', + }); }).middleware('guest'); Route.post('reset', 'DashboardController.resetPassword').middleware('guest'); @@ -92,19 +91,19 @@ if (Env.get('IS_DASHBOARD_ENABLED') != 'false') { Route.get('export', 'DashboardController.export').middleware('auth:session'); Route.post('transfer', 'DashboardController.import').middleware('auth:session'); Route.get('transfer', ({ view }) => view.render('dashboard.transfer')).middleware('auth:session'); - + Route.get('delete', ({ view }) => view.render('dashboard.delete')).middleware('auth:session'); Route.post('delete', 'DashboardController.delete').middleware('auth:session'); - + Route.get('logout', 'DashboardController.logout').middleware('auth:session'); - + Route.get('*', ({ response }) => response.redirect('/user/account')); }).prefix('user').middleware('shield'); } else { Route.group(() => { Route.get('*', ({ response, - }) => response.send('The user dashboard is disabled on this server\n\nIf you are the server owner, please set IS_DASHBOARD_ENABLED to true to enable the dashboard.')) + }) => response.send('The user dashboard is disabled on this server\n\nIf you are the server owner, please set IS_DASHBOARD_ENABLED to true to enable the dashboard.')); }).prefix('user'); } -- cgit v1.2.3-70-g09d2 From fe8bc88e27a1c56678218938f5431f0db976875c Mon Sep 17 00:00:00 2001 From: nick Date: Thu, 17 Jun 2021 03:13:20 +0000 Subject: Send correct Content-Type header for custom icon --- app/Controllers/Http/ServiceController.js | 1 + 1 file changed, 1 insertion(+) (limited to 'app/Controllers') diff --git a/app/Controllers/Http/ServiceController.js b/app/Controllers/Http/ServiceController.js index 05d093b..4aa611c 100644 --- a/app/Controllers/Http/ServiceController.js +++ b/app/Controllers/Http/ServiceController.js @@ -142,6 +142,7 @@ class ServiceController { iconId = uuid() + uuid(); // eslint-disable-next-line no-await-in-loop } while (await fs.exists(path.join(Helpers.tmpPath('uploads'), iconId))); + iconId = `${iconId}.${icon.extname}`; await icon.move(Helpers.tmpPath('uploads'), { name: iconId, -- cgit v1.2.3-70-g09d2