diff --git a/common/src/models/domain/account.ts b/common/src/models/domain/account.ts index 51be98be6e..012ce09cd7 100644 --- a/common/src/models/domain/account.ts +++ b/common/src/models/domain/account.ts @@ -94,7 +94,6 @@ export class AccountProfile { everBeenUnlocked?: boolean; forcePasswordReset?: boolean; hasPremiumPersonally?: boolean; - lastActive?: number; lastSync?: string; userId?: string; usesKeyConnector?: boolean; diff --git a/common/src/models/domain/state.ts b/common/src/models/domain/state.ts index 00a5347a52..f5a2c046b5 100644 --- a/common/src/models/domain/state.ts +++ b/common/src/models/domain/state.ts @@ -9,6 +9,7 @@ export class State< globals: TGlobalState; activeUserId: string; authenticatedAccounts: string[] = []; + accountActivity: { [userId: string]: number } = {}; constructor(globals: TGlobalState) { this.globals = globals; diff --git a/common/src/services/state.service.ts b/common/src/services/state.service.ts index c718b29b29..80f5a81120 100644 --- a/common/src/services/state.service.ts +++ b/common/src/services/state.service.ts @@ -46,6 +46,7 @@ const keys = { authenticatedAccounts: "authenticatedAccounts", activeUserId: "activeUserId", tempAccountSettings: "tempAccountSettings", // used to hold account specific settings (i.e clear clipboard) between initial migration and first account authentication + accountActivity: "accountActivity", }; const partialKeys = { @@ -117,7 +118,7 @@ export class StateService< async addAccount(account: TAccount) { account = await this.setAccountEnvironmentUrls(account); this.state.authenticatedAccounts.push(account.profile.userId); - this.storageService.save(keys.authenticatedAccounts, this.state.authenticatedAccounts); + await this.storageService.save(keys.authenticatedAccounts, this.state.authenticatedAccounts); this.state.accounts[account.profile.userId] = account; await this.scaffoldNewAccountStorage(account); await this.setActiveUser(account.profile.userId); @@ -1561,22 +1562,32 @@ export class StateService< } async getLastActive(options?: StorageOptions): Promise { - return ( - await this.getAccount(this.reconcileOptions(options, await this.defaultOnDiskOptions())) - )?.profile?.lastActive; + options = this.reconcileOptions(options, await this.defaultOnDiskOptions()); + + const accountActivity = await this.storageService.get<{ [userId: string]: number }>( + keys.accountActivity, + options + ); + + if (accountActivity == null || Object.keys(accountActivity).length < 1) { + return null; + } + + return accountActivity[options.userId]; } async setLastActive(value: number, options?: StorageOptions): Promise { - const account = await this.getAccount( - this.reconcileOptions(options, await this.defaultOnDiskOptions()) - ); - if (account != null) { - account.profile.lastActive = value; - await this.saveAccount( - account, - this.reconcileOptions(options, await this.defaultOnDiskOptions()) - ); + options = this.reconcileOptions(options, await this.defaultOnDiskOptions()); + if (options.userId == null) { + return; } + const accountActivity = + (await this.storageService.get<{ [userId: string]: number }>( + keys.accountActivity, + options + )) ?? {}; + accountActivity[options.userId] = value; + await this.storageService.save(keys.accountActivity, accountActivity, options); } async getLastSync(options?: StorageOptions): Promise { diff --git a/common/src/services/stateMigration.service.ts b/common/src/services/stateMigration.service.ts index 490c35a183..7d5e2bc295 100644 --- a/common/src/services/stateMigration.service.ts +++ b/common/src/services/stateMigration.service.ts @@ -122,6 +122,7 @@ const keys = { authenticatedAccounts: "authenticatedAccounts", activeUserId: "activeUserId", tempAccountSettings: "tempAccountSettings", // used to hold account specific settings (i.e clear clipboard) between initial migration and first account authentication + accountActivity: "accountActivity", }; const partialKeys = { @@ -396,7 +397,6 @@ export class StateMigrationService< kdfIterations: await this.get(v1Keys.kdfIterations), kdfType: await this.get(v1Keys.kdf), keyHash: await this.get(v1Keys.keyHash), - lastActive: await this.get(v1Keys.lastActive), lastSync: null, userId: userId, usesKeyConnector: null, @@ -412,6 +412,13 @@ export class StateMigrationService< await this.set(keys.authenticatedAccounts, [userId]); await this.set(keys.activeUserId, userId); + + const accountActivity: { [userId: string]: number } = { + [userId]: await this.get(v1Keys.lastActive), + }; + accountActivity[userId] = await this.get(v1Keys.lastActive); + await this.set(keys.accountActivity, accountActivity); + await clearV1Keys(userId); if (await this.secureStorageService.has(v1Keys.key, { keySuffix: "biometric" })) {