mirror of
https://github.com/bitwarden/browser
synced 2026-02-13 15:03:26 +00:00
Merge branch 'main' into ps/extension-refresh
This commit is contained in:
@@ -1,28 +0,0 @@
|
||||
import { View } from "@bitwarden/common/models/view/view";
|
||||
|
||||
interface SelectionResponseLike {
|
||||
id: string;
|
||||
readOnly: boolean;
|
||||
hidePasswords: boolean;
|
||||
manage: boolean;
|
||||
}
|
||||
|
||||
export class CollectionAccessSelectionView extends View {
|
||||
readonly id: string;
|
||||
readonly readOnly: boolean;
|
||||
readonly hidePasswords: boolean;
|
||||
readonly manage: boolean;
|
||||
|
||||
constructor(response?: SelectionResponseLike) {
|
||||
super();
|
||||
|
||||
if (!response) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.id = response.id;
|
||||
this.readOnly = response.readOnly;
|
||||
this.hidePasswords = response.hidePasswords;
|
||||
this.manage = response.manage;
|
||||
}
|
||||
}
|
||||
@@ -1,9 +1,8 @@
|
||||
import { CollectionAccessSelectionView } from "@bitwarden/admin-console/common";
|
||||
import { View } from "@bitwarden/common/src/models/view/view";
|
||||
|
||||
import { GroupDetailsResponse, GroupResponse } from "../services/group/responses/group.response";
|
||||
|
||||
import { CollectionAccessSelectionView } from "./collection-access-selection.view";
|
||||
|
||||
export class GroupView implements View {
|
||||
id: string;
|
||||
organizationId: string;
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
export * from "./collection-access-selection.view";
|
||||
export * from "./group.view";
|
||||
export * from "./organization-user.view";
|
||||
export * from "./organization-user-admin-view";
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
import { CollectionAccessSelectionView } from "@bitwarden/admin-console/common";
|
||||
import {
|
||||
OrganizationUserStatusType,
|
||||
OrganizationUserType,
|
||||
} from "@bitwarden/common/admin-console/enums";
|
||||
import { PermissionsApi } from "@bitwarden/common/admin-console/models/api/permissions.api";
|
||||
|
||||
import { CollectionAccessSelectionView } from "./collection-access-selection.view";
|
||||
|
||||
export class OrganizationUserAdminView {
|
||||
id: string;
|
||||
userId: string;
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
import { OrganizationUserUserDetailsResponse } from "@bitwarden/admin-console/common";
|
||||
import {
|
||||
OrganizationUserUserDetailsResponse,
|
||||
CollectionAccessSelectionView,
|
||||
} from "@bitwarden/admin-console/common";
|
||||
import {
|
||||
OrganizationUserStatusType,
|
||||
OrganizationUserType,
|
||||
} from "@bitwarden/common/admin-console/enums";
|
||||
import { PermissionsApi } from "@bitwarden/common/admin-console/models/api/permissions.api";
|
||||
|
||||
import { CollectionAccessSelectionView } from "./collection-access-selection.view";
|
||||
|
||||
export class OrganizationUserView {
|
||||
id: string;
|
||||
userId: string;
|
||||
|
||||
@@ -14,7 +14,11 @@ import {
|
||||
takeUntil,
|
||||
} from "rxjs";
|
||||
|
||||
import { OrganizationUserApiService } from "@bitwarden/admin-console/common";
|
||||
import {
|
||||
CollectionAdminService,
|
||||
CollectionAdminView,
|
||||
OrganizationUserApiService,
|
||||
} from "@bitwarden/admin-console/common";
|
||||
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
||||
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
||||
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
|
||||
@@ -26,8 +30,6 @@ import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/pl
|
||||
import { UserId } from "@bitwarden/common/types/guid";
|
||||
import { DialogService, ToastService } from "@bitwarden/components";
|
||||
|
||||
import { CollectionAdminService } from "../../../vault/core/collection-admin.service";
|
||||
import { CollectionAdminView } from "../../../vault/core/views/collection-admin.view";
|
||||
import { InternalGroupService as GroupService, GroupView } from "../core";
|
||||
import {
|
||||
AccessItemType,
|
||||
|
||||
@@ -13,7 +13,12 @@ import {
|
||||
takeUntil,
|
||||
} from "rxjs";
|
||||
|
||||
import { OrganizationUserApiService } from "@bitwarden/admin-console/common";
|
||||
import {
|
||||
CollectionAccessSelectionView,
|
||||
CollectionAdminService,
|
||||
CollectionAdminView,
|
||||
OrganizationUserApiService,
|
||||
} from "@bitwarden/admin-console/common";
|
||||
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
||||
import {
|
||||
OrganizationUserStatusType,
|
||||
@@ -24,14 +29,10 @@ import { Organization } from "@bitwarden/common/admin-console/models/domain/orga
|
||||
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
||||
import { ProductTierType } from "@bitwarden/common/billing/enums";
|
||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
||||
import { CollectionView } from "@bitwarden/common/vault/models/view/collection.view";
|
||||
import { DialogService, ToastService } from "@bitwarden/components";
|
||||
|
||||
import { CollectionAdminService } from "../../../../../vault/core/collection-admin.service";
|
||||
import { CollectionAdminView } from "../../../../../vault/core/views/collection-admin.view";
|
||||
import {
|
||||
CollectionAccessSelectionView,
|
||||
GroupService,
|
||||
GroupView,
|
||||
OrganizationUserAdminView,
|
||||
@@ -133,7 +134,6 @@ export class MemberDialogComponent implements OnDestroy {
|
||||
@Inject(DIALOG_DATA) protected params: MemberDialogParams,
|
||||
private dialogRef: DialogRef<MemberDialogResult>,
|
||||
private i18nService: I18nService,
|
||||
private platformUtilsService: PlatformUtilsService,
|
||||
private formBuilder: FormBuilder,
|
||||
// TODO: We should really look into consolidating naming conventions for these services
|
||||
private collectionAdminService: CollectionAdminService,
|
||||
|
||||
@@ -2,6 +2,7 @@ import { Component, OnInit } from "@angular/core";
|
||||
import { ActivatedRoute, Router } from "@angular/router";
|
||||
import { firstValueFrom } from "rxjs";
|
||||
|
||||
import { CollectionAdminService } from "@bitwarden/admin-console/common";
|
||||
import {
|
||||
canAccessVaultTab,
|
||||
OrganizationService,
|
||||
@@ -11,7 +12,6 @@ import { ImportComponent } from "@bitwarden/importer/ui";
|
||||
|
||||
import { LooseComponentsModule, SharedModule } from "../../../shared";
|
||||
import { ImportCollectionAdminService } from "../../../tools/import/import-collection-admin.service";
|
||||
import { CollectionAdminService } from "../../../vault/core/collection-admin.service";
|
||||
|
||||
@Component({
|
||||
templateUrl: "org-import.component.html",
|
||||
|
||||
@@ -1,11 +1,14 @@
|
||||
import { OrganizationUserUserDetailsResponse } from "@bitwarden/admin-console/common";
|
||||
import {
|
||||
CollectionAccessSelectionView,
|
||||
OrganizationUserUserDetailsResponse,
|
||||
} from "@bitwarden/admin-console/common";
|
||||
import {
|
||||
OrganizationUserStatusType,
|
||||
OrganizationUserType,
|
||||
} from "@bitwarden/common/admin-console/enums";
|
||||
import { SelectItemView } from "@bitwarden/components";
|
||||
|
||||
import { CollectionAccessSelectionView, GroupView } from "../../../core";
|
||||
import { GroupView } from "../../../core";
|
||||
|
||||
/**
|
||||
* Permission options that replace/correspond with manage, readOnly, and hidePassword server fields.
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
export * from "./webauthn-login";
|
||||
export * from "./set-password-jit";
|
||||
export * from "./registration";
|
||||
export * from "./web-lock-component.service";
|
||||
|
||||
@@ -0,0 +1,94 @@
|
||||
import { TestBed } from "@angular/core/testing";
|
||||
import { mock, MockProxy } from "jest-mock-extended";
|
||||
import { firstValueFrom, of } from "rxjs";
|
||||
|
||||
import { UserDecryptionOptionsServiceAbstraction } from "@bitwarden/auth/common";
|
||||
import { UserId } from "@bitwarden/common/types/guid";
|
||||
|
||||
import { WebLockComponentService } from "./web-lock-component.service";
|
||||
|
||||
describe("WebLockComponentService", () => {
|
||||
let service: WebLockComponentService;
|
||||
|
||||
let userDecryptionOptionsService: MockProxy<UserDecryptionOptionsServiceAbstraction>;
|
||||
|
||||
beforeEach(() => {
|
||||
userDecryptionOptionsService = mock<UserDecryptionOptionsServiceAbstraction>();
|
||||
|
||||
TestBed.configureTestingModule({
|
||||
providers: [
|
||||
WebLockComponentService,
|
||||
{
|
||||
provide: UserDecryptionOptionsServiceAbstraction,
|
||||
useValue: userDecryptionOptionsService,
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
service = TestBed.inject(WebLockComponentService);
|
||||
});
|
||||
|
||||
it("instantiates", () => {
|
||||
expect(service).not.toBeFalsy();
|
||||
});
|
||||
|
||||
describe("getBiometricsError", () => {
|
||||
it("throws an error when given a null input", () => {
|
||||
expect(() => service.getBiometricsError(null)).toThrow(
|
||||
"Biometric unlock is not supported in the web app. See getAvailableUnlockOptions$",
|
||||
);
|
||||
});
|
||||
it("throws an error when given a non-null input", () => {
|
||||
expect(() => service.getBiometricsError("error")).toThrow(
|
||||
"Biometric unlock is not supported in the web app. See getAvailableUnlockOptions$",
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe("getPreviousUrl", () => {
|
||||
it("returns null", () => {
|
||||
expect(service.getPreviousUrl()).toBeNull();
|
||||
});
|
||||
});
|
||||
|
||||
describe("isWindowVisible", () => {
|
||||
it("throws an error", async () => {
|
||||
await expect(service.isWindowVisible()).rejects.toThrow("Method not implemented.");
|
||||
});
|
||||
});
|
||||
|
||||
describe("getBiometricsUnlockBtnText", () => {
|
||||
it("throws an error", () => {
|
||||
expect(() => service.getBiometricsUnlockBtnText()).toThrow(
|
||||
"Biometric unlock is not supported in the web app. See getAvailableUnlockOptions$",
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe("getAvailableUnlockOptions$", () => {
|
||||
it("returns an observable of unlock options", async () => {
|
||||
const userId = "user-id" as UserId;
|
||||
const userDecryptionOptions = {
|
||||
hasMasterPassword: true,
|
||||
};
|
||||
userDecryptionOptionsService.userDecryptionOptionsById$.mockReturnValueOnce(
|
||||
of(userDecryptionOptions),
|
||||
);
|
||||
|
||||
const unlockOptions = await firstValueFrom(service.getAvailableUnlockOptions$(userId));
|
||||
|
||||
expect(unlockOptions).toEqual({
|
||||
masterPassword: {
|
||||
enabled: true,
|
||||
},
|
||||
pin: {
|
||||
enabled: false,
|
||||
},
|
||||
biometrics: {
|
||||
enabled: false,
|
||||
disableReason: null,
|
||||
},
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,55 @@
|
||||
import { inject } from "@angular/core";
|
||||
import { map, Observable } from "rxjs";
|
||||
|
||||
import { LockComponentService, UnlockOptions } from "@bitwarden/auth/angular";
|
||||
import {
|
||||
UserDecryptionOptions,
|
||||
UserDecryptionOptionsServiceAbstraction,
|
||||
} from "@bitwarden/auth/common";
|
||||
import { UserId } from "@bitwarden/common/types/guid";
|
||||
|
||||
export class WebLockComponentService implements LockComponentService {
|
||||
private readonly userDecryptionOptionsService = inject(UserDecryptionOptionsServiceAbstraction);
|
||||
|
||||
constructor() {}
|
||||
|
||||
getBiometricsError(error: any): string | null {
|
||||
throw new Error(
|
||||
"Biometric unlock is not supported in the web app. See getAvailableUnlockOptions$",
|
||||
);
|
||||
}
|
||||
|
||||
getPreviousUrl(): string | null {
|
||||
return null;
|
||||
}
|
||||
|
||||
async isWindowVisible(): Promise<boolean> {
|
||||
throw new Error("Method not implemented.");
|
||||
}
|
||||
|
||||
getBiometricsUnlockBtnText(): string {
|
||||
throw new Error(
|
||||
"Biometric unlock is not supported in the web app. See getAvailableUnlockOptions$",
|
||||
);
|
||||
}
|
||||
|
||||
getAvailableUnlockOptions$(userId: UserId): Observable<UnlockOptions> {
|
||||
return this.userDecryptionOptionsService.userDecryptionOptionsById$(userId).pipe(
|
||||
map((userDecryptionOptions: UserDecryptionOptions) => {
|
||||
const unlockOpts: UnlockOptions = {
|
||||
masterPassword: {
|
||||
enabled: userDecryptionOptions.hasMasterPassword,
|
||||
},
|
||||
pin: {
|
||||
enabled: false,
|
||||
},
|
||||
biometrics: {
|
||||
enabled: false,
|
||||
disableReason: null,
|
||||
},
|
||||
};
|
||||
return unlockOpts;
|
||||
}),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
<form [formGroup]="formGroup" [bitSubmit]="submit">
|
||||
<bit-dialog>
|
||||
<h1 bitDialogTitle>
|
||||
{{ (hasBillingToken ? "viewBillingSyncToken" : "generateBillingSyncToken") | i18n }}
|
||||
{{ (hasBillingToken ? "viewBillingToken" : "generateBillingToken") | i18n }}
|
||||
</h1>
|
||||
<div bitDialogContent>
|
||||
<app-user-verification formControlName="verification" *ngIf="!clientSecret">
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<form [formGroup]="formGroup" [bitSubmit]="submit">
|
||||
<bit-dialog>
|
||||
<h1 bitDialogTitle>
|
||||
{{ "manageBillingSync" | i18n }}
|
||||
{{ "manageBillingTokenSync" | i18n }}
|
||||
</h1>
|
||||
<div bitDialogContent>
|
||||
<p>{{ "billingSyncKeyDesc" | i18n }}</p>
|
||||
|
||||
@@ -280,7 +280,7 @@
|
||||
(click)="manageBillingSync()"
|
||||
*ngIf="canManageBillingSync"
|
||||
>
|
||||
{{ (hasBillingSyncToken ? "manageBillingSync" : "setUpBillingSync") | i18n }}
|
||||
{{ (hasBillingSyncToken ? "viewBillingToken" : "setUpBillingSync") | i18n }}
|
||||
</button>
|
||||
</div>
|
||||
<ng-container *ngIf="userOrg.canEditSubscription">
|
||||
|
||||
@@ -89,7 +89,7 @@
|
||||
</a>
|
||||
</bit-label>
|
||||
<bit-hint>
|
||||
{{ "billingSyncDesc" | i18n }}
|
||||
{{ "automaticBillingSyncDesc" | i18n }}
|
||||
</bit-hint>
|
||||
</bit-radio-button>
|
||||
<ng-container *ngIf="updateMethod === licenseOptions.SYNC">
|
||||
@@ -100,7 +100,7 @@
|
||||
type="button"
|
||||
(click)="manageBillingSyncSelfHosted()"
|
||||
>
|
||||
{{ "manageBillingSync" | i18n }}
|
||||
{{ "manageBillingTokenSync" | i18n }}
|
||||
</button>
|
||||
<button
|
||||
bitButton
|
||||
@@ -122,7 +122,7 @@
|
||||
>
|
||||
<bit-label>{{ "manualUpload" | i18n }}</bit-label>
|
||||
<bit-hint>
|
||||
{{ "manualUploadDesc" | i18n }}
|
||||
{{ "manualBillingTokenUploadDesc" | i18n }}
|
||||
</bit-hint>
|
||||
</bit-radio-button>
|
||||
<ng-container *ngIf="updateMethod === licenseOptions.UPLOAD">
|
||||
|
||||
@@ -1,7 +1,11 @@
|
||||
import { CommonModule } from "@angular/common";
|
||||
import { APP_INITIALIZER, NgModule, Optional, SkipSelf } from "@angular/core";
|
||||
|
||||
import { OrganizationUserApiService } from "@bitwarden/admin-console/common";
|
||||
import {
|
||||
CollectionAdminService,
|
||||
DefaultCollectionAdminService,
|
||||
OrganizationUserApiService,
|
||||
} from "@bitwarden/admin-console/common";
|
||||
import { SafeProvider, safeProvider } from "@bitwarden/angular/platform/utils/safe-provider";
|
||||
import {
|
||||
CLIENT_TYPE,
|
||||
@@ -20,6 +24,7 @@ import { JslibServicesModule } from "@bitwarden/angular/services/jslib-services.
|
||||
import { ModalService as ModalServiceAbstraction } from "@bitwarden/angular/services/modal.service";
|
||||
import {
|
||||
RegistrationFinishService as RegistrationFinishServiceAbstraction,
|
||||
LockComponentService,
|
||||
SetPasswordJitService,
|
||||
} from "@bitwarden/auth/angular";
|
||||
import { InternalUserDecryptionOptionsServiceAbstraction } from "@bitwarden/auth/common";
|
||||
@@ -59,10 +64,15 @@ import {
|
||||
ThemeStateService,
|
||||
} from "@bitwarden/common/platform/theming/theme-state.service";
|
||||
import { VaultTimeout, VaultTimeoutStringType } from "@bitwarden/common/types/vault-timeout.type";
|
||||
import { CollectionService } from "@bitwarden/common/vault/abstractions/collection.service";
|
||||
import { BiometricsService } from "@bitwarden/key-management";
|
||||
|
||||
import { PolicyListService } from "../admin-console/core/policy-list.service";
|
||||
import { WebRegistrationFinishService, WebSetPasswordJitService } from "../auth";
|
||||
import {
|
||||
WebSetPasswordJitService,
|
||||
WebRegistrationFinishService,
|
||||
WebLockComponentService,
|
||||
} from "../auth";
|
||||
import { AcceptOrganizationInviteService } from "../auth/organization-invite/accept-organization.service";
|
||||
import { HtmlStorageService } from "../core/html-storage.service";
|
||||
import { I18nService } from "../core/i18n.service";
|
||||
@@ -70,7 +80,6 @@ import { WebBiometricsService } from "../key-management/web-biometric.service";
|
||||
import { WebEnvironmentService } from "../platform/web-environment.service";
|
||||
import { WebMigrationRunner } from "../platform/web-migration-runner";
|
||||
import { WebStorageServiceProvider } from "../platform/web-storage-service.provider";
|
||||
import { CollectionAdminService } from "../vault/core/collection-admin.service";
|
||||
|
||||
import { EventService } from "./event.service";
|
||||
import { InitService } from "./init.service";
|
||||
@@ -144,7 +153,6 @@ const safeProviders: SafeProvider[] = [
|
||||
useClass: WebFileDownloadService,
|
||||
useAngularDecorators: true,
|
||||
}),
|
||||
safeProvider(CollectionAdminService),
|
||||
safeProvider({
|
||||
provide: WindowStorageService,
|
||||
useFactory: () => new WindowStorageService(window.localStorage),
|
||||
@@ -197,6 +205,11 @@ const safeProviders: SafeProvider[] = [
|
||||
PolicyService,
|
||||
],
|
||||
}),
|
||||
safeProvider({
|
||||
provide: LockComponentService,
|
||||
useClass: WebLockComponentService,
|
||||
deps: [],
|
||||
}),
|
||||
safeProvider({
|
||||
provide: SetPasswordJitService,
|
||||
useClass: WebSetPasswordJitService,
|
||||
@@ -217,6 +230,11 @@ const safeProviders: SafeProvider[] = [
|
||||
useClass: DefaultAppIdService,
|
||||
deps: [OBSERVABLE_DISK_LOCAL_STORAGE, LogService],
|
||||
}),
|
||||
safeProvider({
|
||||
provide: CollectionAdminService,
|
||||
useClass: DefaultCollectionAdminService,
|
||||
deps: [ApiService, CryptoServiceAbstraction, EncryptService, CollectionService],
|
||||
}),
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
|
||||
@@ -10,6 +10,7 @@ import {
|
||||
unauthGuardFn,
|
||||
} from "@bitwarden/angular/auth/guards";
|
||||
import { canAccessFeature } from "@bitwarden/angular/platform/guard/feature-flag.guard";
|
||||
import { extensionRefreshSwap } from "@bitwarden/angular/utils/extension-refresh-swap";
|
||||
import {
|
||||
AnonLayoutWrapperComponent,
|
||||
AnonLayoutWrapperData,
|
||||
@@ -20,6 +21,7 @@ import {
|
||||
RegistrationStartSecondaryComponentData,
|
||||
SetPasswordJitComponent,
|
||||
RegistrationLinkExpiredComponent,
|
||||
LockV2Component,
|
||||
LockIcon,
|
||||
UserLockIcon,
|
||||
} from "@bitwarden/auth/angular";
|
||||
@@ -337,21 +339,41 @@ const routes: Routes = [
|
||||
pageTitle: "logIn",
|
||||
},
|
||||
},
|
||||
{
|
||||
path: "lock",
|
||||
canActivate: [deepLinkGuard(), lockGuard()],
|
||||
children: [
|
||||
{
|
||||
path: "",
|
||||
component: LockComponent,
|
||||
},
|
||||
],
|
||||
data: {
|
||||
pageTitle: "yourVaultIsLockedV2",
|
||||
pageIcon: LockIcon,
|
||||
showReadonlyHostname: true,
|
||||
} satisfies AnonLayoutWrapperData,
|
||||
},
|
||||
...extensionRefreshSwap(
|
||||
LockComponent,
|
||||
LockV2Component,
|
||||
{
|
||||
path: "lock",
|
||||
canActivate: [deepLinkGuard(), lockGuard()],
|
||||
children: [
|
||||
{
|
||||
path: "",
|
||||
component: LockComponent,
|
||||
},
|
||||
],
|
||||
data: {
|
||||
pageTitle: "yourVaultIsLockedV2",
|
||||
pageIcon: LockIcon,
|
||||
showReadonlyHostname: true,
|
||||
} satisfies AnonLayoutWrapperData,
|
||||
},
|
||||
{
|
||||
path: "lock",
|
||||
canActivate: [deepLinkGuard(), lockGuard()],
|
||||
children: [
|
||||
{
|
||||
path: "",
|
||||
component: LockV2Component,
|
||||
},
|
||||
],
|
||||
data: {
|
||||
pageTitle: "yourAccountIsLocked",
|
||||
pageIcon: LockIcon,
|
||||
showReadonlyHostname: true,
|
||||
} satisfies AnonLayoutWrapperData,
|
||||
},
|
||||
),
|
||||
|
||||
{
|
||||
path: "2fa",
|
||||
canActivate: [unauthGuardFn()],
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { Injectable } from "@angular/core";
|
||||
|
||||
import { CollectionAdminService, CollectionAdminView } from "@bitwarden/admin-console/common";
|
||||
|
||||
import { ImportCollectionServiceAbstraction } from "../../../../../../libs/importer/src/services/import-collection.service.abstraction";
|
||||
import { CollectionAdminService } from "../../vault/core/collection-admin.service";
|
||||
import { CollectionAdminView } from "../../vault/core/views/collection-admin.view";
|
||||
|
||||
@Injectable()
|
||||
export class ImportCollectionAdminService implements ImportCollectionServiceAbstraction {
|
||||
|
||||
@@ -14,6 +14,9 @@ import {
|
||||
import { first } from "rxjs/operators";
|
||||
|
||||
import {
|
||||
CollectionAccessSelectionView,
|
||||
CollectionAdminService,
|
||||
CollectionAdminView,
|
||||
OrganizationUserApiService,
|
||||
OrganizationUserUserMiniResponse,
|
||||
} from "@bitwarden/admin-console/common";
|
||||
@@ -26,11 +29,7 @@ import { CollectionResponse } from "@bitwarden/common/vault/models/response/coll
|
||||
import { CollectionView } from "@bitwarden/common/vault/models/view/collection.view";
|
||||
import { BitValidators, DialogService } from "@bitwarden/components";
|
||||
|
||||
import {
|
||||
CollectionAccessSelectionView,
|
||||
GroupService,
|
||||
GroupView,
|
||||
} from "../../../admin-console/organizations/core";
|
||||
import { GroupService, GroupView } from "../../../admin-console/organizations/core";
|
||||
import { PermissionMode } from "../../../admin-console/organizations/shared/components/access-selector/access-selector.component";
|
||||
import {
|
||||
AccessItemType,
|
||||
@@ -40,8 +39,6 @@ import {
|
||||
convertToPermission,
|
||||
convertToSelectionView,
|
||||
} from "../../../admin-console/organizations/shared/components/access-selector/access-selector.models";
|
||||
import { CollectionAdminService } from "../../core/collection-admin.service";
|
||||
import { CollectionAdminView } from "../../core/views/collection-admin.view";
|
||||
|
||||
export enum CollectionDialogTabType {
|
||||
Info = 0,
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
import { Component, EventEmitter, Input, Output } from "@angular/core";
|
||||
|
||||
import { CollectionAdminView, Unassigned } from "@bitwarden/admin-console/common";
|
||||
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
|
||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||
import { CollectionView } from "@bitwarden/common/vault/models/view/collection.view";
|
||||
|
||||
import { GroupView } from "../../../admin-console/organizations/core";
|
||||
import { CollectionAdminView } from "../../core/views/collection-admin.view";
|
||||
import { Unassigned } from "../../individual-vault/vault-filter/shared/models/routed-vault-filter.model";
|
||||
|
||||
import {
|
||||
convertToPermission,
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
import { SelectionModel } from "@angular/cdk/collections";
|
||||
import { Component, EventEmitter, Input, Output } from "@angular/core";
|
||||
|
||||
import { Unassigned } from "@bitwarden/admin-console/common";
|
||||
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
|
||||
import { CipherView } from "@bitwarden/common/vault/models/view/cipher.view";
|
||||
import { CollectionView } from "@bitwarden/common/vault/models/view/collection.view";
|
||||
import { TableDataSource } from "@bitwarden/components";
|
||||
|
||||
import { GroupView } from "../../../admin-console/organizations/core";
|
||||
import { Unassigned } from "../../individual-vault/vault-filter/shared/models/routed-vault-filter.model";
|
||||
|
||||
import { VaultItem } from "./vault-item";
|
||||
import { VaultItemEvent } from "./vault-item-event";
|
||||
|
||||
@@ -3,6 +3,11 @@ import { RouterModule } from "@angular/router";
|
||||
import { applicationConfig, Meta, moduleMetadata, StoryObj } from "@storybook/angular";
|
||||
import { BehaviorSubject, of } from "rxjs";
|
||||
|
||||
import {
|
||||
CollectionAccessSelectionView,
|
||||
CollectionAdminView,
|
||||
Unassigned,
|
||||
} from "@bitwarden/admin-console/common";
|
||||
import { OrganizationUserType } from "@bitwarden/common/admin-console/enums";
|
||||
import { PermissionsApi } from "@bitwarden/common/admin-console/models/api/permissions.api";
|
||||
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
|
||||
@@ -19,13 +24,8 @@ import { CipherView } from "@bitwarden/common/vault/models/view/cipher.view";
|
||||
import { LoginUriView } from "@bitwarden/common/vault/models/view/login-uri.view";
|
||||
import { LoginView } from "@bitwarden/common/vault/models/view/login.view";
|
||||
|
||||
import {
|
||||
CollectionAccessSelectionView,
|
||||
GroupView,
|
||||
} from "../../../admin-console/organizations/core";
|
||||
import { GroupView } from "../../../admin-console/organizations/core";
|
||||
import { PreloadedEnglishI18nModule } from "../../../core/tests";
|
||||
import { CollectionAdminView } from "../../core/views/collection-admin.view";
|
||||
import { Unassigned } from "../../individual-vault/vault-filter/shared/models/routed-vault-filter.model";
|
||||
|
||||
import { VaultItemsComponent } from "./vault-items.component";
|
||||
import { VaultItemsModule } from "./vault-items.module";
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
import { SelectionReadOnlyRequest } from "@bitwarden/common/admin-console/models/request/selection-read-only.request";
|
||||
|
||||
export class BulkCollectionAccessRequest {
|
||||
collectionIds: string[];
|
||||
users: SelectionReadOnlyRequest[];
|
||||
groups: SelectionReadOnlyRequest[];
|
||||
}
|
||||
@@ -1,170 +0,0 @@
|
||||
import { Injectable } from "@angular/core";
|
||||
|
||||
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
||||
import { SelectionReadOnlyRequest } from "@bitwarden/common/admin-console/models/request/selection-read-only.request";
|
||||
import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service";
|
||||
import { EncryptService } from "@bitwarden/common/platform/abstractions/encrypt.service";
|
||||
import { EncString } from "@bitwarden/common/platform/models/domain/enc-string";
|
||||
import { CollectionService } from "@bitwarden/common/vault/abstractions/collection.service";
|
||||
import { CollectionData } from "@bitwarden/common/vault/models/data/collection.data";
|
||||
import { CollectionRequest } from "@bitwarden/common/vault/models/request/collection.request";
|
||||
import {
|
||||
CollectionAccessDetailsResponse,
|
||||
CollectionDetailsResponse,
|
||||
CollectionResponse,
|
||||
} from "@bitwarden/common/vault/models/response/collection.response";
|
||||
|
||||
import { CollectionAccessSelectionView } from "../../admin-console/organizations/core";
|
||||
|
||||
import { BulkCollectionAccessRequest } from "./bulk-collection-access.request";
|
||||
import { CollectionAdminView } from "./views/collection-admin.view";
|
||||
|
||||
@Injectable()
|
||||
export class CollectionAdminService {
|
||||
constructor(
|
||||
private apiService: ApiService,
|
||||
private cryptoService: CryptoService,
|
||||
private encryptService: EncryptService,
|
||||
private collectionService: CollectionService,
|
||||
) {}
|
||||
|
||||
async getAll(organizationId: string): Promise<CollectionAdminView[]> {
|
||||
const collectionResponse =
|
||||
await this.apiService.getManyCollectionsWithAccessDetails(organizationId);
|
||||
|
||||
if (collectionResponse?.data == null || collectionResponse.data.length === 0) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return await this.decryptMany(organizationId, collectionResponse.data);
|
||||
}
|
||||
|
||||
async get(
|
||||
organizationId: string,
|
||||
collectionId: string,
|
||||
): Promise<CollectionAdminView | undefined> {
|
||||
const collectionResponse = await this.apiService.getCollectionAccessDetails(
|
||||
organizationId,
|
||||
collectionId,
|
||||
);
|
||||
|
||||
if (collectionResponse == null) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const [view] = await this.decryptMany(organizationId, [collectionResponse]);
|
||||
|
||||
return view;
|
||||
}
|
||||
|
||||
async save(collection: CollectionAdminView): Promise<CollectionDetailsResponse> {
|
||||
const request = await this.encrypt(collection);
|
||||
|
||||
let response: CollectionDetailsResponse;
|
||||
if (collection.id == null) {
|
||||
response = await this.apiService.postCollection(collection.organizationId, request);
|
||||
collection.id = response.id;
|
||||
} else {
|
||||
response = await this.apiService.putCollection(
|
||||
collection.organizationId,
|
||||
collection.id,
|
||||
request,
|
||||
);
|
||||
}
|
||||
|
||||
if (response.assigned) {
|
||||
await this.collectionService.upsert(new CollectionData(response));
|
||||
} else {
|
||||
await this.collectionService.delete(collection.id);
|
||||
}
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
async delete(organizationId: string, collectionId: string): Promise<void> {
|
||||
await this.apiService.deleteCollection(organizationId, collectionId);
|
||||
}
|
||||
|
||||
async bulkAssignAccess(
|
||||
organizationId: string,
|
||||
collectionIds: string[],
|
||||
users: CollectionAccessSelectionView[],
|
||||
groups: CollectionAccessSelectionView[],
|
||||
): Promise<void> {
|
||||
const request = new BulkCollectionAccessRequest();
|
||||
request.collectionIds = collectionIds;
|
||||
request.users = users.map(
|
||||
(u) => new SelectionReadOnlyRequest(u.id, u.readOnly, u.hidePasswords, u.manage),
|
||||
);
|
||||
request.groups = groups.map(
|
||||
(g) => new SelectionReadOnlyRequest(g.id, g.readOnly, g.hidePasswords, g.manage),
|
||||
);
|
||||
|
||||
await this.apiService.send(
|
||||
"POST",
|
||||
`/organizations/${organizationId}/collections/bulk-access`,
|
||||
request,
|
||||
true,
|
||||
false,
|
||||
);
|
||||
}
|
||||
|
||||
private async decryptMany(
|
||||
organizationId: string,
|
||||
collections: CollectionResponse[] | CollectionAccessDetailsResponse[],
|
||||
): Promise<CollectionAdminView[]> {
|
||||
const orgKey = await this.cryptoService.getOrgKey(organizationId);
|
||||
|
||||
const promises = collections.map(async (c) => {
|
||||
const view = new CollectionAdminView();
|
||||
view.id = c.id;
|
||||
view.name = await this.encryptService.decryptToUtf8(new EncString(c.name), orgKey);
|
||||
view.externalId = c.externalId;
|
||||
view.organizationId = c.organizationId;
|
||||
|
||||
if (isCollectionAccessDetailsResponse(c)) {
|
||||
view.groups = c.groups;
|
||||
view.users = c.users;
|
||||
view.assigned = c.assigned;
|
||||
view.readOnly = c.readOnly;
|
||||
view.hidePasswords = c.hidePasswords;
|
||||
view.manage = c.manage;
|
||||
view.unmanaged = c.unmanaged;
|
||||
}
|
||||
|
||||
return view;
|
||||
});
|
||||
|
||||
return await Promise.all(promises);
|
||||
}
|
||||
|
||||
private async encrypt(model: CollectionAdminView): Promise<CollectionRequest> {
|
||||
if (model.organizationId == null) {
|
||||
throw new Error("Collection has no organization id.");
|
||||
}
|
||||
const key = await this.cryptoService.getOrgKey(model.organizationId);
|
||||
if (key == null) {
|
||||
throw new Error("No key for this collection's organization.");
|
||||
}
|
||||
const collection = new CollectionRequest();
|
||||
collection.externalId = model.externalId;
|
||||
collection.name = (await this.encryptService.encrypt(model.name, key)).encryptedString;
|
||||
collection.groups = model.groups.map(
|
||||
(group) =>
|
||||
new SelectionReadOnlyRequest(group.id, group.readOnly, group.hidePasswords, group.manage),
|
||||
);
|
||||
collection.users = model.users.map(
|
||||
(user) =>
|
||||
new SelectionReadOnlyRequest(user.id, user.readOnly, user.hidePasswords, user.manage),
|
||||
);
|
||||
return collection;
|
||||
}
|
||||
}
|
||||
|
||||
function isCollectionAccessDetailsResponse(
|
||||
response: CollectionResponse | CollectionAccessDetailsResponse,
|
||||
): response is CollectionAccessDetailsResponse {
|
||||
const anyResponse = response as any;
|
||||
|
||||
return anyResponse?.groups instanceof Array && anyResponse?.users instanceof Array;
|
||||
}
|
||||
@@ -1,96 +0,0 @@
|
||||
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
|
||||
import { CollectionAccessDetailsResponse } from "@bitwarden/common/src/vault/models/response/collection.response";
|
||||
import { CollectionView } from "@bitwarden/common/vault/models/view/collection.view";
|
||||
|
||||
import { CollectionAccessSelectionView } from "../../../admin-console/organizations/core/views/collection-access-selection.view";
|
||||
import { Unassigned } from "../../individual-vault/vault-filter/shared/models/routed-vault-filter.model";
|
||||
|
||||
export class CollectionAdminView extends CollectionView {
|
||||
groups: CollectionAccessSelectionView[] = [];
|
||||
users: CollectionAccessSelectionView[] = [];
|
||||
|
||||
/**
|
||||
* Flag indicating the collection has no active user or group assigned to it with CanManage permissions
|
||||
* In this case, the collection can be managed by admins/owners or custom users with appropriate permissions
|
||||
*/
|
||||
unmanaged: boolean;
|
||||
|
||||
/**
|
||||
* Flag indicating the user has been explicitly assigned to this Collection
|
||||
*/
|
||||
assigned: boolean;
|
||||
|
||||
constructor(response?: CollectionAccessDetailsResponse) {
|
||||
super(response);
|
||||
|
||||
if (!response) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.groups = response.groups
|
||||
? response.groups.map((g) => new CollectionAccessSelectionView(g))
|
||||
: [];
|
||||
|
||||
this.users = response.users
|
||||
? response.users.map((g) => new CollectionAccessSelectionView(g))
|
||||
: [];
|
||||
|
||||
this.assigned = response.assigned;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the user can edit a collection (including user and group access) from the Admin Console.
|
||||
*/
|
||||
override canEdit(org: Organization): boolean {
|
||||
return (
|
||||
org?.canEditAnyCollection ||
|
||||
(this.unmanaged && org?.canEditUnmanagedCollections) ||
|
||||
super.canEdit(org)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the user can delete a collection from the Admin Console.
|
||||
*/
|
||||
override canDelete(org: Organization): boolean {
|
||||
return org?.canDeleteAnyCollection || super.canDelete(org);
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether the user can modify user access to this collection
|
||||
*/
|
||||
canEditUserAccess(org: Organization): boolean {
|
||||
return (
|
||||
(org.permissions.manageUsers && org.allowAdminAccessToAllCollectionItems) || this.canEdit(org)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether the user can modify group access to this collection
|
||||
*/
|
||||
canEditGroupAccess(org: Organization): boolean {
|
||||
return (
|
||||
(org.permissions.manageGroups && org.allowAdminAccessToAllCollectionItems) ||
|
||||
this.canEdit(org)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the user can view collection info and access in a read-only state from the Admin Console
|
||||
*/
|
||||
override canViewCollectionInfo(org: Organization | undefined): boolean {
|
||||
if (this.isUnassignedCollection) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return this.manage || org?.isAdmin || org?.permissions.editAnyCollection;
|
||||
}
|
||||
|
||||
/**
|
||||
* True if this collection represents the pseudo "Unassigned" collection
|
||||
* This is different from the "unmanaged" flag, which indicates that no users or groups have access to the collection
|
||||
*/
|
||||
get isUnassignedCollection() {
|
||||
return this.id === Unassigned;
|
||||
}
|
||||
}
|
||||
@@ -1,13 +1,12 @@
|
||||
import { Component, Input, OnChanges } from "@angular/core";
|
||||
import { firstValueFrom } from "rxjs";
|
||||
|
||||
import { Unassigned } from "@bitwarden/admin-console/common";
|
||||
import { AvatarService } from "@bitwarden/common/auth/abstractions/avatar.service";
|
||||
import { TokenService } from "@bitwarden/common/auth/abstractions/token.service";
|
||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||
import { Utils } from "@bitwarden/common/platform/misc/utils";
|
||||
|
||||
import { Unassigned } from "../vault-filter/shared/models/routed-vault-filter.model";
|
||||
|
||||
@Component({
|
||||
selector: "app-org-badge",
|
||||
templateUrl: "organization-name-badge.component.html",
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import { Observable } from "rxjs";
|
||||
|
||||
import { CollectionAdminView } from "@bitwarden/admin-console/common";
|
||||
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
|
||||
import { CollectionView } from "@bitwarden/common/src/vault/models/view/collection.view";
|
||||
import { FolderView } from "@bitwarden/common/src/vault/models/view/folder.view";
|
||||
import { TreeNode } from "@bitwarden/common/vault/models/domain/tree-node";
|
||||
|
||||
import { CollectionAdminView } from "../../../../core/views/collection-admin.view";
|
||||
import {
|
||||
CipherTypeFilter,
|
||||
CollectionFilter,
|
||||
|
||||
@@ -2,15 +2,12 @@ import { Injectable } from "@angular/core";
|
||||
import { Router } from "@angular/router";
|
||||
import { combineLatest, map, Observable } from "rxjs";
|
||||
|
||||
import { Unassigned } from "@bitwarden/admin-console/common";
|
||||
import { TreeNode } from "@bitwarden/common/vault/models/domain/tree-node";
|
||||
import { ServiceUtils } from "@bitwarden/common/vault/service-utils";
|
||||
|
||||
import { RoutedVaultFilterBridge } from "../shared/models/routed-vault-filter-bridge.model";
|
||||
import {
|
||||
RoutedVaultFilterModel,
|
||||
Unassigned,
|
||||
All,
|
||||
} from "../shared/models/routed-vault-filter.model";
|
||||
import { RoutedVaultFilterModel, All } from "../shared/models/routed-vault-filter.model";
|
||||
import { VaultFilter } from "../shared/models/vault-filter.model";
|
||||
import {
|
||||
CipherTypeFilter,
|
||||
|
||||
@@ -10,6 +10,7 @@ import {
|
||||
switchMap,
|
||||
} from "rxjs";
|
||||
|
||||
import { CollectionAdminView } from "@bitwarden/admin-console/common";
|
||||
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
||||
import { PolicyService } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction";
|
||||
import { PolicyType } from "@bitwarden/common/admin-console/enums";
|
||||
@@ -26,7 +27,6 @@ import { FolderView } from "@bitwarden/common/vault/models/view/folder.view";
|
||||
import { ServiceUtils } from "@bitwarden/common/vault/service-utils";
|
||||
import { COLLAPSED_GROUPINGS } from "@bitwarden/common/vault/services/key-state/collapsed-groupings.state";
|
||||
|
||||
import { CollectionAdminView } from "../../../core/views/collection-admin.view";
|
||||
import {
|
||||
CipherTypeFilter,
|
||||
CollectionFilter,
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
import { Unassigned } from "@bitwarden/admin-console/common";
|
||||
import { CipherType } from "@bitwarden/common/vault/enums";
|
||||
import { CipherView } from "@bitwarden/common/vault/models/view/cipher.view";
|
||||
|
||||
import { createFilterFunction } from "./filter-function";
|
||||
import { Unassigned, All } from "./routed-vault-filter.model";
|
||||
import { All } from "./routed-vault-filter.model";
|
||||
|
||||
describe("createFilter", () => {
|
||||
describe("given a generic cipher", () => {
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import { Unassigned } from "@bitwarden/admin-console/common";
|
||||
import { CipherType } from "@bitwarden/common/vault/enums";
|
||||
import { CipherView } from "@bitwarden/common/vault/models/view/cipher.view";
|
||||
|
||||
import { All, RoutedVaultFilterModel, Unassigned } from "./routed-vault-filter.model";
|
||||
import { All, RoutedVaultFilterModel } from "./routed-vault-filter.model";
|
||||
|
||||
export type FilterFunction = (cipher: CipherView) => boolean;
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { Unassigned } from "@bitwarden/admin-console/common";
|
||||
import { CipherType } from "@bitwarden/common/vault/enums";
|
||||
import { TreeNode } from "@bitwarden/common/vault/models/domain/tree-node";
|
||||
|
||||
@@ -8,7 +9,6 @@ import {
|
||||
isRoutedVaultFilterItemType,
|
||||
RoutedVaultFilterItemType,
|
||||
RoutedVaultFilterModel,
|
||||
Unassigned,
|
||||
} from "./routed-vault-filter.model";
|
||||
import { VaultFilter, VaultFilterFunction } from "./vault-filter.model";
|
||||
import {
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
export const Unassigned = "unassigned";
|
||||
|
||||
export const All = "all";
|
||||
|
||||
// TODO: Remove `All` when moving to vertical navigation.
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
import { CollectionAdminView } from "@bitwarden/admin-console/common";
|
||||
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
|
||||
import { FolderView } from "@bitwarden/common/src/vault/models/view/folder.view";
|
||||
import { CipherType } from "@bitwarden/common/vault/enums";
|
||||
import { ITreeNodeObject } from "@bitwarden/common/vault/models/domain/tree-node";
|
||||
|
||||
import { CollectionAdminView } from "../../../../core/views/collection-admin.view";
|
||||
|
||||
export type CipherStatus = "all" | "favorites" | "trash" | CipherType;
|
||||
|
||||
export type CipherTypeFilter = ITreeNodeObject & { type: CipherStatus; icon: string };
|
||||
|
||||
@@ -9,6 +9,7 @@ import {
|
||||
} from "@angular/core";
|
||||
import { firstValueFrom } from "rxjs";
|
||||
|
||||
import { Unassigned } from "@bitwarden/admin-console/common";
|
||||
import { JslibModule } from "@bitwarden/angular/jslib.module";
|
||||
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
|
||||
import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum";
|
||||
@@ -26,7 +27,6 @@ import { PipesModule } from "../pipes/pipes.module";
|
||||
import {
|
||||
All,
|
||||
RoutedVaultFilterModel,
|
||||
Unassigned,
|
||||
} from "../vault-filter/shared/models/routed-vault-filter.model";
|
||||
|
||||
@Component({
|
||||
|
||||
@@ -28,6 +28,7 @@ import {
|
||||
tap,
|
||||
} from "rxjs/operators";
|
||||
|
||||
import { Unassigned } from "@bitwarden/admin-console/common";
|
||||
import { SearchPipe } from "@bitwarden/angular/pipes/search.pipe";
|
||||
import { ModalService } from "@bitwarden/angular/services/modal.service";
|
||||
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
||||
@@ -118,7 +119,6 @@ import { createFilterFunction } from "./vault-filter/shared/models/filter-functi
|
||||
import {
|
||||
All,
|
||||
RoutedVaultFilterModel,
|
||||
Unassigned,
|
||||
} from "./vault-filter/shared/models/routed-vault-filter.model";
|
||||
import { VaultFilter } from "./vault-filter/shared/models/vault-filter.model";
|
||||
import { FolderFilter, OrganizationFilter } from "./vault-filter/shared/models/vault-filter.type";
|
||||
|
||||
@@ -3,7 +3,10 @@ import { Component, Inject, OnDestroy } from "@angular/core";
|
||||
import { FormBuilder } from "@angular/forms";
|
||||
import { combineLatest, of, Subject, switchMap, takeUntil } from "rxjs";
|
||||
|
||||
import { OrganizationUserApiService } from "@bitwarden/admin-console/common";
|
||||
import {
|
||||
CollectionAdminService,
|
||||
OrganizationUserApiService,
|
||||
} from "@bitwarden/admin-console/common";
|
||||
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
||||
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
|
||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||
@@ -23,7 +26,6 @@ import {
|
||||
PermissionMode,
|
||||
} from "../../../admin-console/organizations/shared/components/access-selector";
|
||||
import { SharedModule } from "../../../shared";
|
||||
import { CollectionAdminService } from "../../core/collection-admin.service";
|
||||
|
||||
export interface BulkCollectionsDialogParams {
|
||||
organizationId: string;
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { Injectable, OnDestroy } from "@angular/core";
|
||||
import { map, Observable, ReplaySubject, Subject } from "rxjs";
|
||||
|
||||
import { CollectionAdminView } from "@bitwarden/admin-console/common";
|
||||
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
||||
import { PolicyService } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction";
|
||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||
@@ -10,7 +11,6 @@ import { CollectionService } from "@bitwarden/common/vault/abstractions/collecti
|
||||
import { FolderService } from "@bitwarden/common/vault/abstractions/folder/folder.service.abstraction";
|
||||
import { TreeNode } from "@bitwarden/common/vault/models/domain/tree-node";
|
||||
|
||||
import { CollectionAdminView } from "../../../vault/core/views/collection-admin.view";
|
||||
import { VaultFilterService as BaseVaultFilterService } from "../../individual-vault/vault-filter/services/vault-filter.service";
|
||||
import { CollectionFilter } from "../../individual-vault/vault-filter/shared/models/vault-filter.type";
|
||||
|
||||
|
||||
@@ -3,6 +3,11 @@ import { Component, EventEmitter, Input, OnInit, Output } from "@angular/core";
|
||||
import { Router } from "@angular/router";
|
||||
import { firstValueFrom } from "rxjs";
|
||||
|
||||
import {
|
||||
CollectionAdminService,
|
||||
CollectionAdminView,
|
||||
Unassigned,
|
||||
} from "@bitwarden/admin-console/common";
|
||||
import { JslibModule } from "@bitwarden/angular/jslib.module";
|
||||
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
||||
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
|
||||
@@ -22,13 +27,10 @@ import {
|
||||
|
||||
import { HeaderModule } from "../../../layouts/header/header.module";
|
||||
import { SharedModule } from "../../../shared";
|
||||
import { CollectionAdminView } from "../../../vault/core/views/collection-admin.view";
|
||||
import { CollectionDialogTabType } from "../../components/collection-dialog";
|
||||
import { CollectionAdminService } from "../../core/collection-admin.service";
|
||||
import {
|
||||
All,
|
||||
RoutedVaultFilterModel,
|
||||
Unassigned,
|
||||
} from "../../individual-vault/vault-filter/shared/models/routed-vault-filter.model";
|
||||
|
||||
@Component({
|
||||
|
||||
@@ -30,6 +30,11 @@ import {
|
||||
withLatestFrom,
|
||||
} from "rxjs/operators";
|
||||
|
||||
import {
|
||||
CollectionAdminService,
|
||||
CollectionAdminView,
|
||||
Unassigned,
|
||||
} from "@bitwarden/admin-console/common";
|
||||
import { SearchPipe } from "@bitwarden/angular/pipes/search.pipe";
|
||||
import { ModalService } from "@bitwarden/angular/services/modal.service";
|
||||
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
||||
@@ -72,8 +77,6 @@ import {
|
||||
} from "../components/collection-dialog";
|
||||
import { VaultItemEvent } from "../components/vault-items/vault-item-event";
|
||||
import { VaultItemsModule } from "../components/vault-items/vault-items.module";
|
||||
import { CollectionAdminService } from "../core/collection-admin.service";
|
||||
import { CollectionAdminView } from "../core/views/collection-admin.view";
|
||||
import {
|
||||
BulkDeleteDialogResult,
|
||||
openBulkDeleteDialog,
|
||||
@@ -85,7 +88,6 @@ import { createFilterFunction } from "../individual-vault/vault-filter/shared/mo
|
||||
import {
|
||||
All,
|
||||
RoutedVaultFilterModel,
|
||||
Unassigned,
|
||||
} from "../individual-vault/vault-filter/shared/models/routed-vault-filter.model";
|
||||
import {
|
||||
openViewCipherDialog,
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { CollectionAdminView } from "@bitwarden/admin-console/common";
|
||||
import { TreeNode } from "@bitwarden/common/vault/models/domain/tree-node";
|
||||
import {
|
||||
CollectionView,
|
||||
@@ -5,8 +6,6 @@ import {
|
||||
} from "@bitwarden/common/vault/models/view/collection.view";
|
||||
import { ServiceUtils } from "@bitwarden/common/vault/service-utils";
|
||||
|
||||
import { CollectionAdminView } from "../../vault/core/views/collection-admin.view";
|
||||
|
||||
export function getNestedCollectionTree(
|
||||
collections: CollectionAdminView[],
|
||||
): TreeNode<CollectionAdminView>[];
|
||||
|
||||
@@ -1099,8 +1099,11 @@
|
||||
"yourVaultIsLockedV2": {
|
||||
"message": "Your vault is locked"
|
||||
},
|
||||
"uuid": {
|
||||
"message": "UUID"
|
||||
"yourAccountIsLocked": {
|
||||
"message": "Your account is locked"
|
||||
},
|
||||
"uuid":{
|
||||
"message" : "UUID"
|
||||
},
|
||||
"unlock": {
|
||||
"message": "Unlock"
|
||||
@@ -2564,6 +2567,9 @@
|
||||
"downloadLicense": {
|
||||
"message": "Download license"
|
||||
},
|
||||
"viewBillingToken": {
|
||||
"message": "View Billing Token"
|
||||
},
|
||||
"updateLicense": {
|
||||
"message": "Update license"
|
||||
},
|
||||
@@ -3169,6 +3175,10 @@
|
||||
"incorrectPin": {
|
||||
"message": "Incorrect PIN"
|
||||
},
|
||||
"pin": {
|
||||
"message": "PIN",
|
||||
"description": "PIN code. Ex. The short code (often numeric) that you use to unlock a device."
|
||||
},
|
||||
"exportedVault": {
|
||||
"message": "Vault exported"
|
||||
},
|
||||
@@ -5994,8 +6004,8 @@
|
||||
"viewBillingSyncToken": {
|
||||
"message": "View billing sync token"
|
||||
},
|
||||
"generateBillingSyncToken": {
|
||||
"message": "Generate billing sync token"
|
||||
"generateBillingToken": {
|
||||
"message": "Generate billing token"
|
||||
},
|
||||
"copyPasteBillingSync": {
|
||||
"message": "Copy and paste this token into the billing sync settings of your self-hosted organization."
|
||||
@@ -6003,8 +6013,8 @@
|
||||
"billingSyncCanAccess": {
|
||||
"message": "Your billing sync token can access and edit this organization's subscription settings."
|
||||
},
|
||||
"manageBillingSync": {
|
||||
"message": "Manage billing sync"
|
||||
"manageBillingTokenSync": {
|
||||
"message": "Manage Billing Token"
|
||||
},
|
||||
"setUpBillingSync": {
|
||||
"message": "Set up billing sync"
|
||||
@@ -6063,15 +6073,15 @@
|
||||
"billingSyncApiKeyRotated": {
|
||||
"message": "Token rotated"
|
||||
},
|
||||
"billingSyncDesc": {
|
||||
"message": "Billing sync unlocks Families sponsorships and automatic license syncing on your server. After making updates in the Bitwarden cloud server, select Sync License to apply changes."
|
||||
},
|
||||
"billingSyncKeyDesc": {
|
||||
"message": "A billing sync token from your cloud organization's subscription settings is required to complete this form."
|
||||
},
|
||||
"billingSyncKey": {
|
||||
"message": "Billing sync token"
|
||||
},
|
||||
"automaticBillingSyncDesc": {
|
||||
"message": "Automatic sync unlocks Families sponsorships and allows you to sync your license without uploading a file. After making updates in the Bitwarden cloud server, select Sync License to apply changes."
|
||||
},
|
||||
"active": {
|
||||
"message": "Active"
|
||||
},
|
||||
@@ -7463,6 +7473,15 @@
|
||||
"or": {
|
||||
"message": "or"
|
||||
},
|
||||
"unlockWithBiometrics": {
|
||||
"message": "Unlock with biometrics"
|
||||
},
|
||||
"unlockWithPin": {
|
||||
"message": "Unlock with PIN"
|
||||
},
|
||||
"unlockWithMasterPassword": {
|
||||
"message": "Unlock with master password"
|
||||
},
|
||||
"licenseAndBillingManagement": {
|
||||
"message": "License and billing management"
|
||||
},
|
||||
@@ -7472,11 +7491,11 @@
|
||||
"manualUpload": {
|
||||
"message": "Manual upload"
|
||||
},
|
||||
"manualUploadDesc": {
|
||||
"message": "If you do not want to opt into billing sync, manually upload your license here."
|
||||
"manualBillingTokenUploadDesc": {
|
||||
"message": "If you do not want to opt into billing sync, manually upload your license here. This will not automatically unlock Families sponsorships."
|
||||
},
|
||||
"syncLicense": {
|
||||
"message": "Sync license"
|
||||
"message": "Sync License"
|
||||
},
|
||||
"licenseSyncSuccess": {
|
||||
"message": "Successfully synced license"
|
||||
|
||||
Reference in New Issue
Block a user