mirror of
https://github.com/bitwarden/browser
synced 2025-12-16 08:13:42 +00:00
[AC-1139] Fix canDelete logic in
collection-dialog.component.ts and bulk-delete-dialog.component.ts
This commit is contained in:
@@ -72,7 +72,7 @@ export enum CollectionDialogAction {
|
|||||||
export class CollectionDialogComponent implements OnInit, OnDestroy {
|
export class CollectionDialogComponent implements OnInit, OnDestroy {
|
||||||
protected flexibleCollectionsEnabled$ = this.configService.getFeatureFlag$(
|
protected flexibleCollectionsEnabled$ = this.configService.getFeatureFlag$(
|
||||||
FeatureFlag.FlexibleCollections,
|
FeatureFlag.FlexibleCollections,
|
||||||
false
|
false,
|
||||||
);
|
);
|
||||||
|
|
||||||
private destroy$ = new Subject<void>();
|
private destroy$ = new Subject<void>();
|
||||||
@@ -107,7 +107,7 @@ export class CollectionDialogComponent implements OnInit, OnDestroy {
|
|||||||
private organizationUserService: OrganizationUserService,
|
private organizationUserService: OrganizationUserService,
|
||||||
private dialogService: DialogService,
|
private dialogService: DialogService,
|
||||||
private changeDetectorRef: ChangeDetectorRef,
|
private changeDetectorRef: ChangeDetectorRef,
|
||||||
private configService: ConfigServiceAbstraction
|
private configService: ConfigServiceAbstraction,
|
||||||
) {
|
) {
|
||||||
this.tabIndex = params.initialTab ?? CollectionDialogTabType.Info;
|
this.tabIndex = params.initialTab ?? CollectionDialogTabType.Info;
|
||||||
}
|
}
|
||||||
@@ -123,8 +123,8 @@ export class CollectionDialogComponent implements OnInit, OnDestroy {
|
|||||||
map((orgs) =>
|
map((orgs) =>
|
||||||
orgs
|
orgs
|
||||||
.filter((o) => o.canCreateNewCollections && !o.isProviderUser)
|
.filter((o) => o.canCreateNewCollections && !o.isProviderUser)
|
||||||
.sort(Utils.getSortFunction(this.i18nService, "name"))
|
.sort(Utils.getSortFunction(this.i18nService, "name")),
|
||||||
)
|
),
|
||||||
);
|
);
|
||||||
// patchValue will trigger a call to loadOrg() in this case, so no need to call it again here
|
// patchValue will trigger a call to loadOrg() in this case, so no need to call it again here
|
||||||
this.formGroup.patchValue({ selectedOrg: this.params.organizationId });
|
this.formGroup.patchValue({ selectedOrg: this.params.organizationId });
|
||||||
@@ -141,7 +141,7 @@ export class CollectionDialogComponent implements OnInit, OnDestroy {
|
|||||||
|
|
||||||
async loadOrg(orgId: string, collectionIds: string[]) {
|
async loadOrg(orgId: string, collectionIds: string[]) {
|
||||||
const organization$ = of(this.organizationService.get(orgId)).pipe(
|
const organization$ = of(this.organizationService.get(orgId)).pipe(
|
||||||
shareReplay({ refCount: true, bufferSize: 1 })
|
shareReplay({ refCount: true, bufferSize: 1 }),
|
||||||
);
|
);
|
||||||
const groups$ = organization$.pipe(
|
const groups$ = organization$.pipe(
|
||||||
switchMap((organization) => {
|
switchMap((organization) => {
|
||||||
@@ -150,7 +150,7 @@ export class CollectionDialogComponent implements OnInit, OnDestroy {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return this.groupService.getAll(orgId);
|
return this.groupService.getAll(orgId);
|
||||||
})
|
}),
|
||||||
);
|
);
|
||||||
combineLatest({
|
combineLatest({
|
||||||
organization: organization$,
|
organization: organization$,
|
||||||
@@ -168,7 +168,7 @@ export class CollectionDialogComponent implements OnInit, OnDestroy {
|
|||||||
this.organization = organization;
|
this.organization = organization;
|
||||||
this.accessItems = [].concat(
|
this.accessItems = [].concat(
|
||||||
groups.map(mapGroupToAccessItemView),
|
groups.map(mapGroupToAccessItemView),
|
||||||
users.data.map(mapUserToAccessItemView)
|
users.data.map(mapUserToAccessItemView),
|
||||||
);
|
);
|
||||||
|
|
||||||
// Force change detection to update the access selector's items
|
// Force change detection to update the access selector's items
|
||||||
@@ -201,9 +201,8 @@ export class CollectionDialogComponent implements OnInit, OnDestroy {
|
|||||||
} else {
|
} else {
|
||||||
this.nestOptions = collections;
|
this.nestOptions = collections;
|
||||||
const parent = collections.find((c) => c.id === this.params.parentCollectionId);
|
const parent = collections.find((c) => c.id === this.params.parentCollectionId);
|
||||||
const currentOrgUserId = users.data.find(
|
const currentOrgUserId = users.data.find((u) => u.userId === this.organization?.userId)
|
||||||
(u) => u.userId === this.organization?.userId
|
?.id;
|
||||||
)?.id;
|
|
||||||
const initialSelection: AccessItemValue[] =
|
const initialSelection: AccessItemValue[] =
|
||||||
currentOrgUserId !== undefined
|
currentOrgUserId !== undefined
|
||||||
? [
|
? [
|
||||||
@@ -224,7 +223,7 @@ export class CollectionDialogComponent implements OnInit, OnDestroy {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.loading = false;
|
this.loading = false;
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -250,13 +249,13 @@ export class CollectionDialogComponent implements OnInit, OnDestroy {
|
|||||||
this.platformUtilsService.showToast(
|
this.platformUtilsService.showToast(
|
||||||
"error",
|
"error",
|
||||||
null,
|
null,
|
||||||
this.i18nService.t("fieldOnTabRequiresAttention", this.i18nService.t("collectionInfo"))
|
this.i18nService.t("fieldOnTabRequiresAttention", this.i18nService.t("collectionInfo")),
|
||||||
);
|
);
|
||||||
} else if (this.tabIndex === CollectionDialogTabType.Info && accessTabError) {
|
} else if (this.tabIndex === CollectionDialogTabType.Info && accessTabError) {
|
||||||
this.platformUtilsService.showToast(
|
this.platformUtilsService.showToast(
|
||||||
"error",
|
"error",
|
||||||
null,
|
null,
|
||||||
this.i18nService.t("fieldOnTabRequiresAttention", this.i18nService.t("access"))
|
this.i18nService.t("fieldOnTabRequiresAttention", this.i18nService.t("access")),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
@@ -287,8 +286,8 @@ export class CollectionDialogComponent implements OnInit, OnDestroy {
|
|||||||
null,
|
null,
|
||||||
this.i18nService.t(
|
this.i18nService.t(
|
||||||
this.editMode ? "editedCollectionId" : "createdCollectionId",
|
this.editMode ? "editedCollectionId" : "createdCollectionId",
|
||||||
collectionView.name
|
collectionView.name,
|
||||||
)
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
this.close(CollectionDialogAction.Saved, savedCollection);
|
this.close(CollectionDialogAction.Saved, savedCollection);
|
||||||
@@ -310,18 +309,17 @@ export class CollectionDialogComponent implements OnInit, OnDestroy {
|
|||||||
this.platformUtilsService.showToast(
|
this.platformUtilsService.showToast(
|
||||||
"success",
|
"success",
|
||||||
null,
|
null,
|
||||||
this.i18nService.t("deletedCollectionId", this.collection?.name)
|
this.i18nService.t("deletedCollectionId", this.collection?.name),
|
||||||
);
|
);
|
||||||
|
|
||||||
this.close(CollectionDialogAction.Deleted, this.collection);
|
this.close(CollectionDialogAction.Deleted, this.collection);
|
||||||
};
|
};
|
||||||
|
|
||||||
protected canDelete$ = this.flexibleCollectionsEnabled$.pipe(
|
protected canDelete$ = this.flexibleCollectionsEnabled$.pipe(
|
||||||
switchMap(async (flexibleCollectionsEnabled) => {
|
map(
|
||||||
return (
|
(flexibleCollectionsEnabled) =>
|
||||||
this.editMode && this.collection.canDelete(this.organization, flexibleCollectionsEnabled)
|
this.editMode && this.collection.canDelete(this.organization, flexibleCollectionsEnabled),
|
||||||
);
|
),
|
||||||
})
|
|
||||||
);
|
);
|
||||||
|
|
||||||
ngOnDestroy(): void {
|
ngOnDestroy(): void {
|
||||||
@@ -356,7 +354,7 @@ function mapToAccessSelections(collectionDetails: CollectionAdminView): AccessIt
|
|||||||
id: selection.id,
|
id: selection.id,
|
||||||
type: AccessItemType.Member,
|
type: AccessItemType.Member,
|
||||||
permission: convertToPermission(selection),
|
permission: convertToPermission(selection),
|
||||||
}))
|
})),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -377,10 +375,10 @@ function validateCanManagePermission(control: AbstractControl) {
|
|||||||
*/
|
*/
|
||||||
export function openCollectionDialog(
|
export function openCollectionDialog(
|
||||||
dialogService: DialogService,
|
dialogService: DialogService,
|
||||||
config: DialogConfig<CollectionDialogParams>
|
config: DialogConfig<CollectionDialogParams>,
|
||||||
) {
|
) {
|
||||||
return dialogService.open<CollectionDialogResult, CollectionDialogParams>(
|
return dialogService.open<CollectionDialogResult, CollectionDialogParams>(
|
||||||
CollectionDialogComponent,
|
CollectionDialogComponent,
|
||||||
config
|
config,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,11 +34,11 @@ export enum BulkDeleteDialogResult {
|
|||||||
*/
|
*/
|
||||||
export const openBulkDeleteDialog = (
|
export const openBulkDeleteDialog = (
|
||||||
dialogService: DialogService,
|
dialogService: DialogService,
|
||||||
config: DialogConfig<BulkDeleteDialogParams>
|
config: DialogConfig<BulkDeleteDialogParams>,
|
||||||
) => {
|
) => {
|
||||||
return dialogService.open<BulkDeleteDialogResult, BulkDeleteDialogParams>(
|
return dialogService.open<BulkDeleteDialogResult, BulkDeleteDialogParams>(
|
||||||
BulkDeleteDialogComponent,
|
BulkDeleteDialogComponent,
|
||||||
config
|
config,
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -61,7 +61,7 @@ export class BulkDeleteDialogComponent {
|
|||||||
private i18nService: I18nService,
|
private i18nService: I18nService,
|
||||||
private apiService: ApiService,
|
private apiService: ApiService,
|
||||||
private collectionService: CollectionService,
|
private collectionService: CollectionService,
|
||||||
private configService: ConfigServiceAbstraction
|
private configService: ConfigServiceAbstraction,
|
||||||
) {
|
) {
|
||||||
this.cipherIds = params.cipherIds ?? [];
|
this.cipherIds = params.cipherIds ?? [];
|
||||||
this.collectionIds = params.collectionIds ?? [];
|
this.collectionIds = params.collectionIds ?? [];
|
||||||
@@ -95,7 +95,7 @@ export class BulkDeleteDialogComponent {
|
|||||||
this.platformUtilsService.showToast(
|
this.platformUtilsService.showToast(
|
||||||
"success",
|
"success",
|
||||||
null,
|
null,
|
||||||
this.i18nService.t(this.permanent ? "permanentlyDeletedItems" : "deletedItems")
|
this.i18nService.t(this.permanent ? "permanentlyDeletedItems" : "deletedItems"),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (this.collectionIds.length) {
|
if (this.collectionIds.length) {
|
||||||
@@ -103,7 +103,7 @@ export class BulkDeleteDialogComponent {
|
|||||||
this.platformUtilsService.showToast(
|
this.platformUtilsService.showToast(
|
||||||
"success",
|
"success",
|
||||||
null,
|
null,
|
||||||
this.i18nService.t("deletedCollections")
|
this.i18nService.t("deletedCollections"),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
this.close(BulkDeleteDialogResult.Deleted);
|
this.close(BulkDeleteDialogResult.Deleted);
|
||||||
@@ -130,20 +130,17 @@ export class BulkDeleteDialogComponent {
|
|||||||
private async deleteCollections(): Promise<any> {
|
private async deleteCollections(): Promise<any> {
|
||||||
const flexibleCollectionsEnabled = await this.configService.getFeatureFlag(
|
const flexibleCollectionsEnabled = await this.configService.getFeatureFlag(
|
||||||
FeatureFlag.FlexibleCollections,
|
FeatureFlag.FlexibleCollections,
|
||||||
false
|
false,
|
||||||
);
|
);
|
||||||
// From org vault
|
// From org vault
|
||||||
if (this.organization) {
|
if (this.organization) {
|
||||||
if (
|
if (
|
||||||
(flexibleCollectionsEnabled
|
this.collections.some((c) => !c.canDelete(this.organization, flexibleCollectionsEnabled))
|
||||||
? this.collections.some((c) => !c.canDelete)
|
|
||||||
: !this.organization.canDeleteAssignedCollections) &&
|
|
||||||
!this.organization.canDeleteAnyCollection
|
|
||||||
) {
|
) {
|
||||||
this.platformUtilsService.showToast(
|
this.platformUtilsService.showToast(
|
||||||
"error",
|
"error",
|
||||||
this.i18nService.t("errorOccurred"),
|
this.i18nService.t("errorOccurred"),
|
||||||
this.i18nService.t("missingPermissions")
|
this.i18nService.t("missingPermissions"),
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -152,16 +149,11 @@ export class BulkDeleteDialogComponent {
|
|||||||
} else if (this.organizations && this.collections) {
|
} else if (this.organizations && this.collections) {
|
||||||
const deletePromises: Promise<any>[] = [];
|
const deletePromises: Promise<any>[] = [];
|
||||||
for (const organization of this.organizations) {
|
for (const organization of this.organizations) {
|
||||||
if (
|
if (this.collections.some((c) => !c.canDelete(organization, flexibleCollectionsEnabled))) {
|
||||||
(flexibleCollectionsEnabled
|
|
||||||
? this.collections.some((c) => !c.canDelete)
|
|
||||||
: !this.organization.canDeleteAssignedCollections) &&
|
|
||||||
!organization.canDeleteAnyCollection
|
|
||||||
) {
|
|
||||||
this.platformUtilsService.showToast(
|
this.platformUtilsService.showToast(
|
||||||
"error",
|
"error",
|
||||||
this.i18nService.t("errorOccurred"),
|
this.i18nService.t("errorOccurred"),
|
||||||
this.i18nService.t("missingPermissions")
|
this.i18nService.t("missingPermissions"),
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -169,7 +161,7 @@ export class BulkDeleteDialogComponent {
|
|||||||
.filter((o) => o.organizationId === organization.id)
|
.filter((o) => o.organizationId === organization.id)
|
||||||
.map((c) => c.id);
|
.map((c) => c.id);
|
||||||
deletePromises.push(
|
deletePromises.push(
|
||||||
this.apiService.deleteManyCollections(this.organization.id, orgCollections)
|
this.apiService.deleteManyCollections(this.organization.id, orgCollections),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return await Promise.all(deletePromises);
|
return await Promise.all(deletePromises);
|
||||||
|
|||||||
@@ -147,7 +147,7 @@ export class VaultComponent implements OnInit, OnDestroy {
|
|||||||
protected currentSearchText$: Observable<string>;
|
protected currentSearchText$: Observable<string>;
|
||||||
protected showBulkCollectionAccess$ = this.configService.getFeatureFlag$(
|
protected showBulkCollectionAccess$ = this.configService.getFeatureFlag$(
|
||||||
FeatureFlag.BulkCollectionAccess,
|
FeatureFlag.BulkCollectionAccess,
|
||||||
false
|
false,
|
||||||
);
|
);
|
||||||
|
|
||||||
private searchText$ = new Subject<string>();
|
private searchText$ = new Subject<string>();
|
||||||
@@ -183,7 +183,7 @@ export class VaultComponent implements OnInit, OnDestroy {
|
|||||||
private searchPipe: SearchPipe,
|
private searchPipe: SearchPipe,
|
||||||
private configService: ConfigServiceAbstraction,
|
private configService: ConfigServiceAbstraction,
|
||||||
private apiService: ApiService,
|
private apiService: ApiService,
|
||||||
private userVerificationService: UserVerificationService
|
private userVerificationService: UserVerificationService,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
async ngOnInit() {
|
async ngOnInit() {
|
||||||
@@ -191,7 +191,7 @@ export class VaultComponent implements OnInit, OnDestroy {
|
|||||||
this.trashCleanupWarning = this.i18nService.t(
|
this.trashCleanupWarning = this.i18nService.t(
|
||||||
this.platformUtilsService.isSelfHost()
|
this.platformUtilsService.isSelfHost()
|
||||||
? "trashCleanupWarningSelfHosted"
|
? "trashCleanupWarningSelfHosted"
|
||||||
: "trashCleanupWarning"
|
: "trashCleanupWarning",
|
||||||
);
|
);
|
||||||
|
|
||||||
const firstSetup$ = this.route.queryParams.pipe(
|
const firstSetup$ = this.route.queryParams.pipe(
|
||||||
@@ -219,7 +219,7 @@ export class VaultComponent implements OnInit, OnDestroy {
|
|||||||
await this.editCipher(cipherView);
|
await this.editCipher(cipherView);
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
shareReplay({ refCount: true, bufferSize: 1 })
|
shareReplay({ refCount: true, bufferSize: 1 }),
|
||||||
);
|
);
|
||||||
|
|
||||||
this.broadcasterService.subscribe(BroadcasterSubscriptionId, (message: any) => {
|
this.broadcasterService.subscribe(BroadcasterSubscriptionId, (message: any) => {
|
||||||
@@ -243,11 +243,11 @@ export class VaultComponent implements OnInit, OnDestroy {
|
|||||||
|
|
||||||
const filter$ = this.routedVaultFilterService.filter$;
|
const filter$ = this.routedVaultFilterService.filter$;
|
||||||
const canAccessPremium$ = Utils.asyncToObservable(() =>
|
const canAccessPremium$ = Utils.asyncToObservable(() =>
|
||||||
this.stateService.getCanAccessPremium()
|
this.stateService.getCanAccessPremium(),
|
||||||
).pipe(shareReplay({ refCount: true, bufferSize: 1 }));
|
).pipe(shareReplay({ refCount: true, bufferSize: 1 }));
|
||||||
const allCollections$ = Utils.asyncToObservable(() => this.collectionService.getAllDecrypted());
|
const allCollections$ = Utils.asyncToObservable(() => this.collectionService.getAllDecrypted());
|
||||||
const nestedCollections$ = allCollections$.pipe(
|
const nestedCollections$ = allCollections$.pipe(
|
||||||
map((collections) => getNestedCollectionTree(collections))
|
map((collections) => getNestedCollectionTree(collections)),
|
||||||
);
|
);
|
||||||
|
|
||||||
this.searchText$
|
this.searchText$
|
||||||
@@ -257,7 +257,7 @@ export class VaultComponent implements OnInit, OnDestroy {
|
|||||||
queryParams: { search: Utils.isNullOrEmpty(searchText) ? null : searchText },
|
queryParams: { search: Utils.isNullOrEmpty(searchText) ? null : searchText },
|
||||||
queryParamsHandling: "merge",
|
queryParamsHandling: "merge",
|
||||||
replaceUrl: true,
|
replaceUrl: true,
|
||||||
})
|
}),
|
||||||
);
|
);
|
||||||
|
|
||||||
this.currentSearchText$ = this.route.queryParams.pipe(map((queryParams) => queryParams.search));
|
this.currentSearchText$ = this.route.queryParams.pipe(map((queryParams) => queryParams.search));
|
||||||
@@ -277,7 +277,7 @@ export class VaultComponent implements OnInit, OnDestroy {
|
|||||||
|
|
||||||
return ciphers.filter(filterFunction);
|
return ciphers.filter(filterFunction);
|
||||||
}),
|
}),
|
||||||
shareReplay({ refCount: true, bufferSize: 1 })
|
shareReplay({ refCount: true, bufferSize: 1 }),
|
||||||
);
|
);
|
||||||
|
|
||||||
const collections$ = combineLatest([nestedCollections$, filter$, this.currentSearchText$]).pipe(
|
const collections$ = combineLatest([nestedCollections$, filter$, this.currentSearchText$]).pipe(
|
||||||
@@ -297,7 +297,7 @@ export class VaultComponent implements OnInit, OnDestroy {
|
|||||||
} else {
|
} else {
|
||||||
const selectedCollection = ServiceUtils.getTreeNodeObjectFromList(
|
const selectedCollection = ServiceUtils.getTreeNodeObjectFromList(
|
||||||
collections,
|
collections,
|
||||||
filter.collectionId
|
filter.collectionId,
|
||||||
);
|
);
|
||||||
collectionsToReturn = selectedCollection?.children.map((c) => c.node) ?? [];
|
collectionsToReturn = selectedCollection?.children.map((c) => c.node) ?? [];
|
||||||
}
|
}
|
||||||
@@ -307,13 +307,13 @@ export class VaultComponent implements OnInit, OnDestroy {
|
|||||||
collectionsToReturn,
|
collectionsToReturn,
|
||||||
searchText,
|
searchText,
|
||||||
(collection) => collection.name,
|
(collection) => collection.name,
|
||||||
(collection) => collection.id
|
(collection) => collection.id,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return collectionsToReturn;
|
return collectionsToReturn;
|
||||||
}),
|
}),
|
||||||
shareReplay({ refCount: true, bufferSize: 1 })
|
shareReplay({ refCount: true, bufferSize: 1 }),
|
||||||
);
|
);
|
||||||
|
|
||||||
const selectedCollection$ = combineLatest([nestedCollections$, filter$]).pipe(
|
const selectedCollection$ = combineLatest([nestedCollections$, filter$]).pipe(
|
||||||
@@ -329,7 +329,7 @@ export class VaultComponent implements OnInit, OnDestroy {
|
|||||||
|
|
||||||
return ServiceUtils.getTreeNodeObjectFromList(collections, filter.collectionId);
|
return ServiceUtils.getTreeNodeObjectFromList(collections, filter.collectionId);
|
||||||
}),
|
}),
|
||||||
shareReplay({ refCount: true, bufferSize: 1 })
|
shareReplay({ refCount: true, bufferSize: 1 }),
|
||||||
);
|
);
|
||||||
|
|
||||||
firstSetup$
|
firstSetup$
|
||||||
@@ -344,7 +344,7 @@ export class VaultComponent implements OnInit, OnDestroy {
|
|||||||
this.platformUtilsService.showToast(
|
this.platformUtilsService.showToast(
|
||||||
"error",
|
"error",
|
||||||
this.i18nService.t("errorOccurred"),
|
this.i18nService.t("errorOccurred"),
|
||||||
this.i18nService.t("unknownCipher")
|
this.i18nService.t("unknownCipher"),
|
||||||
);
|
);
|
||||||
this.router.navigate([], {
|
this.router.navigate([], {
|
||||||
queryParams: { itemId: null, cipherId: null },
|
queryParams: { itemId: null, cipherId: null },
|
||||||
@@ -353,7 +353,7 @@ export class VaultComponent implements OnInit, OnDestroy {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
takeUntil(this.destroy$)
|
takeUntil(this.destroy$),
|
||||||
)
|
)
|
||||||
.subscribe();
|
.subscribe();
|
||||||
|
|
||||||
@@ -370,9 +370,9 @@ export class VaultComponent implements OnInit, OnDestroy {
|
|||||||
ciphers$,
|
ciphers$,
|
||||||
collections$,
|
collections$,
|
||||||
selectedCollection$,
|
selectedCollection$,
|
||||||
])
|
]),
|
||||||
),
|
),
|
||||||
takeUntil(this.destroy$)
|
takeUntil(this.destroy$),
|
||||||
)
|
)
|
||||||
.subscribe(
|
.subscribe(
|
||||||
([
|
([
|
||||||
@@ -393,7 +393,7 @@ export class VaultComponent implements OnInit, OnDestroy {
|
|||||||
this.selectedCollection = selectedCollection;
|
this.selectedCollection = selectedCollection;
|
||||||
|
|
||||||
this.canCreateCollections = allOrganizations?.some(
|
this.canCreateCollections = allOrganizations?.some(
|
||||||
(o) => o.canCreateNewCollections && !o.isProviderUser
|
(o) => o.canCreateNewCollections && !o.isProviderUser,
|
||||||
);
|
);
|
||||||
|
|
||||||
this.showBulkMove =
|
this.showBulkMove =
|
||||||
@@ -407,7 +407,7 @@ export class VaultComponent implements OnInit, OnDestroy {
|
|||||||
|
|
||||||
this.performingInitialLoad = false;
|
this.performingInitialLoad = false;
|
||||||
this.refreshing = false;
|
this.refreshing = false;
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -534,7 +534,7 @@ export class VaultComponent implements OnInit, OnDestroy {
|
|||||||
comp.onReuploadedAttachment
|
comp.onReuploadedAttachment
|
||||||
.pipe(takeUntil(this.destroy$))
|
.pipe(takeUntil(this.destroy$))
|
||||||
.subscribe(() => (madeAttachmentChanges = true));
|
.subscribe(() => (madeAttachmentChanges = true));
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
modal.onClosed.pipe(takeUntil(this.destroy$)).subscribe(() => {
|
modal.onClosed.pipe(takeUntil(this.destroy$)).subscribe(() => {
|
||||||
@@ -559,7 +559,7 @@ export class VaultComponent implements OnInit, OnDestroy {
|
|||||||
modal.close();
|
modal.close();
|
||||||
this.refresh();
|
this.refresh();
|
||||||
});
|
});
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -573,7 +573,7 @@ export class VaultComponent implements OnInit, OnDestroy {
|
|||||||
modal.close();
|
modal.close();
|
||||||
this.refresh();
|
this.refresh();
|
||||||
});
|
});
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -589,7 +589,7 @@ export class VaultComponent implements OnInit, OnDestroy {
|
|||||||
const selectedColId = this.activeFilter.collectionId;
|
const selectedColId = this.activeFilter.collectionId;
|
||||||
if (selectedColId !== "AllCollections") {
|
if (selectedColId !== "AllCollections") {
|
||||||
component.organizationId = component.collections.find(
|
component.organizationId = component.collections.find(
|
||||||
(collection) => collection.id === selectedColId
|
(collection) => collection.id === selectedColId,
|
||||||
)?.organizationId;
|
)?.organizationId;
|
||||||
component.collectionIds = [selectedColId];
|
component.collectionIds = [selectedColId];
|
||||||
}
|
}
|
||||||
@@ -635,7 +635,7 @@ export class VaultComponent implements OnInit, OnDestroy {
|
|||||||
modal.close();
|
modal.close();
|
||||||
this.refresh();
|
this.refresh();
|
||||||
});
|
});
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
modal.onClosedPromise().then(() => {
|
modal.onClosedPromise().then(() => {
|
||||||
@@ -690,16 +690,13 @@ export class VaultComponent implements OnInit, OnDestroy {
|
|||||||
const organization = this.organizationService.get(collection.organizationId);
|
const organization = this.organizationService.get(collection.organizationId);
|
||||||
const flexibleCollectionsEnabled = await this.configService.getFeatureFlag(
|
const flexibleCollectionsEnabled = await this.configService.getFeatureFlag(
|
||||||
FeatureFlag.FlexibleCollections,
|
FeatureFlag.FlexibleCollections,
|
||||||
false
|
false,
|
||||||
);
|
);
|
||||||
if (
|
if (collection.canDelete(organization, flexibleCollectionsEnabled)) {
|
||||||
(flexibleCollectionsEnabled || !organization.canDeleteAssignedCollections) &&
|
|
||||||
!organization.canDeleteAnyCollection
|
|
||||||
) {
|
|
||||||
this.platformUtilsService.showToast(
|
this.platformUtilsService.showToast(
|
||||||
"error",
|
"error",
|
||||||
this.i18nService.t("errorOccurred"),
|
this.i18nService.t("errorOccurred"),
|
||||||
this.i18nService.t("missingPermissions")
|
this.i18nService.t("missingPermissions"),
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -717,7 +714,7 @@ export class VaultComponent implements OnInit, OnDestroy {
|
|||||||
this.platformUtilsService.showToast(
|
this.platformUtilsService.showToast(
|
||||||
"success",
|
"success",
|
||||||
null,
|
null,
|
||||||
this.i18nService.t("deletedCollectionId", collection.name)
|
this.i18nService.t("deletedCollectionId", collection.name),
|
||||||
);
|
);
|
||||||
// Navigate away if we deleted the collection we were viewing
|
// Navigate away if we deleted the collection we were viewing
|
||||||
if (this.selectedCollection?.node.id === collection.id) {
|
if (this.selectedCollection?.node.id === collection.id) {
|
||||||
@@ -778,7 +775,7 @@ export class VaultComponent implements OnInit, OnDestroy {
|
|||||||
this.platformUtilsService.showToast(
|
this.platformUtilsService.showToast(
|
||||||
"error",
|
"error",
|
||||||
this.i18nService.t("errorOccurred"),
|
this.i18nService.t("errorOccurred"),
|
||||||
this.i18nService.t("nothingSelected")
|
this.i18nService.t("nothingSelected"),
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -801,8 +798,8 @@ export class VaultComponent implements OnInit, OnDestroy {
|
|||||||
.map((i) => i.collection.organizationId);
|
.map((i) => i.collection.organizationId);
|
||||||
const orgs = await firstValueFrom(
|
const orgs = await firstValueFrom(
|
||||||
this.organizationService.organizations$.pipe(
|
this.organizationService.organizations$.pipe(
|
||||||
map((orgs) => orgs.filter((o) => orgIds.includes(o.id)))
|
map((orgs) => orgs.filter((o) => orgIds.includes(o.id))),
|
||||||
)
|
),
|
||||||
);
|
);
|
||||||
await this.bulkDelete(ciphers, collections, orgs);
|
await this.bulkDelete(ciphers, collections, orgs);
|
||||||
}
|
}
|
||||||
@@ -830,7 +827,7 @@ export class VaultComponent implements OnInit, OnDestroy {
|
|||||||
this.platformUtilsService.showToast(
|
this.platformUtilsService.showToast(
|
||||||
"success",
|
"success",
|
||||||
null,
|
null,
|
||||||
this.i18nService.t(permanent ? "permanentlyDeletedItem" : "deletedItem")
|
this.i18nService.t(permanent ? "permanentlyDeletedItem" : "deletedItem"),
|
||||||
);
|
);
|
||||||
this.refresh();
|
this.refresh();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
@@ -841,7 +838,7 @@ export class VaultComponent implements OnInit, OnDestroy {
|
|||||||
async bulkDelete(
|
async bulkDelete(
|
||||||
ciphers: CipherView[],
|
ciphers: CipherView[],
|
||||||
collections: CollectionView[],
|
collections: CollectionView[],
|
||||||
organizations: Organization[]
|
organizations: Organization[],
|
||||||
) {
|
) {
|
||||||
if (!(await this.repromptCipher(ciphers))) {
|
if (!(await this.repromptCipher(ciphers))) {
|
||||||
return;
|
return;
|
||||||
@@ -851,7 +848,7 @@ export class VaultComponent implements OnInit, OnDestroy {
|
|||||||
this.platformUtilsService.showToast(
|
this.platformUtilsService.showToast(
|
||||||
"error",
|
"error",
|
||||||
this.i18nService.t("errorOccurred"),
|
this.i18nService.t("errorOccurred"),
|
||||||
this.i18nService.t("nothingSelected")
|
this.i18nService.t("nothingSelected"),
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -881,7 +878,7 @@ export class VaultComponent implements OnInit, OnDestroy {
|
|||||||
this.platformUtilsService.showToast(
|
this.platformUtilsService.showToast(
|
||||||
"error",
|
"error",
|
||||||
this.i18nService.t("errorOccurred"),
|
this.i18nService.t("errorOccurred"),
|
||||||
this.i18nService.t("nothingSelected")
|
this.i18nService.t("nothingSelected"),
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -933,7 +930,7 @@ export class VaultComponent implements OnInit, OnDestroy {
|
|||||||
this.platformUtilsService.showToast(
|
this.platformUtilsService.showToast(
|
||||||
"info",
|
"info",
|
||||||
null,
|
null,
|
||||||
this.i18nService.t("valueCopied", this.i18nService.t(typeI18nKey))
|
this.i18nService.t("valueCopied", this.i18nService.t(typeI18nKey)),
|
||||||
);
|
);
|
||||||
|
|
||||||
if (field === "password") {
|
if (field === "password") {
|
||||||
@@ -952,7 +949,7 @@ export class VaultComponent implements OnInit, OnDestroy {
|
|||||||
this.platformUtilsService.showToast(
|
this.platformUtilsService.showToast(
|
||||||
"error",
|
"error",
|
||||||
this.i18nService.t("errorOccurred"),
|
this.i18nService.t("errorOccurred"),
|
||||||
this.i18nService.t("nothingSelected")
|
this.i18nService.t("nothingSelected"),
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -130,7 +130,7 @@ export class VaultComponent implements OnInit, OnDestroy {
|
|||||||
protected currentSearchText$: Observable<string>;
|
protected currentSearchText$: Observable<string>;
|
||||||
protected showBulkEditCollectionAccess$ = this.configService.getFeatureFlag$(
|
protected showBulkEditCollectionAccess$ = this.configService.getFeatureFlag$(
|
||||||
FeatureFlag.BulkCollectionAccess,
|
FeatureFlag.BulkCollectionAccess,
|
||||||
false
|
false,
|
||||||
);
|
);
|
||||||
protected flexibleCollectionsEnabled: boolean;
|
protected flexibleCollectionsEnabled: boolean;
|
||||||
|
|
||||||
@@ -164,27 +164,27 @@ export class VaultComponent implements OnInit, OnDestroy {
|
|||||||
private eventCollectionService: EventCollectionService,
|
private eventCollectionService: EventCollectionService,
|
||||||
private totpService: TotpService,
|
private totpService: TotpService,
|
||||||
private apiService: ApiService,
|
private apiService: ApiService,
|
||||||
protected configService: ConfigServiceAbstraction
|
protected configService: ConfigServiceAbstraction,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
async ngOnInit() {
|
async ngOnInit() {
|
||||||
this.trashCleanupWarning = this.i18nService.t(
|
this.trashCleanupWarning = this.i18nService.t(
|
||||||
this.platformUtilsService.isSelfHost()
|
this.platformUtilsService.isSelfHost()
|
||||||
? "trashCleanupWarningSelfHosted"
|
? "trashCleanupWarningSelfHosted"
|
||||||
: "trashCleanupWarning"
|
: "trashCleanupWarning",
|
||||||
);
|
);
|
||||||
|
|
||||||
const filter$ = this.routedVaultFilterService.filter$;
|
const filter$ = this.routedVaultFilterService.filter$;
|
||||||
const organizationId$ = filter$.pipe(
|
const organizationId$ = filter$.pipe(
|
||||||
map((filter) => filter.organizationId),
|
map((filter) => filter.organizationId),
|
||||||
filter((filter) => filter !== undefined),
|
filter((filter) => filter !== undefined),
|
||||||
distinctUntilChanged()
|
distinctUntilChanged(),
|
||||||
);
|
);
|
||||||
|
|
||||||
const organization$ = organizationId$.pipe(
|
const organization$ = organizationId$.pipe(
|
||||||
switchMap((organizationId) => this.organizationService.get$(organizationId)),
|
switchMap((organizationId) => this.organizationService.get$(organizationId)),
|
||||||
takeUntil(this.destroy$),
|
takeUntil(this.destroy$),
|
||||||
shareReplay({ refCount: false, bufferSize: 1 })
|
shareReplay({ refCount: false, bufferSize: 1 }),
|
||||||
);
|
);
|
||||||
|
|
||||||
const firstSetup$ = combineLatest([organization$, this.route.queryParams]).pipe(
|
const firstSetup$ = combineLatest([organization$, this.route.queryParams]).pipe(
|
||||||
@@ -198,7 +198,7 @@ export class VaultComponent implements OnInit, OnDestroy {
|
|||||||
|
|
||||||
return undefined;
|
return undefined;
|
||||||
}),
|
}),
|
||||||
shareReplay({ refCount: true, bufferSize: 1 })
|
shareReplay({ refCount: true, bufferSize: 1 }),
|
||||||
);
|
);
|
||||||
|
|
||||||
this.broadcasterService.subscribe(BroadcasterSubscriptionId, (message: any) => {
|
this.broadcasterService.subscribe(BroadcasterSubscriptionId, (message: any) => {
|
||||||
@@ -227,14 +227,14 @@ export class VaultComponent implements OnInit, OnDestroy {
|
|||||||
queryParams: { search: Utils.isNullOrEmpty(searchText) ? null : searchText },
|
queryParams: { search: Utils.isNullOrEmpty(searchText) ? null : searchText },
|
||||||
queryParamsHandling: "merge",
|
queryParamsHandling: "merge",
|
||||||
replaceUrl: true,
|
replaceUrl: true,
|
||||||
})
|
}),
|
||||||
);
|
);
|
||||||
|
|
||||||
this.currentSearchText$ = this.route.queryParams.pipe(map((queryParams) => queryParams.search));
|
this.currentSearchText$ = this.route.queryParams.pipe(map((queryParams) => queryParams.search));
|
||||||
|
|
||||||
const allCollectionsWithoutUnassigned$ = organizationId$.pipe(
|
const allCollectionsWithoutUnassigned$ = organizationId$.pipe(
|
||||||
switchMap((orgId) => this.collectionAdminService.getAll(orgId)),
|
switchMap((orgId) => this.collectionAdminService.getAll(orgId)),
|
||||||
shareReplay({ refCount: true, bufferSize: 1 })
|
shareReplay({ refCount: true, bufferSize: 1 }),
|
||||||
);
|
);
|
||||||
|
|
||||||
const allCollections$ = combineLatest([organizationId$, allCollectionsWithoutUnassigned$]).pipe(
|
const allCollections$ = combineLatest([organizationId$, allCollectionsWithoutUnassigned$]).pipe(
|
||||||
@@ -244,12 +244,12 @@ export class VaultComponent implements OnInit, OnDestroy {
|
|||||||
noneCollection.id = Unassigned;
|
noneCollection.id = Unassigned;
|
||||||
noneCollection.organizationId = organizationId;
|
noneCollection.organizationId = organizationId;
|
||||||
return allCollections.concat(noneCollection);
|
return allCollections.concat(noneCollection);
|
||||||
})
|
}),
|
||||||
);
|
);
|
||||||
|
|
||||||
const allGroups$ = organizationId$.pipe(
|
const allGroups$ = organizationId$.pipe(
|
||||||
switchMap((organizationId) => this.groupService.getAll(organizationId)),
|
switchMap((organizationId) => this.groupService.getAll(organizationId)),
|
||||||
shareReplay({ refCount: true, bufferSize: 1 })
|
shareReplay({ refCount: true, bufferSize: 1 }),
|
||||||
);
|
);
|
||||||
|
|
||||||
const allCiphers$ = organization$.pipe(
|
const allCiphers$ = organization$.pipe(
|
||||||
@@ -259,12 +259,12 @@ export class VaultComponent implements OnInit, OnDestroy {
|
|||||||
ciphers = await this.cipherService.getAllFromApiForOrganization(organization.id);
|
ciphers = await this.cipherService.getAllFromApiForOrganization(organization.id);
|
||||||
} else {
|
} else {
|
||||||
ciphers = (await this.cipherService.getAllDecrypted()).filter(
|
ciphers = (await this.cipherService.getAllDecrypted()).filter(
|
||||||
(c) => c.organizationId === organization.id
|
(c) => c.organizationId === organization.id,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
await this.searchService.indexCiphers(ciphers, organization.id);
|
await this.searchService.indexCiphers(ciphers, organization.id);
|
||||||
return ciphers;
|
return ciphers;
|
||||||
})
|
}),
|
||||||
);
|
);
|
||||||
|
|
||||||
const ciphers$ = combineLatest([allCiphers$, filter$, this.currentSearchText$]).pipe(
|
const ciphers$ = combineLatest([allCiphers$, filter$, this.currentSearchText$]).pipe(
|
||||||
@@ -282,12 +282,12 @@ export class VaultComponent implements OnInit, OnDestroy {
|
|||||||
|
|
||||||
return ciphers.filter(filterFunction);
|
return ciphers.filter(filterFunction);
|
||||||
}),
|
}),
|
||||||
shareReplay({ refCount: true, bufferSize: 1 })
|
shareReplay({ refCount: true, bufferSize: 1 }),
|
||||||
);
|
);
|
||||||
|
|
||||||
const nestedCollections$ = allCollections$.pipe(
|
const nestedCollections$ = allCollections$.pipe(
|
||||||
map((collections) => getNestedCollectionTree(collections)),
|
map((collections) => getNestedCollectionTree(collections)),
|
||||||
shareReplay({ refCount: true, bufferSize: 1 })
|
shareReplay({ refCount: true, bufferSize: 1 }),
|
||||||
);
|
);
|
||||||
|
|
||||||
const collections$ = combineLatest([nestedCollections$, filter$, this.currentSearchText$]).pipe(
|
const collections$ = combineLatest([nestedCollections$, filter$, this.currentSearchText$]).pipe(
|
||||||
@@ -306,7 +306,7 @@ export class VaultComponent implements OnInit, OnDestroy {
|
|||||||
} else {
|
} else {
|
||||||
const selectedCollection = ServiceUtils.getTreeNodeObjectFromList(
|
const selectedCollection = ServiceUtils.getTreeNodeObjectFromList(
|
||||||
collections,
|
collections,
|
||||||
filter.collectionId
|
filter.collectionId,
|
||||||
);
|
);
|
||||||
collectionsToReturn = selectedCollection?.children.map((c) => c.node) ?? [];
|
collectionsToReturn = selectedCollection?.children.map((c) => c.node) ?? [];
|
||||||
}
|
}
|
||||||
@@ -316,14 +316,14 @@ export class VaultComponent implements OnInit, OnDestroy {
|
|||||||
collectionsToReturn,
|
collectionsToReturn,
|
||||||
searchText,
|
searchText,
|
||||||
(collection) => collection.name,
|
(collection) => collection.name,
|
||||||
(collection) => collection.id
|
(collection) => collection.id,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return collectionsToReturn;
|
return collectionsToReturn;
|
||||||
}),
|
}),
|
||||||
takeUntil(this.destroy$),
|
takeUntil(this.destroy$),
|
||||||
shareReplay({ refCount: true, bufferSize: 1 })
|
shareReplay({ refCount: true, bufferSize: 1 }),
|
||||||
);
|
);
|
||||||
|
|
||||||
const selectedCollection$ = combineLatest([nestedCollections$, filter$]).pipe(
|
const selectedCollection$ = combineLatest([nestedCollections$, filter$]).pipe(
|
||||||
@@ -339,7 +339,7 @@ export class VaultComponent implements OnInit, OnDestroy {
|
|||||||
|
|
||||||
return ServiceUtils.getTreeNodeObjectFromList(collections, filter.collectionId);
|
return ServiceUtils.getTreeNodeObjectFromList(collections, filter.collectionId);
|
||||||
}),
|
}),
|
||||||
shareReplay({ refCount: true, bufferSize: 1 })
|
shareReplay({ refCount: true, bufferSize: 1 }),
|
||||||
);
|
);
|
||||||
|
|
||||||
const showMissingCollectionPermissionMessage$ = combineLatest([
|
const showMissingCollectionPermissionMessage$ = combineLatest([
|
||||||
@@ -357,7 +357,7 @@ export class VaultComponent implements OnInit, OnDestroy {
|
|||||||
!organization.canUseAdminCollections)
|
!organization.canUseAdminCollections)
|
||||||
);
|
);
|
||||||
}),
|
}),
|
||||||
shareReplay({ refCount: true, bufferSize: 1 })
|
shareReplay({ refCount: true, bufferSize: 1 }),
|
||||||
);
|
);
|
||||||
|
|
||||||
firstSetup$
|
firstSetup$
|
||||||
@@ -378,7 +378,7 @@ export class VaultComponent implements OnInit, OnDestroy {
|
|||||||
this.platformUtilsService.showToast(
|
this.platformUtilsService.showToast(
|
||||||
"error",
|
"error",
|
||||||
this.i18nService.t("errorOccurred"),
|
this.i18nService.t("errorOccurred"),
|
||||||
this.i18nService.t("unknownCipher")
|
this.i18nService.t("unknownCipher"),
|
||||||
);
|
);
|
||||||
this.router.navigate([], {
|
this.router.navigate([], {
|
||||||
queryParams: { cipherId: null, itemId: null },
|
queryParams: { cipherId: null, itemId: null },
|
||||||
@@ -386,7 +386,7 @@ export class VaultComponent implements OnInit, OnDestroy {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
takeUntil(this.destroy$)
|
takeUntil(this.destroy$),
|
||||||
)
|
)
|
||||||
.subscribe();
|
.subscribe();
|
||||||
|
|
||||||
@@ -405,7 +405,7 @@ export class VaultComponent implements OnInit, OnDestroy {
|
|||||||
this.platformUtilsService.showToast(
|
this.platformUtilsService.showToast(
|
||||||
"error",
|
"error",
|
||||||
this.i18nService.t("errorOccurred"),
|
this.i18nService.t("errorOccurred"),
|
||||||
this.i18nService.t("unknownCipher")
|
this.i18nService.t("unknownCipher"),
|
||||||
);
|
);
|
||||||
this.router.navigate([], {
|
this.router.navigate([], {
|
||||||
queryParams: { viewEvents: null },
|
queryParams: { viewEvents: null },
|
||||||
@@ -413,7 +413,7 @@ export class VaultComponent implements OnInit, OnDestroy {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
takeUntil(this.destroy$)
|
takeUntil(this.destroy$),
|
||||||
)
|
)
|
||||||
.subscribe();
|
.subscribe();
|
||||||
|
|
||||||
@@ -431,9 +431,9 @@ export class VaultComponent implements OnInit, OnDestroy {
|
|||||||
collections$,
|
collections$,
|
||||||
selectedCollection$,
|
selectedCollection$,
|
||||||
showMissingCollectionPermissionMessage$,
|
showMissingCollectionPermissionMessage$,
|
||||||
])
|
]),
|
||||||
),
|
),
|
||||||
takeUntil(this.destroy$)
|
takeUntil(this.destroy$),
|
||||||
)
|
)
|
||||||
.subscribe(
|
.subscribe(
|
||||||
([
|
([
|
||||||
@@ -463,7 +463,7 @@ export class VaultComponent implements OnInit, OnDestroy {
|
|||||||
|
|
||||||
this.refreshing = false;
|
this.refreshing = false;
|
||||||
this.performingInitialLoad = false;
|
this.performingInitialLoad = false;
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -550,7 +550,7 @@ export class VaultComponent implements OnInit, OnDestroy {
|
|||||||
comp.onDeletedAttachment
|
comp.onDeletedAttachment
|
||||||
.pipe(takeUntil(this.destroy$))
|
.pipe(takeUntil(this.destroy$))
|
||||||
.subscribe(() => (madeAttachmentChanges = true));
|
.subscribe(() => (madeAttachmentChanges = true));
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
modal.onClosed.pipe(takeUntil(this.destroy$)).subscribe(() => {
|
modal.onClosed.pipe(takeUntil(this.destroy$)).subscribe(() => {
|
||||||
@@ -575,13 +575,13 @@ export class VaultComponent implements OnInit, OnDestroy {
|
|||||||
modal.close();
|
modal.close();
|
||||||
this.refresh();
|
this.refresh();
|
||||||
});
|
});
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
async addCipher() {
|
async addCipher() {
|
||||||
const collections = (await firstValueFrom(this.vaultFilterService.filteredCollections$)).filter(
|
const collections = (await firstValueFrom(this.vaultFilterService.filteredCollections$)).filter(
|
||||||
(c) => !c.readOnly && c.id != Unassigned
|
(c) => !c.readOnly && c.id != Unassigned,
|
||||||
);
|
);
|
||||||
|
|
||||||
await this.editCipher(null, (comp) => {
|
await this.editCipher(null, (comp) => {
|
||||||
@@ -599,14 +599,14 @@ export class VaultComponent implements OnInit, OnDestroy {
|
|||||||
|
|
||||||
async editCipher(
|
async editCipher(
|
||||||
cipher: CipherView,
|
cipher: CipherView,
|
||||||
additionalComponentParameters?: (comp: AddEditComponent) => void
|
additionalComponentParameters?: (comp: AddEditComponent) => void,
|
||||||
) {
|
) {
|
||||||
return this.editCipherId(cipher?.id, additionalComponentParameters);
|
return this.editCipherId(cipher?.id, additionalComponentParameters);
|
||||||
}
|
}
|
||||||
|
|
||||||
async editCipherId(
|
async editCipherId(
|
||||||
cipherId: string,
|
cipherId: string,
|
||||||
additionalComponentParameters?: (comp: AddEditComponent) => void
|
additionalComponentParameters?: (comp: AddEditComponent) => void,
|
||||||
) {
|
) {
|
||||||
const cipher = await this.cipherService.get(cipherId);
|
const cipher = await this.cipherService.get(cipherId);
|
||||||
// if cipher exists (cipher is null when new) and MP reprompt
|
// if cipher exists (cipher is null when new) and MP reprompt
|
||||||
@@ -647,7 +647,7 @@ export class VaultComponent implements OnInit, OnDestroy {
|
|||||||
: (comp) => {
|
: (comp) => {
|
||||||
defaultComponentParameters(comp);
|
defaultComponentParameters(comp);
|
||||||
additionalComponentParameters(comp);
|
additionalComponentParameters(comp);
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
modal.onClosedPromise().then(() => {
|
modal.onClosedPromise().then(() => {
|
||||||
@@ -671,7 +671,7 @@ export class VaultComponent implements OnInit, OnDestroy {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const collections = (await firstValueFrom(this.vaultFilterService.filteredCollections$)).filter(
|
const collections = (await firstValueFrom(this.vaultFilterService.filteredCollections$)).filter(
|
||||||
(c) => !c.readOnly && c.id != Unassigned
|
(c) => !c.readOnly && c.id != Unassigned,
|
||||||
);
|
);
|
||||||
|
|
||||||
await this.editCipher(cipher, (comp) => {
|
await this.editCipher(cipher, (comp) => {
|
||||||
@@ -710,7 +710,7 @@ export class VaultComponent implements OnInit, OnDestroy {
|
|||||||
this.platformUtilsService.showToast(
|
this.platformUtilsService.showToast(
|
||||||
"error",
|
"error",
|
||||||
this.i18nService.t("errorOccurred"),
|
this.i18nService.t("errorOccurred"),
|
||||||
this.i18nService.t("nothingSelected")
|
this.i18nService.t("nothingSelected"),
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -742,7 +742,7 @@ export class VaultComponent implements OnInit, OnDestroy {
|
|||||||
this.platformUtilsService.showToast(
|
this.platformUtilsService.showToast(
|
||||||
"success",
|
"success",
|
||||||
null,
|
null,
|
||||||
this.i18nService.t(permanent ? "permanentlyDeletedItem" : "deletedItem")
|
this.i18nService.t(permanent ? "permanentlyDeletedItem" : "deletedItem"),
|
||||||
);
|
);
|
||||||
this.refresh();
|
this.refresh();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
@@ -753,16 +753,13 @@ export class VaultComponent implements OnInit, OnDestroy {
|
|||||||
async deleteCollection(collection: CollectionView): Promise<void> {
|
async deleteCollection(collection: CollectionView): Promise<void> {
|
||||||
const flexibleCollectionsEnabled = await this.configService.getFeatureFlag(
|
const flexibleCollectionsEnabled = await this.configService.getFeatureFlag(
|
||||||
FeatureFlag.FlexibleCollections,
|
FeatureFlag.FlexibleCollections,
|
||||||
false
|
false,
|
||||||
);
|
);
|
||||||
if (
|
if (collection.canDelete(this.organization, flexibleCollectionsEnabled)) {
|
||||||
(flexibleCollectionsEnabled || !this.organization.canDeleteAssignedCollections) &&
|
|
||||||
!this.organization.canDeleteAnyCollection
|
|
||||||
) {
|
|
||||||
this.platformUtilsService.showToast(
|
this.platformUtilsService.showToast(
|
||||||
"error",
|
"error",
|
||||||
this.i18nService.t("errorOccurred"),
|
this.i18nService.t("errorOccurred"),
|
||||||
this.i18nService.t("missingPermissions")
|
this.i18nService.t("missingPermissions"),
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -780,7 +777,7 @@ export class VaultComponent implements OnInit, OnDestroy {
|
|||||||
this.platformUtilsService.showToast(
|
this.platformUtilsService.showToast(
|
||||||
"success",
|
"success",
|
||||||
null,
|
null,
|
||||||
this.i18nService.t("deletedCollectionId", collection.name)
|
this.i18nService.t("deletedCollectionId", collection.name),
|
||||||
);
|
);
|
||||||
|
|
||||||
// Navigate away if we deleted the colletion we were viewing
|
// Navigate away if we deleted the colletion we were viewing
|
||||||
@@ -801,7 +798,7 @@ export class VaultComponent implements OnInit, OnDestroy {
|
|||||||
async bulkDelete(
|
async bulkDelete(
|
||||||
ciphers: CipherView[],
|
ciphers: CipherView[],
|
||||||
collections: CollectionView[],
|
collections: CollectionView[],
|
||||||
organization: Organization
|
organization: Organization,
|
||||||
) {
|
) {
|
||||||
if (!(await this.repromptCipher(ciphers))) {
|
if (!(await this.repromptCipher(ciphers))) {
|
||||||
return;
|
return;
|
||||||
@@ -811,7 +808,7 @@ export class VaultComponent implements OnInit, OnDestroy {
|
|||||||
this.platformUtilsService.showToast(
|
this.platformUtilsService.showToast(
|
||||||
"error",
|
"error",
|
||||||
this.i18nService.t("errorOccurred"),
|
this.i18nService.t("errorOccurred"),
|
||||||
this.i18nService.t("nothingSelected")
|
this.i18nService.t("nothingSelected"),
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -867,7 +864,7 @@ export class VaultComponent implements OnInit, OnDestroy {
|
|||||||
this.platformUtilsService.showToast(
|
this.platformUtilsService.showToast(
|
||||||
"info",
|
"info",
|
||||||
null,
|
null,
|
||||||
this.i18nService.t("valueCopied", this.i18nService.t(typeI18nKey))
|
this.i18nService.t("valueCopied", this.i18nService.t(typeI18nKey)),
|
||||||
);
|
);
|
||||||
|
|
||||||
if (field === "password") {
|
if (field === "password") {
|
||||||
@@ -913,7 +910,7 @@ export class VaultComponent implements OnInit, OnDestroy {
|
|||||||
this.platformUtilsService.showToast(
|
this.platformUtilsService.showToast(
|
||||||
"error",
|
"error",
|
||||||
this.i18nService.t("errorOccurred"),
|
this.i18nService.t("errorOccurred"),
|
||||||
this.i18nService.t("nothingSelected")
|
this.i18nService.t("nothingSelected"),
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user