mirror of
https://github.com/bitwarden/browser
synced 2025-12-14 15:23:33 +00:00
Merge branch 'master' into feature/org-admin-refresh
This commit is contained in:
@@ -4,7 +4,7 @@
|
|||||||
"browser": true,
|
"browser": true,
|
||||||
"webextensions": true
|
"webextensions": true
|
||||||
},
|
},
|
||||||
"plugins": ["@typescript-eslint", "rxjs", "rxjs-angular"],
|
"plugins": ["@typescript-eslint", "rxjs", "rxjs-angular", "import"],
|
||||||
"parser": "@typescript-eslint/parser",
|
"parser": "@typescript-eslint/parser",
|
||||||
"parserOptions": {
|
"parserOptions": {
|
||||||
"project": ["./tsconfig.eslint.json"],
|
"project": ["./tsconfig.eslint.json"],
|
||||||
@@ -18,6 +18,16 @@
|
|||||||
"prettier",
|
"prettier",
|
||||||
"plugin:rxjs/recommended"
|
"plugin:rxjs/recommended"
|
||||||
],
|
],
|
||||||
|
"settings": {
|
||||||
|
"import/parsers": {
|
||||||
|
"@typescript-eslint/parser": [".ts"]
|
||||||
|
},
|
||||||
|
"import/resolver": {
|
||||||
|
"typescript": {
|
||||||
|
"alwaysTryTypes": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"rules": {
|
"rules": {
|
||||||
"@typescript-eslint/no-explicit-any": "off", // TODO: This should be re-enabled
|
"@typescript-eslint/no-explicit-any": "off", // TODO: This should be re-enabled
|
||||||
"@typescript-eslint/no-unused-vars": ["error", { "args": "none" }],
|
"@typescript-eslint/no-unused-vars": ["error", { "args": "none" }],
|
||||||
@@ -65,6 +75,27 @@
|
|||||||
"selector": "CallExpression[callee.name='svgIcon']"
|
"selector": "CallExpression[callee.name='svgIcon']"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"curly": ["error", "all"]
|
"curly": ["error", "all"],
|
||||||
|
"import/namespace": ["off"], // This doesn't resolve namespace imports correctly, but TS will throw for this anyway
|
||||||
|
"import/no-restricted-paths": [
|
||||||
|
"error",
|
||||||
|
{
|
||||||
|
"zones": [
|
||||||
|
// Do not allow angular/node/electron code to be imported into common
|
||||||
|
{
|
||||||
|
"target": "./libs/common/**/*",
|
||||||
|
"from": "./libs/angular/**/*"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"target": "./libs/common/**/*",
|
||||||
|
"from": "./libs/node/**/*"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"target": "./libs/common/**/*",
|
||||||
|
"from": "./libs/electron/**/*"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
6
.github/workflows/release-qa-web.yml
vendored
6
.github/workflows/release-qa-web.yml
vendored
@@ -34,15 +34,11 @@ jobs:
|
|||||||
uses: bitwarden/gh-actions/download-artifacts@850faad0cf6c02a8c0dc46eddde2363fbd6c373a
|
uses: bitwarden/gh-actions/download-artifacts@850faad0cf6c02a8c0dc46eddde2363fbd6c373a
|
||||||
with:
|
with:
|
||||||
workflow: build-web.yml
|
workflow: build-web.yml
|
||||||
path: apps/web
|
path: apps/web/build
|
||||||
workflow_conclusion: success
|
workflow_conclusion: success
|
||||||
branch: ${{ github.ref_name }}
|
branch: ${{ github.ref_name }}
|
||||||
artifacts: web-*-cloud-QA.zip
|
artifacts: web-*-cloud-QA.zip
|
||||||
|
|
||||||
# This should result in a build directory in the current working directory
|
|
||||||
- name: Unzip build asset
|
|
||||||
working-directory: apps/web
|
|
||||||
run: unzip web-*-cloud-QA.zip
|
|
||||||
|
|
||||||
- name: Checkout Repo
|
- name: Checkout Repo
|
||||||
uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b # v3.0.2
|
uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b # v3.0.2
|
||||||
|
|||||||
@@ -2017,7 +2017,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"lastSeenOn": {
|
"lastSeenOn": {
|
||||||
"message": "last seen on $DATE$",
|
"message": "last seen on: $DATE$",
|
||||||
"placeholders": {
|
"placeholders": {
|
||||||
"date": {
|
"date": {
|
||||||
"content": "$1",
|
"content": "$1",
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ import { KeyConnectorService as KeyConnectorServiceAbstraction } from "@bitwarde
|
|||||||
import { LogService as LogServiceAbstraction } from "@bitwarden/common/abstractions/log.service";
|
import { LogService as LogServiceAbstraction } from "@bitwarden/common/abstractions/log.service";
|
||||||
import { MessagingService as MessagingServiceAbstraction } from "@bitwarden/common/abstractions/messaging.service";
|
import { MessagingService as MessagingServiceAbstraction } from "@bitwarden/common/abstractions/messaging.service";
|
||||||
import { NotificationsService as NotificationsServiceAbstraction } from "@bitwarden/common/abstractions/notifications.service";
|
import { NotificationsService as NotificationsServiceAbstraction } from "@bitwarden/common/abstractions/notifications.service";
|
||||||
import { OrganizationService as OrganizationServiceAbstraction } from "@bitwarden/common/abstractions/organization.service";
|
import { OrganizationService as OrganizationServiceAbstraction } from "@bitwarden/common/abstractions/organization/organization.service.abstraction";
|
||||||
import { PasswordGenerationService as PasswordGenerationServiceAbstraction } from "@bitwarden/common/abstractions/passwordGeneration.service";
|
import { PasswordGenerationService as PasswordGenerationServiceAbstraction } from "@bitwarden/common/abstractions/passwordGeneration.service";
|
||||||
import { PlatformUtilsService as PlatformUtilsServiceAbstraction } from "@bitwarden/common/abstractions/platformUtils.service";
|
import { PlatformUtilsService as PlatformUtilsServiceAbstraction } from "@bitwarden/common/abstractions/platformUtils.service";
|
||||||
import { PolicyApiServiceAbstraction } from "@bitwarden/common/abstractions/policy/policy-api.service.abstraction";
|
import { PolicyApiServiceAbstraction } from "@bitwarden/common/abstractions/policy/policy-api.service.abstraction";
|
||||||
@@ -27,6 +27,7 @@ import { SendService as SendServiceAbstraction } from "@bitwarden/common/abstrac
|
|||||||
import { SettingsService as SettingsServiceAbstraction } from "@bitwarden/common/abstractions/settings.service";
|
import { SettingsService as SettingsServiceAbstraction } from "@bitwarden/common/abstractions/settings.service";
|
||||||
import { AbstractStorageService } from "@bitwarden/common/abstractions/storage.service";
|
import { AbstractStorageService } from "@bitwarden/common/abstractions/storage.service";
|
||||||
import { SyncService as SyncServiceAbstraction } from "@bitwarden/common/abstractions/sync/sync.service.abstraction";
|
import { SyncService as SyncServiceAbstraction } from "@bitwarden/common/abstractions/sync/sync.service.abstraction";
|
||||||
|
import { SyncNotifierService as SyncNotifierServiceAbstraction } from "@bitwarden/common/abstractions/sync/syncNotifier.service.abstraction";
|
||||||
import { SystemService as SystemServiceAbstraction } from "@bitwarden/common/abstractions/system.service";
|
import { SystemService as SystemServiceAbstraction } from "@bitwarden/common/abstractions/system.service";
|
||||||
import { TokenService as TokenServiceAbstraction } from "@bitwarden/common/abstractions/token.service";
|
import { TokenService as TokenServiceAbstraction } from "@bitwarden/common/abstractions/token.service";
|
||||||
import { TotpService as TotpServiceAbstraction } from "@bitwarden/common/abstractions/totp.service";
|
import { TotpService as TotpServiceAbstraction } from "@bitwarden/common/abstractions/totp.service";
|
||||||
@@ -58,7 +59,7 @@ import { FolderApiService } from "@bitwarden/common/services/folder/folder-api.s
|
|||||||
import { KeyConnectorService } from "@bitwarden/common/services/keyConnector.service";
|
import { KeyConnectorService } from "@bitwarden/common/services/keyConnector.service";
|
||||||
import { MemoryStorageService } from "@bitwarden/common/services/memoryStorage.service";
|
import { MemoryStorageService } from "@bitwarden/common/services/memoryStorage.service";
|
||||||
import { NotificationsService } from "@bitwarden/common/services/notifications.service";
|
import { NotificationsService } from "@bitwarden/common/services/notifications.service";
|
||||||
import { OrganizationService } from "@bitwarden/common/services/organization.service";
|
import { OrganizationService } from "@bitwarden/common/services/organization/organization.service";
|
||||||
import { PasswordGenerationService } from "@bitwarden/common/services/passwordGeneration.service";
|
import { PasswordGenerationService } from "@bitwarden/common/services/passwordGeneration.service";
|
||||||
import { PolicyApiService } from "@bitwarden/common/services/policy/policy-api.service";
|
import { PolicyApiService } from "@bitwarden/common/services/policy/policy-api.service";
|
||||||
import { PolicyService } from "@bitwarden/common/services/policy/policy.service";
|
import { PolicyService } from "@bitwarden/common/services/policy/policy.service";
|
||||||
@@ -68,6 +69,7 @@ import { SendService } from "@bitwarden/common/services/send.service";
|
|||||||
import { SettingsService } from "@bitwarden/common/services/settings.service";
|
import { SettingsService } from "@bitwarden/common/services/settings.service";
|
||||||
import { StateMigrationService } from "@bitwarden/common/services/stateMigration.service";
|
import { StateMigrationService } from "@bitwarden/common/services/stateMigration.service";
|
||||||
import { SyncService } from "@bitwarden/common/services/sync/sync.service";
|
import { SyncService } from "@bitwarden/common/services/sync/sync.service";
|
||||||
|
import { SyncNotifierService } from "@bitwarden/common/services/sync/syncNotifier.service";
|
||||||
import { SystemService } from "@bitwarden/common/services/system.service";
|
import { SystemService } from "@bitwarden/common/services/system.service";
|
||||||
import { TokenService } from "@bitwarden/common/services/token.service";
|
import { TokenService } from "@bitwarden/common/services/token.service";
|
||||||
import { TotpService } from "@bitwarden/common/services/totp.service";
|
import { TotpService } from "@bitwarden/common/services/totp.service";
|
||||||
@@ -158,6 +160,7 @@ export default class MainBackground {
|
|||||||
folderApiService: FolderApiServiceAbstraction;
|
folderApiService: FolderApiServiceAbstraction;
|
||||||
policyApiService: PolicyApiServiceAbstraction;
|
policyApiService: PolicyApiServiceAbstraction;
|
||||||
userVerificationApiService: UserVerificationApiServiceAbstraction;
|
userVerificationApiService: UserVerificationApiServiceAbstraction;
|
||||||
|
syncNotifierService: SyncNotifierServiceAbstraction;
|
||||||
|
|
||||||
// Passed to the popup for Safari to workaround issues with theming, downloading, etc.
|
// Passed to the popup for Safari to workaround issues with theming, downloading, etc.
|
||||||
backgroundWindow = window;
|
backgroundWindow = window;
|
||||||
@@ -298,7 +301,8 @@ export default class MainBackground {
|
|||||||
this.cryptoFunctionService,
|
this.cryptoFunctionService,
|
||||||
this.stateService
|
this.stateService
|
||||||
);
|
);
|
||||||
this.organizationService = new OrganizationService(this.stateService);
|
this.syncNotifierService = new SyncNotifierService();
|
||||||
|
this.organizationService = new OrganizationService(this.stateService, this.syncNotifierService);
|
||||||
this.policyService = new PolicyService(this.stateService, this.organizationService);
|
this.policyService = new PolicyService(this.stateService, this.organizationService);
|
||||||
this.policyApiService = new PolicyApiService(
|
this.policyApiService = new PolicyApiService(
|
||||||
this.policyService,
|
this.policyService,
|
||||||
@@ -388,9 +392,9 @@ export default class MainBackground {
|
|||||||
this.logService,
|
this.logService,
|
||||||
this.keyConnectorService,
|
this.keyConnectorService,
|
||||||
this.stateService,
|
this.stateService,
|
||||||
this.organizationService,
|
|
||||||
this.providerService,
|
this.providerService,
|
||||||
this.folderApiService,
|
this.folderApiService,
|
||||||
|
this.syncNotifierService,
|
||||||
logoutCallback
|
logoutCallback
|
||||||
);
|
);
|
||||||
this.eventService = new EventService(
|
this.eventService = new EventService(
|
||||||
|
|||||||
@@ -1,12 +1,17 @@
|
|||||||
import { OrganizationService as AbstractOrganizationService } from "@bitwarden/common/abstractions/organization.service";
|
import { OrganizationService as AbstractOrganizationService } from "@bitwarden/common/abstractions/organization/organization.service.abstraction";
|
||||||
import { OrganizationService } from "@bitwarden/common/services/organization.service";
|
import { OrganizationService } from "@bitwarden/common/services/organization/organization.service";
|
||||||
|
|
||||||
import { FactoryOptions, CachedServices, factory } from "./factory-options";
|
import { FactoryOptions, CachedServices, factory } from "./factory-options";
|
||||||
import { stateServiceFactory, StateServiceInitOptions } from "./state-service.factory";
|
import { stateServiceFactory, StateServiceInitOptions } from "./state-service.factory";
|
||||||
|
import {
|
||||||
|
syncNotifierServiceFactory,
|
||||||
|
SyncNotifierServiceInitOptions,
|
||||||
|
} from "./sync-notifier-service.factory";
|
||||||
|
|
||||||
type OrganizationServiceFactoryOptions = FactoryOptions;
|
type OrganizationServiceFactoryOptions = FactoryOptions;
|
||||||
|
|
||||||
export type OrganizationServiceInitOptions = OrganizationServiceFactoryOptions &
|
export type OrganizationServiceInitOptions = OrganizationServiceFactoryOptions &
|
||||||
|
SyncNotifierServiceInitOptions &
|
||||||
StateServiceInitOptions;
|
StateServiceInitOptions;
|
||||||
|
|
||||||
export function organizationServiceFactory(
|
export function organizationServiceFactory(
|
||||||
@@ -17,6 +22,10 @@ export function organizationServiceFactory(
|
|||||||
cache,
|
cache,
|
||||||
"organizationService",
|
"organizationService",
|
||||||
opts,
|
opts,
|
||||||
async () => new OrganizationService(await stateServiceFactory(cache, opts))
|
async () =>
|
||||||
|
new OrganizationService(
|
||||||
|
await stateServiceFactory(cache, opts),
|
||||||
|
await syncNotifierServiceFactory(cache, opts)
|
||||||
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,17 @@
|
|||||||
|
import { SyncNotifierService as AbstractSyncNotifierService } from "@bitwarden/common/abstractions/sync/syncNotifier.service.abstraction";
|
||||||
|
import { SyncNotifierService } from "@bitwarden/common/services/sync/syncNotifier.service";
|
||||||
|
|
||||||
|
import { FactoryOptions, CachedServices, factory } from "./factory-options";
|
||||||
|
|
||||||
|
type SyncNotifierServiceFactoryOptions = FactoryOptions;
|
||||||
|
|
||||||
|
export type SyncNotifierServiceInitOptions = SyncNotifierServiceFactoryOptions;
|
||||||
|
|
||||||
|
export function syncNotifierServiceFactory(
|
||||||
|
cache: { syncNotifierService?: AbstractSyncNotifierService } & CachedServices,
|
||||||
|
opts: SyncNotifierServiceInitOptions
|
||||||
|
): Promise<AbstractSyncNotifierService> {
|
||||||
|
return factory(cache, "syncNotifierService", opts, () =>
|
||||||
|
Promise.resolve(new SyncNotifierService())
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -26,7 +26,7 @@ import { KeyConnectorService } from "@bitwarden/common/abstractions/keyConnector
|
|||||||
import { LogService as LogServiceAbstraction } from "@bitwarden/common/abstractions/log.service";
|
import { LogService as LogServiceAbstraction } from "@bitwarden/common/abstractions/log.service";
|
||||||
import { MessagingService } from "@bitwarden/common/abstractions/messaging.service";
|
import { MessagingService } from "@bitwarden/common/abstractions/messaging.service";
|
||||||
import { NotificationsService } from "@bitwarden/common/abstractions/notifications.service";
|
import { NotificationsService } from "@bitwarden/common/abstractions/notifications.service";
|
||||||
import { OrganizationService } from "@bitwarden/common/abstractions/organization.service";
|
import { OrganizationService } from "@bitwarden/common/abstractions/organization/organization.service.abstraction";
|
||||||
import { PasswordGenerationService } from "@bitwarden/common/abstractions/passwordGeneration.service";
|
import { PasswordGenerationService } from "@bitwarden/common/abstractions/passwordGeneration.service";
|
||||||
import { PasswordRepromptService as PasswordRepromptServiceAbstraction } from "@bitwarden/common/abstractions/passwordReprompt.service";
|
import { PasswordRepromptService as PasswordRepromptServiceAbstraction } from "@bitwarden/common/abstractions/passwordReprompt.service";
|
||||||
import { PlatformUtilsService } from "@bitwarden/common/abstractions/platformUtils.service";
|
import { PlatformUtilsService } from "@bitwarden/common/abstractions/platformUtils.service";
|
||||||
|
|||||||
@@ -14,7 +14,7 @@
|
|||||||
<p class="text-center" *ngIf="isCloud">
|
<p class="text-center" *ngIf="isCloud">
|
||||||
{{ "serverVersion" | i18n }}: {{ this.serverConfig?.version }}
|
{{ "serverVersion" | i18n }}: {{ this.serverConfig?.version }}
|
||||||
<span *ngIf="!serverConfig.isValid()">
|
<span *ngIf="!serverConfig.isValid()">
|
||||||
({{ "lastSeenOn" | i18n }}: {{ serverConfig.utcDate | date: "mediumDate" }})
|
({{ "lastSeenOn" | i18n: (serverConfig.utcDate | date: "mediumDate") }})
|
||||||
</span>
|
</span>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
@@ -24,7 +24,7 @@
|
|||||||
{{ "serverVersion" | i18n }} <small>({{ "thirdParty" | i18n }})</small>:
|
{{ "serverVersion" | i18n }} <small>({{ "thirdParty" | i18n }})</small>:
|
||||||
{{ this.serverConfig?.version }}
|
{{ this.serverConfig?.version }}
|
||||||
<span *ngIf="!serverConfig.isValid()">
|
<span *ngIf="!serverConfig.isValid()">
|
||||||
({{ "lastSeenOn" | i18n }}: {{ serverConfig.utcDate | date: "mediumDate" }})
|
({{ "lastSeenOn" | i18n: (serverConfig.utcDate | date: "mediumDate") }})
|
||||||
</span>
|
</span>
|
||||||
</p>
|
</p>
|
||||||
<div class="text-center">
|
<div class="text-center">
|
||||||
@@ -36,7 +36,7 @@
|
|||||||
{{ "serverVersion" | i18n }} <small>({{ "selfHosted" | i18n }})</small>:
|
{{ "serverVersion" | i18n }} <small>({{ "selfHosted" | i18n }})</small>:
|
||||||
{{ this.serverConfig?.version }}
|
{{ this.serverConfig?.version }}
|
||||||
<span *ngIf="!serverConfig.isValid()">
|
<span *ngIf="!serverConfig.isValid()">
|
||||||
({{ "lastSeenOn" | i18n }}: {{ serverConfig.utcDate | date: "mediumDate" }})
|
({{ "lastSeenOn" | i18n: (serverConfig.utcDate | date: "mediumDate") }})
|
||||||
</span>
|
</span>
|
||||||
</p>
|
</p>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ import { FolderService } from "@bitwarden/common/abstractions/folder/folder.serv
|
|||||||
import { I18nService } from "@bitwarden/common/abstractions/i18n.service";
|
import { I18nService } from "@bitwarden/common/abstractions/i18n.service";
|
||||||
import { LogService } from "@bitwarden/common/abstractions/log.service";
|
import { LogService } from "@bitwarden/common/abstractions/log.service";
|
||||||
import { MessagingService } from "@bitwarden/common/abstractions/messaging.service";
|
import { MessagingService } from "@bitwarden/common/abstractions/messaging.service";
|
||||||
import { OrganizationService } from "@bitwarden/common/abstractions/organization.service";
|
import { OrganizationService } from "@bitwarden/common/abstractions/organization/organization.service.abstraction";
|
||||||
import { PasswordRepromptService } from "@bitwarden/common/abstractions/passwordReprompt.service";
|
import { PasswordRepromptService } from "@bitwarden/common/abstractions/passwordReprompt.service";
|
||||||
import { PlatformUtilsService } from "@bitwarden/common/abstractions/platformUtils.service";
|
import { PlatformUtilsService } from "@bitwarden/common/abstractions/platformUtils.service";
|
||||||
import { PolicyService } from "@bitwarden/common/abstractions/policy/policy.service.abstraction";
|
import { PolicyService } from "@bitwarden/common/abstractions/policy/policy.service.abstraction";
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import { CipherService } from "@bitwarden/common/abstractions/cipher.service";
|
|||||||
import { CollectionService } from "@bitwarden/common/abstractions/collection.service";
|
import { CollectionService } from "@bitwarden/common/abstractions/collection.service";
|
||||||
import { FolderService } from "@bitwarden/common/abstractions/folder/folder.service.abstraction";
|
import { FolderService } from "@bitwarden/common/abstractions/folder/folder.service.abstraction";
|
||||||
import { I18nService } from "@bitwarden/common/abstractions/i18n.service";
|
import { I18nService } from "@bitwarden/common/abstractions/i18n.service";
|
||||||
import { OrganizationService } from "@bitwarden/common/abstractions/organization.service";
|
import { OrganizationService } from "@bitwarden/common/abstractions/organization/organization.service.abstraction";
|
||||||
import { PlatformUtilsService } from "@bitwarden/common/abstractions/platformUtils.service";
|
import { PlatformUtilsService } from "@bitwarden/common/abstractions/platformUtils.service";
|
||||||
import { SearchService } from "@bitwarden/common/abstractions/search.service";
|
import { SearchService } from "@bitwarden/common/abstractions/search.service";
|
||||||
import { CipherType } from "@bitwarden/common/enums/cipherType";
|
import { CipherType } from "@bitwarden/common/enums/cipherType";
|
||||||
@@ -78,7 +78,7 @@ export class CiphersComponent extends BaseCiphersComponent implements OnInit, On
|
|||||||
|
|
||||||
async ngOnInit() {
|
async ngOnInit() {
|
||||||
this.searchTypeSearch = !this.platformUtilsService.isSafari();
|
this.searchTypeSearch = !this.platformUtilsService.isSafari();
|
||||||
this.showOrganizations = await this.organizationService.hasOrganizations();
|
this.showOrganizations = 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) => {
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import { Router } from "@angular/router";
|
|||||||
import { BroadcasterService } from "@bitwarden/common/abstractions/broadcaster.service";
|
import { BroadcasterService } from "@bitwarden/common/abstractions/broadcaster.service";
|
||||||
import { CipherService } from "@bitwarden/common/abstractions/cipher.service";
|
import { CipherService } from "@bitwarden/common/abstractions/cipher.service";
|
||||||
import { I18nService } from "@bitwarden/common/abstractions/i18n.service";
|
import { I18nService } from "@bitwarden/common/abstractions/i18n.service";
|
||||||
import { OrganizationService } from "@bitwarden/common/abstractions/organization.service";
|
import { OrganizationService } from "@bitwarden/common/abstractions/organization/organization.service.abstraction";
|
||||||
import { PasswordRepromptService } from "@bitwarden/common/abstractions/passwordReprompt.service";
|
import { PasswordRepromptService } from "@bitwarden/common/abstractions/passwordReprompt.service";
|
||||||
import { PlatformUtilsService } from "@bitwarden/common/abstractions/platformUtils.service";
|
import { PlatformUtilsService } from "@bitwarden/common/abstractions/platformUtils.service";
|
||||||
import { SearchService } from "@bitwarden/common/abstractions/search.service";
|
import { SearchService } from "@bitwarden/common/abstractions/search.service";
|
||||||
@@ -219,7 +219,7 @@ export class CurrentTabComponent implements OnInit, OnDestroy {
|
|||||||
const otherTypes: CipherType[] = [];
|
const otherTypes: CipherType[] = [];
|
||||||
const dontShowCards = await this.stateService.getDontShowCardsCurrentTab();
|
const dontShowCards = await this.stateService.getDontShowCardsCurrentTab();
|
||||||
const dontShowIdentities = await this.stateService.getDontShowIdentitiesCurrentTab();
|
const dontShowIdentities = await this.stateService.getDontShowIdentitiesCurrentTab();
|
||||||
this.showOrganizations = await this.organizationService.hasOrganizations();
|
this.showOrganizations = this.organizationService.hasOrganizations();
|
||||||
if (!dontShowCards) {
|
if (!dontShowCards) {
|
||||||
otherTypes.push(CipherType.Card);
|
otherTypes.push(CipherType.Card);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,70 +1,76 @@
|
|||||||
<form #form (ngSubmit)="submit()" [appApiAction]="formPromise">
|
<form #form (ngSubmit)="submit()" [appApiAction]="formPromise">
|
||||||
<header>
|
<ng-container *ngIf="organizations$ | async as organizations">
|
||||||
<div class="left">
|
<header>
|
||||||
<button type="button" (click)="cancel()">{{ "cancel" | i18n }}</button>
|
<div class="left">
|
||||||
</div>
|
<button type="button" (click)="cancel()">{{ "cancel" | i18n }}</button>
|
||||||
<h1 class="center">
|
|
||||||
<span class="title">{{ "moveToOrganization" | i18n }}</span>
|
|
||||||
</h1>
|
|
||||||
<div class="right">
|
|
||||||
<button
|
|
||||||
type="submit"
|
|
||||||
[disabled]="form.loading || !canSave"
|
|
||||||
*ngIf="organizations && organizations.length"
|
|
||||||
>
|
|
||||||
<span [hidden]="form.loading">{{ "move" | i18n }}</span>
|
|
||||||
<i class="bwi bwi-spinner bwi-lg bwi-spin" [hidden]="!form.loading" aria-hidden="true"></i>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</header>
|
|
||||||
<main tabindex="-1">
|
|
||||||
<div class="box">
|
|
||||||
<div class="box-content" *ngIf="!organizations || !organizations.length">
|
|
||||||
<div class="box-content-row padded no-hover">
|
|
||||||
{{ "noOrganizationsList" | i18n }}
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="box-content" *ngIf="organizations && organizations.length">
|
<h1 class="center">
|
||||||
<div class="box-content-row" appBoxRow>
|
<span class="title">{{ "moveToOrganization" | i18n }}</span>
|
||||||
<label for="organization">{{ "organization" | i18n }}</label>
|
</h1>
|
||||||
<select
|
<div class="right">
|
||||||
id="organization"
|
<button
|
||||||
name="OrganizationId"
|
type="submit"
|
||||||
[(ngModel)]="organizationId"
|
[disabled]="form.loading || !canSave"
|
||||||
(change)="filterCollections()"
|
*ngIf="organizations && organizations.length"
|
||||||
>
|
|
||||||
<option *ngFor="let o of organizations" [ngValue]="o.id">{{ o.name }}</option>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="box-footer">
|
|
||||||
{{ "moveToOrgDesc" | i18n }}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="box" *ngIf="organizations && organizations.length">
|
|
||||||
<h2 class="box-header">
|
|
||||||
{{ "collections" | i18n }}
|
|
||||||
</h2>
|
|
||||||
<div class="box-content" *ngIf="!collections || !collections.length">
|
|
||||||
<div class="box-content-row padded no-hover">
|
|
||||||
{{ "noCollectionsInList" | i18n }}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="box-content" *ngIf="collections && collections.length">
|
|
||||||
<div
|
|
||||||
class="box-content-row box-content-row-checkbox"
|
|
||||||
*ngFor="let c of collections; let i = index"
|
|
||||||
appBoxRow
|
|
||||||
>
|
>
|
||||||
<label for="collection_{{ i }}">{{ c.name }}</label>
|
<span [hidden]="form.loading">{{ "move" | i18n }}</span>
|
||||||
<input
|
<i
|
||||||
id="collection_{{ i }}"
|
class="bwi bwi-spinner bwi-lg bwi-spin"
|
||||||
type="checkbox"
|
[hidden]="!form.loading"
|
||||||
[(ngModel)]="c.checked"
|
aria-hidden="true"
|
||||||
name="Collection[{{ i }}].Checked"
|
></i>
|
||||||
/>
|
</button>
|
||||||
|
</div>
|
||||||
|
</header>
|
||||||
|
<main tabindex="-1">
|
||||||
|
<div class="box">
|
||||||
|
<div class="box-content" *ngIf="!organizations || !organizations.length">
|
||||||
|
<div class="box-content-row padded no-hover">
|
||||||
|
{{ "noOrganizationsList" | i18n }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="box-content" *ngIf="organizations && organizations.length">
|
||||||
|
<div class="box-content-row" appBoxRow>
|
||||||
|
<label for="organization">{{ "organization" | i18n }}</label>
|
||||||
|
<select
|
||||||
|
id="organization"
|
||||||
|
name="OrganizationId"
|
||||||
|
[(ngModel)]="organizationId"
|
||||||
|
(change)="filterCollections()"
|
||||||
|
>
|
||||||
|
<option *ngFor="let o of organizations" [ngValue]="o.id">{{ o.name }}</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="box-footer">
|
||||||
|
{{ "moveToOrgDesc" | i18n }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<div class="box" *ngIf="organizations && organizations.length">
|
||||||
</main>
|
<h2 class="box-header">
|
||||||
|
{{ "collections" | i18n }}
|
||||||
|
</h2>
|
||||||
|
<div class="box-content" *ngIf="!collections || !collections.length">
|
||||||
|
<div class="box-content-row padded no-hover">
|
||||||
|
{{ "noCollectionsInList" | i18n }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="box-content" *ngIf="collections && collections.length">
|
||||||
|
<div
|
||||||
|
class="box-content-row box-content-row-checkbox"
|
||||||
|
*ngFor="let c of collections; let i = index"
|
||||||
|
appBoxRow
|
||||||
|
>
|
||||||
|
<label for="collection_{{ i }}">{{ c.name }}</label>
|
||||||
|
<input
|
||||||
|
id="collection_{{ i }}"
|
||||||
|
type="checkbox"
|
||||||
|
[(ngModel)]="c.checked"
|
||||||
|
name="Collection[{{ i }}].Checked"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
</ng-container>
|
||||||
</form>
|
</form>
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import { CipherService } from "@bitwarden/common/abstractions/cipher.service";
|
|||||||
import { CollectionService } from "@bitwarden/common/abstractions/collection.service";
|
import { CollectionService } from "@bitwarden/common/abstractions/collection.service";
|
||||||
import { I18nService } from "@bitwarden/common/abstractions/i18n.service";
|
import { I18nService } from "@bitwarden/common/abstractions/i18n.service";
|
||||||
import { LogService } from "@bitwarden/common/abstractions/log.service";
|
import { LogService } from "@bitwarden/common/abstractions/log.service";
|
||||||
import { OrganizationService } from "@bitwarden/common/abstractions/organization.service";
|
import { OrganizationService } from "@bitwarden/common/abstractions/organization/organization.service.abstraction";
|
||||||
import { PlatformUtilsService } from "@bitwarden/common/abstractions/platformUtils.service";
|
import { PlatformUtilsService } from "@bitwarden/common/abstractions/platformUtils.service";
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
|
|||||||
@@ -1,71 +1,70 @@
|
|||||||
<div class="content org-filter-content" *ngIf="loaded && show">
|
<ng-container *ngIf="loaded && organizations$ | async as organizations">
|
||||||
<button
|
<div class="content org-filter-content" *ngIf="loaded && shouldShow(organizations)">
|
||||||
#toggleVaults
|
<ng-container *ngIf="selectedVault$ | async as vaultFilterDisplay">
|
||||||
class="org-filter"
|
|
||||||
(click)="openOverlay()"
|
|
||||||
aria-haspopup="menu"
|
|
||||||
aria-controls="cdk-overlay-container"
|
|
||||||
[attr.aria-expanded]="isOpen"
|
|
||||||
[attr.aria-label]="vaultFilterDisplay"
|
|
||||||
>
|
|
||||||
{{ vaultFilterDisplay | ellipsis: 45 }}
|
|
||||||
<i
|
|
||||||
class="bwi bwi-sm"
|
|
||||||
aria-hidden="true"
|
|
||||||
[ngClass]="{ 'bwi-angle-down': !isOpen, 'bwi-chevron-up': isOpen }"
|
|
||||||
></i>
|
|
||||||
</button>
|
|
||||||
<ng-template class="vault-select-container" #vaultSelectorTemplate>
|
|
||||||
<div
|
|
||||||
class="vault-select"
|
|
||||||
[@transformPanel]="'open'"
|
|
||||||
cdkTrapFocus
|
|
||||||
cdkTrapFocusAutoCapture
|
|
||||||
role="dialog"
|
|
||||||
aria-modal="true"
|
|
||||||
>
|
|
||||||
<button
|
<button
|
||||||
appStopClick
|
#toggleVaults
|
||||||
(click)="selectAllVaults()"
|
class="org-filter"
|
||||||
[ngClass]="{ active: !myVaultOnly && !selectOrganizationId }"
|
(click)="openOverlay()"
|
||||||
appA11yTitle="{{ 'vault' | i18n }}: {{ 'allVaults' | i18n }}"
|
aria-haspopup="menu"
|
||||||
>
|
aria-controls="cdk-overlay-container"
|
||||||
<i class="bwi bwi-fw bwi-filter" aria-hidden="true"></i>
|
[attr.aria-expanded]="isOpen"
|
||||||
{{ "allVaults" | i18n }}
|
[attr.aria-label]="vaultFilterDisplay"
|
||||||
</button>
|
|
||||||
<button
|
|
||||||
*ngIf="!enforcePersonalOwnwership"
|
|
||||||
appStopClick
|
|
||||||
(click)="selectMyVault()"
|
|
||||||
appA11yTitle="{{ 'vault' | i18n }}: {{ 'myVault' | i18n }}"
|
|
||||||
>
|
|
||||||
<i class="bwi bwi-fw bwi-user" aria-hidden="true"></i>
|
|
||||||
{{ "myVault" | i18n }}
|
|
||||||
</button>
|
|
||||||
<button
|
|
||||||
*ngFor="let organization of organizations"
|
|
||||||
appStopClick
|
|
||||||
(click)="selectOrganization(organization)"
|
|
||||||
appA11yTitle="{{ 'vault' | i18n }}: {{ organization.name }}"
|
|
||||||
>
|
>
|
||||||
|
{{ vaultFilterDisplay | ellipsis: 45 }}
|
||||||
<i
|
<i
|
||||||
*ngIf="organization.planProductType !== 1"
|
class="bwi bwi-sm"
|
||||||
class="bwi bwi-fw bwi-business"
|
|
||||||
aria-hidden="true"
|
aria-hidden="true"
|
||||||
></i>
|
[ngClass]="{ 'bwi-angle-down': !isOpen, 'bwi-chevron-up': isOpen }"
|
||||||
<i
|
|
||||||
*ngIf="organization.planProductType === 1"
|
|
||||||
class="bwi bwi-fw bwi-family"
|
|
||||||
aria-hidden="true"
|
|
||||||
></i>
|
|
||||||
<span> {{ organization.name | ellipsis: (organization.enabled ? 21 : 18):true }}</span>
|
|
||||||
<i
|
|
||||||
*ngIf="!organization.enabled"
|
|
||||||
class="bwi bwi-fw bwi-exclamation-triangle text-danger"
|
|
||||||
aria-label="{{ 'organizationIsDisabled' | i18n }}"
|
|
||||||
appA11yTitle="{{ 'organizationIsDisabled' | i18n }}"
|
|
||||||
></i>
|
></i>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</ng-container>
|
||||||
</ng-template>
|
<ng-template class="vault-select-container" #vaultSelectorTemplate>
|
||||||
</div>
|
<div
|
||||||
|
class="vault-select"
|
||||||
|
[@transformPanel]="'open'"
|
||||||
|
cdkTrapFocus
|
||||||
|
cdkTrapFocusAutoCapture
|
||||||
|
role="dialog"
|
||||||
|
aria-modal="true"
|
||||||
|
>
|
||||||
|
<button
|
||||||
|
appStopClick
|
||||||
|
(click)="selectAllVaults()"
|
||||||
|
[ngClass]="{ active: !myVaultOnly && !selectOrganizationId }"
|
||||||
|
>
|
||||||
|
<i class="bwi bwi-fw bwi-filter" aria-hidden="true"></i>
|
||||||
|
{{ "allVaults" | i18n }}
|
||||||
|
</button>
|
||||||
|
<button *ngIf="!enforcePersonalOwnwership" appStopClick (click)="selectMyVault()">
|
||||||
|
<i class="bwi bwi-fw bwi-user" aria-hidden="true"></i>
|
||||||
|
{{ "myVault" | i18n }}
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
*ngFor="let organization of organizations"
|
||||||
|
appStopClick
|
||||||
|
(click)="selectOrganization(organization)"
|
||||||
|
>
|
||||||
|
<i
|
||||||
|
*ngIf="organization.planProductType !== 1"
|
||||||
|
class="bwi bwi-fw bwi-business"
|
||||||
|
aria-hidden="true"
|
||||||
|
></i>
|
||||||
|
<i
|
||||||
|
*ngIf="organization.planProductType === 1"
|
||||||
|
class="bwi bwi-fw bwi-family"
|
||||||
|
aria-hidden="true"
|
||||||
|
></i>
|
||||||
|
<span
|
||||||
|
> {{ organization.name | ellipsis: (organization.enabled ? 21 : 18):true }}</span
|
||||||
|
>
|
||||||
|
<i
|
||||||
|
*ngIf="!organization.enabled"
|
||||||
|
class="bwi bwi-fw bwi-exclamation-triangle text-danger"
|
||||||
|
aria-label="{{ 'organizationIsDisabled' | i18n }}"
|
||||||
|
appA11yTitle="{{ 'organizationIsDisabled' | i18n }}"
|
||||||
|
></i>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</ng-template>
|
||||||
|
</div>
|
||||||
|
</ng-container>
|
||||||
|
|||||||
@@ -5,19 +5,19 @@ import {
|
|||||||
Component,
|
Component,
|
||||||
ElementRef,
|
ElementRef,
|
||||||
EventEmitter,
|
EventEmitter,
|
||||||
NgZone,
|
|
||||||
OnInit,
|
OnInit,
|
||||||
Output,
|
Output,
|
||||||
TemplateRef,
|
TemplateRef,
|
||||||
ViewChild,
|
ViewChild,
|
||||||
ViewContainerRef,
|
ViewContainerRef,
|
||||||
HostListener,
|
HostListener,
|
||||||
|
OnDestroy,
|
||||||
} from "@angular/core";
|
} from "@angular/core";
|
||||||
import { merge } from "rxjs";
|
import { BehaviorSubject, concatMap, map, merge, Observable, Subject, takeUntil } from "rxjs";
|
||||||
|
|
||||||
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 { BroadcasterService } from "@bitwarden/common/abstractions/broadcaster.service";
|
|
||||||
import { I18nService } from "@bitwarden/common/abstractions/i18n.service";
|
import { I18nService } from "@bitwarden/common/abstractions/i18n.service";
|
||||||
|
import { OrganizationService } from "@bitwarden/common/abstractions/organization/organization.service.abstraction";
|
||||||
import { PlatformUtilsService } from "@bitwarden/common/abstractions/platformUtils.service";
|
import { PlatformUtilsService } from "@bitwarden/common/abstractions/platformUtils.service";
|
||||||
import { Organization } from "@bitwarden/common/models/domain/organization";
|
import { Organization } from "@bitwarden/common/models/domain/organization";
|
||||||
|
|
||||||
@@ -47,20 +47,22 @@ import { VaultFilterService } from "../../services/vaultFilter.service";
|
|||||||
]),
|
]),
|
||||||
],
|
],
|
||||||
})
|
})
|
||||||
// eslint-disable-next-line rxjs-angular/prefer-takeuntil
|
export class VaultSelectComponent implements OnInit, OnDestroy {
|
||||||
export class VaultSelectComponent implements OnInit {
|
|
||||||
@Output() onVaultSelectionChanged = new EventEmitter();
|
@Output() onVaultSelectionChanged = new EventEmitter();
|
||||||
|
|
||||||
@ViewChild("toggleVaults", { read: ElementRef })
|
@ViewChild("toggleVaults", { read: ElementRef })
|
||||||
buttonRef: ElementRef<HTMLButtonElement>;
|
buttonRef: ElementRef<HTMLButtonElement>;
|
||||||
@ViewChild("vaultSelectorTemplate", { read: TemplateRef }) templateRef: TemplateRef<HTMLElement>;
|
@ViewChild("vaultSelectorTemplate", { read: TemplateRef }) templateRef: TemplateRef<HTMLElement>;
|
||||||
|
|
||||||
|
private _selectedVault = new BehaviorSubject<string>(null);
|
||||||
|
|
||||||
isOpen = false;
|
isOpen = false;
|
||||||
loaded = false;
|
loaded = false;
|
||||||
organizations: Organization[];
|
organizations$: Observable<Organization[]>;
|
||||||
|
selectedVault$: Observable<string> = this._selectedVault.asObservable();
|
||||||
|
|
||||||
vaultFilter: VaultFilter = new VaultFilter();
|
vaultFilter: VaultFilter = new VaultFilter();
|
||||||
vaultFilterDisplay = "";
|
enforcePersonalOwnership = false;
|
||||||
enforcePersonalOwnwership = false;
|
|
||||||
overlayPostition: ConnectedPosition[] = [
|
overlayPostition: ConnectedPosition[] = [
|
||||||
{
|
{
|
||||||
originX: "start",
|
originX: "start",
|
||||||
@@ -71,22 +73,22 @@ export class VaultSelectComponent implements OnInit {
|
|||||||
];
|
];
|
||||||
|
|
||||||
private overlayRef: OverlayRef;
|
private overlayRef: OverlayRef;
|
||||||
|
private _destroy = new Subject<void>();
|
||||||
|
|
||||||
get show() {
|
shouldShow(organizations: Organization[]): boolean {
|
||||||
return (
|
return (
|
||||||
(this.organizations.length > 0 && !this.enforcePersonalOwnwership) ||
|
(organizations.length > 0 && !this.enforcePersonalOwnership) ||
|
||||||
(this.organizations.length > 1 && this.enforcePersonalOwnwership)
|
(organizations.length > 1 && this.enforcePersonalOwnership)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private vaultFilterService: VaultFilterService,
|
private vaultFilterService: VaultFilterService,
|
||||||
private i18nService: I18nService,
|
private i18nService: I18nService,
|
||||||
private ngZone: NgZone,
|
|
||||||
private broadcasterService: BroadcasterService,
|
|
||||||
private overlay: Overlay,
|
private overlay: Overlay,
|
||||||
private viewContainerRef: ViewContainerRef,
|
private viewContainerRef: ViewContainerRef,
|
||||||
private platformUtilsService: PlatformUtilsService
|
private platformUtilsService: PlatformUtilsService,
|
||||||
|
private organizationService: OrganizationService
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
@HostListener("document:keydown.escape", ["$event"])
|
@HostListener("document:keydown.escape", ["$event"])
|
||||||
@@ -98,46 +100,45 @@ export class VaultSelectComponent implements OnInit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async ngOnInit() {
|
async ngOnInit() {
|
||||||
await this.load();
|
this.organizations$ = this.organizationService.organizations$
|
||||||
this.broadcasterService.subscribe(this.constructor.name, (message: any) => {
|
.pipe(takeUntil(this._destroy))
|
||||||
this.ngZone.run(async () => {
|
.pipe(map((orgs) => orgs.sort((a, b) => a.name.localeCompare(b.name))));
|
||||||
switch (message.command) {
|
|
||||||
case "syncCompleted":
|
this.organizations$
|
||||||
await this.load();
|
.pipe(
|
||||||
break;
|
concatMap(async (organizations) => {
|
||||||
default:
|
this.enforcePersonalOwnership =
|
||||||
break;
|
await this.vaultFilterService.checkForPersonalOwnershipPolicy();
|
||||||
}
|
|
||||||
});
|
if (this.shouldShow(organizations)) {
|
||||||
});
|
if (this.enforcePersonalOwnership && !this.vaultFilter.myVaultOnly) {
|
||||||
|
const firstOrganization = organizations[0];
|
||||||
|
this._selectedVault.next(firstOrganization.name);
|
||||||
|
this.vaultFilterService.setVaultFilter(firstOrganization.id);
|
||||||
|
this.vaultFilter.selectedOrganizationId = firstOrganization.id;
|
||||||
|
} else if (this.vaultFilter.myVaultOnly) {
|
||||||
|
this._selectedVault.next(this.i18nService.t(this.vaultFilterService.myVault));
|
||||||
|
} else if (this.vaultFilter.selectedOrganizationId != null) {
|
||||||
|
const selectedOrganization = organizations.find(
|
||||||
|
(o) => o.id === this.vaultFilter.selectedOrganizationId
|
||||||
|
);
|
||||||
|
this._selectedVault.next(selectedOrganization.name);
|
||||||
|
} else {
|
||||||
|
this._selectedVault.next(this.i18nService.t(this.vaultFilterService.allVaults));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
)
|
||||||
|
.pipe(takeUntil(this._destroy))
|
||||||
|
.subscribe();
|
||||||
|
|
||||||
|
this.loaded = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
async load() {
|
ngOnDestroy(): void {
|
||||||
this.vaultFilter = this.vaultFilterService.getVaultFilter();
|
this._destroy.next();
|
||||||
this.organizations = (await this.vaultFilterService.buildOrganizations()).sort((a, b) =>
|
this._destroy.complete();
|
||||||
a.name.localeCompare(b.name)
|
this._selectedVault.complete();
|
||||||
);
|
|
||||||
this.enforcePersonalOwnwership =
|
|
||||||
await this.vaultFilterService.checkForPersonalOwnershipPolicy();
|
|
||||||
|
|
||||||
if (this.show) {
|
|
||||||
if (this.enforcePersonalOwnwership && !this.vaultFilter.myVaultOnly) {
|
|
||||||
this.vaultFilterService.setVaultFilter(this.organizations[0].id);
|
|
||||||
this.vaultFilter.selectedOrganizationId = this.organizations[0].id;
|
|
||||||
this.vaultFilterDisplay = this.organizations.find(
|
|
||||||
(o) => o.id === this.vaultFilter.selectedOrganizationId
|
|
||||||
).name;
|
|
||||||
} else if (this.vaultFilter.myVaultOnly) {
|
|
||||||
this.vaultFilterDisplay = this.i18nService.t(this.vaultFilterService.myVault);
|
|
||||||
} else if (this.vaultFilter.selectedOrganizationId != null) {
|
|
||||||
this.vaultFilterDisplay = this.organizations.find(
|
|
||||||
(o) => o.id === this.vaultFilter.selectedOrganizationId
|
|
||||||
).name;
|
|
||||||
} else {
|
|
||||||
this.vaultFilterDisplay = this.i18nService.t(this.vaultFilterService.allVaults);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
this.loaded = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
openOverlay() {
|
openOverlay() {
|
||||||
@@ -191,20 +192,20 @@ export class VaultSelectComponent implements OnInit {
|
|||||||
this.i18nService.t("disabledOrganizationFilterError")
|
this.i18nService.t("disabledOrganizationFilterError")
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
this.vaultFilterDisplay = organization.name;
|
this._selectedVault.next(organization.name);
|
||||||
this.vaultFilterService.setVaultFilter(organization.id);
|
this.vaultFilterService.setVaultFilter(organization.id);
|
||||||
this.onVaultSelectionChanged.emit();
|
this.onVaultSelectionChanged.emit();
|
||||||
this.close();
|
this.close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
selectAllVaults() {
|
selectAllVaults() {
|
||||||
this.vaultFilterDisplay = this.i18nService.t(this.vaultFilterService.allVaults);
|
this._selectedVault.next(this.i18nService.t(this.vaultFilterService.allVaults));
|
||||||
this.vaultFilterService.setVaultFilter(this.vaultFilterService.allVaults);
|
this.vaultFilterService.setVaultFilter(this.vaultFilterService.allVaults);
|
||||||
this.onVaultSelectionChanged.emit();
|
this.onVaultSelectionChanged.emit();
|
||||||
this.close();
|
this.close();
|
||||||
}
|
}
|
||||||
selectMyVault() {
|
selectMyVault() {
|
||||||
this.vaultFilterDisplay = this.i18nService.t(this.vaultFilterService.myVault);
|
this._selectedVault.next(this.i18nService.t(this.vaultFilterService.myVault));
|
||||||
this.vaultFilterService.setVaultFilter(this.vaultFilterService.myVault);
|
this.vaultFilterService.setVaultFilter(this.vaultFilterService.myVault);
|
||||||
this.onVaultSelectionChanged.emit();
|
this.onVaultSelectionChanged.emit();
|
||||||
this.close();
|
this.close();
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import { VaultFilterService as BaseVaultFilterService } from "@bitwarden/angular
|
|||||||
import { CipherService } from "@bitwarden/common/abstractions/cipher.service";
|
import { CipherService } from "@bitwarden/common/abstractions/cipher.service";
|
||||||
import { CollectionService } from "@bitwarden/common/abstractions/collection.service";
|
import { CollectionService } from "@bitwarden/common/abstractions/collection.service";
|
||||||
import { FolderService } from "@bitwarden/common/abstractions/folder/folder.service.abstraction";
|
import { FolderService } from "@bitwarden/common/abstractions/folder/folder.service.abstraction";
|
||||||
import { OrganizationService } from "@bitwarden/common/abstractions/organization.service";
|
import { OrganizationService } from "@bitwarden/common/abstractions/organization/organization.service.abstraction";
|
||||||
import { PolicyService } from "@bitwarden/common/abstractions/policy/policy.service.abstraction";
|
import { PolicyService } from "@bitwarden/common/abstractions/policy/policy.service.abstraction";
|
||||||
import { StateService } from "@bitwarden/common/abstractions/state.service";
|
import { StateService } from "@bitwarden/common/abstractions/state.service";
|
||||||
import { CipherView } from "@bitwarden/common/models/view/cipherView";
|
import { CipherView } from "@bitwarden/common/models/view/cipherView";
|
||||||
|
|||||||
@@ -30,8 +30,8 @@ import { ImportService } from "@bitwarden/common/services/import.service";
|
|||||||
import { KeyConnectorService } from "@bitwarden/common/services/keyConnector.service";
|
import { KeyConnectorService } from "@bitwarden/common/services/keyConnector.service";
|
||||||
import { MemoryStorageService } from "@bitwarden/common/services/memoryStorage.service";
|
import { MemoryStorageService } from "@bitwarden/common/services/memoryStorage.service";
|
||||||
import { NoopMessagingService } from "@bitwarden/common/services/noopMessaging.service";
|
import { NoopMessagingService } from "@bitwarden/common/services/noopMessaging.service";
|
||||||
import { OrganizationService } from "@bitwarden/common/services/organization.service";
|
|
||||||
import { OrganizationApiService } from "@bitwarden/common/services/organization/organization-api.service";
|
import { OrganizationApiService } from "@bitwarden/common/services/organization/organization-api.service";
|
||||||
|
import { OrganizationService } from "@bitwarden/common/services/organization/organization.service";
|
||||||
import { PasswordGenerationService } from "@bitwarden/common/services/passwordGeneration.service";
|
import { PasswordGenerationService } from "@bitwarden/common/services/passwordGeneration.service";
|
||||||
import { PolicyService } from "@bitwarden/common/services/policy/policy.service";
|
import { PolicyService } from "@bitwarden/common/services/policy/policy.service";
|
||||||
import { ProviderService } from "@bitwarden/common/services/provider.service";
|
import { ProviderService } from "@bitwarden/common/services/provider.service";
|
||||||
@@ -41,6 +41,7 @@ import { SettingsService } from "@bitwarden/common/services/settings.service";
|
|||||||
import { StateService } from "@bitwarden/common/services/state.service";
|
import { StateService } from "@bitwarden/common/services/state.service";
|
||||||
import { StateMigrationService } from "@bitwarden/common/services/stateMigration.service";
|
import { StateMigrationService } from "@bitwarden/common/services/stateMigration.service";
|
||||||
import { SyncService } from "@bitwarden/common/services/sync/sync.service";
|
import { SyncService } from "@bitwarden/common/services/sync/sync.service";
|
||||||
|
import { SyncNotifierService } from "@bitwarden/common/services/sync/syncNotifier.service";
|
||||||
import { TokenService } from "@bitwarden/common/services/token.service";
|
import { TokenService } from "@bitwarden/common/services/token.service";
|
||||||
import { TotpService } from "@bitwarden/common/services/totp.service";
|
import { TotpService } from "@bitwarden/common/services/totp.service";
|
||||||
import { TwoFactorService } from "@bitwarden/common/services/twoFactor.service";
|
import { TwoFactorService } from "@bitwarden/common/services/twoFactor.service";
|
||||||
@@ -113,6 +114,7 @@ export class Main {
|
|||||||
folderApiService: FolderApiService;
|
folderApiService: FolderApiService;
|
||||||
userVerificationApiService: UserVerificationApiService;
|
userVerificationApiService: UserVerificationApiService;
|
||||||
organizationApiService: OrganizationApiServiceAbstraction;
|
organizationApiService: OrganizationApiServiceAbstraction;
|
||||||
|
syncNotifierService: SyncNotifierService;
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
let p = null;
|
let p = null;
|
||||||
@@ -191,7 +193,9 @@ export class Main {
|
|||||||
customUserAgent
|
customUserAgent
|
||||||
);
|
);
|
||||||
|
|
||||||
this.organizationApiService = new OrganizationApiService(this.apiService);
|
this.syncNotifierService = new SyncNotifierService();
|
||||||
|
|
||||||
|
this.organizationApiService = new OrganizationApiService(this.apiService, this.syncService);
|
||||||
|
|
||||||
this.containerService = new ContainerService(this.cryptoService, this.encryptService);
|
this.containerService = new ContainerService(this.cryptoService, this.encryptService);
|
||||||
|
|
||||||
@@ -231,7 +235,7 @@ export class Main {
|
|||||||
|
|
||||||
this.providerService = new ProviderService(this.stateService);
|
this.providerService = new ProviderService(this.stateService);
|
||||||
|
|
||||||
this.organizationService = new OrganizationService(this.stateService);
|
this.organizationService = new OrganizationService(this.stateService, this.syncNotifierService);
|
||||||
|
|
||||||
this.policyService = new PolicyService(this.stateService, this.organizationService);
|
this.policyService = new PolicyService(this.stateService, this.organizationService);
|
||||||
|
|
||||||
@@ -311,9 +315,9 @@ export class Main {
|
|||||||
this.logService,
|
this.logService,
|
||||||
this.keyConnectorService,
|
this.keyConnectorService,
|
||||||
this.stateService,
|
this.stateService,
|
||||||
this.organizationService,
|
|
||||||
this.providerService,
|
this.providerService,
|
||||||
this.folderApiService,
|
this.folderApiService,
|
||||||
|
this.syncNotifierService,
|
||||||
async (expired: boolean) => await this.logout()
|
async (expired: boolean) => await this.logout()
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -74,7 +74,6 @@ export class ConvertToKeyConnectorCommand {
|
|||||||
} else if (answer.convert === "leave") {
|
} else if (answer.convert === "leave") {
|
||||||
await this.organizationApiService.leave(organization.id);
|
await this.organizationApiService.leave(organization.id);
|
||||||
await this.keyConnectorService.removeConvertAccountRequired();
|
await this.keyConnectorService.removeConvertAccountRequired();
|
||||||
await this.syncService.fullSync(true);
|
|
||||||
return Response.success();
|
return Response.success();
|
||||||
} else {
|
} else {
|
||||||
await this.logout();
|
await this.logout();
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import { CipherService } from "@bitwarden/common/abstractions/cipher.service";
|
|||||||
import { CollectionService } from "@bitwarden/common/abstractions/collection.service";
|
import { CollectionService } from "@bitwarden/common/abstractions/collection.service";
|
||||||
import { CryptoService } from "@bitwarden/common/abstractions/crypto.service";
|
import { CryptoService } from "@bitwarden/common/abstractions/crypto.service";
|
||||||
import { FolderService } from "@bitwarden/common/abstractions/folder/folder.service.abstraction";
|
import { FolderService } from "@bitwarden/common/abstractions/folder/folder.service.abstraction";
|
||||||
import { OrganizationService } from "@bitwarden/common/abstractions/organization.service";
|
import { OrganizationService } from "@bitwarden/common/abstractions/organization/organization.service.abstraction";
|
||||||
import { SearchService } from "@bitwarden/common/abstractions/search.service";
|
import { SearchService } from "@bitwarden/common/abstractions/search.service";
|
||||||
import { StateService } from "@bitwarden/common/abstractions/state.service";
|
import { StateService } from "@bitwarden/common/abstractions/state.service";
|
||||||
import { TotpService } from "@bitwarden/common/abstractions/totp.service";
|
import { TotpService } from "@bitwarden/common/abstractions/totp.service";
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import * as program from "commander";
|
|||||||
import * as inquirer from "inquirer";
|
import * as inquirer from "inquirer";
|
||||||
|
|
||||||
import { ImportService } from "@bitwarden/common/abstractions/import.service";
|
import { ImportService } from "@bitwarden/common/abstractions/import.service";
|
||||||
import { OrganizationService } from "@bitwarden/common/abstractions/organization.service";
|
import { OrganizationService } from "@bitwarden/common/abstractions/organization/organization.service.abstraction";
|
||||||
import { ImportType } from "@bitwarden/common/enums/importOptions";
|
import { ImportType } from "@bitwarden/common/enums/importOptions";
|
||||||
import { Importer } from "@bitwarden/common/importers/importer";
|
import { Importer } from "@bitwarden/common/importers/importer";
|
||||||
import { Response } from "@bitwarden/node/cli/models/response";
|
import { Response } from "@bitwarden/node/cli/models/response";
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
|||||||
import { CipherService } from "@bitwarden/common/abstractions/cipher.service";
|
import { CipherService } from "@bitwarden/common/abstractions/cipher.service";
|
||||||
import { CollectionService } from "@bitwarden/common/abstractions/collection.service";
|
import { CollectionService } from "@bitwarden/common/abstractions/collection.service";
|
||||||
import { FolderService } from "@bitwarden/common/abstractions/folder/folder.service.abstraction";
|
import { FolderService } from "@bitwarden/common/abstractions/folder/folder.service.abstraction";
|
||||||
import { OrganizationService } from "@bitwarden/common/abstractions/organization.service";
|
import { OrganizationService } from "@bitwarden/common/abstractions/organization/organization.service.abstraction";
|
||||||
import { SearchService } from "@bitwarden/common/abstractions/search.service";
|
import { SearchService } from "@bitwarden/common/abstractions/search.service";
|
||||||
import { Utils } from "@bitwarden/common/misc/utils";
|
import { Utils } from "@bitwarden/common/misc/utils";
|
||||||
import { CollectionData } from "@bitwarden/common/models/data/collectionData";
|
import { CollectionData } from "@bitwarden/common/models/data/collectionData";
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import { FolderService } from "@bitwarden/common/abstractions/folder/folder.serv
|
|||||||
import { I18nService } from "@bitwarden/common/abstractions/i18n.service";
|
import { I18nService } from "@bitwarden/common/abstractions/i18n.service";
|
||||||
import { LogService } from "@bitwarden/common/abstractions/log.service";
|
import { LogService } from "@bitwarden/common/abstractions/log.service";
|
||||||
import { MessagingService } from "@bitwarden/common/abstractions/messaging.service";
|
import { MessagingService } from "@bitwarden/common/abstractions/messaging.service";
|
||||||
import { OrganizationService } from "@bitwarden/common/abstractions/organization.service";
|
import { OrganizationService } from "@bitwarden/common/abstractions/organization/organization.service.abstraction";
|
||||||
import { PasswordRepromptService } from "@bitwarden/common/abstractions/passwordReprompt.service";
|
import { PasswordRepromptService } from "@bitwarden/common/abstractions/passwordReprompt.service";
|
||||||
import { PlatformUtilsService } from "@bitwarden/common/abstractions/platformUtils.service";
|
import { PlatformUtilsService } from "@bitwarden/common/abstractions/platformUtils.service";
|
||||||
import { PolicyService } from "@bitwarden/common/abstractions/policy/policy.service.abstraction";
|
import { PolicyService } from "@bitwarden/common/abstractions/policy/policy.service.abstraction";
|
||||||
|
|||||||
@@ -1,78 +1,80 @@
|
|||||||
<div class="modal fade" role="dialog" aria-modal="true" aria-labelledby="moveToOrgTitle">
|
<div class="modal fade" role="dialog" aria-modal="true" aria-labelledby="moveToOrgTitle">
|
||||||
<div class="modal-dialog" role="document">
|
<div class="modal-dialog" role="document">
|
||||||
<form class="modal-content" #form (ngSubmit)="submit()" [appApiAction]="formPromise">
|
<form class="modal-content" #form (ngSubmit)="submit()" [appApiAction]="formPromise">
|
||||||
<div class="modal-body">
|
<ng-container *ngIf="organizations$ | async as organizations">
|
||||||
<div class="box">
|
<div class="modal-body">
|
||||||
<h1 class="box-header" id="moveToOrgTitle">
|
<div class="box">
|
||||||
{{ "moveToOrganization" | i18n }}
|
<h1 class="box-header" id="moveToOrgTitle">
|
||||||
</h1>
|
{{ "moveToOrganization" | i18n }}
|
||||||
<div class="box-content" *ngIf="!organizations || !organizations.length">
|
</h1>
|
||||||
<div class="box-content-row">
|
<div class="box-content" *ngIf="!organizations || !organizations.length">
|
||||||
{{ "noOrganizationsList" | i18n }}
|
<div class="box-content-row">
|
||||||
|
{{ "noOrganizationsList" | i18n }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="box-content" *ngIf="organizations && organizations.length">
|
||||||
|
<div class="box-content-row" appBoxRow>
|
||||||
|
<label for="organization">{{ "organization" | i18n }}</label>
|
||||||
|
<select
|
||||||
|
id="organization"
|
||||||
|
name="OrganizationId"
|
||||||
|
[(ngModel)]="organizationId"
|
||||||
|
(change)="filterCollections()"
|
||||||
|
>
|
||||||
|
<option *ngFor="let o of organizations" [ngValue]="o.id">{{ o.name }}</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="box-footer">
|
||||||
|
{{ "moveToOrgDesc" | i18n }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="box-content" *ngIf="organizations && organizations.length">
|
<div class="box" *ngIf="organizations && organizations.length">
|
||||||
<div class="box-content-row" appBoxRow>
|
<h2 class="box-header">
|
||||||
<label for="organization">{{ "organization" | i18n }}</label>
|
{{ "collections" | i18n }}
|
||||||
<select
|
</h2>
|
||||||
id="organization"
|
<div class="box-content" *ngIf="!collections || !collections.length">
|
||||||
name="OrganizationId"
|
{{ "noCollectionsInList" | i18n }}
|
||||||
[(ngModel)]="organizationId"
|
</div>
|
||||||
(change)="filterCollections()"
|
<div class="box-content" *ngIf="collections && collections.length">
|
||||||
|
<div
|
||||||
|
class="box-content-row box-content-row-checkbox"
|
||||||
|
*ngFor="let c of collections; let i = index"
|
||||||
|
appBoxRow
|
||||||
>
|
>
|
||||||
<option *ngFor="let o of organizations" [ngValue]="o.id">{{ o.name }}</option>
|
<label for="collection_{{ i }}">{{ c.name }}</label>
|
||||||
</select>
|
<input
|
||||||
</div>
|
id="collection_{{ i }}"
|
||||||
</div>
|
type="checkbox"
|
||||||
<div class="box-footer">
|
[(ngModel)]="c.checked"
|
||||||
{{ "moveToOrgDesc" | i18n }}
|
name="Collection[{{ i }}].Checked"
|
||||||
</div>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div class="box" *ngIf="organizations && organizations.length">
|
|
||||||
<h2 class="box-header">
|
|
||||||
{{ "collections" | i18n }}
|
|
||||||
</h2>
|
|
||||||
<div class="box-content" *ngIf="!collections || !collections.length">
|
|
||||||
{{ "noCollectionsInList" | i18n }}
|
|
||||||
</div>
|
|
||||||
<div class="box-content" *ngIf="collections && collections.length">
|
|
||||||
<div
|
|
||||||
class="box-content-row box-content-row-checkbox"
|
|
||||||
*ngFor="let c of collections; let i = index"
|
|
||||||
appBoxRow
|
|
||||||
>
|
|
||||||
<label for="collection_{{ i }}">{{ c.name }}</label>
|
|
||||||
<input
|
|
||||||
id="collection_{{ i }}"
|
|
||||||
type="checkbox"
|
|
||||||
[(ngModel)]="c.checked"
|
|
||||||
name="Collection[{{ i }}].Checked"
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<div class="modal-footer">
|
||||||
<div class="modal-footer">
|
<button
|
||||||
<button
|
type="submit"
|
||||||
type="submit"
|
class="primary"
|
||||||
class="primary"
|
appA11yTitle="{{ 'save' | i18n }}"
|
||||||
appA11yTitle="{{ 'save' | i18n }}"
|
[disabled]="form.loading || !canSave"
|
||||||
[disabled]="form.loading || !canSave"
|
*ngIf="organizations && organizations.length"
|
||||||
*ngIf="organizations && organizations.length"
|
>
|
||||||
>
|
<i
|
||||||
<i
|
class="bwi bwi-save-changes bwi-lg bwi-fw"
|
||||||
class="bwi bwi-save-changes bwi-lg bwi-fw"
|
[hidden]="form.loading"
|
||||||
[hidden]="form.loading"
|
aria-hidden="true"
|
||||||
aria-hidden="true"
|
></i>
|
||||||
></i>
|
<i
|
||||||
<i
|
class="bwi bwi-spinner bwi-spin bwi-lg bwi-fw"
|
||||||
class="bwi bwi-spinner bwi-spin bwi-lg bwi-fw"
|
[hidden]="!form.loading"
|
||||||
[hidden]="!form.loading"
|
aria-hidden="true"
|
||||||
aria-hidden="true"
|
></i>
|
||||||
></i>
|
</button>
|
||||||
</button>
|
<button type="button" data-dismiss="modal">{{ "cancel" | i18n }}</button>
|
||||||
<button type="button" data-dismiss="modal">{{ "cancel" | i18n }}</button>
|
</div>
|
||||||
</div>
|
</ng-container>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import { CipherService } from "@bitwarden/common/abstractions/cipher.service";
|
|||||||
import { CollectionService } from "@bitwarden/common/abstractions/collection.service";
|
import { CollectionService } from "@bitwarden/common/abstractions/collection.service";
|
||||||
import { I18nService } from "@bitwarden/common/abstractions/i18n.service";
|
import { I18nService } from "@bitwarden/common/abstractions/i18n.service";
|
||||||
import { LogService } from "@bitwarden/common/abstractions/log.service";
|
import { LogService } from "@bitwarden/common/abstractions/log.service";
|
||||||
import { OrganizationService } from "@bitwarden/common/abstractions/organization.service";
|
import { OrganizationService } from "@bitwarden/common/abstractions/organization/organization.service.abstraction";
|
||||||
import { PlatformUtilsService } from "@bitwarden/common/abstractions/platformUtils.service";
|
import { PlatformUtilsService } from "@bitwarden/common/abstractions/platformUtils.service";
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
|
|||||||
@@ -36,7 +36,7 @@
|
|||||||
<hr />
|
<hr />
|
||||||
|
|
||||||
<div class="tw-text-light tw-mt-3">
|
<div class="tw-text-light tw-mt-3">
|
||||||
{{ "loginWithDevciceEnabledInfo" | i18n }}
|
{{ "loginWithDeviceEnabledInfo" | i18n }}
|
||||||
<a routerLink="/login">{{ "viewAllLoginOptions" | i18n }}</a>
|
<a routerLink="/login">{{ "viewAllLoginOptions" | i18n }}</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -22,8 +22,7 @@ import { Policy } from "@bitwarden/common/models/domain/policy";
|
|||||||
import { ListResponse } from "@bitwarden/common/models/response/listResponse";
|
import { ListResponse } from "@bitwarden/common/models/response/listResponse";
|
||||||
import { PolicyResponse } from "@bitwarden/common/models/response/policyResponse";
|
import { PolicyResponse } from "@bitwarden/common/models/response/policyResponse";
|
||||||
|
|
||||||
import { flagEnabled } from "src/utils/flags";
|
import { flagEnabled } from "../../../utils/flags";
|
||||||
|
|
||||||
import { RouterService, StateService } from "../../core";
|
import { RouterService, StateService } from "../../core";
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
|
|||||||
@@ -114,7 +114,9 @@
|
|||||||
|
|
||||||
<div class="tw-mb-3 tw-flex">
|
<div class="tw-mb-3 tw-flex">
|
||||||
<ng-container *ngIf="!accountCreated">
|
<ng-container *ngIf="!accountCreated">
|
||||||
<bit-submit-button [loading]="form.loading">{{ "createAccount" | i18n }}</bit-submit-button>
|
<button type="submit" buttonType="primary" bitButton [loading]="form.loading">
|
||||||
|
{{ "createAccount" | i18n }}
|
||||||
|
</button>
|
||||||
<a
|
<a
|
||||||
bitButton
|
bitButton
|
||||||
buttonType="secondary"
|
buttonType="secondary"
|
||||||
@@ -126,7 +128,9 @@
|
|||||||
</a>
|
</a>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
<ng-container *ngIf="accountCreated">
|
<ng-container *ngIf="accountCreated">
|
||||||
<bit-submit-button [loading]="form.loading">{{ "logIn" | i18n }}</bit-submit-button>
|
<button type="submit" buttonType="primary" bitButton [loading]="form.loading">
|
||||||
|
{{ "logIn" | i18n }}
|
||||||
|
</button>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
</div>
|
</div>
|
||||||
<bit-error-summary *ngIf="showErrorSummary" [formGroup]="formGroup"></bit-error-summary>
|
<bit-error-summary *ngIf="showErrorSummary" [formGroup]="formGroup"></bit-error-summary>
|
||||||
|
|||||||
@@ -40,7 +40,9 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="tw-flex tw-space-x-2">
|
<div class="tw-flex tw-space-x-2">
|
||||||
<bit-submit-button [loading]="form.loading">{{ "startTrial" | i18n }}</bit-submit-button>
|
<button type="submit" buttonType="primary" bitButton [loading]="form.loading">
|
||||||
|
{{ "startTrial" | i18n }}
|
||||||
|
</button>
|
||||||
|
|
||||||
<button bitButton type="button" buttonType="secondary" (click)="stepBack()">Back</button>
|
<button bitButton type="button" buttonType="secondary" (click)="stepBack()">Back</button>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -7,8 +7,8 @@ import { CryptoService } from "@bitwarden/common/abstractions/crypto.service";
|
|||||||
import { I18nService } from "@bitwarden/common/abstractions/i18n.service";
|
import { I18nService } from "@bitwarden/common/abstractions/i18n.service";
|
||||||
import { LogService } from "@bitwarden/common/abstractions/log.service";
|
import { LogService } from "@bitwarden/common/abstractions/log.service";
|
||||||
import { MessagingService } from "@bitwarden/common/abstractions/messaging.service";
|
import { MessagingService } from "@bitwarden/common/abstractions/messaging.service";
|
||||||
import { OrganizationService } from "@bitwarden/common/abstractions/organization.service";
|
|
||||||
import { OrganizationApiServiceAbstraction } from "@bitwarden/common/abstractions/organization/organization-api.service.abstraction";
|
import { OrganizationApiServiceAbstraction } from "@bitwarden/common/abstractions/organization/organization-api.service.abstraction";
|
||||||
|
import { OrganizationService } from "@bitwarden/common/abstractions/organization/organization.service.abstraction";
|
||||||
import { PlatformUtilsService } from "@bitwarden/common/abstractions/platformUtils.service";
|
import { PlatformUtilsService } from "@bitwarden/common/abstractions/platformUtils.service";
|
||||||
import { PolicyService } from "@bitwarden/common/abstractions/policy/policy.service.abstraction";
|
import { PolicyService } from "@bitwarden/common/abstractions/policy/policy.service.abstraction";
|
||||||
import { SyncService } from "@bitwarden/common/abstractions/sync/sync.service.abstraction";
|
import { SyncService } from "@bitwarden/common/abstractions/sync/sync.service.abstraction";
|
||||||
|
|||||||
@@ -126,7 +126,12 @@ export abstract class BasePeopleComponent<
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.allUsers = response.data != null && response.data.length > 0 ? response.data : [];
|
this.allUsers = response.data != null && response.data.length > 0 ? response.data : [];
|
||||||
this.allUsers.sort(Utils.getSortFunction(this.i18nService, "email"));
|
this.allUsers.sort(
|
||||||
|
Utils.getSortFunction<ProviderUserUserDetailsResponse | OrganizationUserUserDetailsResponse>(
|
||||||
|
this.i18nService,
|
||||||
|
"email"
|
||||||
|
)
|
||||||
|
);
|
||||||
this.allUsers.forEach((u) => {
|
this.allUsers.forEach((u) => {
|
||||||
if (!this.statusMap.has(u.status)) {
|
if (!this.statusMap.has(u.status)) {
|
||||||
this.statusMap.set(u.status, [u]);
|
this.statusMap.set(u.status, [u]);
|
||||||
|
|||||||
@@ -45,7 +45,11 @@
|
|||||||
|
|
||||||
<bit-menu #orgPickerMenu>
|
<bit-menu #orgPickerMenu>
|
||||||
<ul aria-labelledby="pickerButton" class="tw-m-0 tw-p-0">
|
<ul aria-labelledby="pickerButton" class="tw-m-0 tw-p-0">
|
||||||
<li *ngFor="let org of organizations" class="tw-flex tw-list-none tw-flex-col" role="none">
|
<li
|
||||||
|
*ngFor="let org of organizations$ | async"
|
||||||
|
class="tw-flex tw-list-none tw-flex-col"
|
||||||
|
role="none"
|
||||||
|
>
|
||||||
<a bitMenuItem [routerLink]="['/organizations', org.id]">
|
<a bitMenuItem [routerLink]="['/organizations', org.id]">
|
||||||
<i
|
<i
|
||||||
class="bwi bwi-check mr-2"
|
class="bwi bwi-check mr-2"
|
||||||
|
|||||||
@@ -1,12 +1,13 @@
|
|||||||
import { Component, Input, OnInit } from "@angular/core";
|
import { Component, Input, OnInit } from "@angular/core";
|
||||||
|
import { Observable } from "rxjs";
|
||||||
|
|
||||||
import { I18nService } from "@bitwarden/common/abstractions/i18n.service";
|
import { I18nService } from "@bitwarden/common/abstractions/i18n.service";
|
||||||
import { OrganizationService } from "@bitwarden/common/abstractions/organization.service";
|
import {
|
||||||
import { Utils } from "@bitwarden/common/misc/utils";
|
canAccessAdmin,
|
||||||
|
OrganizationService,
|
||||||
|
} from "@bitwarden/common/abstractions/organization/organization.service.abstraction";
|
||||||
import { Organization } from "@bitwarden/common/models/domain/organization";
|
import { Organization } from "@bitwarden/common/models/domain/organization";
|
||||||
|
|
||||||
import { canAccessOrgAdmin } from "../organizations/navigation-permissions";
|
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: "app-organization-switcher",
|
selector: "app-organization-switcher",
|
||||||
templateUrl: "organization-switcher.component.html",
|
templateUrl: "organization-switcher.component.html",
|
||||||
@@ -15,19 +16,14 @@ export class OrganizationSwitcherComponent implements OnInit {
|
|||||||
constructor(private organizationService: OrganizationService, private i18nService: I18nService) {}
|
constructor(private organizationService: OrganizationService, private i18nService: I18nService) {}
|
||||||
|
|
||||||
@Input() activeOrganization: Organization = null;
|
@Input() activeOrganization: Organization = null;
|
||||||
organizations: Organization[] = [];
|
organizations$: Observable<Organization[]>;
|
||||||
|
|
||||||
loaded = false;
|
loaded = false;
|
||||||
|
|
||||||
async ngOnInit() {
|
async ngOnInit() {
|
||||||
await this.load();
|
this.organizations$ = this.organizationService.organizations$.pipe(
|
||||||
}
|
canAccessAdmin(this.i18nService)
|
||||||
|
);
|
||||||
async load() {
|
|
||||||
const orgs = await this.organizationService.getAll();
|
|
||||||
this.organizations = orgs
|
|
||||||
.filter(canAccessOrgAdmin)
|
|
||||||
.sort(Utils.getSortFunction(this.i18nService, "name"));
|
|
||||||
|
|
||||||
this.loaded = true;
|
this.loaded = true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,8 +17,12 @@
|
|||||||
<li class="nav-item" routerLinkActive="active">
|
<li class="nav-item" routerLinkActive="active">
|
||||||
<a class="nav-link" routerLink="/reports">{{ "reports" | i18n }}</a>
|
<a class="nav-link" routerLink="/reports">{{ "reports" | i18n }}</a>
|
||||||
</li>
|
</li>
|
||||||
<li *ngIf="organizations.length >= 1" class="nav-item" routerLinkActive="active">
|
<li
|
||||||
<a class="nav-link" [routerLink]="['/organizations', organizations[0].id]">{{
|
*ngIf="(organizations$ | async)?.length >= 1"
|
||||||
|
class="nav-item"
|
||||||
|
routerLinkActive="active"
|
||||||
|
>
|
||||||
|
<a class="nav-link" [routerLink]="['/organizations', (organizations$ | async)[0].id]">{{
|
||||||
"organizations" | i18n
|
"organizations" | i18n
|
||||||
}}</a>
|
}}</a>
|
||||||
</li>
|
</li>
|
||||||
|
|||||||
@@ -1,19 +1,19 @@
|
|||||||
import { Component, NgZone, OnInit } from "@angular/core";
|
import { Component, OnInit } from "@angular/core";
|
||||||
|
import { Observable } from "rxjs";
|
||||||
|
|
||||||
import { BroadcasterService } from "@bitwarden/common/abstractions/broadcaster.service";
|
|
||||||
import { I18nService } from "@bitwarden/common/abstractions/i18n.service";
|
import { I18nService } from "@bitwarden/common/abstractions/i18n.service";
|
||||||
import { MessagingService } from "@bitwarden/common/abstractions/messaging.service";
|
import { MessagingService } from "@bitwarden/common/abstractions/messaging.service";
|
||||||
import { OrganizationService } from "@bitwarden/common/abstractions/organization.service";
|
import {
|
||||||
|
canAccessAdmin,
|
||||||
|
OrganizationService,
|
||||||
|
} from "@bitwarden/common/abstractions/organization/organization.service.abstraction";
|
||||||
import { PlatformUtilsService } from "@bitwarden/common/abstractions/platformUtils.service";
|
import { PlatformUtilsService } from "@bitwarden/common/abstractions/platformUtils.service";
|
||||||
import { ProviderService } from "@bitwarden/common/abstractions/provider.service";
|
import { ProviderService } from "@bitwarden/common/abstractions/provider.service";
|
||||||
import { SyncService } from "@bitwarden/common/abstractions/sync/sync.service.abstraction";
|
import { SyncService } from "@bitwarden/common/abstractions/sync/sync.service.abstraction";
|
||||||
import { TokenService } from "@bitwarden/common/abstractions/token.service";
|
import { TokenService } from "@bitwarden/common/abstractions/token.service";
|
||||||
import { Utils } from "@bitwarden/common/misc/utils";
|
|
||||||
import { Organization } from "@bitwarden/common/models/domain/organization";
|
import { Organization } from "@bitwarden/common/models/domain/organization";
|
||||||
import { Provider } from "@bitwarden/common/models/domain/provider";
|
import { Provider } from "@bitwarden/common/models/domain/provider";
|
||||||
|
|
||||||
import { canAccessOrgAdmin } from "../organizations/navigation-permissions";
|
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: "app-navbar",
|
selector: "app-navbar",
|
||||||
templateUrl: "navbar.component.html",
|
templateUrl: "navbar.component.html",
|
||||||
@@ -24,7 +24,7 @@ export class NavbarComponent implements OnInit {
|
|||||||
name: string;
|
name: string;
|
||||||
email: string;
|
email: string;
|
||||||
providers: Provider[] = [];
|
providers: Provider[] = [];
|
||||||
organizations: Organization[] = [];
|
organizations$: Observable<Organization[]>;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private messagingService: MessagingService,
|
private messagingService: MessagingService,
|
||||||
@@ -33,9 +33,7 @@ export class NavbarComponent implements OnInit {
|
|||||||
private providerService: ProviderService,
|
private providerService: ProviderService,
|
||||||
private syncService: SyncService,
|
private syncService: SyncService,
|
||||||
private organizationService: OrganizationService,
|
private organizationService: OrganizationService,
|
||||||
private i18nService: I18nService,
|
private i18nService: I18nService
|
||||||
private broadcasterService: BroadcasterService,
|
|
||||||
private ngZone: NgZone
|
|
||||||
) {
|
) {
|
||||||
this.selfHosted = this.platformUtilsService.isSelfHost();
|
this.selfHosted = this.platformUtilsService.isSelfHost();
|
||||||
}
|
}
|
||||||
@@ -53,24 +51,9 @@ export class NavbarComponent implements OnInit {
|
|||||||
}
|
}
|
||||||
this.providers = await this.providerService.getAll();
|
this.providers = await this.providerService.getAll();
|
||||||
|
|
||||||
this.organizations = await this.buildOrganizations();
|
this.organizations$ = this.organizationService.organizations$.pipe(
|
||||||
|
canAccessAdmin(this.i18nService)
|
||||||
this.broadcasterService.subscribe(this.constructor.name, async (message: any) => {
|
);
|
||||||
this.ngZone.run(async () => {
|
|
||||||
switch (message.command) {
|
|
||||||
case "organizationCreated":
|
|
||||||
if (this.organizations.length < 1) {
|
|
||||||
this.organizations = await this.buildOrganizations();
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
async buildOrganizations() {
|
|
||||||
const allOrgs = await this.organizationService.getAll();
|
|
||||||
return allOrgs.filter(canAccessOrgAdmin).sort(Utils.getSortFunction(this.i18nService, "name"));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
lock() {
|
lock() {
|
||||||
|
|||||||
@@ -1,9 +1,10 @@
|
|||||||
import { NgModule } from "@angular/core";
|
import { NgModule } from "@angular/core";
|
||||||
import { RouterModule, Routes } from "@angular/router";
|
import { RouterModule, Routes } from "@angular/router";
|
||||||
|
|
||||||
|
import { canAccessBillingTab } from "@bitwarden/common/abstractions/organization/organization.service.abstraction";
|
||||||
|
|
||||||
import { PaymentMethodComponent } from "../../settings/payment-method.component";
|
import { PaymentMethodComponent } from "../../settings/payment-method.component";
|
||||||
import { OrganizationPermissionsGuard } from "../guards/org-permissions.guard";
|
import { OrganizationPermissionsGuard } from "../guards/org-permissions.guard";
|
||||||
import { canAccessBillingTab } from "../navigation-permissions";
|
|
||||||
|
|
||||||
import { OrgBillingHistoryViewComponent } from "./organization-billing-history-view.component";
|
import { OrgBillingHistoryViewComponent } from "./organization-billing-history-view.component";
|
||||||
import { OrganizationBillingTabComponent } from "./organization-billing-tab.component";
|
import { OrganizationBillingTabComponent } from "./organization-billing-tab.component";
|
||||||
|
|||||||
@@ -7,8 +7,8 @@ import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
|||||||
import { I18nService } from "@bitwarden/common/abstractions/i18n.service";
|
import { I18nService } from "@bitwarden/common/abstractions/i18n.service";
|
||||||
import { LogService } from "@bitwarden/common/abstractions/log.service";
|
import { LogService } from "@bitwarden/common/abstractions/log.service";
|
||||||
import { MessagingService } from "@bitwarden/common/abstractions/messaging.service";
|
import { MessagingService } from "@bitwarden/common/abstractions/messaging.service";
|
||||||
import { OrganizationService } from "@bitwarden/common/abstractions/organization.service";
|
|
||||||
import { OrganizationApiServiceAbstraction } from "@bitwarden/common/abstractions/organization/organization-api.service.abstraction";
|
import { OrganizationApiServiceAbstraction } from "@bitwarden/common/abstractions/organization/organization-api.service.abstraction";
|
||||||
|
import { OrganizationService } from "@bitwarden/common/abstractions/organization/organization.service.abstraction";
|
||||||
import { PlatformUtilsService } from "@bitwarden/common/abstractions/platformUtils.service";
|
import { PlatformUtilsService } from "@bitwarden/common/abstractions/platformUtils.service";
|
||||||
import { OrganizationApiKeyType } from "@bitwarden/common/enums/organizationApiKeyType";
|
import { OrganizationApiKeyType } from "@bitwarden/common/enums/organizationApiKeyType";
|
||||||
import { OrganizationConnectionType } from "@bitwarden/common/enums/organizationConnectionType";
|
import { OrganizationConnectionType } from "@bitwarden/common/enums/organizationConnectionType";
|
||||||
@@ -87,7 +87,7 @@ export class OrganizationSubscriptionComponent implements OnInit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.loading = true;
|
this.loading = true;
|
||||||
this.userOrg = await this.organizationService.get(this.organizationId);
|
this.userOrg = this.organizationService.get(this.organizationId);
|
||||||
if (this.userOrg.canManageBilling) {
|
if (this.userOrg.canManageBilling) {
|
||||||
this.sub = await this.organizationApiService.getSubscription(this.organizationId);
|
this.sub = await this.organizationApiService.getSubscription(this.organizationId);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import {
|
|||||||
import { mock, MockProxy } from "jest-mock-extended";
|
import { mock, MockProxy } from "jest-mock-extended";
|
||||||
|
|
||||||
import { I18nService } from "@bitwarden/common/abstractions/i18n.service";
|
import { I18nService } from "@bitwarden/common/abstractions/i18n.service";
|
||||||
import { OrganizationService } from "@bitwarden/common/abstractions/organization.service";
|
import { OrganizationService } from "@bitwarden/common/abstractions/organization/organization.service.abstraction";
|
||||||
import { PlatformUtilsService } from "@bitwarden/common/abstractions/platformUtils.service";
|
import { PlatformUtilsService } from "@bitwarden/common/abstractions/platformUtils.service";
|
||||||
import { SyncService } from "@bitwarden/common/abstractions/sync/sync.service.abstraction";
|
import { SyncService } from "@bitwarden/common/abstractions/sync/sync.service.abstraction";
|
||||||
import { OrganizationUserType } from "@bitwarden/common/enums/organizationUserType";
|
import { OrganizationUserType } from "@bitwarden/common/enums/organizationUserType";
|
||||||
@@ -57,7 +57,7 @@ describe("Organization Permissions Guard", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("blocks navigation if organization does not exist", async () => {
|
it("blocks navigation if organization does not exist", async () => {
|
||||||
organizationService.get.mockResolvedValue(null);
|
organizationService.get.mockReturnValue(null);
|
||||||
|
|
||||||
const actual = await organizationPermissionsGuard.canActivate(route, state);
|
const actual = await organizationPermissionsGuard.canActivate(route, state);
|
||||||
|
|
||||||
@@ -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).mockResolvedValue(org);
|
organizationService.get.calledWith(org.id).mockReturnValue(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).mockResolvedValue(org);
|
organizationService.get.calledWith(org.id).mockReturnValue(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).mockResolvedValue(org);
|
organizationService.get.calledWith(org.id).mockReturnValue(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).mockResolvedValue(org);
|
organizationService.get.calledWith(org.id).mockReturnValue(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).mockResolvedValue(org);
|
organizationService.get.calledWith(org.id).mockReturnValue(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).mockResolvedValue(org);
|
organizationService.get.calledWith(org.id).mockReturnValue(org);
|
||||||
|
|
||||||
const actual = await organizationPermissionsGuard.canActivate(route, state);
|
const actual = await organizationPermissionsGuard.canActivate(route, state);
|
||||||
|
|
||||||
|
|||||||
@@ -2,13 +2,14 @@ import { Injectable } from "@angular/core";
|
|||||||
import { ActivatedRouteSnapshot, CanActivate, Router, RouterStateSnapshot } from "@angular/router";
|
import { ActivatedRouteSnapshot, CanActivate, Router, RouterStateSnapshot } from "@angular/router";
|
||||||
|
|
||||||
import { I18nService } from "@bitwarden/common/abstractions/i18n.service";
|
import { I18nService } from "@bitwarden/common/abstractions/i18n.service";
|
||||||
import { OrganizationService } from "@bitwarden/common/abstractions/organization.service";
|
import {
|
||||||
|
canAccessOrgAdmin,
|
||||||
|
OrganizationService,
|
||||||
|
} from "@bitwarden/common/abstractions/organization/organization.service.abstraction";
|
||||||
import { PlatformUtilsService } from "@bitwarden/common/abstractions/platformUtils.service";
|
import { PlatformUtilsService } from "@bitwarden/common/abstractions/platformUtils.service";
|
||||||
import { SyncService } from "@bitwarden/common/abstractions/sync/sync.service.abstraction";
|
import { SyncService } from "@bitwarden/common/abstractions/sync/sync.service.abstraction";
|
||||||
import { Organization } from "@bitwarden/common/models/domain/organization";
|
import { Organization } from "@bitwarden/common/models/domain/organization";
|
||||||
|
|
||||||
import { canAccessOrgAdmin } from "../navigation-permissions";
|
|
||||||
|
|
||||||
@Injectable({
|
@Injectable({
|
||||||
providedIn: "root",
|
providedIn: "root",
|
||||||
})
|
})
|
||||||
@@ -27,7 +28,7 @@ export class OrganizationPermissionsGuard implements CanActivate {
|
|||||||
await this.syncService.fullSync(false);
|
await this.syncService.fullSync(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
const org = await this.organizationService.get(route.params.organizationId);
|
const org = this.organizationService.get(route.params.organizationId);
|
||||||
if (org == null) {
|
if (org == null) {
|
||||||
return this.router.createUrlTree(["/"]);
|
return this.router.createUrlTree(["/"]);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<app-navbar></app-navbar>
|
<app-navbar></app-navbar>
|
||||||
<div class="org-nav !tw-h-32" *ngIf="organization">
|
<div class="org-nav !tw-h-32" *ngIf="organization$ | async as organization">
|
||||||
<div class="container d-flex">
|
<div class="container d-flex">
|
||||||
<div class="d-flex flex-column">
|
<div class="d-flex flex-column">
|
||||||
<app-organization-switcher
|
<app-organization-switcher
|
||||||
@@ -8,13 +8,21 @@
|
|||||||
></app-organization-switcher>
|
></app-organization-switcher>
|
||||||
<bit-tab-nav-bar class="-tw-mb-px">
|
<bit-tab-nav-bar class="-tw-mb-px">
|
||||||
<bit-tab-link route="vault">{{ "vault" | i18n }}</bit-tab-link>
|
<bit-tab-link route="vault">{{ "vault" | i18n }}</bit-tab-link>
|
||||||
<bit-tab-link *ngIf="showMembersTab" route="members">{{ "members" | i18n }}</bit-tab-link>
|
<bit-tab-link *ngIf="canShowMembersTab(organization)" route="members">{{
|
||||||
<bit-tab-link *ngIf="showGroupsTab" route="groups">{{ "groups" | i18n }}</bit-tab-link>
|
"members" | i18n
|
||||||
<bit-tab-link *ngIf="showReportsTab" [route]="reportRoute">{{
|
|
||||||
reportTabLabel | i18n
|
|
||||||
}}</bit-tab-link>
|
}}</bit-tab-link>
|
||||||
<bit-tab-link *ngIf="showBillingTab" route="billing">{{ "billing" | i18n }}</bit-tab-link>
|
<bit-tab-link *ngIf="canShowGroupsTab(organization)" route="groups">{{
|
||||||
<bit-tab-link *ngIf="showSettingsTab" route="settings">{{
|
"groups" | i18n
|
||||||
|
}}</bit-tab-link>
|
||||||
|
<bit-tab-link
|
||||||
|
*ngIf="canShowReportsTab(organization)"
|
||||||
|
[route]="getReportRoute(organization)"
|
||||||
|
>{{ getReportTabLabel(organization) | i18n }}</bit-tab-link
|
||||||
|
>
|
||||||
|
<bit-tab-link *ngIf="canShowBillingTab(organization)" route="billing">{{
|
||||||
|
"billing" | i18n
|
||||||
|
}}</bit-tab-link>
|
||||||
|
<bit-tab-link *ngIf="canShowSettingsTab(organization)" route="settings">{{
|
||||||
"settings" | i18n
|
"settings" | i18n
|
||||||
}}</bit-tab-link>
|
}}</bit-tab-link>
|
||||||
</bit-tab-nav-bar>
|
</bit-tab-nav-bar>
|
||||||
|
|||||||
@@ -1,10 +1,6 @@
|
|||||||
import { Component, NgZone, OnDestroy, OnInit } from "@angular/core";
|
import { Component, OnDestroy, OnInit } from "@angular/core";
|
||||||
import { ActivatedRoute } from "@angular/router";
|
import { ActivatedRoute } from "@angular/router";
|
||||||
import { concatMap, Subject, takeUntil } from "rxjs";
|
import { map, mergeMap, Observable, Subject, takeUntil } from "rxjs";
|
||||||
|
|
||||||
import { BroadcasterService } from "@bitwarden/common/abstractions/broadcaster.service";
|
|
||||||
import { OrganizationService } from "@bitwarden/common/abstractions/organization.service";
|
|
||||||
import { Organization } from "@bitwarden/common/models/domain/organization";
|
|
||||||
|
|
||||||
import {
|
import {
|
||||||
canAccessBillingTab,
|
canAccessBillingTab,
|
||||||
@@ -12,85 +8,67 @@ import {
|
|||||||
canAccessMembersTab,
|
canAccessMembersTab,
|
||||||
canAccessReportingTab,
|
canAccessReportingTab,
|
||||||
canAccessSettingsTab,
|
canAccessSettingsTab,
|
||||||
} from "../navigation-permissions";
|
getOrganizationById,
|
||||||
|
OrganizationService,
|
||||||
const BroadcasterSubscriptionId = "OrganizationLayoutComponent";
|
} from "@bitwarden/common/abstractions/organization/organization.service.abstraction";
|
||||||
|
import { Organization } from "@bitwarden/common/models/domain/organization";
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: "app-organization-layout",
|
selector: "app-organization-layout",
|
||||||
templateUrl: "organization-layout.component.html",
|
templateUrl: "organization-layout.component.html",
|
||||||
})
|
})
|
||||||
export class OrganizationLayoutComponent implements OnInit, OnDestroy {
|
export class OrganizationLayoutComponent implements OnInit, OnDestroy {
|
||||||
private organizationId: string;
|
organization$: Observable<Organization>;
|
||||||
private destroy$ = new Subject<void>();
|
|
||||||
|
|
||||||
organization: Organization;
|
private _destroy = new Subject<void>();
|
||||||
|
|
||||||
constructor(
|
constructor(private route: ActivatedRoute, private organizationService: OrganizationService) {}
|
||||||
private route: ActivatedRoute,
|
|
||||||
private organizationService: OrganizationService,
|
|
||||||
private broadcasterService: BroadcasterService,
|
|
||||||
private ngZone: NgZone
|
|
||||||
) {}
|
|
||||||
|
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
document.body.classList.remove("layout_frontend");
|
document.body.classList.remove("layout_frontend");
|
||||||
this.route.params
|
|
||||||
.pipe(
|
|
||||||
concatMap(async (params: any) => {
|
|
||||||
this.organizationId = params.organizationId;
|
|
||||||
await this.load();
|
|
||||||
}),
|
|
||||||
takeUntil(this.destroy$)
|
|
||||||
)
|
|
||||||
.subscribe();
|
|
||||||
|
|
||||||
this.broadcasterService.subscribe(BroadcasterSubscriptionId, (message: any) => {
|
this.organization$ = this.route.params
|
||||||
this.ngZone.run(async () => {
|
.pipe(takeUntil(this._destroy))
|
||||||
switch (message.command) {
|
.pipe<string>(map((p) => p.organizationId))
|
||||||
case "updatedOrgLicense":
|
.pipe(
|
||||||
await this.load();
|
mergeMap((id) => {
|
||||||
break;
|
return this.organizationService.organizations$
|
||||||
}
|
.pipe(takeUntil(this._destroy))
|
||||||
});
|
.pipe(getOrganizationById(id));
|
||||||
});
|
})
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnDestroy() {
|
ngOnDestroy() {
|
||||||
this.broadcasterService.unsubscribe(BroadcasterSubscriptionId);
|
this._destroy.next();
|
||||||
this.destroy$.next();
|
this._destroy.complete();
|
||||||
this.destroy$.complete();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async load() {
|
canShowSettingsTab(organization: Organization): boolean {
|
||||||
this.organization = await this.organizationService.get(this.organizationId);
|
return canAccessSettingsTab(organization);
|
||||||
}
|
}
|
||||||
|
|
||||||
get showSettingsTab(): boolean {
|
canShowMembersTab(organization: Organization): boolean {
|
||||||
return canAccessSettingsTab(this.organization);
|
return canAccessMembersTab(organization);
|
||||||
}
|
}
|
||||||
|
|
||||||
get showMembersTab(): boolean {
|
canShowGroupsTab(organization: Organization): boolean {
|
||||||
return canAccessMembersTab(this.organization);
|
return canAccessGroupsTab(organization);
|
||||||
}
|
}
|
||||||
|
|
||||||
get showGroupsTab(): boolean {
|
canShowReportsTab(organization: Organization): boolean {
|
||||||
return canAccessGroupsTab(this.organization);
|
return canAccessReportingTab(organization);
|
||||||
}
|
}
|
||||||
|
|
||||||
get showReportsTab(): boolean {
|
canShowBillingTab(organization: Organization): boolean {
|
||||||
return canAccessReportingTab(this.organization);
|
return canAccessBillingTab(organization);
|
||||||
}
|
}
|
||||||
|
|
||||||
get showBillingTab(): boolean {
|
getReportTabLabel(organization: Organization): string {
|
||||||
return canAccessBillingTab(this.organization);
|
return organization.useEvents ? "reporting" : "reports";
|
||||||
}
|
}
|
||||||
|
|
||||||
get reportTabLabel(): string {
|
getReportRoute(organization: Organization): string {
|
||||||
return this.organization.useEvents ? "reporting" : "reports";
|
return organization.useEvents ? "reporting/events" : "reporting/reports";
|
||||||
}
|
|
||||||
|
|
||||||
get reportRoute(): string {
|
|
||||||
return this.organization.useEvents ? "reporting/events" : "reporting/reports";
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
|||||||
import { CryptoService } from "@bitwarden/common/abstractions/crypto.service";
|
import { CryptoService } from "@bitwarden/common/abstractions/crypto.service";
|
||||||
import { I18nService } from "@bitwarden/common/abstractions/i18n.service";
|
import { I18nService } from "@bitwarden/common/abstractions/i18n.service";
|
||||||
import { LogService } from "@bitwarden/common/abstractions/log.service";
|
import { LogService } from "@bitwarden/common/abstractions/log.service";
|
||||||
import { OrganizationService } from "@bitwarden/common/abstractions/organization.service";
|
import { OrganizationService } from "@bitwarden/common/abstractions/organization/organization.service.abstraction";
|
||||||
import { PlatformUtilsService } from "@bitwarden/common/abstractions/platformUtils.service";
|
import { PlatformUtilsService } from "@bitwarden/common/abstractions/platformUtils.service";
|
||||||
import { Utils } from "@bitwarden/common/misc/utils";
|
import { Utils } from "@bitwarden/common/misc/utils";
|
||||||
import { EncString } from "@bitwarden/common/models/domain/encString";
|
import { EncString } from "@bitwarden/common/models/domain/encString";
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
|||||||
import { CollectionService } from "@bitwarden/common/abstractions/collection.service";
|
import { CollectionService } from "@bitwarden/common/abstractions/collection.service";
|
||||||
import { I18nService } from "@bitwarden/common/abstractions/i18n.service";
|
import { I18nService } from "@bitwarden/common/abstractions/i18n.service";
|
||||||
import { LogService } from "@bitwarden/common/abstractions/log.service";
|
import { LogService } from "@bitwarden/common/abstractions/log.service";
|
||||||
import { OrganizationService } from "@bitwarden/common/abstractions/organization.service";
|
import { OrganizationService } from "@bitwarden/common/abstractions/organization/organization.service.abstraction";
|
||||||
import { PlatformUtilsService } from "@bitwarden/common/abstractions/platformUtils.service";
|
import { PlatformUtilsService } from "@bitwarden/common/abstractions/platformUtils.service";
|
||||||
import { SearchService } from "@bitwarden/common/abstractions/search.service";
|
import { SearchService } from "@bitwarden/common/abstractions/search.service";
|
||||||
import { CollectionData } from "@bitwarden/common/models/data/collectionData";
|
import { CollectionData } from "@bitwarden/common/models/data/collectionData";
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import { ExportService } from "@bitwarden/common/abstractions/export.service";
|
|||||||
import { FileDownloadService } from "@bitwarden/common/abstractions/fileDownload/fileDownload.service";
|
import { FileDownloadService } from "@bitwarden/common/abstractions/fileDownload/fileDownload.service";
|
||||||
import { I18nService } from "@bitwarden/common/abstractions/i18n.service";
|
import { I18nService } from "@bitwarden/common/abstractions/i18n.service";
|
||||||
import { LogService } from "@bitwarden/common/abstractions/log.service";
|
import { LogService } from "@bitwarden/common/abstractions/log.service";
|
||||||
import { OrganizationService } from "@bitwarden/common/abstractions/organization.service";
|
import { OrganizationService } from "@bitwarden/common/abstractions/organization/organization.service.abstraction";
|
||||||
import { PlatformUtilsService } from "@bitwarden/common/abstractions/platformUtils.service";
|
import { PlatformUtilsService } from "@bitwarden/common/abstractions/platformUtils.service";
|
||||||
import { ProviderService } from "@bitwarden/common/abstractions/provider.service";
|
import { ProviderService } from "@bitwarden/common/abstractions/provider.service";
|
||||||
import { Organization } from "@bitwarden/common/models/domain/organization";
|
import { Organization } from "@bitwarden/common/models/domain/organization";
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { Component, OnInit } from "@angular/core";
|
import { Component, OnInit } from "@angular/core";
|
||||||
import { ActivatedRoute } from "@angular/router";
|
import { ActivatedRoute } from "@angular/router";
|
||||||
|
|
||||||
import { OrganizationService } from "@bitwarden/common/abstractions/organization.service";
|
import { OrganizationService } from "@bitwarden/common/abstractions/organization/organization.service.abstraction";
|
||||||
import { Organization } from "@bitwarden/common/models/domain/organization";
|
import { Organization } from "@bitwarden/common/models/domain/organization";
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
|
|||||||
@@ -10,8 +10,8 @@ import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
|||||||
import { CryptoService } from "@bitwarden/common/abstractions/crypto.service";
|
import { CryptoService } from "@bitwarden/common/abstractions/crypto.service";
|
||||||
import { I18nService } from "@bitwarden/common/abstractions/i18n.service";
|
import { I18nService } from "@bitwarden/common/abstractions/i18n.service";
|
||||||
import { LogService } from "@bitwarden/common/abstractions/log.service";
|
import { LogService } from "@bitwarden/common/abstractions/log.service";
|
||||||
import { OrganizationService } from "@bitwarden/common/abstractions/organization.service";
|
|
||||||
import { OrganizationApiServiceAbstraction } from "@bitwarden/common/abstractions/organization/organization-api.service.abstraction";
|
import { OrganizationApiServiceAbstraction } from "@bitwarden/common/abstractions/organization/organization-api.service.abstraction";
|
||||||
|
import { OrganizationService } from "@bitwarden/common/abstractions/organization/organization.service.abstraction";
|
||||||
import { PlatformUtilsService } from "@bitwarden/common/abstractions/platformUtils.service";
|
import { PlatformUtilsService } from "@bitwarden/common/abstractions/platformUtils.service";
|
||||||
import { PolicyApiServiceAbstraction } from "@bitwarden/common/abstractions/policy/policy-api.service.abstraction";
|
import { PolicyApiServiceAbstraction } from "@bitwarden/common/abstractions/policy/policy-api.service.abstraction";
|
||||||
import { PolicyService } from "@bitwarden/common/abstractions/policy/policy.service.abstraction";
|
import { PolicyService } from "@bitwarden/common/abstractions/policy/policy.service.abstraction";
|
||||||
|
|||||||
@@ -1,31 +0,0 @@
|
|||||||
import { Organization } from "@bitwarden/common/models/domain/organization";
|
|
||||||
|
|
||||||
export function canAccessMembersTab(org: Organization): boolean {
|
|
||||||
return org.canManageUsers || org.canManageUsersPassword;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function canAccessGroupsTab(org: Organization): boolean {
|
|
||||||
return org.canManageGroups;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function canAccessReportingTab(org: Organization): boolean {
|
|
||||||
return org.canAccessReports || org.canAccessEventLogs;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function canAccessBillingTab(org: Organization): boolean {
|
|
||||||
return org.canManageBilling;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function canAccessSettingsTab(org: Organization): boolean {
|
|
||||||
return org.isOwner;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function canAccessOrgAdmin(org: Organization): boolean {
|
|
||||||
return (
|
|
||||||
canAccessMembersTab(org) ||
|
|
||||||
canAccessGroupsTab(org) ||
|
|
||||||
canAccessReportingTab(org) ||
|
|
||||||
canAccessBillingTab(org) ||
|
|
||||||
canAccessSettingsTab(org)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -2,16 +2,16 @@ import { NgModule } from "@angular/core";
|
|||||||
import { RouterModule, Routes } from "@angular/router";
|
import { RouterModule, Routes } from "@angular/router";
|
||||||
|
|
||||||
import { AuthGuard } from "@bitwarden/angular/guards/auth.guard";
|
import { AuthGuard } from "@bitwarden/angular/guards/auth.guard";
|
||||||
|
import {
|
||||||
|
canAccessOrgAdmin,
|
||||||
|
canAccessGroupsTab,
|
||||||
|
canAccessMembersTab,
|
||||||
|
} from "@bitwarden/common/abstractions/organization/organization.service.abstraction";
|
||||||
|
|
||||||
import { OrganizationPermissionsGuard } from "./guards/org-permissions.guard";
|
import { OrganizationPermissionsGuard } from "./guards/org-permissions.guard";
|
||||||
import { OrganizationLayoutComponent } from "./layouts/organization-layout.component";
|
import { OrganizationLayoutComponent } from "./layouts/organization-layout.component";
|
||||||
import { GroupsComponent } from "./manage/groups.component";
|
import { GroupsComponent } from "./manage/groups.component";
|
||||||
import { PeopleComponent } from "./manage/people.component";
|
import { PeopleComponent } from "./manage/people.component";
|
||||||
import {
|
|
||||||
canAccessGroupsTab,
|
|
||||||
canAccessMembersTab,
|
|
||||||
canAccessOrgAdmin,
|
|
||||||
} from "./navigation-permissions";
|
|
||||||
import { VaultModule } from "./vault/vault.module";
|
import { VaultModule } from "./vault/vault.module";
|
||||||
|
|
||||||
const routes: Routes = [
|
const routes: Routes = [
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import { Component } from "@angular/core";
|
|||||||
import { UntypedFormBuilder } from "@angular/forms";
|
import { UntypedFormBuilder } from "@angular/forms";
|
||||||
|
|
||||||
import { I18nService } from "@bitwarden/common/abstractions/i18n.service";
|
import { I18nService } from "@bitwarden/common/abstractions/i18n.service";
|
||||||
import { OrganizationService } from "@bitwarden/common/abstractions/organization.service";
|
import { OrganizationService } from "@bitwarden/common/abstractions/organization/organization.service.abstraction";
|
||||||
import { PolicyType } from "@bitwarden/common/enums/policyType";
|
import { PolicyType } from "@bitwarden/common/enums/policyType";
|
||||||
|
|
||||||
import { BasePolicy, BasePolicyComponent } from "./base-policy.component";
|
import { BasePolicy, BasePolicyComponent } from "./base-policy.component";
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import { ActivatedRoute, Router } from "@angular/router";
|
|||||||
import { first } from "rxjs/operators";
|
import { first } from "rxjs/operators";
|
||||||
|
|
||||||
import { ModalService } from "@bitwarden/angular/services/modal.service";
|
import { ModalService } from "@bitwarden/angular/services/modal.service";
|
||||||
import { OrganizationService } from "@bitwarden/common/abstractions/organization.service";
|
import { OrganizationService } from "@bitwarden/common/abstractions/organization/organization.service.abstraction";
|
||||||
import { PolicyApiServiceAbstraction } from "@bitwarden/common/abstractions/policy/policy-api.service.abstraction";
|
import { PolicyApiServiceAbstraction } from "@bitwarden/common/abstractions/policy/policy-api.service.abstraction";
|
||||||
import { PolicyType } from "@bitwarden/common/enums/policyType";
|
import { PolicyType } from "@bitwarden/common/enums/policyType";
|
||||||
import { Organization } from "@bitwarden/common/models/domain/organization";
|
import { Organization } from "@bitwarden/common/models/domain/organization";
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { Component } from "@angular/core";
|
import { Component } from "@angular/core";
|
||||||
import { UntypedFormBuilder } from "@angular/forms";
|
import { UntypedFormBuilder } from "@angular/forms";
|
||||||
|
|
||||||
import { OrganizationService } from "@bitwarden/common/abstractions/organization.service";
|
import { OrganizationService } from "@bitwarden/common/abstractions/organization/organization.service.abstraction";
|
||||||
import { PolicyType } from "@bitwarden/common/enums/policyType";
|
import { PolicyType } from "@bitwarden/common/enums/policyType";
|
||||||
import { Organization } from "@bitwarden/common/models/domain/organization";
|
import { Organization } from "@bitwarden/common/models/domain/organization";
|
||||||
|
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
import { NgModule } from "@angular/core";
|
import { NgModule } from "@angular/core";
|
||||||
import { RouterModule, Routes } from "@angular/router";
|
import { RouterModule, Routes } from "@angular/router";
|
||||||
|
|
||||||
|
import { canAccessReportingTab } from "@bitwarden/common/abstractions/organization/organization.service.abstraction";
|
||||||
import { Organization } from "@bitwarden/common/models/domain/organization";
|
import { Organization } from "@bitwarden/common/models/domain/organization";
|
||||||
|
|
||||||
import { OrganizationPermissionsGuard } from "../guards/org-permissions.guard";
|
import { OrganizationPermissionsGuard } from "../guards/org-permissions.guard";
|
||||||
import { EventsComponent } from "../manage/events.component";
|
import { EventsComponent } from "../manage/events.component";
|
||||||
import { canAccessReportingTab } from "../navigation-permissions";
|
|
||||||
import { ExposedPasswordsReportComponent } from "../tools/exposed-passwords-report.component";
|
import { ExposedPasswordsReportComponent } from "../tools/exposed-passwords-report.component";
|
||||||
import { InactiveTwoFactorReportComponent } from "../tools/inactive-two-factor-report.component";
|
import { InactiveTwoFactorReportComponent } from "../tools/inactive-two-factor-report.component";
|
||||||
import { ReusedPasswordsReportComponent } from "../tools/reused-passwords-report.component";
|
import { ReusedPasswordsReportComponent } from "../tools/reused-passwords-report.component";
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import { Component, OnDestroy, OnInit } from "@angular/core";
|
|||||||
import { ActivatedRoute } from "@angular/router";
|
import { ActivatedRoute } from "@angular/router";
|
||||||
import { concatMap, Subject, takeUntil } from "rxjs";
|
import { concatMap, Subject, takeUntil } from "rxjs";
|
||||||
|
|
||||||
import { OrganizationService } from "@bitwarden/common/abstractions/organization.service";
|
import { OrganizationService } from "@bitwarden/common/abstractions/organization/organization.service.abstraction";
|
||||||
import { Organization } from "@bitwarden/common/models/domain/organization";
|
import { Organization } from "@bitwarden/common/models/domain/organization";
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
|
|||||||
@@ -56,9 +56,9 @@
|
|||||||
<app-avatar data="{{ org.name }}" dynamic="true" size="75" fontSize="35"></app-avatar>
|
<app-avatar data="{{ org.name }}" dynamic="true" size="75" fontSize="35"></app-avatar>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<bit-submit-button [loading]="form.loading">
|
<button type="submit" buttonType="primary" bitButton [loading]="form.loading">
|
||||||
{{ "save" | i18n }}
|
{{ "save" | i18n }}
|
||||||
</bit-submit-button>
|
</button>
|
||||||
</form>
|
</form>
|
||||||
<ng-container *ngIf="canUseApi">
|
<ng-container *ngIf="canUseApi">
|
||||||
<div class="secondary-header border-0 mb-0">
|
<div class="secondary-header border-0 mb-0">
|
||||||
|
|||||||
@@ -2,14 +2,12 @@ import { Component, ViewChild, ViewContainerRef } from "@angular/core";
|
|||||||
import { ActivatedRoute, Router } from "@angular/router";
|
import { ActivatedRoute, Router } from "@angular/router";
|
||||||
|
|
||||||
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 { CryptoService } from "@bitwarden/common/abstractions/crypto.service";
|
import { CryptoService } from "@bitwarden/common/abstractions/crypto.service";
|
||||||
import { I18nService } from "@bitwarden/common/abstractions/i18n.service";
|
import { I18nService } from "@bitwarden/common/abstractions/i18n.service";
|
||||||
import { LogService } from "@bitwarden/common/abstractions/log.service";
|
import { LogService } from "@bitwarden/common/abstractions/log.service";
|
||||||
import { OrganizationService } from "@bitwarden/common/abstractions/organization.service";
|
|
||||||
import { OrganizationApiServiceAbstraction } from "@bitwarden/common/abstractions/organization/organization-api.service.abstraction";
|
import { OrganizationApiServiceAbstraction } from "@bitwarden/common/abstractions/organization/organization-api.service.abstraction";
|
||||||
|
import { OrganizationService } from "@bitwarden/common/abstractions/organization/organization.service.abstraction";
|
||||||
import { PlatformUtilsService } from "@bitwarden/common/abstractions/platformUtils.service";
|
import { PlatformUtilsService } from "@bitwarden/common/abstractions/platformUtils.service";
|
||||||
import { SyncService } from "@bitwarden/common/abstractions/sync/sync.service.abstraction";
|
|
||||||
import { OrganizationKeysRequest } from "@bitwarden/common/models/request/organizationKeysRequest";
|
import { OrganizationKeysRequest } from "@bitwarden/common/models/request/organizationKeysRequest";
|
||||||
import { OrganizationUpdateRequest } from "@bitwarden/common/models/request/organizationUpdateRequest";
|
import { OrganizationUpdateRequest } from "@bitwarden/common/models/request/organizationUpdateRequest";
|
||||||
import { OrganizationResponse } from "@bitwarden/common/models/response/organizationResponse";
|
import { OrganizationResponse } from "@bitwarden/common/models/response/organizationResponse";
|
||||||
@@ -39,17 +37,15 @@ export class AccountComponent {
|
|||||||
loading = true;
|
loading = true;
|
||||||
canUseApi = false;
|
canUseApi = false;
|
||||||
org: OrganizationResponse;
|
org: OrganizationResponse;
|
||||||
formPromise: Promise<boolean>;
|
formPromise: Promise<OrganizationResponse>;
|
||||||
taxFormPromise: Promise<unknown>;
|
taxFormPromise: Promise<unknown>;
|
||||||
|
|
||||||
private organizationId: string;
|
private organizationId: string;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private modalService: ModalService,
|
private modalService: ModalService,
|
||||||
private apiService: ApiService,
|
|
||||||
private i18nService: I18nService,
|
private i18nService: I18nService,
|
||||||
private route: ActivatedRoute,
|
private route: ActivatedRoute,
|
||||||
private syncService: SyncService,
|
|
||||||
private platformUtilsService: PlatformUtilsService,
|
private platformUtilsService: PlatformUtilsService,
|
||||||
private cryptoService: CryptoService,
|
private cryptoService: CryptoService,
|
||||||
private logService: LogService,
|
private logService: LogService,
|
||||||
@@ -64,9 +60,7 @@ export class AccountComponent {
|
|||||||
// 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.parent.parent.params.subscribe(async (params) => {
|
this.route.parent.parent.params.subscribe(async (params) => {
|
||||||
this.organizationId = params.organizationId;
|
this.organizationId = params.organizationId;
|
||||||
this.canManageBilling = (
|
this.canManageBilling = this.organizationService.get(this.organizationId).canManageBilling;
|
||||||
await this.organizationService.get(this.organizationId)
|
|
||||||
).canManageBilling;
|
|
||||||
try {
|
try {
|
||||||
this.org = await this.organizationApiService.get(this.organizationId);
|
this.org = await this.organizationApiService.get(this.organizationId);
|
||||||
this.canUseApi = this.org.useApi;
|
this.canUseApi = this.org.useApi;
|
||||||
@@ -92,9 +86,7 @@ export class AccountComponent {
|
|||||||
request.keys = new OrganizationKeysRequest(orgKeys[0], orgKeys[1].encryptedString);
|
request.keys = new OrganizationKeysRequest(orgKeys[0], orgKeys[1].encryptedString);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.formPromise = this.organizationApiService.save(this.organizationId, request).then(() => {
|
this.formPromise = this.organizationApiService.save(this.organizationId, request);
|
||||||
return this.syncService.fullSync(true);
|
|
||||||
});
|
|
||||||
await this.formPromise;
|
await this.formPromise;
|
||||||
this.platformUtilsService.showToast(
|
this.platformUtilsService.showToast(
|
||||||
"success",
|
"success",
|
||||||
|
|||||||
@@ -3,8 +3,8 @@ import { Component, EventEmitter, OnInit, Output } from "@angular/core";
|
|||||||
import { CipherService } from "@bitwarden/common/abstractions/cipher.service";
|
import { CipherService } from "@bitwarden/common/abstractions/cipher.service";
|
||||||
import { I18nService } from "@bitwarden/common/abstractions/i18n.service";
|
import { I18nService } from "@bitwarden/common/abstractions/i18n.service";
|
||||||
import { LogService } from "@bitwarden/common/abstractions/log.service";
|
import { LogService } from "@bitwarden/common/abstractions/log.service";
|
||||||
import { OrganizationService } from "@bitwarden/common/abstractions/organization.service";
|
|
||||||
import { OrganizationApiServiceAbstraction } from "@bitwarden/common/abstractions/organization/organization-api.service.abstraction";
|
import { OrganizationApiServiceAbstraction } from "@bitwarden/common/abstractions/organization/organization-api.service.abstraction";
|
||||||
|
import { OrganizationService } from "@bitwarden/common/abstractions/organization/organization.service.abstraction";
|
||||||
import { PlatformUtilsService } from "@bitwarden/common/abstractions/platformUtils.service";
|
import { PlatformUtilsService } from "@bitwarden/common/abstractions/platformUtils.service";
|
||||||
import { UserVerificationService } from "@bitwarden/common/abstractions/userVerification/userVerification.service.abstraction";
|
import { UserVerificationService } from "@bitwarden/common/abstractions/userVerification/userVerification.service.abstraction";
|
||||||
import { CipherType } from "@bitwarden/common/enums/cipherType";
|
import { CipherType } from "@bitwarden/common/enums/cipherType";
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
import { NgModule } from "@angular/core";
|
import { NgModule } from "@angular/core";
|
||||||
import { RouterModule, Routes } from "@angular/router";
|
import { RouterModule, Routes } from "@angular/router";
|
||||||
|
|
||||||
|
import { canAccessSettingsTab } from "@bitwarden/common/abstractions/organization/organization.service.abstraction";
|
||||||
import { Organization } from "@bitwarden/common/models/domain/organization";
|
import { Organization } from "@bitwarden/common/models/domain/organization";
|
||||||
|
|
||||||
import { OrganizationPermissionsGuard } from "../guards/org-permissions.guard";
|
import { OrganizationPermissionsGuard } from "../guards/org-permissions.guard";
|
||||||
import { canAccessSettingsTab } from "../navigation-permissions";
|
|
||||||
import { PoliciesComponent } from "../policies";
|
import { PoliciesComponent } from "../policies";
|
||||||
|
|
||||||
import { AccountComponent } from "./account.component";
|
import { AccountComponent } from "./account.component";
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import { Component, OnDestroy, OnInit } from "@angular/core";
|
|||||||
import { ActivatedRoute } from "@angular/router";
|
import { ActivatedRoute } from "@angular/router";
|
||||||
import { Subject, switchMap, takeUntil } from "rxjs";
|
import { Subject, switchMap, takeUntil } from "rxjs";
|
||||||
|
|
||||||
import { OrganizationService } from "@bitwarden/common/abstractions/organization.service";
|
import { OrganizationService } from "@bitwarden/common/abstractions/organization/organization.service.abstraction";
|
||||||
import { Organization } from "@bitwarden/common/models/domain/organization";
|
import { Organization } from "@bitwarden/common/models/domain/organization";
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
|
|||||||
@@ -34,7 +34,9 @@
|
|||||||
>
|
>
|
||||||
<option value="" disabled>-- {{ "select" | i18n }} --</option>
|
<option value="" disabled>-- {{ "select" | i18n }} --</option>
|
||||||
<option value="createNew">{{ "newFamiliesOrganization" | i18n }}</option>
|
<option value="createNew">{{ "newFamiliesOrganization" | i18n }}</option>
|
||||||
<option *ngFor="let o of existingFamilyOrganizations" [ngValue]="o.id">{{ o.name }}</option>
|
<option *ngFor="let o of existingFamilyOrganizations$ | async" [ngValue]="o.id">
|
||||||
|
{{ o.name }}
|
||||||
|
</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
<div *ngIf="showNewOrganization" class="col-12">
|
<div *ngIf="showNewOrganization" class="col-12">
|
||||||
|
|||||||
@@ -1,12 +1,13 @@
|
|||||||
import { Component, OnInit, ViewChild, ViewContainerRef } from "@angular/core";
|
import { Component, OnDestroy, OnInit, ViewChild, ViewContainerRef } from "@angular/core";
|
||||||
import { ActivatedRoute, Router } from "@angular/router";
|
import { ActivatedRoute, Router } from "@angular/router";
|
||||||
import { first } from "rxjs/operators";
|
import { Observable, Subject } from "rxjs";
|
||||||
|
import { first, map, takeUntil } from "rxjs/operators";
|
||||||
|
|
||||||
import { ModalService } from "@bitwarden/angular/services/modal.service";
|
import { ModalService } from "@bitwarden/angular/services/modal.service";
|
||||||
import { ValidationService } from "@bitwarden/angular/services/validation.service";
|
import { ValidationService } from "@bitwarden/angular/services/validation.service";
|
||||||
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
||||||
import { I18nService } from "@bitwarden/common/abstractions/i18n.service";
|
import { I18nService } from "@bitwarden/common/abstractions/i18n.service";
|
||||||
import { OrganizationService } from "@bitwarden/common/abstractions/organization.service";
|
import { OrganizationService } from "@bitwarden/common/abstractions/organization/organization.service.abstraction";
|
||||||
import { PlatformUtilsService } from "@bitwarden/common/abstractions/platformUtils.service";
|
import { PlatformUtilsService } from "@bitwarden/common/abstractions/platformUtils.service";
|
||||||
import { SyncService } from "@bitwarden/common/abstractions/sync/sync.service.abstraction";
|
import { SyncService } from "@bitwarden/common/abstractions/sync/sync.service.abstraction";
|
||||||
import { PlanSponsorshipType } from "@bitwarden/common/enums/planSponsorshipType";
|
import { PlanSponsorshipType } from "@bitwarden/common/enums/planSponsorshipType";
|
||||||
@@ -22,8 +23,7 @@ import { OrganizationPlansComponent } from "../../settings/organization-plans.co
|
|||||||
selector: "families-for-enterprise-setup",
|
selector: "families-for-enterprise-setup",
|
||||||
templateUrl: "families-for-enterprise-setup.component.html",
|
templateUrl: "families-for-enterprise-setup.component.html",
|
||||||
})
|
})
|
||||||
// eslint-disable-next-line rxjs-angular/prefer-takeuntil
|
export class FamiliesForEnterpriseSetupComponent implements OnInit, OnDestroy {
|
||||||
export class FamiliesForEnterpriseSetupComponent implements OnInit {
|
|
||||||
@ViewChild(OrganizationPlansComponent, { static: false })
|
@ViewChild(OrganizationPlansComponent, { static: false })
|
||||||
set organizationPlansComponent(value: OrganizationPlansComponent) {
|
set organizationPlansComponent(value: OrganizationPlansComponent) {
|
||||||
if (!value) {
|
if (!value) {
|
||||||
@@ -46,11 +46,14 @@ export class FamiliesForEnterpriseSetupComponent implements OnInit {
|
|||||||
|
|
||||||
token: string;
|
token: string;
|
||||||
existingFamilyOrganizations: Organization[];
|
existingFamilyOrganizations: Organization[];
|
||||||
|
existingFamilyOrganizations$: Observable<Organization[]>;
|
||||||
|
|
||||||
showNewOrganization = false;
|
showNewOrganization = false;
|
||||||
_organizationPlansComponent: OrganizationPlansComponent;
|
_organizationPlansComponent: OrganizationPlansComponent;
|
||||||
_selectedFamilyOrganizationId = "";
|
_selectedFamilyOrganizationId = "";
|
||||||
|
|
||||||
|
private _destroy = new Subject<void>();
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private router: Router,
|
private router: Router,
|
||||||
private platformUtilsService: PlatformUtilsService,
|
private platformUtilsService: PlatformUtilsService,
|
||||||
@@ -84,17 +87,24 @@ export class FamiliesForEnterpriseSetupComponent implements OnInit {
|
|||||||
await this.syncService.fullSync(true);
|
await this.syncService.fullSync(true);
|
||||||
this.badToken = !(await this.apiService.postPreValidateSponsorshipToken(this.token));
|
this.badToken = !(await this.apiService.postPreValidateSponsorshipToken(this.token));
|
||||||
this.loading = false;
|
this.loading = false;
|
||||||
|
});
|
||||||
|
|
||||||
this.existingFamilyOrganizations = (await this.organizationService.getAll()).filter(
|
this.existingFamilyOrganizations$ = this.organizationService.organizations$.pipe(
|
||||||
(o) => o.planProductType === ProductType.Families
|
map((orgs) => orgs.filter((o) => o.planProductType === ProductType.Families))
|
||||||
);
|
);
|
||||||
|
|
||||||
if (this.existingFamilyOrganizations.length === 0) {
|
this.existingFamilyOrganizations$.pipe(takeUntil(this._destroy)).subscribe((orgs) => {
|
||||||
|
if (orgs.length === 0) {
|
||||||
this.selectedFamilyOrganizationId = "createNew";
|
this.selectedFamilyOrganizationId = "createNew";
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ngOnDestroy(): void {
|
||||||
|
this._destroy.next();
|
||||||
|
this._destroy.complete();
|
||||||
|
}
|
||||||
|
|
||||||
async submit() {
|
async submit() {
|
||||||
this.formPromise = this.doSubmit(this._selectedFamilyOrganizationId);
|
this.formPromise = this.doSubmit(this._selectedFamilyOrganizationId);
|
||||||
await this.formPromise;
|
await this.formPromise;
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import { ModalService } from "@bitwarden/angular/services/modal.service";
|
|||||||
import { AuditService } from "@bitwarden/common/abstractions/audit.service";
|
import { AuditService } from "@bitwarden/common/abstractions/audit.service";
|
||||||
import { CipherService } from "@bitwarden/common/abstractions/cipher.service";
|
import { CipherService } from "@bitwarden/common/abstractions/cipher.service";
|
||||||
import { MessagingService } from "@bitwarden/common/abstractions/messaging.service";
|
import { MessagingService } from "@bitwarden/common/abstractions/messaging.service";
|
||||||
import { OrganizationService } from "@bitwarden/common/abstractions/organization.service";
|
import { OrganizationService } from "@bitwarden/common/abstractions/organization/organization.service.abstraction";
|
||||||
import { PasswordRepromptService } from "@bitwarden/common/abstractions/passwordReprompt.service";
|
import { PasswordRepromptService } from "@bitwarden/common/abstractions/passwordReprompt.service";
|
||||||
import { StateService } from "@bitwarden/common/abstractions/state.service";
|
import { StateService } from "@bitwarden/common/abstractions/state.service";
|
||||||
import { Cipher } from "@bitwarden/common/models/domain/cipher";
|
import { Cipher } from "@bitwarden/common/models/domain/cipher";
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import { ModalService } from "@bitwarden/angular/services/modal.service";
|
|||||||
import { I18nService } from "@bitwarden/common/abstractions/i18n.service";
|
import { I18nService } from "@bitwarden/common/abstractions/i18n.service";
|
||||||
import { ImportService } from "@bitwarden/common/abstractions/import.service";
|
import { ImportService } from "@bitwarden/common/abstractions/import.service";
|
||||||
import { LogService } from "@bitwarden/common/abstractions/log.service";
|
import { LogService } from "@bitwarden/common/abstractions/log.service";
|
||||||
import { OrganizationService } from "@bitwarden/common/abstractions/organization.service";
|
import { OrganizationService } from "@bitwarden/common/abstractions/organization/organization.service.abstraction";
|
||||||
import { PlatformUtilsService } from "@bitwarden/common/abstractions/platformUtils.service";
|
import { PlatformUtilsService } from "@bitwarden/common/abstractions/platformUtils.service";
|
||||||
import { PolicyService } from "@bitwarden/common/abstractions/policy/policy.service.abstraction";
|
import { PolicyService } from "@bitwarden/common/abstractions/policy/policy.service.abstraction";
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import { ModalService } from "@bitwarden/angular/services/modal.service";
|
|||||||
import { CipherService } from "@bitwarden/common/abstractions/cipher.service";
|
import { CipherService } from "@bitwarden/common/abstractions/cipher.service";
|
||||||
import { LogService } from "@bitwarden/common/abstractions/log.service";
|
import { LogService } from "@bitwarden/common/abstractions/log.service";
|
||||||
import { MessagingService } from "@bitwarden/common/abstractions/messaging.service";
|
import { MessagingService } from "@bitwarden/common/abstractions/messaging.service";
|
||||||
import { OrganizationService } from "@bitwarden/common/abstractions/organization.service";
|
import { OrganizationService } from "@bitwarden/common/abstractions/organization/organization.service.abstraction";
|
||||||
import { PasswordRepromptService } from "@bitwarden/common/abstractions/passwordReprompt.service";
|
import { PasswordRepromptService } from "@bitwarden/common/abstractions/passwordReprompt.service";
|
||||||
import { StateService } from "@bitwarden/common/abstractions/state.service";
|
import { StateService } from "@bitwarden/common/abstractions/state.service";
|
||||||
import { CipherView } from "@bitwarden/common/models/view/cipherView";
|
import { CipherView } from "@bitwarden/common/models/view/cipherView";
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import { ActivatedRoute } from "@angular/router";
|
|||||||
import { ModalService } from "@bitwarden/angular/services/modal.service";
|
import { ModalService } from "@bitwarden/angular/services/modal.service";
|
||||||
import { CipherService } from "@bitwarden/common/abstractions/cipher.service";
|
import { CipherService } from "@bitwarden/common/abstractions/cipher.service";
|
||||||
import { MessagingService } from "@bitwarden/common/abstractions/messaging.service";
|
import { MessagingService } from "@bitwarden/common/abstractions/messaging.service";
|
||||||
import { OrganizationService } from "@bitwarden/common/abstractions/organization.service";
|
import { OrganizationService } from "@bitwarden/common/abstractions/organization/organization.service.abstraction";
|
||||||
import { PasswordRepromptService } from "@bitwarden/common/abstractions/passwordReprompt.service";
|
import { PasswordRepromptService } from "@bitwarden/common/abstractions/passwordReprompt.service";
|
||||||
import { StateService } from "@bitwarden/common/abstractions/state.service";
|
import { StateService } from "@bitwarden/common/abstractions/state.service";
|
||||||
import { Cipher } from "@bitwarden/common/models/domain/cipher";
|
import { Cipher } from "@bitwarden/common/models/domain/cipher";
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import { Component } from "@angular/core";
|
|||||||
import { ActivatedRoute } from "@angular/router";
|
import { ActivatedRoute } from "@angular/router";
|
||||||
|
|
||||||
import { MessagingService } from "@bitwarden/common/abstractions/messaging.service";
|
import { MessagingService } from "@bitwarden/common/abstractions/messaging.service";
|
||||||
import { OrganizationService } from "@bitwarden/common/abstractions/organization.service";
|
import { OrganizationService } from "@bitwarden/common/abstractions/organization/organization.service.abstraction";
|
||||||
import { Organization } from "@bitwarden/common/models/domain/organization";
|
import { Organization } from "@bitwarden/common/models/domain/organization";
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import { ActivatedRoute } from "@angular/router";
|
|||||||
import { ModalService } from "@bitwarden/angular/services/modal.service";
|
import { ModalService } from "@bitwarden/angular/services/modal.service";
|
||||||
import { CipherService } from "@bitwarden/common/abstractions/cipher.service";
|
import { CipherService } from "@bitwarden/common/abstractions/cipher.service";
|
||||||
import { MessagingService } from "@bitwarden/common/abstractions/messaging.service";
|
import { MessagingService } from "@bitwarden/common/abstractions/messaging.service";
|
||||||
import { OrganizationService } from "@bitwarden/common/abstractions/organization.service";
|
import { OrganizationService } from "@bitwarden/common/abstractions/organization/organization.service.abstraction";
|
||||||
import { PasswordRepromptService } from "@bitwarden/common/abstractions/passwordReprompt.service";
|
import { PasswordRepromptService } from "@bitwarden/common/abstractions/passwordReprompt.service";
|
||||||
import { StateService } from "@bitwarden/common/abstractions/state.service";
|
import { StateService } from "@bitwarden/common/abstractions/state.service";
|
||||||
import { CipherView } from "@bitwarden/common/models/view/cipherView";
|
import { CipherView } from "@bitwarden/common/models/view/cipherView";
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import { ActivatedRoute } from "@angular/router";
|
|||||||
import { ModalService } from "@bitwarden/angular/services/modal.service";
|
import { ModalService } from "@bitwarden/angular/services/modal.service";
|
||||||
import { CipherService } from "@bitwarden/common/abstractions/cipher.service";
|
import { CipherService } from "@bitwarden/common/abstractions/cipher.service";
|
||||||
import { MessagingService } from "@bitwarden/common/abstractions/messaging.service";
|
import { MessagingService } from "@bitwarden/common/abstractions/messaging.service";
|
||||||
import { OrganizationService } from "@bitwarden/common/abstractions/organization.service";
|
import { OrganizationService } from "@bitwarden/common/abstractions/organization/organization.service.abstraction";
|
||||||
import { PasswordGenerationService } from "@bitwarden/common/abstractions/passwordGeneration.service";
|
import { PasswordGenerationService } from "@bitwarden/common/abstractions/passwordGeneration.service";
|
||||||
import { PasswordRepromptService } from "@bitwarden/common/abstractions/passwordReprompt.service";
|
import { PasswordRepromptService } from "@bitwarden/common/abstractions/passwordReprompt.service";
|
||||||
import { StateService } from "@bitwarden/common/abstractions/state.service";
|
import { StateService } from "@bitwarden/common/abstractions/state.service";
|
||||||
|
|||||||
@@ -32,9 +32,9 @@
|
|||||||
<app-user-verification [(ngModel)]="verification" name="secret"> </app-user-verification>
|
<app-user-verification [(ngModel)]="verification" name="secret"> </app-user-verification>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-footer">
|
<div class="modal-footer">
|
||||||
<bit-submit-button [loading]="form.loading">
|
<button type="submit" buttonType="primary" bitButton [loading]="form.loading">
|
||||||
{{ "submit" | i18n }}
|
{{ "submit" | i18n }}
|
||||||
</bit-submit-button>
|
</button>
|
||||||
<button
|
<button
|
||||||
bitButton
|
bitButton
|
||||||
buttonType="secondary"
|
buttonType="secondary"
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import { FolderService } from "@bitwarden/common/abstractions/folder/folder.serv
|
|||||||
import { I18nService } from "@bitwarden/common/abstractions/i18n.service";
|
import { I18nService } from "@bitwarden/common/abstractions/i18n.service";
|
||||||
import { LogService } from "@bitwarden/common/abstractions/log.service";
|
import { LogService } from "@bitwarden/common/abstractions/log.service";
|
||||||
import { MessagingService } from "@bitwarden/common/abstractions/messaging.service";
|
import { MessagingService } from "@bitwarden/common/abstractions/messaging.service";
|
||||||
import { OrganizationService } from "@bitwarden/common/abstractions/organization.service";
|
import { OrganizationService } from "@bitwarden/common/abstractions/organization/organization.service.abstraction";
|
||||||
import { PasswordGenerationService } from "@bitwarden/common/abstractions/passwordGeneration.service";
|
import { PasswordGenerationService } from "@bitwarden/common/abstractions/passwordGeneration.service";
|
||||||
import { PasswordRepromptService } from "@bitwarden/common/abstractions/passwordReprompt.service";
|
import { PasswordRepromptService } from "@bitwarden/common/abstractions/passwordReprompt.service";
|
||||||
import { PlatformUtilsService } from "@bitwarden/common/abstractions/platformUtils.service";
|
import { PlatformUtilsService } from "@bitwarden/common/abstractions/platformUtils.service";
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import { CipherService } from "@bitwarden/common/abstractions/cipher.service";
|
|||||||
import { EventService } from "@bitwarden/common/abstractions/event.service";
|
import { EventService } from "@bitwarden/common/abstractions/event.service";
|
||||||
import { I18nService } from "@bitwarden/common/abstractions/i18n.service";
|
import { I18nService } from "@bitwarden/common/abstractions/i18n.service";
|
||||||
import { LogService } from "@bitwarden/common/abstractions/log.service";
|
import { LogService } from "@bitwarden/common/abstractions/log.service";
|
||||||
import { OrganizationService } from "@bitwarden/common/abstractions/organization.service";
|
import { OrganizationService } from "@bitwarden/common/abstractions/organization/organization.service.abstraction";
|
||||||
import { PasswordRepromptService } from "@bitwarden/common/abstractions/passwordReprompt.service";
|
import { PasswordRepromptService } from "@bitwarden/common/abstractions/passwordReprompt.service";
|
||||||
import { PlatformUtilsService } from "@bitwarden/common/abstractions/platformUtils.service";
|
import { PlatformUtilsService } from "@bitwarden/common/abstractions/platformUtils.service";
|
||||||
import { SearchService } from "@bitwarden/common/abstractions/search.service";
|
import { SearchService } from "@bitwarden/common/abstractions/search.service";
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ import { BroadcasterService } from "@bitwarden/common/abstractions/broadcaster.s
|
|||||||
import { CipherService } from "@bitwarden/common/abstractions/cipher.service";
|
import { CipherService } from "@bitwarden/common/abstractions/cipher.service";
|
||||||
import { I18nService } from "@bitwarden/common/abstractions/i18n.service";
|
import { I18nService } from "@bitwarden/common/abstractions/i18n.service";
|
||||||
import { MessagingService } from "@bitwarden/common/abstractions/messaging.service";
|
import { MessagingService } from "@bitwarden/common/abstractions/messaging.service";
|
||||||
import { OrganizationService } from "@bitwarden/common/abstractions/organization.service";
|
import { OrganizationService } from "@bitwarden/common/abstractions/organization/organization.service.abstraction";
|
||||||
import { PasswordRepromptService } from "@bitwarden/common/abstractions/passwordReprompt.service";
|
import { PasswordRepromptService } from "@bitwarden/common/abstractions/passwordReprompt.service";
|
||||||
import { PlatformUtilsService } from "@bitwarden/common/abstractions/platformUtils.service";
|
import { PlatformUtilsService } from "@bitwarden/common/abstractions/platformUtils.service";
|
||||||
import { SyncService } from "@bitwarden/common/abstractions/sync/sync.service.abstraction";
|
import { SyncService } from "@bitwarden/common/abstractions/sync/sync.service.abstraction";
|
||||||
|
|||||||
@@ -17,9 +17,9 @@
|
|||||||
<small class="form-text text-muted">{{ "breachCheckUsernameEmail" | i18n }}</small>
|
<small class="form-text text-muted">{{ "breachCheckUsernameEmail" | i18n }}</small>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<bit-submit-button [loading]="form.loading">
|
<button type="submit" buttonType="primary" bitButton [loading]="form.loading">
|
||||||
{{ "checkBreaches" | i18n }}
|
{{ "checkBreaches" | i18n }}
|
||||||
</bit-submit-button>
|
</button>
|
||||||
</form>
|
</form>
|
||||||
<div class="mt-4" *ngIf="!form.loading && checkedUsername">
|
<div class="mt-4" *ngIf="!form.loading && checkedUsername">
|
||||||
<p *ngIf="error">{{ "reportError" | i18n }}...</p>
|
<p *ngIf="error">{{ "reportError" | i18n }}...</p>
|
||||||
|
|||||||
@@ -2,9 +2,9 @@
|
|||||||
<h1>{{ "exposedPasswordsReport" | i18n }}</h1>
|
<h1>{{ "exposedPasswordsReport" | i18n }}</h1>
|
||||||
</div>
|
</div>
|
||||||
<p>{{ "exposedPasswordsReportDesc" | i18n }}</p>
|
<p>{{ "exposedPasswordsReportDesc" | i18n }}</p>
|
||||||
<bit-submit-button [loading]="loading" (click)="load()">
|
<button type="submit" buttonType="primary" bitButton [loading]="loading" (click)="load()">
|
||||||
{{ "checkExposedPasswords" | i18n }}
|
{{ "checkExposedPasswords" | i18n }}
|
||||||
</bit-submit-button>
|
</button>
|
||||||
<div class="mt-4" *ngIf="hasLoaded">
|
<div class="mt-4" *ngIf="hasLoaded">
|
||||||
<app-callout type="success" title="{{ 'goodNews' | i18n }}" *ngIf="!ciphers.length">
|
<app-callout type="success" title="{{ 'goodNews' | i18n }}" *ngIf="!ciphers.length">
|
||||||
{{ "noExposedPasswords" | i18n }}
|
{{ "noExposedPasswords" | i18n }}
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import {
|
|||||||
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
||||||
import { PayPalConfig } from "@bitwarden/common/abstractions/environment.service";
|
import { PayPalConfig } from "@bitwarden/common/abstractions/environment.service";
|
||||||
import { LogService } from "@bitwarden/common/abstractions/log.service";
|
import { LogService } from "@bitwarden/common/abstractions/log.service";
|
||||||
import { OrganizationService } from "@bitwarden/common/abstractions/organization.service";
|
import { OrganizationService } from "@bitwarden/common/abstractions/organization/organization.service.abstraction";
|
||||||
import { PlatformUtilsService } from "@bitwarden/common/abstractions/platformUtils.service";
|
import { PlatformUtilsService } from "@bitwarden/common/abstractions/platformUtils.service";
|
||||||
import { StateService } from "@bitwarden/common/abstractions/state.service";
|
import { StateService } from "@bitwarden/common/abstractions/state.service";
|
||||||
import { PaymentMethodType } from "@bitwarden/common/enums/paymentMethodType";
|
import { PaymentMethodType } from "@bitwarden/common/enums/paymentMethodType";
|
||||||
|
|||||||
@@ -71,7 +71,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<bit-submit-button [loading]="form.loading">
|
<button type="submit" buttonType="primary" bitButton [loading]="form.loading">
|
||||||
{{ "changeKdf" | i18n }}
|
{{ "changeKdf" | i18n }}
|
||||||
</bit-submit-button>
|
</button>
|
||||||
</form>
|
</form>
|
||||||
|
|||||||
@@ -100,7 +100,7 @@
|
|||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<bit-submit-button [loading]="form.loading">
|
<button type="submit" buttonType="primary" bitButton [loading]="form.loading">
|
||||||
{{ "changeMasterPassword" | i18n }}
|
{{ "changeMasterPassword" | i18n }}
|
||||||
</bit-submit-button>
|
</button>
|
||||||
</form>
|
</form>
|
||||||
|
|||||||
@@ -10,8 +10,8 @@ import { FolderService } from "@bitwarden/common/abstractions/folder/folder.serv
|
|||||||
import { I18nService } from "@bitwarden/common/abstractions/i18n.service";
|
import { I18nService } from "@bitwarden/common/abstractions/i18n.service";
|
||||||
import { KeyConnectorService } from "@bitwarden/common/abstractions/keyConnector.service";
|
import { KeyConnectorService } from "@bitwarden/common/abstractions/keyConnector.service";
|
||||||
import { MessagingService } from "@bitwarden/common/abstractions/messaging.service";
|
import { MessagingService } from "@bitwarden/common/abstractions/messaging.service";
|
||||||
import { OrganizationService } from "@bitwarden/common/abstractions/organization.service";
|
|
||||||
import { OrganizationApiServiceAbstraction } from "@bitwarden/common/abstractions/organization/organization-api.service.abstraction";
|
import { OrganizationApiServiceAbstraction } from "@bitwarden/common/abstractions/organization/organization-api.service.abstraction";
|
||||||
|
import { OrganizationService } from "@bitwarden/common/abstractions/organization/organization.service.abstraction";
|
||||||
import { PasswordGenerationService } from "@bitwarden/common/abstractions/passwordGeneration.service";
|
import { PasswordGenerationService } from "@bitwarden/common/abstractions/passwordGeneration.service";
|
||||||
import { PlatformUtilsService } from "@bitwarden/common/abstractions/platformUtils.service";
|
import { PlatformUtilsService } from "@bitwarden/common/abstractions/platformUtils.service";
|
||||||
import { PolicyService } from "@bitwarden/common/abstractions/policy/policy.service.abstraction";
|
import { PolicyService } from "@bitwarden/common/abstractions/policy/policy.service.abstraction";
|
||||||
|
|||||||
@@ -100,9 +100,15 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-footer">
|
<div class="modal-footer">
|
||||||
<bit-submit-button [loading]="loading || form.loading" [disabled]="readOnly">
|
<button
|
||||||
|
type="submit"
|
||||||
|
buttonType="primary"
|
||||||
|
bitButton
|
||||||
|
[loading]="loading || form.loading"
|
||||||
|
[disabled]="readOnly"
|
||||||
|
>
|
||||||
{{ "save" | i18n }}
|
{{ "save" | i18n }}
|
||||||
</bit-submit-button>
|
</button>
|
||||||
<button bitButton buttonType="secondary" type="button" data-dismiss="modal">
|
<button bitButton buttonType="secondary" type="button" data-dismiss="modal">
|
||||||
{{ "cancel" | i18n }}
|
{{ "cancel" | i18n }}
|
||||||
</button>
|
</button>
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import { CryptoService } from "@bitwarden/common/abstractions/crypto.service";
|
|||||||
import { I18nService } from "@bitwarden/common/abstractions/i18n.service";
|
import { I18nService } from "@bitwarden/common/abstractions/i18n.service";
|
||||||
import { LogService } from "@bitwarden/common/abstractions/log.service";
|
import { LogService } from "@bitwarden/common/abstractions/log.service";
|
||||||
import { MessagingService } from "@bitwarden/common/abstractions/messaging.service";
|
import { MessagingService } from "@bitwarden/common/abstractions/messaging.service";
|
||||||
import { OrganizationService } from "@bitwarden/common/abstractions/organization.service";
|
import { OrganizationService } from "@bitwarden/common/abstractions/organization/organization.service.abstraction";
|
||||||
import { PlatformUtilsService } from "@bitwarden/common/abstractions/platformUtils.service";
|
import { PlatformUtilsService } from "@bitwarden/common/abstractions/platformUtils.service";
|
||||||
import { StateService } from "@bitwarden/common/abstractions/state.service";
|
import { StateService } from "@bitwarden/common/abstractions/state.service";
|
||||||
import { EmergencyAccessStatusType } from "@bitwarden/common/enums/emergencyAccessStatusType";
|
import { EmergencyAccessStatusType } from "@bitwarden/common/enums/emergencyAccessStatusType";
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import { FolderService } from "@bitwarden/common/abstractions/folder/folder.serv
|
|||||||
import { I18nService } from "@bitwarden/common/abstractions/i18n.service";
|
import { I18nService } from "@bitwarden/common/abstractions/i18n.service";
|
||||||
import { LogService } from "@bitwarden/common/abstractions/log.service";
|
import { LogService } from "@bitwarden/common/abstractions/log.service";
|
||||||
import { MessagingService } from "@bitwarden/common/abstractions/messaging.service";
|
import { MessagingService } from "@bitwarden/common/abstractions/messaging.service";
|
||||||
import { OrganizationService } from "@bitwarden/common/abstractions/organization.service";
|
import { OrganizationService } from "@bitwarden/common/abstractions/organization/organization.service.abstraction";
|
||||||
import { PasswordGenerationService } from "@bitwarden/common/abstractions/passwordGeneration.service";
|
import { PasswordGenerationService } from "@bitwarden/common/abstractions/passwordGeneration.service";
|
||||||
import { PasswordRepromptService } from "@bitwarden/common/abstractions/passwordReprompt.service";
|
import { PasswordRepromptService } from "@bitwarden/common/abstractions/passwordReprompt.service";
|
||||||
import { PlatformUtilsService } from "@bitwarden/common/abstractions/platformUtils.service";
|
import { PlatformUtilsService } from "@bitwarden/common/abstractions/platformUtils.service";
|
||||||
|
|||||||
@@ -318,9 +318,15 @@
|
|||||||
<app-callout [type]="'error'">{{ "singleOrgBlockCreateMessage" | i18n }}</app-callout>
|
<app-callout [type]="'error'">{{ "singleOrgBlockCreateMessage" | i18n }}</app-callout>
|
||||||
</div>
|
</div>
|
||||||
<div class="mt-4">
|
<div class="mt-4">
|
||||||
<bit-submit-button [loading]="form.loading" [disabled]="!formGroup.valid">{{
|
<button
|
||||||
"submit" | i18n
|
type="submit"
|
||||||
}}</bit-submit-button>
|
buttonType="primary"
|
||||||
|
bitButton
|
||||||
|
[loading]="form.loading"
|
||||||
|
[disabled]="!formGroup.valid"
|
||||||
|
>
|
||||||
|
{{ "submit" | i18n }}
|
||||||
|
</button>
|
||||||
<button type="button" class="btn btn-outline-secondary" (click)="cancel()" *ngIf="showCancel">
|
<button type="button" class="btn btn-outline-secondary" (click)="cancel()" *ngIf="showCancel">
|
||||||
{{ "cancel" | i18n }}
|
{{ "cancel" | i18n }}
|
||||||
</button>
|
</button>
|
||||||
|
|||||||
@@ -7,8 +7,8 @@ import { CryptoService } from "@bitwarden/common/abstractions/crypto.service";
|
|||||||
import { I18nService } from "@bitwarden/common/abstractions/i18n.service";
|
import { I18nService } from "@bitwarden/common/abstractions/i18n.service";
|
||||||
import { LogService } from "@bitwarden/common/abstractions/log.service";
|
import { LogService } from "@bitwarden/common/abstractions/log.service";
|
||||||
import { MessagingService } from "@bitwarden/common/abstractions/messaging.service";
|
import { MessagingService } from "@bitwarden/common/abstractions/messaging.service";
|
||||||
import { OrganizationService } from "@bitwarden/common/abstractions/organization.service";
|
|
||||||
import { OrganizationApiServiceAbstraction } from "@bitwarden/common/abstractions/organization/organization-api.service.abstraction";
|
import { OrganizationApiServiceAbstraction } from "@bitwarden/common/abstractions/organization/organization-api.service.abstraction";
|
||||||
|
import { OrganizationService } from "@bitwarden/common/abstractions/organization/organization.service.abstraction";
|
||||||
import { PlatformUtilsService } from "@bitwarden/common/abstractions/platformUtils.service";
|
import { PlatformUtilsService } from "@bitwarden/common/abstractions/platformUtils.service";
|
||||||
import { PolicyService } from "@bitwarden/common/abstractions/policy/policy.service.abstraction";
|
import { PolicyService } from "@bitwarden/common/abstractions/policy/policy.service.abstraction";
|
||||||
import { SyncService } from "@bitwarden/common/abstractions/sync/sync.service.abstraction";
|
import { SyncService } from "@bitwarden/common/abstractions/sync/sync.service.abstraction";
|
||||||
|
|||||||
@@ -68,9 +68,9 @@
|
|||||||
"licenseFileDesc" | i18n: "bitwarden_premium_license.json"
|
"licenseFileDesc" | i18n: "bitwarden_premium_license.json"
|
||||||
}}</small>
|
}}</small>
|
||||||
</div>
|
</div>
|
||||||
<bit-submit-button [loading]="form.loading">
|
<button type="submit" buttonType="primary" bitButton [loading]="form.loading">
|
||||||
{{ "submit" | i18n }}
|
{{ "submit" | i18n }}
|
||||||
</bit-submit-button>
|
</button>
|
||||||
</form>
|
</form>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
<form #form (ngSubmit)="submit()" [appApiAction]="formPromise" ngNativeValidate *ngIf="!selfHosted">
|
<form #form (ngSubmit)="submit()" [appApiAction]="formPromise" ngNativeValidate *ngIf="!selfHosted">
|
||||||
@@ -118,7 +118,7 @@
|
|||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<small class="text-muted font-italic">{{ "paymentChargedAnnually" | i18n }}</small>
|
<small class="text-muted font-italic">{{ "paymentChargedAnnually" | i18n }}</small>
|
||||||
<bit-submit-button [loading]="form.loading">
|
<button type="submit" bitButton [loading]="form.loading">
|
||||||
{{ "submit" | i18n }}
|
{{ "submit" | i18n }}
|
||||||
</bit-submit-button>
|
</button>
|
||||||
</form>
|
</form>
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import { Component, NgZone, OnDestroy, OnInit } from "@angular/core";
|
|||||||
|
|
||||||
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
||||||
import { BroadcasterService } from "@bitwarden/common/abstractions/broadcaster.service";
|
import { BroadcasterService } from "@bitwarden/common/abstractions/broadcaster.service";
|
||||||
import { OrganizationService } from "@bitwarden/common/abstractions/organization.service";
|
import { OrganizationService } from "@bitwarden/common/abstractions/organization/organization.service.abstraction";
|
||||||
import { PlatformUtilsService } from "@bitwarden/common/abstractions/platformUtils.service";
|
import { PlatformUtilsService } from "@bitwarden/common/abstractions/platformUtils.service";
|
||||||
import { TokenService } from "@bitwarden/common/abstractions/token.service";
|
import { TokenService } from "@bitwarden/common/abstractions/token.service";
|
||||||
|
|
||||||
|
|||||||
@@ -22,7 +22,7 @@
|
|||||||
[appApiAction]="formPromise"
|
[appApiAction]="formPromise"
|
||||||
[formGroup]="sponsorshipForm"
|
[formGroup]="sponsorshipForm"
|
||||||
ngNativeValidate
|
ngNativeValidate
|
||||||
*ngIf="anyOrgsAvailable"
|
*ngIf="anyOrgsAvailable$ | async"
|
||||||
>
|
>
|
||||||
<div class="form-group col-7">
|
<div class="form-group col-7">
|
||||||
<label for="availableSponsorshipOrg">{{ "familiesSponsoringOrgSelect" | i18n }}</label>
|
<label for="availableSponsorshipOrg">{{ "familiesSponsoringOrgSelect" | i18n }}</label>
|
||||||
@@ -34,7 +34,9 @@
|
|||||||
required
|
required
|
||||||
>
|
>
|
||||||
<option disabled="true" value="">-- {{ "select" | i18n }} --</option>
|
<option disabled="true" value="">-- {{ "select" | i18n }} --</option>
|
||||||
<option *ngFor="let o of availableSponsorshipOrgs" [ngValue]="o.id">{{ o.name }}</option>
|
<option *ngFor="let o of availableSponsorshipOrgs$ | async" [ngValue]="o.id">
|
||||||
|
{{ o.name }}
|
||||||
|
</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group col-7">
|
<div class="form-group col-7">
|
||||||
@@ -74,7 +76,7 @@
|
|||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
<ng-container *ngIf="anyActiveSponsorships">
|
<ng-container *ngIf="anyActiveSponsorships$ | async">
|
||||||
<div class="border-bottom">
|
<div class="border-bottom">
|
||||||
<table class="table table-hover table-list">
|
<table class="table table-hover table-list">
|
||||||
<thead>
|
<thead>
|
||||||
@@ -86,12 +88,12 @@
|
|||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
<ng-container *ngFor="let o of activeSponsorshipOrgs">
|
<ng-container *ngFor="let o of activeSponsorshipOrgs$ | async">
|
||||||
<tr
|
<tr
|
||||||
sponsoring-org-row
|
sponsoring-org-row
|
||||||
[sponsoringOrg]="o"
|
[sponsoringOrg]="o"
|
||||||
[isSelfHosted]="isSelfHosted"
|
[isSelfHosted]="isSelfHosted"
|
||||||
(sponsorshipRemoved)="load(true)"
|
(sponsorshipRemoved)="forceReload()"
|
||||||
></tr>
|
></tr>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
</tbody>
|
</tbody>
|
||||||
|
|||||||
@@ -1,30 +1,40 @@
|
|||||||
import { Component, OnInit } from "@angular/core";
|
import { Component, OnDestroy, OnInit } from "@angular/core";
|
||||||
import { UntypedFormBuilder, UntypedFormGroup, Validators } from "@angular/forms";
|
import { FormBuilder, FormControl, FormGroup, Validators } from "@angular/forms";
|
||||||
|
import { map, Observable, Subject, takeUntil } from "rxjs";
|
||||||
|
|
||||||
import { notAllowedValueAsync } from "@bitwarden/angular/validators/notAllowedValueAsync.validator";
|
import { notAllowedValueAsync } from "@bitwarden/angular/validators/notAllowedValueAsync.validator";
|
||||||
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
||||||
import { I18nService } from "@bitwarden/common/abstractions/i18n.service";
|
import { I18nService } from "@bitwarden/common/abstractions/i18n.service";
|
||||||
import { OrganizationService } from "@bitwarden/common/abstractions/organization.service";
|
import { OrganizationService } from "@bitwarden/common/abstractions/organization/organization.service.abstraction";
|
||||||
import { PlatformUtilsService } from "@bitwarden/common/abstractions/platformUtils.service";
|
import { PlatformUtilsService } from "@bitwarden/common/abstractions/platformUtils.service";
|
||||||
import { StateService } from "@bitwarden/common/abstractions/state.service";
|
import { StateService } from "@bitwarden/common/abstractions/state.service";
|
||||||
import { SyncService } from "@bitwarden/common/abstractions/sync/sync.service.abstraction";
|
import { SyncService } from "@bitwarden/common/abstractions/sync/sync.service.abstraction";
|
||||||
import { PlanSponsorshipType } from "@bitwarden/common/enums/planSponsorshipType";
|
import { PlanSponsorshipType } from "@bitwarden/common/enums/planSponsorshipType";
|
||||||
import { Organization } from "@bitwarden/common/models/domain/organization";
|
import { Organization } from "@bitwarden/common/models/domain/organization";
|
||||||
|
|
||||||
|
interface RequestSponsorshipForm {
|
||||||
|
selectedSponsorshipOrgId: FormControl<string>;
|
||||||
|
sponsorshipEmail: FormControl<string>;
|
||||||
|
}
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: "app-sponsored-families",
|
selector: "app-sponsored-families",
|
||||||
templateUrl: "sponsored-families.component.html",
|
templateUrl: "sponsored-families.component.html",
|
||||||
})
|
})
|
||||||
export class SponsoredFamiliesComponent implements OnInit {
|
export class SponsoredFamiliesComponent implements OnInit, OnDestroy {
|
||||||
loading = false;
|
loading = false;
|
||||||
|
|
||||||
availableSponsorshipOrgs: Organization[] = [];
|
availableSponsorshipOrgs$: Observable<Organization[]>;
|
||||||
activeSponsorshipOrgs: Organization[] = [];
|
activeSponsorshipOrgs$: Observable<Organization[]>;
|
||||||
|
anyOrgsAvailable$: Observable<boolean>;
|
||||||
|
anyActiveSponsorships$: Observable<boolean>;
|
||||||
|
|
||||||
// Conditional display properties
|
// Conditional display properties
|
||||||
formPromise: Promise<any>;
|
formPromise: Promise<void>;
|
||||||
|
|
||||||
sponsorshipForm: UntypedFormGroup;
|
sponsorshipForm: FormGroup<RequestSponsorshipForm>;
|
||||||
|
|
||||||
|
private _destroy = new Subject<void>();
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private apiService: ApiService,
|
private apiService: ApiService,
|
||||||
@@ -32,31 +42,50 @@ export class SponsoredFamiliesComponent implements OnInit {
|
|||||||
private platformUtilsService: PlatformUtilsService,
|
private platformUtilsService: PlatformUtilsService,
|
||||||
private syncService: SyncService,
|
private syncService: SyncService,
|
||||||
private organizationService: OrganizationService,
|
private organizationService: OrganizationService,
|
||||||
private formBuilder: UntypedFormBuilder,
|
private formBuilder: FormBuilder,
|
||||||
private stateService: StateService
|
private stateService: StateService
|
||||||
) {
|
) {
|
||||||
this.sponsorshipForm = this.formBuilder.group({
|
this.sponsorshipForm = this.formBuilder.group<RequestSponsorshipForm>({
|
||||||
selectedSponsorshipOrgId: [
|
selectedSponsorshipOrgId: new FormControl("", {
|
||||||
"",
|
validators: [Validators.required],
|
||||||
{
|
}),
|
||||||
validators: [Validators.required],
|
sponsorshipEmail: new FormControl("", {
|
||||||
},
|
validators: [Validators.email],
|
||||||
],
|
asyncValidators: [
|
||||||
sponsorshipEmail: [
|
notAllowedValueAsync(async () => await this.stateService.getEmail(), true),
|
||||||
"",
|
],
|
||||||
{
|
updateOn: "blur",
|
||||||
validators: [Validators.email],
|
}),
|
||||||
asyncValidators: [
|
|
||||||
notAllowedValueAsync(async () => await this.stateService.getEmail(), true),
|
|
||||||
],
|
|
||||||
updateOn: "blur",
|
|
||||||
},
|
|
||||||
],
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async ngOnInit() {
|
async ngOnInit() {
|
||||||
await this.load();
|
this.availableSponsorshipOrgs$ = this.organizationService.organizations$.pipe(
|
||||||
|
map((orgs) => orgs.filter((o) => o.familySponsorshipAvailable))
|
||||||
|
);
|
||||||
|
|
||||||
|
this.availableSponsorshipOrgs$.pipe(takeUntil(this._destroy)).subscribe((orgs) => {
|
||||||
|
if (orgs.length === 1) {
|
||||||
|
this.sponsorshipForm.patchValue({
|
||||||
|
selectedSponsorshipOrgId: orgs[0].id,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
this.anyOrgsAvailable$ = this.availableSponsorshipOrgs$.pipe(map((orgs) => orgs.length > 0));
|
||||||
|
|
||||||
|
this.activeSponsorshipOrgs$ = this.organizationService.organizations$.pipe(
|
||||||
|
map((orgs) => orgs.filter((o) => o.familySponsorshipFriendlyName !== null))
|
||||||
|
);
|
||||||
|
|
||||||
|
this.anyActiveSponsorships$ = this.activeSponsorshipOrgs$.pipe(map((orgs) => orgs.length > 0));
|
||||||
|
|
||||||
|
this.loading = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnDestroy(): void {
|
||||||
|
this._destroy.next();
|
||||||
|
this._destroy.complete();
|
||||||
}
|
}
|
||||||
|
|
||||||
async submit() {
|
async submit() {
|
||||||
@@ -73,50 +102,23 @@ export class SponsoredFamiliesComponent implements OnInit {
|
|||||||
this.platformUtilsService.showToast("success", null, this.i18nService.t("sponsorshipCreated"));
|
this.platformUtilsService.showToast("success", null, this.i18nService.t("sponsorshipCreated"));
|
||||||
this.formPromise = null;
|
this.formPromise = null;
|
||||||
this.resetForm();
|
this.resetForm();
|
||||||
await this.load(true);
|
await this.forceReload();
|
||||||
}
|
}
|
||||||
|
|
||||||
async load(forceReload = false) {
|
async forceReload() {
|
||||||
if (this.loading) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.loading = true;
|
this.loading = true;
|
||||||
if (forceReload) {
|
await this.syncService.fullSync(true);
|
||||||
await this.syncService.fullSync(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
const allOrgs = await this.organizationService.getAll();
|
|
||||||
this.availableSponsorshipOrgs = allOrgs.filter((org) => org.familySponsorshipAvailable);
|
|
||||||
|
|
||||||
this.activeSponsorshipOrgs = allOrgs.filter(
|
|
||||||
(org) => org.familySponsorshipFriendlyName !== null
|
|
||||||
);
|
|
||||||
|
|
||||||
if (this.availableSponsorshipOrgs.length === 1) {
|
|
||||||
this.sponsorshipForm.patchValue({
|
|
||||||
selectedSponsorshipOrgId: this.availableSponsorshipOrgs[0].id,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
this.loading = false;
|
this.loading = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
get sponsorshipEmailControl() {
|
get sponsorshipEmailControl() {
|
||||||
return this.sponsorshipForm.controls["sponsorshipEmail"];
|
return this.sponsorshipForm.controls.sponsorshipEmail;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async resetForm() {
|
private async resetForm() {
|
||||||
this.sponsorshipForm.reset();
|
this.sponsorshipForm.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
get anyActiveSponsorships(): boolean {
|
|
||||||
return this.activeSponsorshipOrgs.length > 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
get anyOrgsAvailable(): boolean {
|
|
||||||
return this.availableSponsorshipOrgs.length > 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
get isSelfHosted(): boolean {
|
get isSelfHosted(): boolean {
|
||||||
return this.platformUtilsService.isSelfHost();
|
return this.platformUtilsService.isSelfHost();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -92,9 +92,15 @@
|
|||||||
</div>
|
</div>
|
||||||
<small class="form-text text-muted">{{ "deviceVerificationDesc" | i18n }}</small>
|
<small class="form-text text-muted">{{ "deviceVerificationDesc" | i18n }}</small>
|
||||||
</div>
|
</div>
|
||||||
<bit-submit-button [loading]="form.loading" *ngIf="isDeviceVerificationSectionEnabled">
|
<button
|
||||||
|
type="submit"
|
||||||
|
buttonType="primary"
|
||||||
|
bitButton
|
||||||
|
[loading]="form.loading"
|
||||||
|
*ngIf="isDeviceVerificationSectionEnabled"
|
||||||
|
>
|
||||||
{{ "save" | i18n }}
|
{{ "save" | i18n }}
|
||||||
</bit-submit-button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
|||||||
@@ -12,7 +12,6 @@ import {
|
|||||||
ButtonModule,
|
ButtonModule,
|
||||||
CalloutModule,
|
CalloutModule,
|
||||||
FormFieldModule,
|
FormFieldModule,
|
||||||
SubmitButtonModule,
|
|
||||||
MenuModule,
|
MenuModule,
|
||||||
TabsModule,
|
TabsModule,
|
||||||
IconModule,
|
IconModule,
|
||||||
@@ -45,7 +44,6 @@ import "./locales";
|
|||||||
ButtonModule,
|
ButtonModule,
|
||||||
MenuModule,
|
MenuModule,
|
||||||
FormFieldModule,
|
FormFieldModule,
|
||||||
SubmitButtonModule,
|
|
||||||
IconModule,
|
IconModule,
|
||||||
TabsModule,
|
TabsModule,
|
||||||
],
|
],
|
||||||
@@ -65,7 +63,6 @@ import "./locales";
|
|||||||
ButtonModule,
|
ButtonModule,
|
||||||
MenuModule,
|
MenuModule,
|
||||||
FormFieldModule,
|
FormFieldModule,
|
||||||
SubmitButtonModule,
|
|
||||||
IconModule,
|
IconModule,
|
||||||
TabsModule,
|
TabsModule,
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import { FolderService } from "@bitwarden/common/abstractions/folder/folder.serv
|
|||||||
import { I18nService } from "@bitwarden/common/abstractions/i18n.service";
|
import { I18nService } from "@bitwarden/common/abstractions/i18n.service";
|
||||||
import { LogService } from "@bitwarden/common/abstractions/log.service";
|
import { LogService } from "@bitwarden/common/abstractions/log.service";
|
||||||
import { MessagingService } from "@bitwarden/common/abstractions/messaging.service";
|
import { MessagingService } from "@bitwarden/common/abstractions/messaging.service";
|
||||||
import { OrganizationService } from "@bitwarden/common/abstractions/organization.service";
|
import { OrganizationService } from "@bitwarden/common/abstractions/organization/organization.service.abstraction";
|
||||||
import { PasswordGenerationService } from "@bitwarden/common/abstractions/passwordGeneration.service";
|
import { PasswordGenerationService } from "@bitwarden/common/abstractions/passwordGeneration.service";
|
||||||
import { PasswordRepromptService } from "@bitwarden/common/abstractions/passwordReprompt.service";
|
import { PasswordRepromptService } from "@bitwarden/common/abstractions/passwordReprompt.service";
|
||||||
import { PlatformUtilsService } from "@bitwarden/common/abstractions/platformUtils.service";
|
import { PlatformUtilsService } from "@bitwarden/common/abstractions/platformUtils.service";
|
||||||
|
|||||||
@@ -4,11 +4,12 @@ import { CipherService } from "@bitwarden/common/abstractions/cipher.service";
|
|||||||
import { CollectionService } from "@bitwarden/common/abstractions/collection.service";
|
import { CollectionService } from "@bitwarden/common/abstractions/collection.service";
|
||||||
import { I18nService } from "@bitwarden/common/abstractions/i18n.service";
|
import { I18nService } from "@bitwarden/common/abstractions/i18n.service";
|
||||||
import { LogService } from "@bitwarden/common/abstractions/log.service";
|
import { LogService } from "@bitwarden/common/abstractions/log.service";
|
||||||
import { OrganizationService } from "@bitwarden/common/abstractions/organization.service";
|
import { OrganizationService } from "@bitwarden/common/abstractions/organization/organization.service.abstraction";
|
||||||
import { PlatformUtilsService } from "@bitwarden/common/abstractions/platformUtils.service";
|
import { PlatformUtilsService } from "@bitwarden/common/abstractions/platformUtils.service";
|
||||||
import { Organization } from "@bitwarden/common/models/domain/organization";
|
import { Organization } from "@bitwarden/common/models/domain/organization";
|
||||||
import { CipherView } from "@bitwarden/common/models/view/cipherView";
|
import { CipherView } from "@bitwarden/common/models/view/cipherView";
|
||||||
import { CollectionView } from "@bitwarden/common/models/view/collectionView";
|
import { CollectionView } from "@bitwarden/common/models/view/collectionView";
|
||||||
|
import { Checkable, isChecked } from "@bitwarden/common/types/checkable";
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: "app-vault-bulk-share",
|
selector: "app-vault-bulk-share",
|
||||||
@@ -20,10 +21,10 @@ export class BulkShareComponent implements OnInit {
|
|||||||
@Output() onShared = new EventEmitter();
|
@Output() onShared = new EventEmitter();
|
||||||
|
|
||||||
nonShareableCount = 0;
|
nonShareableCount = 0;
|
||||||
collections: CollectionView[] = [];
|
collections: Checkable<CollectionView>[] = [];
|
||||||
organizations: Organization[] = [];
|
organizations: Organization[] = [];
|
||||||
shareableCiphers: CipherView[] = [];
|
shareableCiphers: CipherView[] = [];
|
||||||
formPromise: Promise<any>;
|
formPromise: Promise<void>;
|
||||||
|
|
||||||
private writeableCollections: CollectionView[] = [];
|
private writeableCollections: CollectionView[] = [];
|
||||||
|
|
||||||
@@ -66,9 +67,7 @@ export class BulkShareComponent implements OnInit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async submit() {
|
async submit() {
|
||||||
const checkedCollectionIds = this.collections
|
const checkedCollectionIds = this.collections.filter(isChecked).map((c) => c.id);
|
||||||
.filter((c) => (c as any).checked)
|
|
||||||
.map((c) => c.id);
|
|
||||||
try {
|
try {
|
||||||
this.formPromise = this.cipherService.shareManyWithServer(
|
this.formPromise = this.cipherService.shareManyWithServer(
|
||||||
this.shareableCiphers,
|
this.shareableCiphers,
|
||||||
@@ -90,8 +89,8 @@ export class BulkShareComponent implements OnInit {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
check(c: CollectionView, select?: boolean) {
|
check(c: Checkable<CollectionView>, select?: boolean) {
|
||||||
(c as any).checked = select == null ? !(c as any).checked : select;
|
c.checked = select == null ? !c.checked : select;
|
||||||
}
|
}
|
||||||
|
|
||||||
selectAll(select: boolean) {
|
selectAll(select: boolean) {
|
||||||
@@ -106,7 +105,7 @@ export class BulkShareComponent implements OnInit {
|
|||||||
this.collections != null
|
this.collections != null
|
||||||
) {
|
) {
|
||||||
for (let i = 0; i < this.collections.length; i++) {
|
for (let i = 0; i < this.collections.length; i++) {
|
||||||
if ((this.collections[i] as any).checked) {
|
if (this.collections[i].checked) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import { CipherService } from "@bitwarden/common/abstractions/cipher.service";
|
|||||||
import { EventService } from "@bitwarden/common/abstractions/event.service";
|
import { EventService } from "@bitwarden/common/abstractions/event.service";
|
||||||
import { I18nService } from "@bitwarden/common/abstractions/i18n.service";
|
import { I18nService } from "@bitwarden/common/abstractions/i18n.service";
|
||||||
import { LogService } from "@bitwarden/common/abstractions/log.service";
|
import { LogService } from "@bitwarden/common/abstractions/log.service";
|
||||||
import { OrganizationService } from "@bitwarden/common/abstractions/organization.service";
|
import { OrganizationService } from "@bitwarden/common/abstractions/organization/organization.service.abstraction";
|
||||||
import { PasswordRepromptService } from "@bitwarden/common/abstractions/passwordReprompt.service";
|
import { PasswordRepromptService } from "@bitwarden/common/abstractions/passwordReprompt.service";
|
||||||
import { PlatformUtilsService } from "@bitwarden/common/abstractions/platformUtils.service";
|
import { PlatformUtilsService } from "@bitwarden/common/abstractions/platformUtils.service";
|
||||||
import { SearchService } from "@bitwarden/common/abstractions/search.service";
|
import { SearchService } from "@bitwarden/common/abstractions/search.service";
|
||||||
|
|||||||
@@ -15,78 +15,87 @@
|
|||||||
<span aria-hidden="true">×</span>
|
<span aria-hidden="true">×</span>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-body" *ngIf="!organizations || !organizations.length">
|
<ng-container *ngIf="organizations$ | async as organizations">
|
||||||
{{ "noOrganizationsList" | i18n }}
|
<div class="modal-body" *ngIf="!organizations || !organizations.length">
|
||||||
</div>
|
{{ "noOrganizationsList" | i18n }}
|
||||||
<div class="modal-body" *ngIf="organizations && organizations.length">
|
|
||||||
<p>{{ "moveToOrgDesc" | i18n }}</p>
|
|
||||||
<div class="form-group">
|
|
||||||
<label for="organization">{{ "organization" | i18n }}</label>
|
|
||||||
<select
|
|
||||||
id="organization"
|
|
||||||
name="OrganizationId"
|
|
||||||
[(ngModel)]="organizationId"
|
|
||||||
class="form-control"
|
|
||||||
(change)="filterCollections()"
|
|
||||||
>
|
|
||||||
<option *ngFor="let o of organizations" [ngValue]="o.id">{{ o.name }}</option>
|
|
||||||
</select>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="d-flex">
|
<div class="modal-body" *ngIf="organizations && organizations.length">
|
||||||
<h3>{{ "collections" | i18n }}</h3>
|
<p>{{ "moveToOrgDesc" | i18n }}</p>
|
||||||
<div class="ml-auto d-flex" *ngIf="collections && collections.length">
|
<div class="form-group">
|
||||||
<button type="button" (click)="selectAll(true)" class="btn btn-link btn-sm py-0">
|
<label for="organization">{{ "organization" | i18n }}</label>
|
||||||
{{ "selectAll" | i18n }}
|
<select
|
||||||
</button>
|
id="organization"
|
||||||
<button type="button" (click)="selectAll(false)" class="btn btn-link btn-sm py-0">
|
name="OrganizationId"
|
||||||
{{ "unselectAll" | i18n }}
|
[(ngModel)]="organizationId"
|
||||||
</button>
|
class="form-control"
|
||||||
|
(change)="filterCollections()"
|
||||||
|
>
|
||||||
|
<option *ngFor="let o of organizations" [ngValue]="o.id">{{ o.name }}</option>
|
||||||
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="d-flex">
|
||||||
|
<h3>{{ "collections" | i18n }}</h3>
|
||||||
|
<div class="ml-auto d-flex" *ngIf="collections && collections.length">
|
||||||
|
<button type="button" (click)="selectAll(true)" class="btn btn-link btn-sm py-0">
|
||||||
|
{{ "selectAll" | i18n }}
|
||||||
|
</button>
|
||||||
|
<button type="button" (click)="selectAll(false)" class="btn btn-link btn-sm py-0">
|
||||||
|
{{ "unselectAll" | i18n }}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div *ngIf="!collections || !collections.length">
|
||||||
|
{{ "noCollectionsInList" | i18n }}
|
||||||
|
</div>
|
||||||
|
<table
|
||||||
|
class="table table-hover table-list mb-0"
|
||||||
|
*ngIf="collections && collections.length"
|
||||||
|
>
|
||||||
|
<tbody>
|
||||||
|
<tr *ngFor="let c of collections; let i = index" (click)="check(c)">
|
||||||
|
<td class="table-list-checkbox">
|
||||||
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
[(ngModel)]="c.checked"
|
||||||
|
name="Collection[{{ i }}].Checked"
|
||||||
|
appStopProp
|
||||||
|
/>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
{{ c.name }}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
</div>
|
</div>
|
||||||
<div *ngIf="!collections || !collections.length">
|
<div class="modal-footer">
|
||||||
{{ "noCollectionsInList" | i18n }}
|
<button
|
||||||
|
type="submit"
|
||||||
|
class="btn btn-primary btn-submit manual"
|
||||||
|
[disabled]="form.loading || !canSave"
|
||||||
|
[ngClass]="{ loading: form.loading }"
|
||||||
|
*ngIf="organizations && organizations.length"
|
||||||
|
>
|
||||||
|
<i
|
||||||
|
class="bwi bwi-spinner bwi-spin"
|
||||||
|
title="{{ 'loading' | i18n }}"
|
||||||
|
aria-hidden="true"
|
||||||
|
></i>
|
||||||
|
<span>{{ "save" | i18n }}</span>
|
||||||
|
</button>
|
||||||
|
<a
|
||||||
|
href="#"
|
||||||
|
routerLink="/create-organization"
|
||||||
|
class="btn btn-primary"
|
||||||
|
*ngIf="!organizations || !organizations.length"
|
||||||
|
>
|
||||||
|
{{ "newOrganization" | i18n }}
|
||||||
|
</a>
|
||||||
|
<button type="button" class="btn btn-outline-secondary" data-dismiss="modal">
|
||||||
|
{{ "cancel" | i18n }}
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<table class="table table-hover table-list mb-0" *ngIf="collections && collections.length">
|
</ng-container>
|
||||||
<tbody>
|
|
||||||
<tr *ngFor="let c of collections; let i = index" (click)="check(c)">
|
|
||||||
<td class="table-list-checkbox">
|
|
||||||
<input
|
|
||||||
type="checkbox"
|
|
||||||
[(ngModel)]="c.checked"
|
|
||||||
name="Collection[{{ i }}].Checked"
|
|
||||||
appStopProp
|
|
||||||
/>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
{{ c.name }}
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
<div class="modal-footer">
|
|
||||||
<button
|
|
||||||
type="submit"
|
|
||||||
class="btn btn-primary btn-submit manual"
|
|
||||||
[disabled]="form.loading || !canSave"
|
|
||||||
[ngClass]="{ loading: form.loading }"
|
|
||||||
*ngIf="organizations && organizations.length"
|
|
||||||
>
|
|
||||||
<i class="bwi bwi-spinner bwi-spin" title="{{ 'loading' | i18n }}" aria-hidden="true"></i>
|
|
||||||
<span>{{ "save" | i18n }}</span>
|
|
||||||
</button>
|
|
||||||
<a
|
|
||||||
href="#"
|
|
||||||
routerLink="/create-organization"
|
|
||||||
class="btn btn-primary"
|
|
||||||
*ngIf="!organizations || !organizations.length"
|
|
||||||
>
|
|
||||||
{{ "newOrganization" | i18n }}
|
|
||||||
</a>
|
|
||||||
<button type="button" class="btn btn-outline-secondary" data-dismiss="modal">
|
|
||||||
{{ "cancel" | i18n }}
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import { CipherService } from "@bitwarden/common/abstractions/cipher.service";
|
|||||||
import { CollectionService } from "@bitwarden/common/abstractions/collection.service";
|
import { CollectionService } from "@bitwarden/common/abstractions/collection.service";
|
||||||
import { I18nService } from "@bitwarden/common/abstractions/i18n.service";
|
import { I18nService } from "@bitwarden/common/abstractions/i18n.service";
|
||||||
import { LogService } from "@bitwarden/common/abstractions/log.service";
|
import { LogService } from "@bitwarden/common/abstractions/log.service";
|
||||||
import { OrganizationService } from "@bitwarden/common/abstractions/organization.service";
|
import { OrganizationService } from "@bitwarden/common/abstractions/organization/organization.service.abstraction";
|
||||||
import { PlatformUtilsService } from "@bitwarden/common/abstractions/platformUtils.service";
|
import { PlatformUtilsService } from "@bitwarden/common/abstractions/platformUtils.service";
|
||||||
import { CollectionView } from "@bitwarden/common/models/view/collectionView";
|
import { CollectionView } from "@bitwarden/common/models/view/collectionView";
|
||||||
|
|
||||||
|
|||||||
@@ -102,9 +102,7 @@ export class OrganizationOptionsComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
this.actionPromise = this.organizationApiService.leave(org.id).then(() => {
|
this.actionPromise = this.organizationApiService.leave(org.id);
|
||||||
return this.syncService.fullSync(true);
|
|
||||||
});
|
|
||||||
await this.actionPromise;
|
await this.actionPromise;
|
||||||
this.platformUtilsService.showToast("success", null, this.i18nService.t("leftOrganization"));
|
this.platformUtilsService.showToast("success", null, this.i18nService.t("leftOrganization"));
|
||||||
await this.load();
|
await this.load();
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import { CipherService } from "@bitwarden/common/abstractions/cipher.service";
|
|||||||
import { CollectionService } from "@bitwarden/common/abstractions/collection.service";
|
import { CollectionService } from "@bitwarden/common/abstractions/collection.service";
|
||||||
import { FolderService } from "@bitwarden/common/abstractions/folder/folder.service.abstraction";
|
import { FolderService } from "@bitwarden/common/abstractions/folder/folder.service.abstraction";
|
||||||
import { I18nService } from "@bitwarden/common/abstractions/i18n.service";
|
import { I18nService } from "@bitwarden/common/abstractions/i18n.service";
|
||||||
import { OrganizationService } from "@bitwarden/common/abstractions/organization.service";
|
import { OrganizationService } from "@bitwarden/common/abstractions/organization/organization.service.abstraction";
|
||||||
import { PolicyService } from "@bitwarden/common/abstractions/policy/policy.service.abstraction";
|
import { PolicyService } from "@bitwarden/common/abstractions/policy/policy.service.abstraction";
|
||||||
import { StateService } from "@bitwarden/common/abstractions/state.service";
|
import { StateService } from "@bitwarden/common/abstractions/state.service";
|
||||||
import { CollectionData } from "@bitwarden/common/models/data/collectionData";
|
import { CollectionData } from "@bitwarden/common/models/data/collectionData";
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ import { CipherService } from "@bitwarden/common/abstractions/cipher.service";
|
|||||||
import { CryptoService } from "@bitwarden/common/abstractions/crypto.service";
|
import { CryptoService } from "@bitwarden/common/abstractions/crypto.service";
|
||||||
import { I18nService } from "@bitwarden/common/abstractions/i18n.service";
|
import { I18nService } from "@bitwarden/common/abstractions/i18n.service";
|
||||||
import { MessagingService } from "@bitwarden/common/abstractions/messaging.service";
|
import { MessagingService } from "@bitwarden/common/abstractions/messaging.service";
|
||||||
import { OrganizationService } from "@bitwarden/common/abstractions/organization.service";
|
import { OrganizationService } from "@bitwarden/common/abstractions/organization/organization.service.abstraction";
|
||||||
import { PasswordRepromptService } from "@bitwarden/common/abstractions/passwordReprompt.service";
|
import { PasswordRepromptService } from "@bitwarden/common/abstractions/passwordReprompt.service";
|
||||||
import { PlatformUtilsService } from "@bitwarden/common/abstractions/platformUtils.service";
|
import { PlatformUtilsService } from "@bitwarden/common/abstractions/platformUtils.service";
|
||||||
import { StateService } from "@bitwarden/common/abstractions/state.service";
|
import { StateService } from "@bitwarden/common/abstractions/state.service";
|
||||||
|
|||||||
@@ -572,8 +572,8 @@
|
|||||||
"loginWithDevice" : {
|
"loginWithDevice" : {
|
||||||
"message": "Log in with device"
|
"message": "Log in with device"
|
||||||
},
|
},
|
||||||
"loginWithDevciceEnabledInfo": {
|
"loginWithDeviceEnabledInfo": {
|
||||||
"message": "Log in with device must be enabled in the settings of the Biwarden mobile app. Need another option?"
|
"message": "Log in with device must be enabled in the settings of the Bitwarden mobile app. Need another option?"
|
||||||
},
|
},
|
||||||
"createAccount": {
|
"createAccount": {
|
||||||
"message": "Create Account"
|
"message": "Create Account"
|
||||||
|
|||||||
@@ -273,7 +273,8 @@ const devServer =
|
|||||||
https://app.simplelogin.io/api/alias/random/new
|
https://app.simplelogin.io/api/alias/random/new
|
||||||
https://quack.duckduckgo.com/api/email/addresses
|
https://quack.duckduckgo.com/api/email/addresses
|
||||||
https://app.anonaddy.com/api/v1/aliases
|
https://app.anonaddy.com/api/v1/aliases
|
||||||
https://api.fastmail.com;
|
https://api.fastmail.com
|
||||||
|
https://quack.duckduckgo.com/api/email/addresses;
|
||||||
object-src
|
object-src
|
||||||
'self'
|
'self'
|
||||||
blob:;`,
|
blob:;`,
|
||||||
|
|||||||
@@ -81,7 +81,13 @@
|
|||||||
<bit-hint>{{ "scimApiKeyHelperText" | i18n }}</bit-hint>
|
<bit-hint>{{ "scimApiKeyHelperText" | i18n }}</bit-hint>
|
||||||
</bit-form-field>
|
</bit-form-field>
|
||||||
|
|
||||||
<bit-submit-button buttonType="primary" [loading]="form.loading" [disabled]="form.loading">
|
<button
|
||||||
|
type="submit"
|
||||||
|
buttonType="primary"
|
||||||
|
bitButton
|
||||||
|
[loading]="form.loading"
|
||||||
|
[disabled]="form.loading"
|
||||||
|
>
|
||||||
{{ "save" | i18n }}
|
{{ "save" | i18n }}
|
||||||
</bit-submit-button>
|
</button>
|
||||||
</form>
|
</form>
|
||||||
|
|||||||
@@ -13,8 +13,8 @@ import { SelectOptions } from "@bitwarden/angular/interfaces/selectOptions";
|
|||||||
import { ControlsOf } from "@bitwarden/angular/types/controls-of";
|
import { ControlsOf } from "@bitwarden/angular/types/controls-of";
|
||||||
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
||||||
import { I18nService } from "@bitwarden/common/abstractions/i18n.service";
|
import { I18nService } from "@bitwarden/common/abstractions/i18n.service";
|
||||||
import { OrganizationService } from "@bitwarden/common/abstractions/organization.service";
|
|
||||||
import { OrganizationApiServiceAbstraction } from "@bitwarden/common/abstractions/organization/organization-api.service.abstraction";
|
import { OrganizationApiServiceAbstraction } from "@bitwarden/common/abstractions/organization/organization-api.service.abstraction";
|
||||||
|
import { OrganizationService } from "@bitwarden/common/abstractions/organization/organization.service.abstraction";
|
||||||
import { PlatformUtilsService } from "@bitwarden/common/abstractions/platformUtils.service";
|
import { PlatformUtilsService } from "@bitwarden/common/abstractions/platformUtils.service";
|
||||||
import {
|
import {
|
||||||
OpenIdConnectRedirectBehavior,
|
OpenIdConnectRedirectBehavior,
|
||||||
|
|||||||
@@ -2,11 +2,11 @@ import { NgModule } from "@angular/core";
|
|||||||
import { RouterModule, Routes } from "@angular/router";
|
import { RouterModule, Routes } from "@angular/router";
|
||||||
|
|
||||||
import { AuthGuard } from "@bitwarden/angular/guards/auth.guard";
|
import { AuthGuard } from "@bitwarden/angular/guards/auth.guard";
|
||||||
|
import { canAccessSettingsTab } from "@bitwarden/common/abstractions/organization/organization.service.abstraction";
|
||||||
import { Organization } from "@bitwarden/common/models/domain/organization";
|
import { Organization } from "@bitwarden/common/models/domain/organization";
|
||||||
|
|
||||||
import { OrganizationPermissionsGuard } from "src/app/organizations/guards/org-permissions.guard";
|
import { OrganizationPermissionsGuard } from "src/app/organizations/guards/org-permissions.guard";
|
||||||
import { OrganizationLayoutComponent } from "src/app/organizations/layouts/organization-layout.component";
|
import { OrganizationLayoutComponent } from "src/app/organizations/layouts/organization-layout.component";
|
||||||
import { canAccessSettingsTab } from "src/app/organizations/navigation-permissions";
|
|
||||||
import { SettingsComponent } from "src/app/organizations/settings/settings.component";
|
import { SettingsComponent } from "src/app/organizations/settings/settings.component";
|
||||||
|
|
||||||
import { ScimComponent } from "./manage/scim.component";
|
import { ScimComponent } from "./manage/scim.component";
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user