mirror of
https://github.com/bitwarden/browser.git
synced 2024-11-25 12:15:18 +01:00
Merge branch 'main' into vault/pm-5273
# Conflicts: # libs/common/src/platform/abstractions/state.service.ts # libs/common/src/platform/services/state.service.ts # libs/common/src/state-migrations/migrate.ts
This commit is contained in:
commit
8a1df6671a
72
.github/workflows/scan.yml
vendored
Normal file
72
.github/workflows/scan.yml
vendored
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
name: Scan
|
||||||
|
|
||||||
|
on:
|
||||||
|
workflow_dispatch:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- "main"
|
||||||
|
- "rc"
|
||||||
|
- "hotfix-rc"
|
||||||
|
pull_request_target:
|
||||||
|
types: [opened, synchronize]
|
||||||
|
|
||||||
|
permissions: read-all
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
check-run:
|
||||||
|
name: Check PR run
|
||||||
|
uses: bitwarden/gh-actions/.github/workflows/check-run.yml@main
|
||||||
|
|
||||||
|
sast:
|
||||||
|
name: SAST scan
|
||||||
|
runs-on: ubuntu-22.04
|
||||||
|
needs: check-run
|
||||||
|
permissions:
|
||||||
|
security-events: write
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Check out repo
|
||||||
|
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
|
||||||
|
with:
|
||||||
|
ref: ${{ github.event.pull_request.head.sha }}
|
||||||
|
|
||||||
|
- name: Scan with Checkmarx
|
||||||
|
uses: checkmarx/ast-github-action@749fec53e0db0f6404a97e2e0807c3e80e3583a7 #2.0.23
|
||||||
|
env:
|
||||||
|
INCREMENTAL: "${{ contains(github.event_name, 'pull_request') && '--sast-incremental' || '' }}"
|
||||||
|
with:
|
||||||
|
project_name: ${{ github.repository }}
|
||||||
|
cx_tenant: ${{ secrets.CHECKMARX_TENANT }}
|
||||||
|
base_uri: https://ast.checkmarx.net/
|
||||||
|
cx_client_id: ${{ secrets.CHECKMARX_CLIENT_ID }}
|
||||||
|
cx_client_secret: ${{ secrets.CHECKMARX_SECRET }}
|
||||||
|
additional_params: --report-format sarif --output-path . ${{ env.INCREMENTAL }}
|
||||||
|
|
||||||
|
- name: Upload Checkmarx results to GitHub
|
||||||
|
uses: github/codeql-action/upload-sarif@8a470fddafa5cbb6266ee11b37ef4d8aae19c571 # v3.24.6
|
||||||
|
with:
|
||||||
|
sarif_file: cx_result.sarif
|
||||||
|
|
||||||
|
quality:
|
||||||
|
name: Quality scan
|
||||||
|
runs-on: ubuntu-22.04
|
||||||
|
needs: check-run
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Check out repo
|
||||||
|
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
|
||||||
|
with:
|
||||||
|
fetch-depth: 0
|
||||||
|
ref: ${{ github.event.pull_request.head.sha }}
|
||||||
|
|
||||||
|
- name: Scan with SonarCloud
|
||||||
|
uses: sonarsource/sonarcloud-github-action@49e6cd3b187936a73b8280d59ffd9da69df63ec9 # v2.1.1
|
||||||
|
env:
|
||||||
|
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
with:
|
||||||
|
args: >
|
||||||
|
-Dsonar.organization=${{ github.repository_owner }}
|
||||||
|
-Dsonar.projectKey=${{ github.repository_owner }}_${{ github.event.repository.name }}
|
||||||
|
-Dsonar.test.inclusions=**/*.spec.ts
|
||||||
|
-Dsonar.tests=.
|
@ -119,7 +119,7 @@
|
|||||||
"message": "Дадаць лагін"
|
"message": "Дадаць лагін"
|
||||||
},
|
},
|
||||||
"addCardMenu": {
|
"addCardMenu": {
|
||||||
"message": "Add card"
|
"message": "Дадаць картку"
|
||||||
},
|
},
|
||||||
"addIdentityMenu": {
|
"addIdentityMenu": {
|
||||||
"message": "Add identity"
|
"message": "Add identity"
|
||||||
@ -269,7 +269,7 @@
|
|||||||
"message": "Даўжыня"
|
"message": "Даўжыня"
|
||||||
},
|
},
|
||||||
"passwordMinLength": {
|
"passwordMinLength": {
|
||||||
"message": "Minimum password length"
|
"message": "Мінімальная даўжыня пароля"
|
||||||
},
|
},
|
||||||
"uppercase": {
|
"uppercase": {
|
||||||
"message": "Вялікія літары (A-Z)"
|
"message": "Вялікія літары (A-Z)"
|
||||||
@ -369,7 +369,7 @@
|
|||||||
"message": "Iншае"
|
"message": "Iншае"
|
||||||
},
|
},
|
||||||
"unlockMethodNeededToChangeTimeoutActionDesc": {
|
"unlockMethodNeededToChangeTimeoutActionDesc": {
|
||||||
"message": "Set up an unlock method to change your vault timeout action."
|
"message": "Наладзіць метад разблакіроўкі для змянення дзеяння часу чакання вашага сховішча."
|
||||||
},
|
},
|
||||||
"unlockMethodNeeded": {
|
"unlockMethodNeeded": {
|
||||||
"message": "Set up an unlock method in Settings"
|
"message": "Set up an unlock method in Settings"
|
||||||
@ -415,7 +415,7 @@
|
|||||||
"message": "Заблакіраваць зараз"
|
"message": "Заблакіраваць зараз"
|
||||||
},
|
},
|
||||||
"lockAll": {
|
"lockAll": {
|
||||||
"message": "Lock all"
|
"message": "Заблакаваць усе"
|
||||||
},
|
},
|
||||||
"immediately": {
|
"immediately": {
|
||||||
"message": "Адразу"
|
"message": "Адразу"
|
||||||
@ -494,7 +494,7 @@
|
|||||||
"message": "Ваш уліковы запіс створаны! Цяпер вы можаце ўвайсці ў яго."
|
"message": "Ваш уліковы запіс створаны! Цяпер вы можаце ўвайсці ў яго."
|
||||||
},
|
},
|
||||||
"youSuccessfullyLoggedIn": {
|
"youSuccessfullyLoggedIn": {
|
||||||
"message": "You successfully logged in"
|
"message": "Вы паспяхова аўтарызаваны"
|
||||||
},
|
},
|
||||||
"youMayCloseThisWindow": {
|
"youMayCloseThisWindow": {
|
||||||
"message": "You may close this window"
|
"message": "You may close this window"
|
||||||
@ -2005,7 +2005,7 @@
|
|||||||
"message": "Выбраць папку..."
|
"message": "Выбраць папку..."
|
||||||
},
|
},
|
||||||
"noFoldersFound": {
|
"noFoldersFound": {
|
||||||
"message": "No folders found",
|
"message": "Папкі не знойдзены",
|
||||||
"description": "Used as a message within the notification bar when no folders are found"
|
"description": "Used as a message within the notification bar when no folders are found"
|
||||||
},
|
},
|
||||||
"orgPermissionsUpdatedMustSetPassword": {
|
"orgPermissionsUpdatedMustSetPassword": {
|
||||||
@ -2215,7 +2215,7 @@
|
|||||||
"message": "Версія сервера"
|
"message": "Версія сервера"
|
||||||
},
|
},
|
||||||
"selfHostedServer": {
|
"selfHostedServer": {
|
||||||
"message": "self-hosted"
|
"message": "уласнае размяшчэнне"
|
||||||
},
|
},
|
||||||
"thirdParty": {
|
"thirdParty": {
|
||||||
"message": "Іншы пастаўшчык"
|
"message": "Іншы пастаўшчык"
|
||||||
@ -2356,25 +2356,25 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"loggingInOn": {
|
"loggingInOn": {
|
||||||
"message": "Logging in on"
|
"message": "Увайсці на"
|
||||||
},
|
},
|
||||||
"opensInANewWindow": {
|
"opensInANewWindow": {
|
||||||
"message": "Адкрываць у новым акне"
|
"message": "Адкрываць у новым акне"
|
||||||
},
|
},
|
||||||
"deviceApprovalRequired": {
|
"deviceApprovalRequired": {
|
||||||
"message": "Device approval required. Select an approval option below:"
|
"message": "Патрабуецца ўхваленне прылады. Выберыце параметры ўхвалення ніжэй:"
|
||||||
},
|
},
|
||||||
"rememberThisDevice": {
|
"rememberThisDevice": {
|
||||||
"message": "Remember this device"
|
"message": "Запомніць гэту прыладу"
|
||||||
},
|
},
|
||||||
"uncheckIfPublicDevice": {
|
"uncheckIfPublicDevice": {
|
||||||
"message": "Uncheck if using a public device"
|
"message": "Здыміце пазнаку, калі выкарыстоўваеце агульнадаступную прыладу"
|
||||||
},
|
},
|
||||||
"approveFromYourOtherDevice": {
|
"approveFromYourOtherDevice": {
|
||||||
"message": "Approve from your other device"
|
"message": "Ухваліць з іншай вашай прылады"
|
||||||
},
|
},
|
||||||
"requestAdminApproval": {
|
"requestAdminApproval": {
|
||||||
"message": "Request admin approval"
|
"message": "Запытаць ухваленне адміністратара"
|
||||||
},
|
},
|
||||||
"approveWithMasterPassword": {
|
"approveWithMasterPassword": {
|
||||||
"message": "Approve with master password"
|
"message": "Approve with master password"
|
||||||
@ -2402,7 +2402,7 @@
|
|||||||
"message": "Адлюстраванне"
|
"message": "Адлюстраванне"
|
||||||
},
|
},
|
||||||
"accountSuccessfullyCreated": {
|
"accountSuccessfullyCreated": {
|
||||||
"message": "Account successfully created!"
|
"message": "Уліковы запіс паспяхова створаны!"
|
||||||
},
|
},
|
||||||
"adminApprovalRequested": {
|
"adminApprovalRequested": {
|
||||||
"message": "Admin approval requested"
|
"message": "Admin approval requested"
|
||||||
|
@ -688,7 +688,7 @@
|
|||||||
"message": "A bejelentkezési jelszó frissítésének kérése, ha változást lett érzékelve egy webhelyen. Minden bejelentkezett fiókra vonatkozik."
|
"message": "A bejelentkezési jelszó frissítésének kérése, ha változást lett érzékelve egy webhelyen. Minden bejelentkezett fiókra vonatkozik."
|
||||||
},
|
},
|
||||||
"enableUsePasskeys": {
|
"enableUsePasskeys": {
|
||||||
"message": "Kérés a jhozzáférési kulcs mentésére és használatára"
|
"message": "Kérés a hozzáférési kulcs mentésére és használatára"
|
||||||
},
|
},
|
||||||
"usePasskeysDesc": {
|
"usePasskeysDesc": {
|
||||||
"message": "Kérés az új hozzáféréi kulcsok mentésére vagy bejelentkezés a széfben tárolt hozzáférési kulcsokkal. Minden bejelentkezett fiókra vonatkozik."
|
"message": "Kérés az új hozzáféréi kulcsok mentésére vagy bejelentkezés a széfben tárolt hozzáférési kulcsokkal. Minden bejelentkezett fiókra vonatkozik."
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import { OrganizationService as AbstractOrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
import { OrganizationService as AbstractOrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
||||||
|
import { OrganizationService } from "@bitwarden/common/admin-console/services/organization/organization.service";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
FactoryOptions,
|
FactoryOptions,
|
||||||
@ -6,11 +7,7 @@ import {
|
|||||||
factory,
|
factory,
|
||||||
} from "../../../platform/background/service-factories/factory-options";
|
} from "../../../platform/background/service-factories/factory-options";
|
||||||
import { stateProviderFactory } from "../../../platform/background/service-factories/state-provider.factory";
|
import { stateProviderFactory } from "../../../platform/background/service-factories/state-provider.factory";
|
||||||
import {
|
import { StateServiceInitOptions } from "../../../platform/background/service-factories/state-service.factory";
|
||||||
stateServiceFactory,
|
|
||||||
StateServiceInitOptions,
|
|
||||||
} from "../../../platform/background/service-factories/state-service.factory";
|
|
||||||
import { BrowserOrganizationService } from "../../services/browser-organization.service";
|
|
||||||
|
|
||||||
type OrganizationServiceFactoryOptions = FactoryOptions;
|
type OrganizationServiceFactoryOptions = FactoryOptions;
|
||||||
|
|
||||||
@ -25,10 +22,6 @@ export function organizationServiceFactory(
|
|||||||
cache,
|
cache,
|
||||||
"organizationService",
|
"organizationService",
|
||||||
opts,
|
opts,
|
||||||
async () =>
|
async () => new OrganizationService(await stateProviderFactory(cache, opts)),
|
||||||
new BrowserOrganizationService(
|
|
||||||
await stateServiceFactory(cache, opts),
|
|
||||||
await stateProviderFactory(cache, opts),
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -1,12 +0,0 @@
|
|||||||
import { BehaviorSubject } from "rxjs";
|
|
||||||
|
|
||||||
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
|
|
||||||
import { OrganizationService } from "@bitwarden/common/admin-console/services/organization/organization.service";
|
|
||||||
|
|
||||||
import { browserSession, sessionSync } from "../../platform/decorators/session-sync-observable";
|
|
||||||
|
|
||||||
@browserSession
|
|
||||||
export class BrowserOrganizationService extends OrganizationService {
|
|
||||||
@sessionSync({ initializer: Organization.fromJSON, initializeAs: "array" })
|
|
||||||
protected _organizations: BehaviorSubject<Organization[]>;
|
|
||||||
}
|
|
@ -0,0 +1,38 @@
|
|||||||
|
import { AvatarService as AvatarServiceAbstraction } from "@bitwarden/common/auth/abstractions/avatar.service";
|
||||||
|
import { AvatarService } from "@bitwarden/common/auth/services/avatar.service";
|
||||||
|
|
||||||
|
import {
|
||||||
|
ApiServiceInitOptions,
|
||||||
|
apiServiceFactory,
|
||||||
|
} from "../../../platform/background/service-factories/api-service.factory";
|
||||||
|
import {
|
||||||
|
CachedServices,
|
||||||
|
factory,
|
||||||
|
FactoryOptions,
|
||||||
|
} from "../../../platform/background/service-factories/factory-options";
|
||||||
|
import {
|
||||||
|
stateProviderFactory,
|
||||||
|
StateProviderInitOptions,
|
||||||
|
} from "../../../platform/background/service-factories/state-provider.factory";
|
||||||
|
|
||||||
|
type AvatarServiceFactoryOptions = FactoryOptions;
|
||||||
|
|
||||||
|
export type AvatarServiceInitOptions = AvatarServiceFactoryOptions &
|
||||||
|
ApiServiceInitOptions &
|
||||||
|
StateProviderInitOptions;
|
||||||
|
|
||||||
|
export function avatarServiceFactory(
|
||||||
|
cache: { avatarService?: AvatarServiceAbstraction } & CachedServices,
|
||||||
|
opts: AvatarServiceInitOptions,
|
||||||
|
): Promise<AvatarServiceAbstraction> {
|
||||||
|
return factory(
|
||||||
|
cache,
|
||||||
|
"avatarService",
|
||||||
|
opts,
|
||||||
|
async () =>
|
||||||
|
new AvatarService(
|
||||||
|
await apiServiceFactory(cache, opts),
|
||||||
|
await stateProviderFactory(cache, opts),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
@ -9,6 +9,7 @@ import {
|
|||||||
ApiServiceInitOptions,
|
ApiServiceInitOptions,
|
||||||
} from "../../../platform/background/service-factories/api-service.factory";
|
} from "../../../platform/background/service-factories/api-service.factory";
|
||||||
import { appIdServiceFactory } from "../../../platform/background/service-factories/app-id-service.factory";
|
import { appIdServiceFactory } from "../../../platform/background/service-factories/app-id-service.factory";
|
||||||
|
import { billingAccountProfileStateServiceFactory } from "../../../platform/background/service-factories/billing-account-profile-state-service.factory";
|
||||||
import {
|
import {
|
||||||
CryptoServiceInitOptions,
|
CryptoServiceInitOptions,
|
||||||
cryptoServiceFactory,
|
cryptoServiceFactory,
|
||||||
@ -119,6 +120,7 @@ export function loginStrategyServiceFactory(
|
|||||||
await deviceTrustCryptoServiceFactory(cache, opts),
|
await deviceTrustCryptoServiceFactory(cache, opts),
|
||||||
await authRequestServiceFactory(cache, opts),
|
await authRequestServiceFactory(cache, opts),
|
||||||
await globalStateProviderFactory(cache, opts),
|
await globalStateProviderFactory(cache, opts),
|
||||||
|
await billingAccountProfileStateServiceFactory(cache, opts),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -7,13 +7,29 @@ import {
|
|||||||
factory,
|
factory,
|
||||||
} from "../../../platform/background/service-factories/factory-options";
|
} from "../../../platform/background/service-factories/factory-options";
|
||||||
import {
|
import {
|
||||||
stateServiceFactory,
|
GlobalStateProviderInitOptions,
|
||||||
StateServiceInitOptions,
|
globalStateProviderFactory,
|
||||||
} from "../../../platform/background/service-factories/state-service.factory";
|
} from "../../../platform/background/service-factories/global-state-provider.factory";
|
||||||
|
import {
|
||||||
|
PlatformUtilsServiceInitOptions,
|
||||||
|
platformUtilsServiceFactory,
|
||||||
|
} from "../../../platform/background/service-factories/platform-utils-service.factory";
|
||||||
|
import {
|
||||||
|
SingleUserStateProviderInitOptions,
|
||||||
|
singleUserStateProviderFactory,
|
||||||
|
} from "../../../platform/background/service-factories/single-user-state-provider.factory";
|
||||||
|
import {
|
||||||
|
SecureStorageServiceInitOptions,
|
||||||
|
secureStorageServiceFactory,
|
||||||
|
} from "../../../platform/background/service-factories/storage-service.factory";
|
||||||
|
|
||||||
type TokenServiceFactoryOptions = FactoryOptions;
|
type TokenServiceFactoryOptions = FactoryOptions;
|
||||||
|
|
||||||
export type TokenServiceInitOptions = TokenServiceFactoryOptions & StateServiceInitOptions;
|
export type TokenServiceInitOptions = TokenServiceFactoryOptions &
|
||||||
|
SingleUserStateProviderInitOptions &
|
||||||
|
GlobalStateProviderInitOptions &
|
||||||
|
PlatformUtilsServiceInitOptions &
|
||||||
|
SecureStorageServiceInitOptions;
|
||||||
|
|
||||||
export function tokenServiceFactory(
|
export function tokenServiceFactory(
|
||||||
cache: { tokenService?: AbstractTokenService } & CachedServices,
|
cache: { tokenService?: AbstractTokenService } & CachedServices,
|
||||||
@ -23,6 +39,12 @@ export function tokenServiceFactory(
|
|||||||
cache,
|
cache,
|
||||||
"tokenService",
|
"tokenService",
|
||||||
opts,
|
opts,
|
||||||
async () => new TokenService(await stateServiceFactory(cache, opts)),
|
async () =>
|
||||||
|
new TokenService(
|
||||||
|
await singleUserStateProviderFactory(cache, opts),
|
||||||
|
await globalStateProviderFactory(cache, opts),
|
||||||
|
(await platformUtilsServiceFactory(cache, opts)).supportsSecureStorage(),
|
||||||
|
await secureStorageServiceFactory(cache, opts),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -1,32 +1,61 @@
|
|||||||
import { Location } from "@angular/common";
|
import { Location } from "@angular/common";
|
||||||
import { Component } from "@angular/core";
|
import { Component } from "@angular/core";
|
||||||
import { ActivatedRoute, Router } from "@angular/router";
|
import { ActivatedRoute, Router } from "@angular/router";
|
||||||
|
import { Observable, combineLatest, switchMap } from "rxjs";
|
||||||
|
|
||||||
import { CurrentAccountService } from "./services/current-account.service";
|
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
||||||
|
import { AvatarService } from "@bitwarden/common/auth/abstractions/avatar.service";
|
||||||
|
import { AuthenticationStatus } from "@bitwarden/common/auth/enums/authentication-status";
|
||||||
|
import { UserId } from "@bitwarden/common/types/guid";
|
||||||
|
|
||||||
|
export type CurrentAccount = {
|
||||||
|
id: UserId;
|
||||||
|
name: string | undefined;
|
||||||
|
email: string;
|
||||||
|
status: AuthenticationStatus;
|
||||||
|
avatarColor: string;
|
||||||
|
};
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: "app-current-account",
|
selector: "app-current-account",
|
||||||
templateUrl: "current-account.component.html",
|
templateUrl: "current-account.component.html",
|
||||||
})
|
})
|
||||||
export class CurrentAccountComponent {
|
export class CurrentAccountComponent {
|
||||||
|
currentAccount$: Observable<CurrentAccount>;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private currentAccountService: CurrentAccountService,
|
private accountService: AccountService,
|
||||||
|
private avatarService: AvatarService,
|
||||||
private router: Router,
|
private router: Router,
|
||||||
private location: Location,
|
private location: Location,
|
||||||
private route: ActivatedRoute,
|
private route: ActivatedRoute,
|
||||||
) {}
|
) {
|
||||||
|
this.currentAccount$ = combineLatest([
|
||||||
|
this.accountService.activeAccount$,
|
||||||
|
this.avatarService.avatarColor$,
|
||||||
|
]).pipe(
|
||||||
|
switchMap(async ([account, avatarColor]) => {
|
||||||
|
if (account == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
const currentAccount: CurrentAccount = {
|
||||||
|
id: account.id,
|
||||||
|
name: account.name || account.email,
|
||||||
|
email: account.email,
|
||||||
|
status: account.status,
|
||||||
|
avatarColor,
|
||||||
|
};
|
||||||
|
|
||||||
get currentAccount$() {
|
return currentAccount;
|
||||||
return this.currentAccountService.currentAccount$;
|
}),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
async currentAccountClicked() {
|
async currentAccountClicked() {
|
||||||
if (this.route.snapshot.data.state.includes("account-switcher")) {
|
if (this.route.snapshot.data.state.includes("account-switcher")) {
|
||||||
this.location.back();
|
this.location.back();
|
||||||
} else {
|
} else {
|
||||||
// FIXME: Verify that this floating promise is intentional. If it is, add an explanatory comment and ensure there is proper error handling.
|
await this.router.navigate(["/account-switcher"]);
|
||||||
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
|
||||||
this.router.navigate(["/account-switcher"]);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
import { matches, mock } from "jest-mock-extended";
|
import { matches, mock } from "jest-mock-extended";
|
||||||
import { BehaviorSubject, firstValueFrom, timeout } from "rxjs";
|
import { BehaviorSubject, firstValueFrom, of, timeout } from "rxjs";
|
||||||
|
|
||||||
import { AccountInfo, AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
import { AccountInfo, AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
||||||
|
import { AvatarService } from "@bitwarden/common/auth/abstractions/avatar.service";
|
||||||
import { AuthenticationStatus } from "@bitwarden/common/auth/enums/authentication-status";
|
import { AuthenticationStatus } from "@bitwarden/common/auth/enums/authentication-status";
|
||||||
import { EnvironmentService } from "@bitwarden/common/platform/abstractions/environment.service";
|
import { EnvironmentService } from "@bitwarden/common/platform/abstractions/environment.service";
|
||||||
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
|
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
|
||||||
import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service";
|
import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service";
|
||||||
import { StateService } from "@bitwarden/common/platform/abstractions/state.service";
|
|
||||||
import { UserId } from "@bitwarden/common/types/guid";
|
import { UserId } from "@bitwarden/common/types/guid";
|
||||||
|
|
||||||
import { AccountSwitcherService } from "./account-switcher.service";
|
import { AccountSwitcherService } from "./account-switcher.service";
|
||||||
@ -16,7 +16,7 @@ describe("AccountSwitcherService", () => {
|
|||||||
const activeAccountSubject = new BehaviorSubject<{ id: UserId } & AccountInfo>(null);
|
const activeAccountSubject = new BehaviorSubject<{ id: UserId } & AccountInfo>(null);
|
||||||
|
|
||||||
const accountService = mock<AccountService>();
|
const accountService = mock<AccountService>();
|
||||||
const stateService = mock<StateService>();
|
const avatarService = mock<AvatarService>();
|
||||||
const messagingService = mock<MessagingService>();
|
const messagingService = mock<MessagingService>();
|
||||||
const environmentService = mock<EnvironmentService>();
|
const environmentService = mock<EnvironmentService>();
|
||||||
const logService = mock<LogService>();
|
const logService = mock<LogService>();
|
||||||
@ -25,11 +25,13 @@ describe("AccountSwitcherService", () => {
|
|||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
jest.resetAllMocks();
|
jest.resetAllMocks();
|
||||||
|
|
||||||
accountService.accounts$ = accountsSubject;
|
accountService.accounts$ = accountsSubject;
|
||||||
accountService.activeAccount$ = activeAccountSubject;
|
accountService.activeAccount$ = activeAccountSubject;
|
||||||
|
|
||||||
accountSwitcherService = new AccountSwitcherService(
|
accountSwitcherService = new AccountSwitcherService(
|
||||||
accountService,
|
accountService,
|
||||||
stateService,
|
avatarService,
|
||||||
messagingService,
|
messagingService,
|
||||||
environmentService,
|
environmentService,
|
||||||
logService,
|
logService,
|
||||||
@ -44,6 +46,7 @@ describe("AccountSwitcherService", () => {
|
|||||||
status: AuthenticationStatus.Unlocked,
|
status: AuthenticationStatus.Unlocked,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
avatarService.getUserAvatarColor$.mockReturnValue(of("#cccccc"));
|
||||||
accountsSubject.next({
|
accountsSubject.next({
|
||||||
"1": user1AccountInfo,
|
"1": user1AccountInfo,
|
||||||
} as Record<UserId, AccountInfo>);
|
} as Record<UserId, AccountInfo>);
|
||||||
@ -72,6 +75,7 @@ describe("AccountSwitcherService", () => {
|
|||||||
status: AuthenticationStatus.Unlocked,
|
status: AuthenticationStatus.Unlocked,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
avatarService.getUserAvatarColor$.mockReturnValue(of("#cccccc"));
|
||||||
accountsSubject.next(seedAccounts);
|
accountsSubject.next(seedAccounts);
|
||||||
activeAccountSubject.next(
|
activeAccountSubject.next(
|
||||||
Object.assign(seedAccounts["1" as UserId], { id: "1" as UserId }),
|
Object.assign(seedAccounts["1" as UserId], { id: "1" as UserId }),
|
||||||
|
@ -11,11 +11,11 @@ import {
|
|||||||
} from "rxjs";
|
} from "rxjs";
|
||||||
|
|
||||||
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
||||||
|
import { AvatarService } from "@bitwarden/common/auth/abstractions/avatar.service";
|
||||||
import { AuthenticationStatus } from "@bitwarden/common/auth/enums/authentication-status";
|
import { AuthenticationStatus } from "@bitwarden/common/auth/enums/authentication-status";
|
||||||
import { EnvironmentService } from "@bitwarden/common/platform/abstractions/environment.service";
|
import { EnvironmentService } from "@bitwarden/common/platform/abstractions/environment.service";
|
||||||
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
|
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
|
||||||
import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service";
|
import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service";
|
||||||
import { StateService } from "@bitwarden/common/platform/abstractions/state.service";
|
|
||||||
import { UserId } from "@bitwarden/common/types/guid";
|
import { UserId } from "@bitwarden/common/types/guid";
|
||||||
|
|
||||||
import { fromChromeEvent } from "../../../../platform/browser/from-chrome-event";
|
import { fromChromeEvent } from "../../../../platform/browser/from-chrome-event";
|
||||||
@ -44,7 +44,7 @@ export class AccountSwitcherService {
|
|||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private accountService: AccountService,
|
private accountService: AccountService,
|
||||||
private stateService: StateService,
|
private avatarService: AvatarService,
|
||||||
private messagingService: MessagingService,
|
private messagingService: MessagingService,
|
||||||
private environmentService: EnvironmentService,
|
private environmentService: EnvironmentService,
|
||||||
private logService: LogService,
|
private logService: LogService,
|
||||||
@ -68,7 +68,9 @@ export class AccountSwitcherService {
|
|||||||
server: await this.environmentService.getHost(id),
|
server: await this.environmentService.getHost(id),
|
||||||
status: account.status,
|
status: account.status,
|
||||||
isActive: id === activeAccount?.id,
|
isActive: id === activeAccount?.id,
|
||||||
avatarColor: await this.stateService.getAvatarColor({ userId: id }),
|
avatarColor: await firstValueFrom(
|
||||||
|
this.avatarService.getUserAvatarColor$(id as UserId),
|
||||||
|
),
|
||||||
};
|
};
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
@ -1,44 +0,0 @@
|
|||||||
import { Injectable } from "@angular/core";
|
|
||||||
import { Observable, switchMap } from "rxjs";
|
|
||||||
|
|
||||||
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
|
||||||
import { AuthenticationStatus } from "@bitwarden/common/auth/enums/authentication-status";
|
|
||||||
import { StateService } from "@bitwarden/common/platform/abstractions/state.service";
|
|
||||||
import { UserId } from "@bitwarden/common/types/guid";
|
|
||||||
|
|
||||||
export type CurrentAccount = {
|
|
||||||
id: UserId;
|
|
||||||
name: string | undefined;
|
|
||||||
email: string;
|
|
||||||
status: AuthenticationStatus;
|
|
||||||
avatarColor: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
@Injectable({
|
|
||||||
providedIn: "root",
|
|
||||||
})
|
|
||||||
export class CurrentAccountService {
|
|
||||||
currentAccount$: Observable<CurrentAccount>;
|
|
||||||
|
|
||||||
constructor(
|
|
||||||
private accountService: AccountService,
|
|
||||||
private stateService: StateService,
|
|
||||||
) {
|
|
||||||
this.currentAccount$ = this.accountService.activeAccount$.pipe(
|
|
||||||
switchMap(async (account) => {
|
|
||||||
if (account == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
const currentAccount: CurrentAccount = {
|
|
||||||
id: account.id,
|
|
||||||
name: account.name || account.email,
|
|
||||||
email: account.email,
|
|
||||||
status: account.status,
|
|
||||||
avatarColor: await this.stateService.getAvatarColor({ userId: account.id }),
|
|
||||||
};
|
|
||||||
|
|
||||||
return currentAccount;
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
@ -91,6 +91,8 @@ export class LoginComponent extends BaseLoginComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async launchSsoBrowser() {
|
async launchSsoBrowser() {
|
||||||
|
// Save off email for SSO
|
||||||
|
await this.ssoLoginService.setSsoEmail(this.formGroup.value.email);
|
||||||
await this.loginService.saveEmailSettings();
|
await this.loginService.saveEmailSettings();
|
||||||
// Generate necessary sso params
|
// Generate necessary sso params
|
||||||
const passwordOptions: any = {
|
const passwordOptions: any = {
|
||||||
|
@ -3,6 +3,7 @@ import { ActivatedRoute, Router } from "@angular/router";
|
|||||||
|
|
||||||
import { TwoFactorOptionsComponent as BaseTwoFactorOptionsComponent } from "@bitwarden/angular/auth/components/two-factor-options.component";
|
import { TwoFactorOptionsComponent as BaseTwoFactorOptionsComponent } from "@bitwarden/angular/auth/components/two-factor-options.component";
|
||||||
import { TwoFactorService } from "@bitwarden/common/auth/abstractions/two-factor.service";
|
import { TwoFactorService } from "@bitwarden/common/auth/abstractions/two-factor.service";
|
||||||
|
import { EnvironmentService } from "@bitwarden/common/platform/abstractions/environment.service";
|
||||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||||
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
||||||
|
|
||||||
@ -16,9 +17,10 @@ export class TwoFactorOptionsComponent extends BaseTwoFactorOptionsComponent {
|
|||||||
router: Router,
|
router: Router,
|
||||||
i18nService: I18nService,
|
i18nService: I18nService,
|
||||||
platformUtilsService: PlatformUtilsService,
|
platformUtilsService: PlatformUtilsService,
|
||||||
|
environmentService: EnvironmentService,
|
||||||
private activatedRoute: ActivatedRoute,
|
private activatedRoute: ActivatedRoute,
|
||||||
) {
|
) {
|
||||||
super(twoFactorService, router, i18nService, platformUtilsService, window);
|
super(twoFactorService, router, i18nService, platformUtilsService, window, environmentService);
|
||||||
}
|
}
|
||||||
|
|
||||||
close() {
|
close() {
|
||||||
|
@ -8,11 +8,21 @@ import {
|
|||||||
AutofillOverlayVisibility,
|
AutofillOverlayVisibility,
|
||||||
} from "@bitwarden/common/autofill/constants";
|
} from "@bitwarden/common/autofill/constants";
|
||||||
import { AutofillSettingsService } from "@bitwarden/common/autofill/services/autofill-settings.service";
|
import { AutofillSettingsService } from "@bitwarden/common/autofill/services/autofill-settings.service";
|
||||||
|
import {
|
||||||
|
DefaultDomainSettingsService,
|
||||||
|
DomainSettingsService,
|
||||||
|
} from "@bitwarden/common/autofill/services/domain-settings.service";
|
||||||
import { ThemeType } from "@bitwarden/common/platform/enums";
|
import { ThemeType } from "@bitwarden/common/platform/enums";
|
||||||
|
import { Utils } from "@bitwarden/common/platform/misc/utils";
|
||||||
import { EnvironmentService } from "@bitwarden/common/platform/services/environment.service";
|
import { EnvironmentService } from "@bitwarden/common/platform/services/environment.service";
|
||||||
import { I18nService } from "@bitwarden/common/platform/services/i18n.service";
|
import { I18nService } from "@bitwarden/common/platform/services/i18n.service";
|
||||||
import { ThemeStateService } from "@bitwarden/common/platform/theming/theme-state.service";
|
import { ThemeStateService } from "@bitwarden/common/platform/theming/theme-state.service";
|
||||||
import { SettingsService } from "@bitwarden/common/services/settings.service";
|
import {
|
||||||
|
FakeStateProvider,
|
||||||
|
FakeAccountService,
|
||||||
|
mockAccountServiceWith,
|
||||||
|
} from "@bitwarden/common/spec";
|
||||||
|
import { UserId } from "@bitwarden/common/types/guid";
|
||||||
import { CipherType } from "@bitwarden/common/vault/enums";
|
import { CipherType } from "@bitwarden/common/vault/enums";
|
||||||
import { CipherRepromptType } from "@bitwarden/common/vault/enums/cipher-reprompt-type";
|
import { CipherRepromptType } from "@bitwarden/common/vault/enums/cipher-reprompt-type";
|
||||||
import { CipherView } from "@bitwarden/common/vault/models/view/cipher.view";
|
import { CipherView } from "@bitwarden/common/vault/models/view/cipher.view";
|
||||||
@ -41,6 +51,10 @@ import OverlayBackground from "./overlay.background";
|
|||||||
const iconServerUrl = "https://icons.bitwarden.com/";
|
const iconServerUrl = "https://icons.bitwarden.com/";
|
||||||
|
|
||||||
describe("OverlayBackground", () => {
|
describe("OverlayBackground", () => {
|
||||||
|
const mockUserId = Utils.newGuid() as UserId;
|
||||||
|
const accountService: FakeAccountService = mockAccountServiceWith(mockUserId);
|
||||||
|
const fakeStateProvider: FakeStateProvider = new FakeStateProvider(accountService);
|
||||||
|
let domainSettingsService: DomainSettingsService;
|
||||||
let buttonPortSpy: chrome.runtime.Port;
|
let buttonPortSpy: chrome.runtime.Port;
|
||||||
let listPortSpy: chrome.runtime.Port;
|
let listPortSpy: chrome.runtime.Port;
|
||||||
let overlayBackground: OverlayBackground;
|
let overlayBackground: OverlayBackground;
|
||||||
@ -50,7 +64,6 @@ describe("OverlayBackground", () => {
|
|||||||
const environmentService = mock<EnvironmentService>({
|
const environmentService = mock<EnvironmentService>({
|
||||||
getIconsUrl: () => iconServerUrl,
|
getIconsUrl: () => iconServerUrl,
|
||||||
});
|
});
|
||||||
const settingsService = mock<SettingsService>();
|
|
||||||
const stateService = mock<BrowserStateService>();
|
const stateService = mock<BrowserStateService>();
|
||||||
const autofillSettingsService = mock<AutofillSettingsService>();
|
const autofillSettingsService = mock<AutofillSettingsService>();
|
||||||
const i18nService = mock<I18nService>();
|
const i18nService = mock<I18nService>();
|
||||||
@ -72,12 +85,13 @@ describe("OverlayBackground", () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
|
domainSettingsService = new DefaultDomainSettingsService(fakeStateProvider);
|
||||||
overlayBackground = new OverlayBackground(
|
overlayBackground = new OverlayBackground(
|
||||||
cipherService,
|
cipherService,
|
||||||
autofillService,
|
autofillService,
|
||||||
authService,
|
authService,
|
||||||
environmentService,
|
environmentService,
|
||||||
settingsService,
|
domainSettingsService,
|
||||||
stateService,
|
stateService,
|
||||||
autofillSettingsService,
|
autofillSettingsService,
|
||||||
i18nService,
|
i18nService,
|
||||||
@ -90,6 +104,7 @@ describe("OverlayBackground", () => {
|
|||||||
.mockResolvedValue(AutofillOverlayVisibility.OnFieldFocus);
|
.mockResolvedValue(AutofillOverlayVisibility.OnFieldFocus);
|
||||||
|
|
||||||
themeStateService.selectedTheme$ = of(ThemeType.Light);
|
themeStateService.selectedTheme$ = of(ThemeType.Light);
|
||||||
|
domainSettingsService.showFavicons$ = of(true);
|
||||||
|
|
||||||
void overlayBackground.init();
|
void overlayBackground.init();
|
||||||
});
|
});
|
||||||
@ -274,7 +289,7 @@ describe("OverlayBackground", () => {
|
|||||||
card: { subTitle: "Mastercard, *1234" },
|
card: { subTitle: "Mastercard, *1234" },
|
||||||
});
|
});
|
||||||
|
|
||||||
it("formats and returns the cipher data", () => {
|
it("formats and returns the cipher data", async () => {
|
||||||
overlayBackground["overlayLoginCiphers"] = new Map([
|
overlayBackground["overlayLoginCiphers"] = new Map([
|
||||||
["overlay-cipher-0", cipher2],
|
["overlay-cipher-0", cipher2],
|
||||||
["overlay-cipher-1", cipher1],
|
["overlay-cipher-1", cipher1],
|
||||||
@ -282,7 +297,7 @@ describe("OverlayBackground", () => {
|
|||||||
["overlay-cipher-3", cipher4],
|
["overlay-cipher-3", cipher4],
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const overlayCipherData = overlayBackground["getOverlayCipherData"]();
|
const overlayCipherData = await overlayBackground["getOverlayCipherData"]();
|
||||||
|
|
||||||
expect(overlayCipherData).toStrictEqual([
|
expect(overlayCipherData).toStrictEqual([
|
||||||
{
|
{
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
import { firstValueFrom } from "rxjs";
|
import { firstValueFrom } from "rxjs";
|
||||||
|
|
||||||
import { SettingsService } from "@bitwarden/common/abstractions/settings.service";
|
|
||||||
import { AuthService } from "@bitwarden/common/auth/abstractions/auth.service";
|
import { AuthService } from "@bitwarden/common/auth/abstractions/auth.service";
|
||||||
import { AuthenticationStatus } from "@bitwarden/common/auth/enums/authentication-status";
|
import { AuthenticationStatus } from "@bitwarden/common/auth/enums/authentication-status";
|
||||||
import { SHOW_AUTOFILL_BUTTON } from "@bitwarden/common/autofill/constants";
|
import { SHOW_AUTOFILL_BUTTON } from "@bitwarden/common/autofill/constants";
|
||||||
import { AutofillSettingsServiceAbstraction } from "@bitwarden/common/autofill/services/autofill-settings.service";
|
import { AutofillSettingsServiceAbstraction } from "@bitwarden/common/autofill/services/autofill-settings.service";
|
||||||
|
import { DomainSettingsService } from "@bitwarden/common/autofill/services/domain-settings.service";
|
||||||
import { InlineMenuVisibilitySetting } from "@bitwarden/common/autofill/types";
|
import { InlineMenuVisibilitySetting } from "@bitwarden/common/autofill/types";
|
||||||
import { EnvironmentService } from "@bitwarden/common/platform/abstractions/environment.service";
|
import { EnvironmentService } from "@bitwarden/common/platform/abstractions/environment.service";
|
||||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||||
@ -92,7 +92,7 @@ class OverlayBackground implements OverlayBackgroundInterface {
|
|||||||
private autofillService: AutofillService,
|
private autofillService: AutofillService,
|
||||||
private authService: AuthService,
|
private authService: AuthService,
|
||||||
private environmentService: EnvironmentService,
|
private environmentService: EnvironmentService,
|
||||||
private settingsService: SettingsService,
|
private domainSettingsService: DomainSettingsService,
|
||||||
private stateService: StateService,
|
private stateService: StateService,
|
||||||
private autofillSettingsService: AutofillSettingsServiceAbstraction,
|
private autofillSettingsService: AutofillSettingsServiceAbstraction,
|
||||||
private i18nService: I18nService,
|
private i18nService: I18nService,
|
||||||
@ -145,7 +145,7 @@ class OverlayBackground implements OverlayBackgroundInterface {
|
|||||||
this.overlayLoginCiphers.set(`overlay-cipher-${cipherIndex}`, ciphersViews[cipherIndex]);
|
this.overlayLoginCiphers.set(`overlay-cipher-${cipherIndex}`, ciphersViews[cipherIndex]);
|
||||||
}
|
}
|
||||||
|
|
||||||
const ciphers = this.getOverlayCipherData();
|
const ciphers = await this.getOverlayCipherData();
|
||||||
this.overlayListPort?.postMessage({ command: "updateOverlayListCiphers", ciphers });
|
this.overlayListPort?.postMessage({ command: "updateOverlayListCiphers", ciphers });
|
||||||
await BrowserApi.tabSendMessageData(currentTab, "updateIsOverlayCiphersPopulated", {
|
await BrowserApi.tabSendMessageData(currentTab, "updateIsOverlayCiphersPopulated", {
|
||||||
isOverlayCiphersPopulated: Boolean(ciphers.length),
|
isOverlayCiphersPopulated: Boolean(ciphers.length),
|
||||||
@ -156,8 +156,8 @@ class OverlayBackground implements OverlayBackgroundInterface {
|
|||||||
* Strips out unnecessary data from the ciphers and returns an array of
|
* Strips out unnecessary data from the ciphers and returns an array of
|
||||||
* objects that contain the cipher data needed for the overlay list.
|
* objects that contain the cipher data needed for the overlay list.
|
||||||
*/
|
*/
|
||||||
private getOverlayCipherData(): OverlayCipherData[] {
|
private async getOverlayCipherData(): Promise<OverlayCipherData[]> {
|
||||||
const isFaviconDisabled = this.settingsService.getDisableFavicon();
|
const showFavicons = await firstValueFrom(this.domainSettingsService.showFavicons$);
|
||||||
const overlayCiphersArray = Array.from(this.overlayLoginCiphers);
|
const overlayCiphersArray = Array.from(this.overlayLoginCiphers);
|
||||||
const overlayCipherData = [];
|
const overlayCipherData = [];
|
||||||
let loginCipherIcon: WebsiteIconData;
|
let loginCipherIcon: WebsiteIconData;
|
||||||
@ -165,7 +165,7 @@ class OverlayBackground implements OverlayBackgroundInterface {
|
|||||||
for (let cipherIndex = 0; cipherIndex < overlayCiphersArray.length; cipherIndex++) {
|
for (let cipherIndex = 0; cipherIndex < overlayCiphersArray.length; cipherIndex++) {
|
||||||
const [overlayCipherId, cipher] = overlayCiphersArray[cipherIndex];
|
const [overlayCipherId, cipher] = overlayCiphersArray[cipherIndex];
|
||||||
if (!loginCipherIcon && cipher.type === CipherType.Login) {
|
if (!loginCipherIcon && cipher.type === CipherType.Login) {
|
||||||
loginCipherIcon = buildCipherIcon(this.iconsServerUrl, cipher, isFaviconDisabled);
|
loginCipherIcon = buildCipherIcon(this.iconsServerUrl, cipher, showFavicons);
|
||||||
}
|
}
|
||||||
|
|
||||||
overlayCipherData.push({
|
overlayCipherData.push({
|
||||||
@ -177,7 +177,7 @@ class OverlayBackground implements OverlayBackgroundInterface {
|
|||||||
icon:
|
icon:
|
||||||
cipher.type === CipherType.Login
|
cipher.type === CipherType.Login
|
||||||
? loginCipherIcon
|
? loginCipherIcon
|
||||||
: buildCipherIcon(this.iconsServerUrl, cipher, isFaviconDisabled),
|
: buildCipherIcon(this.iconsServerUrl, cipher, showFavicons),
|
||||||
login: cipher.type === CipherType.Login ? { username: cipher.login.username } : null,
|
login: cipher.type === CipherType.Login ? { username: cipher.login.username } : null,
|
||||||
card: cipher.type === CipherType.Card ? cipher.card.subTitle : null,
|
card: cipher.type === CipherType.Card ? cipher.card.subTitle : null,
|
||||||
});
|
});
|
||||||
@ -699,7 +699,7 @@ class OverlayBackground implements OverlayBackgroundInterface {
|
|||||||
styleSheetUrl: chrome.runtime.getURL(`overlay/${isOverlayListPort ? "list" : "button"}.css`),
|
styleSheetUrl: chrome.runtime.getURL(`overlay/${isOverlayListPort ? "list" : "button"}.css`),
|
||||||
theme: await firstValueFrom(this.themeStateService.selectedTheme$),
|
theme: await firstValueFrom(this.themeStateService.selectedTheme$),
|
||||||
translations: this.getTranslations(),
|
translations: this.getTranslations(),
|
||||||
ciphers: isOverlayListPort ? this.getOverlayCipherData() : null,
|
ciphers: isOverlayListPort ? await this.getOverlayCipherData() : null,
|
||||||
});
|
});
|
||||||
this.updateOverlayPosition({
|
this.updateOverlayPosition({
|
||||||
overlayElement: isOverlayListPort
|
overlayElement: isOverlayListPort
|
||||||
|
@ -6,6 +6,7 @@ import {
|
|||||||
EventCollectionServiceInitOptions,
|
EventCollectionServiceInitOptions,
|
||||||
eventCollectionServiceFactory,
|
eventCollectionServiceFactory,
|
||||||
} from "../../../background/service-factories/event-collection-service.factory";
|
} from "../../../background/service-factories/event-collection-service.factory";
|
||||||
|
import { billingAccountProfileStateServiceFactory } from "../../../platform/background/service-factories/billing-account-profile-state-service.factory";
|
||||||
import {
|
import {
|
||||||
CachedServices,
|
CachedServices,
|
||||||
factory,
|
factory,
|
||||||
@ -69,6 +70,7 @@ export function autofillServiceFactory(
|
|||||||
await logServiceFactory(cache, opts),
|
await logServiceFactory(cache, opts),
|
||||||
await domainSettingsServiceFactory(cache, opts),
|
await domainSettingsServiceFactory(cache, opts),
|
||||||
await userVerificationServiceFactory(cache, opts),
|
await userVerificationServiceFactory(cache, opts),
|
||||||
|
await billingAccountProfileStateServiceFactory(cache, opts),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,7 @@ import { of } from "rxjs";
|
|||||||
|
|
||||||
import { NOOP_COMMAND_SUFFIX } from "@bitwarden/common/autofill/constants";
|
import { NOOP_COMMAND_SUFFIX } from "@bitwarden/common/autofill/constants";
|
||||||
import { AutofillSettingsServiceAbstraction } from "@bitwarden/common/autofill/services/autofill-settings.service";
|
import { AutofillSettingsServiceAbstraction } from "@bitwarden/common/autofill/services/autofill-settings.service";
|
||||||
|
import { BillingAccountProfileStateService } from "@bitwarden/common/billing/abstractions/account/billing-account-profile-state.service";
|
||||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||||
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
|
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
|
||||||
import { CipherType } from "@bitwarden/common/vault/enums";
|
import { CipherType } from "@bitwarden/common/vault/enums";
|
||||||
@ -18,6 +19,7 @@ describe("context-menu", () => {
|
|||||||
let autofillSettingsService: MockProxy<AutofillSettingsServiceAbstraction>;
|
let autofillSettingsService: MockProxy<AutofillSettingsServiceAbstraction>;
|
||||||
let i18nService: MockProxy<I18nService>;
|
let i18nService: MockProxy<I18nService>;
|
||||||
let logService: MockProxy<LogService>;
|
let logService: MockProxy<LogService>;
|
||||||
|
let billingAccountProfileStateService: MockProxy<BillingAccountProfileStateService>;
|
||||||
|
|
||||||
let removeAllSpy: jest.SpyInstance<void, [callback?: () => void]>;
|
let removeAllSpy: jest.SpyInstance<void, [callback?: () => void]>;
|
||||||
let createSpy: jest.SpyInstance<
|
let createSpy: jest.SpyInstance<
|
||||||
@ -32,6 +34,7 @@ describe("context-menu", () => {
|
|||||||
autofillSettingsService = mock();
|
autofillSettingsService = mock();
|
||||||
i18nService = mock();
|
i18nService = mock();
|
||||||
logService = mock();
|
logService = mock();
|
||||||
|
billingAccountProfileStateService = mock();
|
||||||
|
|
||||||
removeAllSpy = jest
|
removeAllSpy = jest
|
||||||
.spyOn(chrome.contextMenus, "removeAll")
|
.spyOn(chrome.contextMenus, "removeAll")
|
||||||
@ -50,6 +53,7 @@ describe("context-menu", () => {
|
|||||||
autofillSettingsService,
|
autofillSettingsService,
|
||||||
i18nService,
|
i18nService,
|
||||||
logService,
|
logService,
|
||||||
|
billingAccountProfileStateService,
|
||||||
);
|
);
|
||||||
autofillSettingsService.enableContextMenu$ = of(true);
|
autofillSettingsService.enableContextMenu$ = of(true);
|
||||||
});
|
});
|
||||||
@ -66,7 +70,7 @@ describe("context-menu", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("has menu enabled, but does not have premium", async () => {
|
it("has menu enabled, but does not have premium", async () => {
|
||||||
stateService.getCanAccessPremium.mockResolvedValue(false);
|
billingAccountProfileStateService.hasPremiumFromAnySource$ = of(false);
|
||||||
|
|
||||||
const createdMenu = await sut.init();
|
const createdMenu = await sut.init();
|
||||||
expect(createdMenu).toBeTruthy();
|
expect(createdMenu).toBeTruthy();
|
||||||
@ -74,7 +78,7 @@ describe("context-menu", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("has menu enabled and has premium", async () => {
|
it("has menu enabled and has premium", async () => {
|
||||||
stateService.getCanAccessPremium.mockResolvedValue(true);
|
billingAccountProfileStateService.hasPremiumFromAnySource$ = of(true);
|
||||||
|
|
||||||
const createdMenu = await sut.init();
|
const createdMenu = await sut.init();
|
||||||
expect(createdMenu).toBeTruthy();
|
expect(createdMenu).toBeTruthy();
|
||||||
@ -128,7 +132,7 @@ describe("context-menu", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("create entry for each cipher piece", async () => {
|
it("create entry for each cipher piece", async () => {
|
||||||
stateService.getCanAccessPremium.mockResolvedValue(true);
|
billingAccountProfileStateService.hasPremiumFromAnySource$ = of(true);
|
||||||
|
|
||||||
await sut.loadOptions("TEST_TITLE", "1", createCipher());
|
await sut.loadOptions("TEST_TITLE", "1", createCipher());
|
||||||
|
|
||||||
@ -137,7 +141,7 @@ describe("context-menu", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("creates a login/unlock item for each context menu action option when user is not authenticated", async () => {
|
it("creates a login/unlock item for each context menu action option when user is not authenticated", async () => {
|
||||||
stateService.getCanAccessPremium.mockResolvedValue(true);
|
billingAccountProfileStateService.hasPremiumFromAnySource$ = of(true);
|
||||||
|
|
||||||
await sut.loadOptions("TEST_TITLE", "NOOP");
|
await sut.loadOptions("TEST_TITLE", "NOOP");
|
||||||
|
|
||||||
|
@ -17,6 +17,7 @@ import {
|
|||||||
SEPARATOR_ID,
|
SEPARATOR_ID,
|
||||||
} from "@bitwarden/common/autofill/constants";
|
} from "@bitwarden/common/autofill/constants";
|
||||||
import { AutofillSettingsServiceAbstraction } from "@bitwarden/common/autofill/services/autofill-settings.service";
|
import { AutofillSettingsServiceAbstraction } from "@bitwarden/common/autofill/services/autofill-settings.service";
|
||||||
|
import { BillingAccountProfileStateService } from "@bitwarden/common/billing/abstractions/account/billing-account-profile-state.service";
|
||||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||||
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
|
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
|
||||||
import { StateFactory } from "@bitwarden/common/platform/factories/state-factory";
|
import { StateFactory } from "@bitwarden/common/platform/factories/state-factory";
|
||||||
@ -27,6 +28,7 @@ import { CipherView } from "@bitwarden/common/vault/models/view/cipher.view";
|
|||||||
|
|
||||||
import { autofillSettingsServiceFactory } from "../../autofill/background/service_factories/autofill-settings-service.factory";
|
import { autofillSettingsServiceFactory } from "../../autofill/background/service_factories/autofill-settings-service.factory";
|
||||||
import { Account } from "../../models/account";
|
import { Account } from "../../models/account";
|
||||||
|
import { billingAccountProfileStateServiceFactory } from "../../platform/background/service-factories/billing-account-profile-state-service.factory";
|
||||||
import { CachedServices } from "../../platform/background/service-factories/factory-options";
|
import { CachedServices } from "../../platform/background/service-factories/factory-options";
|
||||||
import {
|
import {
|
||||||
i18nServiceFactory,
|
i18nServiceFactory,
|
||||||
@ -163,6 +165,7 @@ export class MainContextMenuHandler {
|
|||||||
private autofillSettingsService: AutofillSettingsServiceAbstraction,
|
private autofillSettingsService: AutofillSettingsServiceAbstraction,
|
||||||
private i18nService: I18nService,
|
private i18nService: I18nService,
|
||||||
private logService: LogService,
|
private logService: LogService,
|
||||||
|
private billingAccountProfileStateService: BillingAccountProfileStateService,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
static async mv3Create(cachedServices: CachedServices) {
|
static async mv3Create(cachedServices: CachedServices) {
|
||||||
@ -184,6 +187,11 @@ export class MainContextMenuHandler {
|
|||||||
stateServiceOptions: {
|
stateServiceOptions: {
|
||||||
stateFactory: stateFactory,
|
stateFactory: stateFactory,
|
||||||
},
|
},
|
||||||
|
platformUtilsServiceOptions: {
|
||||||
|
clipboardWriteCallback: () => Promise.resolve(),
|
||||||
|
biometricCallback: () => Promise.resolve(false),
|
||||||
|
win: self,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
return new MainContextMenuHandler(
|
return new MainContextMenuHandler(
|
||||||
@ -191,6 +199,7 @@ export class MainContextMenuHandler {
|
|||||||
await autofillSettingsServiceFactory(cachedServices, serviceOptions),
|
await autofillSettingsServiceFactory(cachedServices, serviceOptions),
|
||||||
await i18nServiceFactory(cachedServices, serviceOptions),
|
await i18nServiceFactory(cachedServices, serviceOptions),
|
||||||
await logServiceFactory(cachedServices, serviceOptions),
|
await logServiceFactory(cachedServices, serviceOptions),
|
||||||
|
await billingAccountProfileStateServiceFactory(cachedServices, serviceOptions),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -212,7 +221,10 @@ export class MainContextMenuHandler {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
for (const options of this.initContextMenuItems) {
|
for (const options of this.initContextMenuItems) {
|
||||||
if (options.checkPremiumAccess && !(await this.stateService.getCanAccessPremium())) {
|
if (
|
||||||
|
options.checkPremiumAccess &&
|
||||||
|
!(await firstValueFrom(this.billingAccountProfileStateService.hasPremiumFromAnySource$))
|
||||||
|
) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -307,7 +319,9 @@ export class MainContextMenuHandler {
|
|||||||
await createChildItem(COPY_USERNAME_ID);
|
await createChildItem(COPY_USERNAME_ID);
|
||||||
}
|
}
|
||||||
|
|
||||||
const canAccessPremium = await this.stateService.getCanAccessPremium();
|
const canAccessPremium = await firstValueFrom(
|
||||||
|
this.billingAccountProfileStateService.hasPremiumFromAnySource$,
|
||||||
|
);
|
||||||
if (canAccessPremium && (!cipher || !Utils.isNullOrEmpty(cipher.login?.totp))) {
|
if (canAccessPremium && (!cipher || !Utils.isNullOrEmpty(cipher.login?.totp))) {
|
||||||
await createChildItem(COPY_VERIFICATION_CODE_ID);
|
await createChildItem(COPY_VERIFICATION_CODE_ID);
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,15 @@
|
|||||||
import AutofillOverlayButtonIframe from "./autofill-overlay-button-iframe";
|
import AutofillOverlayButtonIframe from "./autofill-overlay-button-iframe";
|
||||||
import AutofillOverlayIframeElement from "./autofill-overlay-iframe-element";
|
|
||||||
|
|
||||||
describe("AutofillOverlayButtonIframe", () => {
|
describe("AutofillOverlayButtonIframe", () => {
|
||||||
window.customElements.define("autofill-overlay-button-iframe", AutofillOverlayButtonIframe);
|
window.customElements.define(
|
||||||
|
"autofill-overlay-button-iframe",
|
||||||
|
class extends HTMLElement {
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
new AutofillOverlayButtonIframe(this);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
afterAll(() => {
|
afterAll(() => {
|
||||||
jest.clearAllMocks();
|
jest.clearAllMocks();
|
||||||
@ -13,7 +20,7 @@ describe("AutofillOverlayButtonIframe", () => {
|
|||||||
|
|
||||||
const iframe = document.querySelector("autofill-overlay-button-iframe");
|
const iframe = document.querySelector("autofill-overlay-button-iframe");
|
||||||
|
|
||||||
expect(iframe).toBeInstanceOf(AutofillOverlayButtonIframe);
|
expect(iframe).toBeInstanceOf(HTMLElement);
|
||||||
expect(iframe).toBeInstanceOf(AutofillOverlayIframeElement);
|
expect(iframe.shadowRoot).toBeDefined();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -3,8 +3,9 @@ import { AutofillOverlayPort } from "../../utils/autofill-overlay.enum";
|
|||||||
import AutofillOverlayIframeElement from "./autofill-overlay-iframe-element";
|
import AutofillOverlayIframeElement from "./autofill-overlay-iframe-element";
|
||||||
|
|
||||||
class AutofillOverlayButtonIframe extends AutofillOverlayIframeElement {
|
class AutofillOverlayButtonIframe extends AutofillOverlayIframeElement {
|
||||||
constructor() {
|
constructor(element: HTMLElement) {
|
||||||
super(
|
super(
|
||||||
|
element,
|
||||||
"overlay/button.html",
|
"overlay/button.html",
|
||||||
AutofillOverlayPort.Button,
|
AutofillOverlayPort.Button,
|
||||||
{
|
{
|
||||||
|
@ -4,7 +4,21 @@ import AutofillOverlayIframeService from "./autofill-overlay-iframe.service";
|
|||||||
jest.mock("./autofill-overlay-iframe.service");
|
jest.mock("./autofill-overlay-iframe.service");
|
||||||
|
|
||||||
describe("AutofillOverlayIframeElement", () => {
|
describe("AutofillOverlayIframeElement", () => {
|
||||||
window.customElements.define("autofill-overlay-iframe", AutofillOverlayIframeElement);
|
window.customElements.define(
|
||||||
|
"autofill-overlay-iframe",
|
||||||
|
class extends HTMLElement {
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
new AutofillOverlayIframeElement(
|
||||||
|
this,
|
||||||
|
"overlay/button.html",
|
||||||
|
"overlay/button",
|
||||||
|
{ background: "transparent", border: "none" },
|
||||||
|
"bitwardenOverlayButton",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
afterAll(() => {
|
afterAll(() => {
|
||||||
jest.clearAllMocks();
|
jest.clearAllMocks();
|
||||||
|
@ -1,16 +1,15 @@
|
|||||||
import AutofillOverlayIframeService from "./autofill-overlay-iframe.service";
|
import AutofillOverlayIframeService from "./autofill-overlay-iframe.service";
|
||||||
|
|
||||||
class AutofillOverlayIframeElement extends HTMLElement {
|
class AutofillOverlayIframeElement {
|
||||||
constructor(
|
constructor(
|
||||||
|
element: HTMLElement,
|
||||||
iframePath: string,
|
iframePath: string,
|
||||||
portName: string,
|
portName: string,
|
||||||
initStyles: Partial<CSSStyleDeclaration>,
|
initStyles: Partial<CSSStyleDeclaration>,
|
||||||
iframeTitle: string,
|
iframeTitle: string,
|
||||||
ariaAlert?: string,
|
ariaAlert?: string,
|
||||||
) {
|
) {
|
||||||
super();
|
const shadow: ShadowRoot = element.attachShadow({ mode: "closed" });
|
||||||
|
|
||||||
const shadow: ShadowRoot = this.attachShadow({ mode: "closed" });
|
|
||||||
const autofillOverlayIframeService = new AutofillOverlayIframeService(
|
const autofillOverlayIframeService = new AutofillOverlayIframeService(
|
||||||
iframePath,
|
iframePath,
|
||||||
portName,
|
portName,
|
||||||
|
@ -1,8 +1,15 @@
|
|||||||
import AutofillOverlayIframeElement from "./autofill-overlay-iframe-element";
|
|
||||||
import AutofillOverlayListIframe from "./autofill-overlay-list-iframe";
|
import AutofillOverlayListIframe from "./autofill-overlay-list-iframe";
|
||||||
|
|
||||||
describe("AutofillOverlayListIframe", () => {
|
describe("AutofillOverlayListIframe", () => {
|
||||||
window.customElements.define("autofill-overlay-list-iframe", AutofillOverlayListIframe);
|
window.customElements.define(
|
||||||
|
"autofill-overlay-list-iframe",
|
||||||
|
class extends HTMLElement {
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
new AutofillOverlayListIframe(this);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
afterAll(() => {
|
afterAll(() => {
|
||||||
jest.clearAllMocks();
|
jest.clearAllMocks();
|
||||||
@ -13,7 +20,7 @@ describe("AutofillOverlayListIframe", () => {
|
|||||||
|
|
||||||
const iframe = document.querySelector("autofill-overlay-list-iframe");
|
const iframe = document.querySelector("autofill-overlay-list-iframe");
|
||||||
|
|
||||||
expect(iframe).toBeInstanceOf(AutofillOverlayListIframe);
|
expect(iframe).toBeInstanceOf(HTMLElement);
|
||||||
expect(iframe).toBeInstanceOf(AutofillOverlayIframeElement);
|
expect(iframe.shadowRoot).toBeDefined();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -3,8 +3,9 @@ import { AutofillOverlayPort } from "../../utils/autofill-overlay.enum";
|
|||||||
import AutofillOverlayIframeElement from "./autofill-overlay-iframe-element";
|
import AutofillOverlayIframeElement from "./autofill-overlay-iframe-element";
|
||||||
|
|
||||||
class AutofillOverlayListIframe extends AutofillOverlayIframeElement {
|
class AutofillOverlayListIframe extends AutofillOverlayIframeElement {
|
||||||
constructor() {
|
constructor(element: HTMLElement) {
|
||||||
super(
|
super(
|
||||||
|
element,
|
||||||
"overlay/list.html",
|
"overlay/list.html",
|
||||||
AutofillOverlayPort.List,
|
AutofillOverlayPort.List,
|
||||||
{
|
{
|
||||||
|
@ -877,6 +877,44 @@ describe("AutofillOverlayContentService", () => {
|
|||||||
sender: "autofillOverlayContentService",
|
sender: "autofillOverlayContentService",
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("builds the overlay elements as custom web components if the user's browser is not Firefox", () => {
|
||||||
|
let namesIndex = 0;
|
||||||
|
const customNames = ["op-autofill-overlay-button", "op-autofill-overlay-list"];
|
||||||
|
|
||||||
|
jest
|
||||||
|
.spyOn(autofillOverlayContentService as any, "generateRandomCustomElementName")
|
||||||
|
.mockImplementation(() => {
|
||||||
|
if (namesIndex > 1) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
const customName = customNames[namesIndex];
|
||||||
|
namesIndex++;
|
||||||
|
|
||||||
|
return customName;
|
||||||
|
});
|
||||||
|
autofillOverlayContentService["isFirefoxBrowser"] = false;
|
||||||
|
|
||||||
|
autofillOverlayContentService.openAutofillOverlay();
|
||||||
|
|
||||||
|
expect(autofillOverlayContentService["overlayButtonElement"]).toBeInstanceOf(HTMLElement);
|
||||||
|
expect(autofillOverlayContentService["overlayButtonElement"].tagName).toEqual(
|
||||||
|
customNames[0].toUpperCase(),
|
||||||
|
);
|
||||||
|
expect(autofillOverlayContentService["overlayListElement"]).toBeInstanceOf(HTMLElement);
|
||||||
|
expect(autofillOverlayContentService["overlayListElement"].tagName).toEqual(
|
||||||
|
customNames[1].toUpperCase(),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("builds the overlay elements as `div` elements if the user's browser is Firefox", () => {
|
||||||
|
autofillOverlayContentService["isFirefoxBrowser"] = true;
|
||||||
|
|
||||||
|
autofillOverlayContentService.openAutofillOverlay();
|
||||||
|
|
||||||
|
expect(autofillOverlayContentService["overlayButtonElement"]).toBeInstanceOf(HTMLDivElement);
|
||||||
|
expect(autofillOverlayContentService["overlayListElement"]).toBeInstanceOf(HTMLDivElement);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("focusMostRecentOverlayField", () => {
|
describe("focusMostRecentOverlayField", () => {
|
||||||
|
@ -30,6 +30,10 @@ class AutofillOverlayContentService implements AutofillOverlayContentServiceInte
|
|||||||
isOverlayCiphersPopulated = false;
|
isOverlayCiphersPopulated = false;
|
||||||
pageDetailsUpdateRequired = false;
|
pageDetailsUpdateRequired = false;
|
||||||
autofillOverlayVisibility: number;
|
autofillOverlayVisibility: number;
|
||||||
|
private isFirefoxBrowser =
|
||||||
|
globalThis.navigator.userAgent.indexOf(" Firefox/") !== -1 ||
|
||||||
|
globalThis.navigator.userAgent.indexOf(" Gecko/") !== -1;
|
||||||
|
private readonly generateRandomCustomElementName = generateRandomCustomElementName;
|
||||||
private readonly findTabs = tabbable;
|
private readonly findTabs = tabbable;
|
||||||
private readonly sendExtensionMessage = sendExtensionMessage;
|
private readonly sendExtensionMessage = sendExtensionMessage;
|
||||||
private formFieldElements: Set<ElementWithOpId<FormFieldElement>> = new Set([]);
|
private formFieldElements: Set<ElementWithOpId<FormFieldElement>> = new Set([]);
|
||||||
@ -593,6 +597,7 @@ class AutofillOverlayContentService implements AutofillOverlayContentServiceInte
|
|||||||
private updateOverlayButtonPosition() {
|
private updateOverlayButtonPosition() {
|
||||||
if (!this.overlayButtonElement) {
|
if (!this.overlayButtonElement) {
|
||||||
this.createAutofillOverlayButton();
|
this.createAutofillOverlayButton();
|
||||||
|
this.updateCustomElementDefaultStyles(this.overlayButtonElement);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!this.isOverlayButtonVisible) {
|
if (!this.isOverlayButtonVisible) {
|
||||||
@ -613,6 +618,7 @@ class AutofillOverlayContentService implements AutofillOverlayContentServiceInte
|
|||||||
private updateOverlayListPosition() {
|
private updateOverlayListPosition() {
|
||||||
if (!this.overlayListElement) {
|
if (!this.overlayListElement) {
|
||||||
this.createAutofillOverlayList();
|
this.createAutofillOverlayList();
|
||||||
|
this.updateCustomElementDefaultStyles(this.overlayListElement);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!this.isOverlayListVisible) {
|
if (!this.isOverlayListVisible) {
|
||||||
@ -765,11 +771,24 @@ class AutofillOverlayContentService implements AutofillOverlayContentServiceInte
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const customElementName = generateRandomCustomElementName();
|
if (this.isFirefoxBrowser) {
|
||||||
globalThis.customElements?.define(customElementName, AutofillOverlayButtonIframe);
|
this.overlayButtonElement = globalThis.document.createElement("div");
|
||||||
this.overlayButtonElement = globalThis.document.createElement(customElementName);
|
new AutofillOverlayButtonIframe(this.overlayButtonElement);
|
||||||
|
|
||||||
this.updateCustomElementDefaultStyles(this.overlayButtonElement);
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const customElementName = this.generateRandomCustomElementName();
|
||||||
|
globalThis.customElements?.define(
|
||||||
|
customElementName,
|
||||||
|
class extends HTMLElement {
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
new AutofillOverlayButtonIframe(this);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
|
this.overlayButtonElement = globalThis.document.createElement(customElementName);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -781,11 +800,24 @@ class AutofillOverlayContentService implements AutofillOverlayContentServiceInte
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const customElementName = generateRandomCustomElementName();
|
if (this.isFirefoxBrowser) {
|
||||||
globalThis.customElements?.define(customElementName, AutofillOverlayListIframe);
|
this.overlayListElement = globalThis.document.createElement("div");
|
||||||
this.overlayListElement = globalThis.document.createElement(customElementName);
|
new AutofillOverlayListIframe(this.overlayListElement);
|
||||||
|
|
||||||
this.updateCustomElementDefaultStyles(this.overlayListElement);
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const customElementName = this.generateRandomCustomElementName();
|
||||||
|
globalThis.customElements?.define(
|
||||||
|
customElementName,
|
||||||
|
class extends HTMLElement {
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
new AutofillOverlayListIframe(this);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
|
this.overlayListElement = globalThis.document.createElement(customElementName);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -8,6 +8,7 @@ import {
|
|||||||
DefaultDomainSettingsService,
|
DefaultDomainSettingsService,
|
||||||
DomainSettingsService,
|
DomainSettingsService,
|
||||||
} from "@bitwarden/common/autofill/services/domain-settings.service";
|
} from "@bitwarden/common/autofill/services/domain-settings.service";
|
||||||
|
import { BillingAccountProfileStateService } from "@bitwarden/common/billing/abstractions/account/billing-account-profile-state.service";
|
||||||
import { EventType } from "@bitwarden/common/enums";
|
import { EventType } from "@bitwarden/common/enums";
|
||||||
import { UriMatchStrategy } from "@bitwarden/common/models/domain/domain-service";
|
import { UriMatchStrategy } from "@bitwarden/common/models/domain/domain-service";
|
||||||
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
|
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
|
||||||
@ -72,6 +73,7 @@ describe("AutofillService", () => {
|
|||||||
const eventCollectionService = mock<EventCollectionService>();
|
const eventCollectionService = mock<EventCollectionService>();
|
||||||
const logService = mock<LogService>();
|
const logService = mock<LogService>();
|
||||||
const userVerificationService = mock<UserVerificationService>();
|
const userVerificationService = mock<UserVerificationService>();
|
||||||
|
const billingAccountProfileStateService = mock<BillingAccountProfileStateService>();
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
autofillService = new AutofillService(
|
autofillService = new AutofillService(
|
||||||
@ -83,6 +85,7 @@ describe("AutofillService", () => {
|
|||||||
logService,
|
logService,
|
||||||
domainSettingsService,
|
domainSettingsService,
|
||||||
userVerificationService,
|
userVerificationService,
|
||||||
|
billingAccountProfileStateService,
|
||||||
);
|
);
|
||||||
|
|
||||||
domainSettingsService = new DefaultDomainSettingsService(fakeStateProvider);
|
domainSettingsService = new DefaultDomainSettingsService(fakeStateProvider);
|
||||||
@ -476,6 +479,7 @@ describe("AutofillService", () => {
|
|||||||
|
|
||||||
it("throws an error if an autofill did not occur for any of the passed pages", async () => {
|
it("throws an error if an autofill did not occur for any of the passed pages", async () => {
|
||||||
autofillOptions.tab.url = "https://a-different-url.com";
|
autofillOptions.tab.url = "https://a-different-url.com";
|
||||||
|
billingAccountProfileStateService.hasPremiumFromAnySource$ = of(true);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await autofillService.doAutoFill(autofillOptions);
|
await autofillService.doAutoFill(autofillOptions);
|
||||||
@ -487,7 +491,6 @@ describe("AutofillService", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("will autofill login data for a page", async () => {
|
it("will autofill login data for a page", async () => {
|
||||||
jest.spyOn(stateService, "getCanAccessPremium");
|
|
||||||
jest.spyOn(autofillService as any, "generateFillScript");
|
jest.spyOn(autofillService as any, "generateFillScript");
|
||||||
jest.spyOn(autofillService as any, "generateLoginFillScript");
|
jest.spyOn(autofillService as any, "generateLoginFillScript");
|
||||||
jest.spyOn(logService, "info");
|
jest.spyOn(logService, "info");
|
||||||
@ -497,8 +500,6 @@ describe("AutofillService", () => {
|
|||||||
const autofillResult = await autofillService.doAutoFill(autofillOptions);
|
const autofillResult = await autofillService.doAutoFill(autofillOptions);
|
||||||
|
|
||||||
const currentAutofillPageDetails = autofillOptions.pageDetails[0];
|
const currentAutofillPageDetails = autofillOptions.pageDetails[0];
|
||||||
expect(stateService.getCanAccessPremium).toHaveBeenCalled();
|
|
||||||
expect(autofillService["getDefaultUriMatchStrategy"]).toHaveBeenCalled();
|
|
||||||
expect(autofillService["generateFillScript"]).toHaveBeenCalledWith(
|
expect(autofillService["generateFillScript"]).toHaveBeenCalledWith(
|
||||||
currentAutofillPageDetails.details,
|
currentAutofillPageDetails.details,
|
||||||
{
|
{
|
||||||
@ -660,7 +661,7 @@ describe("AutofillService", () => {
|
|||||||
it("returns a TOTP value", async () => {
|
it("returns a TOTP value", async () => {
|
||||||
const totpCode = "123456";
|
const totpCode = "123456";
|
||||||
autofillOptions.cipher.login.totp = "totp";
|
autofillOptions.cipher.login.totp = "totp";
|
||||||
jest.spyOn(stateService, "getCanAccessPremium").mockResolvedValue(true);
|
billingAccountProfileStateService.hasPremiumFromAnySource$ = of(true);
|
||||||
jest.spyOn(autofillService, "getShouldAutoCopyTotp").mockResolvedValue(true);
|
jest.spyOn(autofillService, "getShouldAutoCopyTotp").mockResolvedValue(true);
|
||||||
jest.spyOn(totpService, "getCode").mockResolvedValue(totpCode);
|
jest.spyOn(totpService, "getCode").mockResolvedValue(totpCode);
|
||||||
|
|
||||||
@ -673,7 +674,7 @@ describe("AutofillService", () => {
|
|||||||
|
|
||||||
it("does not return a TOTP value if the user does not have premium features", async () => {
|
it("does not return a TOTP value if the user does not have premium features", async () => {
|
||||||
autofillOptions.cipher.login.totp = "totp";
|
autofillOptions.cipher.login.totp = "totp";
|
||||||
jest.spyOn(stateService, "getCanAccessPremium").mockResolvedValue(false);
|
billingAccountProfileStateService.hasPremiumFromAnySource$ = of(false);
|
||||||
jest.spyOn(autofillService, "getShouldAutoCopyTotp").mockResolvedValue(true);
|
jest.spyOn(autofillService, "getShouldAutoCopyTotp").mockResolvedValue(true);
|
||||||
|
|
||||||
const autofillResult = await autofillService.doAutoFill(autofillOptions);
|
const autofillResult = await autofillService.doAutoFill(autofillOptions);
|
||||||
@ -707,7 +708,7 @@ describe("AutofillService", () => {
|
|||||||
it("returns a null value if the user cannot access premium and the organization does not use TOTP", async () => {
|
it("returns a null value if the user cannot access premium and the organization does not use TOTP", async () => {
|
||||||
autofillOptions.cipher.login.totp = "totp";
|
autofillOptions.cipher.login.totp = "totp";
|
||||||
autofillOptions.cipher.organizationUseTotp = false;
|
autofillOptions.cipher.organizationUseTotp = false;
|
||||||
jest.spyOn(stateService, "getCanAccessPremium").mockResolvedValueOnce(false);
|
billingAccountProfileStateService.hasPremiumFromAnySource$ = of(false);
|
||||||
|
|
||||||
const autofillResult = await autofillService.doAutoFill(autofillOptions);
|
const autofillResult = await autofillService.doAutoFill(autofillOptions);
|
||||||
|
|
||||||
@ -717,13 +718,12 @@ describe("AutofillService", () => {
|
|||||||
it("returns a null value if the user has disabled `auto TOTP copy`", async () => {
|
it("returns a null value if the user has disabled `auto TOTP copy`", async () => {
|
||||||
autofillOptions.cipher.login.totp = "totp";
|
autofillOptions.cipher.login.totp = "totp";
|
||||||
autofillOptions.cipher.organizationUseTotp = true;
|
autofillOptions.cipher.organizationUseTotp = true;
|
||||||
jest.spyOn(stateService, "getCanAccessPremium").mockResolvedValue(true);
|
billingAccountProfileStateService.hasPremiumFromAnySource$ = of(true);
|
||||||
jest.spyOn(autofillService, "getShouldAutoCopyTotp").mockResolvedValue(false);
|
jest.spyOn(autofillService, "getShouldAutoCopyTotp").mockResolvedValue(false);
|
||||||
jest.spyOn(totpService, "getCode");
|
jest.spyOn(totpService, "getCode");
|
||||||
|
|
||||||
const autofillResult = await autofillService.doAutoFill(autofillOptions);
|
const autofillResult = await autofillService.doAutoFill(autofillOptions);
|
||||||
|
|
||||||
expect(stateService.getCanAccessPremium).toHaveBeenCalled();
|
|
||||||
expect(autofillService.getShouldAutoCopyTotp).toHaveBeenCalled();
|
expect(autofillService.getShouldAutoCopyTotp).toHaveBeenCalled();
|
||||||
expect(totpService.getCode).not.toHaveBeenCalled();
|
expect(totpService.getCode).not.toHaveBeenCalled();
|
||||||
expect(autofillResult).toBeNull();
|
expect(autofillResult).toBeNull();
|
||||||
@ -3380,6 +3380,34 @@ describe("AutofillService", () => {
|
|||||||
|
|
||||||
expect(value).toBe(false);
|
expect(value).toBe(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("validates attribute identifiers with mixed camel case and non-alpha characters", () => {
|
||||||
|
const attributes: Record<string, boolean> = {
|
||||||
|
_$1_go_look: true,
|
||||||
|
go_look: true,
|
||||||
|
goLook: true,
|
||||||
|
go1look: true,
|
||||||
|
"go look": true,
|
||||||
|
look_go: true,
|
||||||
|
findPerson: true,
|
||||||
|
query$1: true,
|
||||||
|
look_goo: false,
|
||||||
|
golook: false,
|
||||||
|
lookgo: false,
|
||||||
|
logonField: false,
|
||||||
|
ego_input: false,
|
||||||
|
"Gold Password": false,
|
||||||
|
searching_for: false,
|
||||||
|
person_finder: false,
|
||||||
|
};
|
||||||
|
const autofillFieldMocks = Object.keys(attributes).map((key) =>
|
||||||
|
createAutofillFieldMock({ htmlID: key }),
|
||||||
|
);
|
||||||
|
autofillFieldMocks.forEach((field) => {
|
||||||
|
const value = AutofillService["isSearchField"](field);
|
||||||
|
expect(value).toBe(attributes[field.htmlID]);
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("isFieldMatch", () => {
|
describe("isFieldMatch", () => {
|
||||||
|
@ -5,6 +5,7 @@ import { UserVerificationService } from "@bitwarden/common/auth/abstractions/use
|
|||||||
import { AutofillSettingsServiceAbstraction } from "@bitwarden/common/autofill/services/autofill-settings.service";
|
import { AutofillSettingsServiceAbstraction } from "@bitwarden/common/autofill/services/autofill-settings.service";
|
||||||
import { DomainSettingsService } from "@bitwarden/common/autofill/services/domain-settings.service";
|
import { DomainSettingsService } from "@bitwarden/common/autofill/services/domain-settings.service";
|
||||||
import { InlineMenuVisibilitySetting } from "@bitwarden/common/autofill/types";
|
import { InlineMenuVisibilitySetting } from "@bitwarden/common/autofill/types";
|
||||||
|
import { BillingAccountProfileStateService } from "@bitwarden/common/billing/abstractions/account/billing-account-profile-state.service";
|
||||||
import { EventType } from "@bitwarden/common/enums";
|
import { EventType } from "@bitwarden/common/enums";
|
||||||
import {
|
import {
|
||||||
UriMatchStrategySetting,
|
UriMatchStrategySetting,
|
||||||
@ -44,6 +45,7 @@ export default class AutofillService implements AutofillServiceInterface {
|
|||||||
private openPasswordRepromptPopoutDebounce: NodeJS.Timeout;
|
private openPasswordRepromptPopoutDebounce: NodeJS.Timeout;
|
||||||
private currentlyOpeningPasswordRepromptPopout = false;
|
private currentlyOpeningPasswordRepromptPopout = false;
|
||||||
private autofillScriptPortsSet = new Set<chrome.runtime.Port>();
|
private autofillScriptPortsSet = new Set<chrome.runtime.Port>();
|
||||||
|
static searchFieldNamesSet = new Set(AutoFillConstants.SearchFieldNames);
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private cipherService: CipherService,
|
private cipherService: CipherService,
|
||||||
@ -54,6 +56,7 @@ export default class AutofillService implements AutofillServiceInterface {
|
|||||||
private logService: LogService,
|
private logService: LogService,
|
||||||
private domainSettingsService: DomainSettingsService,
|
private domainSettingsService: DomainSettingsService,
|
||||||
private userVerificationService: UserVerificationService,
|
private userVerificationService: UserVerificationService,
|
||||||
|
private billingAccountProfileStateService: BillingAccountProfileStateService,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -239,7 +242,9 @@ export default class AutofillService implements AutofillServiceInterface {
|
|||||||
|
|
||||||
let totp: string | null = null;
|
let totp: string | null = null;
|
||||||
|
|
||||||
const canAccessPremium = await this.stateService.getCanAccessPremium();
|
const canAccessPremium = await firstValueFrom(
|
||||||
|
this.billingAccountProfileStateService.hasPremiumFromAnySource$,
|
||||||
|
);
|
||||||
const defaultUriMatch = await this.getDefaultUriMatchStrategy();
|
const defaultUriMatch = await this.getDefaultUriMatchStrategy();
|
||||||
|
|
||||||
if (!canAccessPremium) {
|
if (!canAccessPremium) {
|
||||||
@ -1380,11 +1385,33 @@ export default class AutofillService implements AutofillServiceInterface {
|
|||||||
return excludedTypes.indexOf(type) > -1;
|
return excludedTypes.indexOf(type) > -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Identifies if a passed field contains text artifacts that identify it as a search field.
|
||||||
|
*
|
||||||
|
* @param field - The autofill field that we are validating as a search field
|
||||||
|
*/
|
||||||
private static isSearchField(field: AutofillField) {
|
private static isSearchField(field: AutofillField) {
|
||||||
const matchFieldAttributeValues = [field.type, field.htmlName, field.htmlID, field.placeholder];
|
const matchFieldAttributeValues = [field.type, field.htmlName, field.htmlID, field.placeholder];
|
||||||
const matchPattern = new RegExp(AutoFillConstants.SearchFieldNames.join("|"), "gi");
|
for (let attrIndex = 0; attrIndex < matchFieldAttributeValues.length; attrIndex++) {
|
||||||
|
if (!matchFieldAttributeValues[attrIndex]) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
return Boolean(matchFieldAttributeValues.join(" ").match(matchPattern));
|
// Separate camel case words and case them to lower case values
|
||||||
|
const camelCaseSeparatedFieldAttribute = matchFieldAttributeValues[attrIndex]
|
||||||
|
.replace(/([a-z])([A-Z])/g, "$1 $2")
|
||||||
|
.toLowerCase();
|
||||||
|
// Split the attribute by non-alphabetical characters to get the keywords
|
||||||
|
const attributeKeywords = camelCaseSeparatedFieldAttribute.split(/[^a-z]/gi);
|
||||||
|
|
||||||
|
for (let keywordIndex = 0; keywordIndex < attributeKeywords.length; keywordIndex++) {
|
||||||
|
if (AutofillService.searchFieldNamesSet.has(attributeKeywords[keywordIndex])) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static isExcludedFieldType(field: AutofillField, excludedTypes: string[]) {
|
static isExcludedFieldType(field: AutofillField, excludedTypes: string[]) {
|
||||||
@ -1397,11 +1424,7 @@ export default class AutofillService implements AutofillServiceInterface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Check if the input is an untyped/mistyped search input
|
// Check if the input is an untyped/mistyped search input
|
||||||
if (this.isSearchField(field)) {
|
return this.isSearchField(field);
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1525,11 +1548,7 @@ export default class AutofillService implements AutofillServiceInterface {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (AutoFillConstants.PasswordFieldExcludeList.some((i) => cleanedValue.indexOf(i) > -1)) {
|
return !AutoFillConstants.PasswordFieldExcludeList.some((i) => cleanedValue.indexOf(i) > -1);
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static fieldHasDisqualifyingAttributeValue(field: AutofillField) {
|
static fieldHasDisqualifyingAttributeValue(field: AutofillField) {
|
||||||
@ -1572,7 +1591,11 @@ export default class AutofillService implements AutofillServiceInterface {
|
|||||||
const arr: AutofillField[] = [];
|
const arr: AutofillField[] = [];
|
||||||
|
|
||||||
pageDetails.fields.forEach((f) => {
|
pageDetails.fields.forEach((f) => {
|
||||||
if (AutofillService.isExcludedFieldType(f, AutoFillConstants.ExcludedAutofillLoginTypes)) {
|
const isPassword = f.type === "password";
|
||||||
|
if (
|
||||||
|
!isPassword &&
|
||||||
|
AutofillService.isExcludedFieldType(f, AutoFillConstants.ExcludedAutofillLoginTypes)
|
||||||
|
) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1581,23 +1604,16 @@ export default class AutofillService implements AutofillServiceInterface {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const isPassword = f.type === "password";
|
|
||||||
|
|
||||||
const isLikePassword = () => {
|
const isLikePassword = () => {
|
||||||
if (f.type !== "text") {
|
if (f.type !== "text") {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (AutofillService.valueIsLikePassword(f.htmlID)) {
|
const testedValues = [f.htmlID, f.htmlName, f.placeholder];
|
||||||
|
for (let i = 0; i < testedValues.length; i++) {
|
||||||
|
if (AutofillService.valueIsLikePassword(testedValues[i])) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (AutofillService.valueIsLikePassword(f.htmlName)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (AutofillService.valueIsLikePassword(f.placeholder)) {
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
@ -755,6 +755,9 @@ class CollectAutofillContentService implements CollectAutofillContentServiceInte
|
|||||||
|
|
||||||
// Prioritize capturing text content from elements rather than nodes.
|
// Prioritize capturing text content from elements rather than nodes.
|
||||||
currentElement = currentElement.parentElement || currentElement.parentNode;
|
currentElement = currentElement.parentElement || currentElement.parentNode;
|
||||||
|
if (!currentElement) {
|
||||||
|
return textContentItems;
|
||||||
|
}
|
||||||
|
|
||||||
let siblingElement = nodeIsElement(currentElement)
|
let siblingElement = nodeIsElement(currentElement)
|
||||||
? currentElement.previousElementSibling
|
? currentElement.previousElementSibling
|
||||||
|
@ -553,17 +553,30 @@ describe("InsertAutofillContentService", () => {
|
|||||||
insertAutofillContentService as any,
|
insertAutofillContentService as any,
|
||||||
"simulateUserMouseClickAndFocusEventInteractions",
|
"simulateUserMouseClickAndFocusEventInteractions",
|
||||||
);
|
);
|
||||||
|
jest.spyOn(targetInput, "blur");
|
||||||
|
|
||||||
insertAutofillContentService["handleFocusOnFieldByOpidAction"]("__0");
|
insertAutofillContentService["handleFocusOnFieldByOpidAction"]("__0");
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
insertAutofillContentService["collectAutofillContentService"].getAutofillFieldElementByOpid,
|
insertAutofillContentService["collectAutofillContentService"].getAutofillFieldElementByOpid,
|
||||||
).toBeCalledWith("__0");
|
).toBeCalledWith("__0");
|
||||||
|
expect(targetInput.blur).not.toHaveBeenCalled();
|
||||||
expect(
|
expect(
|
||||||
insertAutofillContentService["simulateUserMouseClickAndFocusEventInteractions"],
|
insertAutofillContentService["simulateUserMouseClickAndFocusEventInteractions"],
|
||||||
).toHaveBeenCalledWith(targetInput, true);
|
).toHaveBeenCalledWith(targetInput, true);
|
||||||
expect(elementEventCount).toEqual(expectedElementEventCount);
|
expect(elementEventCount).toEqual(expectedElementEventCount);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("blurs the element if it is currently the active element before simulating click and focus events", () => {
|
||||||
|
const targetInput = document.querySelector('input[type="text"]') as FormElementWithAttribute;
|
||||||
|
targetInput.opid = "__0";
|
||||||
|
targetInput.focus();
|
||||||
|
jest.spyOn(targetInput, "blur");
|
||||||
|
|
||||||
|
insertAutofillContentService["handleFocusOnFieldByOpidAction"]("__0");
|
||||||
|
|
||||||
|
expect(targetInput.blur).toHaveBeenCalled();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("insertValueIntoField", () => {
|
describe("insertValueIntoField", () => {
|
||||||
@ -710,7 +723,7 @@ describe("InsertAutofillContentService", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
describe("triggerPostInsertEventsOnElement", () => {
|
describe("triggerPostInsertEventsOnElement", () => {
|
||||||
it("triggers simulated event interactions and blurs the element after", () => {
|
it("triggers simulated event interactions", () => {
|
||||||
const elementValue = "test";
|
const elementValue = "test";
|
||||||
document.body.innerHTML = `<input type="text" id="username" value="${elementValue}"/>`;
|
document.body.innerHTML = `<input type="text" id="username" value="${elementValue}"/>`;
|
||||||
const element = document.getElementById("username") as FillableFormFieldElement;
|
const element = document.getElementById("username") as FillableFormFieldElement;
|
||||||
@ -726,7 +739,6 @@ describe("InsertAutofillContentService", () => {
|
|||||||
expect(insertAutofillContentService["simulateInputElementChangedEvent"]).toHaveBeenCalledWith(
|
expect(insertAutofillContentService["simulateInputElementChangedEvent"]).toHaveBeenCalledWith(
|
||||||
element,
|
element,
|
||||||
);
|
);
|
||||||
expect(element.blur).toHaveBeenCalled();
|
|
||||||
expect(element.value).toBe(elementValue);
|
expect(element.value).toBe(elementValue);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -185,11 +185,18 @@ class InsertAutofillContentService implements InsertAutofillContentServiceInterf
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles finding an element by opid and triggering click and focus events on the element.
|
* Handles finding an element by opid and triggering click and focus events on the element.
|
||||||
* @param {string} opid
|
* To ensure that we trigger a blur event correctly on a filled field, we first check if the
|
||||||
* @private
|
* element is already focused. If it is, we blur the element before focusing on it again.
|
||||||
|
*
|
||||||
|
* @param {string} opid - The opid of the element to focus on.
|
||||||
*/
|
*/
|
||||||
private handleFocusOnFieldByOpidAction(opid: string) {
|
private handleFocusOnFieldByOpidAction(opid: string) {
|
||||||
const element = this.collectAutofillContentService.getAutofillFieldElementByOpid(opid);
|
const element = this.collectAutofillContentService.getAutofillFieldElementByOpid(opid);
|
||||||
|
|
||||||
|
if (document.activeElement === element) {
|
||||||
|
element.blur();
|
||||||
|
}
|
||||||
|
|
||||||
this.simulateUserMouseClickAndFocusEventInteractions(element, true);
|
this.simulateUserMouseClickAndFocusEventInteractions(element, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -282,7 +289,6 @@ class InsertAutofillContentService implements InsertAutofillContentServiceInterf
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.simulateInputElementChangedEvent(element);
|
this.simulateInputElementChangedEvent(element);
|
||||||
element.blur();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -379,10 +385,6 @@ class InsertAutofillContentService implements InsertAutofillContentServiceInterf
|
|||||||
element.dispatchEvent(new Event(simulatedInputEvents[index], { bubbles: true }));
|
element.dispatchEvent(new Event(simulatedInputEvents[index], { bubbles: true }));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private nodeIsElement(node: Node): node is HTMLElement {
|
|
||||||
return node.nodeType === Node.ELEMENT_NODE;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default InsertAutofillContentService;
|
export default InsertAutofillContentService;
|
||||||
|
@ -8,19 +8,18 @@ import {
|
|||||||
AuthRequestServiceAbstraction,
|
AuthRequestServiceAbstraction,
|
||||||
AuthRequestService,
|
AuthRequestService,
|
||||||
} from "@bitwarden/auth/common";
|
} from "@bitwarden/auth/common";
|
||||||
import { AvatarUpdateService as AvatarUpdateServiceAbstraction } from "@bitwarden/common/abstractions/account/avatar-update.service";
|
|
||||||
import { ApiService as ApiServiceAbstraction } from "@bitwarden/common/abstractions/api.service";
|
import { ApiService as ApiServiceAbstraction } from "@bitwarden/common/abstractions/api.service";
|
||||||
import { AuditService as AuditServiceAbstraction } from "@bitwarden/common/abstractions/audit.service";
|
import { AuditService as AuditServiceAbstraction } from "@bitwarden/common/abstractions/audit.service";
|
||||||
import { EventCollectionService as EventCollectionServiceAbstraction } from "@bitwarden/common/abstractions/event/event-collection.service";
|
import { EventCollectionService as EventCollectionServiceAbstraction } from "@bitwarden/common/abstractions/event/event-collection.service";
|
||||||
import { EventUploadService as EventUploadServiceAbstraction } from "@bitwarden/common/abstractions/event/event-upload.service";
|
import { EventUploadService as EventUploadServiceAbstraction } from "@bitwarden/common/abstractions/event/event-upload.service";
|
||||||
import { NotificationsService as NotificationsServiceAbstraction } from "@bitwarden/common/abstractions/notifications.service";
|
import { NotificationsService as NotificationsServiceAbstraction } from "@bitwarden/common/abstractions/notifications.service";
|
||||||
import { SearchService as SearchServiceAbstraction } from "@bitwarden/common/abstractions/search.service";
|
import { SearchService as SearchServiceAbstraction } from "@bitwarden/common/abstractions/search.service";
|
||||||
import { SettingsService as SettingsServiceAbstraction } from "@bitwarden/common/abstractions/settings.service";
|
|
||||||
import { VaultTimeoutSettingsService as VaultTimeoutSettingsServiceAbstraction } from "@bitwarden/common/abstractions/vault-timeout/vault-timeout-settings.service";
|
import { VaultTimeoutSettingsService as VaultTimeoutSettingsServiceAbstraction } from "@bitwarden/common/abstractions/vault-timeout/vault-timeout-settings.service";
|
||||||
import { InternalOrganizationServiceAbstraction } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
import { InternalOrganizationServiceAbstraction } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
||||||
import { PolicyApiServiceAbstraction } from "@bitwarden/common/admin-console/abstractions/policy/policy-api.service.abstraction";
|
import { PolicyApiServiceAbstraction } from "@bitwarden/common/admin-console/abstractions/policy/policy-api.service.abstraction";
|
||||||
import { InternalPolicyService as InternalPolicyServiceAbstraction } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction";
|
import { InternalPolicyService as InternalPolicyServiceAbstraction } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction";
|
||||||
import { ProviderService as ProviderServiceAbstraction } from "@bitwarden/common/admin-console/abstractions/provider.service";
|
import { ProviderService as ProviderServiceAbstraction } from "@bitwarden/common/admin-console/abstractions/provider.service";
|
||||||
|
import { OrganizationService } from "@bitwarden/common/admin-console/services/organization/organization.service";
|
||||||
import { PolicyApiService } from "@bitwarden/common/admin-console/services/policy/policy-api.service";
|
import { PolicyApiService } from "@bitwarden/common/admin-console/services/policy/policy-api.service";
|
||||||
import { PolicyService } from "@bitwarden/common/admin-console/services/policy/policy.service";
|
import { PolicyService } from "@bitwarden/common/admin-console/services/policy/policy.service";
|
||||||
import { ProviderService } from "@bitwarden/common/admin-console/services/provider.service";
|
import { ProviderService } from "@bitwarden/common/admin-console/services/provider.service";
|
||||||
@ -39,6 +38,7 @@ import { AuthenticationStatus } from "@bitwarden/common/auth/enums/authenticatio
|
|||||||
import { ForceSetPasswordReason } from "@bitwarden/common/auth/models/domain/force-set-password-reason";
|
import { ForceSetPasswordReason } from "@bitwarden/common/auth/models/domain/force-set-password-reason";
|
||||||
import { AccountServiceImplementation } from "@bitwarden/common/auth/services/account.service";
|
import { AccountServiceImplementation } from "@bitwarden/common/auth/services/account.service";
|
||||||
import { AuthService } from "@bitwarden/common/auth/services/auth.service";
|
import { AuthService } from "@bitwarden/common/auth/services/auth.service";
|
||||||
|
import { AvatarService } from "@bitwarden/common/auth/services/avatar.service";
|
||||||
import { DeviceTrustCryptoService } from "@bitwarden/common/auth/services/device-trust-crypto.service.implementation";
|
import { DeviceTrustCryptoService } from "@bitwarden/common/auth/services/device-trust-crypto.service.implementation";
|
||||||
import { DevicesServiceImplementation } from "@bitwarden/common/auth/services/devices/devices.service.implementation";
|
import { DevicesServiceImplementation } from "@bitwarden/common/auth/services/devices/devices.service.implementation";
|
||||||
import { DevicesApiServiceImplementation } from "@bitwarden/common/auth/services/devices-api.service.implementation";
|
import { DevicesApiServiceImplementation } from "@bitwarden/common/auth/services/devices-api.service.implementation";
|
||||||
@ -64,6 +64,8 @@ import {
|
|||||||
UserNotificationSettingsService,
|
UserNotificationSettingsService,
|
||||||
UserNotificationSettingsServiceAbstraction,
|
UserNotificationSettingsServiceAbstraction,
|
||||||
} from "@bitwarden/common/autofill/services/user-notification-settings.service";
|
} from "@bitwarden/common/autofill/services/user-notification-settings.service";
|
||||||
|
import { BillingAccountProfileStateService } from "@bitwarden/common/billing/abstractions/account/billing-account-profile-state.service";
|
||||||
|
import { DefaultBillingAccountProfileStateService } from "@bitwarden/common/billing/services/account/billing-account-profile-state.service";
|
||||||
import { AppIdService as AppIdServiceAbstraction } from "@bitwarden/common/platform/abstractions/app-id.service";
|
import { AppIdService as AppIdServiceAbstraction } from "@bitwarden/common/platform/abstractions/app-id.service";
|
||||||
import { ConfigApiServiceAbstraction } from "@bitwarden/common/platform/abstractions/config/config-api.service.abstraction";
|
import { ConfigApiServiceAbstraction } from "@bitwarden/common/platform/abstractions/config/config-api.service.abstraction";
|
||||||
import { CryptoFunctionService as CryptoFunctionServiceAbstraction } from "@bitwarden/common/platform/abstractions/crypto-function.service";
|
import { CryptoFunctionService as CryptoFunctionServiceAbstraction } from "@bitwarden/common/platform/abstractions/crypto-function.service";
|
||||||
@ -117,7 +119,6 @@ import { DefaultStateProvider } from "@bitwarden/common/platform/state/implement
|
|||||||
import { StateEventRegistrarService } from "@bitwarden/common/platform/state/state-event-registrar.service";
|
import { StateEventRegistrarService } from "@bitwarden/common/platform/state/state-event-registrar.service";
|
||||||
/* eslint-enable import/no-restricted-paths */
|
/* eslint-enable import/no-restricted-paths */
|
||||||
import { DefaultThemeStateService } from "@bitwarden/common/platform/theming/theme-state.service";
|
import { DefaultThemeStateService } from "@bitwarden/common/platform/theming/theme-state.service";
|
||||||
import { AvatarUpdateService } from "@bitwarden/common/services/account/avatar-update.service";
|
|
||||||
import { ApiService } from "@bitwarden/common/services/api.service";
|
import { ApiService } from "@bitwarden/common/services/api.service";
|
||||||
import { AuditService } from "@bitwarden/common/services/audit.service";
|
import { AuditService } from "@bitwarden/common/services/audit.service";
|
||||||
import { EventCollectionService } from "@bitwarden/common/services/event/event-collection.service";
|
import { EventCollectionService } from "@bitwarden/common/services/event/event-collection.service";
|
||||||
@ -125,6 +126,7 @@ import { EventUploadService } from "@bitwarden/common/services/event/event-uploa
|
|||||||
import { NotificationsService } from "@bitwarden/common/services/notifications.service";
|
import { NotificationsService } from "@bitwarden/common/services/notifications.service";
|
||||||
import { SearchService } from "@bitwarden/common/services/search.service";
|
import { SearchService } from "@bitwarden/common/services/search.service";
|
||||||
import { VaultTimeoutSettingsService } from "@bitwarden/common/services/vault-timeout/vault-timeout-settings.service";
|
import { VaultTimeoutSettingsService } from "@bitwarden/common/services/vault-timeout/vault-timeout-settings.service";
|
||||||
|
import { AvatarService as AvatarServiceAbstraction } from "@bitwarden/common/src/auth/abstractions/avatar.service";
|
||||||
import {
|
import {
|
||||||
PasswordGenerationService,
|
PasswordGenerationService,
|
||||||
PasswordGenerationServiceAbstraction,
|
PasswordGenerationServiceAbstraction,
|
||||||
@ -180,7 +182,6 @@ import {
|
|||||||
VaultExportServiceAbstraction,
|
VaultExportServiceAbstraction,
|
||||||
} from "@bitwarden/vault-export-core";
|
} from "@bitwarden/vault-export-core";
|
||||||
|
|
||||||
import { BrowserOrganizationService } from "../admin-console/services/browser-organization.service";
|
|
||||||
import ContextMenusBackground from "../autofill/background/context-menus.background";
|
import ContextMenusBackground from "../autofill/background/context-menus.background";
|
||||||
import NotificationBackground from "../autofill/background/notification.background";
|
import NotificationBackground from "../autofill/background/notification.background";
|
||||||
import OverlayBackground from "../autofill/background/overlay.background";
|
import OverlayBackground from "../autofill/background/overlay.background";
|
||||||
@ -211,7 +212,6 @@ import { BrowserPlatformUtilsService } from "../platform/services/platform-utils
|
|||||||
import { BackgroundDerivedStateProvider } from "../platform/state/background-derived-state.provider";
|
import { BackgroundDerivedStateProvider } from "../platform/state/background-derived-state.provider";
|
||||||
import { BackgroundMemoryStorageService } from "../platform/storage/background-memory-storage.service";
|
import { BackgroundMemoryStorageService } from "../platform/storage/background-memory-storage.service";
|
||||||
import { BrowserSendService } from "../services/browser-send.service";
|
import { BrowserSendService } from "../services/browser-send.service";
|
||||||
import { BrowserSettingsService } from "../services/browser-settings.service";
|
|
||||||
import VaultTimeoutService from "../services/vault-timeout/vault-timeout.service";
|
import VaultTimeoutService from "../services/vault-timeout/vault-timeout.service";
|
||||||
import FilelessImporterBackground from "../tools/background/fileless-importer.background";
|
import FilelessImporterBackground from "../tools/background/fileless-importer.background";
|
||||||
import { BrowserFido2UserInterfaceService } from "../vault/fido2/browser-fido2-user-interface.service";
|
import { BrowserFido2UserInterfaceService } from "../vault/fido2/browser-fido2-user-interface.service";
|
||||||
@ -240,7 +240,6 @@ export default class MainBackground {
|
|||||||
appIdService: AppIdServiceAbstraction;
|
appIdService: AppIdServiceAbstraction;
|
||||||
apiService: ApiServiceAbstraction;
|
apiService: ApiServiceAbstraction;
|
||||||
environmentService: BrowserEnvironmentService;
|
environmentService: BrowserEnvironmentService;
|
||||||
settingsService: SettingsServiceAbstraction;
|
|
||||||
cipherService: CipherServiceAbstraction;
|
cipherService: CipherServiceAbstraction;
|
||||||
folderService: InternalFolderServiceAbstraction;
|
folderService: InternalFolderServiceAbstraction;
|
||||||
collectionService: CollectionServiceAbstraction;
|
collectionService: CollectionServiceAbstraction;
|
||||||
@ -288,7 +287,7 @@ export default class MainBackground {
|
|||||||
fido2UserInterfaceService: Fido2UserInterfaceServiceAbstraction;
|
fido2UserInterfaceService: Fido2UserInterfaceServiceAbstraction;
|
||||||
fido2AuthenticatorService: Fido2AuthenticatorServiceAbstraction;
|
fido2AuthenticatorService: Fido2AuthenticatorServiceAbstraction;
|
||||||
fido2ClientService: Fido2ClientServiceAbstraction;
|
fido2ClientService: Fido2ClientServiceAbstraction;
|
||||||
avatarUpdateService: AvatarUpdateServiceAbstraction;
|
avatarService: AvatarServiceAbstraction;
|
||||||
mainContextMenuHandler: MainContextMenuHandler;
|
mainContextMenuHandler: MainContextMenuHandler;
|
||||||
cipherContextMenuHandler: CipherContextMenuHandler;
|
cipherContextMenuHandler: CipherContextMenuHandler;
|
||||||
configService: BrowserConfigService;
|
configService: BrowserConfigService;
|
||||||
@ -311,6 +310,7 @@ export default class MainBackground {
|
|||||||
biometricStateService: BiometricStateService;
|
biometricStateService: BiometricStateService;
|
||||||
stateEventRunnerService: StateEventRunnerService;
|
stateEventRunnerService: StateEventRunnerService;
|
||||||
ssoLoginService: SsoLoginServiceAbstraction;
|
ssoLoginService: SsoLoginServiceAbstraction;
|
||||||
|
billingAccountProfileStateService: BillingAccountProfileStateService;
|
||||||
|
|
||||||
onUpdatedRan: boolean;
|
onUpdatedRan: boolean;
|
||||||
onReplacedRan: boolean;
|
onReplacedRan: boolean;
|
||||||
@ -409,8 +409,7 @@ export default class MainBackground {
|
|||||||
);
|
);
|
||||||
this.activeUserStateProvider = new DefaultActiveUserStateProvider(
|
this.activeUserStateProvider = new DefaultActiveUserStateProvider(
|
||||||
this.accountService,
|
this.accountService,
|
||||||
storageServiceProvider,
|
this.singleUserStateProvider,
|
||||||
stateEventRegistrarService,
|
|
||||||
);
|
);
|
||||||
this.derivedStateProvider = new BackgroundDerivedStateProvider(
|
this.derivedStateProvider = new BackgroundDerivedStateProvider(
|
||||||
this.memoryStorageForStateProviders,
|
this.memoryStorageForStateProviders,
|
||||||
@ -428,6 +427,21 @@ export default class MainBackground {
|
|||||||
);
|
);
|
||||||
this.biometricStateService = new DefaultBiometricStateService(this.stateProvider);
|
this.biometricStateService = new DefaultBiometricStateService(this.stateProvider);
|
||||||
|
|
||||||
|
this.userNotificationSettingsService = new UserNotificationSettingsService(this.stateProvider);
|
||||||
|
this.platformUtilsService = new BackgroundPlatformUtilsService(
|
||||||
|
this.messagingService,
|
||||||
|
(clipboardValue, clearMs) => this.clearClipboard(clipboardValue, clearMs),
|
||||||
|
async () => this.biometricUnlock(),
|
||||||
|
self,
|
||||||
|
);
|
||||||
|
|
||||||
|
this.tokenService = new TokenService(
|
||||||
|
this.singleUserStateProvider,
|
||||||
|
this.globalStateProvider,
|
||||||
|
this.platformUtilsService.supportsSecureStorage(),
|
||||||
|
this.secureStorageService,
|
||||||
|
);
|
||||||
|
|
||||||
const migrationRunner = new MigrationRunner(
|
const migrationRunner = new MigrationRunner(
|
||||||
this.storageService,
|
this.storageService,
|
||||||
this.logService,
|
this.logService,
|
||||||
@ -442,15 +456,9 @@ export default class MainBackground {
|
|||||||
new StateFactory(GlobalState, Account),
|
new StateFactory(GlobalState, Account),
|
||||||
this.accountService,
|
this.accountService,
|
||||||
this.environmentService,
|
this.environmentService,
|
||||||
|
this.tokenService,
|
||||||
migrationRunner,
|
migrationRunner,
|
||||||
);
|
);
|
||||||
this.userNotificationSettingsService = new UserNotificationSettingsService(this.stateProvider);
|
|
||||||
this.platformUtilsService = new BackgroundPlatformUtilsService(
|
|
||||||
this.messagingService,
|
|
||||||
(clipboardValue, clearMs) => this.clearClipboard(clipboardValue, clearMs),
|
|
||||||
async () => this.biometricUnlock(),
|
|
||||||
self,
|
|
||||||
);
|
|
||||||
|
|
||||||
const themeStateService = new DefaultThemeStateService(this.globalStateProvider);
|
const themeStateService = new DefaultThemeStateService(this.globalStateProvider);
|
||||||
|
|
||||||
@ -466,17 +474,17 @@ export default class MainBackground {
|
|||||||
this.stateProvider,
|
this.stateProvider,
|
||||||
this.biometricStateService,
|
this.biometricStateService,
|
||||||
);
|
);
|
||||||
this.tokenService = new TokenService(this.stateService);
|
|
||||||
this.appIdService = new AppIdService(this.globalStateProvider);
|
this.appIdService = new AppIdService(this.globalStateProvider);
|
||||||
this.apiService = new ApiService(
|
this.apiService = new ApiService(
|
||||||
this.tokenService,
|
this.tokenService,
|
||||||
this.platformUtilsService,
|
this.platformUtilsService,
|
||||||
this.environmentService,
|
this.environmentService,
|
||||||
this.appIdService,
|
this.appIdService,
|
||||||
|
this.stateService,
|
||||||
(expired: boolean) => this.logout(expired),
|
(expired: boolean) => this.logout(expired),
|
||||||
);
|
);
|
||||||
this.domainSettingsService = new DefaultDomainSettingsService(this.stateProvider);
|
this.domainSettingsService = new DefaultDomainSettingsService(this.stateProvider);
|
||||||
this.settingsService = new BrowserSettingsService(this.stateService);
|
|
||||||
this.fileUploadService = new FileUploadService(this.logService);
|
this.fileUploadService = new FileUploadService(this.logService);
|
||||||
this.cipherFileUploadService = new CipherFileUploadService(
|
this.cipherFileUploadService = new CipherFileUploadService(
|
||||||
this.apiService,
|
this.apiService,
|
||||||
@ -490,10 +498,7 @@ export default class MainBackground {
|
|||||||
this.stateProvider,
|
this.stateProvider,
|
||||||
);
|
);
|
||||||
this.syncNotifierService = new SyncNotifierService();
|
this.syncNotifierService = new SyncNotifierService();
|
||||||
this.organizationService = new BrowserOrganizationService(
|
this.organizationService = new OrganizationService(this.stateProvider);
|
||||||
this.stateService,
|
|
||||||
this.stateProvider,
|
|
||||||
);
|
|
||||||
this.policyService = new PolicyService(this.stateProvider, this.organizationService);
|
this.policyService = new PolicyService(this.stateProvider, this.organizationService);
|
||||||
this.autofillSettingsService = new AutofillSettingsService(
|
this.autofillSettingsService = new AutofillSettingsService(
|
||||||
this.stateProvider,
|
this.stateProvider,
|
||||||
@ -563,6 +568,10 @@ export default class MainBackground {
|
|||||||
this.stateService,
|
this.stateService,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
this.billingAccountProfileStateService = new DefaultBillingAccountProfileStateService(
|
||||||
|
this.activeUserStateProvider,
|
||||||
|
);
|
||||||
|
|
||||||
this.loginStrategyService = new LoginStrategyService(
|
this.loginStrategyService = new LoginStrategyService(
|
||||||
this.cryptoService,
|
this.cryptoService,
|
||||||
this.apiService,
|
this.apiService,
|
||||||
@ -582,6 +591,7 @@ export default class MainBackground {
|
|||||||
this.deviceTrustCryptoService,
|
this.deviceTrustCryptoService,
|
||||||
this.authRequestService,
|
this.authRequestService,
|
||||||
this.globalStateProvider,
|
this.globalStateProvider,
|
||||||
|
this.billingAccountProfileStateService,
|
||||||
);
|
);
|
||||||
|
|
||||||
this.ssoLoginService = new SsoLoginService(this.stateProvider);
|
this.ssoLoginService = new SsoLoginService(this.stateProvider);
|
||||||
@ -685,7 +695,11 @@ export default class MainBackground {
|
|||||||
this.fileUploadService,
|
this.fileUploadService,
|
||||||
this.sendService,
|
this.sendService,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
this.avatarService = new AvatarService(this.apiService, this.stateProvider);
|
||||||
|
|
||||||
this.providerService = new ProviderService(this.stateProvider);
|
this.providerService = new ProviderService(this.stateProvider);
|
||||||
|
|
||||||
this.syncService = new SyncService(
|
this.syncService = new SyncService(
|
||||||
this.apiService,
|
this.apiService,
|
||||||
this.domainSettingsService,
|
this.domainSettingsService,
|
||||||
@ -703,18 +717,22 @@ export default class MainBackground {
|
|||||||
this.folderApiService,
|
this.folderApiService,
|
||||||
this.organizationService,
|
this.organizationService,
|
||||||
this.sendApiService,
|
this.sendApiService,
|
||||||
|
this.avatarService,
|
||||||
logoutCallback,
|
logoutCallback,
|
||||||
|
this.billingAccountProfileStateService,
|
||||||
);
|
);
|
||||||
this.eventUploadService = new EventUploadService(
|
this.eventUploadService = new EventUploadService(
|
||||||
this.apiService,
|
this.apiService,
|
||||||
this.stateService,
|
this.stateProvider,
|
||||||
this.logService,
|
this.logService,
|
||||||
|
this.accountService,
|
||||||
);
|
);
|
||||||
this.eventCollectionService = new EventCollectionService(
|
this.eventCollectionService = new EventCollectionService(
|
||||||
this.cipherService,
|
this.cipherService,
|
||||||
this.stateService,
|
this.stateProvider,
|
||||||
this.organizationService,
|
this.organizationService,
|
||||||
this.eventUploadService,
|
this.eventUploadService,
|
||||||
|
this.accountService,
|
||||||
);
|
);
|
||||||
this.totpService = new TotpService(this.cryptoFunctionService, this.logService);
|
this.totpService = new TotpService(this.cryptoFunctionService, this.logService);
|
||||||
|
|
||||||
@ -727,6 +745,7 @@ export default class MainBackground {
|
|||||||
this.logService,
|
this.logService,
|
||||||
this.domainSettingsService,
|
this.domainSettingsService,
|
||||||
this.userVerificationService,
|
this.userVerificationService,
|
||||||
|
this.billingAccountProfileStateService,
|
||||||
);
|
);
|
||||||
this.auditService = new AuditService(this.cryptoFunctionService, this.apiService);
|
this.auditService = new AuditService(this.cryptoFunctionService, this.apiService);
|
||||||
|
|
||||||
@ -787,7 +806,6 @@ export default class MainBackground {
|
|||||||
this.fido2AuthenticatorService,
|
this.fido2AuthenticatorService,
|
||||||
this.configService,
|
this.configService,
|
||||||
this.authService,
|
this.authService,
|
||||||
this.stateService,
|
|
||||||
this.vaultSettingsService,
|
this.vaultSettingsService,
|
||||||
this.domainSettingsService,
|
this.domainSettingsService,
|
||||||
this.logService,
|
this.logService,
|
||||||
@ -835,7 +853,6 @@ export default class MainBackground {
|
|||||||
this.cryptoService,
|
this.cryptoService,
|
||||||
this.cryptoFunctionService,
|
this.cryptoFunctionService,
|
||||||
this.runtimeBackground,
|
this.runtimeBackground,
|
||||||
this.i18nService,
|
|
||||||
this.messagingService,
|
this.messagingService,
|
||||||
this.appIdService,
|
this.appIdService,
|
||||||
this.platformUtilsService,
|
this.platformUtilsService,
|
||||||
@ -869,7 +886,7 @@ export default class MainBackground {
|
|||||||
this.autofillService,
|
this.autofillService,
|
||||||
this.authService,
|
this.authService,
|
||||||
this.environmentService,
|
this.environmentService,
|
||||||
this.settingsService,
|
this.domainSettingsService,
|
||||||
this.stateService,
|
this.stateService,
|
||||||
this.autofillSettingsService,
|
this.autofillSettingsService,
|
||||||
this.i18nService,
|
this.i18nService,
|
||||||
@ -943,14 +960,13 @@ export default class MainBackground {
|
|||||||
this.apiService,
|
this.apiService,
|
||||||
);
|
);
|
||||||
|
|
||||||
this.avatarUpdateService = new AvatarUpdateService(this.apiService, this.stateService);
|
|
||||||
|
|
||||||
if (!this.popupOnlyContext) {
|
if (!this.popupOnlyContext) {
|
||||||
this.mainContextMenuHandler = new MainContextMenuHandler(
|
this.mainContextMenuHandler = new MainContextMenuHandler(
|
||||||
this.stateService,
|
this.stateService,
|
||||||
this.autofillSettingsService,
|
this.autofillSettingsService,
|
||||||
this.i18nService,
|
this.i18nService,
|
||||||
this.logService,
|
this.logService,
|
||||||
|
this.billingAccountProfileStateService,
|
||||||
);
|
);
|
||||||
|
|
||||||
this.cipherContextMenuHandler = new CipherContextMenuHandler(
|
this.cipherContextMenuHandler = new CipherContextMenuHandler(
|
||||||
@ -1090,7 +1106,7 @@ export default class MainBackground {
|
|||||||
async logout(expired: boolean, userId?: UserId) {
|
async logout(expired: boolean, userId?: UserId) {
|
||||||
userId ??= (await firstValueFrom(this.accountService.activeAccount$))?.id;
|
userId ??= (await firstValueFrom(this.accountService.activeAccount$))?.id;
|
||||||
|
|
||||||
await this.eventUploadService.uploadEvents(userId);
|
await this.eventUploadService.uploadEvents(userId as UserId);
|
||||||
|
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
this.syncService.setLastSync(new Date(0), userId),
|
this.syncService.setLastSync(new Date(0), userId),
|
||||||
|
@ -5,7 +5,6 @@ import { AuthenticationStatus } from "@bitwarden/common/auth/enums/authenticatio
|
|||||||
import { AppIdService } from "@bitwarden/common/platform/abstractions/app-id.service";
|
import { AppIdService } from "@bitwarden/common/platform/abstractions/app-id.service";
|
||||||
import { CryptoFunctionService } from "@bitwarden/common/platform/abstractions/crypto-function.service";
|
import { CryptoFunctionService } from "@bitwarden/common/platform/abstractions/crypto-function.service";
|
||||||
import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service";
|
import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service";
|
||||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
|
||||||
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
|
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
|
||||||
import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service";
|
import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service";
|
||||||
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
||||||
@ -75,7 +74,6 @@ export class NativeMessagingBackground {
|
|||||||
private cryptoService: CryptoService,
|
private cryptoService: CryptoService,
|
||||||
private cryptoFunctionService: CryptoFunctionService,
|
private cryptoFunctionService: CryptoFunctionService,
|
||||||
private runtimeBackground: RuntimeBackground,
|
private runtimeBackground: RuntimeBackground,
|
||||||
private i18nService: I18nService,
|
|
||||||
private messagingService: MessagingService,
|
private messagingService: MessagingService,
|
||||||
private appIdService: AppIdService,
|
private appIdService: AppIdService,
|
||||||
private platformUtilsService: PlatformUtilsService,
|
private platformUtilsService: PlatformUtilsService,
|
||||||
|
@ -97,6 +97,10 @@ export default class RuntimeBackground {
|
|||||||
case "unlocked": {
|
case "unlocked": {
|
||||||
let item: LockedVaultPendingNotificationsData;
|
let item: LockedVaultPendingNotificationsData;
|
||||||
|
|
||||||
|
if (msg.command === "loggedIn") {
|
||||||
|
await this.sendBwInstalledMessageToVault();
|
||||||
|
}
|
||||||
|
|
||||||
if (this.lockedVaultPendingNotifications?.length > 0) {
|
if (this.lockedVaultPendingNotifications?.length > 0) {
|
||||||
item = this.lockedVaultPendingNotifications.pop();
|
item = this.lockedVaultPendingNotifications.pop();
|
||||||
await closeUnlockPopout();
|
await closeUnlockPopout();
|
||||||
@ -130,9 +134,6 @@ export default class RuntimeBackground {
|
|||||||
await this.main.refreshBadge();
|
await this.main.refreshBadge();
|
||||||
await this.main.refreshMenu();
|
await this.main.refreshMenu();
|
||||||
}, 2000);
|
}, 2000);
|
||||||
// FIXME: Verify that this floating promise is intentional. If it is, add an explanatory comment and ensure there is proper error handling.
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
|
||||||
this.main.avatarUpdateService.loadColorFromState();
|
|
||||||
this.configService.triggerServerConfigFetch();
|
this.configService.triggerServerConfigFetch();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -354,8 +355,6 @@ export default class RuntimeBackground {
|
|||||||
if (await this.environmentService.hasManagedEnvironment()) {
|
if (await this.environmentService.hasManagedEnvironment()) {
|
||||||
await this.environmentService.setUrlsToManagedEnvironment();
|
await this.environmentService.setUrlsToManagedEnvironment();
|
||||||
}
|
}
|
||||||
|
|
||||||
await this.sendBwInstalledMessageToVault();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this.onInstalledReason = null;
|
this.onInstalledReason = null;
|
||||||
|
@ -5,15 +5,14 @@ import {
|
|||||||
organizationServiceFactory,
|
organizationServiceFactory,
|
||||||
OrganizationServiceInitOptions,
|
OrganizationServiceInitOptions,
|
||||||
} from "../../admin-console/background/service-factories/organization-service.factory";
|
} from "../../admin-console/background/service-factories/organization-service.factory";
|
||||||
|
import { accountServiceFactory } from "../../auth/background/service-factories/account-service.factory";
|
||||||
import {
|
import {
|
||||||
FactoryOptions,
|
FactoryOptions,
|
||||||
CachedServices,
|
CachedServices,
|
||||||
factory,
|
factory,
|
||||||
} from "../../platform/background/service-factories/factory-options";
|
} from "../../platform/background/service-factories/factory-options";
|
||||||
import {
|
import { stateProviderFactory } from "../../platform/background/service-factories/state-provider.factory";
|
||||||
stateServiceFactory,
|
import { StateServiceInitOptions } from "../../platform/background/service-factories/state-service.factory";
|
||||||
StateServiceInitOptions,
|
|
||||||
} from "../../platform/background/service-factories/state-service.factory";
|
|
||||||
import {
|
import {
|
||||||
cipherServiceFactory,
|
cipherServiceFactory,
|
||||||
CipherServiceInitOptions,
|
CipherServiceInitOptions,
|
||||||
@ -43,9 +42,10 @@ export function eventCollectionServiceFactory(
|
|||||||
async () =>
|
async () =>
|
||||||
new EventCollectionService(
|
new EventCollectionService(
|
||||||
await cipherServiceFactory(cache, opts),
|
await cipherServiceFactory(cache, opts),
|
||||||
await stateServiceFactory(cache, opts),
|
await stateProviderFactory(cache, opts),
|
||||||
await organizationServiceFactory(cache, opts),
|
await organizationServiceFactory(cache, opts),
|
||||||
await eventUploadServiceFactory(cache, opts),
|
await eventUploadServiceFactory(cache, opts),
|
||||||
|
await accountServiceFactory(cache, opts),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import { EventUploadService as AbstractEventUploadService } from "@bitwarden/common/abstractions/event/event-upload.service";
|
import { EventUploadService as AbstractEventUploadService } from "@bitwarden/common/abstractions/event/event-upload.service";
|
||||||
import { EventUploadService } from "@bitwarden/common/services/event/event-upload.service";
|
import { EventUploadService } from "@bitwarden/common/services/event/event-upload.service";
|
||||||
|
|
||||||
|
import { accountServiceFactory } from "../../auth/background/service-factories/account-service.factory";
|
||||||
import {
|
import {
|
||||||
ApiServiceInitOptions,
|
ApiServiceInitOptions,
|
||||||
apiServiceFactory,
|
apiServiceFactory,
|
||||||
@ -14,10 +15,8 @@ import {
|
|||||||
logServiceFactory,
|
logServiceFactory,
|
||||||
LogServiceInitOptions,
|
LogServiceInitOptions,
|
||||||
} from "../../platform/background/service-factories/log-service.factory";
|
} from "../../platform/background/service-factories/log-service.factory";
|
||||||
import {
|
import { stateProviderFactory } from "../../platform/background/service-factories/state-provider.factory";
|
||||||
stateServiceFactory,
|
import { StateServiceInitOptions } from "../../platform/background/service-factories/state-service.factory";
|
||||||
StateServiceInitOptions,
|
|
||||||
} from "../../platform/background/service-factories/state-service.factory";
|
|
||||||
|
|
||||||
type EventUploadServiceOptions = FactoryOptions;
|
type EventUploadServiceOptions = FactoryOptions;
|
||||||
|
|
||||||
@ -37,8 +36,9 @@ export function eventUploadServiceFactory(
|
|||||||
async () =>
|
async () =>
|
||||||
new EventUploadService(
|
new EventUploadService(
|
||||||
await apiServiceFactory(cache, opts),
|
await apiServiceFactory(cache, opts),
|
||||||
await stateServiceFactory(cache, opts),
|
await stateProviderFactory(cache, opts),
|
||||||
await logServiceFactory(cache, opts),
|
await logServiceFactory(cache, opts),
|
||||||
|
await accountServiceFactory(cache, opts),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -1,28 +0,0 @@
|
|||||||
import { SettingsService as AbstractSettingsService } from "@bitwarden/common/abstractions/settings.service";
|
|
||||||
|
|
||||||
import {
|
|
||||||
FactoryOptions,
|
|
||||||
CachedServices,
|
|
||||||
factory,
|
|
||||||
} from "../../platform/background/service-factories/factory-options";
|
|
||||||
import {
|
|
||||||
stateServiceFactory,
|
|
||||||
StateServiceInitOptions,
|
|
||||||
} from "../../platform/background/service-factories/state-service.factory";
|
|
||||||
import { BrowserSettingsService } from "../../services/browser-settings.service";
|
|
||||||
|
|
||||||
type SettingsServiceFactoryOptions = FactoryOptions;
|
|
||||||
|
|
||||||
export type SettingsServiceInitOptions = SettingsServiceFactoryOptions & StateServiceInitOptions;
|
|
||||||
|
|
||||||
export function settingsServiceFactory(
|
|
||||||
cache: { settingsService?: AbstractSettingsService } & CachedServices,
|
|
||||||
opts: SettingsServiceInitOptions,
|
|
||||||
): Promise<AbstractSettingsService> {
|
|
||||||
return factory(
|
|
||||||
cache,
|
|
||||||
"settingsService",
|
|
||||||
opts,
|
|
||||||
async () => new BrowserSettingsService(await stateServiceFactory(cache, opts)),
|
|
||||||
);
|
|
||||||
}
|
|
@ -9,20 +9,15 @@ import {
|
|||||||
|
|
||||||
import { CachedServices, FactoryOptions, factory } from "./factory-options";
|
import { CachedServices, FactoryOptions, factory } from "./factory-options";
|
||||||
import {
|
import {
|
||||||
StateEventRegistrarServiceInitOptions,
|
SingleUserStateProviderInitOptions,
|
||||||
stateEventRegistrarServiceFactory,
|
singleUserStateProviderFactory,
|
||||||
} from "./state-event-registrar-service.factory";
|
} from "./single-user-state-provider.factory";
|
||||||
import {
|
|
||||||
StorageServiceProviderInitOptions,
|
|
||||||
storageServiceProviderFactory,
|
|
||||||
} from "./storage-service-provider.factory";
|
|
||||||
|
|
||||||
type ActiveUserStateProviderFactory = FactoryOptions;
|
type ActiveUserStateProviderFactory = FactoryOptions;
|
||||||
|
|
||||||
export type ActiveUserStateProviderInitOptions = ActiveUserStateProviderFactory &
|
export type ActiveUserStateProviderInitOptions = ActiveUserStateProviderFactory &
|
||||||
AccountServiceInitOptions &
|
AccountServiceInitOptions &
|
||||||
StorageServiceProviderInitOptions &
|
SingleUserStateProviderInitOptions;
|
||||||
StateEventRegistrarServiceInitOptions;
|
|
||||||
|
|
||||||
export async function activeUserStateProviderFactory(
|
export async function activeUserStateProviderFactory(
|
||||||
cache: { activeUserStateProvider?: ActiveUserStateProvider } & CachedServices,
|
cache: { activeUserStateProvider?: ActiveUserStateProvider } & CachedServices,
|
||||||
@ -35,8 +30,7 @@ export async function activeUserStateProviderFactory(
|
|||||||
async () =>
|
async () =>
|
||||||
new DefaultActiveUserStateProvider(
|
new DefaultActiveUserStateProvider(
|
||||||
await accountServiceFactory(cache, opts),
|
await accountServiceFactory(cache, opts),
|
||||||
await storageServiceProviderFactory(cache, opts),
|
await singleUserStateProviderFactory(cache, opts),
|
||||||
await stateEventRegistrarServiceFactory(cache, opts),
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -20,6 +20,7 @@ import {
|
|||||||
PlatformUtilsServiceInitOptions,
|
PlatformUtilsServiceInitOptions,
|
||||||
platformUtilsServiceFactory,
|
platformUtilsServiceFactory,
|
||||||
} from "./platform-utils-service.factory";
|
} from "./platform-utils-service.factory";
|
||||||
|
import { stateServiceFactory, StateServiceInitOptions } from "./state-service.factory";
|
||||||
|
|
||||||
type ApiServiceFactoryOptions = FactoryOptions & {
|
type ApiServiceFactoryOptions = FactoryOptions & {
|
||||||
apiServiceOptions: {
|
apiServiceOptions: {
|
||||||
@ -32,7 +33,8 @@ export type ApiServiceInitOptions = ApiServiceFactoryOptions &
|
|||||||
TokenServiceInitOptions &
|
TokenServiceInitOptions &
|
||||||
PlatformUtilsServiceInitOptions &
|
PlatformUtilsServiceInitOptions &
|
||||||
EnvironmentServiceInitOptions &
|
EnvironmentServiceInitOptions &
|
||||||
AppIdServiceInitOptions;
|
AppIdServiceInitOptions &
|
||||||
|
StateServiceInitOptions;
|
||||||
|
|
||||||
export function apiServiceFactory(
|
export function apiServiceFactory(
|
||||||
cache: { apiService?: AbstractApiService } & CachedServices,
|
cache: { apiService?: AbstractApiService } & CachedServices,
|
||||||
@ -48,6 +50,7 @@ export function apiServiceFactory(
|
|||||||
await platformUtilsServiceFactory(cache, opts),
|
await platformUtilsServiceFactory(cache, opts),
|
||||||
await environmentServiceFactory(cache, opts),
|
await environmentServiceFactory(cache, opts),
|
||||||
await appIdServiceFactory(cache, opts),
|
await appIdServiceFactory(cache, opts),
|
||||||
|
await stateServiceFactory(cache, opts),
|
||||||
opts.apiServiceOptions.logoutCallback,
|
opts.apiServiceOptions.logoutCallback,
|
||||||
opts.apiServiceOptions.customUserAgent,
|
opts.apiServiceOptions.customUserAgent,
|
||||||
),
|
),
|
||||||
|
@ -0,0 +1,28 @@
|
|||||||
|
import { BillingAccountProfileStateService } from "@bitwarden/common/billing/abstractions/account/billing-account-profile-state.service";
|
||||||
|
import { DefaultBillingAccountProfileStateService } from "@bitwarden/common/billing/services/account/billing-account-profile-state.service";
|
||||||
|
|
||||||
|
import { activeUserStateProviderFactory } from "./active-user-state-provider.factory";
|
||||||
|
import { FactoryOptions, CachedServices, factory } from "./factory-options";
|
||||||
|
import { StateProviderInitOptions } from "./state-provider.factory";
|
||||||
|
|
||||||
|
type BillingAccountProfileStateServiceFactoryOptions = FactoryOptions;
|
||||||
|
|
||||||
|
export type BillingAccountProfileStateServiceInitOptions =
|
||||||
|
BillingAccountProfileStateServiceFactoryOptions & StateProviderInitOptions;
|
||||||
|
|
||||||
|
export function billingAccountProfileStateServiceFactory(
|
||||||
|
cache: {
|
||||||
|
billingAccountProfileStateService?: BillingAccountProfileStateService;
|
||||||
|
} & CachedServices,
|
||||||
|
opts: BillingAccountProfileStateServiceInitOptions,
|
||||||
|
): Promise<BillingAccountProfileStateService> {
|
||||||
|
return factory(
|
||||||
|
cache,
|
||||||
|
"billingAccountProfileStateService",
|
||||||
|
opts,
|
||||||
|
async () =>
|
||||||
|
new DefaultBillingAccountProfileStateService(
|
||||||
|
await activeUserStateProviderFactory(cache, opts),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
@ -5,6 +5,10 @@ import {
|
|||||||
accountServiceFactory,
|
accountServiceFactory,
|
||||||
AccountServiceInitOptions,
|
AccountServiceInitOptions,
|
||||||
} from "../../../auth/background/service-factories/account-service.factory";
|
} from "../../../auth/background/service-factories/account-service.factory";
|
||||||
|
import {
|
||||||
|
tokenServiceFactory,
|
||||||
|
TokenServiceInitOptions,
|
||||||
|
} from "../../../auth/background/service-factories/token-service.factory";
|
||||||
import { Account } from "../../../models/account";
|
import { Account } from "../../../models/account";
|
||||||
import { BrowserStateService } from "../../services/browser-state.service";
|
import { BrowserStateService } from "../../services/browser-state.service";
|
||||||
|
|
||||||
@ -38,6 +42,7 @@ export type StateServiceInitOptions = StateServiceFactoryOptions &
|
|||||||
LogServiceInitOptions &
|
LogServiceInitOptions &
|
||||||
AccountServiceInitOptions &
|
AccountServiceInitOptions &
|
||||||
EnvironmentServiceInitOptions &
|
EnvironmentServiceInitOptions &
|
||||||
|
TokenServiceInitOptions &
|
||||||
MigrationRunnerInitOptions;
|
MigrationRunnerInitOptions;
|
||||||
|
|
||||||
export async function stateServiceFactory(
|
export async function stateServiceFactory(
|
||||||
@ -57,6 +62,7 @@ export async function stateServiceFactory(
|
|||||||
opts.stateServiceOptions.stateFactory,
|
opts.stateServiceOptions.stateFactory,
|
||||||
await accountServiceFactory(cache, opts),
|
await accountServiceFactory(cache, opts),
|
||||||
await environmentServiceFactory(cache, opts),
|
await environmentServiceFactory(cache, opts),
|
||||||
|
await tokenServiceFactory(cache, opts),
|
||||||
await migrationRunnerFactory(cache, opts),
|
await migrationRunnerFactory(cache, opts),
|
||||||
opts.stateServiceOptions.useAccountCache,
|
opts.stateServiceOptions.useAccountCache,
|
||||||
),
|
),
|
||||||
|
@ -7,6 +7,7 @@ import localeBn from "@angular/common/locales/bn";
|
|||||||
import localeBs from "@angular/common/locales/bs";
|
import localeBs from "@angular/common/locales/bs";
|
||||||
import localeCa from "@angular/common/locales/ca";
|
import localeCa from "@angular/common/locales/ca";
|
||||||
import localeCs from "@angular/common/locales/cs";
|
import localeCs from "@angular/common/locales/cs";
|
||||||
|
import localeCy from "@angular/common/locales/cy";
|
||||||
import localeDa from "@angular/common/locales/da";
|
import localeDa from "@angular/common/locales/da";
|
||||||
import localeDe from "@angular/common/locales/de";
|
import localeDe from "@angular/common/locales/de";
|
||||||
import localeEl from "@angular/common/locales/el";
|
import localeEl from "@angular/common/locales/el";
|
||||||
@ -19,6 +20,7 @@ import localeFa from "@angular/common/locales/fa";
|
|||||||
import localeFi from "@angular/common/locales/fi";
|
import localeFi from "@angular/common/locales/fi";
|
||||||
import localeFil from "@angular/common/locales/fil";
|
import localeFil from "@angular/common/locales/fil";
|
||||||
import localeFr from "@angular/common/locales/fr";
|
import localeFr from "@angular/common/locales/fr";
|
||||||
|
import localeGl from "@angular/common/locales/gl";
|
||||||
import localeHe from "@angular/common/locales/he";
|
import localeHe from "@angular/common/locales/he";
|
||||||
import localeHi from "@angular/common/locales/hi";
|
import localeHi from "@angular/common/locales/hi";
|
||||||
import localeHr from "@angular/common/locales/hr";
|
import localeHr from "@angular/common/locales/hr";
|
||||||
@ -33,9 +35,13 @@ import localeKo from "@angular/common/locales/ko";
|
|||||||
import localeLt from "@angular/common/locales/lt";
|
import localeLt from "@angular/common/locales/lt";
|
||||||
import localeLv from "@angular/common/locales/lv";
|
import localeLv from "@angular/common/locales/lv";
|
||||||
import localeMl from "@angular/common/locales/ml";
|
import localeMl from "@angular/common/locales/ml";
|
||||||
|
import localeMr from "@angular/common/locales/mr";
|
||||||
|
import localeMy from "@angular/common/locales/my";
|
||||||
import localeNb from "@angular/common/locales/nb";
|
import localeNb from "@angular/common/locales/nb";
|
||||||
|
import localeNe from "@angular/common/locales/ne";
|
||||||
import localeNl from "@angular/common/locales/nl";
|
import localeNl from "@angular/common/locales/nl";
|
||||||
import localeNn from "@angular/common/locales/nn";
|
import localeNn from "@angular/common/locales/nn";
|
||||||
|
import localeOr from "@angular/common/locales/or";
|
||||||
import localePl from "@angular/common/locales/pl";
|
import localePl from "@angular/common/locales/pl";
|
||||||
import localePtBr from "@angular/common/locales/pt";
|
import localePtBr from "@angular/common/locales/pt";
|
||||||
import localePtPt from "@angular/common/locales/pt-PT";
|
import localePtPt from "@angular/common/locales/pt-PT";
|
||||||
@ -46,6 +52,7 @@ import localeSk from "@angular/common/locales/sk";
|
|||||||
import localeSl from "@angular/common/locales/sl";
|
import localeSl from "@angular/common/locales/sl";
|
||||||
import localeSr from "@angular/common/locales/sr";
|
import localeSr from "@angular/common/locales/sr";
|
||||||
import localeSv from "@angular/common/locales/sv";
|
import localeSv from "@angular/common/locales/sv";
|
||||||
|
import localeTe from "@angular/common/locales/te";
|
||||||
import localeTh from "@angular/common/locales/th";
|
import localeTh from "@angular/common/locales/th";
|
||||||
import localeTr from "@angular/common/locales/tr";
|
import localeTr from "@angular/common/locales/tr";
|
||||||
import localeUk from "@angular/common/locales/uk";
|
import localeUk from "@angular/common/locales/uk";
|
||||||
@ -61,6 +68,7 @@ registerLocaleData(localeBn, "bn");
|
|||||||
registerLocaleData(localeBs, "bs");
|
registerLocaleData(localeBs, "bs");
|
||||||
registerLocaleData(localeCa, "ca");
|
registerLocaleData(localeCa, "ca");
|
||||||
registerLocaleData(localeCs, "cs");
|
registerLocaleData(localeCs, "cs");
|
||||||
|
registerLocaleData(localeCy, "cy");
|
||||||
registerLocaleData(localeDa, "da");
|
registerLocaleData(localeDa, "da");
|
||||||
registerLocaleData(localeDe, "de");
|
registerLocaleData(localeDe, "de");
|
||||||
registerLocaleData(localeEl, "el");
|
registerLocaleData(localeEl, "el");
|
||||||
@ -73,6 +81,7 @@ registerLocaleData(localeFa, "fa");
|
|||||||
registerLocaleData(localeFi, "fi");
|
registerLocaleData(localeFi, "fi");
|
||||||
registerLocaleData(localeFil, "fil");
|
registerLocaleData(localeFil, "fil");
|
||||||
registerLocaleData(localeFr, "fr");
|
registerLocaleData(localeFr, "fr");
|
||||||
|
registerLocaleData(localeGl, "gl");
|
||||||
registerLocaleData(localeHe, "he");
|
registerLocaleData(localeHe, "he");
|
||||||
registerLocaleData(localeHi, "hi");
|
registerLocaleData(localeHi, "hi");
|
||||||
registerLocaleData(localeHr, "hr");
|
registerLocaleData(localeHr, "hr");
|
||||||
@ -87,9 +96,13 @@ registerLocaleData(localeKo, "ko");
|
|||||||
registerLocaleData(localeLt, "lt");
|
registerLocaleData(localeLt, "lt");
|
||||||
registerLocaleData(localeLv, "lv");
|
registerLocaleData(localeLv, "lv");
|
||||||
registerLocaleData(localeMl, "ml");
|
registerLocaleData(localeMl, "ml");
|
||||||
|
registerLocaleData(localeMr, "mr");
|
||||||
|
registerLocaleData(localeMy, "my");
|
||||||
registerLocaleData(localeNb, "nb");
|
registerLocaleData(localeNb, "nb");
|
||||||
|
registerLocaleData(localeNe, "ne");
|
||||||
registerLocaleData(localeNl, "nl");
|
registerLocaleData(localeNl, "nl");
|
||||||
registerLocaleData(localeNn, "nn");
|
registerLocaleData(localeNn, "nn");
|
||||||
|
registerLocaleData(localeOr, "or");
|
||||||
registerLocaleData(localePl, "pl");
|
registerLocaleData(localePl, "pl");
|
||||||
registerLocaleData(localePtBr, "pt-BR");
|
registerLocaleData(localePtBr, "pt-BR");
|
||||||
registerLocaleData(localePtPt, "pt-PT");
|
registerLocaleData(localePtPt, "pt-PT");
|
||||||
@ -100,6 +113,7 @@ registerLocaleData(localeSk, "sk");
|
|||||||
registerLocaleData(localeSl, "sl");
|
registerLocaleData(localeSl, "sl");
|
||||||
registerLocaleData(localeSr, "sr");
|
registerLocaleData(localeSr, "sr");
|
||||||
registerLocaleData(localeSv, "sv");
|
registerLocaleData(localeSv, "sv");
|
||||||
|
registerLocaleData(localeTe, "te");
|
||||||
registerLocaleData(localeTh, "th");
|
registerLocaleData(localeTh, "th");
|
||||||
registerLocaleData(localeTr, "tr");
|
registerLocaleData(localeTr, "tr");
|
||||||
registerLocaleData(localeUk, "uk");
|
registerLocaleData(localeUk, "uk");
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import { mock, MockProxy } from "jest-mock-extended";
|
import { mock, MockProxy } from "jest-mock-extended";
|
||||||
|
|
||||||
|
import { TokenService } from "@bitwarden/common/auth/abstractions/token.service";
|
||||||
import { EnvironmentService } from "@bitwarden/common/platform/abstractions/environment.service";
|
import { EnvironmentService } from "@bitwarden/common/platform/abstractions/environment.service";
|
||||||
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
|
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
|
||||||
import {
|
import {
|
||||||
@ -32,6 +33,7 @@ describe("Browser State Service", () => {
|
|||||||
let stateFactory: MockProxy<StateFactory<GlobalState, Account>>;
|
let stateFactory: MockProxy<StateFactory<GlobalState, Account>>;
|
||||||
let useAccountCache: boolean;
|
let useAccountCache: boolean;
|
||||||
let environmentService: MockProxy<EnvironmentService>;
|
let environmentService: MockProxy<EnvironmentService>;
|
||||||
|
let tokenService: MockProxy<TokenService>;
|
||||||
let migrationRunner: MockProxy<MigrationRunner>;
|
let migrationRunner: MockProxy<MigrationRunner>;
|
||||||
|
|
||||||
let state: State<GlobalState, Account>;
|
let state: State<GlobalState, Account>;
|
||||||
@ -46,6 +48,7 @@ describe("Browser State Service", () => {
|
|||||||
logService = mock();
|
logService = mock();
|
||||||
stateFactory = mock();
|
stateFactory = mock();
|
||||||
environmentService = mock();
|
environmentService = mock();
|
||||||
|
tokenService = mock();
|
||||||
migrationRunner = mock();
|
migrationRunner = mock();
|
||||||
// turn off account cache for tests
|
// turn off account cache for tests
|
||||||
useAccountCache = false;
|
useAccountCache = false;
|
||||||
@ -77,6 +80,7 @@ describe("Browser State Service", () => {
|
|||||||
stateFactory,
|
stateFactory,
|
||||||
accountService,
|
accountService,
|
||||||
environmentService,
|
environmentService,
|
||||||
|
tokenService,
|
||||||
migrationRunner,
|
migrationRunner,
|
||||||
useAccountCache,
|
useAccountCache,
|
||||||
);
|
);
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import { BehaviorSubject } from "rxjs";
|
import { BehaviorSubject } from "rxjs";
|
||||||
|
|
||||||
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
||||||
|
import { TokenService } from "@bitwarden/common/auth/abstractions/token.service";
|
||||||
import { EnvironmentService } from "@bitwarden/common/platform/abstractions/environment.service";
|
import { EnvironmentService } from "@bitwarden/common/platform/abstractions/environment.service";
|
||||||
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
|
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
|
||||||
import {
|
import {
|
||||||
@ -45,6 +46,7 @@ export class BrowserStateService
|
|||||||
stateFactory: StateFactory<GlobalState, Account>,
|
stateFactory: StateFactory<GlobalState, Account>,
|
||||||
accountService: AccountService,
|
accountService: AccountService,
|
||||||
environmentService: EnvironmentService,
|
environmentService: EnvironmentService,
|
||||||
|
tokenService: TokenService,
|
||||||
migrationRunner: MigrationRunner,
|
migrationRunner: MigrationRunner,
|
||||||
useAccountCache = true,
|
useAccountCache = true,
|
||||||
) {
|
) {
|
||||||
@ -56,6 +58,7 @@ export class BrowserStateService
|
|||||||
stateFactory,
|
stateFactory,
|
||||||
accountService,
|
accountService,
|
||||||
environmentService,
|
environmentService,
|
||||||
|
tokenService,
|
||||||
migrationRunner,
|
migrationRunner,
|
||||||
useAccountCache,
|
useAccountCache,
|
||||||
);
|
);
|
||||||
|
@ -17,11 +17,8 @@ import {
|
|||||||
LoginStrategyServiceAbstraction,
|
LoginStrategyServiceAbstraction,
|
||||||
} from "@bitwarden/auth/common";
|
} from "@bitwarden/auth/common";
|
||||||
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
||||||
import { EventCollectionService } from "@bitwarden/common/abstractions/event/event-collection.service";
|
|
||||||
import { EventUploadService } from "@bitwarden/common/abstractions/event/event-upload.service";
|
|
||||||
import { NotificationsService } from "@bitwarden/common/abstractions/notifications.service";
|
import { NotificationsService } from "@bitwarden/common/abstractions/notifications.service";
|
||||||
import { SearchService as SearchServiceAbstraction } from "@bitwarden/common/abstractions/search.service";
|
import { SearchService as SearchServiceAbstraction } from "@bitwarden/common/abstractions/search.service";
|
||||||
import { SettingsService } from "@bitwarden/common/abstractions/settings.service";
|
|
||||||
import { VaultTimeoutSettingsService } from "@bitwarden/common/abstractions/vault-timeout/vault-timeout-settings.service";
|
import { VaultTimeoutSettingsService } from "@bitwarden/common/abstractions/vault-timeout/vault-timeout-settings.service";
|
||||||
import { VaultTimeoutService } from "@bitwarden/common/abstractions/vault-timeout/vault-timeout.service";
|
import { VaultTimeoutService } from "@bitwarden/common/abstractions/vault-timeout/vault-timeout.service";
|
||||||
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
||||||
@ -42,6 +39,10 @@ import {
|
|||||||
AutofillSettingsService,
|
AutofillSettingsService,
|
||||||
AutofillSettingsServiceAbstraction,
|
AutofillSettingsServiceAbstraction,
|
||||||
} from "@bitwarden/common/autofill/services/autofill-settings.service";
|
} from "@bitwarden/common/autofill/services/autofill-settings.service";
|
||||||
|
import {
|
||||||
|
DefaultDomainSettingsService,
|
||||||
|
DomainSettingsService,
|
||||||
|
} from "@bitwarden/common/autofill/services/domain-settings.service";
|
||||||
import {
|
import {
|
||||||
UserNotificationSettingsService,
|
UserNotificationSettingsService,
|
||||||
UserNotificationSettingsServiceAbstraction,
|
UserNotificationSettingsServiceAbstraction,
|
||||||
@ -98,7 +99,6 @@ import { DialogService } from "@bitwarden/components";
|
|||||||
import { ImportServiceAbstraction } from "@bitwarden/importer/core";
|
import { ImportServiceAbstraction } from "@bitwarden/importer/core";
|
||||||
import { VaultExportServiceAbstraction } from "@bitwarden/vault-export-core";
|
import { VaultExportServiceAbstraction } from "@bitwarden/vault-export-core";
|
||||||
|
|
||||||
import { BrowserOrganizationService } from "../../admin-console/services/browser-organization.service";
|
|
||||||
import { UnauthGuardService } from "../../auth/popup/services";
|
import { UnauthGuardService } from "../../auth/popup/services";
|
||||||
import { AutofillService } from "../../autofill/services/abstractions/autofill.service";
|
import { AutofillService } from "../../autofill/services/abstractions/autofill.service";
|
||||||
import MainBackground from "../../background/main.background";
|
import MainBackground from "../../background/main.background";
|
||||||
@ -118,7 +118,6 @@ import { ForegroundPlatformUtilsService } from "../../platform/services/platform
|
|||||||
import { ForegroundDerivedStateProvider } from "../../platform/state/foreground-derived-state.provider";
|
import { ForegroundDerivedStateProvider } from "../../platform/state/foreground-derived-state.provider";
|
||||||
import { ForegroundMemoryStorageService } from "../../platform/storage/foreground-memory-storage.service";
|
import { ForegroundMemoryStorageService } from "../../platform/storage/foreground-memory-storage.service";
|
||||||
import { BrowserSendService } from "../../services/browser-send.service";
|
import { BrowserSendService } from "../../services/browser-send.service";
|
||||||
import { BrowserSettingsService } from "../../services/browser-settings.service";
|
|
||||||
import { FilePopoutUtilsService } from "../../tools/popup/services/file-popout-utils.service";
|
import { FilePopoutUtilsService } from "../../tools/popup/services/file-popout-utils.service";
|
||||||
import { VaultFilterService } from "../../vault/services/vault-filter.service";
|
import { VaultFilterService } from "../../vault/services/vault-filter.service";
|
||||||
|
|
||||||
@ -233,7 +232,6 @@ function getBgService<T>(service: keyof MainBackground) {
|
|||||||
deps: [],
|
deps: [],
|
||||||
},
|
},
|
||||||
{ provide: TotpService, useFactory: getBgService<TotpService>("totpService"), deps: [] },
|
{ provide: TotpService, useFactory: getBgService<TotpService>("totpService"), deps: [] },
|
||||||
{ provide: TokenService, useFactory: getBgService<TokenService>("tokenService"), deps: [] },
|
|
||||||
{
|
{
|
||||||
provide: I18nServiceAbstraction,
|
provide: I18nServiceAbstraction,
|
||||||
useFactory: (globalStateProvider: GlobalStateProvider) => {
|
useFactory: (globalStateProvider: GlobalStateProvider) => {
|
||||||
@ -265,16 +263,6 @@ function getBgService<T>(service: keyof MainBackground) {
|
|||||||
useFactory: getBgService<DevicesServiceAbstraction>("devicesService"),
|
useFactory: getBgService<DevicesServiceAbstraction>("devicesService"),
|
||||||
deps: [],
|
deps: [],
|
||||||
},
|
},
|
||||||
{
|
|
||||||
provide: EventUploadService,
|
|
||||||
useFactory: getBgService<EventUploadService>("eventUploadService"),
|
|
||||||
deps: [],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
provide: EventCollectionService,
|
|
||||||
useFactory: getBgService<EventCollectionService>("eventCollectionService"),
|
|
||||||
deps: [],
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
provide: PlatformUtilsService,
|
provide: PlatformUtilsService,
|
||||||
useExisting: ForegroundPlatformUtilsService,
|
useExisting: ForegroundPlatformUtilsService,
|
||||||
@ -348,11 +336,9 @@ function getBgService<T>(service: keyof MainBackground) {
|
|||||||
},
|
},
|
||||||
{ provide: SyncService, useFactory: getBgService<SyncService>("syncService"), deps: [] },
|
{ provide: SyncService, useFactory: getBgService<SyncService>("syncService"), deps: [] },
|
||||||
{
|
{
|
||||||
provide: SettingsService,
|
provide: DomainSettingsService,
|
||||||
useFactory: (stateService: StateServiceAbstraction) => {
|
useClass: DefaultDomainSettingsService,
|
||||||
return new BrowserSettingsService(stateService);
|
deps: [StateProvider],
|
||||||
},
|
|
||||||
deps: [StateServiceAbstraction],
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
provide: AbstractStorageService,
|
provide: AbstractStorageService,
|
||||||
@ -399,13 +385,6 @@ function getBgService<T>(service: keyof MainBackground) {
|
|||||||
useFactory: getBgService<NotificationsService>("notificationsService"),
|
useFactory: getBgService<NotificationsService>("notificationsService"),
|
||||||
deps: [],
|
deps: [],
|
||||||
},
|
},
|
||||||
{
|
|
||||||
provide: OrganizationService,
|
|
||||||
useFactory: (stateService: StateServiceAbstraction, stateProvider: StateProvider) => {
|
|
||||||
return new BrowserOrganizationService(stateService, stateProvider);
|
|
||||||
},
|
|
||||||
deps: [StateServiceAbstraction, StateProvider],
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
provide: VaultFilterService,
|
provide: VaultFilterService,
|
||||||
useClass: VaultFilterService,
|
useClass: VaultFilterService,
|
||||||
@ -445,6 +424,7 @@ function getBgService<T>(service: keyof MainBackground) {
|
|||||||
logService: LogServiceAbstraction,
|
logService: LogServiceAbstraction,
|
||||||
accountService: AccountServiceAbstraction,
|
accountService: AccountServiceAbstraction,
|
||||||
environmentService: EnvironmentService,
|
environmentService: EnvironmentService,
|
||||||
|
tokenService: TokenService,
|
||||||
migrationRunner: MigrationRunner,
|
migrationRunner: MigrationRunner,
|
||||||
) => {
|
) => {
|
||||||
return new BrowserStateService(
|
return new BrowserStateService(
|
||||||
@ -455,6 +435,7 @@ function getBgService<T>(service: keyof MainBackground) {
|
|||||||
new StateFactory(GlobalState, Account),
|
new StateFactory(GlobalState, Account),
|
||||||
accountService,
|
accountService,
|
||||||
environmentService,
|
environmentService,
|
||||||
|
tokenService,
|
||||||
migrationRunner,
|
migrationRunner,
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
@ -465,6 +446,7 @@ function getBgService<T>(service: keyof MainBackground) {
|
|||||||
LogServiceAbstraction,
|
LogServiceAbstraction,
|
||||||
AccountServiceAbstraction,
|
AccountServiceAbstraction,
|
||||||
EnvironmentService,
|
EnvironmentService,
|
||||||
|
TokenService,
|
||||||
MigrationRunner,
|
MigrationRunner,
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
@ -6,7 +6,6 @@ import { DomainSettingsService } from "@bitwarden/common/autofill/services/domai
|
|||||||
import { BroadcasterService } from "@bitwarden/common/platform/abstractions/broadcaster.service";
|
import { BroadcasterService } from "@bitwarden/common/platform/abstractions/broadcaster.service";
|
||||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||||
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
||||||
import { StateService } from "@bitwarden/common/platform/abstractions/state.service";
|
|
||||||
import { Utils } from "@bitwarden/common/platform/misc/utils";
|
import { Utils } from "@bitwarden/common/platform/misc/utils";
|
||||||
|
|
||||||
import { BrowserApi } from "../../platform/browser/browser-api";
|
import { BrowserApi } from "../../platform/browser/browser-api";
|
||||||
@ -31,7 +30,6 @@ export class ExcludedDomainsComponent implements OnInit, OnDestroy {
|
|||||||
accountSwitcherEnabled = false;
|
accountSwitcherEnabled = false;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private stateService: StateService,
|
|
||||||
private domainSettingsService: DomainSettingsService,
|
private domainSettingsService: DomainSettingsService,
|
||||||
private i18nService: I18nService,
|
private i18nService: I18nService,
|
||||||
private router: Router,
|
private router: Router,
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
import { Component, OnInit } from "@angular/core";
|
import { Component, OnInit } from "@angular/core";
|
||||||
import { firstValueFrom } from "rxjs";
|
import { firstValueFrom } from "rxjs";
|
||||||
|
|
||||||
import { SettingsService } from "@bitwarden/common/abstractions/settings.service";
|
|
||||||
import { AutofillSettingsServiceAbstraction } from "@bitwarden/common/autofill/services/autofill-settings.service";
|
import { AutofillSettingsServiceAbstraction } from "@bitwarden/common/autofill/services/autofill-settings.service";
|
||||||
import { BadgeSettingsServiceAbstraction } from "@bitwarden/common/autofill/services/badge-settings.service";
|
import { BadgeSettingsServiceAbstraction } from "@bitwarden/common/autofill/services/badge-settings.service";
|
||||||
import { DomainSettingsService } from "@bitwarden/common/autofill/services/domain-settings.service";
|
import { DomainSettingsService } from "@bitwarden/common/autofill/services/domain-settings.service";
|
||||||
@ -13,7 +12,6 @@ import {
|
|||||||
} from "@bitwarden/common/models/domain/domain-service";
|
} from "@bitwarden/common/models/domain/domain-service";
|
||||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||||
import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service";
|
import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service";
|
||||||
import { StateService } from "@bitwarden/common/platform/abstractions/state.service";
|
|
||||||
import { ThemeType } from "@bitwarden/common/platform/enums";
|
import { ThemeType } from "@bitwarden/common/platform/enums";
|
||||||
import { ThemeStateService } from "@bitwarden/common/platform/theming/theme-state.service";
|
import { ThemeStateService } from "@bitwarden/common/platform/theming/theme-state.service";
|
||||||
import { VaultSettingsService } from "@bitwarden/common/vault/abstractions/vault-settings/vault-settings.service";
|
import { VaultSettingsService } from "@bitwarden/common/vault/abstractions/vault-settings/vault-settings.service";
|
||||||
@ -51,14 +49,12 @@ export class OptionsComponent implements OnInit {
|
|||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private messagingService: MessagingService,
|
private messagingService: MessagingService,
|
||||||
private stateService: StateService,
|
|
||||||
private userNotificationSettingsService: UserNotificationSettingsServiceAbstraction,
|
private userNotificationSettingsService: UserNotificationSettingsServiceAbstraction,
|
||||||
private autofillSettingsService: AutofillSettingsServiceAbstraction,
|
private autofillSettingsService: AutofillSettingsServiceAbstraction,
|
||||||
private domainSettingsService: DomainSettingsService,
|
private domainSettingsService: DomainSettingsService,
|
||||||
private badgeSettingsService: BadgeSettingsServiceAbstraction,
|
private badgeSettingsService: BadgeSettingsServiceAbstraction,
|
||||||
i18nService: I18nService,
|
i18nService: I18nService,
|
||||||
private themeStateService: ThemeStateService,
|
private themeStateService: ThemeStateService,
|
||||||
private settingsService: SettingsService,
|
|
||||||
private vaultSettingsService: VaultSettingsService,
|
private vaultSettingsService: VaultSettingsService,
|
||||||
) {
|
) {
|
||||||
this.themeOptions = [
|
this.themeOptions = [
|
||||||
@ -114,12 +110,14 @@ export class OptionsComponent implements OnInit {
|
|||||||
this.autofillSettingsService.enableContextMenu$,
|
this.autofillSettingsService.enableContextMenu$,
|
||||||
);
|
);
|
||||||
|
|
||||||
this.showCardsCurrentTab = !(await this.stateService.getDontShowCardsCurrentTab());
|
this.showCardsCurrentTab = await firstValueFrom(this.vaultSettingsService.showCardsCurrentTab$);
|
||||||
this.showIdentitiesCurrentTab = !(await this.stateService.getDontShowIdentitiesCurrentTab());
|
this.showIdentitiesCurrentTab = await firstValueFrom(
|
||||||
|
this.vaultSettingsService.showIdentitiesCurrentTab$,
|
||||||
|
);
|
||||||
|
|
||||||
this.enableAutoTotpCopy = await firstValueFrom(this.autofillSettingsService.autoCopyTotp$);
|
this.enableAutoTotpCopy = await firstValueFrom(this.autofillSettingsService.autoCopyTotp$);
|
||||||
|
|
||||||
this.enableFavicon = !this.settingsService.getDisableFavicon();
|
this.enableFavicon = await firstValueFrom(this.domainSettingsService.showFavicons$);
|
||||||
|
|
||||||
this.enableBadgeCounter = await firstValueFrom(this.badgeSettingsService.enableBadgeCounter$);
|
this.enableBadgeCounter = await firstValueFrom(this.badgeSettingsService.enableBadgeCounter$);
|
||||||
|
|
||||||
@ -169,7 +167,7 @@ export class OptionsComponent implements OnInit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async updateFavicon() {
|
async updateFavicon() {
|
||||||
await this.settingsService.setDisableFavicon(!this.enableFavicon);
|
await this.domainSettingsService.setShowFavicons(this.enableFavicon);
|
||||||
}
|
}
|
||||||
|
|
||||||
async updateBadgeCounter() {
|
async updateBadgeCounter() {
|
||||||
@ -178,11 +176,11 @@ export class OptionsComponent implements OnInit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async updateShowCardsCurrentTab() {
|
async updateShowCardsCurrentTab() {
|
||||||
await this.stateService.setDontShowCardsCurrentTab(!this.showCardsCurrentTab);
|
await this.vaultSettingsService.setShowCardsCurrentTab(this.showCardsCurrentTab);
|
||||||
}
|
}
|
||||||
|
|
||||||
async updateShowIdentitiesCurrentTab() {
|
async updateShowIdentitiesCurrentTab() {
|
||||||
await this.stateService.setDontShowIdentitiesCurrentTab(!this.showIdentitiesCurrentTab);
|
await this.vaultSettingsService.setShowIdentitiesCurrentTab(this.showIdentitiesCurrentTab);
|
||||||
}
|
}
|
||||||
|
|
||||||
async saveTheme() {
|
async saveTheme() {
|
||||||
|
@ -12,7 +12,7 @@
|
|||||||
</header>
|
</header>
|
||||||
<main tabindex="-1">
|
<main tabindex="-1">
|
||||||
<div class="content">
|
<div class="content">
|
||||||
<ng-container *ngIf="!isPremium">
|
<ng-container *ngIf="!(isPremium$ | async)">
|
||||||
<p class="text-center lead">{{ "premiumNotCurrentMember" | i18n }}</p>
|
<p class="text-center lead">{{ "premiumNotCurrentMember" | i18n }}</p>
|
||||||
<p>{{ "premiumSignUpAndGet" | i18n }}</p>
|
<p>{{ "premiumSignUpAndGet" | i18n }}</p>
|
||||||
<ul class="bwi-ul">
|
<ul class="bwi-ul">
|
||||||
@ -61,7 +61,7 @@
|
|||||||
></i>
|
></i>
|
||||||
</button>
|
</button>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
<ng-container *ngIf="isPremium">
|
<ng-container *ngIf="isPremium$ | async">
|
||||||
<p class="text-center lead">{{ "premiumCurrentMember" | i18n }}</p>
|
<p class="text-center lead">{{ "premiumCurrentMember" | i18n }}</p>
|
||||||
<p class="text-center">{{ "premiumCurrentMemberThanks" | i18n }}</p>
|
<p class="text-center">{{ "premiumCurrentMemberThanks" | i18n }}</p>
|
||||||
<button type="button" class="btn block primary" (click)="manage()">
|
<button type="button" class="btn block primary" (click)="manage()">
|
||||||
|
@ -3,6 +3,7 @@ import { Component } from "@angular/core";
|
|||||||
|
|
||||||
import { PremiumComponent as BasePremiumComponent } from "@bitwarden/angular/vault/components/premium.component";
|
import { PremiumComponent as BasePremiumComponent } from "@bitwarden/angular/vault/components/premium.component";
|
||||||
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
||||||
|
import { BillingAccountProfileStateService } from "@bitwarden/common/billing/abstractions/account/billing-account-profile-state.service";
|
||||||
import { EnvironmentService } from "@bitwarden/common/platform/abstractions/environment.service";
|
import { EnvironmentService } from "@bitwarden/common/platform/abstractions/environment.service";
|
||||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||||
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
|
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
|
||||||
@ -27,6 +28,7 @@ export class PremiumComponent extends BasePremiumComponent {
|
|||||||
private currencyPipe: CurrencyPipe,
|
private currencyPipe: CurrencyPipe,
|
||||||
dialogService: DialogService,
|
dialogService: DialogService,
|
||||||
environmentService: EnvironmentService,
|
environmentService: EnvironmentService,
|
||||||
|
billingAccountProfileStateService: BillingAccountProfileStateService,
|
||||||
) {
|
) {
|
||||||
super(
|
super(
|
||||||
i18nService,
|
i18nService,
|
||||||
@ -36,6 +38,7 @@ export class PremiumComponent extends BasePremiumComponent {
|
|||||||
stateService,
|
stateService,
|
||||||
dialogService,
|
dialogService,
|
||||||
environmentService,
|
environmentService,
|
||||||
|
billingAccountProfileStateService,
|
||||||
);
|
);
|
||||||
|
|
||||||
// Support old price string. Can be removed in future once all translations are properly updated.
|
// Support old price string. Can be removed in future once all translations are properly updated.
|
||||||
|
@ -16,7 +16,6 @@ import {
|
|||||||
takeUntil,
|
takeUntil,
|
||||||
} from "rxjs";
|
} from "rxjs";
|
||||||
|
|
||||||
import { ModalService } from "@bitwarden/angular/services/modal.service";
|
|
||||||
import { FingerprintDialogComponent } from "@bitwarden/auth/angular";
|
import { FingerprintDialogComponent } from "@bitwarden/auth/angular";
|
||||||
import { VaultTimeoutSettingsService } from "@bitwarden/common/abstractions/vault-timeout/vault-timeout-settings.service";
|
import { VaultTimeoutSettingsService } from "@bitwarden/common/abstractions/vault-timeout/vault-timeout-settings.service";
|
||||||
import { VaultTimeoutService } from "@bitwarden/common/abstractions/vault-timeout/vault-timeout.service";
|
import { VaultTimeoutService } from "@bitwarden/common/abstractions/vault-timeout/vault-timeout.service";
|
||||||
@ -98,7 +97,6 @@ export class SettingsComponent implements OnInit {
|
|||||||
private environmentService: EnvironmentService,
|
private environmentService: EnvironmentService,
|
||||||
private cryptoService: CryptoService,
|
private cryptoService: CryptoService,
|
||||||
private stateService: StateService,
|
private stateService: StateService,
|
||||||
private modalService: ModalService,
|
|
||||||
private userVerificationService: UserVerificationService,
|
private userVerificationService: UserVerificationService,
|
||||||
private dialogService: DialogService,
|
private dialogService: DialogService,
|
||||||
private changeDetectorRef: ChangeDetectorRef,
|
private changeDetectorRef: ChangeDetectorRef,
|
||||||
|
@ -1,11 +0,0 @@
|
|||||||
import { BehaviorSubject } from "rxjs";
|
|
||||||
|
|
||||||
import { SettingsService } from "@bitwarden/common/services/settings.service";
|
|
||||||
|
|
||||||
import { browserSession, sessionSync } from "../platform/decorators/session-sync-observable";
|
|
||||||
|
|
||||||
@browserSession
|
|
||||||
export class BrowserSettingsService extends SettingsService {
|
|
||||||
@sessionSync({ initializer: (b: boolean) => b })
|
|
||||||
protected _disableFavicon: BehaviorSubject<boolean>;
|
|
||||||
}
|
|
@ -6,6 +6,7 @@ import { first } from "rxjs/operators";
|
|||||||
|
|
||||||
import { AddEditComponent as BaseAddEditComponent } from "@bitwarden/angular/tools/send/add-edit.component";
|
import { AddEditComponent as BaseAddEditComponent } from "@bitwarden/angular/tools/send/add-edit.component";
|
||||||
import { PolicyService } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction";
|
import { PolicyService } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction";
|
||||||
|
import { BillingAccountProfileStateService } from "@bitwarden/common/billing/abstractions/account/billing-account-profile-state.service";
|
||||||
import { EnvironmentService } from "@bitwarden/common/platform/abstractions/environment.service";
|
import { EnvironmentService } from "@bitwarden/common/platform/abstractions/environment.service";
|
||||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||||
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
|
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
|
||||||
@ -49,6 +50,7 @@ export class SendAddEditComponent extends BaseAddEditComponent {
|
|||||||
dialogService: DialogService,
|
dialogService: DialogService,
|
||||||
formBuilder: FormBuilder,
|
formBuilder: FormBuilder,
|
||||||
private filePopoutUtilsService: FilePopoutUtilsService,
|
private filePopoutUtilsService: FilePopoutUtilsService,
|
||||||
|
billingAccountProfileStateService: BillingAccountProfileStateService,
|
||||||
) {
|
) {
|
||||||
super(
|
super(
|
||||||
i18nService,
|
i18nService,
|
||||||
@ -63,6 +65,7 @@ export class SendAddEditComponent extends BaseAddEditComponent {
|
|||||||
sendApiService,
|
sendApiService,
|
||||||
dialogService,
|
dialogService,
|
||||||
formBuilder,
|
formBuilder,
|
||||||
|
billingAccountProfileStateService,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,10 +1,11 @@
|
|||||||
import { Component, EventEmitter, Input, Output } from "@angular/core";
|
import { Component, EventEmitter, Input, OnDestroy, OnInit, Output } from "@angular/core";
|
||||||
|
import { Subject, takeUntil } from "rxjs";
|
||||||
|
|
||||||
import { EventCollectionService } from "@bitwarden/common/abstractions/event/event-collection.service";
|
import { EventCollectionService } from "@bitwarden/common/abstractions/event/event-collection.service";
|
||||||
|
import { BillingAccountProfileStateService } from "@bitwarden/common/billing/abstractions/account/billing-account-profile-state.service";
|
||||||
import { EventType } from "@bitwarden/common/enums";
|
import { EventType } from "@bitwarden/common/enums";
|
||||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||||
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
||||||
import { StateService } from "@bitwarden/common/platform/abstractions/state.service";
|
|
||||||
import { TotpService } from "@bitwarden/common/vault/abstractions/totp.service";
|
import { TotpService } from "@bitwarden/common/vault/abstractions/totp.service";
|
||||||
import { CipherType } from "@bitwarden/common/vault/enums";
|
import { CipherType } from "@bitwarden/common/vault/enums";
|
||||||
import { CipherRepromptType } from "@bitwarden/common/vault/enums/cipher-reprompt-type";
|
import { CipherRepromptType } from "@bitwarden/common/vault/enums/cipher-reprompt-type";
|
||||||
@ -15,7 +16,7 @@ import { PasswordRepromptService } from "@bitwarden/vault";
|
|||||||
selector: "app-action-buttons",
|
selector: "app-action-buttons",
|
||||||
templateUrl: "action-buttons.component.html",
|
templateUrl: "action-buttons.component.html",
|
||||||
})
|
})
|
||||||
export class ActionButtonsComponent {
|
export class ActionButtonsComponent implements OnInit, OnDestroy {
|
||||||
@Output() onView = new EventEmitter<CipherView>();
|
@Output() onView = new EventEmitter<CipherView>();
|
||||||
@Output() launchEvent = new EventEmitter<CipherView>();
|
@Output() launchEvent = new EventEmitter<CipherView>();
|
||||||
@Input() cipher: CipherView;
|
@Input() cipher: CipherView;
|
||||||
@ -24,17 +25,28 @@ export class ActionButtonsComponent {
|
|||||||
cipherType = CipherType;
|
cipherType = CipherType;
|
||||||
userHasPremiumAccess = false;
|
userHasPremiumAccess = false;
|
||||||
|
|
||||||
|
private componentIsDestroyed$ = new Subject<boolean>();
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private i18nService: I18nService,
|
private i18nService: I18nService,
|
||||||
private platformUtilsService: PlatformUtilsService,
|
private platformUtilsService: PlatformUtilsService,
|
||||||
private eventCollectionService: EventCollectionService,
|
private eventCollectionService: EventCollectionService,
|
||||||
private totpService: TotpService,
|
private totpService: TotpService,
|
||||||
private stateService: StateService,
|
|
||||||
private passwordRepromptService: PasswordRepromptService,
|
private passwordRepromptService: PasswordRepromptService,
|
||||||
|
private billingAccountProfileStateService: BillingAccountProfileStateService,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
async ngOnInit() {
|
ngOnInit() {
|
||||||
this.userHasPremiumAccess = await this.stateService.getCanAccessPremium();
|
this.billingAccountProfileStateService.hasPremiumFromAnySource$
|
||||||
|
.pipe(takeUntil(this.componentIsDestroyed$))
|
||||||
|
.subscribe((canAccessPremium: boolean) => {
|
||||||
|
this.userHasPremiumAccess = canAccessPremium;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnDestroy() {
|
||||||
|
this.componentIsDestroyed$.next(true);
|
||||||
|
this.componentIsDestroyed$.complete();
|
||||||
}
|
}
|
||||||
|
|
||||||
launchCipher() {
|
launchCipher() {
|
||||||
|
@ -6,7 +6,6 @@ import { firstValueFrom } from "rxjs";
|
|||||||
import { DomainSettingsService } from "@bitwarden/common/autofill/services/domain-settings.service";
|
import { DomainSettingsService } from "@bitwarden/common/autofill/services/domain-settings.service";
|
||||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||||
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
||||||
import { StateService } from "@bitwarden/common/platform/abstractions/state.service";
|
|
||||||
import { Utils } from "@bitwarden/common/platform/misc/utils";
|
import { Utils } from "@bitwarden/common/platform/misc/utils";
|
||||||
|
|
||||||
import { BrowserFido2UserInterfaceSession } from "../../../fido2/browser-fido2-user-interface.service";
|
import { BrowserFido2UserInterfaceSession } from "../../../fido2/browser-fido2-user-interface.service";
|
||||||
@ -52,7 +51,6 @@ export class Fido2UseBrowserLinkComponent {
|
|||||||
protected fido2PopoutSessionData$ = fido2PopoutSessionData$();
|
protected fido2PopoutSessionData$ = fido2PopoutSessionData$();
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private stateService: StateService,
|
|
||||||
private domainSettingsService: DomainSettingsService,
|
private domainSettingsService: DomainSettingsService,
|
||||||
private platformUtilsService: PlatformUtilsService,
|
private platformUtilsService: PlatformUtilsService,
|
||||||
private i18nService: I18nService,
|
private i18nService: I18nService,
|
||||||
|
@ -5,6 +5,7 @@ import { first } from "rxjs/operators";
|
|||||||
|
|
||||||
import { AttachmentsComponent as BaseAttachmentsComponent } from "@bitwarden/angular/vault/components/attachments.component";
|
import { AttachmentsComponent as BaseAttachmentsComponent } from "@bitwarden/angular/vault/components/attachments.component";
|
||||||
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
||||||
|
import { BillingAccountProfileStateService } from "@bitwarden/common/billing/abstractions/account/billing-account-profile-state.service";
|
||||||
import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service";
|
import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service";
|
||||||
import { FileDownloadService } from "@bitwarden/common/platform/abstractions/file-download/file-download.service";
|
import { FileDownloadService } from "@bitwarden/common/platform/abstractions/file-download/file-download.service";
|
||||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||||
@ -34,6 +35,7 @@ export class AttachmentsComponent extends BaseAttachmentsComponent {
|
|||||||
logService: LogService,
|
logService: LogService,
|
||||||
fileDownloadService: FileDownloadService,
|
fileDownloadService: FileDownloadService,
|
||||||
dialogService: DialogService,
|
dialogService: DialogService,
|
||||||
|
billingAccountProfileStateService: BillingAccountProfileStateService,
|
||||||
) {
|
) {
|
||||||
super(
|
super(
|
||||||
cipherService,
|
cipherService,
|
||||||
@ -46,6 +48,7 @@ export class AttachmentsComponent extends BaseAttachmentsComponent {
|
|||||||
stateService,
|
stateService,
|
||||||
fileDownloadService,
|
fileDownloadService,
|
||||||
dialogService,
|
dialogService,
|
||||||
|
billingAccountProfileStateService,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10,10 +10,10 @@ import { AutofillSettingsServiceAbstraction } from "@bitwarden/common/autofill/s
|
|||||||
import { BroadcasterService } from "@bitwarden/common/platform/abstractions/broadcaster.service";
|
import { BroadcasterService } from "@bitwarden/common/platform/abstractions/broadcaster.service";
|
||||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||||
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
||||||
import { StateService } from "@bitwarden/common/platform/abstractions/state.service";
|
|
||||||
import { Utils } from "@bitwarden/common/platform/misc/utils";
|
import { Utils } from "@bitwarden/common/platform/misc/utils";
|
||||||
import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service";
|
import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service";
|
||||||
import { SyncService } from "@bitwarden/common/vault/abstractions/sync/sync.service.abstraction";
|
import { SyncService } from "@bitwarden/common/vault/abstractions/sync/sync.service.abstraction";
|
||||||
|
import { VaultSettingsService } from "@bitwarden/common/vault/abstractions/vault-settings/vault-settings.service";
|
||||||
import { CipherType } from "@bitwarden/common/vault/enums";
|
import { CipherType } from "@bitwarden/common/vault/enums";
|
||||||
import { CipherRepromptType } from "@bitwarden/common/vault/enums/cipher-reprompt-type";
|
import { CipherRepromptType } from "@bitwarden/common/vault/enums/cipher-reprompt-type";
|
||||||
import { CipherView } from "@bitwarden/common/vault/models/view/cipher.view";
|
import { CipherView } from "@bitwarden/common/vault/models/view/cipher.view";
|
||||||
@ -65,11 +65,11 @@ export class CurrentTabComponent implements OnInit, OnDestroy {
|
|||||||
private changeDetectorRef: ChangeDetectorRef,
|
private changeDetectorRef: ChangeDetectorRef,
|
||||||
private syncService: SyncService,
|
private syncService: SyncService,
|
||||||
private searchService: SearchService,
|
private searchService: SearchService,
|
||||||
private stateService: StateService,
|
|
||||||
private autofillSettingsService: AutofillSettingsServiceAbstraction,
|
private autofillSettingsService: AutofillSettingsServiceAbstraction,
|
||||||
private passwordRepromptService: PasswordRepromptService,
|
private passwordRepromptService: PasswordRepromptService,
|
||||||
private organizationService: OrganizationService,
|
private organizationService: OrganizationService,
|
||||||
private vaultFilterService: VaultFilterService,
|
private vaultFilterService: VaultFilterService,
|
||||||
|
private vaultSettingsService: VaultSettingsService,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
async ngOnInit() {
|
async ngOnInit() {
|
||||||
@ -271,9 +271,11 @@ export class CurrentTabComponent implements OnInit, OnDestroy {
|
|||||||
});
|
});
|
||||||
|
|
||||||
const otherTypes: CipherType[] = [];
|
const otherTypes: CipherType[] = [];
|
||||||
const dontShowCards = await this.stateService.getDontShowCardsCurrentTab();
|
const dontShowCards = !(await firstValueFrom(this.vaultSettingsService.showCardsCurrentTab$));
|
||||||
const dontShowIdentities = await this.stateService.getDontShowIdentitiesCurrentTab();
|
const dontShowIdentities = !(await firstValueFrom(
|
||||||
this.showOrganizations = this.organizationService.hasOrganizations();
|
this.vaultSettingsService.showIdentitiesCurrentTab$,
|
||||||
|
));
|
||||||
|
this.showOrganizations = await this.organizationService.hasOrganizations();
|
||||||
if (!dontShowCards) {
|
if (!dontShowCards) {
|
||||||
otherTypes.push(CipherType.Card);
|
otherTypes.push(CipherType.Card);
|
||||||
}
|
}
|
||||||
|
@ -74,7 +74,7 @@ export class VaultItemsComponent extends BaseVaultItemsComponent implements OnIn
|
|||||||
|
|
||||||
async ngOnInit() {
|
async ngOnInit() {
|
||||||
this.searchTypeSearch = !this.platformUtilsService.isSafari();
|
this.searchTypeSearch = !this.platformUtilsService.isSafari();
|
||||||
this.showOrganizations = this.organizationService.hasOrganizations();
|
this.showOrganizations = await this.organizationService.hasOrganizations();
|
||||||
this.vaultFilter = this.vaultFilterService.getVaultFilter();
|
this.vaultFilter = this.vaultFilterService.getVaultFilter();
|
||||||
// eslint-disable-next-line rxjs-angular/prefer-takeuntil, rxjs/no-async-subscribe
|
// eslint-disable-next-line rxjs-angular/prefer-takeuntil, rxjs/no-async-subscribe
|
||||||
this.route.queryParams.pipe(first()).subscribe(async (params) => {
|
this.route.queryParams.pipe(first()).subscribe(async (params) => {
|
||||||
|
@ -9,6 +9,7 @@ import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
|||||||
import { AuditService } from "@bitwarden/common/abstractions/audit.service";
|
import { AuditService } from "@bitwarden/common/abstractions/audit.service";
|
||||||
import { EventCollectionService } from "@bitwarden/common/abstractions/event/event-collection.service";
|
import { EventCollectionService } from "@bitwarden/common/abstractions/event/event-collection.service";
|
||||||
import { TokenService } from "@bitwarden/common/auth/abstractions/token.service";
|
import { TokenService } from "@bitwarden/common/auth/abstractions/token.service";
|
||||||
|
import { BillingAccountProfileStateService } from "@bitwarden/common/billing/abstractions/account/billing-account-profile-state.service";
|
||||||
import { BroadcasterService } from "@bitwarden/common/platform/abstractions/broadcaster.service";
|
import { BroadcasterService } from "@bitwarden/common/platform/abstractions/broadcaster.service";
|
||||||
import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service";
|
import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service";
|
||||||
import { FileDownloadService } from "@bitwarden/common/platform/abstractions/file-download/file-download.service";
|
import { FileDownloadService } from "@bitwarden/common/platform/abstractions/file-download/file-download.service";
|
||||||
@ -95,6 +96,7 @@ export class ViewComponent extends BaseViewComponent {
|
|||||||
fileDownloadService: FileDownloadService,
|
fileDownloadService: FileDownloadService,
|
||||||
dialogService: DialogService,
|
dialogService: DialogService,
|
||||||
datePipe: DatePipe,
|
datePipe: DatePipe,
|
||||||
|
billingAccountProfileStateService: BillingAccountProfileStateService,
|
||||||
) {
|
) {
|
||||||
super(
|
super(
|
||||||
cipherService,
|
cipherService,
|
||||||
@ -117,6 +119,7 @@ export class ViewComponent extends BaseViewComponent {
|
|||||||
fileDownloadService,
|
fileDownloadService,
|
||||||
dialogService,
|
dialogService,
|
||||||
datePipe,
|
datePipe,
|
||||||
|
billingAccountProfileStateService,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -203,6 +203,7 @@ export class LoginCommand {
|
|||||||
ssoCodeVerifier,
|
ssoCodeVerifier,
|
||||||
this.ssoRedirectUri,
|
this.ssoRedirectUri,
|
||||||
orgIdentifier,
|
orgIdentifier,
|
||||||
|
undefined, // email to look up 2FA token not required as CLI can't remember 2FA token
|
||||||
twoFactor,
|
twoFactor,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
@ -23,10 +23,12 @@ import { PolicyApiService } from "@bitwarden/common/admin-console/services/polic
|
|||||||
import { PolicyService } from "@bitwarden/common/admin-console/services/policy/policy.service";
|
import { PolicyService } from "@bitwarden/common/admin-console/services/policy/policy.service";
|
||||||
import { ProviderService } from "@bitwarden/common/admin-console/services/provider.service";
|
import { ProviderService } from "@bitwarden/common/admin-console/services/provider.service";
|
||||||
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
||||||
|
import { AvatarService as AvatarServiceAbstraction } from "@bitwarden/common/auth/abstractions/avatar.service";
|
||||||
import { DeviceTrustCryptoServiceAbstraction } from "@bitwarden/common/auth/abstractions/device-trust-crypto.service.abstraction";
|
import { DeviceTrustCryptoServiceAbstraction } from "@bitwarden/common/auth/abstractions/device-trust-crypto.service.abstraction";
|
||||||
import { DevicesApiServiceAbstraction } from "@bitwarden/common/auth/abstractions/devices-api.service.abstraction";
|
import { DevicesApiServiceAbstraction } from "@bitwarden/common/auth/abstractions/devices-api.service.abstraction";
|
||||||
import { AccountServiceImplementation } from "@bitwarden/common/auth/services/account.service";
|
import { AccountServiceImplementation } from "@bitwarden/common/auth/services/account.service";
|
||||||
import { AuthService } from "@bitwarden/common/auth/services/auth.service";
|
import { AuthService } from "@bitwarden/common/auth/services/auth.service";
|
||||||
|
import { AvatarService } from "@bitwarden/common/auth/services/avatar.service";
|
||||||
import { DeviceTrustCryptoService } from "@bitwarden/common/auth/services/device-trust-crypto.service.implementation";
|
import { DeviceTrustCryptoService } from "@bitwarden/common/auth/services/device-trust-crypto.service.implementation";
|
||||||
import { DevicesApiServiceImplementation } from "@bitwarden/common/auth/services/devices-api.service.implementation";
|
import { DevicesApiServiceImplementation } from "@bitwarden/common/auth/services/devices-api.service.implementation";
|
||||||
import { KeyConnectorService } from "@bitwarden/common/auth/services/key-connector.service";
|
import { KeyConnectorService } from "@bitwarden/common/auth/services/key-connector.service";
|
||||||
@ -39,6 +41,8 @@ import {
|
|||||||
DefaultDomainSettingsService,
|
DefaultDomainSettingsService,
|
||||||
DomainSettingsService,
|
DomainSettingsService,
|
||||||
} from "@bitwarden/common/autofill/services/domain-settings.service";
|
} from "@bitwarden/common/autofill/services/domain-settings.service";
|
||||||
|
import { BillingAccountProfileStateService } from "@bitwarden/common/billing/abstractions/account/billing-account-profile-state.service";
|
||||||
|
import { DefaultBillingAccountProfileStateService } from "@bitwarden/common/billing/services/account/billing-account-profile-state.service";
|
||||||
import { ClientType } from "@bitwarden/common/enums";
|
import { ClientType } from "@bitwarden/common/enums";
|
||||||
import { ConfigApiServiceAbstraction } from "@bitwarden/common/platform/abstractions/config/config-api.service.abstraction";
|
import { ConfigApiServiceAbstraction } from "@bitwarden/common/platform/abstractions/config/config-api.service.abstraction";
|
||||||
import { KeyGenerationService as KeyGenerationServiceAbstraction } from "@bitwarden/common/platform/abstractions/key-generation.service";
|
import { KeyGenerationService as KeyGenerationServiceAbstraction } from "@bitwarden/common/platform/abstractions/key-generation.service";
|
||||||
@ -86,7 +90,6 @@ import { AuditService } from "@bitwarden/common/services/audit.service";
|
|||||||
import { EventCollectionService } from "@bitwarden/common/services/event/event-collection.service";
|
import { EventCollectionService } from "@bitwarden/common/services/event/event-collection.service";
|
||||||
import { EventUploadService } from "@bitwarden/common/services/event/event-upload.service";
|
import { EventUploadService } from "@bitwarden/common/services/event/event-upload.service";
|
||||||
import { SearchService } from "@bitwarden/common/services/search.service";
|
import { SearchService } from "@bitwarden/common/services/search.service";
|
||||||
import { SettingsService } from "@bitwarden/common/services/settings.service";
|
|
||||||
import { VaultTimeoutSettingsService } from "@bitwarden/common/services/vault-timeout/vault-timeout-settings.service";
|
import { VaultTimeoutSettingsService } from "@bitwarden/common/services/vault-timeout/vault-timeout-settings.service";
|
||||||
import { VaultTimeoutService } from "@bitwarden/common/services/vault-timeout/vault-timeout.service";
|
import { VaultTimeoutService } from "@bitwarden/common/services/vault-timeout/vault-timeout.service";
|
||||||
import {
|
import {
|
||||||
@ -155,7 +158,6 @@ export class Main {
|
|||||||
appIdService: AppIdService;
|
appIdService: AppIdService;
|
||||||
apiService: NodeApiService;
|
apiService: NodeApiService;
|
||||||
environmentService: EnvironmentService;
|
environmentService: EnvironmentService;
|
||||||
settingsService: SettingsService;
|
|
||||||
cipherService: CipherService;
|
cipherService: CipherService;
|
||||||
folderService: InternalFolderService;
|
folderService: InternalFolderService;
|
||||||
organizationUserService: OrganizationUserService;
|
organizationUserService: OrganizationUserService;
|
||||||
@ -216,8 +218,10 @@ export class Main {
|
|||||||
derivedStateProvider: DerivedStateProvider;
|
derivedStateProvider: DerivedStateProvider;
|
||||||
stateProvider: StateProvider;
|
stateProvider: StateProvider;
|
||||||
loginStrategyService: LoginStrategyServiceAbstraction;
|
loginStrategyService: LoginStrategyServiceAbstraction;
|
||||||
|
avatarService: AvatarServiceAbstraction;
|
||||||
stateEventRunnerService: StateEventRunnerService;
|
stateEventRunnerService: StateEventRunnerService;
|
||||||
biometricStateService: BiometricStateService;
|
biometricStateService: BiometricStateService;
|
||||||
|
billingAccountProfileStateService: BillingAccountProfileStateService;
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
let p = null;
|
let p = null;
|
||||||
@ -291,8 +295,7 @@ export class Main {
|
|||||||
|
|
||||||
this.activeUserStateProvider = new DefaultActiveUserStateProvider(
|
this.activeUserStateProvider = new DefaultActiveUserStateProvider(
|
||||||
this.accountService,
|
this.accountService,
|
||||||
storageServiceProvider,
|
this.singleUserStateProvider,
|
||||||
stateEventRegistrarService,
|
|
||||||
);
|
);
|
||||||
|
|
||||||
this.derivedStateProvider = new DefaultDerivedStateProvider(
|
this.derivedStateProvider = new DefaultDerivedStateProvider(
|
||||||
@ -308,6 +311,13 @@ export class Main {
|
|||||||
|
|
||||||
this.environmentService = new EnvironmentService(this.stateProvider, this.accountService);
|
this.environmentService = new EnvironmentService(this.stateProvider, this.accountService);
|
||||||
|
|
||||||
|
this.tokenService = new TokenService(
|
||||||
|
this.singleUserStateProvider,
|
||||||
|
this.globalStateProvider,
|
||||||
|
this.platformUtilsService.supportsSecureStorage(),
|
||||||
|
this.secureStorageService,
|
||||||
|
);
|
||||||
|
|
||||||
const migrationRunner = new MigrationRunner(
|
const migrationRunner = new MigrationRunner(
|
||||||
this.storageService,
|
this.storageService,
|
||||||
this.logService,
|
this.logService,
|
||||||
@ -322,6 +332,7 @@ export class Main {
|
|||||||
new StateFactory(GlobalState, Account),
|
new StateFactory(GlobalState, Account),
|
||||||
this.accountService,
|
this.accountService,
|
||||||
this.environmentService,
|
this.environmentService,
|
||||||
|
this.tokenService,
|
||||||
migrationRunner,
|
migrationRunner,
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -339,7 +350,6 @@ export class Main {
|
|||||||
);
|
);
|
||||||
|
|
||||||
this.appIdService = new AppIdService(this.globalStateProvider);
|
this.appIdService = new AppIdService(this.globalStateProvider);
|
||||||
this.tokenService = new TokenService(this.stateService);
|
|
||||||
|
|
||||||
const customUserAgent =
|
const customUserAgent =
|
||||||
"Bitwarden_CLI/" +
|
"Bitwarden_CLI/" +
|
||||||
@ -352,6 +362,7 @@ export class Main {
|
|||||||
this.platformUtilsService,
|
this.platformUtilsService,
|
||||||
this.environmentService,
|
this.environmentService,
|
||||||
this.appIdService,
|
this.appIdService,
|
||||||
|
this.stateService,
|
||||||
async (expired: boolean) => await this.logout(),
|
async (expired: boolean) => await this.logout(),
|
||||||
customUserAgent,
|
customUserAgent,
|
||||||
);
|
);
|
||||||
@ -362,7 +373,6 @@ export class Main {
|
|||||||
|
|
||||||
this.containerService = new ContainerService(this.cryptoService, this.encryptService);
|
this.containerService = new ContainerService(this.cryptoService, this.encryptService);
|
||||||
|
|
||||||
this.settingsService = new SettingsService(this.stateService);
|
|
||||||
this.domainSettingsService = new DefaultDomainSettingsService(this.stateProvider);
|
this.domainSettingsService = new DefaultDomainSettingsService(this.stateProvider);
|
||||||
|
|
||||||
this.fileUploadService = new FileUploadService(this.logService);
|
this.fileUploadService = new FileUploadService(this.logService);
|
||||||
@ -397,7 +407,7 @@ export class Main {
|
|||||||
|
|
||||||
this.providerService = new ProviderService(this.stateProvider);
|
this.providerService = new ProviderService(this.stateProvider);
|
||||||
|
|
||||||
this.organizationService = new OrganizationService(this.stateService, this.stateProvider);
|
this.organizationService = new OrganizationService(this.stateProvider);
|
||||||
|
|
||||||
this.organizationUserService = new OrganizationUserServiceImplementation(this.apiService);
|
this.organizationUserService = new OrganizationUserServiceImplementation(this.apiService);
|
||||||
|
|
||||||
@ -446,6 +456,10 @@ export class Main {
|
|||||||
this.stateService,
|
this.stateService,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
this.billingAccountProfileStateService = new DefaultBillingAccountProfileStateService(
|
||||||
|
this.activeUserStateProvider,
|
||||||
|
);
|
||||||
|
|
||||||
this.loginStrategyService = new LoginStrategyService(
|
this.loginStrategyService = new LoginStrategyService(
|
||||||
this.cryptoService,
|
this.cryptoService,
|
||||||
this.apiService,
|
this.apiService,
|
||||||
@ -465,6 +479,7 @@ export class Main {
|
|||||||
this.deviceTrustCryptoService,
|
this.deviceTrustCryptoService,
|
||||||
this.authRequestService,
|
this.authRequestService,
|
||||||
this.globalStateProvider,
|
this.globalStateProvider,
|
||||||
|
this.billingAccountProfileStateService,
|
||||||
);
|
);
|
||||||
|
|
||||||
this.authService = new AuthService(
|
this.authService = new AuthService(
|
||||||
@ -555,6 +570,8 @@ export class Main {
|
|||||||
null,
|
null,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
this.avatarService = new AvatarService(this.apiService, this.stateProvider);
|
||||||
|
|
||||||
this.syncService = new SyncService(
|
this.syncService = new SyncService(
|
||||||
this.apiService,
|
this.apiService,
|
||||||
this.domainSettingsService,
|
this.domainSettingsService,
|
||||||
@ -572,7 +589,9 @@ export class Main {
|
|||||||
this.folderApiService,
|
this.folderApiService,
|
||||||
this.organizationService,
|
this.organizationService,
|
||||||
this.sendApiService,
|
this.sendApiService,
|
||||||
|
this.avatarService,
|
||||||
async (expired: boolean) => await this.logout(),
|
async (expired: boolean) => await this.logout(),
|
||||||
|
this.billingAccountProfileStateService,
|
||||||
);
|
);
|
||||||
|
|
||||||
this.totpService = new TotpService(this.cryptoFunctionService, this.logService);
|
this.totpService = new TotpService(this.cryptoFunctionService, this.logService);
|
||||||
@ -619,15 +638,17 @@ export class Main {
|
|||||||
|
|
||||||
this.eventUploadService = new EventUploadService(
|
this.eventUploadService = new EventUploadService(
|
||||||
this.apiService,
|
this.apiService,
|
||||||
this.stateService,
|
this.stateProvider,
|
||||||
this.logService,
|
this.logService,
|
||||||
|
this.accountService,
|
||||||
);
|
);
|
||||||
|
|
||||||
this.eventCollectionService = new EventCollectionService(
|
this.eventCollectionService = new EventCollectionService(
|
||||||
this.cipherService,
|
this.cipherService,
|
||||||
this.stateService,
|
this.stateProvider,
|
||||||
this.organizationService,
|
this.organizationService,
|
||||||
this.eventUploadService,
|
this.eventUploadService,
|
||||||
|
this.accountService,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -651,6 +672,7 @@ export class Main {
|
|||||||
});
|
});
|
||||||
const userId = await this.stateService.getUserId();
|
const userId = await this.stateService.getUserId();
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
|
this.eventUploadService.uploadEvents(userId as UserId),
|
||||||
this.syncService.setLastSync(new Date(0)),
|
this.syncService.setLastSync(new Date(0)),
|
||||||
this.cryptoService.clearKeys(),
|
this.cryptoService.clearKeys(),
|
||||||
this.cipherService.clear(userId),
|
this.cipherService.clear(userId),
|
||||||
|
@ -1,9 +1,12 @@
|
|||||||
|
import { firstValueFrom } from "rxjs";
|
||||||
|
|
||||||
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
||||||
import { AuditService } from "@bitwarden/common/abstractions/audit.service";
|
import { AuditService } from "@bitwarden/common/abstractions/audit.service";
|
||||||
import { EventCollectionService } from "@bitwarden/common/abstractions/event/event-collection.service";
|
import { EventCollectionService } from "@bitwarden/common/abstractions/event/event-collection.service";
|
||||||
import { SearchService } from "@bitwarden/common/abstractions/search.service";
|
import { SearchService } from "@bitwarden/common/abstractions/search.service";
|
||||||
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
||||||
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
|
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
|
||||||
|
import { BillingAccountProfileStateService } from "@bitwarden/common/billing/abstractions/account/billing-account-profile-state.service";
|
||||||
import { EventType } from "@bitwarden/common/enums";
|
import { EventType } from "@bitwarden/common/enums";
|
||||||
import { CardExport } from "@bitwarden/common/models/export/card.export";
|
import { CardExport } from "@bitwarden/common/models/export/card.export";
|
||||||
import { CipherExport } from "@bitwarden/common/models/export/cipher.export";
|
import { CipherExport } from "@bitwarden/common/models/export/cipher.export";
|
||||||
@ -57,6 +60,7 @@ export class GetCommand extends DownloadCommand {
|
|||||||
private apiService: ApiService,
|
private apiService: ApiService,
|
||||||
private organizationService: OrganizationService,
|
private organizationService: OrganizationService,
|
||||||
private eventCollectionService: EventCollectionService,
|
private eventCollectionService: EventCollectionService,
|
||||||
|
private accountProfileService: BillingAccountProfileStateService,
|
||||||
) {
|
) {
|
||||||
super(cryptoService);
|
super(cryptoService);
|
||||||
}
|
}
|
||||||
@ -251,7 +255,9 @@ export class GetCommand extends DownloadCommand {
|
|||||||
return Response.error("Couldn't generate TOTP code.");
|
return Response.error("Couldn't generate TOTP code.");
|
||||||
}
|
}
|
||||||
|
|
||||||
const canAccessPremium = await this.stateService.getCanAccessPremium();
|
const canAccessPremium = await firstValueFrom(
|
||||||
|
this.accountProfileService.hasPremiumFromAnySource$,
|
||||||
|
);
|
||||||
if (!canAccessPremium) {
|
if (!canAccessPremium) {
|
||||||
const originalCipher = await this.cipherService.get(cipher.id);
|
const originalCipher = await this.cipherService.get(cipher.id);
|
||||||
if (
|
if (
|
||||||
@ -334,7 +340,10 @@ export class GetCommand extends DownloadCommand {
|
|||||||
return Response.multipleResults(attachments.map((a) => a.id));
|
return Response.multipleResults(attachments.map((a) => a.id));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(await this.stateService.getCanAccessPremium())) {
|
const canAccessPremium = await firstValueFrom(
|
||||||
|
this.accountProfileService.hasPremiumFromAnySource$,
|
||||||
|
);
|
||||||
|
if (!canAccessPremium) {
|
||||||
const originalCipher = await this.cipherService.get(cipher.id);
|
const originalCipher = await this.cipherService.get(cipher.id);
|
||||||
if (originalCipher == null || originalCipher.organizationId == null) {
|
if (originalCipher == null || originalCipher.organizationId == null) {
|
||||||
return Response.error("Premium status is required to use this feature.");
|
return Response.error("Premium status is required to use this feature.");
|
||||||
|
@ -68,6 +68,7 @@ export class ServeCommand {
|
|||||||
this.main.apiService,
|
this.main.apiService,
|
||||||
this.main.organizationService,
|
this.main.organizationService,
|
||||||
this.main.eventCollectionService,
|
this.main.eventCollectionService,
|
||||||
|
this.main.billingAccountProfileStateService,
|
||||||
);
|
);
|
||||||
this.listCommand = new ListCommand(
|
this.listCommand = new ListCommand(
|
||||||
this.main.cipherService,
|
this.main.cipherService,
|
||||||
@ -82,10 +83,10 @@ export class ServeCommand {
|
|||||||
this.createCommand = new CreateCommand(
|
this.createCommand = new CreateCommand(
|
||||||
this.main.cipherService,
|
this.main.cipherService,
|
||||||
this.main.folderService,
|
this.main.folderService,
|
||||||
this.main.stateService,
|
|
||||||
this.main.cryptoService,
|
this.main.cryptoService,
|
||||||
this.main.apiService,
|
this.main.apiService,
|
||||||
this.main.folderApiService,
|
this.main.folderApiService,
|
||||||
|
this.main.billingAccountProfileStateService,
|
||||||
);
|
);
|
||||||
this.editCommand = new EditCommand(
|
this.editCommand = new EditCommand(
|
||||||
this.main.cipherService,
|
this.main.cipherService,
|
||||||
@ -108,9 +109,9 @@ export class ServeCommand {
|
|||||||
this.deleteCommand = new DeleteCommand(
|
this.deleteCommand = new DeleteCommand(
|
||||||
this.main.cipherService,
|
this.main.cipherService,
|
||||||
this.main.folderService,
|
this.main.folderService,
|
||||||
this.main.stateService,
|
|
||||||
this.main.apiService,
|
this.main.apiService,
|
||||||
this.main.folderApiService,
|
this.main.folderApiService,
|
||||||
|
this.main.billingAccountProfileStateService,
|
||||||
);
|
);
|
||||||
this.confirmCommand = new ConfirmCommand(
|
this.confirmCommand = new ConfirmCommand(
|
||||||
this.main.apiService,
|
this.main.apiService,
|
||||||
@ -135,9 +136,9 @@ export class ServeCommand {
|
|||||||
|
|
||||||
this.sendCreateCommand = new SendCreateCommand(
|
this.sendCreateCommand = new SendCreateCommand(
|
||||||
this.main.sendService,
|
this.main.sendService,
|
||||||
this.main.stateService,
|
|
||||||
this.main.environmentService,
|
this.main.environmentService,
|
||||||
this.main.sendApiService,
|
this.main.sendApiService,
|
||||||
|
this.main.billingAccountProfileStateService,
|
||||||
);
|
);
|
||||||
this.sendDeleteCommand = new SendDeleteCommand(this.main.sendService, this.main.sendApiService);
|
this.sendDeleteCommand = new SendDeleteCommand(this.main.sendService, this.main.sendApiService);
|
||||||
this.sendGetCommand = new SendGetCommand(
|
this.sendGetCommand = new SendGetCommand(
|
||||||
@ -148,9 +149,9 @@ export class ServeCommand {
|
|||||||
);
|
);
|
||||||
this.sendEditCommand = new SendEditCommand(
|
this.sendEditCommand = new SendEditCommand(
|
||||||
this.main.sendService,
|
this.main.sendService,
|
||||||
this.main.stateService,
|
|
||||||
this.sendGetCommand,
|
this.sendGetCommand,
|
||||||
this.main.sendApiService,
|
this.main.sendApiService,
|
||||||
|
this.main.billingAccountProfileStateService,
|
||||||
);
|
);
|
||||||
this.sendListCommand = new SendListCommand(
|
this.sendListCommand = new SendListCommand(
|
||||||
this.main.sendService,
|
this.main.sendService,
|
||||||
|
@ -6,6 +6,7 @@ import { TokenService } from "@bitwarden/common/auth/abstractions/token.service"
|
|||||||
import { AppIdService } from "@bitwarden/common/platform/abstractions/app-id.service";
|
import { AppIdService } from "@bitwarden/common/platform/abstractions/app-id.service";
|
||||||
import { EnvironmentService } from "@bitwarden/common/platform/abstractions/environment.service";
|
import { EnvironmentService } from "@bitwarden/common/platform/abstractions/environment.service";
|
||||||
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
||||||
|
import { StateService } from "@bitwarden/common/platform/abstractions/state.service";
|
||||||
import { ApiService } from "@bitwarden/common/services/api.service";
|
import { ApiService } from "@bitwarden/common/services/api.service";
|
||||||
|
|
||||||
(global as any).fetch = fe.default;
|
(global as any).fetch = fe.default;
|
||||||
@ -20,6 +21,7 @@ export class NodeApiService extends ApiService {
|
|||||||
platformUtilsService: PlatformUtilsService,
|
platformUtilsService: PlatformUtilsService,
|
||||||
environmentService: EnvironmentService,
|
environmentService: EnvironmentService,
|
||||||
appIdService: AppIdService,
|
appIdService: AppIdService,
|
||||||
|
stateService: StateService,
|
||||||
logoutCallback: (expired: boolean) => Promise<void>,
|
logoutCallback: (expired: boolean) => Promise<void>,
|
||||||
customUserAgent: string = null,
|
customUserAgent: string = null,
|
||||||
) {
|
) {
|
||||||
@ -28,6 +30,7 @@ export class NodeApiService extends ApiService {
|
|||||||
platformUtilsService,
|
platformUtilsService,
|
||||||
environmentService,
|
environmentService,
|
||||||
appIdService,
|
appIdService,
|
||||||
|
stateService,
|
||||||
logoutCallback,
|
logoutCallback,
|
||||||
customUserAgent,
|
customUserAgent,
|
||||||
);
|
);
|
||||||
|
@ -1,6 +1,9 @@
|
|||||||
import { StateService } from "@bitwarden/common/platform/abstractions/state.service";
|
import { StateService } from "@bitwarden/common/platform/abstractions/state.service";
|
||||||
import { DefaultPassphraseGenerationOptions } from "@bitwarden/common/tools/generator/passphrase";
|
import { DefaultPassphraseGenerationOptions } from "@bitwarden/common/tools/generator/passphrase";
|
||||||
import { PasswordGenerationServiceAbstraction } from "@bitwarden/common/tools/generator/password";
|
import {
|
||||||
|
DefaultPasswordGenerationOptions,
|
||||||
|
PasswordGenerationServiceAbstraction,
|
||||||
|
} from "@bitwarden/common/tools/generator/password";
|
||||||
import { PasswordGeneratorOptions } from "@bitwarden/common/tools/generator/password/password-generator-options";
|
import { PasswordGeneratorOptions } from "@bitwarden/common/tools/generator/password/password-generator-options";
|
||||||
|
|
||||||
import { Response } from "../models/response";
|
import { Response } from "../models/response";
|
||||||
@ -64,7 +67,10 @@ class Options {
|
|||||||
this.capitalize = CliUtils.convertBooleanOption(passedOptions?.capitalize);
|
this.capitalize = CliUtils.convertBooleanOption(passedOptions?.capitalize);
|
||||||
this.includeNumber = CliUtils.convertBooleanOption(passedOptions?.includeNumber);
|
this.includeNumber = CliUtils.convertBooleanOption(passedOptions?.includeNumber);
|
||||||
this.ambiguous = CliUtils.convertBooleanOption(passedOptions?.ambiguous);
|
this.ambiguous = CliUtils.convertBooleanOption(passedOptions?.ambiguous);
|
||||||
this.length = CliUtils.convertNumberOption(passedOptions?.length, 14);
|
this.length = CliUtils.convertNumberOption(
|
||||||
|
passedOptions?.length,
|
||||||
|
DefaultPasswordGenerationOptions.length,
|
||||||
|
);
|
||||||
this.type = passedOptions?.passphrase ? "passphrase" : "password";
|
this.type = passedOptions?.passphrase ? "passphrase" : "password";
|
||||||
this.separator = CliUtils.convertStringOption(
|
this.separator = CliUtils.convertStringOption(
|
||||||
passedOptions?.separator,
|
passedOptions?.separator,
|
||||||
@ -74,8 +80,14 @@ class Options {
|
|||||||
passedOptions?.words,
|
passedOptions?.words,
|
||||||
DefaultPassphraseGenerationOptions.numWords,
|
DefaultPassphraseGenerationOptions.numWords,
|
||||||
);
|
);
|
||||||
this.minNumber = CliUtils.convertNumberOption(passedOptions?.minNumber, 1);
|
this.minNumber = CliUtils.convertNumberOption(
|
||||||
this.minSpecial = CliUtils.convertNumberOption(passedOptions?.minSpecial, 1);
|
passedOptions?.minNumber,
|
||||||
|
DefaultPasswordGenerationOptions.minNumber,
|
||||||
|
);
|
||||||
|
this.minSpecial = CliUtils.convertNumberOption(
|
||||||
|
passedOptions?.minSpecial,
|
||||||
|
DefaultPasswordGenerationOptions.minSpecial,
|
||||||
|
);
|
||||||
|
|
||||||
if (!this.uppercase && !this.lowercase && !this.special && !this.number) {
|
if (!this.uppercase && !this.lowercase && !this.special && !this.number) {
|
||||||
this.lowercase = true;
|
this.lowercase = true;
|
||||||
|
@ -1,8 +1,10 @@
|
|||||||
import * as fs from "fs";
|
import * as fs from "fs";
|
||||||
import * as path from "path";
|
import * as path from "path";
|
||||||
|
|
||||||
|
import { firstValueFrom } from "rxjs";
|
||||||
|
|
||||||
|
import { BillingAccountProfileStateService } from "@bitwarden/common/billing/abstractions/account/billing-account-profile-state.service";
|
||||||
import { EnvironmentService } from "@bitwarden/common/platform/abstractions/environment.service";
|
import { EnvironmentService } from "@bitwarden/common/platform/abstractions/environment.service";
|
||||||
import { StateService } from "@bitwarden/common/platform/abstractions/state.service";
|
|
||||||
import { SendType } from "@bitwarden/common/tools/send/enums/send-type";
|
import { SendType } from "@bitwarden/common/tools/send/enums/send-type";
|
||||||
import { SendApiService } from "@bitwarden/common/tools/send/services/send-api.service.abstraction";
|
import { SendApiService } from "@bitwarden/common/tools/send/services/send-api.service.abstraction";
|
||||||
import { SendService } from "@bitwarden/common/tools/send/services/send.service.abstraction";
|
import { SendService } from "@bitwarden/common/tools/send/services/send.service.abstraction";
|
||||||
@ -16,9 +18,9 @@ import { SendResponse } from "../models/send.response";
|
|||||||
export class SendCreateCommand {
|
export class SendCreateCommand {
|
||||||
constructor(
|
constructor(
|
||||||
private sendService: SendService,
|
private sendService: SendService,
|
||||||
private stateService: StateService,
|
|
||||||
private environmentService: EnvironmentService,
|
private environmentService: EnvironmentService,
|
||||||
private sendApiService: SendApiService,
|
private sendApiService: SendApiService,
|
||||||
|
private accountProfileService: BillingAccountProfileStateService,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
async run(requestJson: any, cmdOptions: Record<string, any>) {
|
async run(requestJson: any, cmdOptions: Record<string, any>) {
|
||||||
@ -82,7 +84,7 @@ export class SendCreateCommand {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(await this.stateService.getCanAccessPremium())) {
|
if (!(await firstValueFrom(this.accountProfileService.hasPremiumFromAnySource$))) {
|
||||||
return Response.error("Premium status is required to use this feature.");
|
return Response.error("Premium status is required to use this feature.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
import { StateService } from "@bitwarden/common/platform/abstractions/state.service";
|
import { firstValueFrom } from "rxjs";
|
||||||
|
|
||||||
|
import { BillingAccountProfileStateService } from "@bitwarden/common/billing/abstractions/account/billing-account-profile-state.service";
|
||||||
import { SendType } from "@bitwarden/common/tools/send/enums/send-type";
|
import { SendType } from "@bitwarden/common/tools/send/enums/send-type";
|
||||||
import { SendApiService } from "@bitwarden/common/tools/send/services/send-api.service.abstraction";
|
import { SendApiService } from "@bitwarden/common/tools/send/services/send-api.service.abstraction";
|
||||||
import { SendService } from "@bitwarden/common/tools/send/services/send.service.abstraction";
|
import { SendService } from "@bitwarden/common/tools/send/services/send.service.abstraction";
|
||||||
@ -12,9 +14,9 @@ import { SendGetCommand } from "./get.command";
|
|||||||
export class SendEditCommand {
|
export class SendEditCommand {
|
||||||
constructor(
|
constructor(
|
||||||
private sendService: SendService,
|
private sendService: SendService,
|
||||||
private stateService: StateService,
|
|
||||||
private getCommand: SendGetCommand,
|
private getCommand: SendGetCommand,
|
||||||
private sendApiService: SendApiService,
|
private sendApiService: SendApiService,
|
||||||
|
private accountProfileService: BillingAccountProfileStateService,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
async run(requestJson: string, cmdOptions: Record<string, any>): Promise<Response> {
|
async run(requestJson: string, cmdOptions: Record<string, any>): Promise<Response> {
|
||||||
@ -57,7 +59,10 @@ export class SendEditCommand {
|
|||||||
return Response.badRequest("Cannot change a Send's type");
|
return Response.badRequest("Cannot change a Send's type");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (send.type === SendType.File && !(await this.stateService.getCanAccessPremium())) {
|
const canAccessPremium = await firstValueFrom(
|
||||||
|
this.accountProfileService.hasPremiumFromAnySource$,
|
||||||
|
);
|
||||||
|
if (send.type === SendType.File && !canAccessPremium) {
|
||||||
return Response.error("Premium status is required to use this feature.");
|
return Response.error("Premium status is required to use this feature.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -153,6 +153,7 @@ export class SendProgram extends Program {
|
|||||||
this.main.apiService,
|
this.main.apiService,
|
||||||
this.main.organizationService,
|
this.main.organizationService,
|
||||||
this.main.eventCollectionService,
|
this.main.eventCollectionService,
|
||||||
|
this.main.billingAccountProfileStateService,
|
||||||
);
|
);
|
||||||
const response = await cmd.run("template", object, null);
|
const response = await cmd.run("template", object, null);
|
||||||
this.processResponse(response);
|
this.processResponse(response);
|
||||||
@ -253,9 +254,9 @@ export class SendProgram extends Program {
|
|||||||
);
|
);
|
||||||
const cmd = new SendEditCommand(
|
const cmd = new SendEditCommand(
|
||||||
this.main.sendService,
|
this.main.sendService,
|
||||||
this.main.stateService,
|
|
||||||
getCmd,
|
getCmd,
|
||||||
this.main.sendApiService,
|
this.main.sendApiService,
|
||||||
|
this.main.billingAccountProfileStateService,
|
||||||
);
|
);
|
||||||
const response = await cmd.run(encodedJson, options);
|
const response = await cmd.run(encodedJson, options);
|
||||||
this.processResponse(response);
|
this.processResponse(response);
|
||||||
@ -323,9 +324,9 @@ export class SendProgram extends Program {
|
|||||||
await this.exitIfLocked();
|
await this.exitIfLocked();
|
||||||
const cmd = new SendCreateCommand(
|
const cmd = new SendCreateCommand(
|
||||||
this.main.sendService,
|
this.main.sendService,
|
||||||
this.main.stateService,
|
|
||||||
this.main.environmentService,
|
this.main.environmentService,
|
||||||
this.main.sendApiService,
|
this.main.sendApiService,
|
||||||
|
this.main.billingAccountProfileStateService,
|
||||||
);
|
);
|
||||||
return await cmd.run(encodedJson, options);
|
return await cmd.run(encodedJson, options);
|
||||||
}
|
}
|
||||||
|
@ -188,6 +188,7 @@ export class VaultProgram extends Program {
|
|||||||
this.main.apiService,
|
this.main.apiService,
|
||||||
this.main.organizationService,
|
this.main.organizationService,
|
||||||
this.main.eventCollectionService,
|
this.main.eventCollectionService,
|
||||||
|
this.main.billingAccountProfileStateService,
|
||||||
);
|
);
|
||||||
const response = await command.run(object, id, cmd);
|
const response = await command.run(object, id, cmd);
|
||||||
this.processResponse(response);
|
this.processResponse(response);
|
||||||
@ -226,10 +227,10 @@ export class VaultProgram extends Program {
|
|||||||
const command = new CreateCommand(
|
const command = new CreateCommand(
|
||||||
this.main.cipherService,
|
this.main.cipherService,
|
||||||
this.main.folderService,
|
this.main.folderService,
|
||||||
this.main.stateService,
|
|
||||||
this.main.cryptoService,
|
this.main.cryptoService,
|
||||||
this.main.apiService,
|
this.main.apiService,
|
||||||
this.main.folderApiService,
|
this.main.folderApiService,
|
||||||
|
this.main.billingAccountProfileStateService,
|
||||||
);
|
);
|
||||||
const response = await command.run(object, encodedJson, cmd);
|
const response = await command.run(object, encodedJson, cmd);
|
||||||
this.processResponse(response);
|
this.processResponse(response);
|
||||||
@ -313,9 +314,9 @@ export class VaultProgram extends Program {
|
|||||||
const command = new DeleteCommand(
|
const command = new DeleteCommand(
|
||||||
this.main.cipherService,
|
this.main.cipherService,
|
||||||
this.main.folderService,
|
this.main.folderService,
|
||||||
this.main.stateService,
|
|
||||||
this.main.apiService,
|
this.main.apiService,
|
||||||
this.main.folderApiService,
|
this.main.folderApiService,
|
||||||
|
this.main.billingAccountProfileStateService,
|
||||||
);
|
);
|
||||||
const response = await command.run(object, id, cmd);
|
const response = await command.run(object, id, cmd);
|
||||||
this.processResponse(response);
|
this.processResponse(response);
|
||||||
|
@ -1,13 +1,15 @@
|
|||||||
import * as fs from "fs";
|
import * as fs from "fs";
|
||||||
import * as path from "path";
|
import * as path from "path";
|
||||||
|
|
||||||
|
import { firstValueFrom } from "rxjs";
|
||||||
|
|
||||||
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
||||||
import { SelectionReadOnlyRequest } from "@bitwarden/common/admin-console/models/request/selection-read-only.request";
|
import { SelectionReadOnlyRequest } from "@bitwarden/common/admin-console/models/request/selection-read-only.request";
|
||||||
|
import { BillingAccountProfileStateService } from "@bitwarden/common/billing/abstractions/account/billing-account-profile-state.service";
|
||||||
import { CipherExport } from "@bitwarden/common/models/export/cipher.export";
|
import { CipherExport } from "@bitwarden/common/models/export/cipher.export";
|
||||||
import { CollectionExport } from "@bitwarden/common/models/export/collection.export";
|
import { CollectionExport } from "@bitwarden/common/models/export/collection.export";
|
||||||
import { FolderExport } from "@bitwarden/common/models/export/folder.export";
|
import { FolderExport } from "@bitwarden/common/models/export/folder.export";
|
||||||
import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service";
|
import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service";
|
||||||
import { StateService } from "@bitwarden/common/platform/abstractions/state.service";
|
|
||||||
import { Utils } from "@bitwarden/common/platform/misc/utils";
|
import { Utils } from "@bitwarden/common/platform/misc/utils";
|
||||||
import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service";
|
import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service";
|
||||||
import { FolderApiServiceAbstraction } from "@bitwarden/common/vault/abstractions/folder/folder-api.service.abstraction";
|
import { FolderApiServiceAbstraction } from "@bitwarden/common/vault/abstractions/folder/folder-api.service.abstraction";
|
||||||
@ -26,10 +28,10 @@ export class CreateCommand {
|
|||||||
constructor(
|
constructor(
|
||||||
private cipherService: CipherService,
|
private cipherService: CipherService,
|
||||||
private folderService: FolderService,
|
private folderService: FolderService,
|
||||||
private stateService: StateService,
|
|
||||||
private cryptoService: CryptoService,
|
private cryptoService: CryptoService,
|
||||||
private apiService: ApiService,
|
private apiService: ApiService,
|
||||||
private folderApiService: FolderApiServiceAbstraction,
|
private folderApiService: FolderApiServiceAbstraction,
|
||||||
|
private accountProfileService: BillingAccountProfileStateService,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
async run(
|
async run(
|
||||||
@ -124,7 +126,10 @@ export class CreateCommand {
|
|||||||
return Response.notFound();
|
return Response.notFound();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cipher.organizationId == null && !(await this.stateService.getCanAccessPremium())) {
|
if (
|
||||||
|
cipher.organizationId == null &&
|
||||||
|
!(await firstValueFrom(this.accountProfileService.hasPremiumFromAnySource$))
|
||||||
|
) {
|
||||||
return Response.error("Premium status is required to use this feature.");
|
return Response.error("Premium status is required to use this feature.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
|
import { firstValueFrom } from "rxjs";
|
||||||
|
|
||||||
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
||||||
import { StateService } from "@bitwarden/common/platform/abstractions/state.service";
|
import { BillingAccountProfileStateService } from "@bitwarden/common/billing/abstractions/account/billing-account-profile-state.service";
|
||||||
import { Utils } from "@bitwarden/common/platform/misc/utils";
|
import { Utils } from "@bitwarden/common/platform/misc/utils";
|
||||||
import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service";
|
import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service";
|
||||||
import { FolderApiServiceAbstraction } from "@bitwarden/common/vault/abstractions/folder/folder-api.service.abstraction";
|
import { FolderApiServiceAbstraction } from "@bitwarden/common/vault/abstractions/folder/folder-api.service.abstraction";
|
||||||
@ -12,9 +14,9 @@ export class DeleteCommand {
|
|||||||
constructor(
|
constructor(
|
||||||
private cipherService: CipherService,
|
private cipherService: CipherService,
|
||||||
private folderService: FolderService,
|
private folderService: FolderService,
|
||||||
private stateService: StateService,
|
|
||||||
private apiService: ApiService,
|
private apiService: ApiService,
|
||||||
private folderApiService: FolderApiServiceAbstraction,
|
private folderApiService: FolderApiServiceAbstraction,
|
||||||
|
private accountProfileService: BillingAccountProfileStateService,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
async run(object: string, id: string, cmdOptions: Record<string, any>): Promise<Response> {
|
async run(object: string, id: string, cmdOptions: Record<string, any>): Promise<Response> {
|
||||||
@ -75,7 +77,10 @@ export class DeleteCommand {
|
|||||||
return Response.error("Attachment `" + id + "` was not found.");
|
return Response.error("Attachment `" + id + "` was not found.");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cipher.organizationId == null && !(await this.stateService.getCanAccessPremium())) {
|
const canAccessPremium = await firstValueFrom(
|
||||||
|
this.accountProfileService.hasPremiumFromAnySource$,
|
||||||
|
);
|
||||||
|
if (cipher.organizationId == null && !canAccessPremium) {
|
||||||
return Response.error("Premium status is required to use this feature.");
|
return Response.error("Premium status is required to use this feature.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
77
apps/desktop/desktop_native/Cargo.lock
generated
77
apps/desktop/desktop_native/Cargo.lock
generated
@ -130,12 +130,6 @@ version = "0.6.7"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e1e5f035d16fc623ae5f74981db80a439803888314e3a555fd6f04acd51a3205"
|
checksum = "e1e5f035d16fc623ae5f74981db80a439803888314e3a555fd6f04acd51a3205"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "bytes"
|
|
||||||
version = "1.5.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cbc"
|
name = "cbc"
|
||||||
version = "0.1.2"
|
version = "0.1.2"
|
||||||
@ -333,7 +327,6 @@ dependencies = [
|
|||||||
"security-framework-sys",
|
"security-framework-sys",
|
||||||
"sha2",
|
"sha2",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
"tokio",
|
|
||||||
"typenum",
|
"typenum",
|
||||||
"widestring",
|
"widestring",
|
||||||
"windows",
|
"windows",
|
||||||
@ -377,7 +370,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245"
|
checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
"windows-sys 0.52.0",
|
"windows-sys",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -772,17 +765,6 @@ dependencies = [
|
|||||||
"adler",
|
"adler",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "mio"
|
|
||||||
version = "0.8.9"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "3dce281c5e46beae905d4de1870d8b1509a9142b62eedf18b443b011ca8343d0"
|
|
||||||
dependencies = [
|
|
||||||
"libc",
|
|
||||||
"wasi",
|
|
||||||
"windows-sys 0.48.0",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "napi"
|
name = "napi"
|
||||||
version = "2.13.3"
|
version = "2.13.3"
|
||||||
@ -925,7 +907,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "57119c3b893986491ec9aa85056780d3a0f3cf4da7cc09dd3650dbd6c6738fb9"
|
checksum = "57119c3b893986491ec9aa85056780d3a0f3cf4da7cc09dd3650dbd6c6738fb9"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
"windows-sys 0.52.0",
|
"windows-sys",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -1114,7 +1096,7 @@ dependencies = [
|
|||||||
"errno",
|
"errno",
|
||||||
"libc",
|
"libc",
|
||||||
"linux-raw-sys",
|
"linux-raw-sys",
|
||||||
"windows-sys 0.52.0",
|
"windows-sys",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -1204,15 +1186,6 @@ dependencies = [
|
|||||||
"digest",
|
"digest",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "signal-hook-registry"
|
|
||||||
version = "1.4.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1"
|
|
||||||
dependencies = [
|
|
||||||
"libc",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "slab"
|
name = "slab"
|
||||||
version = "0.4.9"
|
version = "0.4.9"
|
||||||
@ -1228,16 +1201,6 @@ version = "1.13.1"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e6ecd384b10a64542d77071bd64bd7b231f4ed5940fba55e98c3de13824cf3d7"
|
checksum = "e6ecd384b10a64542d77071bd64bd7b231f4ed5940fba55e98c3de13824cf3d7"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "socket2"
|
|
||||||
version = "0.5.5"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "7b5fac59a5cb5dd637972e5fca70daf0523c9067fcdc4842f053dae04a18f8e9"
|
|
||||||
dependencies = [
|
|
||||||
"libc",
|
|
||||||
"windows-sys 0.48.0",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "str-buf"
|
name = "str-buf"
|
||||||
version = "1.0.6"
|
version = "1.0.6"
|
||||||
@ -1295,7 +1258,7 @@ dependencies = [
|
|||||||
"fastrand",
|
"fastrand",
|
||||||
"redox_syscall",
|
"redox_syscall",
|
||||||
"rustix",
|
"rustix",
|
||||||
"windows-sys 0.52.0",
|
"windows-sys",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -1329,32 +1292,13 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tokio"
|
name = "tokio"
|
||||||
version = "1.32.0"
|
version = "1.36.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "17ed6077ed6cd6c74735e21f37eb16dc3935f96878b1fe961074089cc80893f9"
|
checksum = "61285f6515fa018fb2d1e46eb21223fff441ee8db5d0f1435e8ab4f5cdb80931"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"backtrace",
|
"backtrace",
|
||||||
"bytes",
|
|
||||||
"libc",
|
|
||||||
"mio",
|
|
||||||
"num_cpus",
|
"num_cpus",
|
||||||
"parking_lot",
|
|
||||||
"pin-project-lite",
|
"pin-project-lite",
|
||||||
"signal-hook-registry",
|
|
||||||
"socket2",
|
|
||||||
"tokio-macros",
|
|
||||||
"windows-sys 0.48.0",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "tokio-macros"
|
|
||||||
version = "2.1.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e"
|
|
||||||
dependencies = [
|
|
||||||
"proc-macro2",
|
|
||||||
"quote",
|
|
||||||
"syn 2.0.38",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -1606,15 +1550,6 @@ dependencies = [
|
|||||||
"windows-targets 0.52.4",
|
"windows-targets 0.52.4",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "windows-sys"
|
|
||||||
version = "0.48.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
|
|
||||||
dependencies = [
|
|
||||||
"windows-targets 0.48.5",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows-sys"
|
name = "windows-sys"
|
||||||
version = "0.52.0"
|
version = "0.52.0"
|
||||||
|
@ -25,7 +25,6 @@ retry = "=2.0.0"
|
|||||||
scopeguard = "=1.2.0"
|
scopeguard = "=1.2.0"
|
||||||
sha2 = "=0.10.8"
|
sha2 = "=0.10.8"
|
||||||
thiserror = "=1.0.51"
|
thiserror = "=1.0.51"
|
||||||
tokio = { version = "=1.32.0", features = ["full"] }
|
|
||||||
typenum = "=1.17.0"
|
typenum = "=1.17.0"
|
||||||
|
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
|
@ -24,7 +24,7 @@
|
|||||||
"**/node_modules/argon2/package.json",
|
"**/node_modules/argon2/package.json",
|
||||||
"**/node_modules/argon2/lib/binding/napi-v3/argon2.node"
|
"**/node_modules/argon2/lib/binding/napi-v3/argon2.node"
|
||||||
],
|
],
|
||||||
"electronVersion": "28.2.6",
|
"electronVersion": "28.2.7",
|
||||||
"generateUpdatesFilesForAllChannels": true,
|
"generateUpdatesFilesForAllChannels": true,
|
||||||
"publish": {
|
"publish": {
|
||||||
"provider": "generic",
|
"provider": "generic",
|
||||||
|
@ -3,13 +3,12 @@ import { FormBuilder } from "@angular/forms";
|
|||||||
import { BehaviorSubject, firstValueFrom, Observable, Subject } from "rxjs";
|
import { BehaviorSubject, firstValueFrom, Observable, Subject } from "rxjs";
|
||||||
import { concatMap, debounceTime, filter, map, switchMap, takeUntil, tap } from "rxjs/operators";
|
import { concatMap, debounceTime, filter, map, switchMap, takeUntil, tap } from "rxjs/operators";
|
||||||
|
|
||||||
import { ModalService } from "@bitwarden/angular/services/modal.service";
|
|
||||||
import { SettingsService } from "@bitwarden/common/abstractions/settings.service";
|
|
||||||
import { VaultTimeoutSettingsService } from "@bitwarden/common/abstractions/vault-timeout/vault-timeout-settings.service";
|
import { VaultTimeoutSettingsService } from "@bitwarden/common/abstractions/vault-timeout/vault-timeout-settings.service";
|
||||||
import { PolicyService } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction";
|
import { PolicyService } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction";
|
||||||
import { PolicyType } from "@bitwarden/common/admin-console/enums";
|
import { PolicyType } from "@bitwarden/common/admin-console/enums";
|
||||||
import { UserVerificationService as UserVerificationServiceAbstraction } from "@bitwarden/common/auth/abstractions/user-verification/user-verification.service.abstraction";
|
import { UserVerificationService as UserVerificationServiceAbstraction } from "@bitwarden/common/auth/abstractions/user-verification/user-verification.service.abstraction";
|
||||||
import { AutofillSettingsServiceAbstraction } from "@bitwarden/common/autofill/services/autofill-settings.service";
|
import { AutofillSettingsServiceAbstraction } from "@bitwarden/common/autofill/services/autofill-settings.service";
|
||||||
|
import { DomainSettingsService } from "@bitwarden/common/autofill/services/domain-settings.service";
|
||||||
import { DeviceType } from "@bitwarden/common/enums";
|
import { DeviceType } from "@bitwarden/common/enums";
|
||||||
import { VaultTimeoutAction } from "@bitwarden/common/enums/vault-timeout-action.enum";
|
import { VaultTimeoutAction } from "@bitwarden/common/enums/vault-timeout-action.enum";
|
||||||
import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service";
|
import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service";
|
||||||
@ -115,9 +114,8 @@ export class SettingsComponent implements OnInit {
|
|||||||
private autofillSettingsService: AutofillSettingsServiceAbstraction,
|
private autofillSettingsService: AutofillSettingsServiceAbstraction,
|
||||||
private messagingService: MessagingService,
|
private messagingService: MessagingService,
|
||||||
private cryptoService: CryptoService,
|
private cryptoService: CryptoService,
|
||||||
private modalService: ModalService,
|
|
||||||
private themeStateService: ThemeStateService,
|
private themeStateService: ThemeStateService,
|
||||||
private settingsService: SettingsService,
|
private domainSettingsService: DomainSettingsService,
|
||||||
private dialogService: DialogService,
|
private dialogService: DialogService,
|
||||||
private userVerificationService: UserVerificationServiceAbstraction,
|
private userVerificationService: UserVerificationServiceAbstraction,
|
||||||
private biometricStateService: BiometricStateService,
|
private biometricStateService: BiometricStateService,
|
||||||
@ -251,7 +249,7 @@ export class SettingsComponent implements OnInit {
|
|||||||
approveLoginRequests: (await this.stateService.getApproveLoginRequests()) ?? false,
|
approveLoginRequests: (await this.stateService.getApproveLoginRequests()) ?? false,
|
||||||
clearClipboard: await firstValueFrom(this.autofillSettingsService.clearClipboardDelay$),
|
clearClipboard: await firstValueFrom(this.autofillSettingsService.clearClipboardDelay$),
|
||||||
minimizeOnCopyToClipboard: await this.stateService.getMinimizeOnCopyToClipboard(),
|
minimizeOnCopyToClipboard: await this.stateService.getMinimizeOnCopyToClipboard(),
|
||||||
enableFavicons: !(await this.stateService.getDisableFavicon()),
|
enableFavicons: await firstValueFrom(this.domainSettingsService.showFavicons$),
|
||||||
enableTray: await this.stateService.getEnableTray(),
|
enableTray: await this.stateService.getEnableTray(),
|
||||||
enableMinToTray: await this.stateService.getEnableMinimizeToTray(),
|
enableMinToTray: await this.stateService.getEnableMinimizeToTray(),
|
||||||
enableCloseToTray: await this.stateService.getEnableCloseToTray(),
|
enableCloseToTray: await this.stateService.getEnableCloseToTray(),
|
||||||
@ -498,7 +496,7 @@ export class SettingsComponent implements OnInit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async saveFavicons() {
|
async saveFavicons() {
|
||||||
await this.settingsService.setDisableFavicon(!this.form.value.enableFavicons);
|
await this.domainSettingsService.setShowFavicons(this.form.value.enableFavicons);
|
||||||
this.messagingService.send("refreshCiphers");
|
this.messagingService.send("refreshCiphers");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -19,9 +19,9 @@ import { FingerprintDialogComponent } from "@bitwarden/auth/angular";
|
|||||||
import { EventUploadService } from "@bitwarden/common/abstractions/event/event-upload.service";
|
import { EventUploadService } from "@bitwarden/common/abstractions/event/event-upload.service";
|
||||||
import { NotificationsService } from "@bitwarden/common/abstractions/notifications.service";
|
import { NotificationsService } from "@bitwarden/common/abstractions/notifications.service";
|
||||||
import { SearchService } from "@bitwarden/common/abstractions/search.service";
|
import { SearchService } from "@bitwarden/common/abstractions/search.service";
|
||||||
import { SettingsService } from "@bitwarden/common/abstractions/settings.service";
|
|
||||||
import { VaultTimeoutSettingsService } from "@bitwarden/common/abstractions/vault-timeout/vault-timeout-settings.service";
|
import { VaultTimeoutSettingsService } from "@bitwarden/common/abstractions/vault-timeout/vault-timeout-settings.service";
|
||||||
import { VaultTimeoutService } from "@bitwarden/common/abstractions/vault-timeout/vault-timeout.service";
|
import { VaultTimeoutService } from "@bitwarden/common/abstractions/vault-timeout/vault-timeout.service";
|
||||||
|
import { InternalOrganizationServiceAbstraction } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
||||||
import { InternalPolicyService } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction";
|
import { InternalPolicyService } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction";
|
||||||
import { ProviderService } from "@bitwarden/common/admin-console/abstractions/provider.service";
|
import { ProviderService } from "@bitwarden/common/admin-console/abstractions/provider.service";
|
||||||
import { AuthService } from "@bitwarden/common/auth/abstractions/auth.service";
|
import { AuthService } from "@bitwarden/common/auth/abstractions/auth.service";
|
||||||
@ -122,7 +122,6 @@ export class AppComponent implements OnInit, OnDestroy {
|
|||||||
constructor(
|
constructor(
|
||||||
private broadcasterService: BroadcasterService,
|
private broadcasterService: BroadcasterService,
|
||||||
private folderService: InternalFolderService,
|
private folderService: InternalFolderService,
|
||||||
private settingsService: SettingsService,
|
|
||||||
private syncService: SyncService,
|
private syncService: SyncService,
|
||||||
private passwordGenerationService: PasswordGenerationServiceAbstraction,
|
private passwordGenerationService: PasswordGenerationServiceAbstraction,
|
||||||
private cipherService: CipherService,
|
private cipherService: CipherService,
|
||||||
@ -153,6 +152,7 @@ export class AppComponent implements OnInit, OnDestroy {
|
|||||||
private biometricStateService: BiometricStateService,
|
private biometricStateService: BiometricStateService,
|
||||||
private stateEventRunnerService: StateEventRunnerService,
|
private stateEventRunnerService: StateEventRunnerService,
|
||||||
private providerService: ProviderService,
|
private providerService: ProviderService,
|
||||||
|
private organizationService: InternalOrganizationServiceAbstraction,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
@ -574,7 +574,8 @@ export class AppComponent implements OnInit, OnDestroy {
|
|||||||
|
|
||||||
let preLogoutActiveUserId;
|
let preLogoutActiveUserId;
|
||||||
try {
|
try {
|
||||||
await this.eventUploadService.uploadEvents(userBeingLoggedOut);
|
// Provide the userId of the user to upload events for
|
||||||
|
await this.eventUploadService.uploadEvents(userBeingLoggedOut as UserId);
|
||||||
await this.syncService.setLastSync(new Date(0), userBeingLoggedOut);
|
await this.syncService.setLastSync(new Date(0), userBeingLoggedOut);
|
||||||
await this.cryptoService.clearKeys(userBeingLoggedOut);
|
await this.cryptoService.clearKeys(userBeingLoggedOut);
|
||||||
await this.cipherService.clear(userBeingLoggedOut);
|
await this.cipherService.clear(userBeingLoggedOut);
|
||||||
|
@ -2,9 +2,10 @@ import { animate, state, style, transition, trigger } from "@angular/animations"
|
|||||||
import { ConnectedPosition } from "@angular/cdk/overlay";
|
import { ConnectedPosition } from "@angular/cdk/overlay";
|
||||||
import { Component, OnDestroy, OnInit } from "@angular/core";
|
import { Component, OnDestroy, OnInit } from "@angular/core";
|
||||||
import { Router } from "@angular/router";
|
import { Router } from "@angular/router";
|
||||||
import { concatMap, Subject, takeUntil } from "rxjs";
|
import { concatMap, firstValueFrom, Subject, takeUntil } from "rxjs";
|
||||||
|
|
||||||
import { AuthService } from "@bitwarden/common/auth/abstractions/auth.service";
|
import { AuthService } from "@bitwarden/common/auth/abstractions/auth.service";
|
||||||
|
import { AvatarService } from "@bitwarden/common/auth/abstractions/avatar.service";
|
||||||
import { TokenService } from "@bitwarden/common/auth/abstractions/token.service";
|
import { TokenService } from "@bitwarden/common/auth/abstractions/token.service";
|
||||||
import { AuthenticationStatus } from "@bitwarden/common/auth/enums/authentication-status";
|
import { AuthenticationStatus } from "@bitwarden/common/auth/enums/authentication-status";
|
||||||
import { EnvironmentService } from "@bitwarden/common/platform/abstractions/environment.service";
|
import { EnvironmentService } from "@bitwarden/common/platform/abstractions/environment.service";
|
||||||
@ -12,6 +13,7 @@ import { MessagingService } from "@bitwarden/common/platform/abstractions/messag
|
|||||||
import { StateService } from "@bitwarden/common/platform/abstractions/state.service";
|
import { StateService } from "@bitwarden/common/platform/abstractions/state.service";
|
||||||
import { Utils } from "@bitwarden/common/platform/misc/utils";
|
import { Utils } from "@bitwarden/common/platform/misc/utils";
|
||||||
import { Account } from "@bitwarden/common/platform/models/domain/account";
|
import { Account } from "@bitwarden/common/platform/models/domain/account";
|
||||||
|
import { UserId } from "@bitwarden/common/types/guid";
|
||||||
|
|
||||||
type ActiveAccount = {
|
type ActiveAccount = {
|
||||||
id: string;
|
id: string;
|
||||||
@ -84,6 +86,7 @@ export class AccountSwitcherComponent implements OnInit, OnDestroy {
|
|||||||
constructor(
|
constructor(
|
||||||
private stateService: StateService,
|
private stateService: StateService,
|
||||||
private authService: AuthService,
|
private authService: AuthService,
|
||||||
|
private avatarService: AvatarService,
|
||||||
private messagingService: MessagingService,
|
private messagingService: MessagingService,
|
||||||
private router: Router,
|
private router: Router,
|
||||||
private tokenService: TokenService,
|
private tokenService: TokenService,
|
||||||
@ -101,7 +104,7 @@ export class AccountSwitcherComponent implements OnInit, OnDestroy {
|
|||||||
id: await this.tokenService.getUserId(),
|
id: await this.tokenService.getUserId(),
|
||||||
name: (await this.tokenService.getName()) ?? (await this.tokenService.getEmail()),
|
name: (await this.tokenService.getName()) ?? (await this.tokenService.getEmail()),
|
||||||
email: await this.tokenService.getEmail(),
|
email: await this.tokenService.getEmail(),
|
||||||
avatarColor: await this.stateService.getAvatarColor(),
|
avatarColor: await firstValueFrom(this.avatarService.avatarColor$),
|
||||||
server: await this.environmentService.getHost(),
|
server: await this.environmentService.getHost(),
|
||||||
};
|
};
|
||||||
} catch {
|
} catch {
|
||||||
@ -154,7 +157,7 @@ export class AccountSwitcherComponent implements OnInit, OnDestroy {
|
|||||||
name: baseAccounts[userId].profile.name,
|
name: baseAccounts[userId].profile.name,
|
||||||
email: baseAccounts[userId].profile.email,
|
email: baseAccounts[userId].profile.email,
|
||||||
authenticationStatus: await this.authService.getAuthStatus(userId),
|
authenticationStatus: await this.authService.getAuthStatus(userId),
|
||||||
avatarColor: await this.stateService.getAvatarColor({ userId: userId }),
|
avatarColor: await firstValueFrom(this.avatarService.getUserAvatarColor$(userId as UserId)),
|
||||||
server: await this.environmentService.getHost(userId),
|
server: await this.environmentService.getHost(userId),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -10,6 +10,7 @@ import {
|
|||||||
OBSERVABLE_MEMORY_STORAGE,
|
OBSERVABLE_MEMORY_STORAGE,
|
||||||
OBSERVABLE_DISK_STORAGE,
|
OBSERVABLE_DISK_STORAGE,
|
||||||
WINDOW,
|
WINDOW,
|
||||||
|
SUPPORTS_SECURE_STORAGE,
|
||||||
SYSTEM_THEME_OBSERVABLE,
|
SYSTEM_THEME_OBSERVABLE,
|
||||||
} from "@bitwarden/angular/services/injection-tokens";
|
} from "@bitwarden/angular/services/injection-tokens";
|
||||||
import { JslibServicesModule } from "@bitwarden/angular/services/jslib-services.module";
|
import { JslibServicesModule } from "@bitwarden/angular/services/jslib-services.module";
|
||||||
@ -18,6 +19,7 @@ import { PolicyService as PolicyServiceAbstraction } from "@bitwarden/common/adm
|
|||||||
import { AccountService as AccountServiceAbstraction } from "@bitwarden/common/auth/abstractions/account.service";
|
import { AccountService as AccountServiceAbstraction } from "@bitwarden/common/auth/abstractions/account.service";
|
||||||
import { AuthService as AuthServiceAbstraction } from "@bitwarden/common/auth/abstractions/auth.service";
|
import { AuthService as AuthServiceAbstraction } from "@bitwarden/common/auth/abstractions/auth.service";
|
||||||
import { LoginService as LoginServiceAbstraction } from "@bitwarden/common/auth/abstractions/login.service";
|
import { LoginService as LoginServiceAbstraction } from "@bitwarden/common/auth/abstractions/login.service";
|
||||||
|
import { TokenService } from "@bitwarden/common/auth/abstractions/token.service";
|
||||||
import { LoginService } from "@bitwarden/common/auth/services/login.service";
|
import { LoginService } from "@bitwarden/common/auth/services/login.service";
|
||||||
import { AutofillSettingsServiceAbstraction } from "@bitwarden/common/autofill/services/autofill-settings.service";
|
import { AutofillSettingsServiceAbstraction } from "@bitwarden/common/autofill/services/autofill-settings.service";
|
||||||
import { BroadcasterService as BroadcasterServiceAbstraction } from "@bitwarden/common/platform/abstractions/broadcaster.service";
|
import { BroadcasterService as BroadcasterServiceAbstraction } from "@bitwarden/common/platform/abstractions/broadcaster.service";
|
||||||
@ -54,7 +56,10 @@ import { LoginGuard } from "../../auth/guards/login.guard";
|
|||||||
import { Account } from "../../models/account";
|
import { Account } from "../../models/account";
|
||||||
import { ElectronCryptoService } from "../../platform/services/electron-crypto.service";
|
import { ElectronCryptoService } from "../../platform/services/electron-crypto.service";
|
||||||
import { ElectronLogRendererService } from "../../platform/services/electron-log.renderer.service";
|
import { ElectronLogRendererService } from "../../platform/services/electron-log.renderer.service";
|
||||||
import { ElectronPlatformUtilsService } from "../../platform/services/electron-platform-utils.service";
|
import {
|
||||||
|
ELECTRON_SUPPORTS_SECURE_STORAGE,
|
||||||
|
ElectronPlatformUtilsService,
|
||||||
|
} from "../../platform/services/electron-platform-utils.service";
|
||||||
import { ElectronRendererMessagingService } from "../../platform/services/electron-renderer-messaging.service";
|
import { ElectronRendererMessagingService } from "../../platform/services/electron-renderer-messaging.service";
|
||||||
import { ElectronRendererSecureStorageService } from "../../platform/services/electron-renderer-secure-storage.service";
|
import { ElectronRendererSecureStorageService } from "../../platform/services/electron-renderer-secure-storage.service";
|
||||||
import { ElectronRendererStorageService } from "../../platform/services/electron-renderer-storage.service";
|
import { ElectronRendererStorageService } from "../../platform/services/electron-renderer-storage.service";
|
||||||
@ -101,6 +106,13 @@ const RELOAD_CALLBACK = new InjectionToken<() => any>("RELOAD_CALLBACK");
|
|||||||
useClass: ElectronPlatformUtilsService,
|
useClass: ElectronPlatformUtilsService,
|
||||||
deps: [I18nServiceAbstraction, MessagingServiceAbstraction],
|
deps: [I18nServiceAbstraction, MessagingServiceAbstraction],
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
// We manually override the value of SUPPORTS_SECURE_STORAGE here to avoid
|
||||||
|
// the TokenService having to inject the PlatformUtilsService which introduces a
|
||||||
|
// circular dependency on Desktop only.
|
||||||
|
provide: SUPPORTS_SECURE_STORAGE,
|
||||||
|
useValue: ELECTRON_SUPPORTS_SECURE_STORAGE,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
provide: I18nServiceAbstraction,
|
provide: I18nServiceAbstraction,
|
||||||
useClass: I18nRendererService,
|
useClass: I18nRendererService,
|
||||||
@ -140,6 +152,7 @@ const RELOAD_CALLBACK = new InjectionToken<() => any>("RELOAD_CALLBACK");
|
|||||||
STATE_FACTORY,
|
STATE_FACTORY,
|
||||||
AccountServiceAbstraction,
|
AccountServiceAbstraction,
|
||||||
EnvironmentService,
|
EnvironmentService,
|
||||||
|
TokenService,
|
||||||
MigrationRunner,
|
MigrationRunner,
|
||||||
STATE_SERVICE_USE_CACHE,
|
STATE_SERVICE_USE_CACHE,
|
||||||
],
|
],
|
||||||
@ -170,7 +183,6 @@ const RELOAD_CALLBACK = new InjectionToken<() => any>("RELOAD_CALLBACK");
|
|||||||
CryptoServiceAbstraction,
|
CryptoServiceAbstraction,
|
||||||
CryptoFunctionServiceAbstraction,
|
CryptoFunctionServiceAbstraction,
|
||||||
MessagingServiceAbstraction,
|
MessagingServiceAbstraction,
|
||||||
I18nServiceAbstraction,
|
|
||||||
EncryptedMessageHandlerService,
|
EncryptedMessageHandlerService,
|
||||||
DialogService,
|
DialogService,
|
||||||
],
|
],
|
||||||
|
@ -4,6 +4,7 @@ import { FormBuilder } from "@angular/forms";
|
|||||||
|
|
||||||
import { AddEditComponent as BaseAddEditComponent } from "@bitwarden/angular/tools/send/add-edit.component";
|
import { AddEditComponent as BaseAddEditComponent } from "@bitwarden/angular/tools/send/add-edit.component";
|
||||||
import { PolicyService } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction";
|
import { PolicyService } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction";
|
||||||
|
import { BillingAccountProfileStateService } from "@bitwarden/common/billing/abstractions/account/billing-account-profile-state.service";
|
||||||
import { EnvironmentService } from "@bitwarden/common/platform/abstractions/environment.service";
|
import { EnvironmentService } from "@bitwarden/common/platform/abstractions/environment.service";
|
||||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||||
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
|
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
|
||||||
@ -32,6 +33,7 @@ export class AddEditComponent extends BaseAddEditComponent {
|
|||||||
sendApiService: SendApiService,
|
sendApiService: SendApiService,
|
||||||
dialogService: DialogService,
|
dialogService: DialogService,
|
||||||
formBuilder: FormBuilder,
|
formBuilder: FormBuilder,
|
||||||
|
billingAccountProfileStateService: BillingAccountProfileStateService,
|
||||||
) {
|
) {
|
||||||
super(
|
super(
|
||||||
i18nService,
|
i18nService,
|
||||||
@ -46,6 +48,7 @@ export class AddEditComponent extends BaseAddEditComponent {
|
|||||||
sendApiService,
|
sendApiService,
|
||||||
dialogService,
|
dialogService,
|
||||||
formBuilder,
|
formBuilder,
|
||||||
|
billingAccountProfileStateService,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,6 +3,7 @@ import { Router } from "@angular/router";
|
|||||||
|
|
||||||
import { TwoFactorOptionsComponent as BaseTwoFactorOptionsComponent } from "@bitwarden/angular/auth/components/two-factor-options.component";
|
import { TwoFactorOptionsComponent as BaseTwoFactorOptionsComponent } from "@bitwarden/angular/auth/components/two-factor-options.component";
|
||||||
import { TwoFactorService } from "@bitwarden/common/auth/abstractions/two-factor.service";
|
import { TwoFactorService } from "@bitwarden/common/auth/abstractions/two-factor.service";
|
||||||
|
import { EnvironmentService } from "@bitwarden/common/platform/abstractions/environment.service";
|
||||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||||
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
||||||
|
|
||||||
@ -16,7 +17,8 @@ export class TwoFactorOptionsComponent extends BaseTwoFactorOptionsComponent {
|
|||||||
router: Router,
|
router: Router,
|
||||||
i18nService: I18nService,
|
i18nService: I18nService,
|
||||||
platformUtilsService: PlatformUtilsService,
|
platformUtilsService: PlatformUtilsService,
|
||||||
|
environmentService: EnvironmentService,
|
||||||
) {
|
) {
|
||||||
super(twoFactorService, router, i18nService, platformUtilsService, window);
|
super(twoFactorService, router, i18nService, platformUtilsService, window, environmentService);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,9 @@ import * as path from "path";
|
|||||||
|
|
||||||
import { app } from "electron";
|
import { app } from "electron";
|
||||||
|
|
||||||
|
import { TokenService as TokenServiceAbstraction } from "@bitwarden/common/auth/abstractions/token.service";
|
||||||
import { AccountServiceImplementation } from "@bitwarden/common/auth/services/account.service";
|
import { AccountServiceImplementation } from "@bitwarden/common/auth/services/account.service";
|
||||||
|
import { TokenService } from "@bitwarden/common/auth/services/token.service";
|
||||||
import { StateService } from "@bitwarden/common/platform/abstractions/state.service";
|
import { StateService } from "@bitwarden/common/platform/abstractions/state.service";
|
||||||
import { DefaultBiometricStateService } from "@bitwarden/common/platform/biometrics/biometric-state.service";
|
import { DefaultBiometricStateService } from "@bitwarden/common/platform/biometrics/biometric-state.service";
|
||||||
import { StateFactory } from "@bitwarden/common/platform/factories/state-factory";
|
import { StateFactory } from "@bitwarden/common/platform/factories/state-factory";
|
||||||
@ -36,6 +38,7 @@ import { ClipboardMain } from "./platform/main/clipboard.main";
|
|||||||
import { DesktopCredentialStorageListener } from "./platform/main/desktop-credential-storage-listener";
|
import { DesktopCredentialStorageListener } from "./platform/main/desktop-credential-storage-listener";
|
||||||
import { MainCryptoFunctionService } from "./platform/main/main-crypto-function.service";
|
import { MainCryptoFunctionService } from "./platform/main/main-crypto-function.service";
|
||||||
import { ElectronLogMainService } from "./platform/services/electron-log.main.service";
|
import { ElectronLogMainService } from "./platform/services/electron-log.main.service";
|
||||||
|
import { ELECTRON_SUPPORTS_SECURE_STORAGE } from "./platform/services/electron-platform-utils.service";
|
||||||
import { ElectronStateService } from "./platform/services/electron-state.service";
|
import { ElectronStateService } from "./platform/services/electron-state.service";
|
||||||
import { ElectronStorageService } from "./platform/services/electron-storage.service";
|
import { ElectronStorageService } from "./platform/services/electron-storage.service";
|
||||||
import { I18nMainService } from "./platform/services/i18n.main.service";
|
import { I18nMainService } from "./platform/services/i18n.main.service";
|
||||||
@ -53,6 +56,7 @@ export class Main {
|
|||||||
mainCryptoFunctionService: MainCryptoFunctionService;
|
mainCryptoFunctionService: MainCryptoFunctionService;
|
||||||
desktopCredentialStorageListener: DesktopCredentialStorageListener;
|
desktopCredentialStorageListener: DesktopCredentialStorageListener;
|
||||||
migrationRunner: MigrationRunner;
|
migrationRunner: MigrationRunner;
|
||||||
|
tokenService: TokenServiceAbstraction;
|
||||||
|
|
||||||
windowMain: WindowMain;
|
windowMain: WindowMain;
|
||||||
messagingMain: MessagingMain;
|
messagingMain: MessagingMain;
|
||||||
@ -124,19 +128,32 @@ export class Main {
|
|||||||
storageServiceProvider,
|
storageServiceProvider,
|
||||||
);
|
);
|
||||||
|
|
||||||
const stateProvider = new DefaultStateProvider(
|
const singleUserStateProvider = new DefaultSingleUserStateProvider(
|
||||||
new DefaultActiveUserStateProvider(
|
|
||||||
accountService,
|
|
||||||
storageServiceProvider,
|
storageServiceProvider,
|
||||||
stateEventRegistrarService,
|
stateEventRegistrarService,
|
||||||
),
|
);
|
||||||
new DefaultSingleUserStateProvider(storageServiceProvider, stateEventRegistrarService),
|
|
||||||
|
const activeUserStateProvider = new DefaultActiveUserStateProvider(
|
||||||
|
accountService,
|
||||||
|
singleUserStateProvider,
|
||||||
|
);
|
||||||
|
|
||||||
|
const stateProvider = new DefaultStateProvider(
|
||||||
|
activeUserStateProvider,
|
||||||
|
singleUserStateProvider,
|
||||||
globalStateProvider,
|
globalStateProvider,
|
||||||
new DefaultDerivedStateProvider(this.memoryStorageForStateProviders),
|
new DefaultDerivedStateProvider(this.memoryStorageForStateProviders),
|
||||||
);
|
);
|
||||||
|
|
||||||
this.environmentService = new EnvironmentService(stateProvider, accountService);
|
this.environmentService = new EnvironmentService(stateProvider, accountService);
|
||||||
|
|
||||||
|
this.tokenService = new TokenService(
|
||||||
|
singleUserStateProvider,
|
||||||
|
globalStateProvider,
|
||||||
|
ELECTRON_SUPPORTS_SECURE_STORAGE,
|
||||||
|
this.storageService,
|
||||||
|
);
|
||||||
|
|
||||||
this.migrationRunner = new MigrationRunner(
|
this.migrationRunner = new MigrationRunner(
|
||||||
this.storageService,
|
this.storageService,
|
||||||
this.logService,
|
this.logService,
|
||||||
@ -154,6 +171,7 @@ export class Main {
|
|||||||
new StateFactory(GlobalState, Account),
|
new StateFactory(GlobalState, Account),
|
||||||
accountService, // will not broadcast logouts. This is a hack until we can remove messaging dependency
|
accountService, // will not broadcast logouts. This is a hack until we can remove messaging dependency
|
||||||
this.environmentService,
|
this.environmentService,
|
||||||
|
this.tokenService,
|
||||||
this.migrationRunner,
|
this.migrationRunner,
|
||||||
false, // Do not use disk caching because this will get out of sync with the renderer service
|
false, // Do not use disk caching because this will get out of sync with the renderer service
|
||||||
);
|
);
|
||||||
@ -175,6 +193,7 @@ export class Main {
|
|||||||
this.messagingService = new ElectronMainMessagingService(this.windowMain, (message) => {
|
this.messagingService = new ElectronMainMessagingService(this.windowMain, (message) => {
|
||||||
this.messagingMain.onMessage(message);
|
this.messagingMain.onMessage(message);
|
||||||
});
|
});
|
||||||
|
|
||||||
this.powerMonitorMain = new PowerMonitorMain(this.messagingService);
|
this.powerMonitorMain = new PowerMonitorMain(this.messagingService);
|
||||||
this.menuMain = new MenuMain(
|
this.menuMain = new MenuMain(
|
||||||
this.i18nService,
|
this.i18nService,
|
||||||
|
@ -8,6 +8,7 @@ import localeBn from "@angular/common/locales/bn";
|
|||||||
import localeBs from "@angular/common/locales/bs";
|
import localeBs from "@angular/common/locales/bs";
|
||||||
import localeCa from "@angular/common/locales/ca";
|
import localeCa from "@angular/common/locales/ca";
|
||||||
import localeCs from "@angular/common/locales/cs";
|
import localeCs from "@angular/common/locales/cs";
|
||||||
|
import localeCy from "@angular/common/locales/cy";
|
||||||
import localeDa from "@angular/common/locales/da";
|
import localeDa from "@angular/common/locales/da";
|
||||||
import localeDe from "@angular/common/locales/de";
|
import localeDe from "@angular/common/locales/de";
|
||||||
import localeEl from "@angular/common/locales/el";
|
import localeEl from "@angular/common/locales/el";
|
||||||
@ -21,6 +22,7 @@ import localeFa from "@angular/common/locales/fa";
|
|||||||
import localeFi from "@angular/common/locales/fi";
|
import localeFi from "@angular/common/locales/fi";
|
||||||
import localeFil from "@angular/common/locales/fil";
|
import localeFil from "@angular/common/locales/fil";
|
||||||
import localeFr from "@angular/common/locales/fr";
|
import localeFr from "@angular/common/locales/fr";
|
||||||
|
import localeGl from "@angular/common/locales/gl";
|
||||||
import localeHe from "@angular/common/locales/he";
|
import localeHe from "@angular/common/locales/he";
|
||||||
import localeHi from "@angular/common/locales/hi";
|
import localeHi from "@angular/common/locales/hi";
|
||||||
import localeHr from "@angular/common/locales/hr";
|
import localeHr from "@angular/common/locales/hr";
|
||||||
@ -32,11 +34,16 @@ import localeKa from "@angular/common/locales/ka";
|
|||||||
import localeKm from "@angular/common/locales/km";
|
import localeKm from "@angular/common/locales/km";
|
||||||
import localeKn from "@angular/common/locales/kn";
|
import localeKn from "@angular/common/locales/kn";
|
||||||
import localeKo from "@angular/common/locales/ko";
|
import localeKo from "@angular/common/locales/ko";
|
||||||
|
import localeLt from "@angular/common/locales/lt";
|
||||||
import localeLv from "@angular/common/locales/lv";
|
import localeLv from "@angular/common/locales/lv";
|
||||||
import localeMl from "@angular/common/locales/ml";
|
import localeMl from "@angular/common/locales/ml";
|
||||||
|
import localeMr from "@angular/common/locales/mr";
|
||||||
|
import localeMy from "@angular/common/locales/my";
|
||||||
import localeNb from "@angular/common/locales/nb";
|
import localeNb from "@angular/common/locales/nb";
|
||||||
|
import localeNe from "@angular/common/locales/ne";
|
||||||
import localeNl from "@angular/common/locales/nl";
|
import localeNl from "@angular/common/locales/nl";
|
||||||
import localeNn from "@angular/common/locales/nn";
|
import localeNn from "@angular/common/locales/nn";
|
||||||
|
import localeOr from "@angular/common/locales/or";
|
||||||
import localePl from "@angular/common/locales/pl";
|
import localePl from "@angular/common/locales/pl";
|
||||||
import localePtBr from "@angular/common/locales/pt";
|
import localePtBr from "@angular/common/locales/pt";
|
||||||
import localePtPt from "@angular/common/locales/pt-PT";
|
import localePtPt from "@angular/common/locales/pt-PT";
|
||||||
@ -48,6 +55,7 @@ import localeSl from "@angular/common/locales/sl";
|
|||||||
import localeSr from "@angular/common/locales/sr";
|
import localeSr from "@angular/common/locales/sr";
|
||||||
import localeMe from "@angular/common/locales/sr-Latn-ME";
|
import localeMe from "@angular/common/locales/sr-Latn-ME";
|
||||||
import localeSv from "@angular/common/locales/sv";
|
import localeSv from "@angular/common/locales/sv";
|
||||||
|
import localeTe from "@angular/common/locales/te";
|
||||||
import localeTh from "@angular/common/locales/th";
|
import localeTh from "@angular/common/locales/th";
|
||||||
import localeTr from "@angular/common/locales/tr";
|
import localeTr from "@angular/common/locales/tr";
|
||||||
import localeUk from "@angular/common/locales/uk";
|
import localeUk from "@angular/common/locales/uk";
|
||||||
@ -64,6 +72,7 @@ registerLocaleData(localeBn, "bn");
|
|||||||
registerLocaleData(localeBs, "bs");
|
registerLocaleData(localeBs, "bs");
|
||||||
registerLocaleData(localeCa, "ca");
|
registerLocaleData(localeCa, "ca");
|
||||||
registerLocaleData(localeCs, "cs");
|
registerLocaleData(localeCs, "cs");
|
||||||
|
registerLocaleData(localeCy, "cy");
|
||||||
registerLocaleData(localeDa, "da");
|
registerLocaleData(localeDa, "da");
|
||||||
registerLocaleData(localeDe, "de");
|
registerLocaleData(localeDe, "de");
|
||||||
registerLocaleData(localeEl, "el");
|
registerLocaleData(localeEl, "el");
|
||||||
@ -77,6 +86,7 @@ registerLocaleData(localeFa, "fa");
|
|||||||
registerLocaleData(localeFi, "fi");
|
registerLocaleData(localeFi, "fi");
|
||||||
registerLocaleData(localeFil, "fil");
|
registerLocaleData(localeFil, "fil");
|
||||||
registerLocaleData(localeFr, "fr");
|
registerLocaleData(localeFr, "fr");
|
||||||
|
registerLocaleData(localeGl, "gl");
|
||||||
registerLocaleData(localeHe, "he");
|
registerLocaleData(localeHe, "he");
|
||||||
registerLocaleData(localeHi, "hi");
|
registerLocaleData(localeHi, "hi");
|
||||||
registerLocaleData(localeHr, "hr");
|
registerLocaleData(localeHr, "hr");
|
||||||
@ -88,12 +98,17 @@ registerLocaleData(localeKa, "ka");
|
|||||||
registerLocaleData(localeKm, "km");
|
registerLocaleData(localeKm, "km");
|
||||||
registerLocaleData(localeKn, "kn");
|
registerLocaleData(localeKn, "kn");
|
||||||
registerLocaleData(localeKo, "ko");
|
registerLocaleData(localeKo, "ko");
|
||||||
|
registerLocaleData(localeLt, "lt");
|
||||||
registerLocaleData(localeLv, "lv");
|
registerLocaleData(localeLv, "lv");
|
||||||
registerLocaleData(localeMe, "me");
|
registerLocaleData(localeMe, "me");
|
||||||
registerLocaleData(localeMl, "ml");
|
registerLocaleData(localeMl, "ml");
|
||||||
|
registerLocaleData(localeMr, "mr");
|
||||||
|
registerLocaleData(localeMy, "my");
|
||||||
registerLocaleData(localeNb, "nb");
|
registerLocaleData(localeNb, "nb");
|
||||||
|
registerLocaleData(localeNe, "ne");
|
||||||
registerLocaleData(localeNl, "nl");
|
registerLocaleData(localeNl, "nl");
|
||||||
registerLocaleData(localeNn, "nn");
|
registerLocaleData(localeNn, "nn");
|
||||||
|
registerLocaleData(localeOr, "or");
|
||||||
registerLocaleData(localePl, "pl");
|
registerLocaleData(localePl, "pl");
|
||||||
registerLocaleData(localePtBr, "pt-BR");
|
registerLocaleData(localePtBr, "pt-BR");
|
||||||
registerLocaleData(localePtPt, "pt-PT");
|
registerLocaleData(localePtPt, "pt-PT");
|
||||||
@ -104,6 +119,7 @@ registerLocaleData(localeSk, "sk");
|
|||||||
registerLocaleData(localeSl, "sl");
|
registerLocaleData(localeSl, "sl");
|
||||||
registerLocaleData(localeSr, "sr");
|
registerLocaleData(localeSr, "sr");
|
||||||
registerLocaleData(localeSv, "sv");
|
registerLocaleData(localeSv, "sv");
|
||||||
|
registerLocaleData(localeTe, "te");
|
||||||
registerLocaleData(localeTh, "th");
|
registerLocaleData(localeTh, "th");
|
||||||
registerLocaleData(localeTr, "tr");
|
registerLocaleData(localeTr, "tr");
|
||||||
registerLocaleData(localeUk, "uk");
|
registerLocaleData(localeUk, "uk");
|
||||||
|
@ -8,6 +8,8 @@ import {
|
|||||||
|
|
||||||
import { ClipboardWriteMessage } from "../types/clipboard";
|
import { ClipboardWriteMessage } from "../types/clipboard";
|
||||||
|
|
||||||
|
export const ELECTRON_SUPPORTS_SECURE_STORAGE = true;
|
||||||
|
|
||||||
export class ElectronPlatformUtilsService implements PlatformUtilsService {
|
export class ElectronPlatformUtilsService implements PlatformUtilsService {
|
||||||
constructor(
|
constructor(
|
||||||
protected i18nService: I18nService,
|
protected i18nService: I18nService,
|
||||||
@ -142,7 +144,7 @@ export class ElectronPlatformUtilsService implements PlatformUtilsService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
supportsSecureStorage(): boolean {
|
supportsSecureStorage(): boolean {
|
||||||
return true;
|
return ELECTRON_SUPPORTS_SECURE_STORAGE;
|
||||||
}
|
}
|
||||||
|
|
||||||
getAutofillKeyboardShortcut(): Promise<string> {
|
getAutofillKeyboardShortcut(): Promise<string> {
|
||||||
|
@ -4,7 +4,6 @@ import { firstValueFrom } from "rxjs";
|
|||||||
import { NativeMessagingVersion } from "@bitwarden/common/enums";
|
import { NativeMessagingVersion } from "@bitwarden/common/enums";
|
||||||
import { CryptoFunctionService } from "@bitwarden/common/platform/abstractions/crypto-function.service";
|
import { CryptoFunctionService } from "@bitwarden/common/platform/abstractions/crypto-function.service";
|
||||||
import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service";
|
import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service";
|
||||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
|
||||||
import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service";
|
import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service";
|
||||||
import { Utils } from "@bitwarden/common/platform/misc/utils";
|
import { Utils } from "@bitwarden/common/platform/misc/utils";
|
||||||
import { EncryptedString, EncString } from "@bitwarden/common/platform/models/domain/enc-string";
|
import { EncryptedString, EncString } from "@bitwarden/common/platform/models/domain/enc-string";
|
||||||
@ -33,7 +32,6 @@ export class NativeMessageHandlerService {
|
|||||||
private cryptoService: CryptoService,
|
private cryptoService: CryptoService,
|
||||||
private cryptoFunctionService: CryptoFunctionService,
|
private cryptoFunctionService: CryptoFunctionService,
|
||||||
private messagingService: MessagingService,
|
private messagingService: MessagingService,
|
||||||
private i18nService: I18nService,
|
|
||||||
private encryptedMessageHandlerService: EncryptedMessageHandlerService,
|
private encryptedMessageHandlerService: EncryptedMessageHandlerService,
|
||||||
private dialogService: DialogService,
|
private dialogService: DialogService,
|
||||||
) {}
|
) {}
|
||||||
|
@ -3,7 +3,6 @@ import { firstValueFrom } from "rxjs";
|
|||||||
|
|
||||||
import { CryptoFunctionService } from "@bitwarden/common/platform/abstractions/crypto-function.service";
|
import { CryptoFunctionService } from "@bitwarden/common/platform/abstractions/crypto-function.service";
|
||||||
import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service";
|
import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service";
|
||||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
|
||||||
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
|
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
|
||||||
import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service";
|
import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service";
|
||||||
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
||||||
@ -35,7 +34,6 @@ export class NativeMessagingService {
|
|||||||
private cryptoService: CryptoService,
|
private cryptoService: CryptoService,
|
||||||
private platformUtilService: PlatformUtilsService,
|
private platformUtilService: PlatformUtilsService,
|
||||||
private logService: LogService,
|
private logService: LogService,
|
||||||
private i18nService: I18nService,
|
|
||||||
private messagingService: MessagingService,
|
private messagingService: MessagingService,
|
||||||
private stateService: StateService,
|
private stateService: StateService,
|
||||||
private biometricStateService: BiometricStateService,
|
private biometricStateService: BiometricStateService,
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
{{ "premiumMembership" | i18n }}
|
{{ "premiumMembership" | i18n }}
|
||||||
</h1>
|
</h1>
|
||||||
<div class="box-content box-content-padded">
|
<div class="box-content box-content-padded">
|
||||||
<div *ngIf="!isPremium">
|
<div *ngIf="!(isPremium$ | async)">
|
||||||
<p class="text-center lead">{{ "premiumNotCurrentMember" | i18n }}</p>
|
<p class="text-center lead">{{ "premiumNotCurrentMember" | i18n }}</p>
|
||||||
<p>{{ "premiumSignUpAndGet" | i18n }}</p>
|
<p>{{ "premiumSignUpAndGet" | i18n }}</p>
|
||||||
<ul class="bwi-ul">
|
<ul class="bwi-ul">
|
||||||
@ -40,7 +40,7 @@
|
|||||||
{{ "premiumPrice" | i18n: (price | currency: "$") }}
|
{{ "premiumPrice" | i18n: (price | currency: "$") }}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div *ngIf="isPremium">
|
<div *ngIf="isPremium$ | async">
|
||||||
<p class="text-center lead">{{ "premiumCurrentMember" | i18n }}</p>
|
<p class="text-center lead">{{ "premiumCurrentMember" | i18n }}</p>
|
||||||
<p class="text-center">{{ "premiumCurrentMemberThanks" | i18n }}</p>
|
<p class="text-center">{{ "premiumCurrentMemberThanks" | i18n }}</p>
|
||||||
</div>
|
</div>
|
||||||
@ -48,7 +48,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-footer">
|
<div class="modal-footer">
|
||||||
<button type="button" class="primary" (click)="manage()" *ngIf="isPremium">
|
<button type="button" class="primary" (click)="manage()" *ngIf="isPremium$ | async">
|
||||||
<b>{{ "premiumManage" | i18n }}</b>
|
<b>{{ "premiumManage" | i18n }}</b>
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
@ -56,13 +56,13 @@
|
|||||||
type="button"
|
type="button"
|
||||||
class="primary"
|
class="primary"
|
||||||
(click)="purchase()"
|
(click)="purchase()"
|
||||||
*ngIf="!isPremium"
|
*ngIf="!(isPremium$ | async)"
|
||||||
[disabled]="$any(purchaseBtn).loading"
|
[disabled]="$any(purchaseBtn).loading"
|
||||||
>
|
>
|
||||||
<b>{{ "premiumPurchase" | i18n }}</b>
|
<b>{{ "premiumPurchase" | i18n }}</b>
|
||||||
</button>
|
</button>
|
||||||
<button type="button" data-dismiss="modal">{{ "close" | i18n }}</button>
|
<button type="button" data-dismiss="modal">{{ "close" | i18n }}</button>
|
||||||
<div class="right" *ngIf="!isPremium">
|
<div class="right" *ngIf="!(isPremium$ | async)">
|
||||||
<button
|
<button
|
||||||
#refreshBtn
|
#refreshBtn
|
||||||
type="button"
|
type="button"
|
||||||
|
@ -2,6 +2,7 @@ import { Component } from "@angular/core";
|
|||||||
|
|
||||||
import { PremiumComponent as BasePremiumComponent } from "@bitwarden/angular/vault/components/premium.component";
|
import { PremiumComponent as BasePremiumComponent } from "@bitwarden/angular/vault/components/premium.component";
|
||||||
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
||||||
|
import { BillingAccountProfileStateService } from "@bitwarden/common/billing/abstractions/account/billing-account-profile-state.service";
|
||||||
import { EnvironmentService } from "@bitwarden/common/platform/abstractions/environment.service";
|
import { EnvironmentService } from "@bitwarden/common/platform/abstractions/environment.service";
|
||||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||||
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
|
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
|
||||||
@ -22,6 +23,7 @@ export class PremiumComponent extends BasePremiumComponent {
|
|||||||
stateService: StateService,
|
stateService: StateService,
|
||||||
dialogService: DialogService,
|
dialogService: DialogService,
|
||||||
environmentService: EnvironmentService,
|
environmentService: EnvironmentService,
|
||||||
|
billingAccountProfileStateService: BillingAccountProfileStateService,
|
||||||
) {
|
) {
|
||||||
super(
|
super(
|
||||||
i18nService,
|
i18nService,
|
||||||
@ -31,6 +33,7 @@ export class PremiumComponent extends BasePremiumComponent {
|
|||||||
stateService,
|
stateService,
|
||||||
dialogService,
|
dialogService,
|
||||||
environmentService,
|
environmentService,
|
||||||
|
billingAccountProfileStateService,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@ import { Component } from "@angular/core";
|
|||||||
|
|
||||||
import { AttachmentsComponent as BaseAttachmentsComponent } from "@bitwarden/angular/vault/components/attachments.component";
|
import { AttachmentsComponent as BaseAttachmentsComponent } from "@bitwarden/angular/vault/components/attachments.component";
|
||||||
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
||||||
|
import { BillingAccountProfileStateService } from "@bitwarden/common/billing/abstractions/account/billing-account-profile-state.service";
|
||||||
import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service";
|
import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service";
|
||||||
import { FileDownloadService } from "@bitwarden/common/platform/abstractions/file-download/file-download.service";
|
import { FileDownloadService } from "@bitwarden/common/platform/abstractions/file-download/file-download.service";
|
||||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||||
@ -26,6 +27,7 @@ export class AttachmentsComponent extends BaseAttachmentsComponent {
|
|||||||
stateService: StateService,
|
stateService: StateService,
|
||||||
fileDownloadService: FileDownloadService,
|
fileDownloadService: FileDownloadService,
|
||||||
dialogService: DialogService,
|
dialogService: DialogService,
|
||||||
|
billingAccountProfileStateService: BillingAccountProfileStateService,
|
||||||
) {
|
) {
|
||||||
super(
|
super(
|
||||||
cipherService,
|
cipherService,
|
||||||
@ -38,6 +40,7 @@ export class AttachmentsComponent extends BaseAttachmentsComponent {
|
|||||||
stateService,
|
stateService,
|
||||||
fileDownloadService,
|
fileDownloadService,
|
||||||
dialogService,
|
dialogService,
|
||||||
|
billingAccountProfileStateService,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,7 @@ import {
|
|||||||
ViewContainerRef,
|
ViewContainerRef,
|
||||||
} from "@angular/core";
|
} from "@angular/core";
|
||||||
import { ActivatedRoute, Router } from "@angular/router";
|
import { ActivatedRoute, Router } from "@angular/router";
|
||||||
|
import { Subject, takeUntil } from "rxjs";
|
||||||
import { first } from "rxjs/operators";
|
import { first } from "rxjs/operators";
|
||||||
|
|
||||||
import { ModalRef } from "@bitwarden/angular/components/modal/modal.ref";
|
import { ModalRef } from "@bitwarden/angular/components/modal/modal.ref";
|
||||||
@ -15,6 +16,7 @@ import { ModalService } from "@bitwarden/angular/services/modal.service";
|
|||||||
import { VaultFilter } from "@bitwarden/angular/vault/vault-filter/models/vault-filter.model";
|
import { VaultFilter } from "@bitwarden/angular/vault/vault-filter/models/vault-filter.model";
|
||||||
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
||||||
import { EventCollectionService } from "@bitwarden/common/abstractions/event/event-collection.service";
|
import { EventCollectionService } from "@bitwarden/common/abstractions/event/event-collection.service";
|
||||||
|
import { BillingAccountProfileStateService } from "@bitwarden/common/billing/abstractions/account/billing-account-profile-state.service";
|
||||||
import { EventType } from "@bitwarden/common/enums";
|
import { EventType } from "@bitwarden/common/enums";
|
||||||
import { BroadcasterService } from "@bitwarden/common/platform/abstractions/broadcaster.service";
|
import { BroadcasterService } from "@bitwarden/common/platform/abstractions/broadcaster.service";
|
||||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||||
@ -84,6 +86,7 @@ export class VaultComponent implements OnInit, OnDestroy {
|
|||||||
activeFilter: VaultFilter = new VaultFilter();
|
activeFilter: VaultFilter = new VaultFilter();
|
||||||
|
|
||||||
private modal: ModalRef = null;
|
private modal: ModalRef = null;
|
||||||
|
private componentIsDestroyed$ = new Subject<boolean>();
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private route: ActivatedRoute,
|
private route: ActivatedRoute,
|
||||||
@ -103,10 +106,16 @@ export class VaultComponent implements OnInit, OnDestroy {
|
|||||||
private searchBarService: SearchBarService,
|
private searchBarService: SearchBarService,
|
||||||
private apiService: ApiService,
|
private apiService: ApiService,
|
||||||
private dialogService: DialogService,
|
private dialogService: DialogService,
|
||||||
|
private billingAccountProfileStateService: BillingAccountProfileStateService,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
async ngOnInit() {
|
async ngOnInit() {
|
||||||
this.userHasPremiumAccess = await this.stateService.getCanAccessPremium();
|
this.billingAccountProfileStateService.hasPremiumFromAnySource$
|
||||||
|
.pipe(takeUntil(this.componentIsDestroyed$))
|
||||||
|
.subscribe((canAccessPremium: boolean) => {
|
||||||
|
this.userHasPremiumAccess = canAccessPremium;
|
||||||
|
});
|
||||||
|
|
||||||
this.broadcasterService.subscribe(BroadcasterSubscriptionId, (message: any) => {
|
this.broadcasterService.subscribe(BroadcasterSubscriptionId, (message: any) => {
|
||||||
// FIXME: Verify that this floating promise is intentional. If it is, add an explanatory comment and ensure there is proper error handling.
|
// FIXME: Verify that this floating promise is intentional. If it is, add an explanatory comment and ensure there is proper error handling.
|
||||||
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
||||||
@ -229,6 +238,8 @@ export class VaultComponent implements OnInit, OnDestroy {
|
|||||||
ngOnDestroy() {
|
ngOnDestroy() {
|
||||||
this.searchBarService.setEnabled(false);
|
this.searchBarService.setEnabled(false);
|
||||||
this.broadcasterService.unsubscribe(BroadcasterSubscriptionId);
|
this.broadcasterService.unsubscribe(BroadcasterSubscriptionId);
|
||||||
|
this.componentIsDestroyed$.next(true);
|
||||||
|
this.componentIsDestroyed$.complete();
|
||||||
}
|
}
|
||||||
|
|
||||||
async load() {
|
async load() {
|
||||||
|
@ -13,6 +13,7 @@ import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
|||||||
import { AuditService } from "@bitwarden/common/abstractions/audit.service";
|
import { AuditService } from "@bitwarden/common/abstractions/audit.service";
|
||||||
import { EventCollectionService } from "@bitwarden/common/abstractions/event/event-collection.service";
|
import { EventCollectionService } from "@bitwarden/common/abstractions/event/event-collection.service";
|
||||||
import { TokenService } from "@bitwarden/common/auth/abstractions/token.service";
|
import { TokenService } from "@bitwarden/common/auth/abstractions/token.service";
|
||||||
|
import { BillingAccountProfileStateService } from "@bitwarden/common/billing/abstractions/account/billing-account-profile-state.service";
|
||||||
import { BroadcasterService } from "@bitwarden/common/platform/abstractions/broadcaster.service";
|
import { BroadcasterService } from "@bitwarden/common/platform/abstractions/broadcaster.service";
|
||||||
import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service";
|
import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service";
|
||||||
import { FileDownloadService } from "@bitwarden/common/platform/abstractions/file-download/file-download.service";
|
import { FileDownloadService } from "@bitwarden/common/platform/abstractions/file-download/file-download.service";
|
||||||
@ -58,6 +59,7 @@ export class ViewComponent extends BaseViewComponent implements OnChanges {
|
|||||||
fileDownloadService: FileDownloadService,
|
fileDownloadService: FileDownloadService,
|
||||||
dialogService: DialogService,
|
dialogService: DialogService,
|
||||||
datePipe: DatePipe,
|
datePipe: DatePipe,
|
||||||
|
billingAccountProfileStateService: BillingAccountProfileStateService,
|
||||||
) {
|
) {
|
||||||
super(
|
super(
|
||||||
cipherService,
|
cipherService,
|
||||||
@ -80,6 +82,7 @@ export class ViewComponent extends BaseViewComponent implements OnChanges {
|
|||||||
fileDownloadService,
|
fileDownloadService,
|
||||||
dialogService,
|
dialogService,
|
||||||
datePipe,
|
datePipe,
|
||||||
|
billingAccountProfileStateService,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
|
@ -1,10 +1,12 @@
|
|||||||
import { Directive, ViewChild, ViewContainerRef } from "@angular/core";
|
import { Directive, ViewChild, ViewContainerRef } from "@angular/core";
|
||||||
|
import { firstValueFrom } from "rxjs";
|
||||||
|
|
||||||
import { SearchPipe } from "@bitwarden/angular/pipes/search.pipe";
|
import { SearchPipe } from "@bitwarden/angular/pipes/search.pipe";
|
||||||
import { UserNamePipe } from "@bitwarden/angular/pipes/user-name.pipe";
|
import { UserNamePipe } from "@bitwarden/angular/pipes/user-name.pipe";
|
||||||
import { ModalService } from "@bitwarden/angular/services/modal.service";
|
import { ModalService } from "@bitwarden/angular/services/modal.service";
|
||||||
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
||||||
import { SearchService } from "@bitwarden/common/abstractions/search.service";
|
import { SearchService } from "@bitwarden/common/abstractions/search.service";
|
||||||
|
import { OrganizationManagementPreferencesService } from "@bitwarden/common/admin-console/abstractions/organization-management-preferences/organization-management-preferences.service";
|
||||||
import {
|
import {
|
||||||
OrganizationUserStatusType,
|
OrganizationUserStatusType,
|
||||||
OrganizationUserType,
|
OrganizationUserType,
|
||||||
@ -17,7 +19,6 @@ import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.se
|
|||||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||||
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
|
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
|
||||||
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
||||||
import { StateService } from "@bitwarden/common/platform/abstractions/state.service";
|
|
||||||
import { ValidationService } from "@bitwarden/common/platform/abstractions/validation.service";
|
import { ValidationService } from "@bitwarden/common/platform/abstractions/validation.service";
|
||||||
import { Utils } from "@bitwarden/common/platform/misc/utils";
|
import { Utils } from "@bitwarden/common/platform/misc/utils";
|
||||||
import { DialogService } from "@bitwarden/components";
|
import { DialogService } from "@bitwarden/components";
|
||||||
@ -109,8 +110,8 @@ export abstract class BasePeopleComponent<
|
|||||||
private logService: LogService,
|
private logService: LogService,
|
||||||
private searchPipe: SearchPipe,
|
private searchPipe: SearchPipe,
|
||||||
protected userNamePipe: UserNamePipe,
|
protected userNamePipe: UserNamePipe,
|
||||||
protected stateService: StateService,
|
|
||||||
protected dialogService: DialogService,
|
protected dialogService: DialogService,
|
||||||
|
protected organizationManagementPreferencesService: OrganizationManagementPreferencesService,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
abstract edit(user: UserType): void;
|
abstract edit(user: UserType): void;
|
||||||
@ -351,7 +352,9 @@ export abstract class BasePeopleComponent<
|
|||||||
const publicKeyResponse = await this.apiService.getUserPublicKey(user.userId);
|
const publicKeyResponse = await this.apiService.getUserPublicKey(user.userId);
|
||||||
const publicKey = Utils.fromB64ToArray(publicKeyResponse.publicKey);
|
const publicKey = Utils.fromB64ToArray(publicKeyResponse.publicKey);
|
||||||
|
|
||||||
const autoConfirm = await this.stateService.getAutoConfirmFingerPrints();
|
const autoConfirm = await firstValueFrom(
|
||||||
|
this.organizationManagementPreferencesService.autoConfirmFingerPrints.state$,
|
||||||
|
);
|
||||||
if (autoConfirm == null || !autoConfirm) {
|
if (autoConfirm == null || !autoConfirm) {
|
||||||
const [modal] = await this.modalService.openViewRef(
|
const [modal] = await this.modalService.openViewRef(
|
||||||
UserConfirmComponent,
|
UserConfirmComponent,
|
||||||
|
@ -17,7 +17,7 @@ export class IsPaidOrgGuard implements CanActivate {
|
|||||||
) {}
|
) {}
|
||||||
|
|
||||||
async canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
|
async canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
|
||||||
const org = this.organizationService.get(route.params.organizationId);
|
const org = await this.organizationService.get(route.params.organizationId);
|
||||||
|
|
||||||
if (org == null) {
|
if (org == null) {
|
||||||
return this.router.createUrlTree(["/"]);
|
return this.router.createUrlTree(["/"]);
|
||||||
|
@ -66,7 +66,7 @@ describe("Organization Permissions Guard", () => {
|
|||||||
|
|
||||||
it("permits navigation if no permissions are specified", async () => {
|
it("permits navigation if no permissions are specified", async () => {
|
||||||
const org = orgFactory();
|
const org = orgFactory();
|
||||||
organizationService.get.calledWith(org.id).mockReturnValue(org);
|
organizationService.get.calledWith(org.id).mockResolvedValue(org);
|
||||||
|
|
||||||
const actual = await organizationPermissionsGuard.canActivate(route, state);
|
const actual = await organizationPermissionsGuard.canActivate(route, state);
|
||||||
|
|
||||||
@ -81,7 +81,7 @@ describe("Organization Permissions Guard", () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const org = orgFactory();
|
const org = orgFactory();
|
||||||
organizationService.get.calledWith(org.id).mockReturnValue(org);
|
organizationService.get.calledWith(org.id).mockResolvedValue(org);
|
||||||
|
|
||||||
const actual = await organizationPermissionsGuard.canActivate(route, state);
|
const actual = await organizationPermissionsGuard.canActivate(route, state);
|
||||||
|
|
||||||
@ -104,7 +104,7 @@ describe("Organization Permissions Guard", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
const org = orgFactory();
|
const org = orgFactory();
|
||||||
organizationService.get.calledWith(org.id).mockReturnValue(org);
|
organizationService.get.calledWith(org.id).mockResolvedValue(org);
|
||||||
|
|
||||||
const actual = await organizationPermissionsGuard.canActivate(route, state);
|
const actual = await organizationPermissionsGuard.canActivate(route, state);
|
||||||
|
|
||||||
@ -124,7 +124,7 @@ describe("Organization Permissions Guard", () => {
|
|||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
const org = orgFactory();
|
const org = orgFactory();
|
||||||
organizationService.get.calledWith(org.id).mockReturnValue(org);
|
organizationService.get.calledWith(org.id).mockResolvedValue(org);
|
||||||
|
|
||||||
const actual = await organizationPermissionsGuard.canActivate(route, state);
|
const actual = await organizationPermissionsGuard.canActivate(route, state);
|
||||||
|
|
||||||
@ -141,7 +141,7 @@ describe("Organization Permissions Guard", () => {
|
|||||||
type: OrganizationUserType.Admin,
|
type: OrganizationUserType.Admin,
|
||||||
enabled: false,
|
enabled: false,
|
||||||
});
|
});
|
||||||
organizationService.get.calledWith(org.id).mockReturnValue(org);
|
organizationService.get.calledWith(org.id).mockResolvedValue(org);
|
||||||
|
|
||||||
const actual = await organizationPermissionsGuard.canActivate(route, state);
|
const actual = await organizationPermissionsGuard.canActivate(route, state);
|
||||||
|
|
||||||
@ -153,7 +153,7 @@ describe("Organization Permissions Guard", () => {
|
|||||||
type: OrganizationUserType.Owner,
|
type: OrganizationUserType.Owner,
|
||||||
enabled: false,
|
enabled: false,
|
||||||
});
|
});
|
||||||
organizationService.get.calledWith(org.id).mockReturnValue(org);
|
organizationService.get.calledWith(org.id).mockResolvedValue(org);
|
||||||
|
|
||||||
const actual = await organizationPermissionsGuard.canActivate(route, state);
|
const actual = await organizationPermissionsGuard.canActivate(route, state);
|
||||||
|
|
||||||
|
@ -28,7 +28,7 @@ export class OrganizationPermissionsGuard implements CanActivate {
|
|||||||
await this.syncService.fullSync(false);
|
await this.syncService.fullSync(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
const org = this.organizationService.get(route.params.organizationId);
|
const org = await this.organizationService.get(route.params.organizationId);
|
||||||
if (org == null) {
|
if (org == null) {
|
||||||
return this.router.createUrlTree(["/"]);
|
return this.router.createUrlTree(["/"]);
|
||||||
}
|
}
|
||||||
|
@ -16,7 +16,7 @@ export class OrganizationRedirectGuard implements CanActivate {
|
|||||||
) {}
|
) {}
|
||||||
|
|
||||||
async canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
|
async canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
|
||||||
const org = this.organizationService.get(route.params.organizationId);
|
const org = await this.organizationService.get(route.params.organizationId);
|
||||||
|
|
||||||
const customRedirect = route.data?.autoRedirectCallback;
|
const customRedirect = route.data?.autoRedirectCallback;
|
||||||
if (customRedirect) {
|
if (customRedirect) {
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
import { Component, EventEmitter, Input, OnInit, Output } from "@angular/core";
|
import { Component, EventEmitter, Input, OnInit, Output } from "@angular/core";
|
||||||
|
|
||||||
|
import { OrganizationManagementPreferencesService } from "@bitwarden/common/admin-console/abstractions/organization-management-preferences/organization-management-preferences.service";
|
||||||
import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service";
|
import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service";
|
||||||
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
|
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
|
||||||
import { StateService } from "@bitwarden/common/platform/abstractions/state.service";
|
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: "app-user-confirm",
|
selector: "app-user-confirm",
|
||||||
@ -22,7 +22,7 @@ export class UserConfirmComponent implements OnInit {
|
|||||||
constructor(
|
constructor(
|
||||||
private cryptoService: CryptoService,
|
private cryptoService: CryptoService,
|
||||||
private logService: LogService,
|
private logService: LogService,
|
||||||
private stateService: StateService,
|
private organizationManagementPreferencesService: OrganizationManagementPreferencesService,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
async ngOnInit() {
|
async ngOnInit() {
|
||||||
@ -45,7 +45,7 @@ export class UserConfirmComponent implements OnInit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (this.dontAskAgain) {
|
if (this.dontAskAgain) {
|
||||||
await this.stateService.setAutoConfirmFingerprints(true);
|
await this.organizationManagementPreferencesService.autoConfirmFingerPrints.set(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.onConfirmedUser.emit();
|
this.onConfirmedUser.emit();
|
||||||
|
@ -2,6 +2,7 @@ import { Component, Input } from "@angular/core";
|
|||||||
|
|
||||||
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
||||||
import { OrganizationUserService } from "@bitwarden/common/admin-console/abstractions/organization-user/organization-user.service";
|
import { OrganizationUserService } from "@bitwarden/common/admin-console/abstractions/organization-user/organization-user.service";
|
||||||
|
import { OrganizationUserStatusType } from "@bitwarden/common/admin-console/enums";
|
||||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||||
|
|
||||||
import { BulkUserDetails } from "./bulk-status.component";
|
import { BulkUserDetails } from "./bulk-status.component";
|
||||||
@ -14,7 +15,9 @@ export class BulkRemoveComponent {
|
|||||||
@Input() organizationId: string;
|
@Input() organizationId: string;
|
||||||
@Input() set users(value: BulkUserDetails[]) {
|
@Input() set users(value: BulkUserDetails[]) {
|
||||||
this._users = value;
|
this._users = value;
|
||||||
this.showNoMasterPasswordWarning = this._users.some((u) => u.hasMasterPassword === false);
|
this.showNoMasterPasswordWarning = this._users.some(
|
||||||
|
(u) => u.status > OrganizationUserStatusType.Invited && u.hasMasterPassword === false,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
get users(): BulkUserDetails[] {
|
get users(): BulkUserDetails[] {
|
||||||
|
@ -2,6 +2,7 @@ import { DIALOG_DATA } from "@angular/cdk/dialog";
|
|||||||
import { Component, Inject } from "@angular/core";
|
import { Component, Inject } from "@angular/core";
|
||||||
|
|
||||||
import { OrganizationUserService } from "@bitwarden/common/admin-console/abstractions/organization-user/organization-user.service";
|
import { OrganizationUserService } from "@bitwarden/common/admin-console/abstractions/organization-user/organization-user.service";
|
||||||
|
import { OrganizationUserStatusType } from "@bitwarden/common/admin-console/enums";
|
||||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||||
import { DialogService } from "@bitwarden/components";
|
import { DialogService } from "@bitwarden/components";
|
||||||
|
|
||||||
@ -37,7 +38,9 @@ export class BulkRestoreRevokeComponent {
|
|||||||
this.isRevoking = data.isRevoking;
|
this.isRevoking = data.isRevoking;
|
||||||
this.organizationId = data.organizationId;
|
this.organizationId = data.organizationId;
|
||||||
this.users = data.users;
|
this.users = data.users;
|
||||||
this.showNoMasterPasswordWarning = this.users.some((u) => u.hasMasterPassword === false);
|
this.showNoMasterPasswordWarning = this.users.some(
|
||||||
|
(u) => u.status > OrganizationUserStatusType.Invited && u.hasMasterPassword === false,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
get bulkTitle() {
|
get bulkTitle() {
|
||||||
|
@ -399,7 +399,11 @@
|
|||||||
</bit-tab>
|
</bit-tab>
|
||||||
<bit-tab *ngIf="organization.useGroups" [label]="'groups' | i18n">
|
<bit-tab *ngIf="organization.useGroups" [label]="'groups' | i18n">
|
||||||
<div class="tw-mb-6">
|
<div class="tw-mb-6">
|
||||||
{{ "groupAccessUserDesc" | i18n }}
|
{{
|
||||||
|
(restrictedAccess$ | async)
|
||||||
|
? ("restrictedGroupAccess" | i18n)
|
||||||
|
: ("groupAccessUserDesc" | i18n)
|
||||||
|
}}
|
||||||
</div>
|
</div>
|
||||||
<bit-access-selector
|
<bit-access-selector
|
||||||
formControlName="groups"
|
formControlName="groups"
|
||||||
@ -408,10 +412,14 @@
|
|||||||
[selectorLabelText]="'selectGroups' | i18n"
|
[selectorLabelText]="'selectGroups' | i18n"
|
||||||
[emptySelectionText]="'noGroupsAdded' | i18n"
|
[emptySelectionText]="'noGroupsAdded' | i18n"
|
||||||
[flexibleCollectionsEnabled]="organization.flexibleCollections"
|
[flexibleCollectionsEnabled]="organization.flexibleCollections"
|
||||||
|
[hideMultiSelect]="restrictedAccess$ | async"
|
||||||
></bit-access-selector>
|
></bit-access-selector>
|
||||||
</bit-tab>
|
</bit-tab>
|
||||||
<bit-tab [label]="'collections' | i18n">
|
<bit-tab [label]="'collections' | i18n">
|
||||||
<div *ngIf="organization.useGroups" class="tw-mb-6">
|
<div class="tw-mb-6" *ngIf="restrictedAccess$ | async">
|
||||||
|
{{ "restrictedCollectionAccess" | i18n }}
|
||||||
|
</div>
|
||||||
|
<div *ngIf="organization.useGroups && !(restrictedAccess$ | async)" class="tw-mb-6">
|
||||||
{{ "userPermissionOverrideHelper" | i18n }}
|
{{ "userPermissionOverrideHelper" | i18n }}
|
||||||
</div>
|
</div>
|
||||||
<div *ngIf="!organization.flexibleCollections" class="tw-mb-6">
|
<div *ngIf="!organization.flexibleCollections" class="tw-mb-6">
|
||||||
@ -441,6 +449,7 @@
|
|||||||
[selectorLabelText]="'selectCollections' | i18n"
|
[selectorLabelText]="'selectCollections' | i18n"
|
||||||
[emptySelectionText]="'noCollectionsAdded' | i18n"
|
[emptySelectionText]="'noCollectionsAdded' | i18n"
|
||||||
[flexibleCollectionsEnabled]="organization.flexibleCollections"
|
[flexibleCollectionsEnabled]="organization.flexibleCollections"
|
||||||
|
[hideMultiSelect]="restrictedAccess$ | async"
|
||||||
></bit-access-selector
|
></bit-access-selector
|
||||||
></bit-tab>
|
></bit-tab>
|
||||||
</bit-tab-group>
|
</bit-tab-group>
|
||||||
|
@ -4,6 +4,7 @@ import { FormBuilder, Validators } from "@angular/forms";
|
|||||||
import {
|
import {
|
||||||
combineLatest,
|
combineLatest,
|
||||||
firstValueFrom,
|
firstValueFrom,
|
||||||
|
map,
|
||||||
Observable,
|
Observable,
|
||||||
of,
|
of,
|
||||||
shareReplay,
|
shareReplay,
|
||||||
@ -20,7 +21,9 @@ import {
|
|||||||
} from "@bitwarden/common/admin-console/enums";
|
} from "@bitwarden/common/admin-console/enums";
|
||||||
import { PermissionsApi } from "@bitwarden/common/admin-console/models/api/permissions.api";
|
import { PermissionsApi } from "@bitwarden/common/admin-console/models/api/permissions.api";
|
||||||
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
|
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
|
||||||
|
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
||||||
import { ProductType } from "@bitwarden/common/enums";
|
import { ProductType } from "@bitwarden/common/enums";
|
||||||
|
import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum";
|
||||||
import { ConfigServiceAbstraction } from "@bitwarden/common/platform/abstractions/config/config.service.abstraction";
|
import { ConfigServiceAbstraction } from "@bitwarden/common/platform/abstractions/config/config.service.abstraction";
|
||||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||||
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
||||||
@ -99,6 +102,8 @@ export class MemberDialogComponent implements OnDestroy {
|
|||||||
groups: [[] as AccessItemValue[]],
|
groups: [[] as AccessItemValue[]],
|
||||||
});
|
});
|
||||||
|
|
||||||
|
protected restrictedAccess$: Observable<boolean>;
|
||||||
|
|
||||||
protected permissionsGroup = this.formBuilder.group({
|
protected permissionsGroup = this.formBuilder.group({
|
||||||
manageAssignedCollectionsGroup: this.formBuilder.group<Record<string, boolean>>({
|
manageAssignedCollectionsGroup: this.formBuilder.group<Record<string, boolean>>({
|
||||||
manageAssignedCollections: false,
|
manageAssignedCollections: false,
|
||||||
@ -144,6 +149,7 @@ export class MemberDialogComponent implements OnDestroy {
|
|||||||
private organizationUserService: OrganizationUserService,
|
private organizationUserService: OrganizationUserService,
|
||||||
private dialogService: DialogService,
|
private dialogService: DialogService,
|
||||||
private configService: ConfigServiceAbstraction,
|
private configService: ConfigServiceAbstraction,
|
||||||
|
private accountService: AccountService,
|
||||||
organizationService: OrganizationService,
|
organizationService: OrganizationService,
|
||||||
) {
|
) {
|
||||||
this.organization$ = organizationService
|
this.organization$ = organizationService
|
||||||
@ -162,12 +168,43 @@ export class MemberDialogComponent implements OnDestroy {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const userDetails$ = this.params.organizationUserId
|
||||||
|
? this.userService.get(this.params.organizationId, this.params.organizationUserId)
|
||||||
|
: of(null);
|
||||||
|
|
||||||
|
// The orgUser cannot manage their own Group assignments if collection access is restricted
|
||||||
|
// TODO: fix disabled state of access-selector rows so that any controls are hidden
|
||||||
|
this.restrictedAccess$ = combineLatest([
|
||||||
|
this.organization$,
|
||||||
|
userDetails$,
|
||||||
|
this.accountService.activeAccount$,
|
||||||
|
this.configService.getFeatureFlag$(FeatureFlag.FlexibleCollectionsV1),
|
||||||
|
]).pipe(
|
||||||
|
map(
|
||||||
|
([organization, userDetails, activeAccount, flexibleCollectionsV1Enabled]) =>
|
||||||
|
// Feature flag conditionals
|
||||||
|
flexibleCollectionsV1Enabled &&
|
||||||
|
organization.flexibleCollections &&
|
||||||
|
// Business logic conditionals
|
||||||
|
userDetails != null &&
|
||||||
|
userDetails.userId == activeAccount.id &&
|
||||||
|
!organization.allowAdminAccessToAllCollectionItems,
|
||||||
|
),
|
||||||
|
shareReplay({ refCount: true, bufferSize: 1 }),
|
||||||
|
);
|
||||||
|
|
||||||
|
this.restrictedAccess$.pipe(takeUntil(this.destroy$)).subscribe((restrictedAccess) => {
|
||||||
|
if (restrictedAccess) {
|
||||||
|
this.formGroup.controls.groups.disable();
|
||||||
|
} else {
|
||||||
|
this.formGroup.controls.groups.enable();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
combineLatest({
|
combineLatest({
|
||||||
organization: this.organization$,
|
organization: this.organization$,
|
||||||
collections: this.collectionAdminService.getAll(this.params.organizationId),
|
collections: this.collectionAdminService.getAll(this.params.organizationId),
|
||||||
userDetails: this.params.organizationUserId
|
userDetails: userDetails$,
|
||||||
? this.userService.get(this.params.organizationId, this.params.organizationUserId)
|
|
||||||
: of(null),
|
|
||||||
groups: groups$,
|
groups: groups$,
|
||||||
})
|
})
|
||||||
.pipe(takeUntil(this.destroy$))
|
.pipe(takeUntil(this.destroy$))
|
||||||
@ -369,7 +406,11 @@ export class MemberDialogComponent implements OnDestroy {
|
|||||||
userView.collections = this.formGroup.value.access
|
userView.collections = this.formGroup.value.access
|
||||||
.filter((v) => v.type === AccessItemType.Collection)
|
.filter((v) => v.type === AccessItemType.Collection)
|
||||||
.map(convertToSelectionView);
|
.map(convertToSelectionView);
|
||||||
userView.groups = this.formGroup.value.groups.map((m) => m.id);
|
|
||||||
|
userView.groups = (await firstValueFrom(this.restrictedAccess$))
|
||||||
|
? null
|
||||||
|
: this.formGroup.value.groups.map((m) => m.id);
|
||||||
|
|
||||||
userView.accessSecretsManager = this.formGroup.value.accessSecretsManager;
|
userView.accessSecretsManager = this.formGroup.value.accessSecretsManager;
|
||||||
|
|
||||||
if (this.editMode) {
|
if (this.editMode) {
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user