diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 53fe40b3..9ffb70ff 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -532,9 +532,9 @@ jobs: env: BUILD_NUMBER: ${{ needs.setup.outputs.build_number }} run: | - $package = Get-Content -Raw -Path $env:GITHUB_WORKSPACE\package.json | ConvertFrom-Json; - $package.build | Add-Member -MemberType NoteProperty -Name buildVersion -Value "$env:BUILD_NUMBER"; - $package | ConvertTo-Json -Depth 32 | Set-Content $env:GITHUB_WORKSPACE\package.json; + $package = Get-Content -Raw -Path $env:GITHUB_WORKSPACE\electron-builder.json | ConvertFrom-Json; + $package | Add-Member -MemberType NoteProperty -Name buildVersion -Value "$env:BUILD_NUMBER"; + $package | ConvertTo-Json -Depth 32 | Set-Content $env:GITHUB_WORKSPACE\electron-builder.json; - name: Cache Native Module uses: actions/cache@48af2dc4a9e8278b89d7fa154b955c30c6aaab09 # v3.0.2 @@ -695,9 +695,9 @@ jobs: env: BUILD_NUMBER: ${{ needs.setup.outputs.build_number }} run: | - $package = Get-Content -Raw -Path $env:GITHUB_WORKSPACE\package.json | ConvertFrom-Json; - $package.build | Add-Member -MemberType NoteProperty -Name buildVersion -Value "$env:BUILD_NUMBER"; - $package | ConvertTo-Json -Depth 32 | Set-Content $env:GITHUB_WORKSPACE\package.json; + $package = Get-Content -Raw -Path $env:GITHUB_WORKSPACE\electron-builder.json | ConvertFrom-Json; + $package | Add-Member -MemberType NoteProperty -Name buildVersion -Value "$env:BUILD_NUMBER"; + $package | ConvertTo-Json -Depth 32 | Set-Content $env:GITHUB_WORKSPACE\electron-builder.json; - name: Cache Native Module uses: actions/cache@48af2dc4a9e8278b89d7fa154b955c30c6aaab09 # v3.0.2 @@ -901,9 +901,9 @@ jobs: env: BUILD_NUMBER: ${{ needs.setup.outputs.build_number }} run: | - $package = Get-Content -Raw -Path $env:GITHUB_WORKSPACE\package.json | ConvertFrom-Json; - $package.build | Add-Member -MemberType NoteProperty -Name buildVersion -Value "$env:BUILD_NUMBER"; - $package | ConvertTo-Json -Depth 32 | Set-Content $env:GITHUB_WORKSPACE\package.json; + $package = Get-Content -Raw -Path $env:GITHUB_WORKSPACE\electron-builder.json | ConvertFrom-Json; + $package | Add-Member -MemberType NoteProperty -Name buildVersion -Value "$env:BUILD_NUMBER"; + $package | ConvertTo-Json -Depth 32 | Set-Content $env:GITHUB_WORKSPACE\electron-builder.json; - name: Cache Native Module uses: actions/cache@48af2dc4a9e8278b89d7fa154b955c30c6aaab09 # v3.0.2 @@ -1094,9 +1094,9 @@ jobs: env: BUILD_NUMBER: ${{ needs.setup.outputs.build_number }} run: | - $package = Get-Content -Raw -Path $env:GITHUB_WORKSPACE\package.json | ConvertFrom-Json; - $package.build | Add-Member -MemberType NoteProperty -Name buildVersion -Value "$env:BUILD_NUMBER"; - $package | ConvertTo-Json -Depth 32 | Set-Content $env:GITHUB_WORKSPACE\package.json; + $package = Get-Content -Raw -Path $env:GITHUB_WORKSPACE\electron-builder.json | ConvertFrom-Json; + $package | Add-Member -MemberType NoteProperty -Name buildVersion -Value "$env:BUILD_NUMBER"; + $package | ConvertTo-Json -Depth 32 | Set-Content $env:GITHUB_WORKSPACE\electron-builder.json; - name: Cache Native Module uses: actions/cache@48af2dc4a9e8278b89d7fa154b955c30c6aaab09 # v3.0.2 diff --git a/README.md b/README.md index 440b085a..d76e58db 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,12 @@ [![Crowdin](https://d322cqt584bo4o.cloudfront.net/bitwarden-desktop/localized.svg)](https://crowdin.com/project/bitwarden-desktop) [![Join the chat at https://gitter.im/bitwarden/Lobby](https://badges.gitter.im/bitwarden/Lobby.svg)](https://gitter.im/bitwarden/Lobby) +> **Repository Reorganization in Progress** +> +> We are currently migrating some projects over to a mono repository. For existing PR's we will be providing documentation on how to move/migrate them. To minimize the overhead we are actively reviewing open PRs. If possible please ensure any pending comments are resolved as soon as possible. +> +> New pull requests created during this transition period may not get addressed —if needed, please create a new PR after the reorganization is complete. + # Bitwarden Desktop Application [![Platforms](https://imgur.com/SLv9paA.png "Windows, macOS, and Linux")](https://bitwarden.com/download/) diff --git a/electron-builder.json b/electron-builder.json new file mode 100644 index 00000000..e92d20a8 --- /dev/null +++ b/electron-builder.json @@ -0,0 +1,121 @@ +{ + "extraMetadata": { "name": "bitwarden" }, + "productName": "Bitwarden", + "appId": "com.bitwarden.desktop", + "buildDependenciesFromSource": true, + "copyright": "Copyright © 2015-2022 Bitwarden Inc.", + "directories": { "buildResources": "resources", "output": "dist", "app": "build" }, + "afterSign": "scripts/after-sign.js", + "asarUnpack": ["**/*.node"], + "files": [ + "**/*", + "!**/node_modules/@bitwarden/desktop-native/**/*", + "**/node_modules/@bitwarden/desktop-native/index.js", + "**/node_modules/@bitwarden/desktop-native/dist/desktop_native.${platform}-${arch}*.node" + ], + "mac": { + "electronUpdaterCompatibility": ">=0.0.1", + "category": "public.app-category.productivity", + "darkModeSupport": true, + "gatekeeperAssess": false, + "hardenedRuntime": true, + "entitlements": "resources/entitlements.mac.plist", + "entitlementsInherit": "resources/entitlements.mac.plist", + "extendInfo": { + "ITSAppUsesNonExemptEncryption": false, + "CFBundleLocalizations": [ + "en", + "cs", + "da", + "de", + "es", + "et", + "fi", + "fr", + "hr", + "hu", + "id", + "it", + "ja", + "nb", + "nl", + "pl", + "pt-BR", + "pt-PT", + "ro", + "ru", + "sk", + "sv", + "tr", + "uk", + "vi", + "zh-Hans", + "zh-Hant" + ], + "CFBundleDevelopmentRegion": "en" + }, + "target": ["dmg", "zip"] + }, + "win": { + "electronUpdaterCompatibility": ">=0.0.1", + "target": ["portable", "nsis-web", "appx"], + "sign": "./sign.js", + "extraResources": [ + { "from": "node_modules/regedit/vbs", "to": "regedit/vbs", "filter": ["**/*"] }, + { "from": "resources/native-messaging.bat", "to": "native-messaging.bat" } + ] + }, + "linux": { + "category": "Utility", + "synopsis": "A secure and free password manager for all of your devices.", + "target": ["deb", "freebsd", "rpm", "AppImage", "snap"], + "desktop": { "Name": "Bitwarden", "Type": "Application", "GenericName": "Password Manager" } + }, + "dmg": { + "icon": "dmg.icns", + "contents": [ + { "x": 150, "y": 185, "type": "file" }, + { "x": 390, "y": 180, "type": "link", "path": "/Applications" } + ], + "window": { "width": 540, "height": 380 } + }, + "mas": { + "entitlements": "resources/entitlements.mas.plist", + "entitlementsInherit": "resources/entitlements.mas.inherit.plist", + "hardenedRuntime": false, + "extendInfo": { "LSMinimumSystemVersion": "10.14.0" } + }, + "nsisWeb": { + "oneClick": false, + "perMachine": false, + "allowToChangeInstallationDirectory": false, + "artifactName": "${productName}-Installer-${version}.${ext}", + "uninstallDisplayName": "${productName}", + "deleteAppDataOnUninstall": true + }, + "portable": { "artifactName": "${productName}-Portable-${version}.${ext}" }, + "appx": { + "artifactName": "${productName}-${version}-${arch}.${ext}", + "backgroundColor": "#175DDC", + "applicationId": "bitwardendesktop", + "identityName": "8bitSolutionsLLC.bitwardendesktop", + "publisher": "CN=14D52771-DE3C-4886-B8BF-825BA7690418", + "publisherDisplayName": "8bit Solutions LLC", + "languages": ["en-US"] + }, + "deb": { + "artifactName": "${productName}-${version}-${arch}.${ext}", + "depends": ["libnotify4", "libxtst6", "libnss3", "libsecret-1-0", "libxss1"] + }, + "appImage": { "artifactName": "${productName}-${version}-${arch}.${ext}" }, + "rpm": { "artifactName": "${productName}-${version}-${arch}.${ext}" }, + "freebsd": { "artifactName": "${productName}-${version}-${arch}.${ext}" }, + "snap": { + "autoStart": true, + "confinement": "strict", + "plugs": ["default", "password-manager-service"], + "stagePackages": ["default"], + "publish": ["github"] + }, + "protocols": [{ "name": "Bitwarden", "schemes": ["bitwarden"] }] +} diff --git a/jslib b/jslib index fe65a337..d7e55465 160000 --- a/jslib +++ b/jslib @@ -1 +1 @@ -Subproject commit fe65a337c8d2b681fc8fbf486c4f7af4c959a230 +Subproject commit d7e554653a7e593f8cdaf7e2fe926eb04fb5d5c5 diff --git a/package.json b/package.json index aa36b148..f735bd60 100644 --- a/package.json +++ b/package.json @@ -63,205 +63,6 @@ "prettier": "prettier --write .", "prepare": "husky install" }, - "build": { - "extraMetadata": { - "name": "bitwarden" - }, - "productName": "Bitwarden", - "appId": "com.bitwarden.desktop", - "buildDependenciesFromSource": true, - "copyright": "Copyright © 2015-2022 Bitwarden Inc.", - "directories": { - "buildResources": "resources", - "output": "dist", - "app": "build" - }, - "afterSign": "scripts/after-sign.js", - "asarUnpack": [ - "**/*.node" - ], - "files": [ - "**/*", - "!**/node_modules/@bitwarden/desktop-native/**/*", - "**/node_modules/@bitwarden/desktop-native/index.js", - "**/node_modules/@bitwarden/desktop-native/dist/desktop_native.${platform}-${arch}*.node" - ], - "mac": { - "electronUpdaterCompatibility": ">=0.0.1", - "category": "public.app-category.productivity", - "darkModeSupport": true, - "gatekeeperAssess": false, - "hardenedRuntime": true, - "entitlements": "resources/entitlements.mac.plist", - "entitlementsInherit": "resources/entitlements.mac.plist", - "extendInfo": { - "ITSAppUsesNonExemptEncryption": false, - "CFBundleLocalizations": [ - "en", - "cs", - "da", - "de", - "es", - "et", - "fi", - "fr", - "hr", - "hu", - "id", - "it", - "ja", - "nb", - "nl", - "pl", - "pt-BR", - "pt-PT", - "ro", - "ru", - "sk", - "sv", - "tr", - "uk", - "vi", - "zh-Hans", - "zh-Hant" - ], - "CFBundleDevelopmentRegion": "en" - }, - "target": [ - "dmg", - "zip" - ] - }, - "win": { - "electronUpdaterCompatibility": ">=0.0.1", - "target": [ - "portable", - "nsis-web", - "appx" - ], - "sign": "./sign.js", - "extraResources": [ - { - "from": "node_modules/regedit/vbs", - "to": "regedit/vbs", - "filter": [ - "**/*" - ] - }, - { - "from": "resources/native-messaging.bat", - "to": "native-messaging.bat" - } - ] - }, - "linux": { - "category": "Utility", - "synopsis": "A secure and free password manager for all of your devices.", - "target": [ - "deb", - "freebsd", - "rpm", - "AppImage", - "snap" - ], - "desktop": { - "Name": "Bitwarden", - "Type": "Application", - "GenericName": "Password Manager" - } - }, - "dmg": { - "icon": "dmg.icns", - "contents": [ - { - "x": 150, - "y": 185, - "type": "file" - }, - { - "x": 390, - "y": 180, - "type": "link", - "path": "/Applications" - } - ], - "window": { - "width": 540, - "height": 380 - } - }, - "mas": { - "entitlements": "resources/entitlements.mas.plist", - "entitlementsInherit": "resources/entitlements.mas.inherit.plist", - "hardenedRuntime": false, - "extendInfo": { - "LSMinimumSystemVersion": "10.14.0" - } - }, - "nsisWeb": { - "oneClick": false, - "perMachine": false, - "allowToChangeInstallationDirectory": false, - "artifactName": "${productName}-Installer-${version}.${ext}", - "uninstallDisplayName": "${productName}", - "deleteAppDataOnUninstall": true - }, - "portable": { - "artifactName": "${productName}-Portable-${version}.${ext}" - }, - "appx": { - "artifactName": "${productName}-${version}-${arch}.${ext}", - "backgroundColor": "#175DDC", - "applicationId": "bitwardendesktop", - "identityName": "8bitSolutionsLLC.bitwardendesktop", - "publisher": "CN=14D52771-DE3C-4886-B8BF-825BA7690418", - "publisherDisplayName": "8bit Solutions LLC", - "languages": [ - "en-US" - ] - }, - "deb": { - "artifactName": "${productName}-${version}-${arch}.${ext}", - "depends": [ - "libnotify4", - "libxtst6", - "libnss3", - "libsecret-1-0", - "libxss1" - ] - }, - "appImage": { - "artifactName": "${productName}-${version}-${arch}.${ext}" - }, - "rpm": { - "artifactName": "${productName}-${version}-${arch}.${ext}" - }, - "freebsd": { - "artifactName": "${productName}-${version}-${arch}.${ext}" - }, - "snap": { - "autoStart": true, - "confinement": "strict", - "plugs": [ - "default", - "password-manager-service" - ], - "stagePackages": [ - "default" - ], - "publish": [ - "github" - ] - }, - "protocols": [ - { - "name": "Bitwarden", - "schemes": [ - "bitwarden" - ] - } - ] - }, "devDependencies": { "@angular/compiler-cli": "^12.2.13", "@ngtools/webpack": "^12.2.13", diff --git a/src/app/accounts/two-factor.component.ts b/src/app/accounts/two-factor.component.ts index db482230..acf8919f 100644 --- a/src/app/accounts/two-factor.component.ts +++ b/src/app/accounts/two-factor.component.ts @@ -4,6 +4,7 @@ import { ActivatedRoute, Router } from "@angular/router"; import { TwoFactorComponent as BaseTwoFactorComponent } from "jslib-angular/components/two-factor.component"; import { ModalService } from "jslib-angular/services/modal.service"; import { ApiService } from "jslib-common/abstractions/api.service"; +import { AppIdService } from "jslib-common/abstractions/appId.service"; import { AuthService } from "jslib-common/abstractions/auth.service"; import { EnvironmentService } from "jslib-common/abstractions/environment.service"; import { I18nService } from "jslib-common/abstractions/i18n.service"; @@ -38,7 +39,8 @@ export class TwoFactorComponent extends BaseTwoFactorComponent { stateService: StateService, route: ActivatedRoute, logService: LogService, - twoFactorService: TwoFactorService + twoFactorService: TwoFactorService, + appIdService: AppIdService ) { super( authService, @@ -51,7 +53,8 @@ export class TwoFactorComponent extends BaseTwoFactorComponent { stateService, route, logService, - twoFactorService + twoFactorService, + appIdService ); super.onSuccessfulLogin = () => { return syncService.fullSync(true); diff --git a/src/app/app.module.ts b/src/app/app.module.ts index 3cd8197d..29e324cf 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -91,7 +91,7 @@ import { SearchComponent } from "./layout/search/search.component"; import { AddEditComponent as SendAddEditComponent } from "./send/add-edit.component"; import { EffluxDatesComponent as SendEffluxDatesComponent } from "./send/efflux-dates.component"; import { SendComponent } from "./send/send.component"; -import { ServicesModule } from "./services.module"; +import { ServicesModule } from "./services/services.module"; import { AddEditCustomFieldsComponent } from "./vault/add-edit-custom-fields.component"; import { AddEditComponent } from "./vault/add-edit.component"; import { AttachmentsComponent } from "./vault/attachments.component"; diff --git a/src/app/services.module.ts b/src/app/services.module.ts deleted file mode 100644 index 74acaabc..00000000 --- a/src/app/services.module.ts +++ /dev/null @@ -1,211 +0,0 @@ -import { APP_INITIALIZER, NgModule } from "@angular/core"; - -import { JslibServicesModule } from "jslib-angular/services/jslib-services.module"; -import { BroadcasterService as BroadcasterServiceAbstraction } from "jslib-common/abstractions/broadcaster.service"; -import { CryptoService as CryptoServiceAbstraction } from "jslib-common/abstractions/crypto.service"; -import { CryptoFunctionService as CryptoFunctionServiceAbstraction } from "jslib-common/abstractions/cryptoFunction.service"; -import { EnvironmentService as EnvironmentServiceAbstraction } from "jslib-common/abstractions/environment.service"; -import { EventService as EventServiceAbstraction } from "jslib-common/abstractions/event.service"; -import { I18nService as I18nServiceAbstraction } from "jslib-common/abstractions/i18n.service"; -import { LogService as LogServiceAbstraction } from "jslib-common/abstractions/log.service"; -import { MessagingService as MessagingServiceAbstraction } from "jslib-common/abstractions/messaging.service"; -import { NotificationsService as NotificationsServiceAbstraction } from "jslib-common/abstractions/notifications.service"; -import { PasswordRepromptService as PasswordRepromptServiceAbstraction } from "jslib-common/abstractions/passwordReprompt.service"; -import { PlatformUtilsService as PlatformUtilsServiceAbstraction } from "jslib-common/abstractions/platformUtils.service"; -import { StateService as StateServiceAbstraction } from "jslib-common/abstractions/state.service"; -import { StateMigrationService as StateMigrationServiceAbstraction } from "jslib-common/abstractions/stateMigration.service"; -import { StorageService as StorageServiceAbstraction } from "jslib-common/abstractions/storage.service"; -import { SyncService as SyncServiceAbstraction } from "jslib-common/abstractions/sync.service"; -import { SystemService as SystemServiceAbstraction } from "jslib-common/abstractions/system.service"; -import { TwoFactorService as TwoFactorServiceAbstraction } from "jslib-common/abstractions/twoFactor.service"; -import { VaultTimeoutService as VaultTimeoutServiceAbstraction } from "jslib-common/abstractions/vaultTimeout.service"; -import { ThemeType } from "jslib-common/enums/themeType"; -import { StateFactory } from "jslib-common/factories/stateFactory"; -import { GlobalState } from "jslib-common/models/domain/globalState"; -import { ContainerService } from "jslib-common/services/container.service"; -import { EventService } from "jslib-common/services/event.service"; -import { StateMigrationService } from "jslib-common/services/stateMigration.service"; -import { SystemService } from "jslib-common/services/system.service"; -import { VaultTimeoutService } from "jslib-common/services/vaultTimeout.service"; -import { ElectronCryptoService } from "jslib-electron/services/electronCrypto.service"; -import { ElectronLogService } from "jslib-electron/services/electronLog.service"; -import { ElectronPlatformUtilsService } from "jslib-electron/services/electronPlatformUtils.service"; -import { ElectronRendererMessagingService } from "jslib-electron/services/electronRendererMessaging.service"; -import { ElectronRendererSecureStorageService } from "jslib-electron/services/electronRendererSecureStorage.service"; -import { ElectronRendererStorageService } from "jslib-electron/services/electronRendererStorage.service"; - -import { Account } from "../models/account"; -import { I18nService } from "../services/i18n.service"; -import { LoginGuardService } from "../services/loginGuard.service"; -import { NativeMessagingService } from "../services/nativeMessaging.service"; -import { PasswordRepromptService } from "../services/passwordReprompt.service"; -import { StateService } from "../services/state.service"; - -import { SearchBarService } from "./layout/search/search-bar.service"; - -export function initFactory( - window: Window, - environmentService: EnvironmentServiceAbstraction, - syncService: SyncServiceAbstraction, - vaultTimeoutService: VaultTimeoutService, - i18nService: I18nService, - eventService: EventService, - twoFactorService: TwoFactorServiceAbstraction, - notificationsService: NotificationsServiceAbstraction, - platformUtilsService: PlatformUtilsServiceAbstraction, - stateService: StateServiceAbstraction, - cryptoService: CryptoServiceAbstraction, - nativeMessagingService: NativeMessagingService -): () => Promise { - return async () => { - nativeMessagingService.init(); - await stateService.init(); - await environmentService.setUrlsFromStorage(); - syncService.fullSync(true); - await vaultTimeoutService.init(true); - const locale = await stateService.getLocale(); - await i18nService.init(locale); - eventService.init(true); - twoFactorService.init(); - setTimeout(() => notificationsService.init(), 3000); - const htmlEl = window.document.documentElement; - htmlEl.classList.add("os_" + platformUtilsService.getDeviceString()); - htmlEl.classList.add("locale_" + i18nService.translationLocale); - const theme = await platformUtilsService.getEffectiveTheme(); - htmlEl.classList.add("theme_" + theme); - platformUtilsService.onDefaultSystemThemeChange(async (sysTheme) => { - const bwTheme = await stateService.getTheme(); - if (bwTheme == null || bwTheme === ThemeType.System) { - htmlEl.classList.remove("theme_" + ThemeType.Light, "theme_" + ThemeType.Dark); - htmlEl.classList.add("theme_" + sysTheme); - } - }); - - let installAction = null; - const installedVersion = await stateService.getInstalledVersion(); - const currentVersion = await platformUtilsService.getApplicationVersion(); - if (installedVersion == null) { - installAction = "install"; - } else if (installedVersion !== currentVersion) { - installAction = "update"; - } - - if (installAction != null) { - await stateService.setInstalledVersion(currentVersion); - } - - const containerService = new ContainerService(cryptoService); - containerService.attachToGlobal(window); - }; -} - -@NgModule({ - imports: [JslibServicesModule], - declarations: [], - providers: [ - { - provide: APP_INITIALIZER, - useFactory: initFactory, - deps: [ - "WINDOW", - EnvironmentServiceAbstraction, - SyncServiceAbstraction, - VaultTimeoutServiceAbstraction, - I18nServiceAbstraction, - EventServiceAbstraction, - TwoFactorServiceAbstraction, - NotificationsServiceAbstraction, - PlatformUtilsServiceAbstraction, - StateServiceAbstraction, - CryptoServiceAbstraction, - NativeMessagingService, - ], - multi: true, - }, - { provide: LogServiceAbstraction, useClass: ElectronLogService, deps: [] }, - { - provide: PlatformUtilsServiceAbstraction, - useFactory: ( - i18nService: I18nServiceAbstraction, - messagingService: MessagingServiceAbstraction, - stateService: StateServiceAbstraction - ) => new ElectronPlatformUtilsService(i18nService, messagingService, true, stateService), - deps: [I18nServiceAbstraction, MessagingServiceAbstraction, StateServiceAbstraction], - }, - { - provide: I18nServiceAbstraction, - useFactory: (window: Window) => new I18nService(window.navigator.language, "./locales"), - deps: ["WINDOW"], - }, - { - provide: MessagingServiceAbstraction, - useClass: ElectronRendererMessagingService, - deps: [BroadcasterServiceAbstraction], - }, - { provide: StorageServiceAbstraction, useClass: ElectronRendererStorageService }, - { provide: "SECURE_STORAGE", useClass: ElectronRendererSecureStorageService }, - { - provide: CryptoServiceAbstraction, - useClass: ElectronCryptoService, - deps: [ - CryptoFunctionServiceAbstraction, - PlatformUtilsServiceAbstraction, - LogServiceAbstraction, - StateServiceAbstraction, - ], - }, - { - provide: SystemServiceAbstraction, - useFactory: ( - messagingService: MessagingServiceAbstraction, - platformUtilsService: PlatformUtilsServiceAbstraction, - stateService: StateServiceAbstraction - ) => new SystemService(messagingService, platformUtilsService, null, stateService), - deps: [MessagingServiceAbstraction, PlatformUtilsServiceAbstraction, StateServiceAbstraction], - }, - { provide: PasswordRepromptServiceAbstraction, useClass: PasswordRepromptService }, - NativeMessagingService, - SearchBarService, - { - provide: LoginGuardService, - useClass: LoginGuardService, - deps: [StateServiceAbstraction, PlatformUtilsServiceAbstraction, I18nServiceAbstraction], - }, - { - provide: StateServiceAbstraction, - useFactory: ( - storageService: StorageServiceAbstraction, - secureStorageService: StorageServiceAbstraction, - logService: LogServiceAbstraction, - stateMigrationService: StateMigrationServiceAbstraction - ) => - new StateService( - storageService, - secureStorageService, - logService, - stateMigrationService, - new StateFactory(GlobalState, Account) - ), - deps: [ - StorageServiceAbstraction, - "SECURE_STORAGE", - LogServiceAbstraction, - StateMigrationServiceAbstraction, - ], - }, - { - provide: StateMigrationServiceAbstraction, - useFactory: ( - storageService: StorageServiceAbstraction, - secureStorageService: StorageServiceAbstraction - ) => - new StateMigrationService( - storageService, - secureStorageService, - new StateFactory(GlobalState, Account) - ), - deps: [StorageServiceAbstraction, "SECURE_STORAGE"], - }, - ], -}) -export class ServicesModule {} diff --git a/src/app/services/init.service.ts b/src/app/services/init.service.ts new file mode 100644 index 00000000..3bc3d49a --- /dev/null +++ b/src/app/services/init.service.ts @@ -0,0 +1,81 @@ +import { Inject, Injectable } from "@angular/core"; + +import { WINDOW } from "jslib-angular/services/jslib-services.module"; +import { CryptoService as CryptoServiceAbstraction } from "jslib-common/abstractions/crypto.service"; +import { EnvironmentService as EnvironmentServiceAbstraction } from "jslib-common/abstractions/environment.service"; +import { EventService as EventServiceAbstraction } from "jslib-common/abstractions/event.service"; +import { I18nService as I18nServiceAbstraction } from "jslib-common/abstractions/i18n.service"; +import { NotificationsService as NotificationsServiceAbstraction } from "jslib-common/abstractions/notifications.service"; +import { PlatformUtilsService as PlatformUtilsServiceAbstraction } from "jslib-common/abstractions/platformUtils.service"; +import { StateService as StateServiceAbstraction } from "jslib-common/abstractions/state.service"; +import { SyncService as SyncServiceAbstraction } from "jslib-common/abstractions/sync.service"; +import { TwoFactorService as TwoFactorServiceAbstraction } from "jslib-common/abstractions/twoFactor.service"; +import { VaultTimeoutService as VaultTimeoutServiceAbstraction } from "jslib-common/abstractions/vaultTimeout.service"; +import { ThemeType } from "jslib-common/enums/themeType"; +import { ContainerService } from "jslib-common/services/container.service"; +import { EventService } from "jslib-common/services/event.service"; +import { VaultTimeoutService } from "jslib-common/services/vaultTimeout.service"; + +import { I18nService } from "../../services/i18n.service"; +import { NativeMessagingService } from "../../services/nativeMessaging.service"; + +@Injectable() +export class InitService { + constructor( + @Inject(WINDOW) private win: Window, + private environmentService: EnvironmentServiceAbstraction, + private syncService: SyncServiceAbstraction, + private vaultTimeoutService: VaultTimeoutServiceAbstraction, + private i18nService: I18nServiceAbstraction, + private eventService: EventServiceAbstraction, + private twoFactorService: TwoFactorServiceAbstraction, + private notificationsService: NotificationsServiceAbstraction, + private platformUtilsService: PlatformUtilsServiceAbstraction, + private stateService: StateServiceAbstraction, + private cryptoService: CryptoServiceAbstraction, + private nativeMessagingService: NativeMessagingService + ) {} + + init() { + return async () => { + this.nativeMessagingService.init(); + await this.stateService.init(); + await this.environmentService.setUrlsFromStorage(); + this.syncService.fullSync(true); + (this.vaultTimeoutService as VaultTimeoutService).init(true); + const locale = await this.stateService.getLocale(); + await (this.i18nService as I18nService).init(locale); + (this.eventService as EventService).init(true); + this.twoFactorService.init(); + setTimeout(() => this.notificationsService.init(), 3000); + const htmlEl = this.win.document.documentElement; + htmlEl.classList.add("os_" + this.platformUtilsService.getDeviceString()); + + const theme = await this.platformUtilsService.getEffectiveTheme(); + htmlEl.classList.add("theme_" + theme); + this.platformUtilsService.onDefaultSystemThemeChange(async (sysTheme) => { + const bwTheme = await this.stateService.getTheme(); + if (bwTheme == null || bwTheme === ThemeType.System) { + htmlEl.classList.remove("theme_" + ThemeType.Light, "theme_" + ThemeType.Dark); + htmlEl.classList.add("theme_" + sysTheme); + } + }); + + let installAction = null; + const installedVersion = await this.stateService.getInstalledVersion(); + const currentVersion = await this.platformUtilsService.getApplicationVersion(); + if (installedVersion == null) { + installAction = "install"; + } else if (installedVersion !== currentVersion) { + installAction = "update"; + } + + if (installAction != null) { + await this.stateService.setInstalledVersion(currentVersion); + } + + const containerService = new ContainerService(this.cryptoService); + containerService.attachToGlobal(this.win); + }; + } +} diff --git a/src/app/services/services.module.ts b/src/app/services/services.module.ts new file mode 100644 index 00000000..694cc6de --- /dev/null +++ b/src/app/services/services.module.ts @@ -0,0 +1,135 @@ +import { APP_INITIALIZER, InjectionToken, NgModule } from "@angular/core"; + +import { + JslibServicesModule, + SECURE_STORAGE, + STATE_FACTORY, + STATE_SERVICE_USE_CACHE, + WINDOW, + CLIENT_TYPE, + LOCALES_DIRECTORY, + SYSTEM_LANGUAGE, +} from "jslib-angular/services/jslib-services.module"; +import { BroadcasterService as BroadcasterServiceAbstraction } from "jslib-common/abstractions/broadcaster.service"; +import { CryptoService as CryptoServiceAbstraction } from "jslib-common/abstractions/crypto.service"; +import { CryptoFunctionService as CryptoFunctionServiceAbstraction } from "jslib-common/abstractions/cryptoFunction.service"; +import { I18nService as I18nServiceAbstraction } from "jslib-common/abstractions/i18n.service"; +import { + LogService, + LogService as LogServiceAbstraction, +} from "jslib-common/abstractions/log.service"; +import { MessagingService as MessagingServiceAbstraction } from "jslib-common/abstractions/messaging.service"; +import { PasswordRepromptService as PasswordRepromptServiceAbstraction } from "jslib-common/abstractions/passwordReprompt.service"; +import { PlatformUtilsService as PlatformUtilsServiceAbstraction } from "jslib-common/abstractions/platformUtils.service"; +import { StateService as StateServiceAbstraction } from "jslib-common/abstractions/state.service"; +import { StateMigrationService as StateMigrationServiceAbstraction } from "jslib-common/abstractions/stateMigration.service"; +import { StorageService as StorageServiceAbstraction } from "jslib-common/abstractions/storage.service"; +import { SystemService as SystemServiceAbstraction } from "jslib-common/abstractions/system.service"; +import { ClientType } from "jslib-common/enums/clientType"; +import { StateFactory } from "jslib-common/factories/stateFactory"; +import { GlobalState } from "jslib-common/models/domain/globalState"; +import { SystemService } from "jslib-common/services/system.service"; +import { ElectronCryptoService } from "jslib-electron/services/electronCrypto.service"; +import { ElectronLogService } from "jslib-electron/services/electronLog.service"; +import { ElectronPlatformUtilsService } from "jslib-electron/services/electronPlatformUtils.service"; +import { ElectronRendererMessagingService } from "jslib-electron/services/electronRendererMessaging.service"; +import { ElectronRendererSecureStorageService } from "jslib-electron/services/electronRendererSecureStorage.service"; +import { ElectronRendererStorageService } from "jslib-electron/services/electronRendererStorage.service"; + +import { Account } from "../../models/account"; +import { I18nService } from "../../services/i18n.service"; +import { LoginGuardService } from "../../services/loginGuard.service"; +import { NativeMessagingService } from "../../services/nativeMessaging.service"; +import { PasswordRepromptService } from "../../services/passwordReprompt.service"; +import { StateService } from "../../services/state.service"; +import { SearchBarService } from "../layout/search/search-bar.service"; + +import { InitService } from "./init.service"; + +const RELOAD_CALLBACK = new InjectionToken<() => any>("RELOAD_CALLBACK"); + +@NgModule({ + imports: [JslibServicesModule], + declarations: [], + providers: [ + InitService, + NativeMessagingService, + SearchBarService, + LoginGuardService, + { + provide: APP_INITIALIZER, + useFactory: (initService: InitService) => initService.init(), + deps: [InitService], + multi: true, + }, + { + provide: STATE_FACTORY, + useValue: new StateFactory(GlobalState, Account), + }, + { + provide: CLIENT_TYPE, + useValue: ClientType.Desktop, + }, + { + provide: RELOAD_CALLBACK, + useValue: null, + }, + { provide: LogServiceAbstraction, useClass: ElectronLogService, deps: [] }, + { + provide: PlatformUtilsServiceAbstraction, + useClass: ElectronPlatformUtilsService, + deps: [ + I18nServiceAbstraction, + MessagingServiceAbstraction, + CLIENT_TYPE, + StateServiceAbstraction, + ], + }, + { + provide: I18nServiceAbstraction, + useClass: I18nService, + deps: [SYSTEM_LANGUAGE, LOCALES_DIRECTORY], + }, + { + provide: MessagingServiceAbstraction, + useClass: ElectronRendererMessagingService, + deps: [BroadcasterServiceAbstraction], + }, + { provide: StorageServiceAbstraction, useClass: ElectronRendererStorageService }, + { provide: SECURE_STORAGE, useClass: ElectronRendererSecureStorageService }, + { + provide: CryptoServiceAbstraction, + useClass: ElectronCryptoService, + deps: [ + CryptoFunctionServiceAbstraction, + PlatformUtilsServiceAbstraction, + LogServiceAbstraction, + StateServiceAbstraction, + ], + }, + { + provide: SystemServiceAbstraction, + useClass: SystemService, + deps: [ + MessagingServiceAbstraction, + PlatformUtilsServiceAbstraction, + RELOAD_CALLBACK, + StateServiceAbstraction, + ], + }, + { provide: PasswordRepromptServiceAbstraction, useClass: PasswordRepromptService }, + { + provide: StateServiceAbstraction, + useClass: StateService, + deps: [ + StorageServiceAbstraction, + SECURE_STORAGE, + LogService, + StateMigrationServiceAbstraction, + STATE_FACTORY, + STATE_SERVICE_USE_CACHE, + ], + }, + ], +}) +export class ServicesModule {} diff --git a/src/app/vault/generator.component.html b/src/app/vault/generator.component.html index 5ff12e44..79c9bf5b 100644 --- a/src/app/vault/generator.component.html +++ b/src/app/vault/generator.component.html @@ -226,6 +226,7 @@ (change)="savePasswordOptions()" [disabled]="enforcedPasswordPolicyOptions?.useUppercase" [(ngModel)]="passwordOptions.uppercase" + attr.aria-label="{{ 'uppercase' | i18n }}" />
@@ -236,6 +237,7 @@ (change)="savePasswordOptions()" [disabled]="enforcedPasswordPolicyOptions?.useLowercase" [(ngModel)]="passwordOptions.lowercase" + attr.aria-label="{{ 'lowercase' | i18n }}" />
@@ -246,6 +248,7 @@ (change)="savePasswordOptions()" [disabled]="enforcedPasswordPolicyOptions?.useNumbers" [(ngModel)]="passwordOptions.number" + attr.aria-label="{{ 'numbers' | i18n }}" />
@@ -256,6 +259,7 @@ (change)="savePasswordOptions()" [disabled]="enforcedPasswordPolicyOptions?.useSpecial" [(ngModel)]="passwordOptions.special" + attr.aria-label="{{ 'specialCharacters' | i18n }}" />
diff --git a/src/locales/en/messages.json b/src/locales/en/messages.json index cc977026..94efc3a9 100644 --- a/src/locales/en/messages.json +++ b/src/locales/en/messages.json @@ -400,6 +400,18 @@ "length": { "message": "Length" }, + "uppercase": { + "message": "Uppercase (A-Z)" + }, + "lowercase": { + "message": "Lowercase (a-z)" + }, + "numbers": { + "message": "Numbers (0-9)" + }, + "specialCharacters": { + "message": "Special Characters (!@#$%^&*)" + }, "numWords": { "message": "Number of Words" }, @@ -775,7 +787,7 @@ "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." }, "goToWebVault": { - "message": "Go To Web Vault" + "message": "Go to Web Vault" }, "getMobileApp": { "message": "Get Mobile App" @@ -973,7 +985,7 @@ "description": "Copy to clipboard" }, "checkForUpdates": { - "message": "Check For Updates" + "message": "Check for Updates…" }, "version": { "message": "Version $VERSION_NUM$", @@ -985,7 +997,7 @@ } }, "restartToUpdate": { - "message": "Restart To Update" + "message": "Restart to Update" }, "restartToUpdateDesc": { "message": "Version $VERSION_NUM$ is ready to install. You must restart the application to complete the installation. Do you want to restart and update now?", diff --git a/src/package.json b/src/package.json index d6989fc4..3e7ab7e0 100644 --- a/src/package.json +++ b/src/package.json @@ -2,7 +2,7 @@ "name": "@bitwarden/desktop", "productName": "Bitwarden", "description": "A secure and free password manager for all of your devices.", - "version": "1.32.2", + "version": "1.33.1", "author": "Bitwarden Inc. (https://bitwarden.com)", "homepage": "https://bitwarden.com", "license": "GPL-3.0", diff --git a/src/scss/vault.scss b/src/scss/vault.scss index 168a23e9..11623cd2 100644 --- a/src/scss/vault.scss +++ b/src/scss/vault.scss @@ -43,7 +43,7 @@ app-root { order: 1; width: 22%; min-width: 175px; - max-width: 250px; + max-width: 600px; border-right: 1px solid #000000; @include themify($themes) {