Commit f4cd2c51 authored by Antoine's avatar Antoine
Browse files

[server] Force the declaration of variable with const, when the variable is not reassigned.

parent 09e30d57
Pipeline #294382 passed with stages
in 4 minutes and 56 seconds
......@@ -31,7 +31,10 @@
# 'plugin:@typescript-eslint/recommended' sets it to "warn"
'@typescript-eslint/no-unused-vars':
- 2
- files: 'server/**/*.js'
rules:
prefer-const:
- 2
rules:
prettier/prettier:
......
......@@ -10,13 +10,13 @@ import { isDemoEnabled } from './settings';
import { asyncErr, getErrorCode, KError, makeLogger } from '../helpers';
import { checkHasAllFields, checkAllowedFields } from '../shared/validators';
let log = makeLogger('controllers/accesses');
const log = makeLogger('controllers/accesses');
// Preloads a bank access (sets @access).
export async function preloadAccess(req, res, next, accessId) {
try {
let { id: userId } = req.user;
let access = await Access.find(userId, accessId);
const { id: userId } = req.user;
const access = await Access.find(userId, accessId);
if (!access) {
throw new KError('bank access not found', 404);
}
......@@ -37,7 +37,7 @@ export async function destroyWithData(userId, access) {
// Destroy a given access, including accounts, alerts and operations.
export async function destroy(req, res) {
try {
let {
const {
user: { id: userId }
} = req;
......@@ -53,7 +53,7 @@ export async function destroy(req, res) {
}
export async function createAndRetrieveData(userId, params) {
let error =
const error =
checkHasAllFields(params, ['vendorId', 'login', 'password']) ||
checkAllowedFields(params, ['vendorId', 'login', 'password', 'fields', 'customLabel']);
if (error) {
......@@ -64,7 +64,7 @@ export async function createAndRetrieveData(userId, params) {
try {
access = await Access.create(userId, params);
await accountManager.retrieveAndAddAccountsByAccess(userId, access, /* interactive */ true);
let { accounts, newOperations } = await accountManager.retrieveOperationsByAccess(
const { accounts, newOperations } = await accountManager.retrieveOperationsByAccess(
userId,
access,
/* ignoreLastFetchDate */ false,
......@@ -93,7 +93,7 @@ export async function createAndRetrieveData(userId, params) {
// password)), and retrieves its accounts and operations.
export async function create(req, res) {
try {
let {
const {
user: { id: userId }
} = req;
......@@ -111,16 +111,16 @@ export async function create(req, res) {
// Fetch operations using the backend and return the operations to the client.
export async function fetchOperations(req, res) {
try {
let { id: userId } = req.user;
let access = req.preloaded.access;
let bankVendor = bankVendorByUuid(access.vendorId);
const { id: userId } = req.user;
const access = req.preloaded.access;
const bankVendor = bankVendorByUuid(access.vendorId);
if (!access.isEnabled() || bankVendor.deprecated) {
let errcode = getErrorCode('DISABLED_ACCESS');
const errcode = getErrorCode('DISABLED_ACCESS');
throw new KError('disabled access', 403, errcode);
}
let { accounts, newOperations } = await accountManager.retrieveOperationsByAccess(
const { accounts, newOperations } = await accountManager.retrieveOperationsByAccess(
userId,
access,
/* ignoreLastFetchDate */ false,
......@@ -140,18 +140,18 @@ export async function fetchOperations(req, res) {
// return both to the client.
export async function fetchAccounts(req, res) {
try {
let { id: userId } = req.user;
let access = req.preloaded.access;
let bankVendor = bankVendorByUuid(access.vendorId);
const { id: userId } = req.user;
const access = req.preloaded.access;
const bankVendor = bankVendorByUuid(access.vendorId);
if (!access.isEnabled() || bankVendor.deprecated) {
let errcode = getErrorCode('DISABLED_ACCESS');
const errcode = getErrorCode('DISABLED_ACCESS');
throw new KError('disabled access', 403, errcode);
}
await accountManager.retrieveAndAddAccountsByAccess(userId, access, /* interactive */ true);
let { accounts, newOperations } = await accountManager.retrieveOperationsByAccess(
const { accounts, newOperations } = await accountManager.retrieveOperationsByAccess(
userId,
access,
/* ignoreLastFetchDate */ true,
......@@ -171,7 +171,7 @@ export async function fetchAccounts(req, res) {
// any regular poll.
export async function poll(req, res) {
try {
let { id: userId } = req.user;
const { id: userId } = req.user;
await fullPoll(userId);
res.status(200).json({
status: 'OK'
......@@ -188,12 +188,12 @@ export async function poll(req, res) {
// Updates a bank access.
export async function update(req, res) {
try {
let { id: userId } = req.user;
let { access } = req.preloaded;
const { id: userId } = req.user;
const { access } = req.preloaded;
let attrs = req.body;
const attrs = req.body;
let error = checkAllowedFields(attrs, ['enabled', 'customLabel']);
const error = checkAllowedFields(attrs, ['enabled', 'customLabel']);
if (error) {
throw new KError(`when updating an access: ${error}`, 400);
}
......@@ -216,22 +216,22 @@ export async function update(req, res) {
export async function updateAndFetchAccounts(req, res) {
try {
let { id: userId } = req.user;
let { access } = req.preloaded;
const { id: userId } = req.user;
const { access } = req.preloaded;
let attrs = req.body;
const attrs = req.body;
let error = checkAllowedFields(attrs, ['login', 'password', 'fields']);
const error = checkAllowedFields(attrs, ['login', 'password', 'fields']);
if (error) {
throw new KError(`when updating and polling an access: ${error}`, 400);
}
if (typeof attrs.fields !== 'undefined') {
let newFields = attrs.fields;
const newFields = attrs.fields;
delete attrs.fields;
for (let { name, value } of newFields) {
let previous = access.fields.find(existing => existing.name === name);
for (const { name, value } of newFields) {
const previous = access.fields.find(existing => existing.name === name);
if (value === null) {
// Delete the custom field if necessary.
if (typeof previous !== 'undefined') {
......
......@@ -5,13 +5,13 @@ import accountManager from '../lib/accounts-manager';
import { isDemoEnabled } from './settings';
let log = makeLogger('controllers/accounts');
const log = makeLogger('controllers/accounts');
// Prefills the @account field with a queried bank account.
export async function preloadAccount(req, res, next, accountID) {
try {
let { id: userId } = req.user;
let account = await Account.find(userId, accountID);
const { id: userId } = req.user;
const account = await Account.find(userId, accountID);
if (!account) {
throw new KError('Bank account not found', 404);
}
......@@ -23,9 +23,9 @@ export async function preloadAccount(req, res, next, accountID) {
}
export async function fixupDefaultAccount(userId) {
let found = await Setting.findOrCreateDefault(userId, 'default-account-id');
const found = await Setting.findOrCreateDefault(userId, 'default-account-id');
if (found && found.value !== '') {
let accountFound = await Account.find(userId, found.value);
const accountFound = await Account.find(userId, found.value);
if (!accountFound) {
log.info(
"-> Removing the default account setting since the account doesn't exist anymore."
......@@ -45,7 +45,7 @@ export async function destroyWithOperations(userId, account) {
await fixupDefaultAccount(userId);
let accounts = await Account.byAccess(userId, { id: account.accessId });
const accounts = await Account.byAccess(userId, { id: account.accessId });
if (accounts && accounts.length === 0) {
log.info('\t-> No other accounts bound: destroying access.');
await Access.destroy(userId, account.accessId);
......@@ -54,16 +54,16 @@ export async function destroyWithOperations(userId, account) {
export async function update(req, res) {
try {
let { id: userId } = req.user;
const { id: userId } = req.user;
let newFields = req.body;
let error = checkAllowedFields(newFields, ['excludeFromBalance', 'customLabel']);
const newFields = req.body;
const error = checkAllowedFields(newFields, ['excludeFromBalance', 'customLabel']);
if (error) {
throw new KError(`when updating an account: ${error}`, 400);
}
let account = req.preloaded.account;
let newAccount = await Account.update(userId, account.id, newFields);
const account = req.preloaded.account;
const newAccount = await Account.update(userId, account.id, newFields);
res.status(200).json(newAccount);
} catch (err) {
return asyncErr(res, err, 'when updating an account');
......@@ -73,7 +73,7 @@ export async function update(req, res) {
// Delete account, operations and alerts.
export async function destroy(req, res) {
try {
let { id: userId } = req.user;
const { id: userId } = req.user;
if (await isDemoEnabled(userId)) {
throw new KError("account deletion isn't allowed in demo mode", 400);
......@@ -88,9 +88,9 @@ export async function destroy(req, res) {
export async function resyncBalance(req, res) {
try {
let { id: userId } = req.user;
let account = req.preloaded.account;
let updatedAccount = await accountManager.resyncAccountBalance(
const { id: userId } = req.user;
const account = req.preloaded.account;
const updatedAccount = await accountManager.resyncAccountBalance(
userId,
account,
/* interactive */ true
......
......@@ -4,8 +4,8 @@ import { checkAlert } from '../shared/validators';
export async function loadAlert(req, res, next, alertId) {
try {
let { id: userId } = req.user;
let alert = await Alert.find(userId, alertId);
const { id: userId } = req.user;
const alert = await Alert.find(userId, alertId);
if (!alert) {
throw new KError('bank alert not found', 404);
}
......@@ -19,9 +19,9 @@ export async function loadAlert(req, res, next, alertId) {
export async function create(req, res) {
try {
let { id: userId } = req.user;
const { id: userId } = req.user;
let newAlert = req.body;
const newAlert = req.body;
if (
!newAlert ||
typeof newAlert.accountId !== 'number' ||
......@@ -30,17 +30,17 @@ export async function create(req, res) {
throw new KError('missing parameters', 400);
}
let validationError = checkAlert(newAlert);
const validationError = checkAlert(newAlert);
if (validationError) {
throw new KError(validationError, 400);
}
let account = await Account.find(userId, newAlert.accountId);
const account = await Account.find(userId, newAlert.accountId);
if (!account) {
throw new KError('bank account not found', 404);
}
let alert = await Alert.create(userId, newAlert);
const alert = await Alert.create(userId, newAlert);
res.status(201).json(alert);
} catch (err) {
return asyncErr(res, err, 'when creating an alert');
......@@ -49,7 +49,7 @@ export async function create(req, res) {
export async function destroy(req, res) {
try {
let { id: userId } = req.user;
const { id: userId } = req.user;
await Alert.destroy(userId, req.preloaded.alert.id);
res.status(204).end();
......@@ -60,8 +60,8 @@ export async function destroy(req, res) {
export async function update(req, res) {
try {
let { id: userId } = req.user;
let { alert } = req.preloaded;
const { id: userId } = req.user;
const { alert } = req.preloaded;
let newAlert = req.body;
if (typeof newAlert.type !== 'undefined') {
......@@ -70,7 +70,7 @@ export async function update(req, res) {
newAlert = Object.assign({}, alert, newAlert);
let validationError = checkAlert(newAlert);
const validationError = checkAlert(newAlert);
if (validationError) {
throw new KError(validationError, 400);
}
......
......@@ -23,7 +23,7 @@ import { cleanData } from './helpers';
import { isDemoEnabled } from './settings';
import { ofxToKresus } from './ofx';
let log = makeLogger('controllers/all');
const log = makeLogger('controllers/all');
const ERR_MSG_LOADING_ALL = 'Error when loading all Kresus data';
......@@ -41,11 +41,11 @@ function cleanMeta(obj) {
*/
async function getAllData(userId, options = {}) {
const { isExport = false, cleanPassword = true } = options;
let ret = {};
const ret = {};
ret.accounts = (await Account.all(userId)).map(cleanMeta);
ret.accesses = (await Access.all(userId)).map(cleanMeta);
for (let access of ret.accesses) {
for (const access of ret.accesses) {
// Process enabled status only for the /all request.
if (!isExport) {
access.enabled = access.isEnabled();
......@@ -89,8 +89,8 @@ async function getAllData(userId, options = {}) {
export async function all(req, res) {
try {
let { id: userId } = req.user;
let ret = await getAllData(userId);
const { id: userId } = req.user;
const ret = await getAllData(userId);
res.status(200).json(ret);
} catch (err) {
err.code = ERR_MSG_LOADING_ALL;
......@@ -104,9 +104,9 @@ const ENCRYPTED_CONTENT_TAG = Buffer.from('KRE');
function encryptData(data, passphrase) {
assert(process.kresus.salt !== null, 'must have provided a salt');
let initVector = crypto.randomBytes(16);
let key = crypto.pbkdf2Sync(passphrase, process.kresus.salt, 100000, 32, 'sha512');
let cipher = crypto.createCipheriv(ENCRYPTION_ALGORITHM, key, initVector);
const initVector = crypto.randomBytes(16);
const key = crypto.pbkdf2Sync(passphrase, process.kresus.salt, 100000, 32, 'sha512');
const cipher = crypto.createCipheriv(ENCRYPTION_ALGORITHM, key, initVector);
return Buffer.concat([
initVector,
......@@ -119,8 +119,8 @@ function encryptData(data, passphrase) {
function decryptData(data, passphrase) {
assert(process.kresus.salt !== null, 'must have provided a salt');
let rawData = Buffer.from(data, 'base64');
let [initVector, tag, encrypted] = [
const rawData = Buffer.from(data, 'base64');
const [initVector, tag, encrypted] = [
rawData.slice(0, 16),
rawData.slice(16, 16 + 3),
rawData.slice(16 + 3)
......@@ -134,15 +134,15 @@ function decryptData(data, passphrase) {
);
}
let key = crypto.pbkdf2Sync(passphrase, process.kresus.salt, 100000, 32, 'sha512');
const key = crypto.pbkdf2Sync(passphrase, process.kresus.salt, 100000, 32, 'sha512');
let decipher = crypto.createDecipheriv(ENCRYPTION_ALGORITHM, key, initVector);
const decipher = crypto.createDecipheriv(ENCRYPTION_ALGORITHM, key, initVector);
return Buffer.concat([decipher.update(encrypted), decipher.final()]).toString();
}
export async function export_(req, res) {
try {
let { id: userId } = req.user;
const { id: userId } = req.user;
let passphrase = null;
if (req.body.encrypted) {
......@@ -194,8 +194,8 @@ function applyRenamings(model) {
return obj => obj;
}
return obj => {
for (let from of Object.keys(model.renamings)) {
let to = model.renamings[from];
for (const from of Object.keys(model.renamings)) {
const to = model.renamings[from];
if (typeof obj[from] !== 'undefined') {
if (typeof obj[to] === 'undefined') {
obj[to] = obj[from];
......@@ -260,11 +260,11 @@ export async function importData(userId, world) {
`);
log.info('Import accesses...');
let accessMap = {};
for (let access of world.accesses) {
let accessId = access.id;
const accessMap = {};
for (const access of world.accesses) {
const accessId = access.id;
delete access.id;
let sanitizedCustomFields = [];
const sanitizedCustomFields = [];
// Support legacy "customFields" value.
if (typeof access.customFields === 'string' && !access.fields) {
......@@ -275,7 +275,7 @@ export async function importData(userId, world) {
}
}
for (let { name, value } of access.fields || []) {
for (const { name, value } of access.fields || []) {
if (typeof name !== 'string') {
log.warn('Ignoring customField because of non-string "name" property.');
continue;
......@@ -291,22 +291,22 @@ export async function importData(userId, world) {
access.fields = sanitizedCustomFields;
let created = await Access.create(userId, access);
const created = await Access.create(userId, access);
accessMap[accessId] = created.id;
}
log.info('Done.');
log.info('Import accounts...');
let accountIdToAccount = new Map();
let vendorToOwnAccountId = new Map();
for (let account of world.accounts) {
const accountIdToAccount = new Map();
const vendorToOwnAccountId = new Map();
for (const account of world.accounts) {
if (typeof accessMap[account.accessId] === 'undefined') {
log.warn('Ignoring orphan account:\n', account);
continue;
}
let accountId = account.id;
const accountId = account.id;
delete account.id;
// For an initial import which does not come from Kresus (ex: a
......@@ -315,9 +315,9 @@ export async function importData(userId, world) {
if (account.lastCheckDate === null) {
let latestOpDate = null;
if (world.operations) {
let accountOps = world.operations.filter(op => op.accountId === accountId);
for (let op of accountOps) {
let opDate = parseDate(op.date);
const accountOps = world.operations.filter(op => op.accountId === accountId);
for (const op of accountOps) {
const opDate = parseDate(op.date);
if (opDate !== null && (latestOpDate === null || opDate > latestOpDate)) {
latestOpDate = opDate;
}
......@@ -327,7 +327,7 @@ export async function importData(userId, world) {
}
account.accessId = accessMap[account.accessId];
let created = await Account.create(userId, account);
const created = await Account.create(userId, account);
accountIdToAccount.set(accountId, created.id);
vendorToOwnAccountId.set(created.vendorAccountId, created.id);
......@@ -335,40 +335,40 @@ export async function importData(userId, world) {
log.info('Done.');
log.info('Import categories...');
let existingCategories = await Category.all(userId);
let existingCategoriesMap = new Map();
for (let category of existingCategories) {
const existingCategories = await Category.all(userId);
const existingCategoriesMap = new Map();
for (const category of existingCategories) {
existingCategoriesMap.set(category.label, category);
}
let categoryMap = {};
for (let category of world.categories) {
let catId = category.id;
const categoryMap = {};
for (const category of world.categories) {
const catId = category.id;
delete category.id;
if (existingCategoriesMap.has(category.label)) {
let existing = existingCategoriesMap.get(category.label);
const existing = existingCategoriesMap.get(category.label);
categoryMap[catId] = existing.id;
} else {
let created = await Category.create(userId, category);
const created = await Category.create(userId, category);
categoryMap[catId] = created.id;
}
}
log.info('Done.');
log.info('Import budgets...');
let makeBudgetKey = b => `${b.categoryId}-${b.year}-${b.month}`;
const makeBudgetKey = b => `${b.categoryId}-${b.year}-${b.month}`;
let existingBudgets = await Budget.all(userId);
let existingBudgetsMap = new Map();
for (let budget of existingBudgets) {
const existingBudgets = await Budget.all(userId);
const existingBudgetsMap = new Map();
for (const budget of existingBudgets) {
existingBudgetsMap.set(makeBudgetKey(budget), budget);
}
for (let importedBudget of world.budgets) {
for (const importedBudget of world.budgets) {
// Note the order here: first map to the actual category id, so the
// map lookup thereafter uses an existing category id.
importedBudget.categoryId = categoryMap[importedBudget.categoryId];
let existingBudget = existingBudgetsMap.get(makeBudgetKey(importedBudget));
const existingBudget = existingBudgetsMap.get(makeBudgetKey(importedBudget));
if (existingBudget) {
if (
!existingBudget.threshold ||
......@@ -388,16 +388,16 @@ export async function importData(userId, world) {
// No need to import operation types.
// importedTypesMap is used to set type to imported operations (backward compatibility).
let importedTypes = world.operationtypes || [];
let importedTypesMap = new Map();
for (let type of importedTypes) {
const importedTypes = world.operationtypes || [];
const importedTypesMap = new Map();
for (const type of importedTypes) {
importedTypesMap.set(type.id.toString(), type.name);
}
log.info('Import transactions...');
let skipTransactions = [];
const skipTransactions = [];
for (let i = 0; i < world.operations.length; i++) {
let op = world.operations[i];
const op = world.operations[i];
op.date = parseDate(op.date);
op.debitDate = parseDate(op.debitDate);
......@@ -435,7 +435,7 @@ export async function importData(userId, world) {
// Remove bankAccount as the operation is now linked to account with accountId prop.
delete op.bankAccount;
let categoryId = op.categoryId;
const categoryId = op.categoryId;
if (typeof categoryId !== 'undefined' && categoryId !== null) {
if (typeof categoryMap[categoryId] === 'undefined') {
log.warn('Unknown category, unsetting for operation:\n', op);
......@@ -445,7 +445,7 @@ export async function importData(userId, world) {
// Set operation type base on operationId.
if (typeof op.operationTypeID !== 'undefined') {
let key = op.operationTypeID.toString();
const key = op.operationTypeID.toString();
if (importedTypesMap.has(key)) {
op.type = importedTypesMap.get(key);
} else {
......@@ -492,7 +492,7 @@ export async function importData(userId, world) {
log.info('Done.');
log.info('Import settings...');
for (let setting of world.settings) {
for (const setting of world.settings) {
if (ConfigGhostSettings.has(setting.key) || setting.key === 'migration-version') {
continue;
}
......@@ -514,7 +514,7 @@ export async function importData(userId, world) {
// Overwrite the previous value of the demo-mode, if it was set.
if (setting.key === 'demo-mode' && setting.value === 'true') {
let found = await Setting.byKey(userId, 'demo-mode');
const found = await Setting.byKey(userId, 'demo-mode');
if (found && found.value !== 'true') {
await Setting.updateByKey(userId, 'demo-mode', true);
continue;
......@@ -528,7 +528,7 @@ export async function importData(userId, world) {
log.info('Done.');
log.info('Import alerts...');
for (let a of world.alerts) {
for (const a of world.alerts) {
// Map alert to account.
if (typeof a.accountId !== 'undefined') {