Skip to content

Commit

Permalink
Rework logging system (#248)
Browse files Browse the repository at this point in the history
This PR adds a much needed cleanup of the logging system.
  • Loading branch information
Mikescops authored May 28, 2024
1 parent 290195c commit 7240493
Show file tree
Hide file tree
Showing 28 changed files with 182 additions and 89 deletions.
4 changes: 2 additions & 2 deletions src/command-handlers/backup.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import winston from 'winston';
import fs from 'fs';
import { connectAndPrepare, getDatabasePath } from '../modules/database';
import { logger } from '../logger';

export const runBackup = async (options: { directory: string; filename: string }) => {
const { db } = await connectAndPrepare({ failIfNoDB: true, forceSync: true });
Expand All @@ -19,5 +19,5 @@ export const runBackup = async (options: { directory: string; filename: string }

fs.copyFileSync(databasePath, backupPath);

winston.info(`Backup saved to ${backupPath}`);
logger.success(`Backup saved to ${backupPath}.`);
};
4 changes: 2 additions & 2 deletions src/command-handlers/configure.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import winston from 'winston';
import { encryptAesCbcHmac256 } from '../modules/crypto/encrypt';
import { deleteLocalKey, setLocalKey, warnUnreachableKeychainDisabled } from '../modules/crypto/keychainManager';
import { connectAndPrepare } from '../modules/database';
import { parseBooleanString } from '../utils';
import { DeviceConfiguration } from '../types';
import { logger } from '../logger';

export const configureSaveMasterPassword = async (boolean: string) => {
let shouldNotSaveMasterPassword = !parseBooleanString(boolean);
Expand All @@ -23,7 +23,7 @@ export const configureSaveMasterPassword = async (boolean: string) => {
if (error instanceof Error) {
errorMessage = error.message;
}
winston.warn(`Unable to delete the local key from the keychain: ${errorMessage}`);
logger.warn(`Unable to delete the local key from the keychain: ${errorMessage}`);
}
}

Expand Down
12 changes: 7 additions & 5 deletions src/command-handlers/devices.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import winston from 'winston';
import { connectAndPrepare, reset } from '../modules/database';
import { deactivateDevices, listDevices, ListDevicesOutput } from '../endpoints';
import { askConfirmReset, epochTimestampToIso } from '../utils';
import { registerDevice } from '../modules/auth';
import { get2FAStatusUnauthenticated } from '../endpoints/get2FAStatusUnauthenticated';
import { logger } from '../logger';

type OutputDevice = ListDevicesOutput['devices'][number] & {
isCurrentDevice: boolean;
Expand All @@ -22,7 +22,7 @@ export async function listAllDevices(options: { json: boolean }) {
);

if (options.json) {
console.log(JSON.stringify(result));
logger.content(JSON.stringify(result));
} else {
// order by last activity, ascending.
// we sort it only on non-json because it is likely that it will be used
Expand Down Expand Up @@ -127,14 +127,16 @@ export const registerNonInteractiveDevice = async (deviceName: string, options:
const serviceDeviceKeys = `dls_${deviceAccessKey}_${serviceDeviceKeysPayloadB64}`;

if (options.json) {
console.log(
logger.content(
JSON.stringify({
DASHLANE_SERVICE_DEVICE_KEYS: serviceDeviceKeys,
})
);
} else {
winston.info('The device credentials have been generated, save and run the following command to export them:');
console.log(`export DASHLANE_SERVICE_DEVICE_KEYS=${serviceDeviceKeys}`);
logger.success(
'The device credentials have been generated, save and run the following command to export them:'
);
logger.content(`export DASHLANE_SERVICE_DEVICE_KEYS=${serviceDeviceKeys}`);
}

db.close();
Expand Down
4 changes: 2 additions & 2 deletions src/command-handlers/exec.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Command } from 'commander';
import winston from 'winston';
import { spawn } from 'child_process';
import { getVaultContent, initVaultContent } from '../modules/database';
import { logger } from '../logger';

export const runExec = async (_options: unknown, program: Command) => {
const command = program.args.join(' ');
Expand All @@ -26,6 +26,6 @@ export const runExec = async (_options: unknown, program: Command) => {

// listen for process exit
child.on('exit', (code) => {
winston.debug(`Child process exited with code ${code ?? 'unknown'}`);
logger.debug(`Child process exited with code ${code ?? 'unknown'}`);
});
};
3 changes: 2 additions & 1 deletion src/command-handlers/inject.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import fs from 'fs';
import { getVaultContent, initVaultContent } from '../modules/database';
import { logger } from '../logger';

interface InjectOpts {
in: string;
Expand Down Expand Up @@ -78,6 +79,6 @@ const outputContent = (output: string, outputFilePath?: string) => {
if (outputFilePath) {
fs.writeFileSync(outputFilePath, output);
} else {
console.log(output);
logger.content(output);
}
};
10 changes: 5 additions & 5 deletions src/command-handlers/logout.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import { Database } from 'better-sqlite3';
import winston from 'winston';
import { deactivateDevices } from '../endpoints';
import { connectAndPrepare, connect, reset } from '../modules/database';
import { LocalConfiguration, DeviceConfiguration } from '../types';
import { askConfirmReset } from '../utils';
import { logger } from '../logger';

export const runLogout = async (options: { ignoreRevocation: boolean }) => {
if (options.ignoreRevocation) {
winston.info("The device credentials won't be revoked on Dashlane's servers");
logger.info("The device credentials won't be revoked on Dashlane's servers.");
}

const resetConfirmation = await askConfirmReset();
Expand All @@ -28,7 +28,7 @@ export const runLogout = async (options: { ignoreRevocation: boolean }) => {
if (error instanceof Error) {
errorMessage = error.message;
}
winston.debug(`Unable to read device configuration during logout: ${errorMessage}`);
logger.debug(`Unable to read device configuration during logout: ${errorMessage}`);

db = connect();
db.serialize();
Expand All @@ -38,9 +38,9 @@ export const runLogout = async (options: { ignoreRevocation: boolean }) => {
deviceIds: [deviceConfiguration.accessKey],
login: deviceConfiguration.login,
localConfiguration,
}).catch((error) => console.error('Unable to deactivate the device', error));
}).catch((error) => logger.error('Unable to deactivate the device', error));
}
reset({ db, localConfiguration });
console.log('The local Dashlane local storage has been reset and you have been logged out');
logger.success('The local Dashlane local storage has been reset and you have been logged out.');
db.close();
};
12 changes: 6 additions & 6 deletions src/command-handlers/passwords.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import Database from 'better-sqlite3';
import { Clipboard } from '@napi-rs/clipboard';
import { authenticator } from 'otplib';
import winston from 'winston';
import { AuthentifiantTransactionContent, BackupEditTransaction, LocalConfiguration, VaultCredential } from '../types';
import { decryptTransactions } from '../modules/crypto';
import { askCredentialChoice, filterMatches } from '../utils';
import { connectAndPrepare } from '../modules/database';
import { logger } from '../logger';

export const runPassword = async (
filters: string[] | null,
Expand All @@ -18,7 +18,7 @@ export const runPassword = async (
db.close();

if (output === 'json') {
console.log(JSON.stringify(foundCredentials));
logger.content(JSON.stringify(foundCredentials));
return;
}

Expand Down Expand Up @@ -54,19 +54,19 @@ export const runPassword = async (
}

if (output === 'console') {
console.log(result);
logger.content(result);
}

const clipboard = new Clipboard();
clipboard.setText(result);
console.log(
logger.content(
`🔓 ${field} for "${selectedCredential.title || selectedCredential.url || 'N/C'}" copied to clipboard!`
);

if (field === 'password' && selectedCredential.otpSecret) {
const token = authenticator.generate(selectedCredential.otpSecret);
const timeRemaining = authenticator.timeRemaining();
console.log(`🔢 OTP code: ${token} \u001B[3m(expires in ${timeRemaining} seconds)\u001B[0m`);
logger.content(`🔢 OTP code: ${token} \u001B[3m(expires in ${timeRemaining} seconds)\u001B[0m`);
}
};

Expand All @@ -79,7 +79,7 @@ interface GetCredential {
export const findCredentials = async (params: GetCredential): Promise<VaultCredential[]> => {
const { localConfiguration, filters, db } = params;

winston.debug(`Retrieving: ${filters && filters.length > 0 ? filters.join(' ') : ''}`);
logger.debug(`Retrieving: ${filters && filters.length > 0 ? filters.join(' ') : ''}`);
const transactions = db
.prepare(`SELECT * FROM transactions WHERE login = ? AND type = 'AUTHENTIFIANT' AND action = 'BACKUP_EDIT'`)
.bind(localConfiguration.login)
Expand Down
3 changes: 2 additions & 1 deletion src/command-handlers/read.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { logger } from '../logger';
import { decryptTransactions } from '../modules/crypto';
import { connectAndPrepare, findVaultContent } from '../modules/database';
import {
Expand Down Expand Up @@ -62,5 +63,5 @@ export const runRead = async (path: string) => {
secrets: decryptedSecrets,
});

console.log(findVaultContent(secretsDecrypted, parsedPath));
logger.content(findVaultContent(secretsDecrypted, parsedPath));
};
8 changes: 4 additions & 4 deletions src/command-handlers/secrets.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import Database from 'better-sqlite3';
import winston from 'winston';
import { BackupEditTransaction, LocalConfiguration, SecretTransactionContent, VaultSecret } from '../types';
import { decryptTransactions } from '../modules/crypto';
import { askSecretChoice, filterMatches } from '../utils';
import { connectAndPrepare } from '../modules/database';
import { logger } from '../logger';

export const runSecret = async (filters: string[] | null, options: { output: 'text' | 'json' }) => {
const { db, localConfiguration } = await connectAndPrepare({});
Expand All @@ -26,7 +26,7 @@ interface GetSecret {
export const getSecret = async (params: GetSecret): Promise<void> => {
const { localConfiguration, filters, db, output } = params;

winston.debug(`Retrieving: ${filters && filters.length > 0 ? filters.join(' ') : ''}`);
logger.debug(`Retrieving: ${filters && filters.length > 0 ? filters.join(' ') : ''}`);
const transactions = db
.prepare(`SELECT * FROM transactions WHERE login = ? AND type = 'SECRET' AND action = 'BACKUP_EDIT'`)
.bind(localConfiguration.login)
Expand All @@ -49,7 +49,7 @@ export const getSecret = async (params: GetSecret): Promise<void> => {

switch (output) {
case 'json':
console.log(JSON.stringify(matchedSecrets));
logger.content(JSON.stringify(matchedSecrets));
break;
case 'text': {
let selectedSecret: VaultSecret | null = null;
Expand All @@ -63,7 +63,7 @@ export const getSecret = async (params: GetSecret): Promise<void> => {
selectedSecret = await askSecretChoice({ matchedSecrets, hasFilters: Boolean(filters?.length) });
}

console.log(selectedSecret.content);
logger.content(selectedSecret.content);
break;
}
default:
Expand Down
8 changes: 4 additions & 4 deletions src/command-handlers/secureNotes.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import Database from 'better-sqlite3';
import winston from 'winston';
import { BackupEditTransaction, LocalConfiguration, SecureNoteTransactionContent, VaultNote } from '../types';
import { decryptTransactions } from '../modules/crypto';
import { askSecureNoteChoice, filterMatches } from '../utils';
import { connectAndPrepare } from '../modules/database';
import { logger } from '../logger';

export const runSecureNote = async (filters: string[] | null, options: { output: 'text' | 'json' }) => {
const { db, localConfiguration } = await connectAndPrepare({});
Expand All @@ -26,7 +26,7 @@ interface GetSecureNote {
export const getNote = async (params: GetSecureNote): Promise<void> => {
const { localConfiguration, filters, db, output } = params;

winston.debug(`Retrieving: ${filters && filters.length > 0 ? filters.join(' ') : ''}`);
logger.debug(`Retrieving: ${filters && filters.length > 0 ? filters.join(' ') : ''}`);
const transactions = db
.prepare(`SELECT * FROM transactions WHERE login = ? AND type = 'SECURENOTE' AND action = 'BACKUP_EDIT'`)
.bind(localConfiguration.login)
Expand All @@ -49,7 +49,7 @@ export const getNote = async (params: GetSecureNote): Promise<void> => {

switch (output) {
case 'json':
console.log(JSON.stringify(matchedNotes));
logger.content(JSON.stringify(matchedNotes));
break;
case 'text': {
let selectedNote: VaultNote | null = null;
Expand All @@ -63,7 +63,7 @@ export const getNote = async (params: GetSecureNote): Promise<void> => {
selectedNote = await askSecureNoteChoice({ matchedNotes, hasFilters: Boolean(filters?.length) });
}

console.log(selectedNote.content);
logger.content(selectedNote.content);
break;
}
default:
Expand Down
16 changes: 8 additions & 8 deletions src/command-handlers/sync.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import Database from 'better-sqlite3';
import winston from 'winston';
import { connectAndPrepare } from '../modules/database';
import { decrypt } from '../modules/crypto/decrypt';
import { encryptAesCbcHmac256 } from '../modules/crypto/encrypt';
Expand All @@ -8,11 +7,12 @@ import { getLatestContent } from '../endpoints';
import type { DeviceConfiguration, LocalConfiguration } from '../types';
import { notEmpty } from '../utils';
import { askReplaceIncorrectMasterPassword } from '../utils/dialogs';
import { logger } from '../logger';

export const runSync = async () => {
const { db, localConfiguration, deviceConfiguration } = await connectAndPrepare({ autoSync: false });
await sync({ db, localConfiguration, deviceConfiguration });
winston.info('Successfully synced');
logger.success('Successfully synced');
db.close();
};

Expand All @@ -25,7 +25,7 @@ interface Sync {
export const sync = async (params: Sync) => {
const { db } = params;
let { localConfiguration } = params;
winston.debug('Start syncing...');
logger.debug('Start syncing...');

const lastServerSyncTimestamp =
(
Expand Down Expand Up @@ -64,7 +64,7 @@ export const sync = async (params: Sync) => {
if (error instanceof Error) {
errorMessage = error.message;
}
winston.debug(`Unable to decrypt a transactions while sync: ${errorMessage}`);
logger.debug(`Unable to decrypt a transactions while sync: ${errorMessage}`);

if (transac.identifier === 'SETTINGS_userId') {
if (!(await askReplaceIncorrectMasterPassword())) {
Expand Down Expand Up @@ -99,10 +99,10 @@ export const sync = async (params: Sync) => {
const nbErrors = latestContent.transactions.length - values.length;

if (nbErrors !== 0) {
winston.debug(`Ignored ${nbErrors} decryption errors`);
logger.debug(`Ignored ${nbErrors} decryption errors`);
}

winston.debug(`Number of new updates: ${values.length}`);
logger.debug(`Number of new updates: ${values.length}`);

const statement = db.prepare(
'REPLACE INTO transactions (login, identifier, type, action, content) VALUES (?, ?, ?, ?, ?)'
Expand All @@ -120,11 +120,11 @@ export const sync = async (params: Sync) => {
.bind(localConfiguration.login, Number(latestContent.timestamp), Math.floor(Date.now() / 1000))
.run();

winston.debug(`Requested timestamp ${lastServerSyncTimestamp}, new timestamp ${latestContent.timestamp}`);
logger.debug(`Requested timestamp ${lastServerSyncTimestamp}, new timestamp ${latestContent.timestamp}`);

const summaryCounted: Record<string, number> = {};
Object.keys(latestContent.summary).forEach((key) => {
summaryCounted[key] = Object.keys(latestContent.summary[key]).length;
});
winston.debug(JSON.stringify(summaryCounted, null, 4));
logger.debug(JSON.stringify(summaryCounted, null, 4));
};
3 changes: 2 additions & 1 deletion src/command-handlers/teamDarkWebInsightsReport.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { getTeamDarkWebInsightsReport } from '../endpoints';
import { logger } from '../logger';
import { getTeamDeviceCredentials } from '../utils';

export const runTeamDarkWebInsightsReport = async (
Expand All @@ -17,5 +18,5 @@ export const runTeamDarkWebInsightsReport = async (
offset: offset ?? 0,
});

console.log(JSON.stringify(response));
logger.content(JSON.stringify(response));
};
3 changes: 2 additions & 1 deletion src/command-handlers/teamDevices.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { connectAndPrepare } from '../modules/database';
import { listTeamDevices, registerTeamDevice } from '../endpoints';
import { epochTimestampToIso } from '../utils';
import { logger } from '../logger';

export const listAllTeamDevices = async (options: { json: boolean }) => {
const { db, localConfiguration } = await connectAndPrepare({ autoSync: false });
Expand All @@ -21,7 +22,7 @@ export const listAllTeamDevices = async (options: { json: boolean }) => {
};
});

console.log(JSON.stringify(result));
logger.content(JSON.stringify(result));
return;
}

Expand Down
Loading

0 comments on commit 7240493

Please sign in to comment.