mirror of
https://github.com/bitwarden/browser
synced 2025-12-16 00:03:56 +00:00
[PM-15506] Implement vNextOrganizationService (#12839)
* [PM-15506] Wire up vNextOrganizationService for libs/common and libs/angular (#12683) * Wire up vNextOrganizationService in PolicyService * Wire vNextOrganizationService in SyncService * wire vNextOrganizationService for EventCollectionService * wire vNextOrganizationService for KeyConnectorService * wire up vNextOrganizationService for CipherAuthorizationService * Wire up vNextOrganizationService in PolicyService * Wire vNextOrganizationService in SyncService * wire vNextOrganizationService for EventCollectionService * wire vNextOrganizationService for KeyConnectorService * wire up vNextOrganizationService for CipherAuthorizationService * wire vNextOrganizationService for share.component * wire vNextOrganizationService for collections.component * wire vNextOrganizationServcie for add-account-credit-dialog * wire vNextOrganizationService for vault-filter.service * fix browser errors for vNextOrganizationService implementation in libs * fix desktop errors for vNextOrganizationService implementation for libs * fix linter errors * fix CLI errors on vNextOrganizationServcie implementations for libs * [PM-15506] Wire up vNextOrganizationService for web client (#12810) PR to a feature branch, no need to review until this goes to main. * implement vNextOrganization service for browser client (#12844) PR to feature branch, no need for review yet. * wire vNextOrganizationService for licence and some web router guards * wire vNextOrganizationService in tests * remove vNext notation for OrganizationService and related * Merge branch 'main' into ac/pm-15506-vNextOrganizationService * fix tsstrict error * fix test, fix ts strict error
This commit is contained in:
@@ -14,6 +14,8 @@ import { ProviderService } from "@bitwarden/common/admin-console/abstractions/pr
|
||||
import { ProviderStatusType, ProviderUserType } from "@bitwarden/common/admin-console/enums";
|
||||
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
|
||||
import { ProviderOrganizationOrganizationDetailsResponse } from "@bitwarden/common/admin-console/models/response/provider/provider-organization.response";
|
||||
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
||||
import { getUserId } from "@bitwarden/common/auth/services/account.service";
|
||||
import { PlanType } from "@bitwarden/common/billing/enums";
|
||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||
import { ValidationService } from "@bitwarden/common/platform/abstractions/validation.service";
|
||||
@@ -68,6 +70,7 @@ export class ClientsComponent {
|
||||
private apiService: ApiService,
|
||||
private organizationService: OrganizationService,
|
||||
private organizationApiService: OrganizationApiServiceAbstraction,
|
||||
private accountService: AccountService,
|
||||
private activatedRoute: ActivatedRoute,
|
||||
private dialogService: DialogService,
|
||||
private i18nService: I18nService,
|
||||
@@ -136,13 +139,14 @@ export class ClientsComponent {
|
||||
|
||||
async load() {
|
||||
const response = await this.apiService.getProviderClients(this.providerId);
|
||||
const userId = await firstValueFrom(getUserId(this.accountService.activeAccount$));
|
||||
const clients = response.data != null && response.data.length > 0 ? response.data : [];
|
||||
this.dataSource.data = clients;
|
||||
this.manageOrganizations =
|
||||
(await this.providerService.get(this.providerId)).type === ProviderUserType.ProviderAdmin;
|
||||
const candidateOrgs = (await this.organizationService.getAll()).filter(
|
||||
(o) => o.isOwner && o.providerId == null,
|
||||
);
|
||||
const candidateOrgs = (
|
||||
await firstValueFrom(this.organizationService.organizations$(userId))
|
||||
).filter((o) => o.isOwner && o.providerId == null);
|
||||
const allowedOrgsIds = await Promise.all(
|
||||
candidateOrgs.map((o) => this.organizationApiService.get(o.id)),
|
||||
).then((orgs) =>
|
||||
|
||||
@@ -9,13 +9,17 @@ import {
|
||||
Validators,
|
||||
} from "@angular/forms";
|
||||
import { ActivatedRoute } from "@angular/router";
|
||||
import { concatMap, Observable, Subject, takeUntil } from "rxjs";
|
||||
import { concatMap, firstValueFrom, Observable, Subject, takeUntil } from "rxjs";
|
||||
|
||||
import { ControlsOf } from "@bitwarden/angular/types/controls-of";
|
||||
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
||||
import { OrganizationApiServiceAbstraction } from "@bitwarden/common/admin-console/abstractions/organization/organization-api.service.abstraction";
|
||||
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
||||
import {
|
||||
getOrganizationById,
|
||||
OrganizationService,
|
||||
} from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
||||
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
|
||||
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
||||
import {
|
||||
MemberDecryptionType,
|
||||
OpenIdConnectRedirectBehavior,
|
||||
@@ -28,6 +32,7 @@ import { SsoConfigApi } from "@bitwarden/common/auth/models/api/sso-config.api";
|
||||
import { OrganizationSsoRequest } from "@bitwarden/common/auth/models/request/organization-sso.request";
|
||||
import { OrganizationSsoResponse } from "@bitwarden/common/auth/models/response/organization-sso.response";
|
||||
import { SsoConfigView } from "@bitwarden/common/auth/models/view/sso-config.view";
|
||||
import { getUserId } from "@bitwarden/common/auth/services/account.service";
|
||||
import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum";
|
||||
import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
|
||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||
@@ -195,6 +200,7 @@ export class SsoComponent implements OnInit, OnDestroy {
|
||||
private platformUtilsService: PlatformUtilsService,
|
||||
private i18nService: I18nService,
|
||||
private organizationService: OrganizationService,
|
||||
private accountService: AccountService,
|
||||
private organizationApiService: OrganizationApiServiceAbstraction,
|
||||
private configService: ConfigService,
|
||||
private toastService: ToastService,
|
||||
@@ -260,7 +266,12 @@ export class SsoComponent implements OnInit, OnDestroy {
|
||||
}
|
||||
|
||||
async load() {
|
||||
this.organization = await this.organizationService.get(this.organizationId);
|
||||
const userId = await firstValueFrom(getUserId(this.accountService.activeAccount$));
|
||||
this.organization = await firstValueFrom(
|
||||
this.organizationService
|
||||
.organizations$(userId)
|
||||
.pipe(getOrganizationById(this.organizationId)),
|
||||
);
|
||||
const ssoSettings = await this.organizationApiService.getSso(this.organizationId);
|
||||
this.populateForm(ssoSettings);
|
||||
|
||||
|
||||
@@ -1,7 +1,13 @@
|
||||
import { inject } from "@angular/core";
|
||||
import { ActivatedRouteSnapshot, CanActivateFn, createUrlTreeFromSnapshot } from "@angular/router";
|
||||
import { firstValueFrom } from "rxjs";
|
||||
|
||||
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
||||
import {
|
||||
getOrganizationById,
|
||||
OrganizationService,
|
||||
} from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
||||
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
||||
import { getUserId } from "@bitwarden/common/auth/services/account.service";
|
||||
import { SyncService } from "@bitwarden/common/vault/abstractions/sync/sync.service.abstraction";
|
||||
|
||||
/**
|
||||
@@ -10,13 +16,17 @@ import { SyncService } from "@bitwarden/common/vault/abstractions/sync/sync.serv
|
||||
export const organizationEnabledGuard: CanActivateFn = async (route: ActivatedRouteSnapshot) => {
|
||||
const syncService = inject(SyncService);
|
||||
const orgService = inject(OrganizationService);
|
||||
const accountService = inject(AccountService);
|
||||
|
||||
/** Workaround to avoid service initialization race condition. */
|
||||
if ((await syncService.getLastSync()) == null) {
|
||||
await syncService.fullSync(false);
|
||||
}
|
||||
|
||||
const org = await orgService.get(route.params.organizationId);
|
||||
const userId = await firstValueFrom(getUserId(accountService.activeAccount$));
|
||||
const org = await firstValueFrom(
|
||||
orgService.organizations$(userId).pipe(getOrganizationById(route.params.organizationId)),
|
||||
);
|
||||
if (org == null || !org.canAccessSecretsManager) {
|
||||
return createUrlTreeFromSnapshot(route, ["/"]);
|
||||
}
|
||||
|
||||
@@ -5,8 +5,11 @@ import {
|
||||
createUrlTreeFromSnapshot,
|
||||
RouterStateSnapshot,
|
||||
} from "@angular/router";
|
||||
import { firstValueFrom } from "rxjs";
|
||||
|
||||
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
||||
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
||||
import { getUserId } from "@bitwarden/common/auth/services/account.service";
|
||||
import { SyncService } from "@bitwarden/common/vault/abstractions/sync/sync.service.abstraction";
|
||||
|
||||
/**
|
||||
@@ -18,13 +21,15 @@ export const canActivateSM: CanActivateFn = async (
|
||||
) => {
|
||||
const syncService = inject(SyncService);
|
||||
const orgService = inject(OrganizationService);
|
||||
const accountService = inject(AccountService);
|
||||
|
||||
/** Workaround to avoid service initialization race condition. */
|
||||
if ((await syncService.getLastSync()) == null) {
|
||||
await syncService.fullSync(false);
|
||||
}
|
||||
|
||||
const orgs = await orgService.getAll();
|
||||
const userId = await firstValueFrom(getUserId(accountService.activeAccount$));
|
||||
const orgs = await firstValueFrom(orgService.organizations$(userId));
|
||||
const smOrg = orgs.find((o) => o.canAccessSecretsManager);
|
||||
if (smOrg) {
|
||||
return createUrlTreeFromSnapshot(route, ["/sm", smOrg.id]);
|
||||
|
||||
@@ -15,8 +15,13 @@ import {
|
||||
takeUntil,
|
||||
} from "rxjs";
|
||||
|
||||
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
||||
import {
|
||||
getOrganizationById,
|
||||
OrganizationService,
|
||||
} from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
||||
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
|
||||
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
||||
import { getUserId } from "@bitwarden/common/auth/services/account.service";
|
||||
import { SecretsManagerLogo } from "@bitwarden/web-vault/app/layouts/secrets-manager-logo";
|
||||
|
||||
import { OrganizationCounts } from "../models/view/counts.view";
|
||||
@@ -41,6 +46,7 @@ export class NavigationComponent implements OnInit, OnDestroy {
|
||||
constructor(
|
||||
protected route: ActivatedRoute,
|
||||
private organizationService: OrganizationService,
|
||||
private accountService: AccountService,
|
||||
private countService: CountService,
|
||||
private projectService: ProjectService,
|
||||
private secretService: SecretService,
|
||||
@@ -50,7 +56,15 @@ export class NavigationComponent implements OnInit, OnDestroy {
|
||||
|
||||
ngOnInit() {
|
||||
const org$ = this.route.params.pipe(
|
||||
concatMap((params) => this.organizationService.get(params.organizationId)),
|
||||
concatMap((params) =>
|
||||
getUserId(this.accountService.activeAccount$).pipe(
|
||||
switchMap((userId) =>
|
||||
this.organizationService
|
||||
.organizations$(userId)
|
||||
.pipe(getOrganizationById(params.organizationId)),
|
||||
),
|
||||
),
|
||||
),
|
||||
distinctUntilChanged(),
|
||||
takeUntil(this.destroy$),
|
||||
);
|
||||
|
||||
@@ -20,8 +20,13 @@ import {
|
||||
|
||||
import { I18nPipe } from "@bitwarden/angular/platform/pipes/i18n.pipe";
|
||||
import { OrganizationApiServiceAbstraction } from "@bitwarden/common/admin-console/abstractions/organization/organization-api.service.abstraction";
|
||||
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
||||
import {
|
||||
getOrganizationById,
|
||||
OrganizationService,
|
||||
} from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
||||
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
|
||||
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
||||
import { getUserId } from "@bitwarden/common/auth/services/account.service";
|
||||
import { OrganizationBillingServiceAbstraction } from "@bitwarden/common/billing/abstractions";
|
||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
|
||||
@@ -112,6 +117,7 @@ export class OverviewComponent implements OnInit, OnDestroy {
|
||||
private serviceAccountService: ServiceAccountService,
|
||||
private dialogService: DialogService,
|
||||
private organizationService: OrganizationService,
|
||||
private accountService: AccountService,
|
||||
private platformUtilsService: PlatformUtilsService,
|
||||
private i18nService: I18nService,
|
||||
private smOnboardingTasksService: SMOnboardingTasksService,
|
||||
@@ -130,7 +136,15 @@ export class OverviewComponent implements OnInit, OnDestroy {
|
||||
distinctUntilChanged(),
|
||||
);
|
||||
|
||||
const org$ = orgId$.pipe(switchMap((orgId) => this.organizationService.get(orgId)));
|
||||
const org$ = orgId$.pipe(
|
||||
switchMap((orgId) =>
|
||||
getUserId(this.accountService.activeAccount$).pipe(
|
||||
switchMap((userId) =>
|
||||
this.organizationService.organizations$(userId).pipe(getOrganizationById(orgId)),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
org$.pipe(takeUntil(this.destroy$)).subscribe((org) => {
|
||||
this.organizationId = org.id;
|
||||
|
||||
@@ -3,10 +3,15 @@ import { TestBed } from "@angular/core/testing";
|
||||
import { Router } from "@angular/router";
|
||||
import { RouterTestingModule } from "@angular/router/testing";
|
||||
import { MockProxy, mock } from "jest-mock-extended";
|
||||
import { of } from "rxjs";
|
||||
|
||||
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
||||
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
|
||||
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||
import { Utils } from "@bitwarden/common/platform/misc/utils";
|
||||
import { FakeAccountService, mockAccountServiceWith } from "@bitwarden/common/spec";
|
||||
import { UserId } from "@bitwarden/common/types/guid";
|
||||
import { ToastService } from "@bitwarden/components";
|
||||
import { RouterService } from "@bitwarden/web-vault/app/core";
|
||||
|
||||
@@ -32,6 +37,8 @@ describe("Project Redirect Guard", () => {
|
||||
let i18nServiceMock: MockProxy<I18nService>;
|
||||
let toastService: MockProxy<ToastService>;
|
||||
let router: Router;
|
||||
let accountService: FakeAccountService;
|
||||
const userId = Utils.newGuid() as UserId;
|
||||
|
||||
const smOrg1 = { id: "123", canAccessSecretsManager: true } as Organization;
|
||||
const projectView = {
|
||||
@@ -50,6 +57,7 @@ describe("Project Redirect Guard", () => {
|
||||
projectServiceMock = mock<ProjectService>();
|
||||
i18nServiceMock = mock<I18nService>();
|
||||
toastService = mock<ToastService>();
|
||||
accountService = mockAccountServiceWith(userId);
|
||||
|
||||
TestBed.configureTestingModule({
|
||||
imports: [
|
||||
@@ -71,6 +79,7 @@ describe("Project Redirect Guard", () => {
|
||||
],
|
||||
providers: [
|
||||
{ provide: OrganizationService, useValue: organizationService },
|
||||
{ provide: AccountService, useValue: accountService },
|
||||
{ provide: RouterService, useValue: routerService },
|
||||
{ provide: ProjectService, useValue: projectServiceMock },
|
||||
{ provide: I18nService, useValue: i18nServiceMock },
|
||||
@@ -83,7 +92,7 @@ describe("Project Redirect Guard", () => {
|
||||
|
||||
it("redirects to sm/{orgId}/projects/{projectId} if project exists", async () => {
|
||||
// Arrange
|
||||
organizationService.getAll.mockResolvedValue([smOrg1]);
|
||||
organizationService.organizations$.mockReturnValue(of([smOrg1]));
|
||||
projectServiceMock.getByProjectId.mockReturnValue(Promise.resolve(projectView));
|
||||
|
||||
// Act
|
||||
@@ -95,7 +104,7 @@ describe("Project Redirect Guard", () => {
|
||||
|
||||
it("redirects to sm/projects if project does not exist", async () => {
|
||||
// Arrange
|
||||
organizationService.getAll.mockResolvedValue([smOrg1]);
|
||||
organizationService.organizations$.mockReturnValue(of([smOrg1]));
|
||||
|
||||
// Act
|
||||
await router.navigateByUrl("sm/123/projects/124");
|
||||
|
||||
@@ -2,9 +2,22 @@
|
||||
// @ts-strict-ignore
|
||||
import { Component, OnInit } from "@angular/core";
|
||||
import { ActivatedRoute } from "@angular/router";
|
||||
import { combineLatest, combineLatestWith, filter, Observable, startWith, switchMap } from "rxjs";
|
||||
import {
|
||||
combineLatest,
|
||||
combineLatestWith,
|
||||
filter,
|
||||
firstValueFrom,
|
||||
Observable,
|
||||
startWith,
|
||||
switchMap,
|
||||
} from "rxjs";
|
||||
|
||||
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
||||
import {
|
||||
getOrganizationById,
|
||||
OrganizationService,
|
||||
} from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
||||
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
||||
import { getUserId } from "@bitwarden/common/auth/services/account.service";
|
||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
|
||||
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
||||
@@ -49,6 +62,7 @@ export class ProjectSecretsComponent implements OnInit {
|
||||
private platformUtilsService: PlatformUtilsService,
|
||||
private i18nService: I18nService,
|
||||
private organizationService: OrganizationService,
|
||||
private accountService: AccountService,
|
||||
private logService: LogService,
|
||||
) {}
|
||||
|
||||
@@ -71,8 +85,13 @@ export class ProjectSecretsComponent implements OnInit {
|
||||
switchMap(async ([_, params]) => {
|
||||
this.organizationId = params.organizationId;
|
||||
this.projectId = params.projectId;
|
||||
const userId = await firstValueFrom(getUserId(this.accountService.activeAccount$));
|
||||
this.organizationEnabled = (
|
||||
await this.organizationService.get(params.organizationId)
|
||||
await firstValueFrom(
|
||||
this.organizationService
|
||||
.organizations$(userId)
|
||||
.pipe(getOrganizationById(params.organizationId)),
|
||||
)
|
||||
)?.enabled;
|
||||
return await this.getSecretsByProject();
|
||||
}),
|
||||
|
||||
@@ -14,7 +14,12 @@ import {
|
||||
concatMap,
|
||||
} from "rxjs";
|
||||
|
||||
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
||||
import {
|
||||
getOrganizationById,
|
||||
OrganizationService,
|
||||
} from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
||||
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
||||
import { getUserId } from "@bitwarden/common/auth/services/account.service";
|
||||
import { DialogService } from "@bitwarden/components";
|
||||
|
||||
import { ProjectCounts } from "../../models/view/counts.view";
|
||||
@@ -49,6 +54,7 @@ export class ProjectComponent implements OnInit, OnDestroy {
|
||||
private accessPolicyService: AccessPolicyService,
|
||||
private dialogService: DialogService,
|
||||
private organizationService: OrganizationService,
|
||||
private accountService: AccountService,
|
||||
private countService: CountService,
|
||||
) {}
|
||||
|
||||
@@ -65,7 +71,15 @@ export class ProjectComponent implements OnInit, OnDestroy {
|
||||
|
||||
const projectId$ = this.route.params.pipe(map((p) => p.projectId));
|
||||
const organization$ = this.route.params.pipe(
|
||||
concatMap((params) => this.organizationService.get$(params.organizationId)),
|
||||
concatMap((params) =>
|
||||
getUserId(this.accountService.activeAccount$).pipe(
|
||||
switchMap((userId) =>
|
||||
this.organizationService
|
||||
.organizations$(userId)
|
||||
.pipe(getOrganizationById(params.organizationId)),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
const projectCounts$ = combineLatest([
|
||||
this.route.params,
|
||||
|
||||
@@ -2,9 +2,21 @@
|
||||
// @ts-strict-ignore
|
||||
import { Component, OnInit } from "@angular/core";
|
||||
import { ActivatedRoute } from "@angular/router";
|
||||
import { combineLatest, lastValueFrom, Observable, startWith, switchMap } from "rxjs";
|
||||
import {
|
||||
combineLatest,
|
||||
firstValueFrom,
|
||||
lastValueFrom,
|
||||
Observable,
|
||||
startWith,
|
||||
switchMap,
|
||||
} from "rxjs";
|
||||
|
||||
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
||||
import {
|
||||
getOrganizationById,
|
||||
OrganizationService,
|
||||
} from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
||||
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
||||
import { getUserId } from "@bitwarden/common/auth/services/account.service";
|
||||
import { DialogService } from "@bitwarden/components";
|
||||
|
||||
import { ProjectListView } from "../../models/view/project-list.view";
|
||||
@@ -41,6 +53,7 @@ export class ProjectsComponent implements OnInit {
|
||||
private projectService: ProjectService,
|
||||
private dialogService: DialogService,
|
||||
private organizationService: OrganizationService,
|
||||
private accountService: AccountService,
|
||||
) {}
|
||||
|
||||
ngOnInit() {
|
||||
@@ -50,8 +63,13 @@ export class ProjectsComponent implements OnInit {
|
||||
]).pipe(
|
||||
switchMap(async ([params]) => {
|
||||
this.organizationId = params.organizationId;
|
||||
const userId = await firstValueFrom(getUserId(this.accountService.activeAccount$));
|
||||
this.organizationEnabled = (
|
||||
await this.organizationService.get(params.organizationId)
|
||||
await firstValueFrom(
|
||||
this.organizationService
|
||||
.organizations$(userId)
|
||||
.pipe(getOrganizationById(params.organizationId)),
|
||||
)
|
||||
)?.enabled;
|
||||
|
||||
return await this.getProjects();
|
||||
|
||||
@@ -3,9 +3,14 @@
|
||||
import { DialogRef, DIALOG_DATA } from "@angular/cdk/dialog";
|
||||
import { ChangeDetectorRef, Component, Inject, OnDestroy, OnInit } from "@angular/core";
|
||||
import { FormControl, FormGroup, Validators } from "@angular/forms";
|
||||
import { lastValueFrom, Subject, takeUntil } from "rxjs";
|
||||
import { firstValueFrom, lastValueFrom, Subject, takeUntil } from "rxjs";
|
||||
|
||||
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
||||
import {
|
||||
getOrganizationById,
|
||||
OrganizationService,
|
||||
} from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
||||
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
||||
import { getUserId } from "@bitwarden/common/auth/services/account.service";
|
||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
||||
import { Utils } from "@bitwarden/common/platform/misc/utils";
|
||||
@@ -97,6 +102,7 @@ export class SecretDialogComponent implements OnInit, OnDestroy {
|
||||
private projectService: ProjectService,
|
||||
private dialogService: DialogService,
|
||||
private organizationService: OrganizationService,
|
||||
private accountService: AccountService,
|
||||
private accessPolicyService: AccessPolicyService,
|
||||
private accessPolicySelectorService: AccessPolicySelectorService,
|
||||
private toastService: ToastService,
|
||||
@@ -127,7 +133,16 @@ export class SecretDialogComponent implements OnInit, OnDestroy {
|
||||
await this.loadAddDialog();
|
||||
}
|
||||
|
||||
if ((await this.organizationService.get(this.data.organizationId))?.isAdmin) {
|
||||
const userId = await firstValueFrom(getUserId(this.accountService.activeAccount$));
|
||||
if (
|
||||
(
|
||||
await firstValueFrom(
|
||||
this.organizationService
|
||||
.organizations$(userId)
|
||||
.pipe(getOrganizationById(this.data.organizationId)),
|
||||
)
|
||||
)?.isAdmin
|
||||
) {
|
||||
this.formGroup.get("project").removeValidators(Validators.required);
|
||||
this.formGroup.get("project").updateValueAndValidity();
|
||||
}
|
||||
|
||||
@@ -2,9 +2,14 @@
|
||||
// @ts-strict-ignore
|
||||
import { Component, OnInit } from "@angular/core";
|
||||
import { ActivatedRoute } from "@angular/router";
|
||||
import { combineLatestWith, Observable, startWith, switchMap } from "rxjs";
|
||||
import { combineLatestWith, firstValueFrom, Observable, startWith, switchMap } from "rxjs";
|
||||
|
||||
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
||||
import {
|
||||
getOrganizationById,
|
||||
OrganizationService,
|
||||
} from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
||||
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
||||
import { getUserId } from "@bitwarden/common/auth/services/account.service";
|
||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
|
||||
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
||||
@@ -46,6 +51,7 @@ export class SecretsComponent implements OnInit {
|
||||
private platformUtilsService: PlatformUtilsService,
|
||||
private i18nService: I18nService,
|
||||
private organizationService: OrganizationService,
|
||||
private accountService: AccountService,
|
||||
private logService: LogService,
|
||||
) {}
|
||||
|
||||
@@ -55,8 +61,13 @@ export class SecretsComponent implements OnInit {
|
||||
combineLatestWith(this.route.params),
|
||||
switchMap(async ([_, params]) => {
|
||||
this.organizationId = params.organizationId;
|
||||
const userId = await firstValueFrom(getUserId(this.accountService.activeAccount$));
|
||||
this.organizationEnabled = (
|
||||
await this.organizationService.get(params.organizationId)
|
||||
await firstValueFrom(
|
||||
this.organizationService
|
||||
.organizations$(userId)
|
||||
.pipe(getOrganizationById(params.organizationId)),
|
||||
)
|
||||
)?.enabled;
|
||||
|
||||
return await this.getSecrets();
|
||||
|
||||
@@ -3,10 +3,15 @@ import { TestBed } from "@angular/core/testing";
|
||||
import { Router } from "@angular/router";
|
||||
import { RouterTestingModule } from "@angular/router/testing";
|
||||
import { MockProxy, mock } from "jest-mock-extended";
|
||||
import { of } from "rxjs";
|
||||
|
||||
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
||||
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
|
||||
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||
import { Utils } from "@bitwarden/common/platform/misc/utils";
|
||||
import { FakeAccountService, mockAccountServiceWith } from "@bitwarden/common/spec";
|
||||
import { UserId } from "@bitwarden/common/types/guid";
|
||||
import { ToastService } from "@bitwarden/components";
|
||||
import { RouterService } from "@bitwarden/web-vault/app/core";
|
||||
|
||||
@@ -32,6 +37,8 @@ describe("Service account Redirect Guard", () => {
|
||||
let i18nServiceMock: MockProxy<I18nService>;
|
||||
let toastService: MockProxy<ToastService>;
|
||||
let router: Router;
|
||||
let accountService: FakeAccountService;
|
||||
const userId = Utils.newGuid() as UserId;
|
||||
|
||||
const smOrg1 = { id: "123", canAccessSecretsManager: true } as Organization;
|
||||
const serviceAccountView = {
|
||||
@@ -46,6 +53,7 @@ describe("Service account Redirect Guard", () => {
|
||||
serviceAccountServiceMock = mock<ServiceAccountService>();
|
||||
i18nServiceMock = mock<I18nService>();
|
||||
toastService = mock<ToastService>();
|
||||
accountService = mockAccountServiceWith(userId);
|
||||
|
||||
TestBed.configureTestingModule({
|
||||
imports: [
|
||||
@@ -67,6 +75,7 @@ describe("Service account Redirect Guard", () => {
|
||||
],
|
||||
providers: [
|
||||
{ provide: OrganizationService, useValue: organizationService },
|
||||
{ provide: AccountService, useValue: accountService },
|
||||
{ provide: RouterService, useValue: routerService },
|
||||
{ provide: ServiceAccountService, useValue: serviceAccountServiceMock },
|
||||
{ provide: I18nService, useValue: i18nServiceMock },
|
||||
@@ -79,7 +88,7 @@ describe("Service account Redirect Guard", () => {
|
||||
|
||||
it("redirects to sm/{orgId}/machine-accounts/{serviceAccountId} if machine account exists", async () => {
|
||||
// Arrange
|
||||
organizationService.getAll.mockResolvedValue([smOrg1]);
|
||||
organizationService.organizations$.mockReturnValue(of([smOrg1]));
|
||||
serviceAccountServiceMock.getByServiceAccountId.mockReturnValue(
|
||||
Promise.resolve(serviceAccountView),
|
||||
);
|
||||
@@ -93,7 +102,7 @@ describe("Service account Redirect Guard", () => {
|
||||
|
||||
it("redirects to sm/machine-accounts if machine account does not exist", async () => {
|
||||
// Arrange
|
||||
organizationService.getAll.mockResolvedValue([smOrg1]);
|
||||
organizationService.organizations$.mockReturnValue(of([smOrg1]));
|
||||
|
||||
// Act
|
||||
await router.navigateByUrl("sm/123/machine-accounts/124");
|
||||
|
||||
@@ -2,9 +2,14 @@
|
||||
// @ts-strict-ignore
|
||||
import { Component, OnInit } from "@angular/core";
|
||||
import { ActivatedRoute } from "@angular/router";
|
||||
import { combineLatest, Observable, startWith, switchMap } from "rxjs";
|
||||
import { combineLatest, firstValueFrom, Observable, startWith, switchMap } from "rxjs";
|
||||
|
||||
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
||||
import {
|
||||
getOrganizationById,
|
||||
OrganizationService,
|
||||
} from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
||||
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
||||
import { getUserId } from "@bitwarden/common/auth/services/account.service";
|
||||
import { DialogService } from "@bitwarden/components";
|
||||
|
||||
import {
|
||||
@@ -39,6 +44,7 @@ export class ServiceAccountsComponent implements OnInit {
|
||||
private dialogService: DialogService,
|
||||
private serviceAccountService: ServiceAccountService,
|
||||
private organizationService: OrganizationService,
|
||||
private accountService: AccountService,
|
||||
) {}
|
||||
|
||||
ngOnInit() {
|
||||
@@ -48,8 +54,13 @@ export class ServiceAccountsComponent implements OnInit {
|
||||
]).pipe(
|
||||
switchMap(async ([params]) => {
|
||||
this.organizationId = params.organizationId;
|
||||
const userId = await firstValueFrom(getUserId(this.accountService.activeAccount$));
|
||||
this.organizationEnabled = (
|
||||
await this.organizationService.get(params.organizationId)
|
||||
await firstValueFrom(
|
||||
this.organizationService
|
||||
.organizations$(userId)
|
||||
.pipe(getOrganizationById(params.organizationId)),
|
||||
)
|
||||
)?.enabled;
|
||||
|
||||
return await this.getServiceAccounts();
|
||||
|
||||
@@ -5,7 +5,12 @@ import { FormControl, FormGroup, Validators } from "@angular/forms";
|
||||
import { ActivatedRoute } from "@angular/router";
|
||||
import { firstValueFrom, Subject, switchMap, takeUntil } from "rxjs";
|
||||
|
||||
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
||||
import {
|
||||
getOrganizationById,
|
||||
OrganizationService,
|
||||
} from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
||||
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
||||
import { getUserId } from "@bitwarden/common/auth/services/account.service";
|
||||
import { FileDownloadService } from "@bitwarden/common/platform/abstractions/file-download/file-download.service";
|
||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
|
||||
@@ -40,6 +45,7 @@ export class SecretsManagerExportComponent implements OnInit, OnDestroy {
|
||||
private route: ActivatedRoute,
|
||||
private i18nService: I18nService,
|
||||
private organizationService: OrganizationService,
|
||||
private accountService: AccountService,
|
||||
private platformUtilsService: PlatformUtilsService,
|
||||
private smPortingService: SecretsManagerPortingService,
|
||||
private fileDownloadService: FileDownloadService,
|
||||
@@ -52,7 +58,14 @@ export class SecretsManagerExportComponent implements OnInit, OnDestroy {
|
||||
async ngOnInit() {
|
||||
this.route.params
|
||||
.pipe(
|
||||
switchMap(async (params) => await this.organizationService.get(params.organizationId)),
|
||||
switchMap(async (params) => {
|
||||
const userId = await firstValueFrom(getUserId(this.accountService.activeAccount$));
|
||||
return await firstValueFrom(
|
||||
this.organizationService
|
||||
.organizations$(userId)
|
||||
.pipe(getOrganizationById(params.organizationId)),
|
||||
);
|
||||
}),
|
||||
takeUntil(this.destroy$),
|
||||
)
|
||||
.subscribe((organization) => {
|
||||
|
||||
@@ -1,8 +1,13 @@
|
||||
import { mock, MockProxy } from "jest-mock-extended";
|
||||
import { of } from "rxjs";
|
||||
|
||||
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
||||
import { OrganizationUserType } from "@bitwarden/common/admin-console/enums";
|
||||
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
|
||||
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
||||
import { Utils } from "@bitwarden/common/platform/misc/utils";
|
||||
import { FakeAccountService, mockAccountServiceWith } from "@bitwarden/common/spec";
|
||||
import { UserId } from "@bitwarden/common/types/guid";
|
||||
|
||||
import { AccessPolicySelectorService } from "./access-policy-selector.service";
|
||||
import { ApItemValueType } from "./models/ap-item-value.type";
|
||||
@@ -12,13 +17,16 @@ import { ApPermissionEnum } from "./models/enums/ap-permission.enum";
|
||||
|
||||
describe("AccessPolicySelectorService", () => {
|
||||
let organizationService: MockProxy<OrganizationService>;
|
||||
let accountService: FakeAccountService;
|
||||
const userId = Utils.newGuid() as UserId;
|
||||
|
||||
let sut: AccessPolicySelectorService;
|
||||
|
||||
beforeEach(() => {
|
||||
organizationService = mock<OrganizationService>();
|
||||
accountService = mockAccountServiceWith(userId);
|
||||
|
||||
sut = new AccessPolicySelectorService(organizationService);
|
||||
sut = new AccessPolicySelectorService(organizationService, accountService as AccountService);
|
||||
});
|
||||
|
||||
afterEach(() => jest.resetAllMocks());
|
||||
@@ -26,7 +34,7 @@ describe("AccessPolicySelectorService", () => {
|
||||
describe("showAccessRemovalWarning", () => {
|
||||
it("returns false when current user is admin", async () => {
|
||||
const org = orgFactory();
|
||||
organizationService.get.calledWith(org.id).mockResolvedValue(org);
|
||||
organizationService.organizations$.calledWith(userId).mockReturnValue(of([org]));
|
||||
|
||||
const selectedPolicyValues: ApItemValueType[] = [];
|
||||
|
||||
@@ -38,7 +46,7 @@ describe("AccessPolicySelectorService", () => {
|
||||
it("returns false when current user is owner", async () => {
|
||||
const org = orgFactory();
|
||||
org.type = OrganizationUserType.Owner;
|
||||
organizationService.get.calledWith(org.id).mockResolvedValue(org);
|
||||
organizationService.organizations$.calledWith(userId).mockReturnValue(of([org]));
|
||||
|
||||
const selectedPolicyValues: ApItemValueType[] = [];
|
||||
|
||||
@@ -49,7 +57,7 @@ describe("AccessPolicySelectorService", () => {
|
||||
|
||||
it("returns true when current user isn't owner/admin and all policies are removed", async () => {
|
||||
const org = setupUserOrg();
|
||||
organizationService.get.calledWith(org.id).mockResolvedValue(org);
|
||||
organizationService.organizations$.calledWith(userId).mockReturnValue(of([org]));
|
||||
|
||||
const selectedPolicyValues: ApItemValueType[] = [];
|
||||
|
||||
@@ -60,7 +68,7 @@ describe("AccessPolicySelectorService", () => {
|
||||
|
||||
it("returns true when current user isn't owner/admin and user policy is set to canRead", async () => {
|
||||
const org = setupUserOrg();
|
||||
organizationService.get.calledWith(org.id).mockResolvedValue(org);
|
||||
organizationService.organizations$.calledWith(userId).mockReturnValue(of([org]));
|
||||
|
||||
const selectedPolicyValues: ApItemValueType[] = [];
|
||||
selectedPolicyValues.push(
|
||||
@@ -79,7 +87,7 @@ describe("AccessPolicySelectorService", () => {
|
||||
|
||||
it("returns false when current user isn't owner/admin and user policy is set to canReadWrite", async () => {
|
||||
const org = setupUserOrg();
|
||||
organizationService.get.calledWith(org.id).mockResolvedValue(org);
|
||||
organizationService.organizations$.calledWith(userId).mockReturnValue(of([org]));
|
||||
|
||||
const selectedPolicyValues: ApItemValueType[] = [
|
||||
createApItemValueType(
|
||||
@@ -97,7 +105,7 @@ describe("AccessPolicySelectorService", () => {
|
||||
|
||||
it("returns true when current user isn't owner/admin and a group Read policy is submitted that the user is a member of", async () => {
|
||||
const org = setupUserOrg();
|
||||
organizationService.get.calledWith(org.id).mockResolvedValue(org);
|
||||
organizationService.organizations$.calledWith(userId).mockReturnValue(of([org]));
|
||||
|
||||
const selectedPolicyValues: ApItemValueType[] = [
|
||||
createApItemValueType(
|
||||
@@ -118,7 +126,7 @@ describe("AccessPolicySelectorService", () => {
|
||||
|
||||
it("returns false when current user isn't owner/admin and a group ReadWrite policy is submitted that the user is a member of", async () => {
|
||||
const org = setupUserOrg();
|
||||
organizationService.get.calledWith(org.id).mockResolvedValue(org);
|
||||
organizationService.organizations$.calledWith(userId).mockReturnValue(of([org]));
|
||||
|
||||
const selectedPolicyValues: ApItemValueType[] = [
|
||||
createApItemValueType(
|
||||
@@ -139,7 +147,7 @@ describe("AccessPolicySelectorService", () => {
|
||||
|
||||
it("returns true when current user isn't owner/admin and a group ReadWrite policy is submitted that the user is not a member of", async () => {
|
||||
const org = setupUserOrg();
|
||||
organizationService.get.calledWith(org.id).mockResolvedValue(org);
|
||||
organizationService.organizations$.calledWith(userId).mockReturnValue(of([org]));
|
||||
|
||||
const selectedPolicyValues: ApItemValueType[] = [
|
||||
createApItemValueType(
|
||||
@@ -160,7 +168,7 @@ describe("AccessPolicySelectorService", () => {
|
||||
|
||||
it("returns false when current user isn't owner/admin, user policy is set to CanRead, and user is in read write group", async () => {
|
||||
const org = setupUserOrg();
|
||||
organizationService.get.calledWith(org.id).mockResolvedValue(org);
|
||||
organizationService.organizations$.calledWith(userId).mockReturnValue(of([org]));
|
||||
|
||||
const selectedPolicyValues: ApItemValueType[] = [
|
||||
createApItemValueType(
|
||||
@@ -187,7 +195,7 @@ describe("AccessPolicySelectorService", () => {
|
||||
|
||||
it("returns true when current user isn't owner/admin, user policy is set to CanRead, and user is not in ReadWrite group", async () => {
|
||||
const org = setupUserOrg();
|
||||
organizationService.get.calledWith(org.id).mockResolvedValue(org);
|
||||
organizationService.organizations$.calledWith(userId).mockReturnValue(of([org]));
|
||||
|
||||
const selectedPolicyValues: ApItemValueType[] = [
|
||||
createApItemValueType(
|
||||
@@ -214,7 +222,7 @@ describe("AccessPolicySelectorService", () => {
|
||||
|
||||
it("returns true when current user isn't owner/admin, user policy is set to CanRead, and user is in Read group", async () => {
|
||||
const org = setupUserOrg();
|
||||
organizationService.get.calledWith(org.id).mockResolvedValue(org);
|
||||
organizationService.organizations$.calledWith(userId).mockReturnValue(of([org]));
|
||||
|
||||
const selectedPolicyValues: ApItemValueType[] = [
|
||||
createApItemValueType(
|
||||
@@ -242,7 +250,7 @@ describe("AccessPolicySelectorService", () => {
|
||||
describe("showSecretAccessRemovalWarning", () => {
|
||||
it("returns false when there are no current access policies", async () => {
|
||||
const org = orgFactory();
|
||||
organizationService.get.calledWith(org.id).mockResolvedValue(org);
|
||||
organizationService.organizations$.calledWith(userId).mockReturnValue(of([org]));
|
||||
|
||||
const currentAccessPolicies: ApItemViewType[] = [];
|
||||
const selectedPolicyValues: ApItemValueType[] = [];
|
||||
@@ -257,7 +265,7 @@ describe("AccessPolicySelectorService", () => {
|
||||
});
|
||||
it("returns false when current user is admin", async () => {
|
||||
const org = orgFactory();
|
||||
organizationService.get.calledWith(org.id).mockResolvedValue(org);
|
||||
organizationService.organizations$.calledWith(userId).mockReturnValue(of([org]));
|
||||
|
||||
const currentAccessPolicies: ApItemViewType[] = [
|
||||
createApItemViewType(
|
||||
@@ -281,7 +289,7 @@ describe("AccessPolicySelectorService", () => {
|
||||
it("returns false when current user is owner", async () => {
|
||||
const org = orgFactory();
|
||||
org.type = OrganizationUserType.Owner;
|
||||
organizationService.get.calledWith(org.id).mockResolvedValue(org);
|
||||
organizationService.organizations$.calledWith(userId).mockReturnValue(of([org]));
|
||||
|
||||
const currentAccessPolicies: ApItemViewType[] = [
|
||||
createApItemViewType(
|
||||
@@ -304,7 +312,7 @@ describe("AccessPolicySelectorService", () => {
|
||||
});
|
||||
it("returns false when current non-admin user doesn't have Read, Write access with current access policies -- user policy", async () => {
|
||||
const org = setupUserOrg();
|
||||
organizationService.get.calledWith(org.id).mockResolvedValue(org);
|
||||
organizationService.organizations$.calledWith(userId).mockReturnValue(of([org]));
|
||||
|
||||
const currentAccessPolicies: ApItemViewType[] = [
|
||||
createApItemViewType(
|
||||
@@ -327,7 +335,7 @@ describe("AccessPolicySelectorService", () => {
|
||||
});
|
||||
it("returns false when current non-admin user doesn't have Read, Write access with current access policies -- group policy", async () => {
|
||||
const org = setupUserOrg();
|
||||
organizationService.get.calledWith(org.id).mockResolvedValue(org);
|
||||
organizationService.organizations$.calledWith(userId).mockReturnValue(of([org]));
|
||||
|
||||
const currentAccessPolicies: ApItemViewType[] = [
|
||||
createApItemViewType(
|
||||
@@ -352,7 +360,7 @@ describe("AccessPolicySelectorService", () => {
|
||||
});
|
||||
it("returns true when current non-admin user has Read, Write access with current access policies and doesn't with selected -- user policy", async () => {
|
||||
const org = setupUserOrg();
|
||||
organizationService.get.calledWith(org.id).mockResolvedValue(org);
|
||||
organizationService.organizations$.calledWith(userId).mockReturnValue(of([org]));
|
||||
|
||||
const currentAccessPolicies: ApItemViewType[] = [
|
||||
createApItemViewType(
|
||||
@@ -381,7 +389,7 @@ describe("AccessPolicySelectorService", () => {
|
||||
});
|
||||
it("returns true when current non-admin user has Read, Write access with current access policies and doesn't with selected -- group policy", async () => {
|
||||
const org = setupUserOrg();
|
||||
organizationService.get.calledWith(org.id).mockResolvedValue(org);
|
||||
organizationService.organizations$.calledWith(userId).mockReturnValue(of([org]));
|
||||
|
||||
const currentAccessPolicies: ApItemViewType[] = [
|
||||
createApItemViewType(
|
||||
@@ -415,7 +423,7 @@ describe("AccessPolicySelectorService", () => {
|
||||
});
|
||||
it("returns false when current non-admin user has Read, Write access with current access policies and does with selected -- user policy", async () => {
|
||||
const org = setupUserOrg();
|
||||
organizationService.get.calledWith(org.id).mockResolvedValue(org);
|
||||
organizationService.organizations$.calledWith(userId).mockReturnValue(of([org]));
|
||||
|
||||
const currentAccessPolicies: ApItemViewType[] = [
|
||||
createApItemViewType(
|
||||
@@ -446,7 +454,7 @@ describe("AccessPolicySelectorService", () => {
|
||||
});
|
||||
it("returns false when current non-admin user has Read, Write access with current access policies and does with selected -- group policy", async () => {
|
||||
const org = setupUserOrg();
|
||||
organizationService.get.calledWith(org.id).mockResolvedValue(org);
|
||||
organizationService.organizations$.calledWith(userId).mockReturnValue(of([org]));
|
||||
|
||||
const currentAccessPolicies: ApItemViewType[] = [
|
||||
createApItemViewType(
|
||||
|
||||
@@ -1,6 +1,12 @@
|
||||
import { Injectable } from "@angular/core";
|
||||
import { firstValueFrom } from "rxjs";
|
||||
|
||||
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
||||
import {
|
||||
getOrganizationById,
|
||||
OrganizationService,
|
||||
} from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
||||
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
||||
import { getUserId } from "@bitwarden/common/auth/services/account.service";
|
||||
|
||||
import { ApItemValueType } from "./models/ap-item-value.type";
|
||||
import { ApItemViewType } from "./models/ap-item-view.type";
|
||||
@@ -11,13 +17,22 @@ import { ApPermissionEnum } from "./models/enums/ap-permission.enum";
|
||||
providedIn: "root",
|
||||
})
|
||||
export class AccessPolicySelectorService {
|
||||
constructor(private organizationService: OrganizationService) {}
|
||||
constructor(
|
||||
private organizationService: OrganizationService,
|
||||
private accountServcie: AccountService,
|
||||
) {}
|
||||
|
||||
async showAccessRemovalWarning(
|
||||
organizationId: string,
|
||||
selectedPoliciesValues: ApItemValueType[],
|
||||
): Promise<boolean> {
|
||||
const organization = await this.organizationService.get(organizationId);
|
||||
const userId = await firstValueFrom(getUserId(this.accountServcie.activeAccount$));
|
||||
const organization = await firstValueFrom(
|
||||
this.organizationService.organizations$(userId).pipe(getOrganizationById(organizationId)),
|
||||
);
|
||||
if (!organization) {
|
||||
return false;
|
||||
}
|
||||
if (organization.isOwner || organization.isAdmin) {
|
||||
return false;
|
||||
}
|
||||
@@ -38,7 +53,13 @@ export class AccessPolicySelectorService {
|
||||
return false;
|
||||
}
|
||||
|
||||
const organization = await this.organizationService.get(organizationId);
|
||||
const userId = await firstValueFrom(getUserId(this.accountServcie.activeAccount$));
|
||||
const organization = await firstValueFrom(
|
||||
this.organizationService.organizations$(userId).pipe(getOrganizationById(organizationId)),
|
||||
);
|
||||
if (!organization) {
|
||||
return false;
|
||||
}
|
||||
if (organization.isOwner || organization.isAdmin || !this.userHasReadWriteAccess(current)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -2,9 +2,14 @@
|
||||
// @ts-strict-ignore
|
||||
import { Component, OnDestroy, OnInit } from "@angular/core";
|
||||
import { ActivatedRoute } from "@angular/router";
|
||||
import { Subject, takeUntil, concatMap } from "rxjs";
|
||||
import { Subject, takeUntil, concatMap, firstValueFrom } from "rxjs";
|
||||
|
||||
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
||||
import {
|
||||
getOrganizationById,
|
||||
OrganizationService,
|
||||
} from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
||||
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
||||
import { getUserId } from "@bitwarden/common/auth/services/account.service";
|
||||
import { DialogService } from "@bitwarden/components";
|
||||
|
||||
import {
|
||||
@@ -33,12 +38,20 @@ export class NewMenuComponent implements OnInit, OnDestroy {
|
||||
private route: ActivatedRoute,
|
||||
private dialogService: DialogService,
|
||||
private organizationService: OrganizationService,
|
||||
private accountService: AccountService,
|
||||
) {}
|
||||
|
||||
ngOnInit() {
|
||||
this.route.params
|
||||
.pipe(
|
||||
concatMap(async (params) => await this.organizationService.get(params.organizationId)),
|
||||
concatMap(async (params) => {
|
||||
const userId = await firstValueFrom(getUserId(this.accountService.activeAccount$));
|
||||
return await firstValueFrom(
|
||||
this.organizationService
|
||||
.organizations$(userId)
|
||||
.pipe(getOrganizationById(params.organizationId)),
|
||||
);
|
||||
}),
|
||||
takeUntil(this.destroy$),
|
||||
)
|
||||
.subscribe((org) => {
|
||||
|
||||
@@ -1,8 +1,13 @@
|
||||
import { Component } from "@angular/core";
|
||||
import { ActivatedRoute } from "@angular/router";
|
||||
import { map, concatMap } from "rxjs";
|
||||
import { map, concatMap, firstValueFrom } from "rxjs";
|
||||
|
||||
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
||||
import {
|
||||
getOrganizationById,
|
||||
OrganizationService,
|
||||
} from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
||||
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
||||
import { getUserId } from "@bitwarden/common/auth/services/account.service";
|
||||
import { Icon, Icons } from "@bitwarden/components";
|
||||
|
||||
@Component({
|
||||
@@ -11,12 +16,20 @@ import { Icon, Icons } from "@bitwarden/components";
|
||||
export class OrgSuspendedComponent {
|
||||
constructor(
|
||||
private organizationService: OrganizationService,
|
||||
private accountService: AccountService,
|
||||
private route: ActivatedRoute,
|
||||
) {}
|
||||
|
||||
protected NoAccess: Icon = Icons.NoAccess;
|
||||
protected organizationName$ = this.route.params.pipe(
|
||||
concatMap(async (params) => await this.organizationService.get(params.organizationId)),
|
||||
concatMap(async (params) => {
|
||||
const userId = await firstValueFrom(getUserId(this.accountService.activeAccount$));
|
||||
return await firstValueFrom(
|
||||
this.organizationService
|
||||
.organizations$(userId)
|
||||
.pipe(getOrganizationById(params.organizationId)),
|
||||
);
|
||||
}),
|
||||
map((org) => org?.name),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@ import { Component, DestroyRef, inject, OnInit } from "@angular/core";
|
||||
import { takeUntilDestroyed } from "@angular/core/rxjs-interop";
|
||||
import { FormControl } from "@angular/forms";
|
||||
import { ActivatedRoute } from "@angular/router";
|
||||
import { combineLatest, debounceTime, map, Observable, of, skipWhile } from "rxjs";
|
||||
import { combineLatest, debounceTime, firstValueFrom, map, Observable, of, skipWhile } from "rxjs";
|
||||
|
||||
import {
|
||||
CriticalAppsService,
|
||||
@@ -14,8 +14,13 @@ import {
|
||||
ApplicationHealthReportDetailWithCriticalFlag,
|
||||
ApplicationHealthReportSummary,
|
||||
} from "@bitwarden/bit-common/tools/reports/risk-insights/models/password-health";
|
||||
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
||||
import {
|
||||
getOrganizationById,
|
||||
OrganizationService,
|
||||
} from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
||||
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
|
||||
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
||||
import { getUserId } from "@bitwarden/common/auth/services/account.service";
|
||||
import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum";
|
||||
import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
|
||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||
@@ -77,34 +82,42 @@ export class AllApplicationsComponent implements OnInit {
|
||||
);
|
||||
|
||||
const organizationId = this.activatedRoute.snapshot.paramMap.get("organizationId") ?? "";
|
||||
combineLatest([
|
||||
this.dataService.applications$,
|
||||
this.criticalAppsService.getAppsListForOrg(organizationId),
|
||||
this.organizationService.get$(organizationId),
|
||||
])
|
||||
.pipe(
|
||||
takeUntilDestroyed(this.destroyRef),
|
||||
skipWhile(([_, __, organization]) => !organization),
|
||||
map(([applications, criticalApps, organization]) => {
|
||||
const criticalUrls = criticalApps.map((ca) => ca.uri);
|
||||
const data = applications?.map((app) => ({
|
||||
...app,
|
||||
isMarkedAsCritical: criticalUrls.includes(app.applicationName),
|
||||
})) as ApplicationHealthReportDetailWithCriticalFlag[];
|
||||
return { data, organization };
|
||||
}),
|
||||
)
|
||||
.subscribe(({ data, organization }) => {
|
||||
if (data) {
|
||||
this.dataSource.data = data;
|
||||
this.applicationSummary = this.reportService.generateApplicationsSummary(data);
|
||||
}
|
||||
if (organization) {
|
||||
this.organization = organization;
|
||||
}
|
||||
});
|
||||
const userId = await firstValueFrom(getUserId(this.accountService.activeAccount$));
|
||||
|
||||
this.isLoading$ = this.dataService.isLoading$;
|
||||
if (organizationId) {
|
||||
const organization$ = this.organizationService
|
||||
.organizations$(userId)
|
||||
.pipe(getOrganizationById(organizationId));
|
||||
|
||||
combineLatest([
|
||||
this.dataService.applications$,
|
||||
this.criticalAppsService.getAppsListForOrg(organizationId),
|
||||
organization$,
|
||||
])
|
||||
.pipe(
|
||||
takeUntilDestroyed(this.destroyRef),
|
||||
skipWhile(([_, __, organization]) => !organization),
|
||||
map(([applications, criticalApps, organization]) => {
|
||||
const criticalUrls = criticalApps.map((ca) => ca.uri);
|
||||
const data = applications?.map((app) => ({
|
||||
...app,
|
||||
isMarkedAsCritical: criticalUrls.includes(app.applicationName),
|
||||
})) as ApplicationHealthReportDetailWithCriticalFlag[];
|
||||
return { data, organization };
|
||||
}),
|
||||
)
|
||||
.subscribe(({ data, organization }) => {
|
||||
if (data) {
|
||||
this.dataSource.data = data;
|
||||
this.applicationSummary = this.reportService.generateApplicationsSummary(data);
|
||||
}
|
||||
if (organization) {
|
||||
this.organization = organization;
|
||||
}
|
||||
});
|
||||
|
||||
this.isLoading$ = this.dataService.isLoading$;
|
||||
}
|
||||
}
|
||||
|
||||
constructor(
|
||||
@@ -116,6 +129,7 @@ export class AllApplicationsComponent implements OnInit {
|
||||
protected dataService: RiskInsightsDataService,
|
||||
protected organizationService: OrganizationService,
|
||||
protected reportService: RiskInsightsReportService,
|
||||
private accountService: AccountService,
|
||||
protected criticalAppsService: CriticalAppsService,
|
||||
protected dialogService: DialogService,
|
||||
) {
|
||||
|
||||
@@ -10,8 +10,12 @@ import {
|
||||
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
||||
import { AuditService } from "@bitwarden/common/abstractions/audit.service";
|
||||
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
||||
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||
import { Utils } from "@bitwarden/common/platform/misc/utils";
|
||||
import { mockAccountServiceWith } from "@bitwarden/common/spec";
|
||||
import { PasswordStrengthServiceAbstraction } from "@bitwarden/common/tools/password-strength";
|
||||
import { UserId } from "@bitwarden/common/types/guid";
|
||||
import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service";
|
||||
import { TableModule } from "@bitwarden/components";
|
||||
import { LooseComponentsModule } from "@bitwarden/web-vault/app/shared";
|
||||
@@ -24,6 +28,7 @@ describe("PasswordHealthMembersUriComponent", () => {
|
||||
let fixture: ComponentFixture<PasswordHealthMembersURIComponent>;
|
||||
let cipherServiceMock: MockProxy<CipherService>;
|
||||
const passwordHealthServiceMock = mock<PasswordHealthService>();
|
||||
const userId = Utils.newGuid() as UserId;
|
||||
|
||||
const activeRouteParams = convertToParamMap({ organizationId: "orgId" });
|
||||
|
||||
@@ -36,6 +41,7 @@ describe("PasswordHealthMembersUriComponent", () => {
|
||||
{ provide: I18nService, useValue: mock<I18nService>() },
|
||||
{ provide: AuditService, useValue: mock<AuditService>() },
|
||||
{ provide: OrganizationService, useValue: mock<OrganizationService>() },
|
||||
{ provide: AccountService, useValue: mockAccountServiceWith(userId) },
|
||||
{
|
||||
provide: PasswordStrengthServiceAbstraction,
|
||||
useValue: mock<PasswordStrengthServiceAbstraction>(),
|
||||
|
||||
Reference in New Issue
Block a user