import { IStorage, LSAToken, ProvisioningData, ProvisioningParams } from '@lenovo-software/lsa-clients-common'; import { Logger } from '../common/logger'; import { Policy } from './policy'; import Preferences from './preferences'; export enum LogSeverity { DEBUG = 1, INFO, WARNING, ERROR } export interface IStorageLogger { logDebug(severity: LogSeverity, logThis: string): Promise; } export interface GoogProfileUserInfo { email: string; id: string; } export class Storage implements IStorage, IStorageLogger { private deviceType = 'Chromebook'; private osType = 'Chrome'; private osVersion = 'TODO'; private initialized = false; private email: string = ''; constructor(private persistence: Preferences, private policy: Policy) {} loadHotProvisioningCode(): string { return ''; } saveHotProvisioningCode(hotProvisioningCode: string): Promise { throw new Error('Method not implemented.'); } saveProvisioningCode(provisioningCode: string): Promise { // TODO return Promise.resolve(); } loadOsString(): string { return this.osType; } //loginName is the name part of an email address for chromebooks. It's also the same as the deviceName loadLoginName(): string { return this.loadDeviceName(); } public async logDebug(severity: LogSeverity, logThis: string): Promise { if (this.persistence === null) { throw new Error('Storage.logDebug(): init() not called yet.'); } switch (severity) { case LogSeverity.DEBUG: { Logger.getInstance().logDebug(logThis); break; } case LogSeverity.INFO: { Logger.getInstance().logInfo(logThis); break; } case LogSeverity.WARNING: { Logger.getInstance().logWarning(logThis); break; } case LogSeverity.ERROR: { Logger.getInstance().logError(logThis); break; } } } public async init() { if (this.initialized) { return; } try { await this.loadEmailFromGoogle(); this.initialized = true; } catch (e) { throw new Error('Storage.init(): Error initializing persistence layer: ' + e); } } public loadProvisioningData(): ProvisioningData | null { if (!this.initialized) { throw new Error('Storage.loadProvisioningData: Not initialized.'); } const data = this.persistence.getSetting(Preferences.ProvisioningData_Key); console.log('data = ' + JSON.stringify(data)); return data ? ProvisioningData.fromAny(data) : null; } public saveProvisioningData(data: ProvisioningData): Promise { if (!this.initialized) { throw new Error('Storage.saveProvisioningData: Not initialized.'); } this.persistence.saveSetting(Preferences.ProvisioningData_Key, data); return Promise.resolve(); } public loadProvisioningParams(): ProvisioningParams | null { if (!this.initialized) { throw new Error('Storage.loadProvisioningParams: Not initialized.'); } const data = this.persistence.getSetting(Preferences.ProvisioningParams_Key); return data ? ProvisioningParams.fromAny(data) : null; } public saveProvisioningParams(data: ProvisioningParams): Promise { if (!this.initialized) { throw new Error('Storage.saveProvisioningParams: Not initialized.'); } this.persistence.saveSetting(Preferences.ProvisioningParams_Key, data); return Promise.resolve(); } public loadToken(): LSAToken | null { if (!this.initialized) { throw new Error('Storage.loadToken: Not initialized.'); } const data = this.persistence.getSetting(Preferences.Token_Key); return data ? LSAToken.fromAny(data) : null; } public saveToken(data: LSAToken): Promise { if (!this.initialized) { throw new Error('Storage.saveToken: Not initialized.'); } this.persistence.saveSetting(Preferences.Token_Key, data); return Promise.resolve(); } public loadPrivateKey(): string { if (!this.initialized) { throw new Error('Storage.loadPrivateKey: Not initialized.'); } return this.persistence.getSetting(Preferences.PrivateKey_Key); } public savePrivateKey(data: string): Promise { if (!this.initialized) { throw new Error('Storage.savePrivateKey: Not initialized.'); } this.persistence.saveSetting(Preferences.PrivateKey_Key, data); return Promise.resolve(); } public loadPublicKey(): string { if (!this.initialized) { throw new Error('Storage.loadPublicKey: Not initialized.'); } return this.persistence.getSetting(Preferences.PublicKey_Key); } public savePublicKey(data: string): Promise { if (!this.initialized) { throw new Error('Storage.savePublicKey: Not initialized.'); } this.persistence.saveSetting(Preferences.PublicKey_Key, data); return Promise.resolve(); } public loadAPIServer(): string { let server = this.policy.api_server; return server; } public loadProvisioningCode(): string { return this.policy.provisioning_code; } public loadDeviceName(): string { // This is traditionally the username portion of the email address. const arr = this.loadEmailAddr().split('@'); if (!arr || !Array.isArray(arr) || arr.length < 1) throw new Error('Invalid email address supplied.'); return arr[0]; } //this method must be synchronous. Therefore, it should only be called after storage has initialized, so the email can load from google public loadEmailAddr(): string { return this.email; } public loadDeviceId(): string { const pd = this.loadProvisioningData(); return pd ? pd.deviceID : ''; } public loadDeviceType(): string { return this.deviceType; } public loadOsType(): string { return this.osType; } public forceReprovision(): boolean { // TODO return false; } public getClientVersion(): string { return 'GETCLIENTVERSION: TODO'; } public loadDisplayName(): string { if (!this.initialized) { throw new Error('Storage.loadDisplayName: Not initialized.'); } return this.persistence.getSetting(Preferences.DisplayName_Key) || this.loadDeviceName(); } public loadOsVersion(): string { return this.osVersion; } private loadEmailFromGoogle(): Promise { return new Promise((resolve, reject) => { //requires that the identity.email permission be granted chrome.identity.getProfileUserInfo((response: GoogProfileUserInfo) => { if (response?.email) { this.email = response.email; resolve(); } else { reject(new Error('Email was not returned from Google')); } }); }); } }