Refactor cached username logic from events.ts to bootstrap.ts for reuse

Change-type: patch
This commit is contained in:
Paulo Castro 2022-02-11 15:23:36 +00:00
parent d2330f9ed1
commit 948095ce4d
2 changed files with 67 additions and 40 deletions

View File

@ -16,12 +16,7 @@
*/ */
import * as packageJSON from '../package.json'; import * as packageJSON from '../package.json';
import { getBalenaSdk, stripIndent } from './utils/lazy'; import { stripIndent } from './utils/lazy';
interface CachedUsername {
token: string;
username: string;
}
/** /**
* Track balena CLI usage events (product improvement analytics). * Track balena CLI usage events (product improvement analytics).
@ -49,40 +44,13 @@ export async function trackCommand(commandSignature: string) {
scope.setExtra('command', commandSignature); scope.setExtra('command', commandSignature);
}); });
} }
const settings = await import('balena-settings-client'); const { getCachedUsername } = await import('./utils/bootstrap');
let username: string | undefined;
const username = await (async () => { try {
const getStorage = await import('balena-settings-storage'); username = (await getCachedUsername())?.username;
const dataDirectory = settings.get<string>('dataDirectory'); } catch {
const storage = getStorage({ dataDirectory }); // ignore
let token; }
try {
token = await storage.get('token');
} catch {
// If we can't get a token then we can't get a username
return;
}
try {
const result = (await storage.get('cachedUsername')) as CachedUsername;
if (result.token === token) {
return result.username;
}
} catch {
// ignore
}
try {
const balena = getBalenaSdk();
const $username = await balena.auth.whoami();
await storage.set('cachedUsername', {
token,
username: $username,
} as CachedUsername);
return $username;
} catch {
return;
}
})();
if (!process.env.BALENARC_NO_SENTRY) { if (!process.env.BALENARC_NO_SENTRY) {
Sentry!.configureScope((scope) => { Sentry!.configureScope((scope) => {
scope.setUser({ scope.setUser({
@ -96,6 +64,7 @@ export async function trackCommand(commandSignature: string) {
!process.env.BALENA_CLI_TEST_TYPE && !process.env.BALENA_CLI_TEST_TYPE &&
!process.env.BALENARC_NO_ANALYTICS !process.env.BALENARC_NO_ANALYTICS
) { ) {
const settings = await import('balena-settings-client');
const balenaUrl = settings.get<string>('balenaUrl'); const balenaUrl = settings.get<string>('balenaUrl');
await sendEvent(balenaUrl, `[CLI] ${commandSignature}`, username); await sendEvent(balenaUrl, `[CLI] ${commandSignature}`, username);
} }

View File

@ -119,3 +119,61 @@ export async function pkgExec(modFunc: string, args: string[]) {
console.error(err); console.error(err);
} }
} }
export interface CachedUsername {
token: string;
username: string;
}
let cachedUsername: CachedUsername | undefined;
/**
* Return the parsed contents of the `~/.balena/cachedUsername` file. If the file
* does not exist, create it with the details from the cloud. If not connected
* to the internet, return undefined. This function is used by `lib/events.ts`
* (event tracking) and `lib/utils/device/ssh.ts` and needs to gracefully handle
* the scenario of not being connected to the internet.
*/
export async function getCachedUsername(): Promise<CachedUsername | undefined> {
if (cachedUsername) {
return cachedUsername;
}
const [{ getBalenaSdk }, getStorage, settings] = await Promise.all([
import('./lazy'),
import('balena-settings-storage'),
import('balena-settings-client'),
]);
const dataDirectory = settings.get<string>('dataDirectory');
const storage = getStorage({ dataDirectory });
let token: string | undefined;
try {
token = (await storage.get('token')) as string | undefined;
} catch {
// ignore
}
if (!token) {
// If we can't get a token then we can't get a username
return;
}
try {
const result = (await storage.get('cachedUsername')) as
| CachedUsername
| undefined;
if (result && result.token === token && result.username) {
cachedUsername = result;
return cachedUsername;
}
} catch {
// ignore
}
try {
const username = await getBalenaSdk().auth.whoami();
if (username) {
cachedUsername = { token, username };
await storage.set('cachedUsername', cachedUsername);
}
} catch {
// ignore (not connected to the internet?)
}
return cachedUsername;
}