diff --git a/angular/src/components/add-edit.component.ts b/angular/src/components/add-edit.component.ts index 3c6d0bc3..54cc5d2e 100644 --- a/angular/src/components/add-edit.component.ts +++ b/angular/src/components/add-edit.component.ts @@ -22,10 +22,10 @@ import { FolderService } from 'jslib-common/abstractions/folder.service'; import { I18nService } from 'jslib-common/abstractions/i18n.service'; import { LogService } from 'jslib-common/abstractions/log.service'; import { MessagingService } from 'jslib-common/abstractions/messaging.service'; +import { OrganizationService } from 'jslib-common/abstractions/organization.service'; import { PlatformUtilsService } from 'jslib-common/abstractions/platformUtils.service'; import { PolicyService } from 'jslib-common/abstractions/policy.service'; import { StateService } from 'jslib-common/abstractions/state.service'; -import { UserService } from 'jslib-common/abstractions/user.service'; import { Cipher } from 'jslib-common/models/domain/cipher'; @@ -87,9 +87,9 @@ export class AddEditComponent implements OnInit { constructor(protected cipherService: CipherService, protected folderService: FolderService, protected i18nService: I18nService, protected platformUtilsService: PlatformUtilsService, protected auditService: AuditService, protected stateService: StateService, - protected userService: UserService, protected collectionService: CollectionService, - protected messagingService: MessagingService, protected eventService: EventService, - protected policyService: PolicyService, private logService: LogService) { + protected collectionService: CollectionService, protected messagingService: MessagingService, + protected eventService: EventService, protected policyService: PolicyService, + private logService: LogService, private organizationService: OrganizationService) { this.typeOptions = [ { name: i18nService.t('typeLogin'), value: CipherType.Login }, { name: i18nService.t('typeCard'), value: CipherType.Card }, @@ -154,11 +154,11 @@ export class AddEditComponent implements OnInit { if (await this.policyService.policyAppliesToUser(PolicyType.PersonalOwnership)) { this.allowPersonal = false; } else { - const myEmail = await this.userService.getEmail(); + const myEmail = await this.stateService.getEmail(); this.ownershipOptions.push({ name: myEmail, value: null }); } - const orgs = await this.userService.getAllOrganizations(); + const orgs = await this.organizationService.getAll(); orgs.sort(Utils.getSortFunction(this.i18nService, 'name')).forEach(o => { if (o.enabled && o.status === OrganizationUserStatusType.Confirmed) { this.ownershipOptions.push({ name: o.name, value: o.id }); @@ -185,12 +185,12 @@ export class AddEditComponent implements OnInit { this.title = this.i18nService.t('addItem'); } - const addEditCipherInfo: any = await this.stateService.get('addEditCipherInfo'); + const addEditCipherInfo: any = await this.stateService.getAddEditCipherInfo(); if (addEditCipherInfo != null) { this.cipher = addEditCipherInfo.cipher; this.collectionIds = addEditCipherInfo.collectionIds; } - await this.stateService.remove('addEditCipherInfo'); + await this.stateService.setAddEditCipherInfo(null); if (this.cipher == null) { if (this.editMode) { @@ -434,7 +434,7 @@ export class AddEditComponent implements OnInit { } if (this.cipher.organizationId != null) { this.collections = this.writeableCollections.filter(c => c.organizationId === this.cipher.organizationId); - const org = await this.userService.getOrganization(this.cipher.organizationId); + const org = await this.organizationService.get(this.cipher.organizationId); if (org != null) { this.cipher.organizationUseTotp = org.useTotp; } diff --git a/angular/src/components/attachments.component.ts b/angular/src/components/attachments.component.ts index dcbaf19b..6745251b 100644 --- a/angular/src/components/attachments.component.ts +++ b/angular/src/components/attachments.component.ts @@ -12,7 +12,7 @@ import { CryptoService } from 'jslib-common/abstractions/crypto.service'; import { I18nService } from 'jslib-common/abstractions/i18n.service'; import { LogService } from 'jslib-common/abstractions/log.service'; import { PlatformUtilsService } from 'jslib-common/abstractions/platformUtils.service'; -import { UserService } from 'jslib-common/abstractions/user.service'; +import { StateService } from 'jslib-common/abstractions/state.service'; import { Cipher } from 'jslib-common/models/domain/cipher'; import { ErrorResponse } from 'jslib-common/models/response/errorResponse'; @@ -37,9 +37,9 @@ export class AttachmentsComponent implements OnInit { emergencyAccessId?: string = null; constructor(protected cipherService: CipherService, protected i18nService: I18nService, - protected cryptoService: CryptoService, protected userService: UserService, - protected platformUtilsService: PlatformUtilsService, protected apiService: ApiService, - protected win: Window, private logService: LogService) { } + protected cryptoService: CryptoService, protected platformUtilsService: PlatformUtilsService, + protected apiService: ApiService, protected win: Window, + protected logService: LogService, protected stateService: StateService) { } async ngOnInit() { await this.init(); @@ -164,7 +164,7 @@ export class AttachmentsComponent implements OnInit { this.cipher = await this.cipherDomain.decrypt(); this.hasUpdatedKey = await this.cryptoService.hasEncKey(); - const canAccessPremium = await this.userService.canAccessPremium(); + const canAccessPremium = await this.stateService.getCanAccessPremium(); this.canAccessAttachments = canAccessPremium || this.cipher.organizationId != null; if (!this.canAccessAttachments) { diff --git a/angular/src/components/avatar.component.ts b/angular/src/components/avatar.component.ts index 1760c521..a9ba9117 100644 --- a/angular/src/components/avatar.component.ts +++ b/angular/src/components/avatar.component.ts @@ -45,7 +45,7 @@ export class AvatarComponent implements OnChanges, OnInit { } private async generate() { - const enableGravatars = await this.stateService.get('enableGravatars'); + const enableGravatars = await this.stateService.getEnableGravitars(); if (enableGravatars && this.email != null) { const hashBytes = await this.cryptoFunctionService.hash(this.email.toLowerCase().trim(), 'md5'); const hash = Utils.fromBufferToHex(hashBytes).toLowerCase(); diff --git a/angular/src/components/change-password.component.ts b/angular/src/components/change-password.component.ts index 5af79115..7bbb3c51 100644 --- a/angular/src/components/change-password.component.ts +++ b/angular/src/components/change-password.component.ts @@ -6,7 +6,7 @@ import { MessagingService } from 'jslib-common/abstractions/messaging.service'; import { PasswordGenerationService } from 'jslib-common/abstractions/passwordGeneration.service'; import { PlatformUtilsService } from 'jslib-common/abstractions/platformUtils.service'; import { PolicyService } from 'jslib-common/abstractions/policy.service'; -import { UserService } from 'jslib-common/abstractions/user.service'; +import { StateService } from 'jslib-common/abstractions/state.service'; import { EncString } from 'jslib-common/models/domain/encString'; import { MasterPasswordPolicyOptions } from 'jslib-common/models/domain/masterPasswordPolicyOptions'; @@ -29,12 +29,12 @@ export class ChangePasswordComponent implements OnInit { private masterPasswordStrengthTimeout: any; constructor(protected i18nService: I18nService, protected cryptoService: CryptoService, - protected messagingService: MessagingService, protected userService: UserService, - protected passwordGenerationService: PasswordGenerationService, - protected platformUtilsService: PlatformUtilsService, protected policyService: PolicyService) { } + protected messagingService: MessagingService, protected passwordGenerationService: PasswordGenerationService, + protected platformUtilsService: PlatformUtilsService, protected policyService: PolicyService, + protected stateService: StateService) { } async ngOnInit() { - this.email = await this.userService.getEmail(); + this.email = await this.stateService.getEmail(); this.enforcedPolicyOptions = await this.policyService.getMasterPasswordPolicyOptions(); } @@ -47,12 +47,12 @@ export class ChangePasswordComponent implements OnInit { return; } - const email = await this.userService.getEmail(); + const email = await this.stateService.getEmail(); if (this.kdf == null) { - this.kdf = await this.userService.getKdf(); + this.kdf = await this.stateService.getKdfType(); } if (this.kdfIterations == null) { - this.kdfIterations = await this.userService.getKdfIterations(); + this.kdfIterations = await this.stateService.getKdfIterations(); } const key = await this.cryptoService.makeKey(this.masterPassword, email.trim().toLowerCase(), this.kdf, this.kdfIterations); diff --git a/angular/src/components/groupings.component.ts b/angular/src/components/groupings.component.ts index 1c3c27a1..30f0aa63 100644 --- a/angular/src/components/groupings.component.ts +++ b/angular/src/components/groupings.component.ts @@ -14,10 +14,7 @@ import { TreeNode } from 'jslib-common/models/domain/treeNode'; import { CollectionService } from 'jslib-common/abstractions/collection.service'; import { FolderService } from 'jslib-common/abstractions/folder.service'; -import { StorageService } from 'jslib-common/abstractions/storage.service'; -import { UserService } from 'jslib-common/abstractions/user.service'; - -import { ConstantsService } from 'jslib-common/services/constants.service'; +import { StateService } from 'jslib-common/abstractions/state.service'; @Directive() export class GroupingsComponent { @@ -50,15 +47,12 @@ export class GroupingsComponent { selectedCollectionId: string = null; private collapsedGroupings: Set; - private collapsedGroupingsKey: string; constructor(protected collectionService: CollectionService, protected folderService: FolderService, - protected storageService: StorageService, protected userService: UserService) { } + private stateService: StateService) { } async load(setLoaded = true) { - const userId = await this.userService.getUserId(); - this.collapsedGroupingsKey = ConstantsService.collapsedGroupingsKey + '_' + userId; - const collapsedGroupings = await this.storageService.get(this.collapsedGroupingsKey); + const collapsedGroupings = await this.stateService.getCollapsedGroupings(); if (collapsedGroupings == null) { this.collapsedGroupings = new Set(); } else { @@ -149,7 +143,7 @@ export class GroupingsComponent { this.selectedCollectionId = null; } - collapse(grouping: FolderView | CollectionView, idPrefix = '') { + async collapse(grouping: FolderView | CollectionView, idPrefix = '') { if (grouping.id == null) { return; } @@ -159,7 +153,7 @@ export class GroupingsComponent { } else { this.collapsedGroupings.add(id); } - this.storageService.save(this.collapsedGroupingsKey, this.collapsedGroupings); + await this.stateService.setCollapsedGroupings(this.collapsedGroupings); } isCollapsed(grouping: FolderView | CollectionView, idPrefix = '') { diff --git a/angular/src/components/icon.component.ts b/angular/src/components/icon.component.ts index b3a75d5a..1ae988c7 100644 --- a/angular/src/components/icon.component.ts +++ b/angular/src/components/icon.component.ts @@ -11,8 +11,6 @@ import { CipherView } from 'jslib-common/models/view/cipherView'; import { EnvironmentService } from 'jslib-common/abstractions/environment.service'; import { StateService } from 'jslib-common/abstractions/state.service'; -import { ConstantsService } from 'jslib-common/services/constants.service'; - import { Utils } from 'jslib-common/misc/utils'; const IconMap: any = { @@ -37,7 +35,7 @@ export class IconComponent implements OnChanges { private iconsUrl: string; - constructor(environmentService: EnvironmentService, protected stateService: StateService) { + constructor(environmentService: EnvironmentService, private stateService: StateService) { this.iconsUrl = environmentService.getIconsUrl(); } @@ -46,7 +44,7 @@ export class IconComponent implements OnChanges { // to avoid this we reset all state variables. this.image = null; this.fallbackImage = null; - this.imageEnabled = !(await this.stateService.get(ConstantsService.disableFaviconKey)); + this.imageEnabled = !(await this.stateService.getDisableFavicon()); this.load(); } diff --git a/angular/src/components/lock.component.ts b/angular/src/components/lock.component.ts index 329dd0c6..9eb8aedf 100644 --- a/angular/src/components/lock.component.ts +++ b/angular/src/components/lock.component.ts @@ -9,12 +9,8 @@ import { LogService } from 'jslib-common/abstractions/log.service'; import { MessagingService } from 'jslib-common/abstractions/messaging.service'; import { PlatformUtilsService } from 'jslib-common/abstractions/platformUtils.service'; import { StateService } from 'jslib-common/abstractions/state.service'; -import { StorageService } from 'jslib-common/abstractions/storage.service'; -import { UserService } from 'jslib-common/abstractions/user.service'; import { VaultTimeoutService } from 'jslib-common/abstractions/vaultTimeout.service'; -import { ConstantsService } from 'jslib-common/services/constants.service'; - import { EncString } from 'jslib-common/models/domain/encString'; import { SymmetricCryptoKey } from 'jslib-common/models/domain/symmetricCryptoKey'; @@ -23,6 +19,7 @@ import { PasswordVerificationRequest } from 'jslib-common/models/request/passwor import { Utils } from 'jslib-common/misc/utils'; import { HashPurpose } from 'jslib-common/enums/hashPurpose'; +import { KeySuffixOptions } from 'jslib-common/enums/keySuffixOptions'; @Directive() export class LockComponent implements OnInit { @@ -45,19 +42,18 @@ export class LockComponent implements OnInit { constructor(protected router: Router, protected i18nService: I18nService, protected platformUtilsService: PlatformUtilsService, protected messagingService: MessagingService, - protected userService: UserService, protected cryptoService: CryptoService, - protected storageService: StorageService, protected vaultTimeoutService: VaultTimeoutService, + protected cryptoService: CryptoService, protected vaultTimeoutService: VaultTimeoutService, protected environmentService: EnvironmentService, protected stateService: StateService, protected apiService: ApiService, private logService: LogService) { } async ngOnInit() { this.pinSet = await this.vaultTimeoutService.isPinLockSet(); - this.pinLock = (this.pinSet[0] && this.vaultTimeoutService.pinProtectedKey != null) || this.pinSet[1]; + this.pinLock = (this.pinSet[0] && (await this.stateService.getEncryptedPinProtected()) != null) || this.pinSet[1]; this.supportsBiometric = await this.platformUtilsService.supportsBiometric(); this.biometricLock = await this.vaultTimeoutService.isBiometricLockSet() && - (await this.cryptoService.hasKeyStored('biometric') || !this.platformUtilsService.supportsSecureStorage()); - this.biometricText = await this.storageService.get(ConstantsService.biometricText); - this.email = await this.userService.getEmail(); + (await this.cryptoService.hasKeyStored(KeySuffixOptions.Biometric) || !this.platformUtilsService.supportsSecureStorage()); + this.biometricText = await this.stateService.getBiometricText(); + this.email = await this.stateService.getEmail(); const webVaultUrl = this.environmentService.getWebVaultUrl(); const vaultUrl = webVaultUrl === 'https://vault.bitwarden.com' ? 'https://bitwarden.com' : webVaultUrl; @@ -76,17 +72,17 @@ export class LockComponent implements OnInit { return; } - const kdf = await this.userService.getKdf(); - const kdfIterations = await this.userService.getKdfIterations(); + const kdf = await this.stateService.getKdfType(); + const kdfIterations = await this.stateService.getKdfIterations(); if (this.pinLock) { let failed = true; try { if (this.pinSet[0]) { const key = await this.cryptoService.makeKeyFromPin(this.pin, this.email, kdf, kdfIterations, - this.vaultTimeoutService.pinProtectedKey); + await this.stateService.getDecryptedPinProtected()); const encKey = await this.cryptoService.getEncKey(key); - const protectedPin = await this.storageService.get(ConstantsService.protectedPin); + const protectedPin = await this.stateService.getProtectedPin(); const decPin = await this.cryptoService.decryptToUtf8(new EncString(protectedPin), encKey); failed = decPin !== this.pin; if (!failed) { @@ -137,11 +133,11 @@ export class LockComponent implements OnInit { if (passwordValid) { if (this.pinSet[0]) { - const protectedPin = await this.storageService.get(ConstantsService.protectedPin); + const protectedPin = await this.stateService.getProtectedPin(); const encKey = await this.cryptoService.getEncKey(key); const decPin = await this.cryptoService.decryptToUtf8(new EncString(protectedPin), encKey); const pinKey = await this.cryptoService.makePinKey(decPin, this.email, kdf, kdfIterations); - this.vaultTimeoutService.pinProtectedKey = await this.cryptoService.encrypt(key.key, pinKey); + await this.stateService.setDecryptedPinProtected(await this.cryptoService.encrypt(key.key, pinKey)); } this.setKeyAndContinue(key); } else { @@ -164,7 +160,7 @@ export class LockComponent implements OnInit { return; } - const success = (await this.cryptoService.getKey('biometric')) != null; + const success = (await this.cryptoService.getKey(KeySuffixOptions.Biometric)) != null; if (success) { await this.doContinue(); @@ -184,10 +180,10 @@ export class LockComponent implements OnInit { } private async doContinue() { - this.vaultTimeoutService.biometricLocked = false; - this.vaultTimeoutService.everBeenUnlocked = true; - const disableFavicon = await this.storageService.get(ConstantsService.disableFaviconKey); - await this.stateService.save(ConstantsService.disableFaviconKey, !!disableFavicon); + await this.stateService.setBiometricLocked(false); + await this.stateService.setEverBeenUnlocked(true); + const disableFavicon = await this.stateService.getDisableFavicon(); + await this.stateService.setDisableFavicon(!!disableFavicon); this.messagingService.send('unlocked'); if (this.onSuccessfulSubmit != null) { this.onSuccessfulSubmit(); diff --git a/angular/src/components/login.component.ts b/angular/src/components/login.component.ts index bfac5f53..0e2763c0 100644 --- a/angular/src/components/login.component.ts +++ b/angular/src/components/login.component.ts @@ -16,19 +16,11 @@ import { LogService } from 'jslib-common/abstractions/log.service'; import { PasswordGenerationService } from 'jslib-common/abstractions/passwordGeneration.service'; import { PlatformUtilsService } from 'jslib-common/abstractions/platformUtils.service'; import { StateService } from 'jslib-common/abstractions/state.service'; -import { StorageService } from 'jslib-common/abstractions/storage.service'; - -import { ConstantsService } from 'jslib-common/services/constants.service'; import { Utils } from 'jslib-common/misc/utils'; import { CaptchaProtectedComponent } from './captchaProtected.component'; -const Keys = { - rememberedEmail: 'rememberedEmail', - rememberEmail: 'rememberEmail', -}; - @Directive() export class LoginComponent extends CaptchaProtectedComponent implements OnInit { @Input() email: string = ''; @@ -50,19 +42,18 @@ export class LoginComponent extends CaptchaProtectedComponent implements OnInit platformUtilsService: PlatformUtilsService, i18nService: I18nService, protected stateService: StateService, environmentService: EnvironmentService, protected passwordGenerationService: PasswordGenerationService, - protected cryptoFunctionService: CryptoFunctionService, private storageService: StorageService, - protected logService: LogService) { + protected cryptoFunctionService: CryptoFunctionService, protected logService: LogService) { super(environmentService, i18nService, platformUtilsService); } async ngOnInit() { if (this.email == null || this.email === '') { - this.email = await this.storageService.get(Keys.rememberedEmail); + this.email = await this.stateService.getRememberedEmail(); if (this.email == null) { this.email = ''; } } - this.rememberEmail = await this.storageService.get(Keys.rememberEmail); + this.rememberEmail = await this.stateService.getRememberEmail(); if (this.rememberEmail == null) { this.rememberEmail = true; } @@ -93,11 +84,10 @@ export class LoginComponent extends CaptchaProtectedComponent implements OnInit try { this.formPromise = this.authService.logIn(this.email, this.masterPassword, this.captchaToken); const response = await this.formPromise; - await this.storageService.save(Keys.rememberEmail, this.rememberEmail); if (this.rememberEmail) { - await this.storageService.save(Keys.rememberedEmail, this.email); + await this.stateService.setRememberedEmail(this.email); } else { - await this.storageService.remove(Keys.rememberedEmail); + await this.stateService.setRememberedEmail(null); } if (this.handleCaptchaRequired(response)) { return; @@ -114,8 +104,8 @@ export class LoginComponent extends CaptchaProtectedComponent implements OnInit this.router.navigate([this.forcePasswordResetRoute]); } } else { - const disableFavicon = await this.storageService.get(ConstantsService.disableFaviconKey); - await this.stateService.save(ConstantsService.disableFaviconKey, !!disableFavicon); + const disableFavicon = await this.stateService.getDisableFavicon(); + await this.stateService.setDisableFavicon(!!disableFavicon); if (this.onSuccessfulLogin != null) { this.onSuccessfulLogin(); } @@ -151,8 +141,8 @@ export class LoginComponent extends CaptchaProtectedComponent implements OnInit const codeChallenge = Utils.fromBufferToUrlB64(codeVerifierHash); // Save sso params - await this.storageService.save(ConstantsService.ssoStateKey, state); - await this.storageService.save(ConstantsService.ssoCodeVerifierKey, ssoCodeVerifier); + await this.stateService.setSsoState(state); + await this.stateService.setSsoCodeVerifier(ssoCodeVerifier); // Build URI const webUrl = this.environmentService.getWebVaultUrl(); diff --git a/angular/src/components/premium.component.ts b/angular/src/components/premium.component.ts index 5b5b4c89..13efaa3b 100644 --- a/angular/src/components/premium.component.ts +++ b/angular/src/components/premium.component.ts @@ -4,7 +4,7 @@ import { ApiService } from 'jslib-common/abstractions/api.service'; import { I18nService } from 'jslib-common/abstractions/i18n.service'; import { LogService } from 'jslib-common/abstractions/log.service'; import { PlatformUtilsService } from 'jslib-common/abstractions/platformUtils.service'; -import { UserService } from 'jslib-common/abstractions/user.service'; +import { StateService } from 'jslib-common/abstractions/state.service'; @Directive() export class PremiumComponent implements OnInit { @@ -13,10 +13,11 @@ export class PremiumComponent implements OnInit { refreshPromise: Promise; constructor(protected i18nService: I18nService, protected platformUtilsService: PlatformUtilsService, - protected apiService: ApiService, protected userService: UserService, private logService: LogService) { } + protected apiService: ApiService, private logService: LogService, + protected stateService: StateService) { } async ngOnInit() { - this.isPremium = await this.userService.canAccessPremium(); + this.isPremium = await this.stateService.getCanAccessPremium(); } async refresh() { @@ -24,7 +25,7 @@ export class PremiumComponent implements OnInit { this.refreshPromise = this.apiService.refreshIdentityToken(); await this.refreshPromise; this.platformUtilsService.showToast('success', null, this.i18nService.t('refreshComplete')); - this.isPremium = await this.userService.canAccessPremium(); + this.isPremium = await this.stateService.getCanAccessPremium(); } catch (e) { this.logService.error(e); } diff --git a/angular/src/components/register.component.ts b/angular/src/components/register.component.ts index fd91af29..df0579bc 100644 --- a/angular/src/components/register.component.ts +++ b/angular/src/components/register.component.ts @@ -141,7 +141,7 @@ export class RegisterComponent extends CaptchaProtectedComponent implements OnIn const request = new RegisterRequest(this.email, this.name, hashedPassword, this.hint, encKey[1].encryptedString, kdf, kdfIterations, this.referenceData, this.captchaToken); request.keys = new KeysRequest(keys[0], keys[1].encryptedString); - const orgInvite = await this.stateService.get('orgInvitation'); + const orgInvite = await this.stateService.getOrganizationInvitation(); if (orgInvite != null && orgInvite.token != null && orgInvite.organizationUserId != null) { request.token = orgInvite.token; request.organizationUserId = orgInvite.organizationUserId; diff --git a/angular/src/components/send/add-edit.component.ts b/angular/src/components/send/add-edit.component.ts index 70bd87ba..69d5c7d4 100644 --- a/angular/src/components/send/add-edit.component.ts +++ b/angular/src/components/send/add-edit.component.ts @@ -17,7 +17,7 @@ import { MessagingService } from 'jslib-common/abstractions/messaging.service'; import { PlatformUtilsService } from 'jslib-common/abstractions/platformUtils.service'; import { PolicyService } from 'jslib-common/abstractions/policy.service'; import { SendService } from 'jslib-common/abstractions/send.service'; -import { UserService } from 'jslib-common/abstractions/user.service'; +import { StateService } from 'jslib-common/abstractions/state.service'; import { SendFileView } from 'jslib-common/models/view/sendFileView'; import { SendTextView } from 'jslib-common/models/view/sendTextView'; @@ -57,9 +57,9 @@ export class AddEditComponent implements OnInit { constructor(protected i18nService: I18nService, protected platformUtilsService: PlatformUtilsService, protected environmentService: EnvironmentService, protected datePipe: DatePipe, - protected sendService: SendService, protected userService: UserService, - protected messagingService: MessagingService, protected policyService: PolicyService, - private logService: LogService) { + protected sendService: SendService, protected messagingService: MessagingService, + protected policyService: PolicyService, private logService: LogService, + protected stateService: StateService) { this.typeOptions = [ { name: i18nService.t('sendTypeFile'), value: SendType.File }, { name: i18nService.t('sendTypeText'), value: SendType.Text }, @@ -108,8 +108,8 @@ export class AddEditComponent implements OnInit { this.disableHideEmail = await this.policyService.policyAppliesToUser(PolicyType.SendOptions, p => p.data.disableHideEmail); - this.canAccessPremium = await this.userService.canAccessPremium(); - this.emailVerified = await this.userService.getEmailVerified(); + this.canAccessPremium = await this.stateService.getCanAccessPremium(); + this.emailVerified = await this.stateService.getEmailVerified(); if (!this.canAccessPremium || !this.emailVerified) { this.type = SendType.Text; } diff --git a/angular/src/components/send/send.component.ts b/angular/src/components/send/send.component.ts index 77f36459..c9b83a5c 100644 --- a/angular/src/components/send/send.component.ts +++ b/angular/src/components/send/send.component.ts @@ -16,7 +16,6 @@ import { PlatformUtilsService } from 'jslib-common/abstractions/platformUtils.se import { PolicyService } from 'jslib-common/abstractions/policy.service'; import { SearchService } from 'jslib-common/abstractions/search.service'; import { SendService } from 'jslib-common/abstractions/send.service'; -import { UserService } from 'jslib-common/abstractions/user.service'; @Directive() export class SendComponent implements OnInit { @@ -48,8 +47,7 @@ export class SendComponent implements OnInit { constructor(protected sendService: SendService, protected i18nService: I18nService, protected platformUtilsService: PlatformUtilsService, protected environmentService: EnvironmentService, protected ngZone: NgZone, protected searchService: SearchService, - protected policyService: PolicyService, protected userService: UserService, - private logService: LogService) { } + protected policyService: PolicyService, private logService: LogService) { } async ngOnInit() { this.disableSend = await this.policyService.policyAppliesToUser(PolicyType.DisableSend); diff --git a/angular/src/components/set-password.component.ts b/angular/src/components/set-password.component.ts index c12e32e6..c828a793 100644 --- a/angular/src/components/set-password.component.ts +++ b/angular/src/components/set-password.component.ts @@ -13,8 +13,8 @@ import { MessagingService } from 'jslib-common/abstractions/messaging.service'; import { PasswordGenerationService } from 'jslib-common/abstractions/passwordGeneration.service'; import { PlatformUtilsService } from 'jslib-common/abstractions/platformUtils.service'; import { PolicyService } from 'jslib-common/abstractions/policy.service'; +import { StateService } from 'jslib-common/abstractions/state.service'; import { SyncService } from 'jslib-common/abstractions/sync.service'; -import { UserService } from 'jslib-common/abstractions/user.service'; import { EncString } from 'jslib-common/models/domain/encString'; import { SymmetricCryptoKey } from 'jslib-common/models/domain/symmetricCryptoKey'; @@ -42,12 +42,13 @@ export class SetPasswordComponent extends BaseChangePasswordComponent { onSuccessfulChangePassword: () => Promise; successRoute = 'vault'; - constructor(i18nService: I18nService, cryptoService: CryptoService, messagingService: MessagingService, - userService: UserService, passwordGenerationService: PasswordGenerationService, - platformUtilsService: PlatformUtilsService, policyService: PolicyService, protected router: Router, - private apiService: ApiService, private syncService: SyncService, private route: ActivatedRoute) { - super(i18nService, cryptoService, messagingService, userService, passwordGenerationService, - platformUtilsService, policyService); + constructor(i18nService: I18nService, cryptoService: CryptoService, + messagingService: MessagingService, passwordGenerationService: PasswordGenerationService, + platformUtilsService: PlatformUtilsService, policyService: PolicyService, + protected router: Router, private apiService: ApiService, + private syncService: SyncService, private route: ActivatedRoute, stateService: StateService) { + super(i18nService, cryptoService, messagingService, passwordGenerationService, + platformUtilsService, policyService, stateService); } async ngOnInit() { @@ -102,7 +103,7 @@ export class SetPasswordComponent extends BaseChangePasswordComponent { if (response == null) { throw new Error(this.i18nService.t('resetPasswordOrgKeysError')); } - const userId = await this.userService.getUserId(); + const userId = await this.stateService.getUserId(); const publicKey = Utils.fromB64ToArray(response.publicKey); // RSA Encrypt user's encKey.key with organization public key @@ -138,8 +139,8 @@ export class SetPasswordComponent extends BaseChangePasswordComponent { } private async onSetPasswordSuccess(key: SymmetricCryptoKey, encKey: [SymmetricCryptoKey, EncString], keys: [string, EncString]) { - await this.userService.setInformation(await this.userService.getUserId(), await this.userService.getEmail(), - this.kdf, this.kdfIterations); + await this.stateService.setKdfType(this.kdf); + await this.stateService.setKdfIterations(this.kdfIterations); await this.cryptoService.setKey(key); await this.cryptoService.setEncKey(encKey[1].encryptedString); await this.cryptoService.setEncPrivateKey(keys[1].encryptedString); diff --git a/angular/src/components/set-pin.component.ts b/angular/src/components/set-pin.component.ts index 41a2383c..36210ea8 100644 --- a/angular/src/components/set-pin.component.ts +++ b/angular/src/components/set-pin.component.ts @@ -1,11 +1,7 @@ import { Directive } from '@angular/core'; import { CryptoService } from 'jslib-common/abstractions/crypto.service'; -import { StorageService } from 'jslib-common/abstractions/storage.service'; -import { UserService } from 'jslib-common/abstractions/user.service'; -import { VaultTimeoutService } from 'jslib-common/abstractions/vaultTimeout.service'; - -import { ConstantsService } from 'jslib-common/services/constants.service'; +import { StateService } from 'jslib-common/abstractions/state.service'; import { Utils } from 'jslib-common/misc/utils'; @@ -18,8 +14,8 @@ export class SetPinComponent { showPin = false; masterPassOnRestart = true; - constructor(private modalRef: ModalRef, private cryptoService: CryptoService, private userService: UserService, - private storageService: StorageService, private vaultTimeoutService: VaultTimeoutService) { } + constructor(private modalRef: ModalRef, private cryptoService: CryptoService, + private stateService: StateService) { } toggleVisibility() { this.showPin = !this.showPin; @@ -30,18 +26,18 @@ export class SetPinComponent { this.modalRef.close(false); } - const kdf = await this.userService.getKdf(); - const kdfIterations = await this.userService.getKdfIterations(); - const email = await this.userService.getEmail(); + const kdf = await this.stateService.getKdfType(); + const kdfIterations = await this.stateService.getKdfIterations(); + const email = await this.stateService.getEmail(); const pinKey = await this.cryptoService.makePinKey(this.pin, email, kdf, kdfIterations); const key = await this.cryptoService.getKey(); const pinProtectedKey = await this.cryptoService.encrypt(key.key, pinKey); if (this.masterPassOnRestart) { const encPin = await this.cryptoService.encrypt(this.pin); - await this.storageService.save(ConstantsService.protectedPin, encPin.encryptedString); - this.vaultTimeoutService.pinProtectedKey = pinProtectedKey; + await this.stateService.setProtectedPin(encPin.encryptedString); + await this.stateService.setDecryptedPinProtected(pinProtectedKey); } else { - await this.storageService.save(ConstantsService.pinProtectedKey, pinProtectedKey.encryptedString); + await this.stateService.setEncryptedPinProtected(pinProtectedKey.encryptedString); } this.modalRef.close(true); diff --git a/angular/src/components/share.component.ts b/angular/src/components/share.component.ts index e5badc37..1812f427 100644 --- a/angular/src/components/share.component.ts +++ b/angular/src/components/share.component.ts @@ -12,8 +12,8 @@ import { CipherService } from 'jslib-common/abstractions/cipher.service'; import { CollectionService } from 'jslib-common/abstractions/collection.service'; import { I18nService } from 'jslib-common/abstractions/i18n.service'; import { LogService } from 'jslib-common/abstractions/log.service'; +import { OrganizationService } from 'jslib-common/abstractions/organization.service'; import { PlatformUtilsService } from 'jslib-common/abstractions/platformUtils.service'; -import { UserService } from 'jslib-common/abstractions/user.service'; import { Organization } from 'jslib-common/models/domain/organization'; import { CipherView } from 'jslib-common/models/view/cipherView'; @@ -35,8 +35,8 @@ export class ShareComponent implements OnInit { protected writeableCollections: CollectionView[] = []; constructor(protected collectionService: CollectionService, protected platformUtilsService: PlatformUtilsService, - protected i18nService: I18nService, protected userService: UserService, - protected cipherService: CipherService, private logService: LogService) { } + protected i18nService: I18nService, protected cipherService: CipherService, + private logService: LogService, protected organizationService: OrganizationService) { } async ngOnInit() { await this.load(); @@ -45,7 +45,7 @@ export class ShareComponent implements OnInit { async load() { const allCollections = await this.collectionService.getAllDecrypted(); this.writeableCollections = allCollections.map(c => c).filter(c => !c.readOnly); - const orgs = await this.userService.getAllOrganizations(); + const orgs = await this.organizationService.getAll(); this.organizations = orgs.sort(Utils.getSortFunction(this.i18nService, 'name')) .filter(o => o.enabled && o.status === OrganizationUserStatusType.Confirmed); diff --git a/angular/src/components/sso.component.ts b/angular/src/components/sso.component.ts index 3e950bec..4c1d718f 100644 --- a/angular/src/components/sso.component.ts +++ b/angular/src/components/sso.component.ts @@ -15,9 +15,6 @@ import { LogService } from 'jslib-common/abstractions/log.service'; import { PasswordGenerationService } from 'jslib-common/abstractions/passwordGeneration.service'; import { PlatformUtilsService } from 'jslib-common/abstractions/platformUtils.service'; import { StateService } from 'jslib-common/abstractions/state.service'; -import { StorageService } from 'jslib-common/abstractions/storage.service'; - -import { ConstantsService } from 'jslib-common/services/constants.service'; import { Utils } from 'jslib-common/misc/utils'; @@ -47,18 +44,18 @@ export class SsoComponent { constructor(protected authService: AuthService, protected router: Router, protected i18nService: I18nService, protected route: ActivatedRoute, - protected storageService: StorageService, protected stateService: StateService, - protected platformUtilsService: PlatformUtilsService, protected apiService: ApiService, - protected cryptoFunctionService: CryptoFunctionService, protected environmentService: EnvironmentService, - protected passwordGenerationService: PasswordGenerationService, protected logService: LogService) { } + protected stateService: StateService, protected platformUtilsService: PlatformUtilsService, + protected apiService: ApiService, protected cryptoFunctionService: CryptoFunctionService, + protected environmentService: EnvironmentService, protected passwordGenerationService: PasswordGenerationService, + protected logService: LogService) { } async ngOnInit() { this.route.queryParams.pipe(first()).subscribe(async qParams => { if (qParams.code != null && qParams.state != null) { - const codeVerifier = await this.storageService.get(ConstantsService.ssoCodeVerifierKey); - const state = await this.storageService.get(ConstantsService.ssoStateKey); - await this.storageService.remove(ConstantsService.ssoCodeVerifierKey); - await this.storageService.remove(ConstantsService.ssoStateKey); + const codeVerifier = await this.stateService.getSsoCodeVerifier(); + const state = await this.stateService.getSsoState(); + await this.stateService.setSsoCodeVerifier(null); + await this.stateService.setSsoState(null); if (qParams.code != null && codeVerifier != null && state != null && this.checkState(state, qParams.state)) { await this.logIn(qParams.code, codeVerifier, this.getOrgIdentiferFromState(qParams.state)); } @@ -106,7 +103,7 @@ export class SsoComponent { const codeVerifier = await this.passwordGenerationService.generatePassword(passwordOptions); const codeVerifierHash = await this.cryptoFunctionService.hash(codeVerifier, 'sha256'); codeChallenge = Utils.fromBufferToUrlB64(codeVerifierHash); - await this.storageService.save(ConstantsService.ssoCodeVerifierKey, codeVerifier); + await this.stateService.setSsoCodeVerifier(codeVerifier); } if (state == null) { @@ -120,7 +117,7 @@ export class SsoComponent { state += `_identifier=${this.identifier}`; // Save state (regardless of new or existing) - await this.storageService.save(ConstantsService.ssoStateKey, state); + await this.stateService.setSsoState(state); let authorizeUrl = this.environmentService.getIdentityUrl() + '/connect/authorize?' + 'client_id=' + this.clientId + '&redirect_uri=' + encodeURIComponent(this.redirectUri) + '&' + @@ -170,8 +167,8 @@ export class SsoComponent { this.router.navigate([this.forcePasswordResetRoute]); } } else { - const disableFavicon = await this.storageService.get(ConstantsService.disableFaviconKey); - await this.stateService.save(ConstantsService.disableFaviconKey, !!disableFavicon); + const disableFavicon = await this.stateService.getDisableFavicon(); + await this.stateService.setDisableFavicon(!!disableFavicon); if (this.onSuccessfulLogin != null) { this.onSuccessfulLogin(); } diff --git a/angular/src/components/two-factor.component.ts b/angular/src/components/two-factor.component.ts index 18deda6e..7bb4fc1b 100644 --- a/angular/src/components/two-factor.component.ts +++ b/angular/src/components/two-factor.component.ts @@ -20,10 +20,8 @@ import { I18nService } from 'jslib-common/abstractions/i18n.service'; import { LogService } from 'jslib-common/abstractions/log.service'; import { PlatformUtilsService } from 'jslib-common/abstractions/platformUtils.service'; import { StateService } from 'jslib-common/abstractions/state.service'; -import { StorageService } from 'jslib-common/abstractions/storage.service'; import { TwoFactorProviders } from 'jslib-common/services/auth.service'; -import { ConstantsService } from 'jslib-common/services/constants.service'; import * as DuoWebSDK from 'duo_web_sdk'; import { WebAuthnIFrame } from 'jslib-common/misc/webauthn_iframe'; @@ -58,8 +56,7 @@ export class TwoFactorComponent implements OnInit, OnDestroy { protected i18nService: I18nService, protected apiService: ApiService, protected platformUtilsService: PlatformUtilsService, protected win: Window, protected environmentService: EnvironmentService, protected stateService: StateService, - protected storageService: StorageService, protected route: ActivatedRoute, - protected logService: LogService) { + protected route: ActivatedRoute, protected logService: LogService) { this.webAuthnSupported = this.platformUtilsService.supportsWebAuthn(win); } @@ -179,8 +176,8 @@ export class TwoFactorComponent implements OnInit, OnDestroy { async doSubmit() { this.formPromise = this.authService.logInTwoFactor(this.selectedProviderType, this.token, this.remember); const response: AuthResult = await this.formPromise; - const disableFavicon = await this.storageService.get(ConstantsService.disableFaviconKey); - await this.stateService.save(ConstantsService.disableFaviconKey, !!disableFavicon); + const disableFavicon = await this.stateService.getDisableFavicon(); + await this.stateService.setDisableFavicon(!!disableFavicon); if (this.onSuccessfulLogin != null) { this.onSuccessfulLogin(); } diff --git a/angular/src/components/update-temp-password.component.ts b/angular/src/components/update-temp-password.component.ts index 29e54521..ffb27db2 100644 --- a/angular/src/components/update-temp-password.component.ts +++ b/angular/src/components/update-temp-password.component.ts @@ -8,8 +8,8 @@ import { MessagingService } from 'jslib-common/abstractions/messaging.service'; import { PasswordGenerationService } from 'jslib-common/abstractions/passwordGeneration.service'; import { PlatformUtilsService } from 'jslib-common/abstractions/platformUtils.service'; import { PolicyService } from 'jslib-common/abstractions/policy.service'; +import { StateService } from 'jslib-common/abstractions/state.service'; import { SyncService } from 'jslib-common/abstractions/sync.service'; -import { UserService } from 'jslib-common/abstractions/user.service'; import { ChangePasswordComponent as BaseChangePasswordComponent } from './change-password.component'; @@ -30,11 +30,11 @@ export class UpdateTempPasswordComponent extends BaseChangePasswordComponent { constructor(i18nService: I18nService, platformUtilsService: PlatformUtilsService, passwordGenerationService: PasswordGenerationService, policyService: PolicyService, - cryptoService: CryptoService, userService: UserService, - messagingService: MessagingService, private apiService: ApiService, + cryptoService: CryptoService, messagingService: MessagingService, + private apiService: ApiService, stateService: StateService, private syncService: SyncService, private logService: LogService) { - super(i18nService, cryptoService, messagingService, userService, passwordGenerationService, - platformUtilsService, policyService); + super(i18nService, cryptoService, messagingService, passwordGenerationService, + platformUtilsService, policyService, stateService); } async ngOnInit() { @@ -49,9 +49,9 @@ export class UpdateTempPasswordComponent extends BaseChangePasswordComponent { async setupSubmitActions(): Promise { this.enforcedPolicyOptions = await this.policyService.getMasterPasswordPolicyOptions(); - this.email = await this.userService.getEmail(); - this.kdf = await this.userService.getKdf(); - this.kdfIterations = await this.userService.getKdfIterations(); + this.email = await this.stateService.getEmail(); + this.kdf = await this.stateService.getKdfType(); + this.kdfIterations = await this.stateService.getKdfIterations(); return true; } diff --git a/angular/src/components/view.component.ts b/angular/src/components/view.component.ts index 8e12634f..6a3da19e 100644 --- a/angular/src/components/view.component.ts +++ b/angular/src/components/view.component.ts @@ -24,9 +24,9 @@ import { I18nService } from 'jslib-common/abstractions/i18n.service'; import { LogService } from 'jslib-common/abstractions/log.service'; import { PasswordRepromptService } from 'jslib-common/abstractions/passwordReprompt.service'; import { PlatformUtilsService } from 'jslib-common/abstractions/platformUtils.service'; +import { StateService } from 'jslib-common/abstractions/state.service'; import { TokenService } from 'jslib-common/abstractions/token.service'; import { TotpService } from 'jslib-common/abstractions/totp.service'; -import { UserService } from 'jslib-common/abstractions/user.service'; import { ErrorResponse } from 'jslib-common/models/response/errorResponse'; @@ -67,9 +67,9 @@ export class ViewComponent implements OnDestroy, OnInit { protected cryptoService: CryptoService, protected platformUtilsService: PlatformUtilsService, protected auditService: AuditService, protected win: Window, protected broadcasterService: BroadcasterService, protected ngZone: NgZone, - protected changeDetectorRef: ChangeDetectorRef, protected userService: UserService, - protected eventService: EventService, protected apiService: ApiService, - protected passwordRepromptService: PasswordRepromptService, private logService: LogService) { } + protected changeDetectorRef: ChangeDetectorRef, protected eventService: EventService, + protected apiService: ApiService, protected passwordRepromptService: PasswordRepromptService, + private logService: LogService, protected stateService: StateService) { } ngOnInit() { this.broadcasterService.subscribe(BroadcasterSubscriptionId, (message: any) => { @@ -96,7 +96,7 @@ export class ViewComponent implements OnDestroy, OnInit { const cipher = await this.cipherService.get(this.cipherId); this.cipher = await cipher.decrypt(); - this.canAccessPremium = await this.userService.canAccessPremium(); + this.canAccessPremium = await this.stateService.getCanAccessPremium(); if (this.cipher.type === CipherType.Login && this.cipher.login.totp && (cipher.organizationUseTotp || this.canAccessPremium)) { diff --git a/angular/src/services/auth-guard.service.ts b/angular/src/services/auth-guard.service.ts index f80f8aca..6b1f0f15 100644 --- a/angular/src/services/auth-guard.service.ts +++ b/angular/src/services/auth-guard.service.ts @@ -7,16 +7,16 @@ import { } from '@angular/router'; import { MessagingService } from 'jslib-common/abstractions/messaging.service'; -import { UserService } from 'jslib-common/abstractions/user.service'; +import { StateService } from 'jslib-common/abstractions/state.service'; import { VaultTimeoutService } from 'jslib-common/abstractions/vaultTimeout.service'; @Injectable() export class AuthGuardService implements CanActivate { - constructor(private vaultTimeoutService: VaultTimeoutService, private userService: UserService, - private router: Router, private messagingService: MessagingService) { } + constructor(private vaultTimeoutService: VaultTimeoutService, private router: Router, + private messagingService: MessagingService, private stateService: StateService) { } async canActivate(route: ActivatedRouteSnapshot, routerState: RouterStateSnapshot) { - const isAuthed = await this.userService.isAuthenticated(); + const isAuthed = this.stateService.getIsAuthenticated(); if (!isAuthed) { this.messagingService.send('authBlocked'); return false; diff --git a/angular/src/services/lock-guard.service.ts b/angular/src/services/lock-guard.service.ts index 400eedc5..c9e81e0d 100644 --- a/angular/src/services/lock-guard.service.ts +++ b/angular/src/services/lock-guard.service.ts @@ -4,29 +4,25 @@ import { Router, } from '@angular/router'; -import { UserService } from 'jslib-common/abstractions/user.service'; +import { StateService } from 'jslib-common/abstractions/state.service'; import { VaultTimeoutService } from 'jslib-common/abstractions/vaultTimeout.service'; @Injectable() export class LockGuardService implements CanActivate { - - protected homepage = 'vault'; - constructor(private vaultTimeoutService: VaultTimeoutService, private userService: UserService, - private router: Router) { } + constructor(private vaultTimeoutService: VaultTimeoutService, private router: Router, + private stateService: StateService) { } async canActivate() { - const isAuthed = await this.userService.isAuthenticated(); - if (isAuthed) { - const locked = await this.vaultTimeoutService.isLocked(); - if (locked) { - return true; - } else { - this.router.navigate([this.homepage]); - return false; - } + if (!await this.stateService.getIsAuthenticated()) { + this.router.navigate(['login']); + return false; } - this.router.navigate(['']); - return false; + if (!await this.vaultTimeoutService.isLocked()) { + this.router.navigate(['vault']); + return false; + } + + return true; } } diff --git a/angular/src/services/unauth-guard.service.ts b/angular/src/services/unauth-guard.service.ts index 786241b8..663fced5 100644 --- a/angular/src/services/unauth-guard.service.ts +++ b/angular/src/services/unauth-guard.service.ts @@ -1,22 +1,21 @@ import { Injectable } from '@angular/core'; import { - ActivatedRouteSnapshot, CanActivate, Router, } from '@angular/router'; -import { UserService } from 'jslib-common/abstractions/user.service'; +import { StateService } from 'jslib-common/abstractions/state.service'; import { VaultTimeoutService } from 'jslib-common/abstractions/vaultTimeout.service'; @Injectable() export class UnauthGuardService implements CanActivate { protected homepage = 'vault'; - constructor(private vaultTimeoutService: VaultTimeoutService, private userService: UserService, - private router: Router) { } + constructor(private vaultTimeoutService: VaultTimeoutService, private router: Router, + private stateService: StateService) { } async canActivate() { - const isAuthed = await this.userService.isAuthenticated(); + const isAuthed = await this.stateService.getIsAuthenticated(); if (isAuthed) { const locked = await this.vaultTimeoutService.isLocked(); if (locked) { @@ -26,7 +25,5 @@ export class UnauthGuardService implements CanActivate { } return false; } - - return true; } } diff --git a/electron/src/biometric.darwin.main.ts b/electron/src/biometric.darwin.main.ts index 26d3bd74..162c7722 100644 --- a/electron/src/biometric.darwin.main.ts +++ b/electron/src/biometric.darwin.main.ts @@ -1,21 +1,18 @@ import { ipcMain, systemPreferences } from 'electron'; -import { I18nService } from 'jslib-common/abstractions/i18n.service'; -import { StorageService } from 'jslib-common/abstractions/storage.service'; -import { ConstantsService } from 'jslib-common/services/constants.service'; - import { BiometricMain } from 'jslib-common/abstractions/biometric.main'; -import { ElectronConstants } from './electronConstants'; +import { I18nService } from 'jslib-common/abstractions/i18n.service'; +import { StateService } from 'jslib-common/abstractions/state.service'; export default class BiometricDarwinMain implements BiometricMain { isError: boolean = false; - constructor(private storageService: StorageService, private i18nservice: I18nService) {} + constructor(private i18nservice: I18nService, private stateService: StateService) {} async init() { - this.storageService.save(ElectronConstants.enableBiometric, await this.supportsBiometric()); - this.storageService.save(ConstantsService.biometricText, 'unlockWithTouchId'); - this.storageService.save(ElectronConstants.noAutoPromptBiometricsText, 'noAutoPromptTouchId'); + await this.stateService.setEnableBiometric(await this.supportsBiometric()); + await this.stateService.setBiometricText('unlockWithTouchId'); + await this.stateService.setNoAutoPromptBiometricsText('noAutoPromptTouchId'); ipcMain.on('biometric', async (event: any, message: any) => { event.returnValue = await this.authenticateBiometric(); diff --git a/electron/src/biometric.windows.main.ts b/electron/src/biometric.windows.main.ts index d33875b7..c541b7fe 100644 --- a/electron/src/biometric.windows.main.ts +++ b/electron/src/biometric.windows.main.ts @@ -1,22 +1,20 @@ import { ipcMain } from 'electron'; import forceFocus from 'forcefocus'; -import { ElectronConstants } from './electronConstants'; import { WindowMain } from './window.main'; import { BiometricMain } from 'jslib-common/abstractions/biometric.main'; import { I18nService } from 'jslib-common/abstractions/i18n.service'; import { LogService } from 'jslib-common/abstractions/log.service'; -import { StorageService } from 'jslib-common/abstractions/storage.service'; -import { ConstantsService } from 'jslib-common/services/constants.service'; +import { StateService } from 'jslib-common/abstractions/state.service'; export default class BiometricWindowsMain implements BiometricMain { isError: boolean = false; private windowsSecurityCredentialsUiModule: any; - constructor(private storageService: StorageService, private i18nservice: I18nService, private windowMain: WindowMain, - private logService: LogService) { } + constructor(private i18nservice: I18nService, private windowMain: WindowMain, + private stateService: StateService, private logService: LogService) { } async init() { this.windowsSecurityCredentialsUiModule = this.getWindowsSecurityCredentialsUiModule(); @@ -27,9 +25,9 @@ export default class BiometricWindowsMain implements BiometricMain { // store error state so we can let the user know on the settings page this.isError = true; } - this.storageService.save(ElectronConstants.enableBiometric, supportsBiometric); - this.storageService.save(ConstantsService.biometricText, 'unlockWithWindowsHello'); - this.storageService.save(ElectronConstants.noAutoPromptBiometricsText, 'noAutoPromptWindowsHello'); + this.stateService.setEnableBiometric(supportsBiometric); + this.stateService.setBiometricText('unlockWithWindowsHello'); + this.stateService.setNoAutoPromptBiometricsText('noAutoPromptWindowsHello'); ipcMain.on('biometric', async (event: any, message: any) => { event.returnValue = await this.authenticateBiometric(); diff --git a/electron/src/electronConstants.ts b/electron/src/electronConstants.ts deleted file mode 100644 index 68be1956..00000000 --- a/electron/src/electronConstants.ts +++ /dev/null @@ -1,14 +0,0 @@ -export class ElectronConstants { - static readonly enableMinimizeToTrayKey: string = 'enableMinimizeToTray'; - static readonly enableCloseToTrayKey: string = 'enableCloseToTray'; - static readonly enableTrayKey: string = 'enableTray'; - static readonly enableStartToTrayKey: string = 'enableStartToTrayKey'; - static readonly enableAlwaysOnTopKey: string = 'enableAlwaysOnTopKey'; - static readonly minimizeOnCopyToClipboardKey: string = 'minimizeOnCopyToClipboardKey'; - static readonly enableBiometric: string = 'enabledBiometric'; - static readonly enableBrowserIntegration: string = 'enableBrowserIntegration'; - static readonly enableBrowserIntegrationFingerprint: string = 'enableBrowserIntegrationFingerprint'; - static readonly alwaysShowDock: string = 'alwaysShowDock'; - static readonly openAtLogin: string = 'openAtLogin'; - static readonly noAutoPromptBiometricsText: string = 'noAutoPromptBiometricsText'; -} diff --git a/electron/src/tray.main.ts b/electron/src/tray.main.ts index 30df8410..c7508904 100644 --- a/electron/src/tray.main.ts +++ b/electron/src/tray.main.ts @@ -2,7 +2,6 @@ import { app, BrowserWindow, Menu, - MenuItem, MenuItemConstructorOptions, nativeImage, Tray, @@ -10,9 +9,8 @@ import { import * as path from 'path'; import { I18nService } from 'jslib-common/abstractions/i18n.service'; -import { StorageService } from 'jslib-common/abstractions/storage.service'; +import { StateService } from 'jslib-common/abstractions/state.service'; -import { ElectronConstants } from './electronConstants'; import { WindowMain } from './window.main'; export class TrayMain { @@ -24,7 +22,7 @@ export class TrayMain { private pressedIcon: Electron.NativeImage; constructor(private windowMain: WindowMain, private i18nService: I18nService, - private storageService: StorageService) { + private stateService: StateService) { if (process.platform === 'win32') { this.icon = path.join(__dirname, '/images/icon.ico'); } else if (process.platform === 'darwin') { @@ -55,21 +53,21 @@ export class TrayMain { } this.contextMenu = Menu.buildFromTemplate(menuItemOptions); - if (await this.storageService.get(ElectronConstants.enableTrayKey)) { + if (await this.stateService.getEnableTray()) { this.showTray(); } } setupWindowListeners(win: BrowserWindow) { win.on('minimize', async (e: Event) => { - if (await this.storageService.get(ElectronConstants.enableMinimizeToTrayKey)) { + if (await this.stateService.getEnableMinimizeToTray()) { e.preventDefault(); this.hideToTray(); } }); win.on('close', async (e: Event) => { - if (await this.storageService.get(ElectronConstants.enableCloseToTrayKey)) { + if (await this.stateService.getEnableCloseToTray()) { if (!this.windowMain.isQuitting) { e.preventDefault(); this.hideToTray(); @@ -78,7 +76,7 @@ export class TrayMain { }); win.on('show', async (e: Event) => { - const enableTray = await this.storageService.get(ElectronConstants.enableTrayKey); + const enableTray = await this.stateService.getEnableTray(); if (!enableTray) { setTimeout(() => this.removeTray(false), 100); } @@ -103,7 +101,7 @@ export class TrayMain { if (this.windowMain.win != null) { this.windowMain.win.hide(); } - if (this.isDarwin() && !await this.storageService.get(ElectronConstants.alwaysShowDock)) { + if (this.isDarwin() && !await this.stateService.getAlwaysShowDock()) { this.hideDock(); } } @@ -167,7 +165,7 @@ export class TrayMain { } if (this.windowMain.win.isVisible()) { this.windowMain.win.hide(); - if (this.isDarwin() && !await this.storageService.get(ElectronConstants.alwaysShowDock)) { + if (this.isDarwin() && !await this.stateService.getAlwaysShowDock()) { this.hideDock(); } } else { diff --git a/electron/src/window.main.ts b/electron/src/window.main.ts index f51dc114..b8cb5c20 100644 --- a/electron/src/window.main.ts +++ b/electron/src/window.main.ts @@ -7,9 +7,8 @@ import * as path from 'path'; import * as url from 'url'; import { LogService } from 'jslib-common/abstractions/log.service'; -import { StorageService } from 'jslib-common/abstractions/storage.service'; +import { StateService } from 'jslib-common/abstractions/state.service'; -import { ElectronConstants } from './electronConstants'; import { cleanUserAgent, isDev, @@ -17,11 +16,8 @@ import { isSnapStore, } from './utils'; +const mainWindowSizeKey = 'mainWindowSize'; const WindowEventHandlingDelay = 100; -const Keys = { - mainWindowSize: 'mainWindowSize', -}; - export class WindowMain { win: BrowserWindow; isQuitting: boolean = false; @@ -30,7 +26,7 @@ export class WindowMain { private windowStates: { [key: string]: any; } = {}; private enableAlwaysOnTop: boolean = false; - constructor(private storageService: StorageService, private logService: LogService, + constructor(private stateService: StateService, private logService: LogService, private hideTitleBar = false, private defaultWidth = 950, private defaultHeight = 600, private argvCallback: (argv: string[]) => void = null, private createWindowCallback: (win: BrowserWindow) => void) { } @@ -81,7 +77,7 @@ export class WindowMain { // Quit when all windows are closed. app.on('window-all-closed', () => { // On OS X it is common for applications and their menu bar - // to stay active until the user quits explicitly with Cmd + Q + // to stay KKKactive until the user quits explicitly with Cmd + Q if (process.platform !== 'darwin' || this.isQuitting || isMacAppStore()) { app.quit(); } @@ -107,100 +103,104 @@ export class WindowMain { } async createWindow(): Promise { - this.windowStates[Keys.mainWindowSize] = await this.getWindowState(Keys.mainWindowSize, this.defaultWidth, - this.defaultHeight); - this.enableAlwaysOnTop = await this.storageService.get(ElectronConstants.enableAlwaysOnTopKey); + try { + this.windowStates[mainWindowSizeKey] = await this.getWindowState(mainWindowSizeKey, this.defaultWidth, + this.defaultHeight); + this.enableAlwaysOnTop = await this.stateService.getEnableAlwaysOnTop(); - // Create the browser window. - this.win = new BrowserWindow({ - width: this.windowStates[Keys.mainWindowSize].width, - height: this.windowStates[Keys.mainWindowSize].height, - minWidth: 680, - minHeight: 500, - x: this.windowStates[Keys.mainWindowSize].x, - y: this.windowStates[Keys.mainWindowSize].y, - title: app.name, - icon: process.platform === 'linux' ? path.join(__dirname, '/images/icon.png') : undefined, - titleBarStyle: this.hideTitleBar && process.platform === 'darwin' ? 'hiddenInset' : undefined, - show: false, - backgroundColor: '#fff', - alwaysOnTop: this.enableAlwaysOnTop, - webPreferences: { - nodeIntegration: true, - backgroundThrottling: false, - contextIsolation: false, - }, - }); - - if (this.windowStates[Keys.mainWindowSize].isMaximized) { - this.win.maximize(); - } - - // Show it later since it might need to be maximized. - this.win.show(); - - // and load the index.html of the app. - this.win.loadURL(url.format( - { - protocol: 'file:', - pathname: path.join(__dirname, '/index.html'), - slashes: true, - }), - { - userAgent: cleanUserAgent(this.win.webContents.userAgent), - } - ); - - // Open the DevTools. - if (isDev()) { - this.win.webContents.openDevTools(); - } - - // Emitted when the window is closed. - this.win.on('closed', async () => { - await this.updateWindowState(Keys.mainWindowSize, this.win); - - // Dereference the window object, usually you would store window - // in an array if your app supports multi windows, this is the time - // when you should delete the corresponding element. - this.win = null; - }); - - this.win.on('close', async () => { - await this.updateWindowState(Keys.mainWindowSize, this.win); - }); - - this.win.on('maximize', async () => { - await this.updateWindowState(Keys.mainWindowSize, this.win); - }); - - this.win.on('unmaximize', async () => { - await this.updateWindowState(Keys.mainWindowSize, this.win); - }); - - this.win.on('resize', () => { - this.windowStateChangeHandler(Keys.mainWindowSize, this.win); - }); - - this.win.on('move', () => { - this.windowStateChangeHandler(Keys.mainWindowSize, this.win); - }); - this.win.on('focus', () => { - this.win.webContents.send('messagingService', { - command: 'windowIsFocused', - windowIsFocused: true, + // Create the browser window. + this.win = new BrowserWindow({ + width: this.windowStates[mainWindowSizeKey].width, + height: this.windowStates[mainWindowSizeKey].height, + minWidth: 680, + minHeight: 500, + x: this.windowStates[mainWindowSizeKey].x, + y: this.windowStates[mainWindowSizeKey].y, + title: app.name, + icon: process.platform === 'linux' ? path.join(__dirname, '/images/icon.png') : undefined, + titleBarStyle: this.hideTitleBar && process.platform === 'darwin' ? 'hiddenInset' : undefined, + show: false, + backgroundColor: '#fff', + alwaysOnTop: this.enableAlwaysOnTop, + webPreferences: { + nodeIntegration: true, + backgroundThrottling: false, + contextIsolation: false, + }, }); - }); - if (this.createWindowCallback) { - this.createWindowCallback(this.win); + if (this.windowStates[mainWindowSizeKey].isMaximized) { + this.win.maximize(); + } + + // Show it later since it might need to be maximized. + this.win.show(); + + // and load the index.html of the app. + this.win.loadURL(url.format( + { + protocol: 'file:', + pathname: path.join(__dirname, '/index.html'), + slashes: true, + }), + { + userAgent: cleanUserAgent(this.win.webContents.userAgent), + } + ); + + // Open the DevTools. + if (isDev()) { + this.win.webContents.openDevTools(); + } + + // Emitted when the window is closed. + this.win.on('closed', async () => { + await this.updateWindowState(mainWindowSizeKey, this.win); + + // Dereference the window object, usually you would store window + // in an array if your app supports multi windows, this is the time + // when you should delete the corresponding element. + this.win = null; + }); + + this.win.on('close', async () => { + await this.updateWindowState(mainWindowSizeKey, this.win); + }); + + this.win.on('maximize', async () => { + await this.updateWindowState(mainWindowSizeKey, this.win); + }); + + this.win.on('unmaximize', async () => { + await this.updateWindowState(mainWindowSizeKey, this.win); + }); + + this.win.on('resize', () => { + this.windowStateChangeHandler(mainWindowSizeKey, this.win); + }); + + this.win.on('move', () => { + this.windowStateChangeHandler(mainWindowSizeKey, this.win); + }); + this.win.on('focus', () => { + this.win.webContents.send('messagingService', { + command: 'windowIsFocused', + windowIsFocused: true, + }); + }); + + if (this.createWindowCallback) { + this.createWindowCallback(this.win); + } + } catch (e) { + this.logService.error(e); } } async toggleAlwaysOnTop() { this.enableAlwaysOnTop = !this.win.isAlwaysOnTop(); this.win.setAlwaysOnTop(this.enableAlwaysOnTop); - await this.storageService.save(ElectronConstants.enableAlwaysOnTopKey, this.enableAlwaysOnTop); + await this.stateService.setEnableAlwaysOnTop(this.enableAlwaysOnTop); } private windowStateChangeHandler(configKey: string, win: BrowserWindow) { @@ -219,7 +219,7 @@ export class WindowMain { const bounds = win.getBounds(); if (this.windowStates[configKey] == null) { - this.windowStates[configKey] = await this.storageService.get(configKey); + this.windowStates[configKey] = (await this.stateService.getWindow()).get(configKey); if (this.windowStates[configKey] == null) { this.windowStates[configKey] = {}; } @@ -235,14 +235,19 @@ export class WindowMain { this.windowStates[configKey].height = bounds.height; } - await this.storageService.save(configKey, this.windowStates[configKey]); + const cachedWindow = await this.stateService.getWindow() ?? new Map(); + cachedWindow.set(configKey, this.windowStates[configKey]); + await this.stateService.setWindow(cachedWindow); } catch (e) { this.logService.error(e); } } private async getWindowState(configKey: string, defaultWidth: number, defaultHeight: number) { - let state = await this.storageService.get(configKey); + const windowState = await this.stateService.getWindow() ?? new Map(); + let state = windowState.has(configKey) ? + windowState.get(configKey) : + null; const isValid = state != null && (this.stateHasBounds(state) || state.isMaximized); let displayBounds: Electron.Rectangle = null; diff --git a/node/src/cli/baseProgram.ts b/node/src/cli/baseProgram.ts index 7772ba80..99447db8 100644 --- a/node/src/cli/baseProgram.ts +++ b/node/src/cli/baseProgram.ts @@ -1,15 +1,15 @@ import * as chalk from 'chalk'; +import { StateService } from 'jslib-common/abstractions/state.service'; + import { Response } from './models/response'; import { ListResponse } from './models/response/listResponse'; import { MessageResponse } from './models/response/messageResponse'; import { StringResponse } from './models/response/stringResponse'; -import { UserService } from 'jslib-common/abstractions/user.service'; - export abstract class BaseProgram { constructor( - private userService: UserService, + private stateService: StateService, private writeLn: (s: string, finalLine: boolean, error: boolean) => void) { } protected processResponse(response: Response, exitImmediately = false, dataProcessor: () => string = null) { @@ -92,15 +92,15 @@ export abstract class BaseProgram { } protected async exitIfAuthed() { - const authed = await this.userService.isAuthenticated(); + const authed = await this.stateService.getIsAuthenticated(); if (authed) { - const email = await this.userService.getEmail(); + const email = await this.stateService.getEmail(); this.processResponse(Response.error('You are already logged in as ' + email + '.'), true); } } protected async exitIfNotAuthed() { - const authed = await this.userService.isAuthenticated(); + const authed = await this.stateService.getIsAuthenticated(); if (!authed) { this.processResponse(Response.error('You are not logged in.'), true); } diff --git a/node/src/cli/commands/login.command.ts b/node/src/cli/commands/login.command.ts index 6ed398e4..6487092a 100644 --- a/node/src/cli/commands/login.command.ts +++ b/node/src/cli/commands/login.command.ts @@ -17,8 +17,8 @@ import { I18nService } from 'jslib-common/abstractions/i18n.service'; import { PasswordGenerationService } from 'jslib-common/abstractions/passwordGeneration.service'; import { PlatformUtilsService } from 'jslib-common/abstractions/platformUtils.service'; import { PolicyService } from 'jslib-common/abstractions/policy.service'; +import { StateService } from 'jslib-common/abstractions/state.service'; import { SyncService } from 'jslib-common/abstractions/sync.service'; -import { UserService } from 'jslib-common/abstractions/user.service'; import { Response } from '../models/response'; @@ -47,7 +47,7 @@ export class LoginCommand { protected i18nService: I18nService, protected environmentService: EnvironmentService, protected passwordGenerationService: PasswordGenerationService, protected cryptoFunctionService: CryptoFunctionService, protected platformUtilsService: PlatformUtilsService, - protected userService: UserService, protected cryptoService: CryptoService, + protected stateService: StateService, protected cryptoService: CryptoService, protected policyService: PolicyService, clientId: string, private syncService: SyncService) { this.clientId = clientId; } @@ -285,7 +285,7 @@ export class LoginCommand { } if (this.email == null || this.email === 'undefined') { - this.email = await this.userService.getEmail(); + this.email = await this.stateService.getEmail(); } // Get New Master Password @@ -335,8 +335,8 @@ export class LoginCommand { // Retrieve details for key generation const enforcedPolicyOptions = await this.policyService.getMasterPasswordPolicyOptions(); - const kdf = await this.userService.getKdf(); - const kdfIterations = await this.userService.getKdfIterations(); + const kdf = await this.stateService.getKdfType(); + const kdfIterations = await this.stateService.getKdfIterations(); if (enforcedPolicyOptions != null && !this.policyService.evaluateMasterPassword(