From c11c4a36169bc9ac50a70723dfd45dea8f6a609f Mon Sep 17 00:00:00 2001 From: Cameron Clough Date: Mon, 21 Mar 2022 23:38:56 +0000 Subject: [PATCH] refactor: orm models and logger fixes --- src/models/accounts.model.js | 102 ++++++------ src/models/athena_action_log.model.js | 94 ++++++----- src/models/athena_returned_data.model.js | 78 +++++---- src/models/device_authorised_users.model.js | 78 +++++---- src/models/devices.model.js | 126 ++++++++------- src/models/drive_segments.model.js | 110 +++++++------ src/models/drives.model.js | 150 +++++++++--------- src/models/index.js | 19 +++ src/models/oauth_accounts.model.js | 78 +++++---- src/models/{index.model.js => orm.js} | 18 --- src/server/controllers/admin.js | 10 +- .../controllers/authentication/index.js | 59 ++++--- .../authentication/oauth/google.js | 4 +- .../controllers/authentication/twofactor.js | 39 +++-- src/server/controllers/devices.js | 36 ++--- src/server/controllers/users.js | 25 +-- src/server/routes/api.js | 4 +- src/server/routes/api/authentication/oauth.js | 4 +- src/server/routes/api/devices.js | 2 +- src/server/routes/api/realtime.js | 11 +- src/server/routes/useradmin.js | 11 +- src/server/websocket/athena/helpers.js | 9 +- src/server/websocket/athena/index.js | 6 +- src/worker/worker.js | 2 +- 24 files changed, 532 insertions(+), 543 deletions(-) create mode 100644 src/models/index.js rename src/models/{index.model.js => orm.js} (56%) diff --git a/src/models/accounts.model.js b/src/models/accounts.model.js index 18f252c..341832e 100644 --- a/src/models/accounts.model.js +++ b/src/models/accounts.model.js @@ -1,54 +1,52 @@ import { DataTypes } from 'sequelize'; -export default (sequelize) => { - sequelize.define( - 'accounts', - { - id: { - allowNull: false, - autoIncrement: true, - primaryKey: true, - type: DataTypes.INTEGER, - }, - email: { - allowNull: false, - type: DataTypes.TEXT, - }, - password: { - allowNull: true, - type: DataTypes.TEXT, - }, - created: { - allowNull: true, - type: DataTypes.BIGINT, - }, - last_ping: { - allowNull: true, - type: DataTypes.BIGINT, - }, - '2fa_token': { - allowNull: true, - type: DataTypes.TEXT, - }, - admin: { - allowNull: true, - type: DataTypes.BOOLEAN, - }, - email_verify_token: { - allowNull: true, - type: DataTypes.TEXT, - }, - g_oauth_sub: { - allowNull: true, - type: DataTypes.TEXT, - }, - two_factor_enabled: { - allowNull: true, - type: DataTypes.BOOLEAN, - }, - }, - { - timestamps: false, - }, - ); -}; +import sequelize from './orm'; + +const Accounts = sequelize.define('accounts', { + id: { + allowNull: false, + autoIncrement: true, + primaryKey: true, + type: DataTypes.INTEGER, + }, + email: { + allowNull: false, + type: DataTypes.TEXT, + }, + password: { + allowNull: true, + type: DataTypes.TEXT, + }, + created: { + allowNull: true, + type: DataTypes.BIGINT, + }, + last_ping: { + allowNull: true, + type: DataTypes.BIGINT, + }, + '2fa_token': { + allowNull: true, + type: DataTypes.TEXT, + }, + admin: { + allowNull: true, + type: DataTypes.BOOLEAN, + }, + email_verify_token: { + allowNull: true, + type: DataTypes.TEXT, + }, + g_oauth_sub: { + allowNull: true, + type: DataTypes.TEXT, + }, + two_factor_enabled: { + allowNull: true, + type: DataTypes.BOOLEAN, + }, +}, { + timestamps: false, +}); + +export default Accounts; diff --git a/src/models/athena_action_log.model.js b/src/models/athena_action_log.model.js index ddf1264..15d3e3e 100644 --- a/src/models/athena_action_log.model.js +++ b/src/models/athena_action_log.model.js @@ -1,50 +1,48 @@ import { DataTypes } from 'sequelize'; -export default (sequelize) => { - sequelize.define( - 'athena_action_log', - { - id: { - allowNull: false, - autoIncrement: true, - primaryKey: true, - type: DataTypes.INTEGER, - }, - account_id: { - allowNull: true, - type: DataTypes.INTEGER, - }, - device_id: { - allowNull: true, - type: DataTypes.INTEGER, - }, - action: { - allowNull: true, - type: DataTypes.TEXT, - }, - user_ip: { - allowNull: true, - type: DataTypes.TEXT, - }, - device_ip: { - allowNull: true, - type: DataTypes.TEXT, - }, - meta: { - allowNull: true, - type: DataTypes.TEXT, - }, - created_at: { - allowNull: true, - type: DataTypes.BIGINT, - }, - dongle_id: { - allowNull: true, - type: DataTypes.TEXT, - }, - }, - { - timestamps: false, - }, - ); -}; +import sequelize from './orm'; + +const AthenaActionLog = sequelize.define('athena_action_log', { + id: { + allowNull: false, + autoIncrement: true, + primaryKey: true, + type: DataTypes.INTEGER, + }, + account_id: { + allowNull: true, + type: DataTypes.INTEGER, + }, + device_id: { + allowNull: true, + type: DataTypes.INTEGER, + }, + action: { + allowNull: true, + type: DataTypes.TEXT, + }, + user_ip: { + allowNull: true, + type: DataTypes.TEXT, + }, + device_ip: { + allowNull: true, + type: DataTypes.TEXT, + }, + meta: { + allowNull: true, + type: DataTypes.TEXT, + }, + created_at: { + allowNull: true, + type: DataTypes.BIGINT, + }, + dongle_id: { + allowNull: true, + type: DataTypes.TEXT, + }, +}, { + timestamps: false, +}); + +export default AthenaActionLog; diff --git a/src/models/athena_returned_data.model.js b/src/models/athena_returned_data.model.js index fe3ed07..908a236 100644 --- a/src/models/athena_returned_data.model.js +++ b/src/models/athena_returned_data.model.js @@ -1,42 +1,40 @@ import { DataTypes } from 'sequelize'; -export default (sequelize) => { - sequelize.define( - 'athena_returned_data', - { - id: { - allowNull: false, - autoIncrement: true, - primaryKey: true, - type: DataTypes.INTEGER, - }, - device_id: { - allowNull: true, - type: DataTypes.INTEGER, - }, - type: { - allowNull: true, - type: DataTypes.TEXT, - }, - data: { - allowNull: true, - type: DataTypes.TEXT, - }, - created_at: { - allowNull: true, - type: DataTypes.TEXT, - }, - uuid: { - allowNull: false, - type: DataTypes.TEXT, - }, - resolved_at: { - allowNull: true, - type: DataTypes.INTEGER, - }, - }, - { - timestamps: false, - }, - ); -}; +import sequelize from './orm'; + +const AthenaReturnedData = sequelize.define('athena_returned_data', { + id: { + allowNull: false, + autoIncrement: true, + primaryKey: true, + type: DataTypes.INTEGER, + }, + device_id: { + allowNull: true, + type: DataTypes.INTEGER, + }, + type: { + allowNull: true, + type: DataTypes.TEXT, + }, + data: { + allowNull: true, + type: DataTypes.TEXT, + }, + created_at: { + allowNull: true, + type: DataTypes.TEXT, + }, + uuid: { + allowNull: false, + type: DataTypes.TEXT, + }, + resolved_at: { + allowNull: true, + type: DataTypes.INTEGER, + }, +}, { + timestamps: false, +}); + +export default AthenaReturnedData; diff --git a/src/models/device_authorised_users.model.js b/src/models/device_authorised_users.model.js index 87f0ede..4ce7609 100644 --- a/src/models/device_authorised_users.model.js +++ b/src/models/device_authorised_users.model.js @@ -1,42 +1,40 @@ import { DataTypes } from 'sequelize'; -export default (sequelize) => { - sequelize.define( - 'device_authorised_users', - { - id: { - allowNull: false, - autoIncrement: true, - primaryKey: true, - type: DataTypes.INTEGER, - }, - account_id: { - allowNull: false, - type: DataTypes.INTEGER, - }, - device_id: { - allowNull: true, - type: DataTypes.INTEGER, - }, - athena: { - allowNull: true, - type: DataTypes.BOOLEAN, - }, - unpair: { - allowNull: true, - type: DataTypes.BOOLEAN, - }, - view_drives: { - allowNull: true, - type: DataTypes.BOOLEAN, - }, - created_at: { - allowNull: true, - type: DataTypes.BIGINT, - }, - }, - { - timestamps: false, - }, - ); -}; +import sequelize from './orm'; + +const DeviceAuthorisedUsers = sequelize.define('device_authorised_users', { + id: { + allowNull: false, + autoIncrement: true, + primaryKey: true, + type: DataTypes.INTEGER, + }, + account_id: { + allowNull: false, + type: DataTypes.INTEGER, + }, + device_id: { + allowNull: true, + type: DataTypes.INTEGER, + }, + athena: { + allowNull: true, + type: DataTypes.BOOLEAN, + }, + unpair: { + allowNull: true, + type: DataTypes.BOOLEAN, + }, + view_drives: { + allowNull: true, + type: DataTypes.BOOLEAN, + }, + created_at: { + allowNull: true, + type: DataTypes.BIGINT, + }, +}, { + timestamps: false, +}); + +export default DeviceAuthorisedUsers; diff --git a/src/models/devices.model.js b/src/models/devices.model.js index 5417d80..bb2c439 100644 --- a/src/models/devices.model.js +++ b/src/models/devices.model.js @@ -1,66 +1,64 @@ import { DataTypes } from 'sequelize'; -export default (sequelize) => { - sequelize.define( - 'device', - { - id: { - allowNull: false, - autoIncrement: true, - primaryKey: true, - type: DataTypes.INTEGER, - }, - dongle_id: { - allowNull: false, - type: DataTypes.TEXT, - }, - account_id: { - allowNull: true, - type: DataTypes.INTEGER, - }, - imei: { - allowNull: true, - type: DataTypes.TEXT, - }, - serial: { - allowNull: true, - type: DataTypes.TEXT, - }, - device_type: { - allowNull: true, - type: DataTypes.TEXT, - }, - public_key: { - allowNull: true, - type: DataTypes.TEXT, - }, - created: { - allowNull: true, - type: DataTypes.BIGINT, - }, - last_ping: { - allowNull: true, - type: DataTypes.BIGINT, - }, - storage_used: { - allowNull: true, - type: DataTypes.INTEGER, - }, - max_storage: { - allowNull: true, - type: DataTypes.INTEGER, - }, - ignore_uploads: { - allowNull: true, - type: DataTypes.BOOLEAN, - }, - nickname: { - allowNull: true, - type: DataTypes.TEXT, - }, - }, - { - timestamps: false, - }, - ); -}; +import sequelize from './orm'; + +const Devices = sequelize.define('device', { + id: { + allowNull: false, + autoIncrement: true, + primaryKey: true, + type: DataTypes.INTEGER, + }, + dongle_id: { + allowNull: false, + type: DataTypes.TEXT, + }, + account_id: { + allowNull: true, + type: DataTypes.INTEGER, + }, + imei: { + allowNull: true, + type: DataTypes.TEXT, + }, + serial: { + allowNull: true, + type: DataTypes.TEXT, + }, + device_type: { + allowNull: true, + type: DataTypes.TEXT, + }, + public_key: { + allowNull: true, + type: DataTypes.TEXT, + }, + created: { + allowNull: true, + type: DataTypes.BIGINT, + }, + last_ping: { + allowNull: true, + type: DataTypes.BIGINT, + }, + storage_used: { + allowNull: true, + type: DataTypes.INTEGER, + }, + max_storage: { + allowNull: true, + type: DataTypes.INTEGER, + }, + ignore_uploads: { + allowNull: true, + type: DataTypes.BOOLEAN, + }, + nickname: { + allowNull: true, + type: DataTypes.TEXT, + }, +}, { + timestamps: false, +}); + +export default Devices; diff --git a/src/models/drive_segments.model.js b/src/models/drive_segments.model.js index f07de36..9ed1669 100644 --- a/src/models/drive_segments.model.js +++ b/src/models/drive_segments.model.js @@ -1,58 +1,56 @@ import { DataTypes } from 'sequelize'; -export default (sequelize) => { - sequelize.define( - 'drive_segments', - { - id: { - allowNull: false, - autoIncrement: true, - primaryKey: true, - type: DataTypes.INTEGER, - }, - segment_id: { - allowNull: false, - type: DataTypes.INTEGER, - }, - drive_identifier: { - allowNull: true, - type: DataTypes.TEXT, - }, - dongle_id: { - allowNull: true, - type: DataTypes.TEXT, - }, - duration: { - allowedNull: true, - type: DataTypes.INTEGER, - }, - distance_meters: { - allowNull: true, - type: DataTypes.INTEGER, - }, - upload_complete: { - allowNull: true, - type: DataTypes.BOOLEAN, - }, - is_processed: { - allowNull: true, - type: DataTypes.BOOLEAN, - }, - is_stalled: { - allowNull: true, - type: DataTypes.BOOLEAN, - }, - created: { - allowNull: true, - type: DataTypes.BIGINT, - }, - process_attempts: { - allowNull: true, - type: DataTypes.INTEGER, - }, - }, - { - timestamps: false, - }, - ); -}; +import sequelize from './orm'; + +const DriveSegments = sequelize.define('drive_segments', { + id: { + allowNull: false, + autoIncrement: true, + primaryKey: true, + type: DataTypes.INTEGER, + }, + segment_id: { + allowNull: false, + type: DataTypes.INTEGER, + }, + drive_identifier: { + allowNull: true, + type: DataTypes.TEXT, + }, + dongle_id: { + allowNull: true, + type: DataTypes.TEXT, + }, + duration: { + allowedNull: true, + type: DataTypes.INTEGER, + }, + distance_meters: { + allowNull: true, + type: DataTypes.INTEGER, + }, + upload_complete: { + allowNull: true, + type: DataTypes.BOOLEAN, + }, + is_processed: { + allowNull: true, + type: DataTypes.BOOLEAN, + }, + is_stalled: { + allowNull: true, + type: DataTypes.BOOLEAN, + }, + created: { + allowNull: true, + type: DataTypes.BIGINT, + }, + process_attempts: { + allowNull: true, + type: DataTypes.INTEGER, + }, +}, { + timestamps: false, +}); + +export default DriveSegments; diff --git a/src/models/drives.model.js b/src/models/drives.model.js index 83546bb..f81840f 100644 --- a/src/models/drives.model.js +++ b/src/models/drives.model.js @@ -1,78 +1,76 @@ import { DataTypes } from 'sequelize'; -export default (sequelize) => { - sequelize.define( - 'drives', - { - id: { - allowNull: false, - autoIncrement: true, - primaryKey: true, - type: DataTypes.INTEGER, - }, - identifier: { - allowNull: true, - type: DataTypes.TEXT, - }, - dongle_id: { - allowNull: true, - type: DataTypes.TEXT, - }, - max_segment: { - allowNull: true, - type: DataTypes.INTEGER, - }, - upload_complete: { - allowedNull: true, - type: DataTypes.BOOLEAN, - }, - duration: { - allowNull: true, - type: DataTypes.INTEGER, - }, - distance_meters: { - allowNull: true, - type: DataTypes.INTEGER, - }, - filesize: { - allowNull: true, - type: DataTypes.INTEGER, - }, - is_processed: { - allowNull: true, - type: DataTypes.BOOLEAN, - }, - created: { - allowNull: true, - type: DataTypes.BIGINT, - }, - last_upload: { - allowNull: true, - type: DataTypes.BIGINT, - }, - is_preserved: { - allowNull: true, - type: DataTypes.BOOLEAN, - }, - is_deleted: { - allowNull: true, - type: DataTypes.BOOLEAN, - }, - drive_date: { - allowNull: true, - type: DataTypes.BIGINT, - }, - is_physically_removed: { - allowNull: true, - type: DataTypes.BOOLEAN, - }, - metadata: { - allowNull: true, - type: DataTypes.TEXT, - }, - }, - { - timestamps: false, - }, - ); -}; +import sequelize from './orm'; + +const Drives = sequelize.define('drives', { + id: { + allowNull: false, + autoIncrement: true, + primaryKey: true, + type: DataTypes.INTEGER, + }, + identifier: { + allowNull: true, + type: DataTypes.TEXT, + }, + dongle_id: { + allowNull: true, + type: DataTypes.TEXT, + }, + max_segment: { + allowNull: true, + type: DataTypes.INTEGER, + }, + upload_complete: { + allowedNull: true, + type: DataTypes.BOOLEAN, + }, + duration: { + allowNull: true, + type: DataTypes.INTEGER, + }, + distance_meters: { + allowNull: true, + type: DataTypes.INTEGER, + }, + filesize: { + allowNull: true, + type: DataTypes.INTEGER, + }, + is_processed: { + allowNull: true, + type: DataTypes.BOOLEAN, + }, + created: { + allowNull: true, + type: DataTypes.BIGINT, + }, + last_upload: { + allowNull: true, + type: DataTypes.BIGINT, + }, + is_preserved: { + allowNull: true, + type: DataTypes.BOOLEAN, + }, + is_deleted: { + allowNull: true, + type: DataTypes.BOOLEAN, + }, + drive_date: { + allowNull: true, + type: DataTypes.BIGINT, + }, + is_physically_removed: { + allowNull: true, + type: DataTypes.BOOLEAN, + }, + metadata: { + allowNull: true, + type: DataTypes.TEXT, + }, +}, { + timestamps: false, +}); + +export default Drives; diff --git a/src/models/index.js b/src/models/index.js new file mode 100644 index 0000000..02c1617 --- /dev/null +++ b/src/models/index.js @@ -0,0 +1,19 @@ +import Accounts from './accounts.model'; +import AthenaActionLog from './athena_action_log.model'; +import AthenaReturnedData from './athena_returned_data.model'; +import DeviceAuthorisedUsers from './device_authorised_users.model'; +import Devices from './devices.model'; +import DriveSegments from './drive_segments.model'; +import Drives from './drives.model'; +import OAuthAccounts from './oauth_accounts.model'; + +export { + Accounts, + AthenaActionLog, + AthenaReturnedData, + DeviceAuthorisedUsers, + Devices, + DriveSegments, + Drives, + OAuthAccounts, +}; diff --git a/src/models/oauth_accounts.model.js b/src/models/oauth_accounts.model.js index e1dd6a9..de3524a 100644 --- a/src/models/oauth_accounts.model.js +++ b/src/models/oauth_accounts.model.js @@ -1,42 +1,40 @@ import { DataTypes } from 'sequelize'; -export default (sequelize) => { - sequelize.define( - 'oauth_accounts', - { - id: { - id: false, - autoIncrement: true, - primaryKey: true, - type: DataTypes.INTEGER, - }, - account_id: { - allowNull: false, - type: DataTypes.INTEGER, - }, - email: { - allowNull: false, - type: DataTypes.TEXT, - }, - created: { - allowNull: true, - type: DataTypes.TIME, - }, - last_used: { - allowNull: true, - type: DataTypes.CHAR, - }, - refresh: { - allowNull: true, - type: DataTypes.TEXT, - }, - provider: { - allowNull: true, - type: DataTypes.TEXT, - }, - }, - { - timestamps: false, - }, - ); -}; +import sequelize from './orm'; + +const OAuthAccounts = sequelize.define('oauth_accounts', { + id: { + id: false, + autoIncrement: true, + primaryKey: true, + type: DataTypes.INTEGER, + }, + account_id: { + allowNull: false, + type: DataTypes.INTEGER, + }, + email: { + allowNull: false, + type: DataTypes.TEXT, + }, + created: { + allowNull: true, + type: DataTypes.TIME, + }, + last_used: { + allowNull: true, + type: DataTypes.CHAR, + }, + refresh: { + allowNull: true, + type: DataTypes.TEXT, + }, + provider: { + allowNull: true, + type: DataTypes.TEXT, + }, +}, { + timestamps: false, +}); + +export default OAuthAccounts; diff --git a/src/models/index.model.js b/src/models/orm.js similarity index 56% rename from src/models/index.model.js rename to src/models/orm.js index a4d5d3f..0f0e99b 100644 --- a/src/models/index.model.js +++ b/src/models/orm.js @@ -1,6 +1,3 @@ -/* eslint-disable no-restricted-syntax */ -/* eslint-disable global-require */ - import { Sequelize } from 'sequelize'; const sequelize = new Sequelize({ @@ -14,21 +11,6 @@ const sequelize = new Sequelize({ sequelize.options.logging = () => {}; -const modelDefiners = [ - require('./devices.model').default, - require('./drives.model').default, - require('./accounts.model').default, - require('./athena_action_log.model').default, - require('./athena_returned_data.model').default, - require('./device_authorised_users.model').default, - require('./drive_segments.model').default, - require('./oauth_accounts.model').default, -]; - -for (const modelDefiner of modelDefiners) { - modelDefiner(sequelize); -} - /** * Synchronise the database (create new tables) to match the models defined * above. diff --git a/src/server/controllers/admin.js b/src/server/controllers/admin.js index 50c20ae..fb434e1 100644 --- a/src/server/controllers/admin.js +++ b/src/server/controllers/admin.js @@ -1,11 +1,7 @@ -import orm from '../../models/index.model'; - // TODO move everythijng away from this dumb intertwined style -// eslint-disable-next-line no-unused-vars -import devices from './devices'; - import authentication from './authentication'; +import { Accounts } from '../../models'; async function isCurrentUserAdmin(hardFail, req) { const account = await authentication.getAuthenticatedAccount(req); @@ -29,12 +25,12 @@ async function banAccount(ban, userId) { return { success: false, status: 400, data: { bad_data: true } }; } - await orm.models.accounts.update( + await Accounts.update( { banned: cleanBan ? 1 : 0 }, { where: { id: userId } }, ); - const verify = await orm.models.accounts.findOne({ where: { id: userId } }); + const verify = await Accounts.findOne({ where: { id: userId } }); if (verify.dataValues && verify.dataValues.banned === cleanBan ? 1 : 0) { return { success: true, status: 200, data: { banned: ban } }; } diff --git a/src/server/controllers/authentication/index.js b/src/server/controllers/authentication/index.js index a1cf02d..604d5e8 100644 --- a/src/server/controllers/authentication/index.js +++ b/src/server/controllers/authentication/index.js @@ -1,7 +1,8 @@ import crypto from 'crypto'; import jsonwebtoken from 'jsonwebtoken'; import log4js from 'log4js'; -import orm from '../../../models/index.model'; + +import { Accounts } from '../../../models'; const logger = log4js.getLogger('default'); @@ -24,38 +25,44 @@ export async function readJWT(token) { } async function signIn(email, password) { - let account = await orm.models.accounts.findOne({ where: { email } }); + let account = await Accounts.findOne({ where: { email } }); - if (account && account.dataValues) { - account = account.dataValues; - const inputPassword = crypto.createHash('sha256').update(password + process.env.APP_SALT).digest('hex'); - if (account.password === inputPassword) { - const token = jsonwebtoken.sign({ accountId: account.id }, process.env.APP_SALT); - - return { success: true, jwt: token }; - } - return { success: false, msg: 'BAD PASSWORD', invalidPassword: true }; + if (!account || !account.dataValues) { + return { success: false, msg: 'BAD ACCOUNT', badAccount: true }; } - return { success: false, msg: 'BAD ACCOUNT', badAccount: true }; + + account = account.dataValues; + const inputPassword = crypto.createHash('sha256').update(password + process.env.APP_SALT).digest('hex'); + if (account.password !== inputPassword) { + return { + success: false, + msg: 'BAD PASSWORD', + invalidPassword: true, + }; + } + + const token = jsonwebtoken.sign({ accountId: account.id }, process.env.APP_SALT); + return { success: true, jwt: token }; } async function changePassword(account, newPassword, oldPassword) { if (!account || !newPassword || !oldPassword) { return { success: false, error: 'MISSING_DATA' }; } + const oldPasswordHash = crypto.createHash('sha256').update(oldPassword + process.env.APP_SALT).digest('hex'); - - if (account.password === oldPasswordHash) { - const newPasswordHash = crypto.createHash('sha256').update(newPassword + process.env.APP_SALT).digest('hex'); - - await orm.models.accounts.update( - { password: newPasswordHash }, - { where: { id: account.id } }, - ); - - return { success: true, msg: 'PASSWORD CHANGED', changed: true }; + if (account.password !== oldPasswordHash) { + return { success: false, msg: 'BAD PASSWORD', passwordCorrect: false }; } - return { success: false, msg: 'BAD PASSWORD', passwordCorrect: false }; + + const newPasswordHash = crypto.createHash('sha256').update(newPassword + process.env.APP_SALT).digest('hex'); + + await Accounts.update( + { password: newPasswordHash }, + { where: { id: account.id } }, + ); + + return { success: true, msg: 'PASSWORD CHANGED', changed: true }; } /* @@ -89,13 +96,13 @@ async function getAccountFromJWT(jwt, limitData) { query = { ...query, attributes: { exclude: ['password', '2fa_token', 'session_seed'] } }; } - const account = await orm.models.accounts.findOne(query); - if (!account.dataValues) { + const account = await Accounts.findOne(query); + if (!account || !account.dataValues) { return null; // {success: false, isInvalid: true} } try { - await orm.models.accounts.update( + await Accounts.update( { last_ping: Date.now() }, { where: { id: account.id } }, ); diff --git a/src/server/controllers/authentication/oauth/google.js b/src/server/controllers/authentication/oauth/google.js index 390a16c..2efaed0 100644 --- a/src/server/controllers/authentication/oauth/google.js +++ b/src/server/controllers/authentication/oauth/google.js @@ -45,11 +45,11 @@ export async function getToken(code, scope) { return { error: true, ...AUTH_OAUTH_ERR_GOOGLE_FAILED_TOKEN_FETCH }; } - logger.log(`accessToken: ${accessToken}`); + logger.info(`accessToken: ${accessToken}`); const id = jsonwebtoken.decode(accessToken.token.id_token); - logger.log(`jsonwebtoken.${id}`); + logger.info(`jsonwebtoken.${id}`); return id; } diff --git a/src/server/controllers/authentication/twofactor.js b/src/server/controllers/authentication/twofactor.js index 61511f0..c02f821 100644 --- a/src/server/controllers/authentication/twofactor.js +++ b/src/server/controllers/authentication/twofactor.js @@ -1,4 +1,6 @@ import { generateSecret, verify } from '2fa-util'; + +import { Accounts } from '../../../models'; import { AUTH_2FA_BAD_ACCOUNT, AUTH_2FA_ONBOARD_ALREADY_ENROLLED, @@ -6,7 +8,6 @@ import { AUTH_2FA_ENROLLED, AUTH_2FA_BAD_TOKEN, } from '../../consistency/terms'; -import orm from '../../../models/index.model'; export async function twoFactorOnboard(account) { if (!account || !account.dataValues) { return { success: false, ...AUTH_2FA_BAD_ACCOUNT }; } @@ -14,7 +15,7 @@ export async function twoFactorOnboard(account) { const token = await generateSecret(account.email, process.env.AUTH_2FA_ISSUER); - orm.models.account.update( + await Accounts.update( { '2fa_token': token.secret }, { id: account.id }, ); @@ -24,30 +25,26 @@ export async function twoFactorOnboard(account) { export async function twoFactorConfirm(account, token) { const isTokenValid = await verifyTwoFactor(account.id, token); - - if (isTokenValid) { - orm.models.account.update( - { two_factor_enabled: true }, - { id: account.id }, - ); - return { - success: true, - ...AUTH_2FA_ENROLLED, - }; + if (!isTokenValid) { + return { success: false, ...AUTH_2FA_BAD_TOKEN }; } - return { - success: false, - ...AUTH_2FA_BAD_TOKEN, - }; + + await Accounts.update( + { two_factor_enabled: true }, + { id: account.id }, + ); + return { success: true, ...AUTH_2FA_ENROLLED }; } export async function verifyTwoFactor(account, token) { - if (!account || !account.dataValues) { return { success: false, ...AUTH_2FA_BAD_ACCOUNT }; } - if (account['2fa_token'] !== null) return { success: false, ...AUTH_2FA_NOT_ENROLLED }; + if (!account || !account.dataValues) { + return { success: false, ...AUTH_2FA_BAD_ACCOUNT }; + } + if (!account['2fa_token']) { + return { success: false, ...AUTH_2FA_NOT_ENROLLED }; + } - const result = await verify(token, account['2fa_token']).catch(console.log); - - return result; + return verify(token, account['2fa_token']).catch(console.log); } export default null; diff --git a/src/server/controllers/devices.js b/src/server/controllers/devices.js index 2edf61d..b599020 100644 --- a/src/server/controllers/devices.js +++ b/src/server/controllers/devices.js @@ -2,8 +2,8 @@ import sanitizeFactory from 'sanitize'; import crypto from 'crypto'; import dirTree from 'directory-tree'; import log4js from 'log4js'; -import orm from '../../models/index.model'; +import { Devices } from '../../models'; import { readJWT, validateJWT } from './authentication'; import { getAccountFromId } from './users'; @@ -23,14 +23,14 @@ async function pairDevice(account, qrString) { if (qrString.indexOf('--') >= 0) { const [, serial, pairToken] = qrCodeParts; - device = await orm.models.device.findOne({ where: { serial } }); + device = await Devices.findOne({ where: { serial } }); pairJWT = pairToken; } else { const data = await readJWT(qrString); if (!data || !data.pair) { return { success: false, noPair: true }; } - device = await orm.models.device.findOne({ where: { dongle_id: data.identity } }); + device = await Devices.findOne({ where: { dongle_id: data.identity } }); pairJWT = qrString; } @@ -50,12 +50,12 @@ async function pairDevice(account, qrString) { } async function pairDeviceToAccountId(dongleId, accountId) { - await orm.models.device.update( + await Devices.update( { account_id: accountId }, { where: { dongle_id: dongleId } }, ); - const check = await orm.models.device.findOne( + const check = await Devices.findOne( { where: { dongle_id: dongleId, account_id: accountId } }, ); if (check.dataValues) { @@ -67,12 +67,12 @@ async function pairDeviceToAccountId(dongleId, accountId) { } async function unpairDevice(account, dongleId) { - const device = await orm.models.device.getOne( + const device = await Devices.getOne( { where: { account_id: account.id, dongle_id: dongleId } }, ); if (device && device.dataValues) { - await orm.models.device.update( + await Devices.update( { account_id: 0 }, { where: { dongle_id: dongleId } }, ); @@ -82,14 +82,14 @@ async function unpairDevice(account, dongleId) { } async function setDeviceNickname(account, dongleId, nickname) { - const device = await orm.models.device.getOne( + const device = await Devices.getOne( { where: { account_id: account.id, dongle_id: dongleId } }, ); const cleanNickname = sanitize.value(nickname, 'string'); if (device && device.dataValues) { - await orm.models.device.update( + await Devices.update( { nickname: cleanNickname }, { where: { dongle_id: dongleId } }, ); @@ -99,12 +99,12 @@ async function setDeviceNickname(account, dongleId, nickname) { } async function getDevices(accountId) { - return orm.models.device.findAll({ where: { account_id: accountId } }); + return Devices.findAll({ where: { account_id: accountId } }); } async function getDeviceFromDongle(dongleId) { if (!dongleId) return null; - const devices = await orm.models.device.findOne({ where: { dongle_id: dongleId } }); + const devices = await Devices.findOne({ where: { dongle_id: dongleId } }); if (!devices || !devices.dataValues) { return null; } @@ -113,7 +113,7 @@ async function getDeviceFromDongle(dongleId) { // TODO combine these redundant functions into one async function getDeviceFromSerial(serial) { if (!serial) return null; - const devices = await orm.models.device.findOne({ where: { serial } }); + const devices = await Devices.findOne({ where: { serial } }); if (!devices || !devices.dataValues) { return null; } @@ -123,7 +123,7 @@ async function getDeviceFromSerial(serial) { async function updateDevice(dongleId, data) { if (!dongleId) return null; - return orm.models.device.update(data, { where: { dongle_id: dongleId } }); + return Devices.update(data, { where: { dongle_id: dongleId } }); } async function setIgnoredUploads(dongleId, isIgnored) { @@ -137,11 +137,11 @@ async function setIgnoredUploads(dongleId, isIgnored) { } async function getAllDevicesFiltered() { - return orm.models.device.findAll(); + return Devices.findAll(); } async function updateLastPing(deviceId) { - return orm.models.device.update( + return Devices.update( { last_ping: Date.now() }, { where: { [Op.or]: [{ id: deviceId }, { dongle_id: deviceId }] } }, ); @@ -196,7 +196,7 @@ async function getDrives(dongleId, includeDeleted, includeMeta) { async function getDrive(identifier) { const drive = await orm.models.drives.findOne({ where: { identifier } }); - logger.log(drive); + logger.info(drive); if (drive.dataValues) return drive.dataValues; return null; @@ -274,7 +274,7 @@ async function updateOrCreateDrive(dongleId, identifier, data) { logger.info('updateOrCreate Drive', dongleId, identifier, data); const check = await orm.models.drives.findOne({ where: { dongle_id: dongleId, identifier } }); - logger.log('checking for existing drive....', check); + logger.info('checking for existing drive....', check); if (check) { return orm.models.drives.update( @@ -322,7 +322,7 @@ async function getDriveSegment(driveName, segment) { } async function createDongle(dongleId, accountId, imei, serial, publicKey) { - return orm.models.device.create({ + return Devices.create({ dongle_id: dongleId, account_id: 0, imei, diff --git a/src/server/controllers/users.js b/src/server/controllers/users.js index 25118e2..c8d0b53 100644 --- a/src/server/controllers/users.js +++ b/src/server/controllers/users.js @@ -1,24 +1,25 @@ import crypto from 'crypto'; import log4js from 'log4js'; -import orm from '../../models/index.model'; + +import { Accounts } from '../../models'; const logger = log4js.getLogger('default'); export async function getAccountFromId(id) { - return orm.models.accounts.findByPk(id); + return Accounts.findByPk(id); } export async function getAccountFromEmail(email) { if (!email) return null; - const account = orm.models.accounts.findOne({ where: { email } }); + const account = Accounts.findOne({ where: { email } }); if (account.dataValues) return account.dataValues; return null; } export async function createBaseAccount() { - await orm.models.accounts.create({ + await Accounts.create({ id: 0, email: 'dummy@retropilot.org', password: '123123', @@ -31,8 +32,8 @@ export async function createBaseAccount() { } export async function _dirtyCreateAccount(email, password, created, admin) { - logger.log('creating acount: ', email, password, created, admin); - return orm.models.accounts.create({ + logger.info('creating account: ', email, password, created, admin); + return Accounts.create({ email, password, created, admin, }); } @@ -48,12 +49,12 @@ export async function createAccount(email, password) { const emailToken = crypto.createHmac('sha256', process.env.APP_SALT).update(email.trim()).digest('hex'); password = crypto.createHash('sha256').update(password + process.env.APP_SALT).digest('hex'); - const account = await orm.models.accounts.findOne({ where: { email } }); + const account = await Accounts.findOne({ where: { email } }); if (account != null && account.dataValues != null) { return { success: true, status: 409, data: { alreadyRegistered: true } }; } - await orm.models.accounts.create({ + await Accounts.create({ email, password, created: Date.now(), @@ -61,7 +62,7 @@ export async function createAccount(email, password) { email_verify_token: emailToken, }); - const didAccountRegister = await orm.models.accounts.findOne({ where: { email } }); + const didAccountRegister = await Accounts.findOne({ where: { email } }); if (didAccountRegister != null && didAccountRegister.dataValues != null) { return { success: true, status: 200 }; @@ -76,7 +77,7 @@ export async function verifyEmailToken(token) { return { success: false, status: 400, data: { missingToken: true } }; } - const account = await orm.models.accounts.findOne( + const account = await Accounts.findOne( { where: { email_verify_token: token } }, ); @@ -87,7 +88,7 @@ export async function verifyEmailToken(token) { return { success: true, status: 409, data: { alreadyVerified: true } }; } - await orm.models.accounts.update( + await Accounts.update( { verified: true }, { where: { id: account.id } }, ); @@ -96,7 +97,7 @@ export async function verifyEmailToken(token) { } export async function getAllUsers() { - return orm.models.accounts.findAll({ attributes: ['id', 'last_ping', 'created', 'admin', 'banned'] }); + return Accounts.findAll({ attributes: ['id', 'last_ping', 'created', 'admin', 'banned'] }); } export default { diff --git a/src/server/routes/api.js b/src/server/routes/api.js index 2921a91..21fb8d1 100644 --- a/src/server/routes/api.js +++ b/src/server/routes/api.js @@ -270,8 +270,8 @@ async function upload(req, res) { logger.warn("drive failed to make", err) }) - logger.log("drive value", drive) - logger.log("drive name:", driveName) + logger.info("drive value", drive) + logger.info("drive name:", driveName) if (drive === undefined || drive === null) { logger.info("CREATING NEW DRIVE") diff --git a/src/server/routes/api/authentication/oauth.js b/src/server/routes/api/authentication/oauth.js index ce5a4ea..d92b917 100644 --- a/src/server/routes/api/authentication/oauth.js +++ b/src/server/routes/api/authentication/oauth.js @@ -24,13 +24,13 @@ async function isAuthenticated(req, res, next) { } router.get('/authentication/oauth/callback', async (req, res) => { - logger.log(req.query); + logger.info(req.query); res.json(await getToken(req.query.code, req.query.scope)); }); router.get('/authentication/oauth/:provider', async (req, res) => { const { provider } = req.params; - logger.log('provider', provider); + logger.info('provider', provider); let url; switch (provider) { case 'google': diff --git a/src/server/routes/api/devices.js b/src/server/routes/api/devices.js index 81eb9b4..e2baead 100644 --- a/src/server/routes/api/devices.js +++ b/src/server/routes/api/devices.js @@ -54,7 +54,7 @@ router.put('/retropilot/0/device/:dongle_id/', [isAuthenticated, bodyParser.json } const { body } = req; - logger.log(MutateDevice.isValid(body)); + logger.info(MutateDevice.isValid(body)); // TODO: response? return res.json({ success: true }); }); diff --git a/src/server/routes/api/realtime.js b/src/server/routes/api/realtime.js index 9d097a6..6c96ded 100644 --- a/src/server/routes/api/realtime.js +++ b/src/server/routes/api/realtime.js @@ -1,12 +1,11 @@ import express from 'express'; -/* eslint-disable no-unused-vars */ -import authenticationController from '../../controllers/authentication'; -import userController from '../../controllers/users'; +import { AthenaReturnedData } from '../../../models'; +import authenticationController from '../../controllers/authentication'; import deviceController from '../../controllers/devices'; -import models from '../../../models/index.model'; -/* eslint-enable no-unused-vars */ + const router = express.Router(); + const whitelistParams = { getmessage: true, getversion: true, @@ -146,7 +145,7 @@ router.get('/dongle/:dongle_id/get', async (req, res) => { }); } - return res.json(await models.models.athena_returned_data.findAll({ + return res.json(await AthenaReturnedData.findAll({ where: { device_id: device.id }, })); }); diff --git a/src/server/routes/useradmin.js b/src/server/routes/useradmin.js index 0d6b098..a28d3e2 100644 --- a/src/server/routes/useradmin.js +++ b/src/server/routes/useradmin.js @@ -35,7 +35,7 @@ if(process.env.NODE_ENV === 'development') { router.post('/useradmin/auth', bodyParser.urlencoded({ extended: true }), runAsyncWrapper(async (req, res) => { const signIn = await authenticationController.signIn(req.body.email, req.body.password); - logger.log(signIn); + logger.info(signIn); if (signIn.success) { res.cookie('jwt', signIn.jwt); @@ -134,14 +134,15 @@ router.post('/useradmin/register/token', bodyParser.urlencoded({ extended: true Date.now(), false, ); - } catch(error) { - console.error(error); + } catch (error) { + console.error('error creating account', error); } - logger.log(result); + logger.debug('created account:', result); if (result.dataValues) { - logger.info(`USERADMIN REGISTRATION - created new account #${result.lastID} with email ${email}`); + const account = result.dataValues; + logger.info(`USERADMIN REGISTRATION - created new account #${account.id} with email ${email}`); return res.redirect(`/useradmin?status=${encodeURIComponent('Successfully registered')}`); } diff --git a/src/server/websocket/athena/helpers.js b/src/server/websocket/athena/helpers.js index 5ad9e72..b8a9d58 100644 --- a/src/server/websocket/athena/helpers.js +++ b/src/server/websocket/athena/helpers.js @@ -1,6 +1,7 @@ /* eslint-disable no-underscore-dangle */ import { v4 as uuid } from 'uuid'; -import orm from '../../../models/index.model'; + +import { AthenaReturnedData } from '../../../models'; let realtime; let wss; @@ -31,7 +32,7 @@ function invoke(command, params, dongleId, accountId, id) { wss.retropilotFunc.actionLogger(accountId, websocket.device_id, 'ATHENA_USER_INVOKE__ISSUED', null, websocket._socket.remoteAddress, JSON.stringify({ command, params, uniqueID }), websocket.dongleId); - orm.models.athena_returned_data.create({ + AthenaReturnedData.create({ device_id: websocket.device_id, type: command, created_at: Date.now(), @@ -47,7 +48,9 @@ function isDeviceConnected(accountId, deviceId, dongleId) { const websocket = wss.retropilotFunc.findFromDongle(dongleId); wss.retropilotFunc.actionLogger(accountId, deviceId, 'ATHENA_USER_STATUS__IS_CONNECTED', null, websocket ? websocket._socket.remoteAddress : null, JSON.stringify({ connected: !!websocket, heartbeat: websocket ? websocket.heartbeat : null }), dongleId); - if (!websocket) return { connected: false }; + if (!websocket) { + return { connected: false }; + } return { connected: true, heartbeat: websocket.heartbeat }; } diff --git a/src/server/websocket/athena/index.js b/src/server/websocket/athena/index.js index 1180cce..6a8edd9 100644 --- a/src/server/websocket/athena/index.js +++ b/src/server/websocket/athena/index.js @@ -6,7 +6,7 @@ import httpServer from 'http'; import { readFileSync } from 'fs'; import log4js from 'log4js'; -import models from '../../../models/index.model'; +import { AthenaActionLog, AthenaReturnedData } from '../../../models'; import deviceController from '../../controllers/devices'; import helperFunctions from './helpers'; @@ -88,7 +88,7 @@ async function manageConnection(ws, res) { console.log({ device_id: ws.device_id, uuid: json.id }); - console.log(await models.models.athena_returned_data.update({ + console.log(await AthenaReturnedData.update({ data: JSON.stringify(json), resolved_at: Date.now(), }, { where: { device_id: ws.device_id, uuid: json.id } })); @@ -164,7 +164,7 @@ wss.retropilotFunc = { /* eslint-disable camelcase */ actionLogger: async (account_id, device_id, action, user_ip, device_ip, meta, dongle_id) => { - models.models.athena_action_log.create({ + await AthenaActionLog.create({ account_id, device_id, action, user_ip, device_ip, meta, created_at: Date.now(), dongle_id, }); }, diff --git a/src/worker/worker.js b/src/worker/worker.js index 23206e8..3d2f60b 100644 --- a/src/worker/worker.js +++ b/src/worker/worker.js @@ -8,7 +8,7 @@ import Reader from '@commaai/log_reader'; import ffprobe from 'ffprobe'; import ffprobeStatic from 'ffprobe-static'; -import orm from '../models/index.model'; +import orm from '../models/orm'; import { initializeStorage, deleteFolderRecursive,