1
0
mirror of https://github.com/bitwarden/browser synced 2025-12-10 05:13:29 +00:00

Enable import into managed collections within Password Manager (#13288)

Members of an org that lacked the canAccessImport permission were not able to import into an organization. With the introduction of flexible collections, Bitwarden would like to enable members of an organization to import into collections they manage

Co-authored-by: Daniel James Smith <djsmith85@users.noreply.github.com>
This commit is contained in:
Daniel James Smith
2025-02-13 19:50:29 +01:00
committed by GitHub
parent 9655b1b3bc
commit a0c38543ac

View File

@@ -15,8 +15,8 @@ import {
} from "@angular/core";
import { FormBuilder, ReactiveFormsModule, Validators } from "@angular/forms";
import * as JSZip from "jszip";
import { concat, Observable, Subject, lastValueFrom, combineLatest, firstValueFrom } from "rxjs";
import { filter, map, switchMap, takeUntil } from "rxjs/operators";
import { Observable, Subject, lastValueFrom, combineLatest, firstValueFrom } from "rxjs";
import { combineLatestWith, filter, map, switchMap, takeUntil } from "rxjs/operators";
import { CollectionService, CollectionView } from "@bitwarden/admin-console/common";
import { JslibModule } from "@bitwarden/angular/jslib.module";
@@ -239,11 +239,10 @@ export class ImportComponent implements OnInit, OnDestroy, AfterViewInit {
async ngOnInit() {
this.setImportOptions();
await this.initializeOrganizations();
if (this.organizationId && (await this.canAccessImport(this.organizationId))) {
this.handleOrganizationImportInit();
if (this.organizationId) {
await this.handleOrganizationImportInit();
} else {
this.handleImportInit();
await this.handleImportInit();
}
this.formGroup.controls.format.valueChanges
@@ -255,7 +254,19 @@ export class ImportComponent implements OnInit, OnDestroy, AfterViewInit {
await this.handlePolicies();
}
private handleOrganizationImportInit() {
private async handleOrganizationImportInit() {
const userId = await firstValueFrom(getUserId(this.accountService.activeAccount$));
this.organizations$ = this.organizationService
.memberOrganizations$(userId)
.pipe(
map((orgs) =>
orgs.filter(
(org) =>
org.id == this.organizationId && (org.canAccessImport || org.canCreateNewCollections),
),
),
);
this.formGroup.controls.vaultSelector.patchValue(this.organizationId);
this.formGroup.controls.vaultSelector.disable();
@@ -268,7 +279,7 @@ export class ImportComponent implements OnInit, OnDestroy, AfterViewInit {
this.isFromAC = true;
}
private handleImportInit() {
private async handleImportInit() {
// Filter out the no folder-item from folderViews$
this.folders$ = this.activeUserId$.pipe(
switchMap((userId) => {
@@ -279,6 +290,17 @@ export class ImportComponent implements OnInit, OnDestroy, AfterViewInit {
this.formGroup.controls.targetSelector.disable();
// Retrieve all organizations a user is a member of and has collections they can manage
const userId = await firstValueFrom(getUserId(this.accountService.activeAccount$));
this.organizations$ = this.organizationService.memberOrganizations$(userId).pipe(
combineLatestWith(this.collectionService.decryptedCollections$),
map(([organizations, collections]) =>
organizations
.filter((org) => collections.some((c) => c.organizationId === org.id && c.manage))
.sort(Utils.getSortFunction(this.i18nService, "name")),
),
);
combineLatest([this.formGroup.controls.vaultSelector.valueChanges, this.organizations$])
.pipe(takeUntil(this.destroy$))
.subscribe(([value, organizations]) => {
@@ -303,18 +325,6 @@ export class ImportComponent implements OnInit, OnDestroy, AfterViewInit {
this.formGroup.controls.vaultSelector.setValue("myVault");
}
private async initializeOrganizations() {
const userId = await firstValueFrom(getUserId(this.accountService.activeAccount$));
this.organizations$ = concat(
this.organizationService.memberOrganizations$(userId).pipe(
// Import is an alternative way to create collections during onboarding, so import from Password Manager
// is available to any user who can create collections in the organization.
map((orgs) => orgs.filter((org) => org.canAccessImport || org.canCreateNewCollections)),
map((orgs) => orgs.sort(Utils.getSortFunction(this.i18nService, "name"))),
),
);
}
private async handlePolicies() {
combineLatest([
this.policyService.policyAppliesToActiveUser$(PolicyType.PersonalOwnership),