Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rework logging system #248

Merged
merged 2 commits into from
May 28, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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