refactor: orm models and logger fixes

pull/4/head
Cameron Clough 2022-03-21 23:38:56 +00:00
parent 28285df723
commit c11c4a3616
No known key found for this signature in database
GPG Key ID: BFB3B74B026ED43F
24 changed files with 532 additions and 543 deletions

View File

@ -1,54 +1,52 @@
import { DataTypes } from 'sequelize'; import { DataTypes } from 'sequelize';
export default (sequelize) => { import sequelize from './orm';
sequelize.define(
'accounts', const Accounts = sequelize.define('accounts', {
{ id: {
id: { allowNull: false,
allowNull: false, autoIncrement: true,
autoIncrement: true, primaryKey: true,
primaryKey: true, type: DataTypes.INTEGER,
type: DataTypes.INTEGER, },
}, email: {
email: { allowNull: false,
allowNull: false, type: DataTypes.TEXT,
type: DataTypes.TEXT, },
}, password: {
password: { allowNull: true,
allowNull: true, type: DataTypes.TEXT,
type: DataTypes.TEXT, },
}, created: {
created: { allowNull: true,
allowNull: true, type: DataTypes.BIGINT,
type: DataTypes.BIGINT, },
}, last_ping: {
last_ping: { allowNull: true,
allowNull: true, type: DataTypes.BIGINT,
type: DataTypes.BIGINT, },
}, '2fa_token': {
'2fa_token': { allowNull: true,
allowNull: true, type: DataTypes.TEXT,
type: DataTypes.TEXT, },
}, admin: {
admin: { allowNull: true,
allowNull: true, type: DataTypes.BOOLEAN,
type: DataTypes.BOOLEAN, },
}, email_verify_token: {
email_verify_token: { allowNull: true,
allowNull: true, type: DataTypes.TEXT,
type: DataTypes.TEXT, },
}, g_oauth_sub: {
g_oauth_sub: { allowNull: true,
allowNull: true, type: DataTypes.TEXT,
type: DataTypes.TEXT, },
}, two_factor_enabled: {
two_factor_enabled: { allowNull: true,
allowNull: true, type: DataTypes.BOOLEAN,
type: DataTypes.BOOLEAN, },
}, }, {
}, timestamps: false,
{ });
timestamps: false,
}, export default Accounts;
);
};

View File

@ -1,50 +1,48 @@
import { DataTypes } from 'sequelize'; import { DataTypes } from 'sequelize';
export default (sequelize) => { import sequelize from './orm';
sequelize.define(
'athena_action_log', const AthenaActionLog = sequelize.define('athena_action_log', {
{ id: {
id: { allowNull: false,
allowNull: false, autoIncrement: true,
autoIncrement: true, primaryKey: true,
primaryKey: true, type: DataTypes.INTEGER,
type: DataTypes.INTEGER, },
}, account_id: {
account_id: { allowNull: true,
allowNull: true, type: DataTypes.INTEGER,
type: DataTypes.INTEGER, },
}, device_id: {
device_id: { allowNull: true,
allowNull: true, type: DataTypes.INTEGER,
type: DataTypes.INTEGER, },
}, action: {
action: { allowNull: true,
allowNull: true, type: DataTypes.TEXT,
type: DataTypes.TEXT, },
}, user_ip: {
user_ip: { allowNull: true,
allowNull: true, type: DataTypes.TEXT,
type: DataTypes.TEXT, },
}, device_ip: {
device_ip: { allowNull: true,
allowNull: true, type: DataTypes.TEXT,
type: DataTypes.TEXT, },
}, meta: {
meta: { allowNull: true,
allowNull: true, type: DataTypes.TEXT,
type: DataTypes.TEXT, },
}, created_at: {
created_at: { allowNull: true,
allowNull: true, type: DataTypes.BIGINT,
type: DataTypes.BIGINT, },
}, dongle_id: {
dongle_id: { allowNull: true,
allowNull: true, type: DataTypes.TEXT,
type: DataTypes.TEXT, },
}, }, {
}, timestamps: false,
{ });
timestamps: false,
}, export default AthenaActionLog;
);
};

View File

@ -1,42 +1,40 @@
import { DataTypes } from 'sequelize'; import { DataTypes } from 'sequelize';
export default (sequelize) => { import sequelize from './orm';
sequelize.define(
'athena_returned_data', const AthenaReturnedData = sequelize.define('athena_returned_data', {
{ id: {
id: { allowNull: false,
allowNull: false, autoIncrement: true,
autoIncrement: true, primaryKey: true,
primaryKey: true, type: DataTypes.INTEGER,
type: DataTypes.INTEGER, },
}, device_id: {
device_id: { allowNull: true,
allowNull: true, type: DataTypes.INTEGER,
type: DataTypes.INTEGER, },
}, type: {
type: { allowNull: true,
allowNull: true, type: DataTypes.TEXT,
type: DataTypes.TEXT, },
}, data: {
data: { allowNull: true,
allowNull: true, type: DataTypes.TEXT,
type: DataTypes.TEXT, },
}, created_at: {
created_at: { allowNull: true,
allowNull: true, type: DataTypes.TEXT,
type: DataTypes.TEXT, },
}, uuid: {
uuid: { allowNull: false,
allowNull: false, type: DataTypes.TEXT,
type: DataTypes.TEXT, },
}, resolved_at: {
resolved_at: { allowNull: true,
allowNull: true, type: DataTypes.INTEGER,
type: DataTypes.INTEGER, },
}, }, {
}, timestamps: false,
{ });
timestamps: false,
}, export default AthenaReturnedData;
);
};

View File

@ -1,42 +1,40 @@
import { DataTypes } from 'sequelize'; import { DataTypes } from 'sequelize';
export default (sequelize) => { import sequelize from './orm';
sequelize.define(
'device_authorised_users', const DeviceAuthorisedUsers = sequelize.define('device_authorised_users', {
{ id: {
id: { allowNull: false,
allowNull: false, autoIncrement: true,
autoIncrement: true, primaryKey: true,
primaryKey: true, type: DataTypes.INTEGER,
type: DataTypes.INTEGER, },
}, account_id: {
account_id: { allowNull: false,
allowNull: false, type: DataTypes.INTEGER,
type: DataTypes.INTEGER, },
}, device_id: {
device_id: { allowNull: true,
allowNull: true, type: DataTypes.INTEGER,
type: DataTypes.INTEGER, },
}, athena: {
athena: { allowNull: true,
allowNull: true, type: DataTypes.BOOLEAN,
type: DataTypes.BOOLEAN, },
}, unpair: {
unpair: { allowNull: true,
allowNull: true, type: DataTypes.BOOLEAN,
type: DataTypes.BOOLEAN, },
}, view_drives: {
view_drives: { allowNull: true,
allowNull: true, type: DataTypes.BOOLEAN,
type: DataTypes.BOOLEAN, },
}, created_at: {
created_at: { allowNull: true,
allowNull: true, type: DataTypes.BIGINT,
type: DataTypes.BIGINT, },
}, }, {
}, timestamps: false,
{ });
timestamps: false,
}, export default DeviceAuthorisedUsers;
);
};

View File

@ -1,66 +1,64 @@
import { DataTypes } from 'sequelize'; import { DataTypes } from 'sequelize';
export default (sequelize) => { import sequelize from './orm';
sequelize.define(
'device', const Devices = sequelize.define('device', {
{ id: {
id: { allowNull: false,
allowNull: false, autoIncrement: true,
autoIncrement: true, primaryKey: true,
primaryKey: true, type: DataTypes.INTEGER,
type: DataTypes.INTEGER, },
}, dongle_id: {
dongle_id: { allowNull: false,
allowNull: false, type: DataTypes.TEXT,
type: DataTypes.TEXT, },
}, account_id: {
account_id: { allowNull: true,
allowNull: true, type: DataTypes.INTEGER,
type: DataTypes.INTEGER, },
}, imei: {
imei: { allowNull: true,
allowNull: true, type: DataTypes.TEXT,
type: DataTypes.TEXT, },
}, serial: {
serial: { allowNull: true,
allowNull: true, type: DataTypes.TEXT,
type: DataTypes.TEXT, },
}, device_type: {
device_type: { allowNull: true,
allowNull: true, type: DataTypes.TEXT,
type: DataTypes.TEXT, },
}, public_key: {
public_key: { allowNull: true,
allowNull: true, type: DataTypes.TEXT,
type: DataTypes.TEXT, },
}, created: {
created: { allowNull: true,
allowNull: true, type: DataTypes.BIGINT,
type: DataTypes.BIGINT, },
}, last_ping: {
last_ping: { allowNull: true,
allowNull: true, type: DataTypes.BIGINT,
type: DataTypes.BIGINT, },
}, storage_used: {
storage_used: { allowNull: true,
allowNull: true, type: DataTypes.INTEGER,
type: DataTypes.INTEGER, },
}, max_storage: {
max_storage: { allowNull: true,
allowNull: true, type: DataTypes.INTEGER,
type: DataTypes.INTEGER, },
}, ignore_uploads: {
ignore_uploads: { allowNull: true,
allowNull: true, type: DataTypes.BOOLEAN,
type: DataTypes.BOOLEAN, },
}, nickname: {
nickname: { allowNull: true,
allowNull: true, type: DataTypes.TEXT,
type: DataTypes.TEXT, },
}, }, {
}, timestamps: false,
{ });
timestamps: false,
}, export default Devices;
);
};

View File

@ -1,58 +1,56 @@
import { DataTypes } from 'sequelize'; import { DataTypes } from 'sequelize';
export default (sequelize) => { import sequelize from './orm';
sequelize.define(
'drive_segments', const DriveSegments = sequelize.define('drive_segments', {
{ id: {
id: { allowNull: false,
allowNull: false, autoIncrement: true,
autoIncrement: true, primaryKey: true,
primaryKey: true, type: DataTypes.INTEGER,
type: DataTypes.INTEGER, },
}, segment_id: {
segment_id: { allowNull: false,
allowNull: false, type: DataTypes.INTEGER,
type: DataTypes.INTEGER, },
}, drive_identifier: {
drive_identifier: { allowNull: true,
allowNull: true, type: DataTypes.TEXT,
type: DataTypes.TEXT, },
}, dongle_id: {
dongle_id: { allowNull: true,
allowNull: true, type: DataTypes.TEXT,
type: DataTypes.TEXT, },
}, duration: {
duration: { allowedNull: true,
allowedNull: true, type: DataTypes.INTEGER,
type: DataTypes.INTEGER, },
}, distance_meters: {
distance_meters: { allowNull: true,
allowNull: true, type: DataTypes.INTEGER,
type: DataTypes.INTEGER, },
}, upload_complete: {
upload_complete: { allowNull: true,
allowNull: true, type: DataTypes.BOOLEAN,
type: DataTypes.BOOLEAN, },
}, is_processed: {
is_processed: { allowNull: true,
allowNull: true, type: DataTypes.BOOLEAN,
type: DataTypes.BOOLEAN, },
}, is_stalled: {
is_stalled: { allowNull: true,
allowNull: true, type: DataTypes.BOOLEAN,
type: DataTypes.BOOLEAN, },
}, created: {
created: { allowNull: true,
allowNull: true, type: DataTypes.BIGINT,
type: DataTypes.BIGINT, },
}, process_attempts: {
process_attempts: { allowNull: true,
allowNull: true, type: DataTypes.INTEGER,
type: DataTypes.INTEGER, },
}, }, {
}, timestamps: false,
{ });
timestamps: false,
}, export default DriveSegments;
);
};

View File

@ -1,78 +1,76 @@
import { DataTypes } from 'sequelize'; import { DataTypes } from 'sequelize';
export default (sequelize) => { import sequelize from './orm';
sequelize.define(
'drives', const Drives = sequelize.define('drives', {
{ id: {
id: { allowNull: false,
allowNull: false, autoIncrement: true,
autoIncrement: true, primaryKey: true,
primaryKey: true, type: DataTypes.INTEGER,
type: DataTypes.INTEGER, },
}, identifier: {
identifier: { allowNull: true,
allowNull: true, type: DataTypes.TEXT,
type: DataTypes.TEXT, },
}, dongle_id: {
dongle_id: { allowNull: true,
allowNull: true, type: DataTypes.TEXT,
type: DataTypes.TEXT, },
}, max_segment: {
max_segment: { allowNull: true,
allowNull: true, type: DataTypes.INTEGER,
type: DataTypes.INTEGER, },
}, upload_complete: {
upload_complete: { allowedNull: true,
allowedNull: true, type: DataTypes.BOOLEAN,
type: DataTypes.BOOLEAN, },
}, duration: {
duration: { allowNull: true,
allowNull: true, type: DataTypes.INTEGER,
type: DataTypes.INTEGER, },
}, distance_meters: {
distance_meters: { allowNull: true,
allowNull: true, type: DataTypes.INTEGER,
type: DataTypes.INTEGER, },
}, filesize: {
filesize: { allowNull: true,
allowNull: true, type: DataTypes.INTEGER,
type: DataTypes.INTEGER, },
}, is_processed: {
is_processed: { allowNull: true,
allowNull: true, type: DataTypes.BOOLEAN,
type: DataTypes.BOOLEAN, },
}, created: {
created: { allowNull: true,
allowNull: true, type: DataTypes.BIGINT,
type: DataTypes.BIGINT, },
}, last_upload: {
last_upload: { allowNull: true,
allowNull: true, type: DataTypes.BIGINT,
type: DataTypes.BIGINT, },
}, is_preserved: {
is_preserved: { allowNull: true,
allowNull: true, type: DataTypes.BOOLEAN,
type: DataTypes.BOOLEAN, },
}, is_deleted: {
is_deleted: { allowNull: true,
allowNull: true, type: DataTypes.BOOLEAN,
type: DataTypes.BOOLEAN, },
}, drive_date: {
drive_date: { allowNull: true,
allowNull: true, type: DataTypes.BIGINT,
type: DataTypes.BIGINT, },
}, is_physically_removed: {
is_physically_removed: { allowNull: true,
allowNull: true, type: DataTypes.BOOLEAN,
type: DataTypes.BOOLEAN, },
}, metadata: {
metadata: { allowNull: true,
allowNull: true, type: DataTypes.TEXT,
type: DataTypes.TEXT, },
}, }, {
}, timestamps: false,
{ });
timestamps: false,
}, export default Drives;
);
};

View File

@ -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,
};

View File

@ -1,42 +1,40 @@
import { DataTypes } from 'sequelize'; import { DataTypes } from 'sequelize';
export default (sequelize) => { import sequelize from './orm';
sequelize.define(
'oauth_accounts', const OAuthAccounts = sequelize.define('oauth_accounts', {
{ id: {
id: { id: false,
id: false, autoIncrement: true,
autoIncrement: true, primaryKey: true,
primaryKey: true, type: DataTypes.INTEGER,
type: DataTypes.INTEGER, },
}, account_id: {
account_id: { allowNull: false,
allowNull: false, type: DataTypes.INTEGER,
type: DataTypes.INTEGER, },
}, email: {
email: { allowNull: false,
allowNull: false, type: DataTypes.TEXT,
type: DataTypes.TEXT, },
}, created: {
created: { allowNull: true,
allowNull: true, type: DataTypes.TIME,
type: DataTypes.TIME, },
}, last_used: {
last_used: { allowNull: true,
allowNull: true, type: DataTypes.CHAR,
type: DataTypes.CHAR, },
}, refresh: {
refresh: { allowNull: true,
allowNull: true, type: DataTypes.TEXT,
type: DataTypes.TEXT, },
}, provider: {
provider: { allowNull: true,
allowNull: true, type: DataTypes.TEXT,
type: DataTypes.TEXT, },
}, }, {
}, timestamps: false,
{ });
timestamps: false,
}, export default OAuthAccounts;
);
};

View File

@ -1,6 +1,3 @@
/* eslint-disable no-restricted-syntax */
/* eslint-disable global-require */
import { Sequelize } from 'sequelize'; import { Sequelize } from 'sequelize';
const sequelize = new Sequelize({ const sequelize = new Sequelize({
@ -14,21 +11,6 @@ const sequelize = new Sequelize({
sequelize.options.logging = () => {}; 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 * Synchronise the database (create new tables) to match the models defined
* above. * above.

View File

@ -1,11 +1,7 @@
import orm from '../../models/index.model';
// TODO move everythijng away from this dumb intertwined style // 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 authentication from './authentication';
import { Accounts } from '../../models';
async function isCurrentUserAdmin(hardFail, req) { async function isCurrentUserAdmin(hardFail, req) {
const account = await authentication.getAuthenticatedAccount(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 } }; return { success: false, status: 400, data: { bad_data: true } };
} }
await orm.models.accounts.update( await Accounts.update(
{ banned: cleanBan ? 1 : 0 }, { banned: cleanBan ? 1 : 0 },
{ where: { id: userId } }, { 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) { if (verify.dataValues && verify.dataValues.banned === cleanBan ? 1 : 0) {
return { success: true, status: 200, data: { banned: ban } }; return { success: true, status: 200, data: { banned: ban } };
} }

View File

@ -1,7 +1,8 @@
import crypto from 'crypto'; import crypto from 'crypto';
import jsonwebtoken from 'jsonwebtoken'; import jsonwebtoken from 'jsonwebtoken';
import log4js from 'log4js'; import log4js from 'log4js';
import orm from '../../../models/index.model';
import { Accounts } from '../../../models';
const logger = log4js.getLogger('default'); const logger = log4js.getLogger('default');
@ -24,38 +25,44 @@ export async function readJWT(token) {
} }
async function signIn(email, password) { 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) { if (!account || !account.dataValues) {
account = account.dataValues; return { success: false, msg: 'BAD ACCOUNT', badAccount: true };
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 };
} }
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) { async function changePassword(account, newPassword, oldPassword) {
if (!account || !newPassword || !oldPassword) { if (!account || !newPassword || !oldPassword) {
return { success: false, error: 'MISSING_DATA' }; return { success: false, error: 'MISSING_DATA' };
} }
const oldPasswordHash = crypto.createHash('sha256').update(oldPassword + process.env.APP_SALT).digest('hex'); const oldPasswordHash = crypto.createHash('sha256').update(oldPassword + process.env.APP_SALT).digest('hex');
if (account.password !== oldPasswordHash) {
if (account.password === oldPasswordHash) { return { success: false, msg: 'BAD PASSWORD', passwordCorrect: false };
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 };
} }
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'] } }; query = { ...query, attributes: { exclude: ['password', '2fa_token', 'session_seed'] } };
} }
const account = await orm.models.accounts.findOne(query); const account = await Accounts.findOne(query);
if (!account.dataValues) { if (!account || !account.dataValues) {
return null; // {success: false, isInvalid: true} return null; // {success: false, isInvalid: true}
} }
try { try {
await orm.models.accounts.update( await Accounts.update(
{ last_ping: Date.now() }, { last_ping: Date.now() },
{ where: { id: account.id } }, { where: { id: account.id } },
); );

View File

@ -45,11 +45,11 @@ export async function getToken(code, scope) {
return { error: true, ...AUTH_OAUTH_ERR_GOOGLE_FAILED_TOKEN_FETCH }; 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); const id = jsonwebtoken.decode(accessToken.token.id_token);
logger.log(`jsonwebtoken.${id}`); logger.info(`jsonwebtoken.${id}`);
return id; return id;
} }

View File

@ -1,4 +1,6 @@
import { generateSecret, verify } from '2fa-util'; import { generateSecret, verify } from '2fa-util';
import { Accounts } from '../../../models';
import { import {
AUTH_2FA_BAD_ACCOUNT, AUTH_2FA_BAD_ACCOUNT,
AUTH_2FA_ONBOARD_ALREADY_ENROLLED, AUTH_2FA_ONBOARD_ALREADY_ENROLLED,
@ -6,7 +8,6 @@ import {
AUTH_2FA_ENROLLED, AUTH_2FA_ENROLLED,
AUTH_2FA_BAD_TOKEN, AUTH_2FA_BAD_TOKEN,
} from '../../consistency/terms'; } from '../../consistency/terms';
import orm from '../../../models/index.model';
export async function twoFactorOnboard(account) { export async function twoFactorOnboard(account) {
if (!account || !account.dataValues) { return { success: false, ...AUTH_2FA_BAD_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); const token = await generateSecret(account.email, process.env.AUTH_2FA_ISSUER);
orm.models.account.update( await Accounts.update(
{ '2fa_token': token.secret }, { '2fa_token': token.secret },
{ id: account.id }, { id: account.id },
); );
@ -24,30 +25,26 @@ export async function twoFactorOnboard(account) {
export async function twoFactorConfirm(account, token) { export async function twoFactorConfirm(account, token) {
const isTokenValid = await verifyTwoFactor(account.id, token); const isTokenValid = await verifyTwoFactor(account.id, token);
if (!isTokenValid) {
if (isTokenValid) { return { success: false, ...AUTH_2FA_BAD_TOKEN };
orm.models.account.update(
{ two_factor_enabled: true },
{ id: account.id },
);
return {
success: true,
...AUTH_2FA_ENROLLED,
};
} }
return {
success: false, await Accounts.update(
...AUTH_2FA_BAD_TOKEN, { two_factor_enabled: true },
}; { id: account.id },
);
return { success: true, ...AUTH_2FA_ENROLLED };
} }
export async function verifyTwoFactor(account, token) { export async function verifyTwoFactor(account, token) {
if (!account || !account.dataValues) { return { success: false, ...AUTH_2FA_BAD_ACCOUNT }; } if (!account || !account.dataValues) {
if (account['2fa_token'] !== null) return { success: false, ...AUTH_2FA_NOT_ENROLLED }; 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 verify(token, account['2fa_token']).catch(console.log);
return result;
} }
export default null; export default null;

View File

@ -2,8 +2,8 @@ import sanitizeFactory from 'sanitize';
import crypto from 'crypto'; import crypto from 'crypto';
import dirTree from 'directory-tree'; import dirTree from 'directory-tree';
import log4js from 'log4js'; import log4js from 'log4js';
import orm from '../../models/index.model';
import { Devices } from '../../models';
import { readJWT, validateJWT } from './authentication'; import { readJWT, validateJWT } from './authentication';
import { getAccountFromId } from './users'; import { getAccountFromId } from './users';
@ -23,14 +23,14 @@ async function pairDevice(account, qrString) {
if (qrString.indexOf('--') >= 0) { if (qrString.indexOf('--') >= 0) {
const [, serial, pairToken] = qrCodeParts; const [, serial, pairToken] = qrCodeParts;
device = await orm.models.device.findOne({ where: { serial } }); device = await Devices.findOne({ where: { serial } });
pairJWT = pairToken; pairJWT = pairToken;
} else { } else {
const data = await readJWT(qrString); const data = await readJWT(qrString);
if (!data || !data.pair) { if (!data || !data.pair) {
return { success: false, noPair: true }; 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; pairJWT = qrString;
} }
@ -50,12 +50,12 @@ async function pairDevice(account, qrString) {
} }
async function pairDeviceToAccountId(dongleId, accountId) { async function pairDeviceToAccountId(dongleId, accountId) {
await orm.models.device.update( await Devices.update(
{ account_id: accountId }, { account_id: accountId },
{ where: { dongle_id: dongleId } }, { where: { dongle_id: dongleId } },
); );
const check = await orm.models.device.findOne( const check = await Devices.findOne(
{ where: { dongle_id: dongleId, account_id: accountId } }, { where: { dongle_id: dongleId, account_id: accountId } },
); );
if (check.dataValues) { if (check.dataValues) {
@ -67,12 +67,12 @@ async function pairDeviceToAccountId(dongleId, accountId) {
} }
async function unpairDevice(account, dongleId) { 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 } }, { where: { account_id: account.id, dongle_id: dongleId } },
); );
if (device && device.dataValues) { if (device && device.dataValues) {
await orm.models.device.update( await Devices.update(
{ account_id: 0 }, { account_id: 0 },
{ where: { dongle_id: dongleId } }, { where: { dongle_id: dongleId } },
); );
@ -82,14 +82,14 @@ async function unpairDevice(account, dongleId) {
} }
async function setDeviceNickname(account, dongleId, nickname) { 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 } }, { where: { account_id: account.id, dongle_id: dongleId } },
); );
const cleanNickname = sanitize.value(nickname, 'string'); const cleanNickname = sanitize.value(nickname, 'string');
if (device && device.dataValues) { if (device && device.dataValues) {
await orm.models.device.update( await Devices.update(
{ nickname: cleanNickname }, { nickname: cleanNickname },
{ where: { dongle_id: dongleId } }, { where: { dongle_id: dongleId } },
); );
@ -99,12 +99,12 @@ async function setDeviceNickname(account, dongleId, nickname) {
} }
async function getDevices(accountId) { async function getDevices(accountId) {
return orm.models.device.findAll({ where: { account_id: accountId } }); return Devices.findAll({ where: { account_id: accountId } });
} }
async function getDeviceFromDongle(dongleId) { async function getDeviceFromDongle(dongleId) {
if (!dongleId) return null; 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) { if (!devices || !devices.dataValues) {
return null; return null;
} }
@ -113,7 +113,7 @@ async function getDeviceFromDongle(dongleId) {
// TODO combine these redundant functions into one // TODO combine these redundant functions into one
async function getDeviceFromSerial(serial) { async function getDeviceFromSerial(serial) {
if (!serial) return null; if (!serial) return null;
const devices = await orm.models.device.findOne({ where: { serial } }); const devices = await Devices.findOne({ where: { serial } });
if (!devices || !devices.dataValues) { if (!devices || !devices.dataValues) {
return null; return null;
} }
@ -123,7 +123,7 @@ async function getDeviceFromSerial(serial) {
async function updateDevice(dongleId, data) { async function updateDevice(dongleId, data) {
if (!dongleId) return null; 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) { async function setIgnoredUploads(dongleId, isIgnored) {
@ -137,11 +137,11 @@ async function setIgnoredUploads(dongleId, isIgnored) {
} }
async function getAllDevicesFiltered() { async function getAllDevicesFiltered() {
return orm.models.device.findAll(); return Devices.findAll();
} }
async function updateLastPing(deviceId) { async function updateLastPing(deviceId) {
return orm.models.device.update( return Devices.update(
{ last_ping: Date.now() }, { last_ping: Date.now() },
{ where: { [Op.or]: [{ id: deviceId }, { dongle_id: deviceId }] } }, { where: { [Op.or]: [{ id: deviceId }, { dongle_id: deviceId }] } },
); );
@ -196,7 +196,7 @@ async function getDrives(dongleId, includeDeleted, includeMeta) {
async function getDrive(identifier) { async function getDrive(identifier) {
const drive = await orm.models.drives.findOne({ where: { identifier } }); const drive = await orm.models.drives.findOne({ where: { identifier } });
logger.log(drive); logger.info(drive);
if (drive.dataValues) return drive.dataValues; if (drive.dataValues) return drive.dataValues;
return null; return null;
@ -274,7 +274,7 @@ async function updateOrCreateDrive(dongleId, identifier, data) {
logger.info('updateOrCreate Drive', dongleId, identifier, data); logger.info('updateOrCreate Drive', dongleId, identifier, data);
const check = await orm.models.drives.findOne({ where: { dongle_id: dongleId, identifier } }); 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) { if (check) {
return orm.models.drives.update( return orm.models.drives.update(
@ -322,7 +322,7 @@ async function getDriveSegment(driveName, segment) {
} }
async function createDongle(dongleId, accountId, imei, serial, publicKey) { async function createDongle(dongleId, accountId, imei, serial, publicKey) {
return orm.models.device.create({ return Devices.create({
dongle_id: dongleId, dongle_id: dongleId,
account_id: 0, account_id: 0,
imei, imei,

View File

@ -1,24 +1,25 @@
import crypto from 'crypto'; import crypto from 'crypto';
import log4js from 'log4js'; import log4js from 'log4js';
import orm from '../../models/index.model';
import { Accounts } from '../../models';
const logger = log4js.getLogger('default'); const logger = log4js.getLogger('default');
export async function getAccountFromId(id) { export async function getAccountFromId(id) {
return orm.models.accounts.findByPk(id); return Accounts.findByPk(id);
} }
export async function getAccountFromEmail(email) { export async function getAccountFromEmail(email) {
if (!email) return null; if (!email) return null;
const account = orm.models.accounts.findOne({ where: { email } }); const account = Accounts.findOne({ where: { email } });
if (account.dataValues) return account.dataValues; if (account.dataValues) return account.dataValues;
return null; return null;
} }
export async function createBaseAccount() { export async function createBaseAccount() {
await orm.models.accounts.create({ await Accounts.create({
id: 0, id: 0,
email: 'dummy@retropilot.org', email: 'dummy@retropilot.org',
password: '123123', password: '123123',
@ -31,8 +32,8 @@ export async function createBaseAccount() {
} }
export async function _dirtyCreateAccount(email, password, created, admin) { export async function _dirtyCreateAccount(email, password, created, admin) {
logger.log('creating acount: ', email, password, created, admin); logger.info('creating account: ', email, password, created, admin);
return orm.models.accounts.create({ return Accounts.create({
email, password, created, admin, 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'); 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'); 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) { if (account != null && account.dataValues != null) {
return { success: true, status: 409, data: { alreadyRegistered: true } }; return { success: true, status: 409, data: { alreadyRegistered: true } };
} }
await orm.models.accounts.create({ await Accounts.create({
email, email,
password, password,
created: Date.now(), created: Date.now(),
@ -61,7 +62,7 @@ export async function createAccount(email, password) {
email_verify_token: emailToken, 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) { if (didAccountRegister != null && didAccountRegister.dataValues != null) {
return { success: true, status: 200 }; return { success: true, status: 200 };
@ -76,7 +77,7 @@ export async function verifyEmailToken(token) {
return { success: false, status: 400, data: { missingToken: true } }; 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 } }, { where: { email_verify_token: token } },
); );
@ -87,7 +88,7 @@ export async function verifyEmailToken(token) {
return { success: true, status: 409, data: { alreadyVerified: true } }; return { success: true, status: 409, data: { alreadyVerified: true } };
} }
await orm.models.accounts.update( await Accounts.update(
{ verified: true }, { verified: true },
{ where: { id: account.id } }, { where: { id: account.id } },
); );
@ -96,7 +97,7 @@ export async function verifyEmailToken(token) {
} }
export async function getAllUsers() { 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 { export default {

View File

@ -270,8 +270,8 @@ async function upload(req, res) {
logger.warn("drive failed to make", err) logger.warn("drive failed to make", err)
}) })
logger.log("drive value", drive) logger.info("drive value", drive)
logger.log("drive name:", driveName) logger.info("drive name:", driveName)
if (drive === undefined || drive === null) { if (drive === undefined || drive === null) {
logger.info("CREATING NEW DRIVE") logger.info("CREATING NEW DRIVE")

View File

@ -24,13 +24,13 @@ async function isAuthenticated(req, res, next) {
} }
router.get('/authentication/oauth/callback', async (req, res) => { 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)); res.json(await getToken(req.query.code, req.query.scope));
}); });
router.get('/authentication/oauth/:provider', async (req, res) => { router.get('/authentication/oauth/:provider', async (req, res) => {
const { provider } = req.params; const { provider } = req.params;
logger.log('provider', provider); logger.info('provider', provider);
let url; let url;
switch (provider) { switch (provider) {
case 'google': case 'google':

View File

@ -54,7 +54,7 @@ router.put('/retropilot/0/device/:dongle_id/', [isAuthenticated, bodyParser.json
} }
const { body } = req; const { body } = req;
logger.log(MutateDevice.isValid(body)); logger.info(MutateDevice.isValid(body));
// TODO: response? // TODO: response?
return res.json({ success: true }); return res.json({ success: true });
}); });

View File

@ -1,12 +1,11 @@
import express from 'express'; 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 deviceController from '../../controllers/devices';
import models from '../../../models/index.model';
/* eslint-enable no-unused-vars */
const router = express.Router(); const router = express.Router();
const whitelistParams = { const whitelistParams = {
getmessage: true, getmessage: true,
getversion: 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 }, where: { device_id: device.id },
})); }));
}); });

View File

@ -35,7 +35,7 @@ if(process.env.NODE_ENV === 'development') {
router.post('/useradmin/auth', bodyParser.urlencoded({ extended: true }), runAsyncWrapper(async (req, res) => { router.post('/useradmin/auth', bodyParser.urlencoded({ extended: true }), runAsyncWrapper(async (req, res) => {
const signIn = await authenticationController.signIn(req.body.email, req.body.password); const signIn = await authenticationController.signIn(req.body.email, req.body.password);
logger.log(signIn); logger.info(signIn);
if (signIn.success) { if (signIn.success) {
res.cookie('jwt', signIn.jwt); res.cookie('jwt', signIn.jwt);
@ -134,14 +134,15 @@ router.post('/useradmin/register/token', bodyParser.urlencoded({ extended: true
Date.now(), Date.now(),
false, false,
); );
} catch(error) { } catch (error) {
console.error(error); console.error('error creating account', error);
} }
logger.log(result); logger.debug('created account:', result);
if (result.dataValues) { 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')}`); return res.redirect(`/useradmin?status=${encodeURIComponent('Successfully registered')}`);
} }

View File

@ -1,6 +1,7 @@
/* eslint-disable no-underscore-dangle */ /* eslint-disable no-underscore-dangle */
import { v4 as uuid } from 'uuid'; import { v4 as uuid } from 'uuid';
import orm from '../../../models/index.model';
import { AthenaReturnedData } from '../../../models';
let realtime; let realtime;
let wss; 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); 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, device_id: websocket.device_id,
type: command, type: command,
created_at: Date.now(), created_at: Date.now(),
@ -47,7 +48,9 @@ function isDeviceConnected(accountId, deviceId, dongleId) {
const websocket = wss.retropilotFunc.findFromDongle(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); 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 }; return { connected: true, heartbeat: websocket.heartbeat };
} }

View File

@ -6,7 +6,7 @@ import httpServer from 'http';
import { readFileSync } from 'fs'; import { readFileSync } from 'fs';
import log4js from 'log4js'; import log4js from 'log4js';
import models from '../../../models/index.model'; import { AthenaActionLog, AthenaReturnedData } from '../../../models';
import deviceController from '../../controllers/devices'; import deviceController from '../../controllers/devices';
import helperFunctions from './helpers'; 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({ 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), data: JSON.stringify(json),
resolved_at: Date.now(), resolved_at: Date.now(),
}, { where: { device_id: ws.device_id, uuid: json.id } })); }, { where: { device_id: ws.device_id, uuid: json.id } }));
@ -164,7 +164,7 @@ wss.retropilotFunc = {
/* eslint-disable camelcase */ /* eslint-disable camelcase */
actionLogger: async (account_id, device_id, action, user_ip, device_ip, meta, dongle_id) => { 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, account_id, device_id, action, user_ip, device_ip, meta, created_at: Date.now(), dongle_id,
}); });
}, },

View File

@ -8,7 +8,7 @@ import Reader from '@commaai/log_reader';
import ffprobe from 'ffprobe'; import ffprobe from 'ffprobe';
import ffprobeStatic from 'ffprobe-static'; import ffprobeStatic from 'ffprobe-static';
import orm from '../models/index.model'; import orm from '../models/orm';
import { import {
initializeStorage, initializeStorage,
deleteFolderRecursive, deleteFolderRecursive,