mirror of
https://github.com/bitwarden/browser
synced 2025-12-11 05:43:41 +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:
@@ -25,7 +25,7 @@ import { InternalOrganizationServiceAbstraction } from "@bitwarden/common/admin-
|
|||||||
import { PolicyApiServiceAbstraction } from "@bitwarden/common/admin-console/abstractions/policy/policy-api.service.abstraction";
|
import { PolicyApiServiceAbstraction } from "@bitwarden/common/admin-console/abstractions/policy/policy-api.service.abstraction";
|
||||||
import { InternalPolicyService as InternalPolicyServiceAbstraction } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction";
|
import { InternalPolicyService as InternalPolicyServiceAbstraction } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction";
|
||||||
import { ProviderService as ProviderServiceAbstraction } from "@bitwarden/common/admin-console/abstractions/provider.service";
|
import { ProviderService as ProviderServiceAbstraction } from "@bitwarden/common/admin-console/abstractions/provider.service";
|
||||||
import { OrganizationService } from "@bitwarden/common/admin-console/services/organization/organization.service";
|
import { DefaultOrganizationService } from "@bitwarden/common/admin-console/services/organization/default-organization.service";
|
||||||
import { PolicyApiService } from "@bitwarden/common/admin-console/services/policy/policy-api.service";
|
import { PolicyApiService } from "@bitwarden/common/admin-console/services/policy/policy-api.service";
|
||||||
import { PolicyService } from "@bitwarden/common/admin-console/services/policy/policy.service";
|
import { PolicyService } from "@bitwarden/common/admin-console/services/policy/policy.service";
|
||||||
import { ProviderService } from "@bitwarden/common/admin-console/services/provider.service";
|
import { ProviderService } from "@bitwarden/common/admin-console/services/provider.service";
|
||||||
@@ -669,7 +669,7 @@ export default class MainBackground {
|
|||||||
this.appIdService = new AppIdService(this.storageService, this.logService);
|
this.appIdService = new AppIdService(this.storageService, this.logService);
|
||||||
|
|
||||||
this.userDecryptionOptionsService = new UserDecryptionOptionsService(this.stateProvider);
|
this.userDecryptionOptionsService = new UserDecryptionOptionsService(this.stateProvider);
|
||||||
this.organizationService = new OrganizationService(this.stateProvider);
|
this.organizationService = new DefaultOrganizationService(this.stateProvider);
|
||||||
this.policyService = new PolicyService(this.stateProvider, this.organizationService);
|
this.policyService = new PolicyService(this.stateProvider, this.organizationService);
|
||||||
|
|
||||||
this.vaultTimeoutSettingsService = new VaultTimeoutSettingsService(
|
this.vaultTimeoutSettingsService = new VaultTimeoutSettingsService(
|
||||||
@@ -1248,6 +1248,7 @@ export default class MainBackground {
|
|||||||
this.cipherAuthorizationService = new DefaultCipherAuthorizationService(
|
this.cipherAuthorizationService = new DefaultCipherAuthorizationService(
|
||||||
this.collectionService,
|
this.collectionService,
|
||||||
this.organizationService,
|
this.organizationService,
|
||||||
|
this.accountService,
|
||||||
);
|
);
|
||||||
|
|
||||||
this.inlineMenuFieldQualificationService = new InlineMenuFieldQualificationService();
|
this.inlineMenuFieldQualificationService = new InlineMenuFieldQualificationService();
|
||||||
|
|||||||
@@ -31,8 +31,8 @@ import { LockService, LoginEmailService, PinServiceAbstraction } from "@bitwarde
|
|||||||
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
||||||
import { EventCollectionService as EventCollectionServiceAbstraction } from "@bitwarden/common/abstractions/event/event-collection.service";
|
import { EventCollectionService as EventCollectionServiceAbstraction } from "@bitwarden/common/abstractions/event/event-collection.service";
|
||||||
import { VaultTimeoutService } from "@bitwarden/common/abstractions/vault-timeout/vault-timeout.service";
|
import { VaultTimeoutService } from "@bitwarden/common/abstractions/vault-timeout/vault-timeout.service";
|
||||||
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
|
||||||
import { PolicyService } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction";
|
import { PolicyService } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction";
|
||||||
|
import { DefaultOrganizationService } from "@bitwarden/common/admin-console/services/organization/default-organization.service";
|
||||||
import {
|
import {
|
||||||
AccountService,
|
AccountService,
|
||||||
AccountService as AccountServiceAbstraction,
|
AccountService as AccountServiceAbstraction,
|
||||||
@@ -369,7 +369,7 @@ const safeProviders: SafeProvider[] = [
|
|||||||
provide: VaultFilterService,
|
provide: VaultFilterService,
|
||||||
useClass: VaultFilterService,
|
useClass: VaultFilterService,
|
||||||
deps: [
|
deps: [
|
||||||
OrganizationService,
|
DefaultOrganizationService,
|
||||||
FolderServiceAbstraction,
|
FolderServiceAbstraction,
|
||||||
CipherService,
|
CipherService,
|
||||||
CollectionService,
|
CollectionService,
|
||||||
|
|||||||
@@ -6,6 +6,10 @@ import { OrganizationService } from "@bitwarden/common/admin-console/abstraction
|
|||||||
import { PolicyService } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction";
|
import { PolicyService } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction";
|
||||||
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
|
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
|
||||||
import { Policy } from "@bitwarden/common/admin-console/models/domain/policy";
|
import { Policy } from "@bitwarden/common/admin-console/models/domain/policy";
|
||||||
|
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 { FamiliesPolicyService } from "./families-policy.service"; // Adjust the import as necessary
|
import { FamiliesPolicyService } from "./families-policy.service"; // Adjust the import as necessary
|
||||||
|
|
||||||
@@ -13,16 +17,20 @@ describe("FamiliesPolicyService", () => {
|
|||||||
let service: FamiliesPolicyService;
|
let service: FamiliesPolicyService;
|
||||||
let organizationService: MockProxy<OrganizationService>;
|
let organizationService: MockProxy<OrganizationService>;
|
||||||
let policyService: MockProxy<PolicyService>;
|
let policyService: MockProxy<PolicyService>;
|
||||||
|
let accountService: FakeAccountService;
|
||||||
|
const userId = Utils.newGuid() as UserId;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
organizationService = mock<OrganizationService>();
|
organizationService = mock<OrganizationService>();
|
||||||
policyService = mock<PolicyService>();
|
policyService = mock<PolicyService>();
|
||||||
|
accountService = mockAccountServiceWith(userId);
|
||||||
|
|
||||||
TestBed.configureTestingModule({
|
TestBed.configureTestingModule({
|
||||||
providers: [
|
providers: [
|
||||||
FamiliesPolicyService,
|
FamiliesPolicyService,
|
||||||
{ provide: OrganizationService, useValue: organizationService },
|
{ provide: OrganizationService, useValue: organizationService },
|
||||||
{ provide: PolicyService, useValue: policyService },
|
{ provide: PolicyService, useValue: policyService },
|
||||||
|
{ provide: AccountService, useValue: accountService },
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -40,7 +48,7 @@ describe("FamiliesPolicyService", () => {
|
|||||||
jest.spyOn(service, "hasSingleEnterpriseOrg$").mockReturnValue(of(true));
|
jest.spyOn(service, "hasSingleEnterpriseOrg$").mockReturnValue(of(true));
|
||||||
|
|
||||||
const organizations = [{ id: "org1", canManageSponsorships: true }] as Organization[];
|
const organizations = [{ id: "org1", canManageSponsorships: true }] as Organization[];
|
||||||
organizationService.getAll$.mockReturnValue(of(organizations));
|
organizationService.organizations$.mockReturnValue(of(organizations));
|
||||||
|
|
||||||
const policies = [{ organizationId: "org1", enabled: true }] as Policy[];
|
const policies = [{ organizationId: "org1", enabled: true }] as Policy[];
|
||||||
policyService.getAll$.mockReturnValue(of(policies));
|
policyService.getAll$.mockReturnValue(of(policies));
|
||||||
@@ -53,7 +61,7 @@ describe("FamiliesPolicyService", () => {
|
|||||||
jest.spyOn(service, "hasSingleEnterpriseOrg$").mockReturnValue(of(true));
|
jest.spyOn(service, "hasSingleEnterpriseOrg$").mockReturnValue(of(true));
|
||||||
|
|
||||||
const organizations = [{ id: "org1", canManageSponsorships: true }] as Organization[];
|
const organizations = [{ id: "org1", canManageSponsorships: true }] as Organization[];
|
||||||
organizationService.getAll$.mockReturnValue(of(organizations));
|
organizationService.organizations$.mockReturnValue(of(organizations));
|
||||||
|
|
||||||
const policies = [{ organizationId: "org1", enabled: false }] as Policy[];
|
const policies = [{ organizationId: "org1", enabled: false }] as Policy[];
|
||||||
policyService.getAll$.mockReturnValue(of(policies));
|
policyService.getAll$.mockReturnValue(of(policies));
|
||||||
@@ -64,7 +72,7 @@ describe("FamiliesPolicyService", () => {
|
|||||||
|
|
||||||
it("should return true when there is exactly one enterprise organization that can manage sponsorships", async () => {
|
it("should return true when there is exactly one enterprise organization that can manage sponsorships", async () => {
|
||||||
const organizations = [{ id: "org1", canManageSponsorships: true }] as Organization[];
|
const organizations = [{ id: "org1", canManageSponsorships: true }] as Organization[];
|
||||||
organizationService.getAll$.mockReturnValue(of(organizations));
|
organizationService.organizations$.mockReturnValue(of(organizations));
|
||||||
|
|
||||||
const result = await firstValueFrom(service.hasSingleEnterpriseOrg$());
|
const result = await firstValueFrom(service.hasSingleEnterpriseOrg$());
|
||||||
expect(result).toBe(true);
|
expect(result).toBe(true);
|
||||||
@@ -75,7 +83,7 @@ describe("FamiliesPolicyService", () => {
|
|||||||
{ id: "org1", canManageSponsorships: true },
|
{ id: "org1", canManageSponsorships: true },
|
||||||
{ id: "org2", canManageSponsorships: true },
|
{ id: "org2", canManageSponsorships: true },
|
||||||
] as Organization[];
|
] as Organization[];
|
||||||
organizationService.getAll$.mockReturnValue(of(organizations));
|
organizationService.organizations$.mockReturnValue(of(organizations));
|
||||||
|
|
||||||
const result = await firstValueFrom(service.hasSingleEnterpriseOrg$());
|
const result = await firstValueFrom(service.hasSingleEnterpriseOrg$());
|
||||||
expect(result).toBe(false);
|
expect(result).toBe(false);
|
||||||
|
|||||||
@@ -4,27 +4,34 @@ import { map, Observable, of, switchMap } from "rxjs";
|
|||||||
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
||||||
import { PolicyService } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction";
|
import { PolicyService } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction";
|
||||||
import { PolicyType } from "@bitwarden/common/admin-console/enums";
|
import { PolicyType } from "@bitwarden/common/admin-console/enums";
|
||||||
|
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
||||||
|
import { getUserId } from "@bitwarden/common/auth/services/account.service";
|
||||||
|
|
||||||
@Injectable({ providedIn: "root" })
|
@Injectable({ providedIn: "root" })
|
||||||
export class FamiliesPolicyService {
|
export class FamiliesPolicyService {
|
||||||
constructor(
|
constructor(
|
||||||
private policyService: PolicyService,
|
private policyService: PolicyService,
|
||||||
private organizationService: OrganizationService,
|
private organizationService: OrganizationService,
|
||||||
|
private accountService: AccountService,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
hasSingleEnterpriseOrg$(): Observable<boolean> {
|
hasSingleEnterpriseOrg$(): Observable<boolean> {
|
||||||
// Retrieve all organizations the user is part of
|
// Retrieve all organizations the user is part of
|
||||||
return this.organizationService.getAll$().pipe(
|
return getUserId(this.accountService.activeAccount$).pipe(
|
||||||
map((organizations) => {
|
switchMap((userId) =>
|
||||||
// Filter to only those organizations that can manage sponsorships
|
this.organizationService.organizations$(userId).pipe(
|
||||||
const sponsorshipOrgs = organizations.filter((org) => org.canManageSponsorships);
|
map((organizations) => {
|
||||||
|
// Filter to only those organizations that can manage sponsorships
|
||||||
|
const sponsorshipOrgs = organizations.filter((org) => org.canManageSponsorships);
|
||||||
|
|
||||||
// Check if there is exactly one organization that can manage sponsorships.
|
// Check if there is exactly one organization that can manage sponsorships.
|
||||||
// This is important because users that are part of multiple organizations
|
// This is important because users that are part of multiple organizations
|
||||||
// may always access free bitwarden family menu. We want to restrict access
|
// may always access free bitwarden family menu. We want to restrict access
|
||||||
// to the policy only when there is a single enterprise organization and the free family policy is turn.
|
// to the policy only when there is a single enterprise organization and the free family policy is turn.
|
||||||
return sponsorshipOrgs.length === 1;
|
return sponsorshipOrgs.length === 1;
|
||||||
}),
|
}),
|
||||||
|
),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -34,18 +41,22 @@ export class FamiliesPolicyService {
|
|||||||
if (!hasSingleEnterpriseOrg) {
|
if (!hasSingleEnterpriseOrg) {
|
||||||
return of(false);
|
return of(false);
|
||||||
}
|
}
|
||||||
return this.organizationService.getAll$().pipe(
|
return getUserId(this.accountService.activeAccount$).pipe(
|
||||||
map((organizations) => organizations.find((org) => org.canManageSponsorships)?.id),
|
switchMap((userId) =>
|
||||||
switchMap((enterpriseOrgId) =>
|
this.organizationService.organizations$(userId).pipe(
|
||||||
this.policyService
|
map((organizations) => organizations.find((org) => org.canManageSponsorships)?.id),
|
||||||
.getAll$(PolicyType.FreeFamiliesSponsorshipPolicy)
|
switchMap((enterpriseOrgId) =>
|
||||||
.pipe(
|
this.policyService
|
||||||
map(
|
.getAll$(PolicyType.FreeFamiliesSponsorshipPolicy)
|
||||||
(policies) =>
|
.pipe(
|
||||||
policies.find((policy) => policy.organizationId === enterpriseOrgId)?.enabled ??
|
map(
|
||||||
false,
|
(policies) =>
|
||||||
),
|
policies.find((policy) => policy.organizationId === enterpriseOrgId)
|
||||||
|
?.enabled ?? false,
|
||||||
|
),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}),
|
}),
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import { Observable, firstValueFrom, of, switchMap } from "rxjs";
|
|||||||
import { JslibModule } from "@bitwarden/angular/jslib.module";
|
import { JslibModule } from "@bitwarden/angular/jslib.module";
|
||||||
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
||||||
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
||||||
|
import { getUserId } from "@bitwarden/common/auth/services/account.service";
|
||||||
import { BillingAccountProfileStateService } from "@bitwarden/common/billing/abstractions/account/billing-account-profile-state.service";
|
import { BillingAccountProfileStateService } from "@bitwarden/common/billing/abstractions/account/billing-account-profile-state.service";
|
||||||
import { EnvironmentService } from "@bitwarden/common/platform/abstractions/environment.service";
|
import { EnvironmentService } from "@bitwarden/common/platform/abstractions/environment.service";
|
||||||
import { DialogService, ItemModule } from "@bitwarden/components";
|
import { DialogService, ItemModule } from "@bitwarden/components";
|
||||||
@@ -43,6 +44,9 @@ export class MoreFromBitwardenPageV2Component {
|
|||||||
private familiesPolicyService: FamiliesPolicyService,
|
private familiesPolicyService: FamiliesPolicyService,
|
||||||
private accountService: AccountService,
|
private accountService: AccountService,
|
||||||
) {
|
) {
|
||||||
|
this.familySponsorshipAvailable$ = getUserId(this.accountService.activeAccount$).pipe(
|
||||||
|
switchMap((userId) => this.organizationService.familySponsorshipAvailable$(userId)),
|
||||||
|
);
|
||||||
this.canAccessPremium$ = this.accountService.activeAccount$.pipe(
|
this.canAccessPremium$ = this.accountService.activeAccount$.pipe(
|
||||||
switchMap((account) =>
|
switchMap((account) =>
|
||||||
account
|
account
|
||||||
@@ -50,7 +54,6 @@ export class MoreFromBitwardenPageV2Component {
|
|||||||
: of(false),
|
: of(false),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
this.familySponsorshipAvailable$ = this.organizationService.familySponsorshipAvailable$;
|
|
||||||
this.hasSingleEnterpriseOrg$ = this.familiesPolicyService.hasSingleEnterpriseOrg$();
|
this.hasSingleEnterpriseOrg$ = this.familiesPolicyService.hasSingleEnterpriseOrg$();
|
||||||
this.isFreeFamilyPolicyEnabled$ = this.familiesPolicyService.isFreeFamilyPolicyEnabled$();
|
this.isFreeFamilyPolicyEnabled$ = this.familiesPolicyService.isFreeFamilyPolicyEnabled$();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ describe("OpenAttachmentsComponent", () => {
|
|||||||
} as Organization;
|
} as Organization;
|
||||||
|
|
||||||
const getCipher = jest.fn().mockResolvedValue(cipherDomain);
|
const getCipher = jest.fn().mockResolvedValue(cipherDomain);
|
||||||
const getOrganization = jest.fn().mockResolvedValue(org);
|
const organizations$ = jest.fn().mockReturnValue(of([org]));
|
||||||
const showFilePopoutMessage = jest.fn().mockReturnValue(false);
|
const showFilePopoutMessage = jest.fn().mockReturnValue(false);
|
||||||
|
|
||||||
const mockUserId = Utils.newGuid() as UserId;
|
const mockUserId = Utils.newGuid() as UserId;
|
||||||
@@ -67,7 +67,7 @@ describe("OpenAttachmentsComponent", () => {
|
|||||||
openCurrentPagePopout.mockClear();
|
openCurrentPagePopout.mockClear();
|
||||||
getCipher.mockClear();
|
getCipher.mockClear();
|
||||||
showToast.mockClear();
|
showToast.mockClear();
|
||||||
getOrganization.mockClear();
|
organizations$.mockClear();
|
||||||
showFilePopoutMessage.mockClear();
|
showFilePopoutMessage.mockClear();
|
||||||
hasPremiumFromAnySource$.next(true);
|
hasPremiumFromAnySource$.next(true);
|
||||||
|
|
||||||
@@ -89,7 +89,7 @@ describe("OpenAttachmentsComponent", () => {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
provide: OrganizationService,
|
provide: OrganizationService,
|
||||||
useValue: { get: getOrganization },
|
useValue: { organizations$ },
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
provide: FilePopoutUtilsService,
|
provide: FilePopoutUtilsService,
|
||||||
@@ -148,11 +148,11 @@ describe("OpenAttachmentsComponent", () => {
|
|||||||
|
|
||||||
describe("Free Orgs", () => {
|
describe("Free Orgs", () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
component.cipherIsAPartOfFreeOrg = undefined;
|
component.cipherIsAPartOfFreeOrg = false;
|
||||||
});
|
});
|
||||||
|
|
||||||
it("sets `cipherIsAPartOfFreeOrg` to false when the cipher is not a part of an organization", async () => {
|
it("sets `cipherIsAPartOfFreeOrg` to false when the cipher is not a part of an organization", async () => {
|
||||||
cipherView.organizationId = null;
|
cipherView.organizationId = "";
|
||||||
|
|
||||||
await component.ngOnInit();
|
await component.ngOnInit();
|
||||||
|
|
||||||
@@ -162,6 +162,7 @@ describe("OpenAttachmentsComponent", () => {
|
|||||||
it("sets `cipherIsAPartOfFreeOrg` to true when the cipher is a part of a free organization", async () => {
|
it("sets `cipherIsAPartOfFreeOrg` to true when the cipher is a part of a free organization", async () => {
|
||||||
cipherView.organizationId = "888-333-333";
|
cipherView.organizationId = "888-333-333";
|
||||||
org.productTierType = ProductTierType.Free;
|
org.productTierType = ProductTierType.Free;
|
||||||
|
org.id = cipherView.organizationId;
|
||||||
|
|
||||||
await component.ngOnInit();
|
await component.ngOnInit();
|
||||||
|
|
||||||
@@ -171,6 +172,7 @@ describe("OpenAttachmentsComponent", () => {
|
|||||||
it("sets `cipherIsAPartOfFreeOrg` to false when the organization is not free", async () => {
|
it("sets `cipherIsAPartOfFreeOrg` to false when the organization is not free", async () => {
|
||||||
cipherView.organizationId = "888-333-333";
|
cipherView.organizationId = "888-333-333";
|
||||||
org.productTierType = ProductTierType.Families;
|
org.productTierType = ProductTierType.Families;
|
||||||
|
org.id = cipherView.organizationId;
|
||||||
|
|
||||||
await component.ngOnInit();
|
await component.ngOnInit();
|
||||||
|
|
||||||
|
|||||||
@@ -7,8 +7,12 @@ import { Router } from "@angular/router";
|
|||||||
import { firstValueFrom, map, switchMap } from "rxjs";
|
import { firstValueFrom, map, switchMap } from "rxjs";
|
||||||
|
|
||||||
import { JslibModule } from "@bitwarden/angular/jslib.module";
|
import { JslibModule } from "@bitwarden/angular/jslib.module";
|
||||||
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 { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
||||||
|
import { getUserId } from "@bitwarden/common/auth/services/account.service";
|
||||||
import { BillingAccountProfileStateService } from "@bitwarden/common/billing/abstractions";
|
import { BillingAccountProfileStateService } from "@bitwarden/common/billing/abstractions";
|
||||||
import { ProductTierType } from "@bitwarden/common/billing/enums";
|
import { ProductTierType } from "@bitwarden/common/billing/enums";
|
||||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||||
@@ -86,7 +90,12 @@ export class OpenAttachmentsComponent implements OnInit {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const org = await this.organizationService.get(cipher.organizationId);
|
const userId = await firstValueFrom(getUserId(this.accountService.activeAccount$));
|
||||||
|
const org = await firstValueFrom(
|
||||||
|
this.organizationService
|
||||||
|
.organizations$(userId)
|
||||||
|
.pipe(getOrganizationById(cipher.organizationId)),
|
||||||
|
);
|
||||||
|
|
||||||
this.cipherIsAPartOfFreeOrg = org.productTierType === ProductTierType.Free;
|
this.cipherIsAPartOfFreeOrg = org.productTierType === ProductTierType.Free;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import { filter } from "rxjs/operators";
|
|||||||
import { JslibModule } from "@bitwarden/angular/jslib.module";
|
import { JslibModule } from "@bitwarden/angular/jslib.module";
|
||||||
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
||||||
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
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 { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||||
import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service";
|
import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service";
|
||||||
import { CipherRepromptType, CipherType } from "@bitwarden/common/vault/enums";
|
import { CipherRepromptType, CipherType } from "@bitwarden/common/vault/enums";
|
||||||
@@ -88,7 +89,8 @@ export class ItemMoreOptionsComponent implements OnInit {
|
|||||||
) {}
|
) {}
|
||||||
|
|
||||||
async ngOnInit(): Promise<void> {
|
async ngOnInit(): Promise<void> {
|
||||||
this.hasOrganizations = await this.organizationService.hasOrganizations();
|
const userId = await firstValueFrom(getUserId(this.accountService.activeAccount$));
|
||||||
|
this.hasOrganizations = await firstValueFrom(this.organizationService.hasOrganizations(userId));
|
||||||
}
|
}
|
||||||
|
|
||||||
get canEdit() {
|
get canEdit() {
|
||||||
|
|||||||
@@ -6,10 +6,12 @@ import { CollectionService, CollectionView } from "@bitwarden/admin-console/comm
|
|||||||
import { SearchService } from "@bitwarden/common/abstractions/search.service";
|
import { SearchService } from "@bitwarden/common/abstractions/search.service";
|
||||||
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
||||||
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
|
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
|
||||||
|
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
||||||
import { ProductTierType } from "@bitwarden/common/billing/enums";
|
import { ProductTierType } from "@bitwarden/common/billing/enums";
|
||||||
|
import { Utils } from "@bitwarden/common/platform/misc/utils";
|
||||||
import { SyncService } from "@bitwarden/common/platform/sync";
|
import { SyncService } from "@bitwarden/common/platform/sync";
|
||||||
import { ObservableTracker } from "@bitwarden/common/spec";
|
import { ObservableTracker, mockAccountServiceWith } from "@bitwarden/common/spec";
|
||||||
import { CipherId } from "@bitwarden/common/types/guid";
|
import { CipherId, UserId } from "@bitwarden/common/types/guid";
|
||||||
import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service";
|
import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service";
|
||||||
import { VaultSettingsService } from "@bitwarden/common/vault/abstractions/vault-settings/vault-settings.service";
|
import { VaultSettingsService } from "@bitwarden/common/vault/abstractions/vault-settings/vault-settings.service";
|
||||||
import { CipherType } from "@bitwarden/common/vault/enums";
|
import { CipherType } from "@bitwarden/common/vault/enums";
|
||||||
@@ -43,6 +45,8 @@ describe("VaultPopupItemsService", () => {
|
|||||||
const vaultAutofillServiceMock = mock<VaultPopupAutofillService>();
|
const vaultAutofillServiceMock = mock<VaultPopupAutofillService>();
|
||||||
const syncServiceMock = mock<SyncService>();
|
const syncServiceMock = mock<SyncService>();
|
||||||
const inlineMenuFieldQualificationServiceMock = mock<InlineMenuFieldQualificationService>();
|
const inlineMenuFieldQualificationServiceMock = mock<InlineMenuFieldQualificationService>();
|
||||||
|
const userId = Utils.newGuid() as UserId;
|
||||||
|
const accountServiceMock = mockAccountServiceWith(userId);
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
allCiphers = cipherFactory(10);
|
allCiphers = cipherFactory(10);
|
||||||
@@ -99,7 +103,7 @@ describe("VaultPopupItemsService", () => {
|
|||||||
{ id: "col2", name: "Collection 2" } as CollectionView,
|
{ id: "col2", name: "Collection 2" } as CollectionView,
|
||||||
];
|
];
|
||||||
|
|
||||||
organizationServiceMock.organizations$ = new BehaviorSubject([mockOrg]);
|
organizationServiceMock.organizations$.mockReturnValue(new BehaviorSubject([mockOrg]));
|
||||||
collectionService.decryptedCollections$ = new BehaviorSubject(mockCollections);
|
collectionService.decryptedCollections$ = new BehaviorSubject(mockCollections);
|
||||||
|
|
||||||
activeUserLastSync$ = new BehaviorSubject(new Date());
|
activeUserLastSync$ = new BehaviorSubject(new Date());
|
||||||
@@ -111,6 +115,7 @@ describe("VaultPopupItemsService", () => {
|
|||||||
{ provide: VaultSettingsService, useValue: vaultSettingsServiceMock },
|
{ provide: VaultSettingsService, useValue: vaultSettingsServiceMock },
|
||||||
{ provide: SearchService, useValue: searchService },
|
{ provide: SearchService, useValue: searchService },
|
||||||
{ provide: OrganizationService, useValue: organizationServiceMock },
|
{ provide: OrganizationService, useValue: organizationServiceMock },
|
||||||
|
{ provide: AccountService, useValue: accountServiceMock },
|
||||||
{ provide: VaultPopupListFiltersService, useValue: vaultPopupListFiltersServiceMock },
|
{ provide: VaultPopupListFiltersService, useValue: vaultPopupListFiltersServiceMock },
|
||||||
{ provide: CollectionService, useValue: collectionService },
|
{ provide: CollectionService, useValue: collectionService },
|
||||||
{ provide: VaultPopupAutofillService, useValue: vaultAutofillServiceMock },
|
{ provide: VaultPopupAutofillService, useValue: vaultAutofillServiceMock },
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ import {
|
|||||||
import { CollectionService } from "@bitwarden/admin-console/common";
|
import { CollectionService } from "@bitwarden/admin-console/common";
|
||||||
import { SearchService } from "@bitwarden/common/abstractions/search.service";
|
import { SearchService } from "@bitwarden/common/abstractions/search.service";
|
||||||
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
||||||
|
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
||||||
import { Utils } from "@bitwarden/common/platform/misc/utils";
|
import { Utils } from "@bitwarden/common/platform/misc/utils";
|
||||||
import { SyncService } from "@bitwarden/common/platform/sync";
|
import { SyncService } from "@bitwarden/common/platform/sync";
|
||||||
import { CollectionId, OrganizationId } from "@bitwarden/common/types/guid";
|
import { CollectionId, OrganizationId } from "@bitwarden/common/types/guid";
|
||||||
@@ -56,6 +57,9 @@ export class VaultPopupItemsService {
|
|||||||
|
|
||||||
latestSearchText$: Observable<string> = this._searchText$.asObservable();
|
latestSearchText$: Observable<string> = this._searchText$.asObservable();
|
||||||
|
|
||||||
|
private organizations$ = this.accountService.activeAccount$.pipe(
|
||||||
|
switchMap((account) => this.organizationService.organizations$(account?.id)),
|
||||||
|
);
|
||||||
/**
|
/**
|
||||||
* Observable that contains the list of other cipher types that should be shown
|
* Observable that contains the list of other cipher types that should be shown
|
||||||
* in the autofill section of the Vault tab. Depends on vault settings.
|
* in the autofill section of the Vault tab. Depends on vault settings.
|
||||||
@@ -97,10 +101,7 @@ export class VaultPopupItemsService {
|
|||||||
|
|
||||||
private _activeCipherList$: Observable<PopupCipherView[]> = this._allDecryptedCiphers$.pipe(
|
private _activeCipherList$: Observable<PopupCipherView[]> = this._allDecryptedCiphers$.pipe(
|
||||||
switchMap((ciphers) =>
|
switchMap((ciphers) =>
|
||||||
combineLatest([
|
combineLatest([this.organizations$, this.collectionService.decryptedCollections$]).pipe(
|
||||||
this.organizationService.organizations$,
|
|
||||||
this.collectionService.decryptedCollections$,
|
|
||||||
]).pipe(
|
|
||||||
map(([organizations, collections]) => {
|
map(([organizations, collections]) => {
|
||||||
const orgMap = Object.fromEntries(organizations.map((org) => [org.id, org]));
|
const orgMap = Object.fromEntries(organizations.map((org) => [org.id, org]));
|
||||||
const collectionMap = Object.fromEntries(collections.map((col) => [col.id, col]));
|
const collectionMap = Object.fromEntries(collections.map((col) => [col.id, col]));
|
||||||
@@ -232,7 +233,7 @@ export class VaultPopupItemsService {
|
|||||||
/** Observable that indicates when the user should see the deactivated org state */
|
/** Observable that indicates when the user should see the deactivated org state */
|
||||||
showDeactivatedOrg$: Observable<boolean> = combineLatest([
|
showDeactivatedOrg$: Observable<boolean> = combineLatest([
|
||||||
this.vaultPopupListFiltersService.filters$.pipe(distinctUntilKeyChanged("organization")),
|
this.vaultPopupListFiltersService.filters$.pipe(distinctUntilKeyChanged("organization")),
|
||||||
this.organizationService.organizations$,
|
this.organizations$,
|
||||||
]).pipe(
|
]).pipe(
|
||||||
map(([filters, orgs]) => {
|
map(([filters, orgs]) => {
|
||||||
if (!filters.organization || filters.organization.id === MY_VAULT_ID) {
|
if (!filters.organization || filters.organization.id === MY_VAULT_ID) {
|
||||||
@@ -249,10 +250,7 @@ export class VaultPopupItemsService {
|
|||||||
*/
|
*/
|
||||||
deletedCiphers$: Observable<PopupCipherView[]> = this._allDecryptedCiphers$.pipe(
|
deletedCiphers$: Observable<PopupCipherView[]> = this._allDecryptedCiphers$.pipe(
|
||||||
switchMap((ciphers) =>
|
switchMap((ciphers) =>
|
||||||
combineLatest([
|
combineLatest([this.organizations$, this.collectionService.decryptedCollections$]).pipe(
|
||||||
this.organizationService.organizations$,
|
|
||||||
this.collectionService.decryptedCollections$,
|
|
||||||
]).pipe(
|
|
||||||
map(([organizations, collections]) => {
|
map(([organizations, collections]) => {
|
||||||
const orgMap = Object.fromEntries(organizations.map((org) => [org.id, org]));
|
const orgMap = Object.fromEntries(organizations.map((org) => [org.id, org]));
|
||||||
const collectionMap = Object.fromEntries(collections.map((col) => [col.id, col]));
|
const collectionMap = Object.fromEntries(collections.map((col) => [col.id, col]));
|
||||||
@@ -281,6 +279,7 @@ export class VaultPopupItemsService {
|
|||||||
private collectionService: CollectionService,
|
private collectionService: CollectionService,
|
||||||
private vaultPopupAutofillService: VaultPopupAutofillService,
|
private vaultPopupAutofillService: VaultPopupAutofillService,
|
||||||
private syncService: SyncService,
|
private syncService: SyncService,
|
||||||
|
private accountService: AccountService,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
applyFilter(newSearchText: string) {
|
applyFilter(newSearchText: string) {
|
||||||
|
|||||||
@@ -23,7 +23,9 @@ import { MY_VAULT_ID, VaultPopupListFiltersService } from "./vault-popup-list-fi
|
|||||||
|
|
||||||
describe("VaultPopupListFiltersService", () => {
|
describe("VaultPopupListFiltersService", () => {
|
||||||
let service: VaultPopupListFiltersService;
|
let service: VaultPopupListFiltersService;
|
||||||
const memberOrganizations$ = new BehaviorSubject<Organization[]>([]);
|
const _memberOrganizations$ = new BehaviorSubject<Organization[]>([]);
|
||||||
|
const memberOrganizations$ = (userId: UserId) => _memberOrganizations$;
|
||||||
|
const organizations$ = new BehaviorSubject<Organization[]>([]);
|
||||||
const folderViews$ = new BehaviorSubject([]);
|
const folderViews$ = new BehaviorSubject([]);
|
||||||
const cipherViews$ = new BehaviorSubject({});
|
const cipherViews$ = new BehaviorSubject({});
|
||||||
const decryptedCollections$ = new BehaviorSubject<CollectionView[]>([]);
|
const decryptedCollections$ = new BehaviorSubject<CollectionView[]>([]);
|
||||||
@@ -44,6 +46,7 @@ describe("VaultPopupListFiltersService", () => {
|
|||||||
|
|
||||||
const organizationService = {
|
const organizationService = {
|
||||||
memberOrganizations$,
|
memberOrganizations$,
|
||||||
|
organizations$,
|
||||||
} as unknown as OrganizationService;
|
} as unknown as OrganizationService;
|
||||||
|
|
||||||
const i18nService = {
|
const i18nService = {
|
||||||
@@ -58,7 +61,7 @@ describe("VaultPopupListFiltersService", () => {
|
|||||||
const update = jest.fn().mockResolvedValue(undefined);
|
const update = jest.fn().mockResolvedValue(undefined);
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
memberOrganizations$.next([]);
|
_memberOrganizations$.next([]);
|
||||||
decryptedCollections$.next([]);
|
decryptedCollections$.next([]);
|
||||||
policyAppliesToActiveUser$.next(false);
|
policyAppliesToActiveUser$.next(false);
|
||||||
policyService.policyAppliesToActiveUser$.mockClear();
|
policyService.policyAppliesToActiveUser$.mockClear();
|
||||||
@@ -135,7 +138,7 @@ describe("VaultPopupListFiltersService", () => {
|
|||||||
|
|
||||||
describe("organizations$", () => {
|
describe("organizations$", () => {
|
||||||
it('does not add "myVault" to the list of organizations when there are no organizations', (done) => {
|
it('does not add "myVault" to the list of organizations when there are no organizations', (done) => {
|
||||||
memberOrganizations$.next([]);
|
_memberOrganizations$.next([]);
|
||||||
|
|
||||||
service.organizations$.subscribe((organizations) => {
|
service.organizations$.subscribe((organizations) => {
|
||||||
expect(organizations.map((o) => o.label)).toEqual([]);
|
expect(organizations.map((o) => o.label)).toEqual([]);
|
||||||
@@ -145,7 +148,7 @@ describe("VaultPopupListFiltersService", () => {
|
|||||||
|
|
||||||
it('adds "myVault" to the list of organizations when there are other organizations', (done) => {
|
it('adds "myVault" to the list of organizations when there are other organizations', (done) => {
|
||||||
const orgs = [{ name: "bobby's org", id: "1234-3323-23223" }] as Organization[];
|
const orgs = [{ name: "bobby's org", id: "1234-3323-23223" }] as Organization[];
|
||||||
memberOrganizations$.next(orgs);
|
_memberOrganizations$.next(orgs);
|
||||||
|
|
||||||
service.organizations$.subscribe((organizations) => {
|
service.organizations$.subscribe((organizations) => {
|
||||||
expect(organizations.map((o) => o.label)).toEqual(["myVault", "bobby's org"]);
|
expect(organizations.map((o) => o.label)).toEqual(["myVault", "bobby's org"]);
|
||||||
@@ -158,7 +161,7 @@ describe("VaultPopupListFiltersService", () => {
|
|||||||
{ name: "bobby's org", id: "1234-3323-23223" },
|
{ name: "bobby's org", id: "1234-3323-23223" },
|
||||||
{ name: "alice's org", id: "2223-4343-99888" },
|
{ name: "alice's org", id: "2223-4343-99888" },
|
||||||
] as Organization[];
|
] as Organization[];
|
||||||
memberOrganizations$.next(orgs);
|
_memberOrganizations$.next(orgs);
|
||||||
|
|
||||||
service.organizations$.subscribe((organizations) => {
|
service.organizations$.subscribe((organizations) => {
|
||||||
expect(organizations.map((o) => o.label)).toEqual([
|
expect(organizations.map((o) => o.label)).toEqual([
|
||||||
@@ -179,7 +182,7 @@ describe("VaultPopupListFiltersService", () => {
|
|||||||
|
|
||||||
it("returns an empty array when the policy applies and there is a single organization", (done) => {
|
it("returns an empty array when the policy applies and there is a single organization", (done) => {
|
||||||
policyAppliesToActiveUser$.next(true);
|
policyAppliesToActiveUser$.next(true);
|
||||||
memberOrganizations$.next([
|
_memberOrganizations$.next([
|
||||||
{ name: "bobby's org", id: "1234-3323-23223" },
|
{ name: "bobby's org", id: "1234-3323-23223" },
|
||||||
] as Organization[]);
|
] as Organization[]);
|
||||||
|
|
||||||
@@ -196,7 +199,7 @@ describe("VaultPopupListFiltersService", () => {
|
|||||||
{ name: "alice's org", id: "2223-4343-99888" },
|
{ name: "alice's org", id: "2223-4343-99888" },
|
||||||
] as Organization[];
|
] as Organization[];
|
||||||
|
|
||||||
memberOrganizations$.next(orgs);
|
_memberOrganizations$.next(orgs);
|
||||||
|
|
||||||
service.organizations$.subscribe((organizations) => {
|
service.organizations$.subscribe((organizations) => {
|
||||||
expect(organizations.map((o) => o.label)).toEqual([
|
expect(organizations.map((o) => o.label)).toEqual([
|
||||||
@@ -216,7 +219,7 @@ describe("VaultPopupListFiltersService", () => {
|
|||||||
{ name: "catherine's org", id: "77733-4343-99888" },
|
{ name: "catherine's org", id: "77733-4343-99888" },
|
||||||
] as Organization[];
|
] as Organization[];
|
||||||
|
|
||||||
memberOrganizations$.next(orgs);
|
_memberOrganizations$.next(orgs);
|
||||||
|
|
||||||
service.organizations$.subscribe((organizations) => {
|
service.organizations$.subscribe((organizations) => {
|
||||||
expect(organizations.map((o) => o.label)).toEqual([
|
expect(organizations.map((o) => o.label)).toEqual([
|
||||||
@@ -240,7 +243,7 @@ describe("VaultPopupListFiltersService", () => {
|
|||||||
},
|
},
|
||||||
] as Organization[];
|
] as Organization[];
|
||||||
|
|
||||||
memberOrganizations$.next(orgs);
|
_memberOrganizations$.next(orgs);
|
||||||
|
|
||||||
service.organizations$.subscribe((organizations) => {
|
service.organizations$.subscribe((organizations) => {
|
||||||
expect(organizations.map((o) => o.icon)).toEqual(["bwi-user", "bwi-family"]);
|
expect(organizations.map((o) => o.icon)).toEqual(["bwi-user", "bwi-family"]);
|
||||||
@@ -258,7 +261,7 @@ describe("VaultPopupListFiltersService", () => {
|
|||||||
},
|
},
|
||||||
] as Organization[];
|
] as Organization[];
|
||||||
|
|
||||||
memberOrganizations$.next(orgs);
|
_memberOrganizations$.next(orgs);
|
||||||
|
|
||||||
service.organizations$.subscribe((organizations) => {
|
service.organizations$.subscribe((organizations) => {
|
||||||
expect(organizations.map((o) => o.icon)).toEqual(["bwi-user", "bwi-family"]);
|
expect(organizations.map((o) => o.icon)).toEqual(["bwi-user", "bwi-family"]);
|
||||||
@@ -276,7 +279,7 @@ describe("VaultPopupListFiltersService", () => {
|
|||||||
},
|
},
|
||||||
] as Organization[];
|
] as Organization[];
|
||||||
|
|
||||||
memberOrganizations$.next(orgs);
|
_memberOrganizations$.next(orgs);
|
||||||
|
|
||||||
service.organizations$.subscribe((organizations) => {
|
service.organizations$.subscribe((organizations) => {
|
||||||
expect(organizations.map((o) => o.icon)).toEqual([
|
expect(organizations.map((o) => o.icon)).toEqual([
|
||||||
|
|||||||
@@ -208,7 +208,9 @@ export class VaultPopupListFiltersService {
|
|||||||
* Organization array structured to be directly passed to `ChipSelectComponent`
|
* Organization array structured to be directly passed to `ChipSelectComponent`
|
||||||
*/
|
*/
|
||||||
organizations$: Observable<ChipSelectOption<Organization>[]> = combineLatest([
|
organizations$: Observable<ChipSelectOption<Organization>[]> = combineLatest([
|
||||||
this.organizationService.memberOrganizations$,
|
this.accountService.activeAccount$.pipe(
|
||||||
|
switchMap((account) => this.organizationService.memberOrganizations$(account?.id)),
|
||||||
|
),
|
||||||
this.policyService.policyAppliesToActiveUser$(PolicyType.PersonalOwnership),
|
this.policyService.policyAppliesToActiveUser$(PolicyType.PersonalOwnership),
|
||||||
]).pipe(
|
]).pipe(
|
||||||
map(([orgs, personalOwnershipApplies]): [Organization[], boolean] => [
|
map(([orgs, personalOwnershipApplies]): [Organization[], boolean] => [
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ export class VaultFilterService extends BaseVaultFilterService {
|
|||||||
this.vaultFilter.myVaultOnly = false;
|
this.vaultFilter.myVaultOnly = false;
|
||||||
this.vaultFilter.selectedOrganizationId = null;
|
this.vaultFilter.selectedOrganizationId = null;
|
||||||
|
|
||||||
this.accountService.activeAccount$.subscribe((account) => {
|
accountService.activeAccount$.subscribe((account) => {
|
||||||
this.setVaultFilter(this.allVaults);
|
this.setVaultFilter(this.allVaults);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import { SearchService } from "@bitwarden/common/abstractions/search.service";
|
|||||||
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
||||||
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
|
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
|
||||||
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
||||||
|
import { getUserId } from "@bitwarden/common/auth/services/account.service";
|
||||||
import { BillingAccountProfileStateService } from "@bitwarden/common/billing/abstractions/account/billing-account-profile-state.service";
|
import { BillingAccountProfileStateService } from "@bitwarden/common/billing/abstractions/account/billing-account-profile-state.service";
|
||||||
import { EventType } from "@bitwarden/common/enums";
|
import { EventType } from "@bitwarden/common/enums";
|
||||||
import { CardExport } from "@bitwarden/common/models/export/card.export";
|
import { CardExport } from "@bitwarden/common/models/export/card.export";
|
||||||
@@ -479,10 +480,18 @@ export class GetCommand extends DownloadCommand {
|
|||||||
|
|
||||||
private async getOrganization(id: string) {
|
private async getOrganization(id: string) {
|
||||||
let org: Organization = null;
|
let org: Organization = null;
|
||||||
|
const userId = await firstValueFrom(getUserId(this.accountService.activeAccount$));
|
||||||
|
if (!userId) {
|
||||||
|
return Response.badRequest("No user found.");
|
||||||
|
}
|
||||||
if (Utils.isGuid(id)) {
|
if (Utils.isGuid(id)) {
|
||||||
org = await this.organizationService.getFromState(id);
|
org = await firstValueFrom(
|
||||||
|
this.organizationService
|
||||||
|
.organizations$(userId)
|
||||||
|
.pipe(map((organizations) => organizations.find((o) => o.id === id))),
|
||||||
|
);
|
||||||
} else if (id.trim() !== "") {
|
} else if (id.trim() !== "") {
|
||||||
let orgs = await firstValueFrom(this.organizationService.organizations$);
|
let orgs = await firstValueFrom(this.organizationService.organizations$(userId));
|
||||||
orgs = CliUtils.searchOrganizations(orgs, id);
|
orgs = CliUtils.searchOrganizations(orgs, id);
|
||||||
if (orgs.length > 1) {
|
if (orgs.length > 1) {
|
||||||
return Response.multipleResults(orgs.map((c) => c.id));
|
return Response.multipleResults(orgs.map((c) => c.id));
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import { EventCollectionService } from "@bitwarden/common/abstractions/event/eve
|
|||||||
import { SearchService } from "@bitwarden/common/abstractions/search.service";
|
import { SearchService } from "@bitwarden/common/abstractions/search.service";
|
||||||
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
||||||
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
||||||
|
import { getUserId } from "@bitwarden/common/auth/services/account.service";
|
||||||
import { EventType } from "@bitwarden/common/enums";
|
import { EventType } from "@bitwarden/common/enums";
|
||||||
import { ListResponse as ApiListResponse } from "@bitwarden/common/models/response/list.response";
|
import { ListResponse as ApiListResponse } from "@bitwarden/common/models/response/list.response";
|
||||||
import { Utils } from "@bitwarden/common/platform/misc/utils";
|
import { Utils } from "@bitwarden/common/platform/misc/utils";
|
||||||
@@ -177,7 +178,15 @@ export class ListCommand {
|
|||||||
if (!Utils.isGuid(options.organizationId)) {
|
if (!Utils.isGuid(options.organizationId)) {
|
||||||
return Response.badRequest("`" + options.organizationId + "` is not a GUID.");
|
return Response.badRequest("`" + options.organizationId + "` is not a GUID.");
|
||||||
}
|
}
|
||||||
const organization = await this.organizationService.getFromState(options.organizationId);
|
const userId = await firstValueFrom(getUserId(this.accountService.activeAccount$));
|
||||||
|
if (!userId) {
|
||||||
|
return Response.badRequest("No user found.");
|
||||||
|
}
|
||||||
|
const organization = await firstValueFrom(
|
||||||
|
this.organizationService
|
||||||
|
.organizations$(userId)
|
||||||
|
.pipe(map((organizatons) => organizatons.find((o) => o.id == options.organizationId))),
|
||||||
|
);
|
||||||
if (organization == null) {
|
if (organization == null) {
|
||||||
return Response.error("Organization not found.");
|
return Response.error("Organization not found.");
|
||||||
}
|
}
|
||||||
@@ -210,7 +219,16 @@ export class ListCommand {
|
|||||||
if (!Utils.isGuid(options.organizationId)) {
|
if (!Utils.isGuid(options.organizationId)) {
|
||||||
return Response.badRequest("`" + options.organizationId + "` is not a GUID.");
|
return Response.badRequest("`" + options.organizationId + "` is not a GUID.");
|
||||||
}
|
}
|
||||||
const organization = await this.organizationService.getFromState(options.organizationId);
|
const userId = await firstValueFrom(getUserId(this.accountService.activeAccount$));
|
||||||
|
|
||||||
|
if (!userId) {
|
||||||
|
return Response.badRequest("No user found.");
|
||||||
|
}
|
||||||
|
const organization = await firstValueFrom(
|
||||||
|
this.organizationService
|
||||||
|
.organizations$(userId)
|
||||||
|
.pipe(map((organizatons) => organizatons.find((o) => o.id == options.organizationId))),
|
||||||
|
);
|
||||||
if (organization == null) {
|
if (organization == null) {
|
||||||
return Response.error("Organization not found.");
|
return Response.error("Organization not found.");
|
||||||
}
|
}
|
||||||
@@ -236,7 +254,12 @@ export class ListCommand {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private async listOrganizations(options: Options) {
|
private async listOrganizations(options: Options) {
|
||||||
let organizations = await firstValueFrom(this.organizationService.memberOrganizations$);
|
const userId = await firstValueFrom(getUserId(this.accountService.activeAccount$));
|
||||||
|
|
||||||
|
if (!userId) {
|
||||||
|
return Response.badRequest("No user found.");
|
||||||
|
}
|
||||||
|
let organizations = await firstValueFrom(this.organizationService.memberOrganizations$(userId));
|
||||||
|
|
||||||
if (options.search != null && options.search.trim() !== "") {
|
if (options.search != null && options.search.trim() !== "") {
|
||||||
organizations = CliUtils.searchOrganizations(organizations, options.search);
|
organizations = CliUtils.searchOrganizations(organizations, options.search);
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import * as fs from "fs";
|
|||||||
import * as path from "path";
|
import * as path from "path";
|
||||||
|
|
||||||
import * as jsdom from "jsdom";
|
import * as jsdom from "jsdom";
|
||||||
import { firstValueFrom, map } from "rxjs";
|
import { firstValueFrom } from "rxjs";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
OrganizationUserApiService,
|
OrganizationUserApiService,
|
||||||
@@ -25,8 +25,8 @@ import { EventUploadService as EventUploadServiceAbstraction } from "@bitwarden/
|
|||||||
import { OrganizationApiServiceAbstraction } from "@bitwarden/common/admin-console/abstractions/organization/organization-api.service.abstraction";
|
import { OrganizationApiServiceAbstraction } from "@bitwarden/common/admin-console/abstractions/organization/organization-api.service.abstraction";
|
||||||
import { PolicyApiServiceAbstraction } from "@bitwarden/common/admin-console/abstractions/policy/policy-api.service.abstraction";
|
import { PolicyApiServiceAbstraction } from "@bitwarden/common/admin-console/abstractions/policy/policy-api.service.abstraction";
|
||||||
import { ProviderApiServiceAbstraction } from "@bitwarden/common/admin-console/abstractions/provider/provider-api.service.abstraction";
|
import { ProviderApiServiceAbstraction } from "@bitwarden/common/admin-console/abstractions/provider/provider-api.service.abstraction";
|
||||||
|
import { DefaultOrganizationService } from "@bitwarden/common/admin-console/services/organization/default-organization.service";
|
||||||
import { OrganizationApiService } from "@bitwarden/common/admin-console/services/organization/organization-api.service";
|
import { OrganizationApiService } from "@bitwarden/common/admin-console/services/organization/organization-api.service";
|
||||||
import { OrganizationService } from "@bitwarden/common/admin-console/services/organization/organization.service";
|
|
||||||
import { PolicyApiService } from "@bitwarden/common/admin-console/services/policy/policy-api.service";
|
import { PolicyApiService } from "@bitwarden/common/admin-console/services/policy/policy-api.service";
|
||||||
import { PolicyService } from "@bitwarden/common/admin-console/services/policy/policy.service";
|
import { PolicyService } from "@bitwarden/common/admin-console/services/policy/policy.service";
|
||||||
import { ProviderApiService } from "@bitwarden/common/admin-console/services/provider/provider-api.service";
|
import { ProviderApiService } from "@bitwarden/common/admin-console/services/provider/provider-api.service";
|
||||||
@@ -36,7 +36,10 @@ import { AvatarService as AvatarServiceAbstraction } from "@bitwarden/common/aut
|
|||||||
import { DeviceTrustServiceAbstraction } from "@bitwarden/common/auth/abstractions/device-trust.service.abstraction";
|
import { DeviceTrustServiceAbstraction } from "@bitwarden/common/auth/abstractions/device-trust.service.abstraction";
|
||||||
import { DevicesApiServiceAbstraction } from "@bitwarden/common/auth/abstractions/devices-api.service.abstraction";
|
import { DevicesApiServiceAbstraction } from "@bitwarden/common/auth/abstractions/devices-api.service.abstraction";
|
||||||
import { InternalMasterPasswordServiceAbstraction } from "@bitwarden/common/auth/abstractions/master-password.service.abstraction";
|
import { InternalMasterPasswordServiceAbstraction } from "@bitwarden/common/auth/abstractions/master-password.service.abstraction";
|
||||||
import { AccountServiceImplementation } from "@bitwarden/common/auth/services/account.service";
|
import {
|
||||||
|
AccountServiceImplementation,
|
||||||
|
getUserId,
|
||||||
|
} from "@bitwarden/common/auth/services/account.service";
|
||||||
import { AuthService } from "@bitwarden/common/auth/services/auth.service";
|
import { AuthService } from "@bitwarden/common/auth/services/auth.service";
|
||||||
import { AvatarService } from "@bitwarden/common/auth/services/avatar.service";
|
import { AvatarService } from "@bitwarden/common/auth/services/avatar.service";
|
||||||
import { DeviceTrustService } from "@bitwarden/common/auth/services/device-trust.service.implementation";
|
import { DeviceTrustService } from "@bitwarden/common/auth/services/device-trust.service.implementation";
|
||||||
@@ -238,7 +241,8 @@ export class ServiceContainer {
|
|||||||
stateService: StateService;
|
stateService: StateService;
|
||||||
autofillSettingsService: AutofillSettingsServiceAbstraction;
|
autofillSettingsService: AutofillSettingsServiceAbstraction;
|
||||||
domainSettingsService: DomainSettingsService;
|
domainSettingsService: DomainSettingsService;
|
||||||
organizationService: OrganizationService;
|
organizationService: DefaultOrganizationService;
|
||||||
|
DefaultOrganizationService: DefaultOrganizationService;
|
||||||
providerService: ProviderService;
|
providerService: ProviderService;
|
||||||
twoFactorService: TwoFactorService;
|
twoFactorService: TwoFactorService;
|
||||||
folderApiService: FolderApiService;
|
folderApiService: FolderApiService;
|
||||||
@@ -450,7 +454,7 @@ export class ServiceContainer {
|
|||||||
this.biometricStateService = new DefaultBiometricStateService(this.stateProvider);
|
this.biometricStateService = new DefaultBiometricStateService(this.stateProvider);
|
||||||
this.userDecryptionOptionsService = new UserDecryptionOptionsService(this.stateProvider);
|
this.userDecryptionOptionsService = new UserDecryptionOptionsService(this.stateProvider);
|
||||||
|
|
||||||
this.organizationService = new OrganizationService(this.stateProvider);
|
this.organizationService = new DefaultOrganizationService(this.stateProvider);
|
||||||
this.policyService = new PolicyService(this.stateProvider, this.organizationService);
|
this.policyService = new PolicyService(this.stateProvider, this.organizationService);
|
||||||
|
|
||||||
this.vaultTimeoutSettingsService = new VaultTimeoutSettingsService(
|
this.vaultTimeoutSettingsService = new VaultTimeoutSettingsService(
|
||||||
@@ -824,6 +828,7 @@ export class ServiceContainer {
|
|||||||
this.cipherAuthorizationService = new DefaultCipherAuthorizationService(
|
this.cipherAuthorizationService = new DefaultCipherAuthorizationService(
|
||||||
this.collectionService,
|
this.collectionService,
|
||||||
this.organizationService,
|
this.organizationService,
|
||||||
|
this.accountService,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -831,7 +836,7 @@ export class ServiceContainer {
|
|||||||
this.authService.logOut(() => {
|
this.authService.logOut(() => {
|
||||||
/* Do nothing */
|
/* Do nothing */
|
||||||
});
|
});
|
||||||
const userId = await firstValueFrom(this.accountService.activeAccount$.pipe(map((a) => a?.id)));
|
const userId = await firstValueFrom(getUserId(this.accountService.activeAccount$));
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
this.eventUploadService.uploadEvents(userId as UserId),
|
this.eventUploadService.uploadEvents(userId as UserId),
|
||||||
this.keyService.clearKeys(),
|
this.keyService.clearKeys(),
|
||||||
|
|||||||
@@ -2,8 +2,10 @@
|
|||||||
// @ts-strict-ignore
|
// @ts-strict-ignore
|
||||||
import { OptionValues } from "commander";
|
import { OptionValues } from "commander";
|
||||||
import * as inquirer from "inquirer";
|
import * as inquirer from "inquirer";
|
||||||
|
import { firstValueFrom, map } from "rxjs";
|
||||||
|
|
||||||
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
||||||
|
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
||||||
import { SyncService } from "@bitwarden/common/vault/abstractions/sync/sync.service.abstraction";
|
import { SyncService } from "@bitwarden/common/vault/abstractions/sync/sync.service.abstraction";
|
||||||
import { ImportServiceAbstraction, ImportType } from "@bitwarden/importer/core";
|
import { ImportServiceAbstraction, ImportType } from "@bitwarden/importer/core";
|
||||||
|
|
||||||
@@ -16,12 +18,23 @@ export class ImportCommand {
|
|||||||
private importService: ImportServiceAbstraction,
|
private importService: ImportServiceAbstraction,
|
||||||
private organizationService: OrganizationService,
|
private organizationService: OrganizationService,
|
||||||
private syncService: SyncService,
|
private syncService: SyncService,
|
||||||
|
private accountService: AccountService,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
async run(format: ImportType, filepath: string, options: OptionValues): Promise<Response> {
|
async run(format: ImportType, filepath: string, options: OptionValues): Promise<Response> {
|
||||||
const organizationId = options.organizationid;
|
const organizationId = options.organizationid;
|
||||||
if (organizationId != null) {
|
if (organizationId != null) {
|
||||||
const organization = await this.organizationService.getFromState(organizationId);
|
const userId = await firstValueFrom(
|
||||||
|
this.accountService.activeAccount$.pipe(map((a) => a?.id)),
|
||||||
|
);
|
||||||
|
if (!userId) {
|
||||||
|
return Response.badRequest("No user found.");
|
||||||
|
}
|
||||||
|
const organization = await firstValueFrom(
|
||||||
|
this.organizationService
|
||||||
|
.organizations$(userId)
|
||||||
|
.pipe(map((organizations) => organizations.find((o) => o.id === organizationId))),
|
||||||
|
);
|
||||||
|
|
||||||
if (organization == null) {
|
if (organization == null) {
|
||||||
return Response.badRequest(
|
return Response.badRequest(
|
||||||
|
|||||||
@@ -450,6 +450,7 @@ export class VaultProgram extends BaseProgram {
|
|||||||
this.serviceContainer.importService,
|
this.serviceContainer.importService,
|
||||||
this.serviceContainer.organizationService,
|
this.serviceContainer.organizationService,
|
||||||
this.serviceContainer.syncService,
|
this.serviceContainer.syncService,
|
||||||
|
this.serviceContainer.accountService,
|
||||||
);
|
);
|
||||||
const response = await command.run(format, filepath, options);
|
const response = await command.run(format, filepath, options);
|
||||||
this.processResponse(response);
|
this.processResponse(response);
|
||||||
|
|||||||
@@ -202,7 +202,17 @@ export class CreateCommand {
|
|||||||
if (orgKey == null) {
|
if (orgKey == null) {
|
||||||
throw new Error("No encryption key for this organization.");
|
throw new Error("No encryption key for this organization.");
|
||||||
}
|
}
|
||||||
const organization = await this.organizationService.get(req.organizationId);
|
const userId = await firstValueFrom(
|
||||||
|
this.accountService.activeAccount$.pipe(map((a) => a?.id)),
|
||||||
|
);
|
||||||
|
if (!userId) {
|
||||||
|
return Response.badRequest("No user found.");
|
||||||
|
}
|
||||||
|
const organization = await firstValueFrom(
|
||||||
|
this.organizationService
|
||||||
|
.organizations$(userId)
|
||||||
|
.pipe(map((organizations) => organizations.find((o) => o.id === req.organizationId))),
|
||||||
|
);
|
||||||
const currentOrgUserId = organization.organizationUserId;
|
const currentOrgUserId = organization.organizationUserId;
|
||||||
|
|
||||||
const groups =
|
const groups =
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ import { MasterPasswordServiceAbstraction } from "@bitwarden/common/auth/abstrac
|
|||||||
import { UserVerificationService } from "@bitwarden/common/auth/abstractions/user-verification/user-verification.service.abstraction";
|
import { UserVerificationService } from "@bitwarden/common/auth/abstractions/user-verification/user-verification.service.abstraction";
|
||||||
import { AuthenticationStatus } from "@bitwarden/common/auth/enums/authentication-status";
|
import { AuthenticationStatus } from "@bitwarden/common/auth/enums/authentication-status";
|
||||||
import { ForceSetPasswordReason } from "@bitwarden/common/auth/models/domain/force-set-password-reason";
|
import { ForceSetPasswordReason } from "@bitwarden/common/auth/models/domain/force-set-password-reason";
|
||||||
|
import { getUserId } from "@bitwarden/common/auth/services/account.service";
|
||||||
import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum";
|
import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum";
|
||||||
import { VaultTimeoutAction } from "@bitwarden/common/enums/vault-timeout-action.enum";
|
import { VaultTimeoutAction } from "@bitwarden/common/enums/vault-timeout-action.enum";
|
||||||
import { ProcessReloadServiceAbstraction } from "@bitwarden/common/key-management/abstractions/process-reload.service";
|
import { ProcessReloadServiceAbstraction } from "@bitwarden/common/key-management/abstractions/process-reload.service";
|
||||||
@@ -872,9 +873,10 @@ export class AppComponent implements OnInit, OnDestroy {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private async deleteAccount() {
|
private async deleteAccount() {
|
||||||
|
const userId = await firstValueFrom(getUserId(this.accountService.activeAccount$));
|
||||||
await firstValueFrom(
|
await firstValueFrom(
|
||||||
this.configService.getFeatureFlag$(FeatureFlag.AccountDeprovisioning).pipe(
|
this.configService.getFeatureFlag$(FeatureFlag.AccountDeprovisioning).pipe(
|
||||||
withLatestFrom(this.organizationService.organizations$),
|
withLatestFrom(this.organizationService.organizations$(userId)),
|
||||||
map(async ([accountDeprovisioningEnabled, organization]) => {
|
map(async ([accountDeprovisioningEnabled, organization]) => {
|
||||||
if (
|
if (
|
||||||
accountDeprovisioningEnabled &&
|
accountDeprovisioningEnabled &&
|
||||||
|
|||||||
@@ -5,11 +5,16 @@ import { TestBed } from "@angular/core/testing";
|
|||||||
import { provideRouter } from "@angular/router";
|
import { provideRouter } from "@angular/router";
|
||||||
import { RouterTestingHarness } from "@angular/router/testing";
|
import { RouterTestingHarness } from "@angular/router/testing";
|
||||||
import { MockProxy, any, mock } from "jest-mock-extended";
|
import { MockProxy, any, mock } from "jest-mock-extended";
|
||||||
|
import { of } from "rxjs";
|
||||||
|
|
||||||
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
||||||
import { OrganizationUserType } from "@bitwarden/common/admin-console/enums";
|
import { OrganizationUserType } from "@bitwarden/common/admin-console/enums";
|
||||||
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
|
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
|
||||||
|
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
||||||
import { ProductTierType } from "@bitwarden/common/billing/enums";
|
import { ProductTierType } from "@bitwarden/common/billing/enums";
|
||||||
|
import { Utils } from "@bitwarden/common/platform/misc/utils";
|
||||||
|
import { FakeAccountService, mockAccountServiceWith } from "@bitwarden/common/spec";
|
||||||
|
import { UserId } from "@bitwarden/common/types/guid";
|
||||||
import { DialogService } from "@bitwarden/components";
|
import { DialogService } from "@bitwarden/components";
|
||||||
|
|
||||||
import { isEnterpriseOrgGuard } from "./is-enterprise-org.guard";
|
import { isEnterpriseOrgGuard } from "./is-enterprise-org.guard";
|
||||||
@@ -44,15 +49,19 @@ describe("Is Enterprise Org Guard", () => {
|
|||||||
let organizationService: MockProxy<OrganizationService>;
|
let organizationService: MockProxy<OrganizationService>;
|
||||||
let dialogService: MockProxy<DialogService>;
|
let dialogService: MockProxy<DialogService>;
|
||||||
let routerHarness: RouterTestingHarness;
|
let routerHarness: RouterTestingHarness;
|
||||||
|
let accountService: FakeAccountService;
|
||||||
|
const userId = Utils.newGuid() as UserId;
|
||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
organizationService = mock<OrganizationService>();
|
organizationService = mock<OrganizationService>();
|
||||||
dialogService = mock<DialogService>();
|
dialogService = mock<DialogService>();
|
||||||
|
accountService = mockAccountServiceWith(userId);
|
||||||
|
|
||||||
TestBed.configureTestingModule({
|
TestBed.configureTestingModule({
|
||||||
providers: [
|
providers: [
|
||||||
{ provide: OrganizationService, useValue: organizationService },
|
{ provide: OrganizationService, useValue: organizationService },
|
||||||
{ provide: DialogService, useValue: dialogService },
|
{ provide: DialogService, useValue: dialogService },
|
||||||
|
{ provide: AccountService, useValue: accountService },
|
||||||
provideRouter([
|
provideRouter([
|
||||||
{
|
{
|
||||||
path: "",
|
path: "",
|
||||||
@@ -82,7 +91,7 @@ describe("Is Enterprise Org Guard", () => {
|
|||||||
|
|
||||||
it("redirects to `/` if the organization id provided is not found", async () => {
|
it("redirects to `/` if the organization id provided is not found", async () => {
|
||||||
const org = orgFactory();
|
const org = orgFactory();
|
||||||
organizationService.get.calledWith(org.id).mockResolvedValue(null);
|
organizationService.organizations$.calledWith(userId).mockReturnValue(of([]));
|
||||||
await routerHarness.navigateByUrl(`organizations/${org.id}/enterpriseOrgsOnly`);
|
await routerHarness.navigateByUrl(`organizations/${org.id}/enterpriseOrgsOnly`);
|
||||||
expect(routerHarness.routeNativeElement?.querySelector("h1")?.textContent?.trim() ?? "").toBe(
|
expect(routerHarness.routeNativeElement?.querySelector("h1")?.textContent?.trim() ?? "").toBe(
|
||||||
"This is the home screen!",
|
"This is the home screen!",
|
||||||
@@ -101,7 +110,7 @@ describe("Is Enterprise Org Guard", () => {
|
|||||||
type: OrganizationUserType.User,
|
type: OrganizationUserType.User,
|
||||||
productTierType: productTierType,
|
productTierType: productTierType,
|
||||||
});
|
});
|
||||||
organizationService.get.calledWith(org.id).mockResolvedValue(org);
|
organizationService.organizations$.calledWith(userId).mockReturnValue(of([org]));
|
||||||
await routerHarness.navigateByUrl(`organizations/${org.id}/enterpriseOrgsOnly`);
|
await routerHarness.navigateByUrl(`organizations/${org.id}/enterpriseOrgsOnly`);
|
||||||
expect(dialogService.openSimpleDialog).toHaveBeenCalled();
|
expect(dialogService.openSimpleDialog).toHaveBeenCalled();
|
||||||
expect(
|
expect(
|
||||||
@@ -115,7 +124,7 @@ describe("Is Enterprise Org Guard", () => {
|
|||||||
type: OrganizationUserType.Owner,
|
type: OrganizationUserType.Owner,
|
||||||
productTierType: ProductTierType.Teams,
|
productTierType: ProductTierType.Teams,
|
||||||
});
|
});
|
||||||
organizationService.get.calledWith(org.id).mockResolvedValue(org);
|
organizationService.organizations$.calledWith(userId).mockReturnValue(of([org]));
|
||||||
dialogService.openSimpleDialog.calledWith(any()).mockResolvedValue(true);
|
dialogService.openSimpleDialog.calledWith(any()).mockResolvedValue(true);
|
||||||
await routerHarness.navigateByUrl(`organizations/${org.id}/enterpriseOrgsOnly`);
|
await routerHarness.navigateByUrl(`organizations/${org.id}/enterpriseOrgsOnly`);
|
||||||
expect(routerHarness.routeNativeElement?.querySelector("h1")?.textContent?.trim() ?? "").toBe(
|
expect(routerHarness.routeNativeElement?.querySelector("h1")?.textContent?.trim() ?? "").toBe(
|
||||||
@@ -133,7 +142,7 @@ describe("Is Enterprise Org Guard", () => {
|
|||||||
type: OrganizationUserType.User,
|
type: OrganizationUserType.User,
|
||||||
productTierType: productTierType,
|
productTierType: productTierType,
|
||||||
});
|
});
|
||||||
organizationService.get.calledWith(org.id).mockResolvedValue(org);
|
organizationService.organizations$.calledWith(userId).mockReturnValue(of([org]));
|
||||||
await routerHarness.navigateByUrl(`organizations/${org.id}/enterpriseOrgsOnlyNoError`);
|
await routerHarness.navigateByUrl(`organizations/${org.id}/enterpriseOrgsOnlyNoError`);
|
||||||
expect(dialogService.openSimpleDialog).not.toHaveBeenCalled();
|
expect(dialogService.openSimpleDialog).not.toHaveBeenCalled();
|
||||||
expect(
|
expect(
|
||||||
@@ -143,7 +152,7 @@ describe("Is Enterprise Org Guard", () => {
|
|||||||
|
|
||||||
it("proceeds with navigation if the organization in question is a enterprise organization", async () => {
|
it("proceeds with navigation if the organization in question is a enterprise organization", async () => {
|
||||||
const org = orgFactory({ productTierType: ProductTierType.Enterprise });
|
const org = orgFactory({ productTierType: ProductTierType.Enterprise });
|
||||||
organizationService.get.calledWith(org.id).mockResolvedValue(org);
|
organizationService.organizations$.calledWith(userId).mockReturnValue(of([org]));
|
||||||
await routerHarness.navigateByUrl(`organizations/${org.id}/enterpriseOrgsOnly`);
|
await routerHarness.navigateByUrl(`organizations/${org.id}/enterpriseOrgsOnly`);
|
||||||
expect(routerHarness.routeNativeElement?.querySelector("h1")?.textContent?.trim() ?? "").toBe(
|
expect(routerHarness.routeNativeElement?.querySelector("h1")?.textContent?.trim() ?? "").toBe(
|
||||||
"This component can only be accessed by a enterprise organization!",
|
"This component can only be accessed by a enterprise organization!",
|
||||||
|
|||||||
@@ -7,8 +7,13 @@ import {
|
|||||||
Router,
|
Router,
|
||||||
RouterStateSnapshot,
|
RouterStateSnapshot,
|
||||||
} from "@angular/router";
|
} from "@angular/router";
|
||||||
|
import { firstValueFrom, map } 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 { ProductTierType } from "@bitwarden/common/billing/enums";
|
import { ProductTierType } from "@bitwarden/common/billing/enums";
|
||||||
import { DialogService } from "@bitwarden/components";
|
import { DialogService } from "@bitwarden/components";
|
||||||
|
|
||||||
@@ -23,9 +28,15 @@ export function isEnterpriseOrgGuard(showError: boolean = true): CanActivateFn {
|
|||||||
return async (route: ActivatedRouteSnapshot, _state: RouterStateSnapshot) => {
|
return async (route: ActivatedRouteSnapshot, _state: RouterStateSnapshot) => {
|
||||||
const router = inject(Router);
|
const router = inject(Router);
|
||||||
const organizationService = inject(OrganizationService);
|
const organizationService = inject(OrganizationService);
|
||||||
|
const accountService = inject(AccountService);
|
||||||
const dialogService = inject(DialogService);
|
const dialogService = inject(DialogService);
|
||||||
|
|
||||||
const org = await organizationService.get(route.params.organizationId);
|
const userId = await firstValueFrom(accountService.activeAccount$.pipe(map((a) => a?.id)));
|
||||||
|
const org = await firstValueFrom(
|
||||||
|
organizationService
|
||||||
|
.organizations$(userId)
|
||||||
|
.pipe(getOrganizationById(route.params.organizationId)),
|
||||||
|
);
|
||||||
|
|
||||||
if (org == null) {
|
if (org == null) {
|
||||||
return router.createUrlTree(["/"]);
|
return router.createUrlTree(["/"]);
|
||||||
|
|||||||
@@ -5,10 +5,15 @@ import { TestBed } from "@angular/core/testing";
|
|||||||
import { provideRouter } from "@angular/router";
|
import { provideRouter } from "@angular/router";
|
||||||
import { RouterTestingHarness } from "@angular/router/testing";
|
import { RouterTestingHarness } from "@angular/router/testing";
|
||||||
import { MockProxy, any, mock } from "jest-mock-extended";
|
import { MockProxy, any, mock } from "jest-mock-extended";
|
||||||
|
import { of } from "rxjs";
|
||||||
|
|
||||||
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
||||||
import { OrganizationUserType } from "@bitwarden/common/admin-console/enums";
|
import { OrganizationUserType } from "@bitwarden/common/admin-console/enums";
|
||||||
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
|
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 { DialogService } from "@bitwarden/components";
|
import { DialogService } from "@bitwarden/components";
|
||||||
|
|
||||||
import { isPaidOrgGuard } from "./is-paid-org.guard";
|
import { isPaidOrgGuard } from "./is-paid-org.guard";
|
||||||
@@ -43,15 +48,19 @@ describe("Is Paid Org Guard", () => {
|
|||||||
let organizationService: MockProxy<OrganizationService>;
|
let organizationService: MockProxy<OrganizationService>;
|
||||||
let dialogService: MockProxy<DialogService>;
|
let dialogService: MockProxy<DialogService>;
|
||||||
let routerHarness: RouterTestingHarness;
|
let routerHarness: RouterTestingHarness;
|
||||||
|
let accountService: FakeAccountService;
|
||||||
|
const userId = Utils.newGuid() as UserId;
|
||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
organizationService = mock<OrganizationService>();
|
organizationService = mock<OrganizationService>();
|
||||||
dialogService = mock<DialogService>();
|
dialogService = mock<DialogService>();
|
||||||
|
accountService = mockAccountServiceWith(userId);
|
||||||
|
|
||||||
TestBed.configureTestingModule({
|
TestBed.configureTestingModule({
|
||||||
providers: [
|
providers: [
|
||||||
{ provide: OrganizationService, useValue: organizationService },
|
{ provide: OrganizationService, useValue: organizationService },
|
||||||
{ provide: DialogService, useValue: dialogService },
|
{ provide: DialogService, useValue: dialogService },
|
||||||
|
{ provide: AccountService, useValue: accountService },
|
||||||
provideRouter([
|
provideRouter([
|
||||||
{
|
{
|
||||||
path: "",
|
path: "",
|
||||||
@@ -75,7 +84,7 @@ describe("Is Paid Org Guard", () => {
|
|||||||
|
|
||||||
it("redirects to `/` if the organization id provided is not found", async () => {
|
it("redirects to `/` if the organization id provided is not found", async () => {
|
||||||
const org = orgFactory();
|
const org = orgFactory();
|
||||||
organizationService.get.calledWith(org.id).mockResolvedValue(null);
|
organizationService.organizations$.calledWith(userId).mockReturnValue(of([]));
|
||||||
await routerHarness.navigateByUrl(`organizations/${org.id}/paidOrganizationsOnly`);
|
await routerHarness.navigateByUrl(`organizations/${org.id}/paidOrganizationsOnly`);
|
||||||
expect(routerHarness.routeNativeElement?.querySelector("h1")?.textContent?.trim() ?? "").toBe(
|
expect(routerHarness.routeNativeElement?.querySelector("h1")?.textContent?.trim() ?? "").toBe(
|
||||||
"This is the home screen!",
|
"This is the home screen!",
|
||||||
@@ -86,7 +95,7 @@ describe("Is Paid Org Guard", () => {
|
|||||||
// `useTotp` is the current indicator of a free org, it is the baseline
|
// `useTotp` is the current indicator of a free org, it is the baseline
|
||||||
// feature offered above the free organization level.
|
// feature offered above the free organization level.
|
||||||
const org = orgFactory({ type: OrganizationUserType.User, useTotp: false });
|
const org = orgFactory({ type: OrganizationUserType.User, useTotp: false });
|
||||||
organizationService.get.calledWith(org.id).mockResolvedValue(org);
|
organizationService.organizations$.calledWith(userId).mockReturnValue(of([org]));
|
||||||
await routerHarness.navigateByUrl(`organizations/${org.id}/paidOrganizationsOnly`);
|
await routerHarness.navigateByUrl(`organizations/${org.id}/paidOrganizationsOnly`);
|
||||||
expect(dialogService.openSimpleDialog).toHaveBeenCalled();
|
expect(dialogService.openSimpleDialog).toHaveBeenCalled();
|
||||||
expect(
|
expect(
|
||||||
@@ -98,7 +107,7 @@ describe("Is Paid Org Guard", () => {
|
|||||||
// `useTotp` is the current indicator of a free org, it is the baseline
|
// `useTotp` is the current indicator of a free org, it is the baseline
|
||||||
// feature offered above the free organization level.
|
// feature offered above the free organization level.
|
||||||
const org = orgFactory({ type: OrganizationUserType.Owner, useTotp: false });
|
const org = orgFactory({ type: OrganizationUserType.Owner, useTotp: false });
|
||||||
organizationService.get.calledWith(org.id).mockResolvedValue(org);
|
organizationService.organizations$.calledWith(userId).mockReturnValue(of([org]));
|
||||||
dialogService.openSimpleDialog.calledWith(any()).mockResolvedValue(true);
|
dialogService.openSimpleDialog.calledWith(any()).mockResolvedValue(true);
|
||||||
await routerHarness.navigateByUrl(`organizations/${org.id}/paidOrganizationsOnly`);
|
await routerHarness.navigateByUrl(`organizations/${org.id}/paidOrganizationsOnly`);
|
||||||
expect(routerHarness.routeNativeElement?.querySelector("h1")?.textContent?.trim() ?? "").toBe(
|
expect(routerHarness.routeNativeElement?.querySelector("h1")?.textContent?.trim() ?? "").toBe(
|
||||||
@@ -108,7 +117,7 @@ describe("Is Paid Org Guard", () => {
|
|||||||
|
|
||||||
it("proceeds with navigation if the organization in question is a paid organization", async () => {
|
it("proceeds with navigation if the organization in question is a paid organization", async () => {
|
||||||
const org = orgFactory({ useTotp: true });
|
const org = orgFactory({ useTotp: true });
|
||||||
organizationService.get.calledWith(org.id).mockResolvedValue(org);
|
organizationService.organizations$.calledWith(userId).mockReturnValue(of([org]));
|
||||||
await routerHarness.navigateByUrl(`organizations/${org.id}/paidOrganizationsOnly`);
|
await routerHarness.navigateByUrl(`organizations/${org.id}/paidOrganizationsOnly`);
|
||||||
expect(routerHarness.routeNativeElement?.querySelector("h1")?.textContent?.trim() ?? "").toBe(
|
expect(routerHarness.routeNativeElement?.querySelector("h1")?.textContent?.trim() ?? "").toBe(
|
||||||
"This component can only be accessed by a paid organization!",
|
"This component can only be accessed by a paid organization!",
|
||||||
|
|||||||
@@ -7,8 +7,13 @@ import {
|
|||||||
Router,
|
Router,
|
||||||
RouterStateSnapshot,
|
RouterStateSnapshot,
|
||||||
} from "@angular/router";
|
} from "@angular/router";
|
||||||
|
import { firstValueFrom, map } 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 { DialogService } from "@bitwarden/components";
|
import { DialogService } from "@bitwarden/components";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -22,9 +27,15 @@ export function isPaidOrgGuard(): CanActivateFn {
|
|||||||
return async (route: ActivatedRouteSnapshot, _state: RouterStateSnapshot) => {
|
return async (route: ActivatedRouteSnapshot, _state: RouterStateSnapshot) => {
|
||||||
const router = inject(Router);
|
const router = inject(Router);
|
||||||
const organizationService = inject(OrganizationService);
|
const organizationService = inject(OrganizationService);
|
||||||
|
const accountService = inject(AccountService);
|
||||||
const dialogService = inject(DialogService);
|
const dialogService = inject(DialogService);
|
||||||
|
|
||||||
const org = await organizationService.get(route.params.organizationId);
|
const userId = await firstValueFrom(accountService.activeAccount$.pipe(map((a) => a?.id)));
|
||||||
|
const org = await firstValueFrom(
|
||||||
|
organizationService
|
||||||
|
.organizations$(userId)
|
||||||
|
.pipe(getOrganizationById(route.params.organizationId)),
|
||||||
|
);
|
||||||
|
|
||||||
if (org == null) {
|
if (org == null) {
|
||||||
return router.createUrlTree(["/"]);
|
return router.createUrlTree(["/"]);
|
||||||
|
|||||||
@@ -8,11 +8,16 @@ import {
|
|||||||
RouterStateSnapshot,
|
RouterStateSnapshot,
|
||||||
} from "@angular/router";
|
} from "@angular/router";
|
||||||
import { mock, MockProxy } from "jest-mock-extended";
|
import { mock, MockProxy } from "jest-mock-extended";
|
||||||
|
import { of } from "rxjs";
|
||||||
|
|
||||||
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
||||||
import { OrganizationUserType } from "@bitwarden/common/admin-console/enums";
|
import { OrganizationUserType } from "@bitwarden/common/admin-console/enums";
|
||||||
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
|
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 { 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 { SyncService } from "@bitwarden/common/vault/abstractions/sync/sync.service.abstraction";
|
import { SyncService } from "@bitwarden/common/vault/abstractions/sync/sync.service.abstraction";
|
||||||
import { ToastService } from "@bitwarden/components";
|
import { ToastService } from "@bitwarden/components";
|
||||||
|
|
||||||
@@ -34,10 +39,13 @@ describe("Organization Permissions Guard", () => {
|
|||||||
let organizationService: MockProxy<OrganizationService>;
|
let organizationService: MockProxy<OrganizationService>;
|
||||||
let state: MockProxy<RouterStateSnapshot>;
|
let state: MockProxy<RouterStateSnapshot>;
|
||||||
let route: MockProxy<ActivatedRouteSnapshot>;
|
let route: MockProxy<ActivatedRouteSnapshot>;
|
||||||
|
let accountService: FakeAccountService;
|
||||||
|
const userId = Utils.newGuid() as UserId;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
router = mock<Router>();
|
router = mock<Router>();
|
||||||
organizationService = mock<OrganizationService>();
|
organizationService = mock<OrganizationService>();
|
||||||
|
accountService = mockAccountServiceWith(userId);
|
||||||
state = mock<RouterStateSnapshot>();
|
state = mock<RouterStateSnapshot>();
|
||||||
route = mock<ActivatedRouteSnapshot>({
|
route = mock<ActivatedRouteSnapshot>({
|
||||||
params: {
|
params: {
|
||||||
@@ -48,6 +56,7 @@ describe("Organization Permissions Guard", () => {
|
|||||||
TestBed.configureTestingModule({
|
TestBed.configureTestingModule({
|
||||||
providers: [
|
providers: [
|
||||||
{ provide: Router, useValue: router },
|
{ provide: Router, useValue: router },
|
||||||
|
{ provide: AccountService, useValue: accountService },
|
||||||
{ provide: OrganizationService, useValue: organizationService },
|
{ provide: OrganizationService, useValue: organizationService },
|
||||||
{ provide: ToastService, useValue: mock<ToastService>() },
|
{ provide: ToastService, useValue: mock<ToastService>() },
|
||||||
{ provide: I18nService, useValue: mock<I18nService>() },
|
{ provide: I18nService, useValue: mock<I18nService>() },
|
||||||
@@ -57,7 +66,7 @@ describe("Organization Permissions Guard", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("blocks navigation if organization does not exist", async () => {
|
it("blocks navigation if organization does not exist", async () => {
|
||||||
organizationService.get.mockReturnValue(null);
|
organizationService.organizations$.mockReturnValue(of([]));
|
||||||
|
|
||||||
const actual = await TestBed.runInInjectionContext(
|
const actual = await TestBed.runInInjectionContext(
|
||||||
async () => await organizationPermissionsGuard()(route, state),
|
async () => await organizationPermissionsGuard()(route, state),
|
||||||
@@ -68,7 +77,7 @@ describe("Organization Permissions Guard", () => {
|
|||||||
|
|
||||||
it("permits navigation if no permissions are specified", async () => {
|
it("permits navigation if no permissions are specified", async () => {
|
||||||
const org = orgFactory();
|
const org = orgFactory();
|
||||||
organizationService.get.calledWith(org.id).mockResolvedValue(org);
|
organizationService.organizations$.calledWith(userId).mockReturnValue(of([org]));
|
||||||
|
|
||||||
const actual = await TestBed.runInInjectionContext(async () =>
|
const actual = await TestBed.runInInjectionContext(async () =>
|
||||||
organizationPermissionsGuard()(route, state),
|
organizationPermissionsGuard()(route, state),
|
||||||
@@ -81,7 +90,7 @@ describe("Organization Permissions Guard", () => {
|
|||||||
const permissionsCallback = jest.fn();
|
const permissionsCallback = jest.fn();
|
||||||
permissionsCallback.mockImplementation((_org) => true);
|
permissionsCallback.mockImplementation((_org) => true);
|
||||||
const org = orgFactory();
|
const org = orgFactory();
|
||||||
organizationService.get.calledWith(org.id).mockResolvedValue(org);
|
organizationService.organizations$.calledWith(userId).mockReturnValue(of([org]));
|
||||||
|
|
||||||
const actual = await TestBed.runInInjectionContext(
|
const actual = await TestBed.runInInjectionContext(
|
||||||
async () => await organizationPermissionsGuard(permissionsCallback)(route, state),
|
async () => await organizationPermissionsGuard(permissionsCallback)(route, state),
|
||||||
@@ -103,7 +112,7 @@ describe("Organization Permissions Guard", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
const org = orgFactory();
|
const org = orgFactory();
|
||||||
organizationService.get.calledWith(org.id).mockResolvedValue(org);
|
organizationService.organizations$.calledWith(userId).mockReturnValue(of([org]));
|
||||||
|
|
||||||
const actual = await TestBed.runInInjectionContext(
|
const actual = await TestBed.runInInjectionContext(
|
||||||
async () => await organizationPermissionsGuard(permissionsCallback)(route, state),
|
async () => await organizationPermissionsGuard(permissionsCallback)(route, state),
|
||||||
@@ -122,7 +131,7 @@ describe("Organization Permissions Guard", () => {
|
|||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
const org = orgFactory();
|
const org = orgFactory();
|
||||||
organizationService.get.calledWith(org.id).mockResolvedValue(org);
|
organizationService.organizations$.calledWith(userId).mockReturnValue(of([org]));
|
||||||
|
|
||||||
const actual = await TestBed.runInInjectionContext(
|
const actual = await TestBed.runInInjectionContext(
|
||||||
async () => await organizationPermissionsGuard((_org: Organization) => false)(route, state),
|
async () => await organizationPermissionsGuard((_org: Organization) => false)(route, state),
|
||||||
@@ -141,7 +150,7 @@ describe("Organization Permissions Guard", () => {
|
|||||||
type: OrganizationUserType.Admin,
|
type: OrganizationUserType.Admin,
|
||||||
enabled: false,
|
enabled: false,
|
||||||
});
|
});
|
||||||
organizationService.get.calledWith(org.id).mockResolvedValue(org);
|
organizationService.organizations$.calledWith(userId).mockReturnValue(of([org]));
|
||||||
|
|
||||||
const actual = await TestBed.runInInjectionContext(
|
const actual = await TestBed.runInInjectionContext(
|
||||||
async () => await organizationPermissionsGuard()(route, state),
|
async () => await organizationPermissionsGuard()(route, state),
|
||||||
@@ -155,7 +164,7 @@ describe("Organization Permissions Guard", () => {
|
|||||||
type: OrganizationUserType.Owner,
|
type: OrganizationUserType.Owner,
|
||||||
enabled: false,
|
enabled: false,
|
||||||
});
|
});
|
||||||
organizationService.get.calledWith(org.id).mockResolvedValue(org);
|
organizationService.organizations$.calledWith(userId).mockReturnValue(of([org]));
|
||||||
|
|
||||||
const actual = await TestBed.runInInjectionContext(
|
const actual = await TestBed.runInInjectionContext(
|
||||||
async () => await organizationPermissionsGuard()(route, state),
|
async () => await organizationPermissionsGuard()(route, state),
|
||||||
|
|||||||
@@ -7,12 +7,14 @@ import {
|
|||||||
Router,
|
Router,
|
||||||
RouterStateSnapshot,
|
RouterStateSnapshot,
|
||||||
} from "@angular/router";
|
} from "@angular/router";
|
||||||
|
import { firstValueFrom, map } from "rxjs";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
canAccessOrgAdmin,
|
canAccessOrgAdmin,
|
||||||
OrganizationService,
|
OrganizationService,
|
||||||
} from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
} from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
||||||
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
|
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 { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||||
import { SyncService } from "@bitwarden/common/vault/abstractions/sync/sync.service.abstraction";
|
import { SyncService } from "@bitwarden/common/vault/abstractions/sync/sync.service.abstraction";
|
||||||
import { ToastService } from "@bitwarden/components";
|
import { ToastService } from "@bitwarden/components";
|
||||||
@@ -46,13 +48,21 @@ export function organizationPermissionsGuard(
|
|||||||
const toastService = inject(ToastService);
|
const toastService = inject(ToastService);
|
||||||
const i18nService = inject(I18nService);
|
const i18nService = inject(I18nService);
|
||||||
const syncService = inject(SyncService);
|
const syncService = inject(SyncService);
|
||||||
|
const accountService = inject(AccountService);
|
||||||
|
|
||||||
// TODO: We need to fix issue once and for all.
|
// TODO: We need to fix issue once and for all.
|
||||||
if ((await syncService.getLastSync()) == null) {
|
if ((await syncService.getLastSync()) == null) {
|
||||||
await syncService.fullSync(false);
|
await syncService.fullSync(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
const org = await organizationService.get(route.params.organizationId);
|
const userId = await firstValueFrom(accountService.activeAccount$.pipe(map((a) => a?.id)));
|
||||||
|
|
||||||
|
const org = await firstValueFrom(
|
||||||
|
organizationService
|
||||||
|
.organizations$(userId)
|
||||||
|
.pipe(map((organizations) => organizations.find((org) => route.params.organizationId))),
|
||||||
|
);
|
||||||
|
|
||||||
if (org == null) {
|
if (org == null) {
|
||||||
return router.createUrlTree(["/"]);
|
return router.createUrlTree(["/"]);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,10 +5,15 @@ import { TestBed } from "@angular/core/testing";
|
|||||||
import { provideRouter } from "@angular/router";
|
import { provideRouter } from "@angular/router";
|
||||||
import { RouterTestingHarness } from "@angular/router/testing";
|
import { RouterTestingHarness } from "@angular/router/testing";
|
||||||
import { MockProxy, mock } from "jest-mock-extended";
|
import { MockProxy, mock } from "jest-mock-extended";
|
||||||
|
import { of } from "rxjs";
|
||||||
|
|
||||||
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
||||||
import { OrganizationUserType } from "@bitwarden/common/admin-console/enums";
|
import { OrganizationUserType } from "@bitwarden/common/admin-console/enums";
|
||||||
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
|
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 { organizationRedirectGuard } from "./org-redirect.guard";
|
import { organizationRedirectGuard } from "./org-redirect.guard";
|
||||||
|
|
||||||
@@ -41,13 +46,17 @@ const orgFactory = (props: Partial<Organization> = {}) =>
|
|||||||
describe("Organization Redirect Guard", () => {
|
describe("Organization Redirect Guard", () => {
|
||||||
let organizationService: MockProxy<OrganizationService>;
|
let organizationService: MockProxy<OrganizationService>;
|
||||||
let routerHarness: RouterTestingHarness;
|
let routerHarness: RouterTestingHarness;
|
||||||
|
let accountService: FakeAccountService;
|
||||||
|
const userId = Utils.newGuid() as UserId;
|
||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
organizationService = mock<OrganizationService>();
|
organizationService = mock<OrganizationService>();
|
||||||
|
accountService = mockAccountServiceWith(userId);
|
||||||
|
|
||||||
TestBed.configureTestingModule({
|
TestBed.configureTestingModule({
|
||||||
providers: [
|
providers: [
|
||||||
{ provide: OrganizationService, useValue: organizationService },
|
{ provide: OrganizationService, useValue: organizationService },
|
||||||
|
{ provide: AccountService, useValue: accountService },
|
||||||
provideRouter([
|
provideRouter([
|
||||||
{
|
{
|
||||||
path: "",
|
path: "",
|
||||||
@@ -89,16 +98,16 @@ describe("Organization Redirect Guard", () => {
|
|||||||
|
|
||||||
it("redirects to `/` if the organization id provided is not found", async () => {
|
it("redirects to `/` if the organization id provided is not found", async () => {
|
||||||
const org = orgFactory();
|
const org = orgFactory();
|
||||||
organizationService.get.calledWith(org.id).mockResolvedValue(null);
|
organizationService.organizations$.calledWith(userId).mockReturnValue(of([]));
|
||||||
await routerHarness.navigateByUrl(`organizations/${org.id}/noCallback`);
|
await routerHarness.navigateByUrl(`organizations/${org.id}/noCallback`);
|
||||||
expect(routerHarness.routeNativeElement?.querySelector("h1")?.textContent?.trim() ?? "").toBe(
|
expect(routerHarness.routeNativeElement?.querySelector("h1")?.textContent?.trim() ?? "").toBe(
|
||||||
"This is the home screen!",
|
"This is the home screen!",
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("redirects to `/organizations/{id}` if no custom redirect is supplied but the user can access the admin onsole", async () => {
|
it("redirects to `/organizations/{id}` if no custom redirect is supplied but the user can access the admin console", async () => {
|
||||||
const org = orgFactory();
|
const org = orgFactory();
|
||||||
organizationService.get.calledWith(org.id).mockResolvedValue(org);
|
organizationService.organizations$.calledWith(userId).mockReturnValue(of([org]));
|
||||||
await routerHarness.navigateByUrl(`organizations/${org.id}/noCallback`);
|
await routerHarness.navigateByUrl(`organizations/${org.id}/noCallback`);
|
||||||
expect(routerHarness.routeNativeElement?.querySelector("h1")?.textContent?.trim() ?? "").toBe(
|
expect(routerHarness.routeNativeElement?.querySelector("h1")?.textContent?.trim() ?? "").toBe(
|
||||||
"This is the admin console!",
|
"This is the admin console!",
|
||||||
@@ -107,7 +116,7 @@ describe("Organization Redirect Guard", () => {
|
|||||||
|
|
||||||
it("redirects properly when the redirect callback returns a single string", async () => {
|
it("redirects properly when the redirect callback returns a single string", async () => {
|
||||||
const org = orgFactory();
|
const org = orgFactory();
|
||||||
organizationService.get.calledWith(org.id).mockResolvedValue(org);
|
organizationService.organizations$.calledWith(userId).mockReturnValue(of([org]));
|
||||||
await routerHarness.navigateByUrl(`organizations/${org.id}/stringCallback`);
|
await routerHarness.navigateByUrl(`organizations/${org.id}/stringCallback`);
|
||||||
expect(routerHarness.routeNativeElement?.querySelector("h1")?.textContent?.trim() ?? "").toBe(
|
expect(routerHarness.routeNativeElement?.querySelector("h1")?.textContent?.trim() ?? "").toBe(
|
||||||
"This is a subroute of the admin console!",
|
"This is a subroute of the admin console!",
|
||||||
@@ -116,7 +125,7 @@ describe("Organization Redirect Guard", () => {
|
|||||||
|
|
||||||
it("redirects properly when the redirect callback returns an array of strings", async () => {
|
it("redirects properly when the redirect callback returns an array of strings", async () => {
|
||||||
const org = orgFactory();
|
const org = orgFactory();
|
||||||
organizationService.get.calledWith(org.id).mockResolvedValue(org);
|
organizationService.organizations$.calledWith(userId).mockReturnValue(of([org]));
|
||||||
await routerHarness.navigateByUrl(`organizations/${org.id}/arrayCallback`);
|
await routerHarness.navigateByUrl(`organizations/${org.id}/arrayCallback`);
|
||||||
expect(routerHarness.routeNativeElement?.querySelector("h1")?.textContent?.trim() ?? "").toBe(
|
expect(routerHarness.routeNativeElement?.querySelector("h1")?.textContent?.trim() ?? "").toBe(
|
||||||
"This is a subroute of the admin console!",
|
"This is a subroute of the admin console!",
|
||||||
|
|||||||
@@ -5,12 +5,14 @@ import {
|
|||||||
Router,
|
Router,
|
||||||
RouterStateSnapshot,
|
RouterStateSnapshot,
|
||||||
} from "@angular/router";
|
} from "@angular/router";
|
||||||
|
import { firstValueFrom, map } from "rxjs";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
canAccessOrgAdmin,
|
canAccessOrgAdmin,
|
||||||
OrganizationService,
|
OrganizationService,
|
||||||
} from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
} from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
||||||
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
|
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
|
||||||
|
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
@@ -25,8 +27,25 @@ export function organizationRedirectGuard(
|
|||||||
return async (route: ActivatedRouteSnapshot, state: RouterStateSnapshot) => {
|
return async (route: ActivatedRouteSnapshot, state: RouterStateSnapshot) => {
|
||||||
const router = inject(Router);
|
const router = inject(Router);
|
||||||
const organizationService = inject(OrganizationService);
|
const organizationService = inject(OrganizationService);
|
||||||
|
const accountService = inject(AccountService);
|
||||||
|
|
||||||
const org = await organizationService.get(route.params.organizationId);
|
const userId = await firstValueFrom(accountService.activeAccount$.pipe(map((a) => a?.id)));
|
||||||
|
|
||||||
|
if (!userId) {
|
||||||
|
return router.createUrlTree(["/"]);
|
||||||
|
}
|
||||||
|
|
||||||
|
const org = await firstValueFrom(
|
||||||
|
organizationService
|
||||||
|
.organizations$(userId)
|
||||||
|
.pipe(
|
||||||
|
map((organizations) => organizations.find((o) => o.id === route.params.organizationId)),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!org) {
|
||||||
|
return router.createUrlTree(["/"]);
|
||||||
|
}
|
||||||
|
|
||||||
if (customRedirect != null) {
|
if (customRedirect != null) {
|
||||||
let redirectPath = customRedirect(org);
|
let redirectPath = customRedirect(org);
|
||||||
|
|||||||
@@ -4,8 +4,12 @@ import { Component, OnInit } from "@angular/core";
|
|||||||
import { ActivatedRoute } from "@angular/router";
|
import { ActivatedRoute } from "@angular/router";
|
||||||
import { Observable, switchMap } from "rxjs";
|
import { Observable, 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 { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
|
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
|
||||||
|
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
||||||
import { IntegrationType } from "@bitwarden/common/enums";
|
import { IntegrationType } from "@bitwarden/common/enums";
|
||||||
|
|
||||||
import { HeaderModule } from "../../../layouts/header/header.module";
|
import { HeaderModule } from "../../../layouts/header/header.module";
|
||||||
@@ -34,13 +38,22 @@ export class AdminConsoleIntegrationsComponent implements OnInit {
|
|||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
this.organization$ = this.route.params.pipe(
|
this.organization$ = this.route.params.pipe(
|
||||||
switchMap((params) => this.organizationService.get$(params.organizationId)),
|
switchMap((params) =>
|
||||||
|
this.accountService.activeAccount$.pipe(
|
||||||
|
switchMap((account) =>
|
||||||
|
this.organizationService
|
||||||
|
.organizations$(account?.id)
|
||||||
|
.pipe(getOrganizationById(params.organizationId)),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private route: ActivatedRoute,
|
private route: ActivatedRoute,
|
||||||
private organizationService: OrganizationService,
|
private organizationService: OrganizationService,
|
||||||
|
private accountService: AccountService,
|
||||||
) {
|
) {
|
||||||
this.integrationsList = [
|
this.integrationsList = [
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
import { CommonModule } from "@angular/common";
|
import { CommonModule } from "@angular/common";
|
||||||
import { Component, OnInit } from "@angular/core";
|
import { Component, OnInit } from "@angular/core";
|
||||||
import { ActivatedRoute, RouterModule } from "@angular/router";
|
import { ActivatedRoute, RouterModule } from "@angular/router";
|
||||||
import { combineLatest, filter, map, Observable, switchMap } from "rxjs";
|
import { combineLatest, filter, firstValueFrom, map, Observable, switchMap } from "rxjs";
|
||||||
|
|
||||||
import { JslibModule } from "@bitwarden/angular/jslib.module";
|
import { JslibModule } from "@bitwarden/angular/jslib.module";
|
||||||
import {
|
import {
|
||||||
@@ -20,6 +20,8 @@ import { PolicyService } from "@bitwarden/common/admin-console/abstractions/poli
|
|||||||
import { ProviderService } from "@bitwarden/common/admin-console/abstractions/provider.service";
|
import { ProviderService } from "@bitwarden/common/admin-console/abstractions/provider.service";
|
||||||
import { PolicyType, ProviderStatusType } from "@bitwarden/common/admin-console/enums";
|
import { PolicyType, ProviderStatusType } from "@bitwarden/common/admin-console/enums";
|
||||||
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
|
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 { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum";
|
||||||
import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
|
import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
|
||||||
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
||||||
@@ -66,14 +68,16 @@ export class OrganizationLayoutComponent implements OnInit {
|
|||||||
private configService: ConfigService,
|
private configService: ConfigService,
|
||||||
private policyService: PolicyService,
|
private policyService: PolicyService,
|
||||||
private providerService: ProviderService,
|
private providerService: ProviderService,
|
||||||
|
private accountService: AccountService,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
async ngOnInit() {
|
async ngOnInit() {
|
||||||
document.body.classList.remove("layout_frontend");
|
document.body.classList.remove("layout_frontend");
|
||||||
|
|
||||||
|
const userId = await firstValueFrom(getUserId(this.accountService.activeAccount$));
|
||||||
this.organization$ = this.route.params.pipe(
|
this.organization$ = this.route.params.pipe(
|
||||||
map((p) => p.organizationId),
|
map((p) => p.organizationId),
|
||||||
switchMap((id) => this.organizationService.organizations$.pipe(getById(id))),
|
switchMap((id) => this.organizationService.organizations$(userId).pipe(getById(id))),
|
||||||
filter((org) => org != null),
|
filter((org) => org != null),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -2,14 +2,19 @@
|
|||||||
// @ts-strict-ignore
|
// @ts-strict-ignore
|
||||||
import { Component, OnDestroy, OnInit } from "@angular/core";
|
import { Component, OnDestroy, OnInit } from "@angular/core";
|
||||||
import { ActivatedRoute, Router } from "@angular/router";
|
import { ActivatedRoute, Router } from "@angular/router";
|
||||||
import { concatMap, Subject, takeUntil } from "rxjs";
|
import { concatMap, firstValueFrom, Subject, takeUntil } from "rxjs";
|
||||||
|
|
||||||
import { OrganizationUserApiService } from "@bitwarden/admin-console/common";
|
import { OrganizationUserApiService } from "@bitwarden/admin-console/common";
|
||||||
import { UserNamePipe } from "@bitwarden/angular/pipes/user-name.pipe";
|
import { UserNamePipe } from "@bitwarden/angular/pipes/user-name.pipe";
|
||||||
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
||||||
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 { ProviderService } from "@bitwarden/common/admin-console/abstractions/provider.service";
|
import { ProviderService } from "@bitwarden/common/admin-console/abstractions/provider.service";
|
||||||
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
|
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 { EventSystemUser } from "@bitwarden/common/enums";
|
import { EventSystemUser } from "@bitwarden/common/enums";
|
||||||
import { EventResponse } from "@bitwarden/common/models/response/event.response";
|
import { EventResponse } from "@bitwarden/common/models/response/event.response";
|
||||||
import { FileDownloadService } from "@bitwarden/common/platform/abstractions/file-download/file-download.service";
|
import { FileDownloadService } from "@bitwarden/common/platform/abstractions/file-download/file-download.service";
|
||||||
@@ -55,6 +60,7 @@ export class EventsComponent extends BaseEventsComponent implements OnInit, OnDe
|
|||||||
private providerService: ProviderService,
|
private providerService: ProviderService,
|
||||||
fileDownloadService: FileDownloadService,
|
fileDownloadService: FileDownloadService,
|
||||||
toastService: ToastService,
|
toastService: ToastService,
|
||||||
|
private accountService: AccountService,
|
||||||
) {
|
) {
|
||||||
super(
|
super(
|
||||||
eventService,
|
eventService,
|
||||||
@@ -68,11 +74,16 @@ export class EventsComponent extends BaseEventsComponent implements OnInit, OnDe
|
|||||||
}
|
}
|
||||||
|
|
||||||
async ngOnInit() {
|
async ngOnInit() {
|
||||||
|
const userId = await firstValueFrom(getUserId(this.accountService.activeAccount$));
|
||||||
this.route.params
|
this.route.params
|
||||||
.pipe(
|
.pipe(
|
||||||
concatMap(async (params) => {
|
concatMap(async (params) => {
|
||||||
this.organizationId = params.organizationId;
|
this.organizationId = params.organizationId;
|
||||||
this.organization = await this.organizationService.get(this.organizationId);
|
this.organization = await firstValueFrom(
|
||||||
|
this.organizationService
|
||||||
|
.organizations$(userId)
|
||||||
|
.pipe(getOrganizationById(this.organizationId)),
|
||||||
|
);
|
||||||
if (this.organization == null || !this.organization.useEvents) {
|
if (this.organization == null || !this.organization.useEvents) {
|
||||||
await this.router.navigate(["/organizations", this.organizationId]);
|
await this.router.navigate(["/organizations", this.organizationId]);
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import {
|
|||||||
of,
|
of,
|
||||||
shareReplay,
|
shareReplay,
|
||||||
Subject,
|
Subject,
|
||||||
|
switchMap,
|
||||||
takeUntil,
|
takeUntil,
|
||||||
} from "rxjs";
|
} from "rxjs";
|
||||||
|
|
||||||
@@ -22,7 +23,10 @@ import {
|
|||||||
OrganizationUserApiService,
|
OrganizationUserApiService,
|
||||||
} from "@bitwarden/admin-console/common";
|
} from "@bitwarden/admin-console/common";
|
||||||
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
||||||
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 { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
|
||||||
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
||||||
import { ErrorResponse } from "@bitwarden/common/models/response/error.response";
|
import { ErrorResponse } from "@bitwarden/common/models/response/error.response";
|
||||||
@@ -97,9 +101,14 @@ export const openGroupAddEditDialog = (
|
|||||||
templateUrl: "group-add-edit.component.html",
|
templateUrl: "group-add-edit.component.html",
|
||||||
})
|
})
|
||||||
export class GroupAddEditComponent implements OnInit, OnDestroy {
|
export class GroupAddEditComponent implements OnInit, OnDestroy {
|
||||||
private organization$ = this.organizationService
|
private organization$ = this.accountService.activeAccount$.pipe(
|
||||||
.get$(this.organizationId)
|
switchMap((account) =>
|
||||||
.pipe(shareReplay({ refCount: true }));
|
this.organizationService
|
||||||
|
.organizations$(account?.id)
|
||||||
|
.pipe(getOrganizationById(this.organizationId))
|
||||||
|
.pipe(shareReplay({ refCount: true })),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
protected PermissionMode = PermissionMode;
|
protected PermissionMode = PermissionMode;
|
||||||
protected ResultType = GroupAddEditDialogResultType;
|
protected ResultType = GroupAddEditDialogResultType;
|
||||||
|
|||||||
@@ -22,7 +22,10 @@ import {
|
|||||||
OrganizationUserApiService,
|
OrganizationUserApiService,
|
||||||
CollectionView,
|
CollectionView,
|
||||||
} from "@bitwarden/admin-console/common";
|
} from "@bitwarden/admin-console/common";
|
||||||
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 {
|
import {
|
||||||
OrganizationUserStatusType,
|
OrganizationUserStatusType,
|
||||||
OrganizationUserType,
|
OrganizationUserType,
|
||||||
@@ -156,9 +159,14 @@ export class MemberDialogComponent implements OnDestroy {
|
|||||||
private toastService: ToastService,
|
private toastService: ToastService,
|
||||||
private configService: ConfigService,
|
private configService: ConfigService,
|
||||||
) {
|
) {
|
||||||
this.organization$ = organizationService
|
this.organization$ = accountService.activeAccount$.pipe(
|
||||||
.get$(this.params.organizationId)
|
switchMap((account) =>
|
||||||
.pipe(shareReplay({ refCount: true, bufferSize: 1 }));
|
organizationService
|
||||||
|
.organizations$(account?.id)
|
||||||
|
.pipe(getOrganizationById(this.params.organizationId))
|
||||||
|
.pipe(shareReplay({ refCount: true, bufferSize: 1 })),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
this.editMode = this.params.organizationUserId != null;
|
this.editMode = this.params.organizationUserId != null;
|
||||||
this.tabIndex = this.params.initialTab ?? MemberDialogTab.Role;
|
this.tabIndex = this.params.initialTab ?? MemberDialogTab.Role;
|
||||||
|
|||||||
@@ -28,7 +28,10 @@ import { UserNamePipe } from "@bitwarden/angular/pipes/user-name.pipe";
|
|||||||
import { ModalService } from "@bitwarden/angular/services/modal.service";
|
import { ModalService } from "@bitwarden/angular/services/modal.service";
|
||||||
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
||||||
import { OrganizationApiServiceAbstraction } from "@bitwarden/common/admin-console/abstractions/organization/organization-api.service.abstraction";
|
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 { OrganizationManagementPreferencesService } from "@bitwarden/common/admin-console/abstractions/organization-management-preferences/organization-management-preferences.service";
|
import { OrganizationManagementPreferencesService } from "@bitwarden/common/admin-console/abstractions/organization-management-preferences/organization-management-preferences.service";
|
||||||
import { PolicyApiServiceAbstraction as PolicyApiService } from "@bitwarden/common/admin-console/abstractions/policy/policy-api.service.abstraction";
|
import { PolicyApiServiceAbstraction as PolicyApiService } from "@bitwarden/common/admin-console/abstractions/policy/policy-api.service.abstraction";
|
||||||
import { PolicyService } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction";
|
import { PolicyService } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction";
|
||||||
@@ -40,6 +43,7 @@ import {
|
|||||||
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
|
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
|
||||||
import { Policy } from "@bitwarden/common/admin-console/models/domain/policy";
|
import { Policy } from "@bitwarden/common/admin-console/models/domain/policy";
|
||||||
import { OrganizationKeysRequest } from "@bitwarden/common/admin-console/models/request/organization-keys.request";
|
import { OrganizationKeysRequest } from "@bitwarden/common/admin-console/models/request/organization-keys.request";
|
||||||
|
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
||||||
import { BillingApiServiceAbstraction } from "@bitwarden/common/billing/abstractions/billing-api.service.abstraction";
|
import { BillingApiServiceAbstraction } from "@bitwarden/common/billing/abstractions/billing-api.service.abstraction";
|
||||||
import { isNotSelfUpgradable, ProductTierType } from "@bitwarden/common/billing/enums";
|
import { isNotSelfUpgradable, ProductTierType } from "@bitwarden/common/billing/enums";
|
||||||
import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum";
|
import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum";
|
||||||
@@ -122,6 +126,7 @@ export class MembersComponent extends BaseMembersComponent<OrganizationUserView>
|
|||||||
private route: ActivatedRoute,
|
private route: ActivatedRoute,
|
||||||
private syncService: SyncService,
|
private syncService: SyncService,
|
||||||
private organizationService: OrganizationService,
|
private organizationService: OrganizationService,
|
||||||
|
private accountService: AccountService,
|
||||||
private organizationApiService: OrganizationApiServiceAbstraction,
|
private organizationApiService: OrganizationApiServiceAbstraction,
|
||||||
private organizationUserApiService: OrganizationUserApiService,
|
private organizationUserApiService: OrganizationUserApiService,
|
||||||
private router: Router,
|
private router: Router,
|
||||||
@@ -144,7 +149,15 @@ export class MembersComponent extends BaseMembersComponent<OrganizationUserView>
|
|||||||
);
|
);
|
||||||
|
|
||||||
const organization$ = this.route.params.pipe(
|
const organization$ = this.route.params.pipe(
|
||||||
concatMap((params) => this.organizationService.get$(params.organizationId)),
|
concatMap((params) =>
|
||||||
|
this.accountService.activeAccount$.pipe(
|
||||||
|
switchMap((account) =>
|
||||||
|
this.organizationService
|
||||||
|
.organizations$(account?.id)
|
||||||
|
.pipe(getOrganizationById(params.organizationId)),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
shareReplay({ refCount: true, bufferSize: 1 }),
|
shareReplay({ refCount: true, bufferSize: 1 }),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
// FIXME: Update this file to be type safe and remove this and next line
|
// FIXME: Update this file to be type safe and remove this and next line
|
||||||
// @ts-strict-ignore
|
// @ts-strict-ignore
|
||||||
import { mock, MockProxy } from "jest-mock-extended";
|
import { mock, MockProxy } from "jest-mock-extended";
|
||||||
|
import { of } from "rxjs";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
OrganizationUserApiService,
|
OrganizationUserApiService,
|
||||||
@@ -164,10 +165,9 @@ describe("OrganizationUserResetPasswordService", () => {
|
|||||||
|
|
||||||
describe("getRotatedData", () => {
|
describe("getRotatedData", () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
organizationService.getAll.mockResolvedValue([
|
organizationService.organizations$.mockReturnValue(
|
||||||
createOrganization("1", "org1"),
|
of([createOrganization("1", "org1"), createOrganization("2", "org2")]),
|
||||||
createOrganization("2", "org2"),
|
);
|
||||||
]);
|
|
||||||
organizationApiService.getKeys.mockResolvedValue(
|
organizationApiService.getKeys.mockResolvedValue(
|
||||||
new OrganizationKeysResponse({
|
new OrganizationKeysResponse({
|
||||||
privateKey: "test-private-key",
|
privateKey: "test-private-key",
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
// FIXME: Update this file to be type safe and remove this and next line
|
// FIXME: Update this file to be type safe and remove this and next line
|
||||||
// @ts-strict-ignore
|
// @ts-strict-ignore
|
||||||
import { Injectable } from "@angular/core";
|
import { Injectable } from "@angular/core";
|
||||||
|
import { firstValueFrom } from "rxjs";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
OrganizationUserApiService,
|
OrganizationUserApiService,
|
||||||
@@ -154,7 +155,7 @@ export class OrganizationUserResetPasswordService
|
|||||||
throw new Error("New user key is required for rotation.");
|
throw new Error("New user key is required for rotation.");
|
||||||
}
|
}
|
||||||
|
|
||||||
const allOrgs = await this.organizationService.getAll();
|
const allOrgs = await firstValueFrom(this.organizationService.organizations$(userId));
|
||||||
|
|
||||||
if (!allOrgs) {
|
if (!allOrgs) {
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -2,11 +2,17 @@
|
|||||||
// @ts-strict-ignore
|
// @ts-strict-ignore
|
||||||
import { Component, OnInit } from "@angular/core";
|
import { Component, OnInit } from "@angular/core";
|
||||||
import { FormBuilder, FormGroup, Validators } from "@angular/forms";
|
import { FormBuilder, FormGroup, Validators } from "@angular/forms";
|
||||||
|
import { firstValueFrom } from "rxjs";
|
||||||
|
|
||||||
import { ControlsOf } from "@bitwarden/angular/types/controls-of";
|
import { ControlsOf } from "@bitwarden/angular/types/controls-of";
|
||||||
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 { PolicyType } from "@bitwarden/common/admin-console/enums";
|
import { PolicyType } from "@bitwarden/common/admin-console/enums";
|
||||||
import { MasterPasswordPolicyOptions } from "@bitwarden/common/admin-console/models/domain/master-password-policy-options";
|
import { MasterPasswordPolicyOptions } from "@bitwarden/common/admin-console/models/domain/master-password-policy-options";
|
||||||
|
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 { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||||
import { Utils } from "@bitwarden/common/platform/misc/utils";
|
import { Utils } from "@bitwarden/common/platform/misc/utils";
|
||||||
|
|
||||||
@@ -43,6 +49,7 @@ export class MasterPasswordPolicyComponent extends BasePolicyComponent implement
|
|||||||
private formBuilder: FormBuilder,
|
private formBuilder: FormBuilder,
|
||||||
i18nService: I18nService,
|
i18nService: I18nService,
|
||||||
private organizationService: OrganizationService,
|
private organizationService: OrganizationService,
|
||||||
|
private accountService: AccountService,
|
||||||
) {
|
) {
|
||||||
super();
|
super();
|
||||||
|
|
||||||
@@ -58,7 +65,12 @@ export class MasterPasswordPolicyComponent extends BasePolicyComponent implement
|
|||||||
|
|
||||||
async ngOnInit() {
|
async ngOnInit() {
|
||||||
super.ngOnInit();
|
super.ngOnInit();
|
||||||
const organization = await this.organizationService.get(this.policyResponse.organizationId);
|
const userId = await firstValueFrom(getUserId(this.accountService.activeAccount$));
|
||||||
|
const organization = await firstValueFrom(
|
||||||
|
this.organizationService
|
||||||
|
.organizations$(userId)
|
||||||
|
.pipe(getOrganizationById(this.policyResponse.organizationId)),
|
||||||
|
);
|
||||||
this.showKeyConnectorInfo = organization.keyConnectorEnabled;
|
this.showKeyConnectorInfo = organization.keyConnectorEnabled;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,14 +2,18 @@
|
|||||||
// @ts-strict-ignore
|
// @ts-strict-ignore
|
||||||
import { Component, OnInit, ViewChild, ViewContainerRef } from "@angular/core";
|
import { Component, OnInit, ViewChild, ViewContainerRef } from "@angular/core";
|
||||||
import { ActivatedRoute } from "@angular/router";
|
import { ActivatedRoute } from "@angular/router";
|
||||||
import { lastValueFrom } from "rxjs";
|
import { firstValueFrom, lastValueFrom } from "rxjs";
|
||||||
import { first } from "rxjs/operators";
|
import { first, map } from "rxjs/operators";
|
||||||
|
|
||||||
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 { PolicyApiServiceAbstraction } from "@bitwarden/common/admin-console/abstractions/policy/policy-api.service.abstraction";
|
import { PolicyApiServiceAbstraction } from "@bitwarden/common/admin-console/abstractions/policy/policy-api.service.abstraction";
|
||||||
import { PolicyType } from "@bitwarden/common/admin-console/enums";
|
import { PolicyType } from "@bitwarden/common/admin-console/enums";
|
||||||
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
|
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
|
||||||
import { PolicyResponse } from "@bitwarden/common/admin-console/models/response/policy.response";
|
import { PolicyResponse } from "@bitwarden/common/admin-console/models/response/policy.response";
|
||||||
|
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
||||||
import { DialogService } from "@bitwarden/components";
|
import { DialogService } from "@bitwarden/components";
|
||||||
|
|
||||||
import { PolicyListService } from "../../core/policy-list.service";
|
import { PolicyListService } from "../../core/policy-list.service";
|
||||||
@@ -37,6 +41,7 @@ export class PoliciesComponent implements OnInit {
|
|||||||
constructor(
|
constructor(
|
||||||
private route: ActivatedRoute,
|
private route: ActivatedRoute,
|
||||||
private organizationService: OrganizationService,
|
private organizationService: OrganizationService,
|
||||||
|
private accountService: AccountService,
|
||||||
private policyApiService: PolicyApiServiceAbstraction,
|
private policyApiService: PolicyApiServiceAbstraction,
|
||||||
private policyListService: PolicyListService,
|
private policyListService: PolicyListService,
|
||||||
private dialogService: DialogService,
|
private dialogService: DialogService,
|
||||||
@@ -46,7 +51,14 @@ export class PoliciesComponent implements OnInit {
|
|||||||
// eslint-disable-next-line rxjs-angular/prefer-takeuntil, rxjs/no-async-subscribe
|
// eslint-disable-next-line rxjs-angular/prefer-takeuntil, rxjs/no-async-subscribe
|
||||||
this.route.parent.parent.params.subscribe(async (params) => {
|
this.route.parent.parent.params.subscribe(async (params) => {
|
||||||
this.organizationId = params.organizationId;
|
this.organizationId = params.organizationId;
|
||||||
this.organization = await this.organizationService.get(this.organizationId);
|
const userId = await firstValueFrom(
|
||||||
|
this.accountService.activeAccount$.pipe(map((a) => a?.id)),
|
||||||
|
);
|
||||||
|
this.organization = await firstValueFrom(
|
||||||
|
this.organizationService
|
||||||
|
.organizations$(userId)
|
||||||
|
.pipe(getOrganizationById(this.organizationId)),
|
||||||
|
);
|
||||||
this.policies = this.policyListService.getPolicies();
|
this.policies = this.policyListService.getPolicies();
|
||||||
|
|
||||||
await this.load();
|
await this.load();
|
||||||
|
|||||||
@@ -1,9 +1,15 @@
|
|||||||
import { Component, OnInit } from "@angular/core";
|
import { Component, OnInit } from "@angular/core";
|
||||||
import { FormBuilder } from "@angular/forms";
|
import { FormBuilder } from "@angular/forms";
|
||||||
|
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 { PolicyType } from "@bitwarden/common/admin-console/enums";
|
import { PolicyType } from "@bitwarden/common/admin-console/enums";
|
||||||
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
|
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 { BasePolicy, BasePolicyComponent } from "./base-policy.component";
|
import { BasePolicy, BasePolicyComponent } from "./base-policy.component";
|
||||||
|
|
||||||
@@ -31,13 +37,29 @@ export class ResetPasswordPolicyComponent extends BasePolicyComponent implements
|
|||||||
constructor(
|
constructor(
|
||||||
private formBuilder: FormBuilder,
|
private formBuilder: FormBuilder,
|
||||||
private organizationService: OrganizationService,
|
private organizationService: OrganizationService,
|
||||||
|
private accountService: AccountService,
|
||||||
) {
|
) {
|
||||||
super();
|
super();
|
||||||
}
|
}
|
||||||
|
|
||||||
async ngOnInit() {
|
async ngOnInit() {
|
||||||
super.ngOnInit();
|
super.ngOnInit();
|
||||||
const organization = await this.organizationService.get(this.policyResponse.organizationId);
|
|
||||||
|
const userId = await firstValueFrom(getUserId(this.accountService.activeAccount$));
|
||||||
|
|
||||||
|
if (!userId) {
|
||||||
|
throw new Error("No user found.");
|
||||||
|
}
|
||||||
|
|
||||||
|
const organization = await firstValueFrom(
|
||||||
|
this.organizationService
|
||||||
|
.organizations$(userId)
|
||||||
|
.pipe(getOrganizationById(this.policyResponse.organizationId)),
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!organization) {
|
||||||
|
throw new Error("No organization found.");
|
||||||
|
}
|
||||||
this.showKeyConnectorInfo = organization.keyConnectorEnabled;
|
this.showKeyConnectorInfo = organization.keyConnectorEnabled;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,9 +2,14 @@
|
|||||||
// @ts-strict-ignore
|
// @ts-strict-ignore
|
||||||
import { Component, OnInit } from "@angular/core";
|
import { Component, OnInit } from "@angular/core";
|
||||||
import { ActivatedRoute, NavigationEnd, Router } from "@angular/router";
|
import { ActivatedRoute, NavigationEnd, Router } from "@angular/router";
|
||||||
import { filter, map, Observable, startWith, concatMap } from "rxjs";
|
import { filter, map, Observable, startWith, 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 { ProductTierType } from "@bitwarden/common/billing/enums";
|
import { ProductTierType } from "@bitwarden/common/billing/enums";
|
||||||
|
|
||||||
import { ReportVariant, reports, ReportType, ReportEntry } from "../../../tools/reports";
|
import { ReportVariant, reports, ReportType, ReportEntry } from "../../../tools/reports";
|
||||||
@@ -20,6 +25,7 @@ export class ReportsHomeComponent implements OnInit {
|
|||||||
constructor(
|
constructor(
|
||||||
private route: ActivatedRoute,
|
private route: ActivatedRoute,
|
||||||
private organizationService: OrganizationService,
|
private organizationService: OrganizationService,
|
||||||
|
private accountService: AccountService,
|
||||||
private router: Router,
|
private router: Router,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
@@ -30,8 +36,14 @@ export class ReportsHomeComponent implements OnInit {
|
|||||||
startWith(this.isReportsHomepageRouteUrl(this.router.url)),
|
startWith(this.isReportsHomepageRouteUrl(this.router.url)),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const userId = await firstValueFrom(getUserId(this.accountService.activeAccount$));
|
||||||
|
|
||||||
this.reports$ = this.route.params.pipe(
|
this.reports$ = this.route.params.pipe(
|
||||||
concatMap((params) => this.organizationService.get$(params.organizationId)),
|
concatMap((params) =>
|
||||||
|
this.organizationService
|
||||||
|
.organizations$(userId)
|
||||||
|
.pipe(getOrganizationById(params.organizationId)),
|
||||||
|
),
|
||||||
map((org) => this.buildReports(org.productTierType)),
|
map((org) => this.buildReports(org.productTierType)),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,15 +3,29 @@
|
|||||||
import { Component, OnDestroy, OnInit, ViewChild, ViewContainerRef } from "@angular/core";
|
import { Component, OnDestroy, OnInit, ViewChild, ViewContainerRef } from "@angular/core";
|
||||||
import { FormBuilder, Validators } from "@angular/forms";
|
import { FormBuilder, Validators } from "@angular/forms";
|
||||||
import { ActivatedRoute, Router } from "@angular/router";
|
import { ActivatedRoute, Router } from "@angular/router";
|
||||||
import { combineLatest, from, lastValueFrom, of, Subject, switchMap, takeUntil } from "rxjs";
|
import {
|
||||||
|
combineLatest,
|
||||||
|
firstValueFrom,
|
||||||
|
from,
|
||||||
|
lastValueFrom,
|
||||||
|
of,
|
||||||
|
Subject,
|
||||||
|
switchMap,
|
||||||
|
takeUntil,
|
||||||
|
} from "rxjs";
|
||||||
|
|
||||||
import { ModalService } from "@bitwarden/angular/services/modal.service";
|
import { ModalService } from "@bitwarden/angular/services/modal.service";
|
||||||
import { OrganizationApiServiceAbstraction } from "@bitwarden/common/admin-console/abstractions/organization/organization-api.service.abstraction";
|
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 { OrganizationCollectionManagementUpdateRequest } from "@bitwarden/common/admin-console/models/request/organization-collection-management-update.request";
|
import { OrganizationCollectionManagementUpdateRequest } from "@bitwarden/common/admin-console/models/request/organization-collection-management-update.request";
|
||||||
import { OrganizationKeysRequest } from "@bitwarden/common/admin-console/models/request/organization-keys.request";
|
import { OrganizationKeysRequest } from "@bitwarden/common/admin-console/models/request/organization-keys.request";
|
||||||
import { OrganizationUpdateRequest } from "@bitwarden/common/admin-console/models/request/organization-update.request";
|
import { OrganizationUpdateRequest } from "@bitwarden/common/admin-console/models/request/organization-update.request";
|
||||||
import { OrganizationResponse } from "@bitwarden/common/admin-console/models/response/organization.response";
|
import { OrganizationResponse } from "@bitwarden/common/admin-console/models/response/organization.response";
|
||||||
|
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
||||||
|
import { getUserId } from "@bitwarden/common/auth/services/account.service";
|
||||||
import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
|
import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
|
||||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||||
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
||||||
@@ -77,6 +91,7 @@ export class AccountComponent implements OnInit, OnDestroy {
|
|||||||
private platformUtilsService: PlatformUtilsService,
|
private platformUtilsService: PlatformUtilsService,
|
||||||
private keyService: KeyService,
|
private keyService: KeyService,
|
||||||
private router: Router,
|
private router: Router,
|
||||||
|
private accountService: AccountService,
|
||||||
private organizationService: OrganizationService,
|
private organizationService: OrganizationService,
|
||||||
private organizationApiService: OrganizationApiServiceAbstraction,
|
private organizationApiService: OrganizationApiServiceAbstraction,
|
||||||
private dialogService: DialogService,
|
private dialogService: DialogService,
|
||||||
@@ -88,9 +103,14 @@ export class AccountComponent implements OnInit, OnDestroy {
|
|||||||
async ngOnInit() {
|
async ngOnInit() {
|
||||||
this.selfHosted = this.platformUtilsService.isSelfHost();
|
this.selfHosted = this.platformUtilsService.isSelfHost();
|
||||||
|
|
||||||
|
const userId = await firstValueFrom(getUserId(this.accountService.activeAccount$));
|
||||||
this.route.params
|
this.route.params
|
||||||
.pipe(
|
.pipe(
|
||||||
switchMap((params) => this.organizationService.get$(params.organizationId)),
|
switchMap((params) =>
|
||||||
|
this.organizationService
|
||||||
|
.organizations$(userId)
|
||||||
|
.pipe(getOrganizationById(params.organizationId)),
|
||||||
|
),
|
||||||
switchMap((organization) => {
|
switchMap((organization) => {
|
||||||
return combineLatest([
|
return combineLatest([
|
||||||
of(organization),
|
of(organization),
|
||||||
|
|||||||
@@ -3,12 +3,17 @@
|
|||||||
import { DIALOG_DATA, DialogConfig, DialogRef } from "@angular/cdk/dialog";
|
import { DIALOG_DATA, DialogConfig, DialogRef } from "@angular/cdk/dialog";
|
||||||
import { Component, Inject, OnDestroy, OnInit } from "@angular/core";
|
import { Component, Inject, OnDestroy, OnInit } from "@angular/core";
|
||||||
import { FormBuilder, FormControl, Validators } from "@angular/forms";
|
import { FormBuilder, FormControl, Validators } from "@angular/forms";
|
||||||
import { combineLatest, Subject, takeUntil } from "rxjs";
|
import { combineLatest, firstValueFrom, Subject, takeUntil } from "rxjs";
|
||||||
|
|
||||||
import { OrganizationApiServiceAbstraction } from "@bitwarden/common/admin-console/abstractions/organization/organization-api.service.abstraction";
|
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 { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
|
||||||
|
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
||||||
import { UserVerificationService } from "@bitwarden/common/auth/abstractions/user-verification/user-verification.service.abstraction";
|
import { UserVerificationService } from "@bitwarden/common/auth/abstractions/user-verification/user-verification.service.abstraction";
|
||||||
|
import { getUserId } from "@bitwarden/common/auth/services/account.service";
|
||||||
import { Verification } from "@bitwarden/common/auth/types/verification";
|
import { Verification } from "@bitwarden/common/auth/types/verification";
|
||||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||||
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
||||||
@@ -94,6 +99,7 @@ export class DeleteOrganizationDialogComponent implements OnInit, OnDestroy {
|
|||||||
private userVerificationService: UserVerificationService,
|
private userVerificationService: UserVerificationService,
|
||||||
private cipherService: CipherService,
|
private cipherService: CipherService,
|
||||||
private organizationService: OrganizationService,
|
private organizationService: OrganizationService,
|
||||||
|
private accountService: AccountService,
|
||||||
private organizationApiService: OrganizationApiServiceAbstraction,
|
private organizationApiService: OrganizationApiServiceAbstraction,
|
||||||
private formBuilder: FormBuilder,
|
private formBuilder: FormBuilder,
|
||||||
private toastService: ToastService,
|
private toastService: ToastService,
|
||||||
@@ -106,9 +112,12 @@ export class DeleteOrganizationDialogComponent implements OnInit, OnDestroy {
|
|||||||
|
|
||||||
async ngOnInit(): Promise<void> {
|
async ngOnInit(): Promise<void> {
|
||||||
this.deleteOrganizationRequestType = this.params.requestType;
|
this.deleteOrganizationRequestType = this.params.requestType;
|
||||||
|
const userId = await firstValueFrom(getUserId(this.accountService.activeAccount$));
|
||||||
|
|
||||||
combineLatest([
|
combineLatest([
|
||||||
this.organizationService.get$(this.params.organizationId),
|
this.organizationService
|
||||||
|
.organizations$(userId)
|
||||||
|
.pipe(getOrganizationById(this.params.organizationId)),
|
||||||
this.cipherService.getAllFromApiForOrganization(this.params.organizationId),
|
this.cipherService.getAllFromApiForOrganization(this.params.organizationId),
|
||||||
])
|
])
|
||||||
.pipe(takeUntil(this.destroy$))
|
.pipe(takeUntil(this.destroy$))
|
||||||
|
|||||||
@@ -2,13 +2,15 @@
|
|||||||
// @ts-strict-ignore
|
// @ts-strict-ignore
|
||||||
import { Component, OnInit } from "@angular/core";
|
import { Component, OnInit } from "@angular/core";
|
||||||
import { ActivatedRoute, Router } from "@angular/router";
|
import { ActivatedRoute, Router } from "@angular/router";
|
||||||
import { firstValueFrom } from "rxjs";
|
import { firstValueFrom, map } from "rxjs";
|
||||||
|
|
||||||
import { CollectionAdminService } from "@bitwarden/admin-console/common";
|
import { CollectionAdminService } from "@bitwarden/admin-console/common";
|
||||||
import {
|
import {
|
||||||
canAccessVaultTab,
|
canAccessVaultTab,
|
||||||
OrganizationService,
|
OrganizationService,
|
||||||
} from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
} 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 { ImportCollectionServiceAbstraction } from "@bitwarden/importer/core";
|
import { ImportCollectionServiceAbstraction } from "@bitwarden/importer/core";
|
||||||
import { ImportComponent } from "@bitwarden/importer/ui";
|
import { ImportComponent } from "@bitwarden/importer/ui";
|
||||||
|
|
||||||
@@ -36,6 +38,7 @@ export class OrgImportComponent implements OnInit {
|
|||||||
private route: ActivatedRoute,
|
private route: ActivatedRoute,
|
||||||
private organizationService: OrganizationService,
|
private organizationService: OrganizationService,
|
||||||
private router: Router,
|
private router: Router,
|
||||||
|
private accountService: AccountService,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
@@ -46,7 +49,12 @@ export class OrgImportComponent implements OnInit {
|
|||||||
* Callback that is called after a successful import.
|
* Callback that is called after a successful import.
|
||||||
*/
|
*/
|
||||||
protected async onSuccessfulImport(organizationId: string): Promise<void> {
|
protected async onSuccessfulImport(organizationId: string): Promise<void> {
|
||||||
const organization = await firstValueFrom(this.organizationService.get$(organizationId));
|
const userId = await firstValueFrom(getUserId(this.accountService.activeAccount$));
|
||||||
|
const organization = await firstValueFrom(
|
||||||
|
this.organizationService
|
||||||
|
.organizations$(userId)
|
||||||
|
.pipe(map((organizations) => organizations.find((o) => o.id === organizationId))),
|
||||||
|
);
|
||||||
if (organization == null) {
|
if (organization == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,16 +3,20 @@
|
|||||||
import { DialogRef } from "@angular/cdk/dialog";
|
import { DialogRef } from "@angular/cdk/dialog";
|
||||||
import { Component, OnInit } from "@angular/core";
|
import { Component, OnInit } from "@angular/core";
|
||||||
import { ActivatedRoute } from "@angular/router";
|
import { ActivatedRoute } from "@angular/router";
|
||||||
import { concatMap, takeUntil, map, lastValueFrom } from "rxjs";
|
import { concatMap, takeUntil, map, lastValueFrom, firstValueFrom } from "rxjs";
|
||||||
import { first, tap } from "rxjs/operators";
|
import { first, tap } from "rxjs/operators";
|
||||||
|
|
||||||
import { ModalService } from "@bitwarden/angular/services/modal.service";
|
import { ModalService } from "@bitwarden/angular/services/modal.service";
|
||||||
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
||||||
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 { PolicyService } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction";
|
import { PolicyService } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction";
|
||||||
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
||||||
import { TwoFactorProviderType } from "@bitwarden/common/auth/enums/two-factor-provider-type";
|
import { TwoFactorProviderType } from "@bitwarden/common/auth/enums/two-factor-provider-type";
|
||||||
import { TwoFactorDuoResponse } from "@bitwarden/common/auth/models/response/two-factor-duo.response";
|
import { TwoFactorDuoResponse } from "@bitwarden/common/auth/models/response/two-factor-duo.response";
|
||||||
|
import { getUserId } from "@bitwarden/common/auth/services/account.service";
|
||||||
import { AuthResponse } from "@bitwarden/common/auth/types/auth-response";
|
import { AuthResponse } from "@bitwarden/common/auth/types/auth-response";
|
||||||
import { BillingAccountProfileStateService } from "@bitwarden/common/billing/abstractions/account/billing-account-profile-state.service";
|
import { BillingAccountProfileStateService } from "@bitwarden/common/billing/abstractions/account/billing-account-profile-state.service";
|
||||||
import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service";
|
import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service";
|
||||||
@@ -38,7 +42,7 @@ export class TwoFactorSetupComponent extends BaseTwoFactorSetupComponent impleme
|
|||||||
private route: ActivatedRoute,
|
private route: ActivatedRoute,
|
||||||
private organizationService: OrganizationService,
|
private organizationService: OrganizationService,
|
||||||
billingAccountProfileStateService: BillingAccountProfileStateService,
|
billingAccountProfileStateService: BillingAccountProfileStateService,
|
||||||
accountService: AccountService,
|
protected accountService: AccountService,
|
||||||
) {
|
) {
|
||||||
super(
|
super(
|
||||||
dialogService,
|
dialogService,
|
||||||
@@ -52,11 +56,13 @@ export class TwoFactorSetupComponent extends BaseTwoFactorSetupComponent impleme
|
|||||||
}
|
}
|
||||||
|
|
||||||
async ngOnInit() {
|
async ngOnInit() {
|
||||||
|
const userId = await firstValueFrom(getUserId(this.accountService.activeAccount$));
|
||||||
this.route.params
|
this.route.params
|
||||||
.pipe(
|
.pipe(
|
||||||
concatMap((params) =>
|
concatMap((params) =>
|
||||||
this.organizationService
|
this.organizationService
|
||||||
.get$(params.organizationId)
|
.organizations$(userId)
|
||||||
|
.pipe(getOrganizationById(params.organizationId))
|
||||||
.pipe(map((organization) => ({ params, organization }))),
|
.pipe(map((organization) => ({ params, organization }))),
|
||||||
),
|
),
|
||||||
tap(async (mapResponse) => {
|
tap(async (mapResponse) => {
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
import { Component, OnDestroy, OnInit, ViewChild } from "@angular/core";
|
import { Component, OnDestroy, OnInit, ViewChild } from "@angular/core";
|
||||||
import { FormBuilder, Validators } from "@angular/forms";
|
import { FormBuilder, Validators } from "@angular/forms";
|
||||||
import { ActivatedRoute, Router } from "@angular/router";
|
import { ActivatedRoute, Router } from "@angular/router";
|
||||||
import { lastValueFrom, Observable, Subject } from "rxjs";
|
import { firstValueFrom, lastValueFrom, Observable, Subject } from "rxjs";
|
||||||
import { first, map, takeUntil } from "rxjs/operators";
|
import { first, map, takeUntil } from "rxjs/operators";
|
||||||
|
|
||||||
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
||||||
@@ -12,6 +12,8 @@ import { OrganizationUserType } from "@bitwarden/common/admin-console/enums";
|
|||||||
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
|
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
|
||||||
import { OrganizationSponsorshipRedeemRequest } from "@bitwarden/common/admin-console/models/request/organization/organization-sponsorship-redeem.request";
|
import { OrganizationSponsorshipRedeemRequest } from "@bitwarden/common/admin-console/models/request/organization/organization-sponsorship-redeem.request";
|
||||||
import { PreValidateSponsorshipResponse } from "@bitwarden/common/admin-console/models/response/pre-validate-sponsorship.response";
|
import { PreValidateSponsorshipResponse } from "@bitwarden/common/admin-console/models/response/pre-validate-sponsorship.response";
|
||||||
|
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
||||||
|
import { getUserId } from "@bitwarden/common/auth/services/account.service";
|
||||||
import { PlanSponsorshipType, PlanType, ProductTierType } from "@bitwarden/common/billing/enums";
|
import { PlanSponsorshipType, PlanType, ProductTierType } from "@bitwarden/common/billing/enums";
|
||||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||||
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
||||||
@@ -69,6 +71,7 @@ export class FamiliesForEnterpriseSetupComponent implements OnInit, OnDestroy {
|
|||||||
private syncService: SyncService,
|
private syncService: SyncService,
|
||||||
private validationService: ValidationService,
|
private validationService: ValidationService,
|
||||||
private organizationService: OrganizationService,
|
private organizationService: OrganizationService,
|
||||||
|
private accountService: AccountService,
|
||||||
private dialogService: DialogService,
|
private dialogService: DialogService,
|
||||||
private formBuilder: FormBuilder,
|
private formBuilder: FormBuilder,
|
||||||
private toastService: ToastService,
|
private toastService: ToastService,
|
||||||
@@ -115,14 +118,18 @@ export class FamiliesForEnterpriseSetupComponent implements OnInit, OnDestroy {
|
|||||||
this.loading = false;
|
this.loading = false;
|
||||||
});
|
});
|
||||||
|
|
||||||
this.existingFamilyOrganizations$ = this.organizationService.organizations$.pipe(
|
const userId = await firstValueFrom(getUserId(this.accountService.activeAccount$));
|
||||||
map((orgs) =>
|
this.existingFamilyOrganizations$ = this.organizationService
|
||||||
orgs.filter(
|
.organizations$(userId)
|
||||||
(o) =>
|
.pipe(
|
||||||
o.productTierType === ProductTierType.Families && o.type === OrganizationUserType.Owner,
|
map((orgs) =>
|
||||||
|
orgs.filter(
|
||||||
|
(o) =>
|
||||||
|
o.productTierType === ProductTierType.Families &&
|
||||||
|
o.type === OrganizationUserType.Owner,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
);
|
||||||
);
|
|
||||||
|
|
||||||
this.existingFamilyOrganizations$.pipe(takeUntil(this._destroy)).subscribe((orgs) => {
|
this.existingFamilyOrganizations$.pipe(takeUntil(this._destroy)).subscribe((orgs) => {
|
||||||
if (orgs.length === 0) {
|
if (orgs.length === 0) {
|
||||||
|
|||||||
@@ -2,10 +2,15 @@
|
|||||||
// @ts-strict-ignore
|
// @ts-strict-ignore
|
||||||
import { Component, OnInit } from "@angular/core";
|
import { Component, OnInit } from "@angular/core";
|
||||||
import { ActivatedRoute } from "@angular/router";
|
import { ActivatedRoute } from "@angular/router";
|
||||||
|
import { firstValueFrom, map } from "rxjs";
|
||||||
|
|
||||||
import { ModalService } from "@bitwarden/angular/services/modal.service";
|
import { ModalService } from "@bitwarden/angular/services/modal.service";
|
||||||
import { AuditService } from "@bitwarden/common/abstractions/audit.service";
|
import { AuditService } from "@bitwarden/common/abstractions/audit.service";
|
||||||
import { 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 { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||||
import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service";
|
import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service";
|
||||||
import { SyncService } from "@bitwarden/common/vault/abstractions/sync/sync.service.abstraction";
|
import { SyncService } from "@bitwarden/common/vault/abstractions/sync/sync.service.abstraction";
|
||||||
@@ -32,6 +37,7 @@ export class ExposedPasswordsReportComponent
|
|||||||
auditService: AuditService,
|
auditService: AuditService,
|
||||||
modalService: ModalService,
|
modalService: ModalService,
|
||||||
organizationService: OrganizationService,
|
organizationService: OrganizationService,
|
||||||
|
protected accountService: AccountService,
|
||||||
private route: ActivatedRoute,
|
private route: ActivatedRoute,
|
||||||
passwordRepromptService: PasswordRepromptService,
|
passwordRepromptService: PasswordRepromptService,
|
||||||
i18nService: I18nService,
|
i18nService: I18nService,
|
||||||
@@ -41,6 +47,7 @@ export class ExposedPasswordsReportComponent
|
|||||||
cipherService,
|
cipherService,
|
||||||
auditService,
|
auditService,
|
||||||
organizationService,
|
organizationService,
|
||||||
|
accountService,
|
||||||
modalService,
|
modalService,
|
||||||
passwordRepromptService,
|
passwordRepromptService,
|
||||||
i18nService,
|
i18nService,
|
||||||
@@ -52,7 +59,14 @@ export class ExposedPasswordsReportComponent
|
|||||||
this.isAdminConsoleActive = true;
|
this.isAdminConsoleActive = true;
|
||||||
// eslint-disable-next-line rxjs-angular/prefer-takeuntil, rxjs/no-async-subscribe
|
// eslint-disable-next-line rxjs-angular/prefer-takeuntil, rxjs/no-async-subscribe
|
||||||
this.route.parent.parent.params.subscribe(async (params) => {
|
this.route.parent.parent.params.subscribe(async (params) => {
|
||||||
this.organization = await this.organizationService.get(params.organizationId);
|
const userId = await firstValueFrom(
|
||||||
|
this.accountService.activeAccount$.pipe(map((a) => a?.id)),
|
||||||
|
);
|
||||||
|
this.organization = await firstValueFrom(
|
||||||
|
this.organizationService
|
||||||
|
.organizations$(userId)
|
||||||
|
.pipe(getOrganizationById(params.organizationId)),
|
||||||
|
);
|
||||||
this.manageableCiphers = await this.cipherService.getAll();
|
this.manageableCiphers = await this.cipherService.getAll();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,9 +2,14 @@
|
|||||||
// @ts-strict-ignore
|
// @ts-strict-ignore
|
||||||
import { Component, OnInit } from "@angular/core";
|
import { Component, OnInit } from "@angular/core";
|
||||||
import { ActivatedRoute } from "@angular/router";
|
import { ActivatedRoute } from "@angular/router";
|
||||||
|
import { firstValueFrom, map } from "rxjs";
|
||||||
|
|
||||||
import { ModalService } from "@bitwarden/angular/services/modal.service";
|
import { ModalService } from "@bitwarden/angular/services/modal.service";
|
||||||
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 { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||||
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
|
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
|
||||||
import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service";
|
import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service";
|
||||||
@@ -31,12 +36,14 @@ export class InactiveTwoFactorReportComponent
|
|||||||
logService: LogService,
|
logService: LogService,
|
||||||
passwordRepromptService: PasswordRepromptService,
|
passwordRepromptService: PasswordRepromptService,
|
||||||
organizationService: OrganizationService,
|
organizationService: OrganizationService,
|
||||||
|
accountService: AccountService,
|
||||||
i18nService: I18nService,
|
i18nService: I18nService,
|
||||||
syncService: SyncService,
|
syncService: SyncService,
|
||||||
) {
|
) {
|
||||||
super(
|
super(
|
||||||
cipherService,
|
cipherService,
|
||||||
organizationService,
|
organizationService,
|
||||||
|
accountService,
|
||||||
modalService,
|
modalService,
|
||||||
logService,
|
logService,
|
||||||
passwordRepromptService,
|
passwordRepromptService,
|
||||||
@@ -49,7 +56,14 @@ export class InactiveTwoFactorReportComponent
|
|||||||
this.isAdminConsoleActive = true;
|
this.isAdminConsoleActive = true;
|
||||||
// eslint-disable-next-line rxjs-angular/prefer-takeuntil, rxjs/no-async-subscribe
|
// eslint-disable-next-line rxjs-angular/prefer-takeuntil, rxjs/no-async-subscribe
|
||||||
this.route.parent.parent.params.subscribe(async (params) => {
|
this.route.parent.parent.params.subscribe(async (params) => {
|
||||||
this.organization = await this.organizationService.get(params.organizationId);
|
const userId = await firstValueFrom(
|
||||||
|
this.accountService.activeAccount$.pipe(map((a) => a?.id)),
|
||||||
|
);
|
||||||
|
this.organization = await firstValueFrom(
|
||||||
|
this.organizationService
|
||||||
|
.organizations$(userId)
|
||||||
|
.pipe(getOrganizationById(params.organizationId)),
|
||||||
|
);
|
||||||
await super.ngOnInit();
|
await super.ngOnInit();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,9 +2,14 @@
|
|||||||
// @ts-strict-ignore
|
// @ts-strict-ignore
|
||||||
import { Component, OnInit } from "@angular/core";
|
import { Component, OnInit } from "@angular/core";
|
||||||
import { ActivatedRoute } from "@angular/router";
|
import { ActivatedRoute } from "@angular/router";
|
||||||
|
import { firstValueFrom, map } from "rxjs";
|
||||||
|
|
||||||
import { ModalService } from "@bitwarden/angular/services/modal.service";
|
import { ModalService } from "@bitwarden/angular/services/modal.service";
|
||||||
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 { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||||
import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service";
|
import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service";
|
||||||
import { SyncService } from "@bitwarden/common/vault/abstractions/sync/sync.service.abstraction";
|
import { SyncService } from "@bitwarden/common/vault/abstractions/sync/sync.service.abstraction";
|
||||||
@@ -31,6 +36,7 @@ export class ReusedPasswordsReportComponent
|
|||||||
modalService: ModalService,
|
modalService: ModalService,
|
||||||
private route: ActivatedRoute,
|
private route: ActivatedRoute,
|
||||||
organizationService: OrganizationService,
|
organizationService: OrganizationService,
|
||||||
|
protected accountService: AccountService,
|
||||||
passwordRepromptService: PasswordRepromptService,
|
passwordRepromptService: PasswordRepromptService,
|
||||||
i18nService: I18nService,
|
i18nService: I18nService,
|
||||||
syncService: SyncService,
|
syncService: SyncService,
|
||||||
@@ -38,6 +44,7 @@ export class ReusedPasswordsReportComponent
|
|||||||
super(
|
super(
|
||||||
cipherService,
|
cipherService,
|
||||||
organizationService,
|
organizationService,
|
||||||
|
accountService,
|
||||||
modalService,
|
modalService,
|
||||||
passwordRepromptService,
|
passwordRepromptService,
|
||||||
i18nService,
|
i18nService,
|
||||||
@@ -49,7 +56,14 @@ export class ReusedPasswordsReportComponent
|
|||||||
this.isAdminConsoleActive = true;
|
this.isAdminConsoleActive = true;
|
||||||
// eslint-disable-next-line rxjs-angular/prefer-takeuntil, rxjs/no-async-subscribe
|
// eslint-disable-next-line rxjs-angular/prefer-takeuntil, rxjs/no-async-subscribe
|
||||||
this.route.parent.parent.params.subscribe(async (params) => {
|
this.route.parent.parent.params.subscribe(async (params) => {
|
||||||
this.organization = await this.organizationService.get(params.organizationId);
|
const userId = await firstValueFrom(
|
||||||
|
this.accountService.activeAccount$.pipe(map((a) => a?.id)),
|
||||||
|
);
|
||||||
|
this.organization = await firstValueFrom(
|
||||||
|
this.organizationService
|
||||||
|
.organizations$(userId)
|
||||||
|
.pipe(getOrganizationById(params.organizationId)),
|
||||||
|
);
|
||||||
this.manageableCiphers = await this.cipherService.getAll();
|
this.manageableCiphers = await this.cipherService.getAll();
|
||||||
await super.ngOnInit();
|
await super.ngOnInit();
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -2,10 +2,15 @@
|
|||||||
// @ts-strict-ignore
|
// @ts-strict-ignore
|
||||||
import { Component, OnInit } from "@angular/core";
|
import { Component, OnInit } from "@angular/core";
|
||||||
import { ActivatedRoute } from "@angular/router";
|
import { ActivatedRoute } from "@angular/router";
|
||||||
|
import { firstValueFrom, map } from "rxjs";
|
||||||
|
|
||||||
import { CollectionService } from "@bitwarden/admin-console/common";
|
import { CollectionService } from "@bitwarden/admin-console/common";
|
||||||
import { ModalService } from "@bitwarden/angular/services/modal.service";
|
import { ModalService } from "@bitwarden/angular/services/modal.service";
|
||||||
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 { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||||
import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service";
|
import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service";
|
||||||
import { SyncService } from "@bitwarden/common/vault/abstractions/sync/sync.service.abstraction";
|
import { SyncService } from "@bitwarden/common/vault/abstractions/sync/sync.service.abstraction";
|
||||||
@@ -29,6 +34,7 @@ export class UnsecuredWebsitesReportComponent
|
|||||||
modalService: ModalService,
|
modalService: ModalService,
|
||||||
private route: ActivatedRoute,
|
private route: ActivatedRoute,
|
||||||
organizationService: OrganizationService,
|
organizationService: OrganizationService,
|
||||||
|
protected accountService: AccountService,
|
||||||
passwordRepromptService: PasswordRepromptService,
|
passwordRepromptService: PasswordRepromptService,
|
||||||
i18nService: I18nService,
|
i18nService: I18nService,
|
||||||
syncService: SyncService,
|
syncService: SyncService,
|
||||||
@@ -37,6 +43,7 @@ export class UnsecuredWebsitesReportComponent
|
|||||||
super(
|
super(
|
||||||
cipherService,
|
cipherService,
|
||||||
organizationService,
|
organizationService,
|
||||||
|
accountService,
|
||||||
modalService,
|
modalService,
|
||||||
passwordRepromptService,
|
passwordRepromptService,
|
||||||
i18nService,
|
i18nService,
|
||||||
@@ -49,7 +56,14 @@ export class UnsecuredWebsitesReportComponent
|
|||||||
this.isAdminConsoleActive = true;
|
this.isAdminConsoleActive = true;
|
||||||
// eslint-disable-next-line rxjs-angular/prefer-takeuntil, rxjs/no-async-subscribe
|
// eslint-disable-next-line rxjs-angular/prefer-takeuntil, rxjs/no-async-subscribe
|
||||||
this.route.parent.parent.params.subscribe(async (params) => {
|
this.route.parent.parent.params.subscribe(async (params) => {
|
||||||
this.organization = await this.organizationService.get(params.organizationId);
|
const userId = await firstValueFrom(
|
||||||
|
this.accountService.activeAccount$.pipe(map((a) => a?.id)),
|
||||||
|
);
|
||||||
|
this.organization = await firstValueFrom(
|
||||||
|
this.organizationService
|
||||||
|
.organizations$(userId)
|
||||||
|
.pipe(getOrganizationById(params.organizationId)),
|
||||||
|
);
|
||||||
await super.ngOnInit();
|
await super.ngOnInit();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,9 +2,14 @@
|
|||||||
// @ts-strict-ignore
|
// @ts-strict-ignore
|
||||||
import { Component, OnInit } from "@angular/core";
|
import { Component, OnInit } from "@angular/core";
|
||||||
import { ActivatedRoute } from "@angular/router";
|
import { ActivatedRoute } from "@angular/router";
|
||||||
|
import { firstValueFrom, map } from "rxjs";
|
||||||
|
|
||||||
import { ModalService } from "@bitwarden/angular/services/modal.service";
|
import { ModalService } from "@bitwarden/angular/services/modal.service";
|
||||||
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 { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||||
import { PasswordStrengthServiceAbstraction } from "@bitwarden/common/tools/password-strength";
|
import { PasswordStrengthServiceAbstraction } from "@bitwarden/common/tools/password-strength";
|
||||||
import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service";
|
import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service";
|
||||||
@@ -36,11 +41,13 @@ export class WeakPasswordsReportComponent
|
|||||||
passwordRepromptService: PasswordRepromptService,
|
passwordRepromptService: PasswordRepromptService,
|
||||||
i18nService: I18nService,
|
i18nService: I18nService,
|
||||||
syncService: SyncService,
|
syncService: SyncService,
|
||||||
|
protected accountService: AccountService,
|
||||||
) {
|
) {
|
||||||
super(
|
super(
|
||||||
cipherService,
|
cipherService,
|
||||||
passwordStrengthService,
|
passwordStrengthService,
|
||||||
organizationService,
|
organizationService,
|
||||||
|
accountService,
|
||||||
modalService,
|
modalService,
|
||||||
passwordRepromptService,
|
passwordRepromptService,
|
||||||
i18nService,
|
i18nService,
|
||||||
@@ -52,7 +59,14 @@ export class WeakPasswordsReportComponent
|
|||||||
this.isAdminConsoleActive = true;
|
this.isAdminConsoleActive = true;
|
||||||
// eslint-disable-next-line rxjs-angular/prefer-takeuntil, rxjs/no-async-subscribe
|
// eslint-disable-next-line rxjs-angular/prefer-takeuntil, rxjs/no-async-subscribe
|
||||||
this.route.parent.parent.params.subscribe(async (params) => {
|
this.route.parent.parent.params.subscribe(async (params) => {
|
||||||
this.organization = await this.organizationService.get(params.organizationId);
|
const userId = await firstValueFrom(
|
||||||
|
this.accountService.activeAccount$.pipe(map((a) => a?.id)),
|
||||||
|
);
|
||||||
|
this.organization = await firstValueFrom(
|
||||||
|
this.organizationService
|
||||||
|
.organizations$(userId)
|
||||||
|
.pipe(getOrganizationById(params.organizationId)),
|
||||||
|
);
|
||||||
this.manageableCiphers = await this.cipherService.getAll();
|
this.manageableCiphers = await this.cipherService.getAll();
|
||||||
await super.ngOnInit();
|
await super.ngOnInit();
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ import { AccountService } from "@bitwarden/common/auth/abstractions/account.serv
|
|||||||
import { AuthService } from "@bitwarden/common/auth/abstractions/auth.service";
|
import { AuthService } from "@bitwarden/common/auth/abstractions/auth.service";
|
||||||
import { KeyConnectorService } from "@bitwarden/common/auth/abstractions/key-connector.service";
|
import { KeyConnectorService } from "@bitwarden/common/auth/abstractions/key-connector.service";
|
||||||
import { AuthenticationStatus } from "@bitwarden/common/auth/enums/authentication-status";
|
import { AuthenticationStatus } from "@bitwarden/common/auth/enums/authentication-status";
|
||||||
|
import { getUserId } from "@bitwarden/common/auth/services/account.service";
|
||||||
import { ProcessReloadServiceAbstraction } from "@bitwarden/common/key-management/abstractions/process-reload.service";
|
import { ProcessReloadServiceAbstraction } from "@bitwarden/common/key-management/abstractions/process-reload.service";
|
||||||
import { BroadcasterService } from "@bitwarden/common/platform/abstractions/broadcaster.service";
|
import { BroadcasterService } from "@bitwarden/common/platform/abstractions/broadcaster.service";
|
||||||
import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
|
import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
|
||||||
@@ -219,7 +220,10 @@ export class AppComponent implements OnDestroy, OnInit {
|
|||||||
break;
|
break;
|
||||||
case "syncOrganizationStatusChanged": {
|
case "syncOrganizationStatusChanged": {
|
||||||
const { organizationId, enabled } = message;
|
const { organizationId, enabled } = message;
|
||||||
const organizations = await firstValueFrom(this.organizationService.organizations$);
|
const userId = await firstValueFrom(getUserId(this.accountService.activeAccount$));
|
||||||
|
const organizations = await firstValueFrom(
|
||||||
|
this.organizationService.organizations$(userId),
|
||||||
|
);
|
||||||
const organization = organizations.find((org) => org.id === organizationId);
|
const organization = organizations.find((org) => org.id === organizationId);
|
||||||
|
|
||||||
if (organization) {
|
if (organization) {
|
||||||
@@ -227,21 +231,27 @@ export class AppComponent implements OnDestroy, OnInit {
|
|||||||
...organization,
|
...organization,
|
||||||
enabled: enabled,
|
enabled: enabled,
|
||||||
};
|
};
|
||||||
await this.organizationService.upsert(updatedOrganization);
|
await this.organizationService.upsert(updatedOrganization, userId);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case "syncOrganizationCollectionSettingChanged": {
|
case "syncOrganizationCollectionSettingChanged": {
|
||||||
const { organizationId, limitCollectionCreation, limitCollectionDeletion } = message;
|
const { organizationId, limitCollectionCreation, limitCollectionDeletion } = message;
|
||||||
const organizations = await firstValueFrom(this.organizationService.organizations$);
|
const userId = await firstValueFrom(getUserId(this.accountService.activeAccount$));
|
||||||
|
const organizations = await firstValueFrom(
|
||||||
|
this.organizationService.organizations$(userId),
|
||||||
|
);
|
||||||
const organization = organizations.find((org) => org.id === organizationId);
|
const organization = organizations.find((org) => org.id === organizationId);
|
||||||
|
|
||||||
if (organization) {
|
if (organization) {
|
||||||
await this.organizationService.upsert({
|
await this.organizationService.upsert(
|
||||||
...organization,
|
{
|
||||||
limitCollectionCreation: limitCollectionCreation,
|
...organization,
|
||||||
limitCollectionDeletion: limitCollectionDeletion,
|
limitCollectionCreation: limitCollectionCreation,
|
||||||
});
|
limitCollectionDeletion: limitCollectionDeletion,
|
||||||
|
},
|
||||||
|
userId,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -291,7 +301,7 @@ export class AppComponent implements OnDestroy, OnInit {
|
|||||||
// will prevent any toasts from being displayed long enough to be read
|
// will prevent any toasts from being displayed long enough to be read
|
||||||
|
|
||||||
await this.eventUploadService.uploadEvents();
|
await this.eventUploadService.uploadEvents();
|
||||||
const userId = await firstValueFrom(this.accountService.activeAccount$.pipe(map((a) => a?.id)));
|
const userId = await firstValueFrom(getUserId(this.accountService.activeAccount$));
|
||||||
|
|
||||||
const logoutPromise = firstValueFrom(
|
const logoutPromise = firstValueFrom(
|
||||||
this.authService.authStatusFor$(userId).pipe(
|
this.authService.authStatusFor$(userId).pipe(
|
||||||
|
|||||||
@@ -1,11 +1,13 @@
|
|||||||
// FIXME: Update this file to be type safe and remove this and next line
|
// FIXME: Update this file to be type safe and remove this and next line
|
||||||
// @ts-strict-ignore
|
// @ts-strict-ignore
|
||||||
import { Component, OnInit, ViewChild, ViewContainerRef } from "@angular/core";
|
import { Component, OnInit, ViewChild, ViewContainerRef } from "@angular/core";
|
||||||
import { combineLatest, from, lastValueFrom, map, Observable } from "rxjs";
|
import { combineLatest, firstValueFrom, from, lastValueFrom, map, Observable } from "rxjs";
|
||||||
|
|
||||||
import { ModalService } from "@bitwarden/angular/services/modal.service";
|
import { ModalService } from "@bitwarden/angular/services/modal.service";
|
||||||
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
||||||
|
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
||||||
import { UserVerificationService } from "@bitwarden/common/auth/abstractions/user-verification/user-verification.service.abstraction";
|
import { UserVerificationService } from "@bitwarden/common/auth/abstractions/user-verification/user-verification.service.abstraction";
|
||||||
|
import { getUserId } from "@bitwarden/common/auth/services/account.service";
|
||||||
import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum";
|
import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum";
|
||||||
import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
|
import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
|
||||||
import { DialogService } from "@bitwarden/components";
|
import { DialogService } from "@bitwarden/components";
|
||||||
@@ -33,16 +35,21 @@ export class AccountComponent implements OnInit {
|
|||||||
private userVerificationService: UserVerificationService,
|
private userVerificationService: UserVerificationService,
|
||||||
private configService: ConfigService,
|
private configService: ConfigService,
|
||||||
private organizationService: OrganizationService,
|
private organizationService: OrganizationService,
|
||||||
|
private accountService: AccountService,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
async ngOnInit() {
|
async ngOnInit() {
|
||||||
|
const userId = await firstValueFrom(getUserId(this.accountService.activeAccount$));
|
||||||
|
|
||||||
const isAccountDeprovisioningEnabled$ = this.configService.getFeatureFlag$(
|
const isAccountDeprovisioningEnabled$ = this.configService.getFeatureFlag$(
|
||||||
FeatureFlag.AccountDeprovisioning,
|
FeatureFlag.AccountDeprovisioning,
|
||||||
);
|
);
|
||||||
|
|
||||||
const userIsManagedByOrganization$ = this.organizationService.organizations$.pipe(
|
const userIsManagedByOrganization$ = this.organizationService
|
||||||
map((organizations) => organizations.some((o) => o.userIsManagedByOrganization === true)),
|
.organizations$(userId)
|
||||||
);
|
.pipe(
|
||||||
|
map((organizations) => organizations.some((o) => o.userIsManagedByOrganization === true)),
|
||||||
|
);
|
||||||
|
|
||||||
const hasMasterPassword$ = from(this.userVerificationService.hasMasterPassword());
|
const hasMasterPassword$ = from(this.userVerificationService.hasMasterPassword());
|
||||||
|
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import { OrganizationService } from "@bitwarden/common/admin-console/abstraction
|
|||||||
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
|
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
|
||||||
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
||||||
import { UpdateProfileRequest } from "@bitwarden/common/auth/models/request/update-profile.request";
|
import { UpdateProfileRequest } from "@bitwarden/common/auth/models/request/update-profile.request";
|
||||||
|
import { getUserId } from "@bitwarden/common/auth/services/account.service";
|
||||||
import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum";
|
import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum";
|
||||||
import { ProfileResponse } from "@bitwarden/common/models/response/profile.response";
|
import { ProfileResponse } from "@bitwarden/common/models/response/profile.response";
|
||||||
import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
|
import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
|
||||||
@@ -49,16 +50,21 @@ export class ProfileComponent implements OnInit, OnDestroy {
|
|||||||
this.fingerprintMaterial = await firstValueFrom(
|
this.fingerprintMaterial = await firstValueFrom(
|
||||||
this.accountService.activeAccount$.pipe(map((a) => a?.id)),
|
this.accountService.activeAccount$.pipe(map((a) => a?.id)),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const userId = await firstValueFrom(getUserId(this.accountService.activeAccount$));
|
||||||
|
|
||||||
this.managingOrganization$ = this.configService
|
this.managingOrganization$ = this.configService
|
||||||
.getFeatureFlag$(FeatureFlag.AccountDeprovisioning)
|
.getFeatureFlag$(FeatureFlag.AccountDeprovisioning)
|
||||||
.pipe(
|
.pipe(
|
||||||
switchMap((isAccountDeprovisioningEnabled) =>
|
switchMap((isAccountDeprovisioningEnabled) =>
|
||||||
isAccountDeprovisioningEnabled
|
isAccountDeprovisioningEnabled
|
||||||
? this.organizationService.organizations$.pipe(
|
? this.organizationService
|
||||||
map((organizations) =>
|
.organizations$(userId)
|
||||||
organizations.find((o) => o.userIsManagedByOrganization === true),
|
.pipe(
|
||||||
),
|
map((organizations) =>
|
||||||
)
|
organizations.find((o) => o.userIsManagedByOrganization === true),
|
||||||
|
),
|
||||||
|
)
|
||||||
: of(null),
|
: of(null),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import { AccountService } from "@bitwarden/common/auth/abstractions/account.serv
|
|||||||
import { InternalMasterPasswordServiceAbstraction } from "@bitwarden/common/auth/abstractions/master-password.service.abstraction";
|
import { InternalMasterPasswordServiceAbstraction } from "@bitwarden/common/auth/abstractions/master-password.service.abstraction";
|
||||||
import { UserVerificationService } from "@bitwarden/common/auth/abstractions/user-verification/user-verification.service.abstraction";
|
import { UserVerificationService } from "@bitwarden/common/auth/abstractions/user-verification/user-verification.service.abstraction";
|
||||||
import { PasswordRequest } from "@bitwarden/common/auth/models/request/password.request";
|
import { PasswordRequest } from "@bitwarden/common/auth/models/request/password.request";
|
||||||
|
import { getUserId } from "@bitwarden/common/auth/services/account.service";
|
||||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||||
import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service";
|
import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service";
|
||||||
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
||||||
@@ -188,7 +189,7 @@ export class ChangePasswordComponent
|
|||||||
await this.kdfConfigService.getKdfConfig(),
|
await this.kdfConfigService.getKdfConfig(),
|
||||||
);
|
);
|
||||||
|
|
||||||
const userId = await firstValueFrom(this.accountService.activeAccount$.pipe(map((a) => a?.id)));
|
const userId = await firstValueFrom(getUserId(this.accountService.activeAccount$));
|
||||||
const newLocalKeyHash = await this.keyService.hashMasterKey(
|
const newLocalKeyHash = await this.keyService.hashMasterKey(
|
||||||
this.masterPassword,
|
this.masterPassword,
|
||||||
newMasterKey,
|
newMasterKey,
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
|||||||
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
||||||
import { OrganizationManagementPreferencesService } from "@bitwarden/common/admin-console/abstractions/organization-management-preferences/organization-management-preferences.service";
|
import { OrganizationManagementPreferencesService } from "@bitwarden/common/admin-console/abstractions/organization-management-preferences/organization-management-preferences.service";
|
||||||
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
||||||
|
import { getUserId } from "@bitwarden/common/auth/services/account.service";
|
||||||
import { BillingAccountProfileStateService } from "@bitwarden/common/billing/abstractions/account/billing-account-profile-state.service";
|
import { BillingAccountProfileStateService } from "@bitwarden/common/billing/abstractions/account/billing-account-profile-state.service";
|
||||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||||
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
|
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
|
||||||
@@ -83,7 +84,8 @@ export class EmergencyAccessComponent implements OnInit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async ngOnInit() {
|
async ngOnInit() {
|
||||||
const orgs = await this.organizationService.getAll();
|
const userId = await firstValueFrom(getUserId(this.accountService.activeAccount$));
|
||||||
|
const orgs = await firstValueFrom(this.organizationService.organizations$(userId));
|
||||||
this.isOrganizationOwner = orgs.some((o) => o.isOwner);
|
this.isOrganizationOwner = orgs.some((o) => o.isOwner);
|
||||||
// FIXME: Verify that this floating promise is intentional. If it is, add an explanatory comment and ensure there is proper error handling.
|
// FIXME: Verify that this floating promise is intentional. If it is, add an explanatory comment and ensure there is proper error handling.
|
||||||
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
||||||
|
|||||||
@@ -43,6 +43,7 @@ describe("EmergencyViewDialogComponent", () => {
|
|||||||
imports: [EmergencyViewDialogComponent, NoopAnimationsModule],
|
imports: [EmergencyViewDialogComponent, NoopAnimationsModule],
|
||||||
providers: [
|
providers: [
|
||||||
{ provide: OrganizationService, useValue: mock<OrganizationService>() },
|
{ provide: OrganizationService, useValue: mock<OrganizationService>() },
|
||||||
|
{ provide: AccountService, useValue: accountService },
|
||||||
{ provide: CollectionService, useValue: mock<CollectionService>() },
|
{ provide: CollectionService, useValue: mock<CollectionService>() },
|
||||||
{ provide: FolderService, useValue: mock<FolderService>() },
|
{ provide: FolderService, useValue: mock<FolderService>() },
|
||||||
{ provide: I18nService, useValue: { t: (...keys: string[]) => keys.join(" ") } },
|
{ provide: I18nService, useValue: { t: (...keys: string[]) => keys.join(" ") } },
|
||||||
|
|||||||
@@ -71,7 +71,7 @@ export class TwoFactorSetupComponent implements OnInit, OnDestroy {
|
|||||||
protected messagingService: MessagingService,
|
protected messagingService: MessagingService,
|
||||||
protected policyService: PolicyService,
|
protected policyService: PolicyService,
|
||||||
billingAccountProfileStateService: BillingAccountProfileStateService,
|
billingAccountProfileStateService: BillingAccountProfileStateService,
|
||||||
private accountService: AccountService,
|
protected accountService: AccountService,
|
||||||
) {
|
) {
|
||||||
this.canAccessPremium$ = this.accountService.activeAccount$.pipe(
|
this.canAccessPremium$ = this.accountService.activeAccount$.pipe(
|
||||||
switchMap((account) =>
|
switchMap((account) =>
|
||||||
|
|||||||
@@ -1,15 +1,35 @@
|
|||||||
import { inject } from "@angular/core";
|
import { inject } from "@angular/core";
|
||||||
import { ActivatedRouteSnapshot, CanActivateFn } from "@angular/router";
|
import { ActivatedRouteSnapshot, CanActivateFn } from "@angular/router";
|
||||||
|
import { firstValueFrom, map } 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 { ProviderService } from "@bitwarden/common/admin-console/abstractions/provider.service";
|
import { ProviderService } from "@bitwarden/common/admin-console/abstractions/provider.service";
|
||||||
import { ProviderStatusType } from "@bitwarden/common/admin-console/enums";
|
import { ProviderStatusType } from "@bitwarden/common/admin-console/enums";
|
||||||
|
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
||||||
|
|
||||||
export const organizationIsUnmanaged: CanActivateFn = async (route: ActivatedRouteSnapshot) => {
|
export const organizationIsUnmanaged: CanActivateFn = async (route: ActivatedRouteSnapshot) => {
|
||||||
const organizationService = inject(OrganizationService);
|
const organizationService = inject(OrganizationService);
|
||||||
const providerService = inject(ProviderService);
|
const providerService = inject(ProviderService);
|
||||||
|
const accountService = inject(AccountService);
|
||||||
|
|
||||||
const organization = await organizationService.get(route.params.organizationId);
|
const userId = await firstValueFrom(accountService.activeAccount$.pipe(map((a) => a?.id)));
|
||||||
|
|
||||||
|
if (!userId) {
|
||||||
|
throw new Error("No user found.");
|
||||||
|
}
|
||||||
|
|
||||||
|
const organization = await firstValueFrom(
|
||||||
|
organizationService
|
||||||
|
.organizations$(userId)
|
||||||
|
.pipe(getOrganizationById(route.params.organizationId)),
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!organization) {
|
||||||
|
throw new Error("No organization found.");
|
||||||
|
}
|
||||||
|
|
||||||
if (!organization.hasProvider) {
|
if (!organization.hasProvider) {
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -2,11 +2,16 @@
|
|||||||
// @ts-strict-ignore
|
// @ts-strict-ignore
|
||||||
import { Component, EventEmitter, Input, OnDestroy, OnInit, Output } from "@angular/core";
|
import { Component, EventEmitter, Input, OnDestroy, OnInit, Output } from "@angular/core";
|
||||||
import { FormBuilder, Validators } from "@angular/forms";
|
import { FormBuilder, Validators } from "@angular/forms";
|
||||||
import { Subject, takeUntil } from "rxjs";
|
import { Subject, firstValueFrom, takeUntil } from "rxjs";
|
||||||
|
|
||||||
import { OrganizationApiServiceAbstraction } from "@bitwarden/common/admin-console/abstractions/organization/organization-api.service.abstraction";
|
import { OrganizationApiServiceAbstraction } from "@bitwarden/common/admin-console/abstractions/organization/organization-api.service.abstraction";
|
||||||
import { InternalOrganizationServiceAbstraction } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
import {
|
||||||
|
getOrganizationById,
|
||||||
|
InternalOrganizationServiceAbstraction,
|
||||||
|
} from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
||||||
import { OrganizationData } from "@bitwarden/common/admin-console/models/data/organization.data";
|
import { OrganizationData } from "@bitwarden/common/admin-console/models/data/organization.data";
|
||||||
|
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
||||||
|
import { getUserId } from "@bitwarden/common/auth/services/account.service";
|
||||||
import { OrganizationSubscriptionUpdateRequest } from "@bitwarden/common/billing/models/request/organization-subscription-update.request";
|
import { OrganizationSubscriptionUpdateRequest } from "@bitwarden/common/billing/models/request/organization-subscription-update.request";
|
||||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||||
import { ToastService } from "@bitwarden/components";
|
import { ToastService } from "@bitwarden/components";
|
||||||
@@ -37,6 +42,7 @@ export class AdjustSubscription implements OnInit, OnDestroy {
|
|||||||
private formBuilder: FormBuilder,
|
private formBuilder: FormBuilder,
|
||||||
private toastService: ToastService,
|
private toastService: ToastService,
|
||||||
private internalOrganizationService: InternalOrganizationServiceAbstraction,
|
private internalOrganizationService: InternalOrganizationServiceAbstraction,
|
||||||
|
private accountService: AccountService,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
@@ -73,14 +79,19 @@ export class AdjustSubscription implements OnInit, OnDestroy {
|
|||||||
request,
|
request,
|
||||||
);
|
);
|
||||||
|
|
||||||
const organization = await this.internalOrganizationService.get(this.organizationId);
|
const userId = await firstValueFrom(getUserId(this.accountService.activeAccount$));
|
||||||
|
const organization = await firstValueFrom(
|
||||||
|
this.internalOrganizationService
|
||||||
|
.organizations$(userId)
|
||||||
|
.pipe(getOrganizationById(this.organizationId)),
|
||||||
|
);
|
||||||
|
|
||||||
const organizationData = new OrganizationData(response, {
|
const organizationData = new OrganizationData(response, {
|
||||||
isMember: organization.isMember,
|
isMember: organization.isMember,
|
||||||
isProviderUser: organization.isProviderUser,
|
isProviderUser: organization.isProviderUser,
|
||||||
});
|
});
|
||||||
|
|
||||||
await this.internalOrganizationService.upsert(organizationData);
|
await this.internalOrganizationService.upsert(organizationData, userId);
|
||||||
|
|
||||||
this.toastService.showToast({
|
this.toastService.showToast({
|
||||||
variant: "success",
|
variant: "success",
|
||||||
|
|||||||
@@ -13,17 +13,21 @@ import {
|
|||||||
} from "@angular/core";
|
} from "@angular/core";
|
||||||
import { FormBuilder, Validators } from "@angular/forms";
|
import { FormBuilder, Validators } from "@angular/forms";
|
||||||
import { Router } from "@angular/router";
|
import { Router } from "@angular/router";
|
||||||
import { Subject, takeUntil } from "rxjs";
|
import { Subject, firstValueFrom, map, takeUntil } from "rxjs";
|
||||||
|
|
||||||
import { ManageTaxInformationComponent } from "@bitwarden/angular/billing/components";
|
import { ManageTaxInformationComponent } from "@bitwarden/angular/billing/components";
|
||||||
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
||||||
import { OrganizationApiServiceAbstraction } from "@bitwarden/common/admin-console/abstractions/organization/organization-api.service.abstraction";
|
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 { PolicyService } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction";
|
import { PolicyService } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction";
|
||||||
import { PolicyType } from "@bitwarden/common/admin-console/enums";
|
import { PolicyType } from "@bitwarden/common/admin-console/enums";
|
||||||
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
|
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
|
||||||
import { OrganizationKeysRequest } from "@bitwarden/common/admin-console/models/request/organization-keys.request";
|
import { OrganizationKeysRequest } from "@bitwarden/common/admin-console/models/request/organization-keys.request";
|
||||||
import { OrganizationUpgradeRequest } from "@bitwarden/common/admin-console/models/request/organization-upgrade.request";
|
import { OrganizationUpgradeRequest } from "@bitwarden/common/admin-console/models/request/organization-upgrade.request";
|
||||||
|
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
||||||
import {
|
import {
|
||||||
BillingApiServiceAbstraction,
|
BillingApiServiceAbstraction,
|
||||||
BillingInformation,
|
BillingInformation,
|
||||||
@@ -209,6 +213,7 @@ export class ChangePlanDialogComponent implements OnInit, OnDestroy {
|
|||||||
private configService: ConfigService,
|
private configService: ConfigService,
|
||||||
private billingApiService: BillingApiServiceAbstraction,
|
private billingApiService: BillingApiServiceAbstraction,
|
||||||
private taxService: TaxServiceAbstraction,
|
private taxService: TaxServiceAbstraction,
|
||||||
|
private accountService: AccountService,
|
||||||
private organizationBillingService: OrganizationBillingService,
|
private organizationBillingService: OrganizationBillingService,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
@@ -226,7 +231,14 @@ export class ChangePlanDialogComponent implements OnInit, OnDestroy {
|
|||||||
this.organizationId = this.dialogParams.organizationId;
|
this.organizationId = this.dialogParams.organizationId;
|
||||||
this.currentPlan = this.sub?.plan;
|
this.currentPlan = this.sub?.plan;
|
||||||
this.selectedPlan = this.sub?.plan;
|
this.selectedPlan = this.sub?.plan;
|
||||||
this.organization = await this.organizationService.get(this.organizationId);
|
const userId = await firstValueFrom(
|
||||||
|
this.accountService.activeAccount$.pipe(map((a) => a?.id)),
|
||||||
|
);
|
||||||
|
this.organization = await firstValueFrom(
|
||||||
|
this.organizationService
|
||||||
|
.organizations$(userId)
|
||||||
|
.pipe(getOrganizationById(this.organizationId)),
|
||||||
|
);
|
||||||
if (this.deprecateStripeSourcesAPI) {
|
if (this.deprecateStripeSourcesAPI) {
|
||||||
const { accountCredit, paymentSource } =
|
const { accountCredit, paymentSource } =
|
||||||
await this.billingApiService.getOrganizationPaymentMethod(this.organizationId);
|
await this.billingApiService.getOrganizationPaymentMethod(this.organizationId);
|
||||||
|
|||||||
@@ -11,13 +11,16 @@ import {
|
|||||||
} from "@angular/core";
|
} from "@angular/core";
|
||||||
import { FormBuilder, Validators } from "@angular/forms";
|
import { FormBuilder, Validators } from "@angular/forms";
|
||||||
import { Router } from "@angular/router";
|
import { Router } from "@angular/router";
|
||||||
import { Subject, takeUntil } from "rxjs";
|
import { Subject, firstValueFrom, takeUntil } from "rxjs";
|
||||||
import { debounceTime } from "rxjs/operators";
|
import { debounceTime, map } from "rxjs/operators";
|
||||||
|
|
||||||
import { ManageTaxInformationComponent } from "@bitwarden/angular/billing/components";
|
import { ManageTaxInformationComponent } from "@bitwarden/angular/billing/components";
|
||||||
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
||||||
import { OrganizationApiServiceAbstraction } from "@bitwarden/common/admin-console/abstractions/organization/organization-api.service.abstraction";
|
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 { PolicyService } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction";
|
import { PolicyService } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction";
|
||||||
import { ProviderApiServiceAbstraction } from "@bitwarden/common/admin-console/abstractions/provider/provider-api.service.abstraction";
|
import { ProviderApiServiceAbstraction } from "@bitwarden/common/admin-console/abstractions/provider/provider-api.service.abstraction";
|
||||||
import { PolicyType } from "@bitwarden/common/admin-console/enums";
|
import { PolicyType } from "@bitwarden/common/admin-console/enums";
|
||||||
@@ -27,6 +30,7 @@ import { OrganizationKeysRequest } from "@bitwarden/common/admin-console/models/
|
|||||||
import { OrganizationUpgradeRequest } from "@bitwarden/common/admin-console/models/request/organization-upgrade.request";
|
import { OrganizationUpgradeRequest } from "@bitwarden/common/admin-console/models/request/organization-upgrade.request";
|
||||||
import { ProviderOrganizationCreateRequest } from "@bitwarden/common/admin-console/models/request/provider/provider-organization-create.request";
|
import { ProviderOrganizationCreateRequest } from "@bitwarden/common/admin-console/models/request/provider/provider-organization-create.request";
|
||||||
import { ProviderResponse } from "@bitwarden/common/admin-console/models/response/provider/provider.response";
|
import { ProviderResponse } from "@bitwarden/common/admin-console/models/response/provider/provider.response";
|
||||||
|
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
||||||
import { BillingApiServiceAbstraction } from "@bitwarden/common/billing/abstractions";
|
import { BillingApiServiceAbstraction } from "@bitwarden/common/billing/abstractions";
|
||||||
import { TaxServiceAbstraction } from "@bitwarden/common/billing/abstractions/tax.service.abstraction";
|
import { TaxServiceAbstraction } from "@bitwarden/common/billing/abstractions/tax.service.abstraction";
|
||||||
import { PaymentMethodType, PlanType, ProductTierType } from "@bitwarden/common/billing/enums";
|
import { PaymentMethodType, PlanType, ProductTierType } from "@bitwarden/common/billing/enums";
|
||||||
@@ -179,6 +183,7 @@ export class OrganizationPlansComponent implements OnInit, OnDestroy {
|
|||||||
private configService: ConfigService,
|
private configService: ConfigService,
|
||||||
private billingApiService: BillingApiServiceAbstraction,
|
private billingApiService: BillingApiServiceAbstraction,
|
||||||
private taxService: TaxServiceAbstraction,
|
private taxService: TaxServiceAbstraction,
|
||||||
|
private accountService: AccountService,
|
||||||
) {
|
) {
|
||||||
this.selfHosted = this.platformUtilsService.isSelfHost();
|
this.selfHosted = this.platformUtilsService.isSelfHost();
|
||||||
}
|
}
|
||||||
@@ -189,7 +194,14 @@ export class OrganizationPlansComponent implements OnInit, OnDestroy {
|
|||||||
);
|
);
|
||||||
|
|
||||||
if (this.organizationId) {
|
if (this.organizationId) {
|
||||||
this.organization = await this.organizationService.get(this.organizationId);
|
const userId = await firstValueFrom(
|
||||||
|
this.accountService.activeAccount$.pipe(map((a) => a?.id)),
|
||||||
|
);
|
||||||
|
this.organization = await firstValueFrom(
|
||||||
|
this.organizationService
|
||||||
|
.organizations$(userId)
|
||||||
|
.pipe(getOrganizationById(this.organizationId)),
|
||||||
|
);
|
||||||
this.billing = await this.organizationApiService.getBilling(this.organizationId);
|
this.billing = await this.organizationApiService.getBilling(this.organizationId);
|
||||||
this.sub = await this.organizationApiService.getSubscription(this.organizationId);
|
this.sub = await this.organizationApiService.getSubscription(this.organizationId);
|
||||||
this.taxInformation = await this.organizationApiService.getTaxInfo(this.organizationId);
|
this.taxInformation = await this.organizationApiService.getTaxInfo(this.organizationId);
|
||||||
|
|||||||
@@ -6,9 +6,14 @@ import { firstValueFrom, lastValueFrom, Observable, Subject } from "rxjs";
|
|||||||
|
|
||||||
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
||||||
import { OrganizationApiServiceAbstraction } from "@bitwarden/common/admin-console/abstractions/organization/organization-api.service.abstraction";
|
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 { OrganizationApiKeyType } from "@bitwarden/common/admin-console/enums";
|
import { OrganizationApiKeyType } from "@bitwarden/common/admin-console/enums";
|
||||||
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
|
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 { BillingApiServiceAbstraction } from "@bitwarden/common/billing/abstractions";
|
import { BillingApiServiceAbstraction } from "@bitwarden/common/billing/abstractions";
|
||||||
import { PlanType, ProductTierType } from "@bitwarden/common/billing/enums";
|
import { PlanType, ProductTierType } from "@bitwarden/common/billing/enums";
|
||||||
import { OrganizationSubscriptionResponse } from "@bitwarden/common/billing/models/response/organization-subscription.response";
|
import { OrganizationSubscriptionResponse } from "@bitwarden/common/billing/models/response/organization-subscription.response";
|
||||||
@@ -76,6 +81,7 @@ export class OrganizationSubscriptionCloudComponent implements OnInit, OnDestroy
|
|||||||
private i18nService: I18nService,
|
private i18nService: I18nService,
|
||||||
private logService: LogService,
|
private logService: LogService,
|
||||||
private organizationService: OrganizationService,
|
private organizationService: OrganizationService,
|
||||||
|
private accountService: AccountService,
|
||||||
private organizationApiService: OrganizationApiServiceAbstraction,
|
private organizationApiService: OrganizationApiServiceAbstraction,
|
||||||
private route: ActivatedRoute,
|
private route: ActivatedRoute,
|
||||||
private dialogService: DialogService,
|
private dialogService: DialogService,
|
||||||
@@ -117,7 +123,12 @@ export class OrganizationSubscriptionCloudComponent implements OnInit, OnDestroy
|
|||||||
async load() {
|
async load() {
|
||||||
this.loading = true;
|
this.loading = true;
|
||||||
this.locale = await firstValueFrom(this.i18nService.locale$);
|
this.locale = await firstValueFrom(this.i18nService.locale$);
|
||||||
this.userOrg = await this.organizationService.get(this.organizationId);
|
const userId = await firstValueFrom(getUserId(this.accountService.activeAccount$));
|
||||||
|
this.userOrg = await firstValueFrom(
|
||||||
|
this.organizationService
|
||||||
|
.organizations$(userId)
|
||||||
|
.pipe(getOrganizationById(this.organizationId)),
|
||||||
|
);
|
||||||
|
|
||||||
const isIndependentOrganizationOwner = !this.userOrg.hasProvider && this.userOrg.isOwner;
|
const isIndependentOrganizationOwner = !this.userOrg.hasProvider && this.userOrg.isOwner;
|
||||||
const isResoldOrganizationOwner = this.userOrg.hasReseller && this.userOrg.isOwner;
|
const isResoldOrganizationOwner = this.userOrg.hasReseller && this.userOrg.isOwner;
|
||||||
|
|||||||
@@ -7,10 +7,15 @@ import { concatMap, firstValueFrom, Subject, takeUntil } from "rxjs";
|
|||||||
|
|
||||||
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
||||||
import { OrganizationApiServiceAbstraction } from "@bitwarden/common/admin-console/abstractions/organization/organization-api.service.abstraction";
|
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 { OrganizationConnectionType } from "@bitwarden/common/admin-console/enums";
|
import { OrganizationConnectionType } from "@bitwarden/common/admin-console/enums";
|
||||||
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
|
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
|
||||||
import { OrganizationConnectionResponse } from "@bitwarden/common/admin-console/models/response/organization-connection.response";
|
import { OrganizationConnectionResponse } from "@bitwarden/common/admin-console/models/response/organization-connection.response";
|
||||||
|
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
||||||
|
import { getUserId } from "@bitwarden/common/auth/services/account.service";
|
||||||
import { ProductTierType } from "@bitwarden/common/billing/enums";
|
import { ProductTierType } from "@bitwarden/common/billing/enums";
|
||||||
import { BillingSyncConfigApi } from "@bitwarden/common/billing/models/api/billing-sync-config.api";
|
import { BillingSyncConfigApi } from "@bitwarden/common/billing/models/api/billing-sync-config.api";
|
||||||
import { SelfHostedOrganizationSubscriptionView } from "@bitwarden/common/billing/models/view/self-hosted-organization-subscription.view";
|
import { SelfHostedOrganizationSubscriptionView } from "@bitwarden/common/billing/models/view/self-hosted-organization-subscription.view";
|
||||||
@@ -80,6 +85,7 @@ export class OrganizationSubscriptionSelfhostComponent implements OnInit, OnDest
|
|||||||
private messagingService: MessagingService,
|
private messagingService: MessagingService,
|
||||||
private apiService: ApiService,
|
private apiService: ApiService,
|
||||||
private organizationService: OrganizationService,
|
private organizationService: OrganizationService,
|
||||||
|
private accountService: AccountService,
|
||||||
private route: ActivatedRoute,
|
private route: ActivatedRoute,
|
||||||
private organizationApiService: OrganizationApiServiceAbstraction,
|
private organizationApiService: OrganizationApiServiceAbstraction,
|
||||||
private platformUtilsService: PlatformUtilsService,
|
private platformUtilsService: PlatformUtilsService,
|
||||||
@@ -115,7 +121,12 @@ export class OrganizationSubscriptionSelfhostComponent implements OnInit, OnDest
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.loading = true;
|
this.loading = true;
|
||||||
this.userOrg = await this.organizationService.get(this.organizationId);
|
const userId = await firstValueFrom(getUserId(this.accountService.activeAccount$));
|
||||||
|
this.userOrg = await firstValueFrom(
|
||||||
|
this.organizationService
|
||||||
|
.organizations$(userId)
|
||||||
|
.pipe(getOrganizationById(this.organizationId)),
|
||||||
|
);
|
||||||
this.showAutomaticSyncAndManualUpload =
|
this.showAutomaticSyncAndManualUpload =
|
||||||
this.userOrg.productTierType == ProductTierType.Families ? false : true;
|
this.userOrg.productTierType == ProductTierType.Families ? false : true;
|
||||||
if (this.userOrg.canViewSubscription) {
|
if (this.userOrg.canViewSubscription) {
|
||||||
|
|||||||
@@ -4,11 +4,15 @@ import { Location } from "@angular/common";
|
|||||||
import { Component, OnDestroy } from "@angular/core";
|
import { Component, OnDestroy } from "@angular/core";
|
||||||
import { takeUntilDestroyed } from "@angular/core/rxjs-interop";
|
import { takeUntilDestroyed } from "@angular/core/rxjs-interop";
|
||||||
import { ActivatedRoute, Router } from "@angular/router";
|
import { ActivatedRoute, Router } from "@angular/router";
|
||||||
import { from, lastValueFrom, switchMap } from "rxjs";
|
import { firstValueFrom, from, lastValueFrom, map, switchMap } from "rxjs";
|
||||||
|
|
||||||
import { OrganizationApiServiceAbstraction } from "@bitwarden/common/admin-console/abstractions/organization/organization-api.service.abstraction";
|
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 { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
|
||||||
|
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
||||||
import { BillingApiServiceAbstraction } from "@bitwarden/common/billing/abstractions";
|
import { BillingApiServiceAbstraction } from "@bitwarden/common/billing/abstractions";
|
||||||
import { PaymentMethodType } from "@bitwarden/common/billing/enums";
|
import { PaymentMethodType } from "@bitwarden/common/billing/enums";
|
||||||
import { VerifyBankAccountRequest } from "@bitwarden/common/billing/models/request/verify-bank-account.request";
|
import { VerifyBankAccountRequest } from "@bitwarden/common/billing/models/request/verify-bank-account.request";
|
||||||
@@ -60,6 +64,7 @@ export class OrganizationPaymentMethodComponent implements OnDestroy {
|
|||||||
private location: Location,
|
private location: Location,
|
||||||
private trialFlowService: TrialFlowService,
|
private trialFlowService: TrialFlowService,
|
||||||
private organizationService: OrganizationService,
|
private organizationService: OrganizationService,
|
||||||
|
private accountService: AccountService,
|
||||||
protected syncService: SyncService,
|
protected syncService: SyncService,
|
||||||
) {
|
) {
|
||||||
this.activatedRoute.params
|
this.activatedRoute.params
|
||||||
@@ -120,7 +125,14 @@ export class OrganizationPaymentMethodComponent implements OnDestroy {
|
|||||||
const organizationSubscriptionPromise = this.organizationApiService.getSubscription(
|
const organizationSubscriptionPromise = this.organizationApiService.getSubscription(
|
||||||
this.organizationId,
|
this.organizationId,
|
||||||
);
|
);
|
||||||
const organizationPromise = this.organizationService.get(this.organizationId);
|
const userId = await firstValueFrom(
|
||||||
|
this.accountService.activeAccount$.pipe(map((a) => a?.id)),
|
||||||
|
);
|
||||||
|
const organizationPromise = await firstValueFrom(
|
||||||
|
this.organizationService
|
||||||
|
.organizations$(userId)
|
||||||
|
.pipe(getOrganizationById(this.organizationId)),
|
||||||
|
);
|
||||||
|
|
||||||
[this.organizationSubscriptionResponse, this.organization] = await Promise.all([
|
[this.organizationSubscriptionResponse, this.organization] = await Promise.all([
|
||||||
organizationSubscriptionPromise,
|
organizationSubscriptionPromise,
|
||||||
|
|||||||
@@ -2,11 +2,16 @@
|
|||||||
// @ts-strict-ignore
|
// @ts-strict-ignore
|
||||||
import { Component, EventEmitter, Input, OnDestroy, OnInit, Output } from "@angular/core";
|
import { Component, EventEmitter, Input, OnDestroy, OnInit, Output } from "@angular/core";
|
||||||
import { FormBuilder, Validators } from "@angular/forms";
|
import { FormBuilder, Validators } from "@angular/forms";
|
||||||
import { Subject, takeUntil } from "rxjs";
|
import { Subject, firstValueFrom, takeUntil } from "rxjs";
|
||||||
|
|
||||||
import { OrganizationApiServiceAbstraction } from "@bitwarden/common/admin-console/abstractions/organization/organization-api.service.abstraction";
|
import { OrganizationApiServiceAbstraction } from "@bitwarden/common/admin-console/abstractions/organization/organization-api.service.abstraction";
|
||||||
import { InternalOrganizationServiceAbstraction } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
import {
|
||||||
|
getOrganizationById,
|
||||||
|
InternalOrganizationServiceAbstraction,
|
||||||
|
} from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
||||||
import { OrganizationData } from "@bitwarden/common/admin-console/models/data/organization.data";
|
import { OrganizationData } from "@bitwarden/common/admin-console/models/data/organization.data";
|
||||||
|
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
||||||
|
import { getUserId } from "@bitwarden/common/auth/services/account.service";
|
||||||
import { OrganizationSmSubscriptionUpdateRequest } from "@bitwarden/common/billing/models/request/organization-sm-subscription-update.request";
|
import { OrganizationSmSubscriptionUpdateRequest } from "@bitwarden/common/billing/models/request/organization-sm-subscription-update.request";
|
||||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||||
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
||||||
@@ -107,6 +112,7 @@ export class SecretsManagerAdjustSubscriptionComponent implements OnInit, OnDest
|
|||||||
private platformUtilsService: PlatformUtilsService,
|
private platformUtilsService: PlatformUtilsService,
|
||||||
private toastService: ToastService,
|
private toastService: ToastService,
|
||||||
private internalOrganizationService: InternalOrganizationServiceAbstraction,
|
private internalOrganizationService: InternalOrganizationServiceAbstraction,
|
||||||
|
private accountService: AccountService,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
@@ -165,14 +171,19 @@ export class SecretsManagerAdjustSubscriptionComponent implements OnInit, OnDest
|
|||||||
request,
|
request,
|
||||||
);
|
);
|
||||||
|
|
||||||
const organization = await this.internalOrganizationService.get(this.organizationId);
|
const userId = await firstValueFrom(getUserId(this.accountService.activeAccount$));
|
||||||
|
const organization = await firstValueFrom(
|
||||||
|
this.internalOrganizationService
|
||||||
|
.organizations$(userId)
|
||||||
|
.pipe(getOrganizationById(this.organizationId)),
|
||||||
|
);
|
||||||
|
|
||||||
const organizationData = new OrganizationData(response, {
|
const organizationData = new OrganizationData(response, {
|
||||||
isMember: organization.isMember,
|
isMember: organization.isMember,
|
||||||
isProviderUser: organization.isProviderUser,
|
isProviderUser: organization.isProviderUser,
|
||||||
});
|
});
|
||||||
|
|
||||||
await this.internalOrganizationService.upsert(organizationData);
|
await this.internalOrganizationService.upsert(organizationData, userId);
|
||||||
|
|
||||||
this.toastService.showToast({
|
this.toastService.showToast({
|
||||||
variant: "success",
|
variant: "success",
|
||||||
|
|||||||
@@ -2,12 +2,15 @@
|
|||||||
// @ts-strict-ignore
|
// @ts-strict-ignore
|
||||||
import { Component, EventEmitter, Input, Output } from "@angular/core";
|
import { Component, EventEmitter, Input, Output } from "@angular/core";
|
||||||
import { FormBuilder } from "@angular/forms";
|
import { FormBuilder } from "@angular/forms";
|
||||||
|
import { firstValueFrom } from "rxjs";
|
||||||
|
|
||||||
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
||||||
import { OrganizationApiServiceAbstraction } from "@bitwarden/common/admin-console/abstractions/organization/organization-api.service.abstraction";
|
import { OrganizationApiServiceAbstraction } from "@bitwarden/common/admin-console/abstractions/organization/organization-api.service.abstraction";
|
||||||
import { InternalOrganizationServiceAbstraction } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
import { InternalOrganizationServiceAbstraction } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
||||||
import { OrganizationData } from "@bitwarden/common/admin-console/models/data/organization.data";
|
import { OrganizationData } from "@bitwarden/common/admin-console/models/data/organization.data";
|
||||||
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
|
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 { SecretsManagerSubscribeRequest } from "@bitwarden/common/billing/models/request/sm-subscribe.request";
|
import { SecretsManagerSubscribeRequest } from "@bitwarden/common/billing/models/request/sm-subscribe.request";
|
||||||
import { BillingCustomerDiscount } from "@bitwarden/common/billing/models/response/organization-subscription.response";
|
import { BillingCustomerDiscount } from "@bitwarden/common/billing/models/response/organization-subscription.response";
|
||||||
import { PlanResponse } from "@bitwarden/common/billing/models/response/plan.response";
|
import { PlanResponse } from "@bitwarden/common/billing/models/response/plan.response";
|
||||||
@@ -37,6 +40,7 @@ export class SecretsManagerSubscribeStandaloneComponent {
|
|||||||
private organizationApiService: OrganizationApiServiceAbstraction,
|
private organizationApiService: OrganizationApiServiceAbstraction,
|
||||||
private organizationService: InternalOrganizationServiceAbstraction,
|
private organizationService: InternalOrganizationServiceAbstraction,
|
||||||
private toastService: ToastService,
|
private toastService: ToastService,
|
||||||
|
private accountService: AccountService,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
submit = async () => {
|
submit = async () => {
|
||||||
@@ -56,7 +60,8 @@ export class SecretsManagerSubscribeStandaloneComponent {
|
|||||||
isMember: this.organization.isMember,
|
isMember: this.organization.isMember,
|
||||||
isProviderUser: this.organization.isProviderUser,
|
isProviderUser: this.organization.isProviderUser,
|
||||||
});
|
});
|
||||||
await this.organizationService.upsert(organizationData);
|
const userId = await firstValueFrom(getUserId(this.accountService.activeAccount$));
|
||||||
|
await this.organizationService.upsert(organizationData, userId);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Because subscribing to Secrets Manager automatically provides access to Secrets Manager for the
|
Because subscribing to Secrets Manager automatically provides access to Secrets Manager for the
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import { OrganizationService } from "@bitwarden/common/admin-console/abstraction
|
|||||||
import { PolicyService } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction";
|
import { PolicyService } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction";
|
||||||
import { PolicyType } from "@bitwarden/common/admin-console/enums";
|
import { PolicyType } from "@bitwarden/common/admin-console/enums";
|
||||||
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
|
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
|
||||||
|
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
||||||
import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum";
|
import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum";
|
||||||
import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
|
import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
|
||||||
|
|
||||||
@@ -25,15 +26,34 @@ export class FreeFamiliesPolicyService {
|
|||||||
constructor(
|
constructor(
|
||||||
private policyService: PolicyService,
|
private policyService: PolicyService,
|
||||||
private organizationService: OrganizationService,
|
private organizationService: OrganizationService,
|
||||||
|
private accountService: AccountService,
|
||||||
private configService: ConfigService,
|
private configService: ConfigService,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
|
canManageSponsorships$ = this.accountService.activeAccount$.pipe(
|
||||||
|
switchMap((account) => {
|
||||||
|
if (account?.id) {
|
||||||
|
return this.organizationService.canManageSponsorships$(account?.id);
|
||||||
|
} else {
|
||||||
|
return of();
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
organizations$ = this.accountService.activeAccount$.pipe(
|
||||||
|
switchMap((account) => {
|
||||||
|
if (account?.id) {
|
||||||
|
return this.organizationService.organizations$(account?.id);
|
||||||
|
} else {
|
||||||
|
return of();
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
get showFreeFamilies$(): Observable<boolean> {
|
get showFreeFamilies$(): Observable<boolean> {
|
||||||
return this.isFreeFamilyFlagEnabled$.pipe(
|
return this.isFreeFamilyFlagEnabled$.pipe(
|
||||||
switchMap((isFreeFamilyFlagEnabled) =>
|
switchMap((isFreeFamilyFlagEnabled) =>
|
||||||
isFreeFamilyFlagEnabled
|
isFreeFamilyFlagEnabled ? this.getFreeFamiliesVisibility$() : this.canManageSponsorships$,
|
||||||
? this.getFreeFamiliesVisibility$()
|
|
||||||
: this.organizationService.canManageSponsorships$,
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -41,7 +61,7 @@ export class FreeFamiliesPolicyService {
|
|||||||
private getFreeFamiliesVisibility$(): Observable<boolean> {
|
private getFreeFamiliesVisibility$(): Observable<boolean> {
|
||||||
return combineLatest([
|
return combineLatest([
|
||||||
this.checkEnterpriseOrganizationsAndFetchPolicy(),
|
this.checkEnterpriseOrganizationsAndFetchPolicy(),
|
||||||
this.organizationService.canManageSponsorships$,
|
this.canManageSponsorships$,
|
||||||
]).pipe(
|
]).pipe(
|
||||||
map(([orgStatus, canManageSponsorships]) =>
|
map(([orgStatus, canManageSponsorships]) =>
|
||||||
this.shouldShowFreeFamilyLink(orgStatus, canManageSponsorships),
|
this.shouldShowFreeFamilyLink(orgStatus, canManageSponsorships),
|
||||||
@@ -61,7 +81,7 @@ export class FreeFamiliesPolicyService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
checkEnterpriseOrganizationsAndFetchPolicy(): Observable<EnterpriseOrgStatus> {
|
checkEnterpriseOrganizationsAndFetchPolicy(): Observable<EnterpriseOrgStatus> {
|
||||||
return this.organizationService.organizations$.pipe(
|
return this.organizations$.pipe(
|
||||||
filter((organizations) => Array.isArray(organizations) && organizations.length > 0),
|
filter((organizations) => Array.isArray(organizations) && organizations.length > 0),
|
||||||
switchMap((organizations) => this.fetchEnterpriseOrganizationPolicy(organizations)),
|
switchMap((organizations) => this.fetchEnterpriseOrganizationPolicy(organizations)),
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ import { PolicyService } from "@bitwarden/common/admin-console/abstractions/poli
|
|||||||
import { PolicyType } from "@bitwarden/common/admin-console/enums";
|
import { PolicyType } from "@bitwarden/common/admin-console/enums";
|
||||||
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
|
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
|
||||||
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
||||||
|
import { getUserId } from "@bitwarden/common/auth/services/account.service";
|
||||||
import { PlanSponsorshipType } from "@bitwarden/common/billing/enums";
|
import { PlanSponsorshipType } from "@bitwarden/common/billing/enums";
|
||||||
import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum";
|
import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum";
|
||||||
import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
|
import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
|
||||||
@@ -90,11 +91,13 @@ export class SponsoredFamiliesComponent implements OnInit, OnDestroy {
|
|||||||
FeatureFlag.DisableFreeFamiliesSponsorship,
|
FeatureFlag.DisableFreeFamiliesSponsorship,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const userId = await firstValueFrom(getUserId(this.accountService.activeAccount$));
|
||||||
|
|
||||||
if (this.isFreeFamilyFlagEnabled) {
|
if (this.isFreeFamilyFlagEnabled) {
|
||||||
await this.preventAccessToFreeFamiliesPage();
|
await this.preventAccessToFreeFamiliesPage();
|
||||||
|
|
||||||
this.availableSponsorshipOrgs$ = combineLatest([
|
this.availableSponsorshipOrgs$ = combineLatest([
|
||||||
this.organizationService.organizations$,
|
this.organizationService.organizations$(userId),
|
||||||
this.policyService.getAll$(PolicyType.FreeFamiliesSponsorshipPolicy),
|
this.policyService.getAll$(PolicyType.FreeFamiliesSponsorshipPolicy),
|
||||||
]).pipe(
|
]).pipe(
|
||||||
map(([organizations, policies]) =>
|
map(([organizations, policies]) =>
|
||||||
@@ -111,9 +114,9 @@ export class SponsoredFamiliesComponent implements OnInit, OnDestroy {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
this.availableSponsorshipOrgs$ = this.organizationService.organizations$.pipe(
|
this.availableSponsorshipOrgs$ = this.organizationService
|
||||||
map((orgs) => orgs.filter((o) => o.familySponsorshipAvailable)),
|
.organizations$(userId)
|
||||||
);
|
.pipe(map((orgs) => orgs.filter((o) => o.familySponsorshipAvailable)));
|
||||||
}
|
}
|
||||||
|
|
||||||
this.availableSponsorshipOrgs$.pipe(takeUntil(this._destroy)).subscribe((orgs) => {
|
this.availableSponsorshipOrgs$.pipe(takeUntil(this._destroy)).subscribe((orgs) => {
|
||||||
@@ -126,9 +129,9 @@ export class SponsoredFamiliesComponent implements OnInit, OnDestroy {
|
|||||||
|
|
||||||
this.anyOrgsAvailable$ = this.availableSponsorshipOrgs$.pipe(map((orgs) => orgs.length > 0));
|
this.anyOrgsAvailable$ = this.availableSponsorshipOrgs$.pipe(map((orgs) => orgs.length > 0));
|
||||||
|
|
||||||
this.activeSponsorshipOrgs$ = this.organizationService.organizations$.pipe(
|
this.activeSponsorshipOrgs$ = this.organizationService
|
||||||
map((orgs) => orgs.filter((o) => o.familySponsorshipFriendlyName !== null)),
|
.organizations$(userId)
|
||||||
);
|
.pipe(map((orgs) => orgs.filter((o) => o.familySponsorshipFriendlyName !== null)));
|
||||||
|
|
||||||
this.anyActiveSponsorships$ = this.activeSponsorshipOrgs$.pipe(map((orgs) => orgs.length > 0));
|
this.anyActiveSponsorships$ = this.activeSponsorshipOrgs$.pipe(map((orgs) => orgs.length > 0));
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,10 @@ import { FormControl, FormGroup, Validators } from "@angular/forms";
|
|||||||
import { firstValueFrom, map } from "rxjs";
|
import { firstValueFrom, map } from "rxjs";
|
||||||
|
|
||||||
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
||||||
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 { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
||||||
import { PaymentMethodType } from "@bitwarden/common/billing/enums";
|
import { PaymentMethodType } from "@bitwarden/common/billing/enums";
|
||||||
import { BitPayInvoiceRequest } from "@bitwarden/common/billing/models/request/bit-pay-invoice.request";
|
import { BitPayInvoiceRequest } from "@bitwarden/common/billing/models/request/bit-pay-invoice.request";
|
||||||
@@ -77,7 +80,14 @@ export class AddCreditDialogComponent implements OnInit {
|
|||||||
this.creditAmount = "20.00";
|
this.creditAmount = "20.00";
|
||||||
}
|
}
|
||||||
this.ppButtonCustomField = "organization_id:" + this.organizationId;
|
this.ppButtonCustomField = "organization_id:" + this.organizationId;
|
||||||
const org = await this.organizationService.get(this.organizationId);
|
const userId = await firstValueFrom(
|
||||||
|
this.accountService.activeAccount$.pipe(map((a) => a?.id)),
|
||||||
|
);
|
||||||
|
const org = await firstValueFrom(
|
||||||
|
this.organizationService
|
||||||
|
.organizations$(userId)
|
||||||
|
.pipe(getOrganizationById(this.organizationId)),
|
||||||
|
);
|
||||||
if (org != null) {
|
if (org != null) {
|
||||||
this.subject = org.name;
|
this.subject = org.name;
|
||||||
this.name = org.name;
|
this.name = org.name;
|
||||||
|
|||||||
@@ -4,12 +4,16 @@ import { Location } from "@angular/common";
|
|||||||
import { Component, OnDestroy, OnInit } from "@angular/core";
|
import { Component, OnDestroy, OnInit } from "@angular/core";
|
||||||
import { FormBuilder, FormControl, Validators } from "@angular/forms";
|
import { FormBuilder, FormControl, Validators } from "@angular/forms";
|
||||||
import { ActivatedRoute, Router } from "@angular/router";
|
import { ActivatedRoute, Router } from "@angular/router";
|
||||||
import { lastValueFrom } from "rxjs";
|
import { firstValueFrom, lastValueFrom, map } from "rxjs";
|
||||||
|
|
||||||
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
||||||
import { OrganizationApiServiceAbstraction } from "@bitwarden/common/admin-console/abstractions/organization/organization-api.service.abstraction";
|
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 { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
|
||||||
|
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
||||||
import { PaymentMethodType } from "@bitwarden/common/billing/enums";
|
import { PaymentMethodType } from "@bitwarden/common/billing/enums";
|
||||||
import { BillingPaymentResponse } from "@bitwarden/common/billing/models/response/billing-payment.response";
|
import { BillingPaymentResponse } from "@bitwarden/common/billing/models/response/billing-payment.response";
|
||||||
import { OrganizationSubscriptionResponse } from "@bitwarden/common/billing/models/response/organization-subscription.response";
|
import { OrganizationSubscriptionResponse } from "@bitwarden/common/billing/models/response/organization-subscription.response";
|
||||||
@@ -73,6 +77,7 @@ export class PaymentMethodComponent implements OnInit, OnDestroy {
|
|||||||
private toastService: ToastService,
|
private toastService: ToastService,
|
||||||
private trialFlowService: TrialFlowService,
|
private trialFlowService: TrialFlowService,
|
||||||
private organizationService: OrganizationService,
|
private organizationService: OrganizationService,
|
||||||
|
private accountService: AccountService,
|
||||||
protected syncService: SyncService,
|
protected syncService: SyncService,
|
||||||
) {
|
) {
|
||||||
const state = this.router.getCurrentNavigation()?.extras?.state;
|
const state = this.router.getCurrentNavigation()?.extras?.state;
|
||||||
@@ -117,7 +122,14 @@ export class PaymentMethodComponent implements OnInit, OnDestroy {
|
|||||||
const organizationSubscriptionPromise = this.organizationApiService.getSubscription(
|
const organizationSubscriptionPromise = this.organizationApiService.getSubscription(
|
||||||
this.organizationId,
|
this.organizationId,
|
||||||
);
|
);
|
||||||
const organizationPromise = this.organizationService.get(this.organizationId);
|
const userId = await firstValueFrom(
|
||||||
|
this.accountService.activeAccount$.pipe(map((a) => a?.id)),
|
||||||
|
);
|
||||||
|
const organizationPromise = await firstValueFrom(
|
||||||
|
this.organizationService
|
||||||
|
.organizations$(userId)
|
||||||
|
.pipe(getOrganizationById(this.organizationId)),
|
||||||
|
);
|
||||||
|
|
||||||
[this.billing, this.org, this.organization] = await Promise.all([
|
[this.billing, this.org, this.organization] = await Promise.all([
|
||||||
billingPromise,
|
billingPromise,
|
||||||
|
|||||||
@@ -3,11 +3,12 @@
|
|||||||
import { CommonModule } from "@angular/common";
|
import { CommonModule } from "@angular/common";
|
||||||
import { Component, EventEmitter, Input, Output } from "@angular/core";
|
import { Component, EventEmitter, Input, Output } from "@angular/core";
|
||||||
import { ActivatedRoute } from "@angular/router";
|
import { ActivatedRoute } from "@angular/router";
|
||||||
import { combineLatest, map, Observable } from "rxjs";
|
import { combineLatest, map, Observable, switchMap } from "rxjs";
|
||||||
|
|
||||||
import { JslibModule } from "@bitwarden/angular/jslib.module";
|
import { JslibModule } from "@bitwarden/angular/jslib.module";
|
||||||
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
||||||
import type { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
|
import type { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
|
||||||
|
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
||||||
import { BillingApiServiceAbstraction } from "@bitwarden/common/billing/abstractions/billing-api.service.abstraction";
|
import { BillingApiServiceAbstraction } from "@bitwarden/common/billing/abstractions/billing-api.service.abstraction";
|
||||||
import { DialogService, NavigationModule } from "@bitwarden/components";
|
import { DialogService, NavigationModule } from "@bitwarden/components";
|
||||||
|
|
||||||
@@ -20,12 +21,17 @@ import { TrialFlowService } from "./../../billing/services/trial-flow.service";
|
|||||||
imports: [CommonModule, JslibModule, NavigationModule],
|
imports: [CommonModule, JslibModule, NavigationModule],
|
||||||
})
|
})
|
||||||
export class OrgSwitcherComponent {
|
export class OrgSwitcherComponent {
|
||||||
protected organizations$: Observable<Organization[]> =
|
protected organizations$: Observable<Organization[]> = this.accountService.activeAccount$.pipe(
|
||||||
this.organizationService.organizations$.pipe(
|
switchMap((account) =>
|
||||||
map((orgs) =>
|
this.organizationService
|
||||||
orgs.filter((org) => this.filter(org)).sort((a, b) => a.name.localeCompare(b.name)),
|
.organizations$(account?.id)
|
||||||
),
|
.pipe(
|
||||||
);
|
map((orgs) =>
|
||||||
|
orgs.filter((org) => this.filter(org)).sort((a, b) => a.name.localeCompare(b.name)),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
protected activeOrganization$: Observable<Organization> = combineLatest([
|
protected activeOrganization$: Observable<Organization> = combineLatest([
|
||||||
this.route.paramMap,
|
this.route.paramMap,
|
||||||
@@ -61,6 +67,7 @@ export class OrgSwitcherComponent {
|
|||||||
private organizationService: OrganizationService,
|
private organizationService: OrganizationService,
|
||||||
private trialFlowService: TrialFlowService,
|
private trialFlowService: TrialFlowService,
|
||||||
protected billingApiService: BillingApiServiceAbstraction,
|
protected billingApiService: BillingApiServiceAbstraction,
|
||||||
|
private accountService: AccountService,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
protected toggle(event?: MouseEvent) {
|
protected toggle(event?: MouseEvent) {
|
||||||
|
|||||||
@@ -1,15 +1,17 @@
|
|||||||
import { Component, Directive, importProvidersFrom, Input } from "@angular/core";
|
import { Component, Directive, importProvidersFrom, Input } from "@angular/core";
|
||||||
import { RouterModule } from "@angular/router";
|
import { RouterModule } from "@angular/router";
|
||||||
import { applicationConfig, Meta, moduleMetadata, StoryObj } from "@storybook/angular";
|
import { applicationConfig, Meta, moduleMetadata, StoryObj } from "@storybook/angular";
|
||||||
import { BehaviorSubject, firstValueFrom } from "rxjs";
|
import { BehaviorSubject, firstValueFrom, Observable, of } from "rxjs";
|
||||||
|
|
||||||
import { I18nPipe } from "@bitwarden/angular/platform/pipes/i18n.pipe";
|
import { I18nPipe } from "@bitwarden/angular/platform/pipes/i18n.pipe";
|
||||||
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
||||||
import { ProviderService } from "@bitwarden/common/admin-console/abstractions/provider.service";
|
import { ProviderService } from "@bitwarden/common/admin-console/abstractions/provider.service";
|
||||||
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
|
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
|
||||||
import { Provider } from "@bitwarden/common/admin-console/models/domain/provider";
|
import { Provider } from "@bitwarden/common/admin-console/models/domain/provider";
|
||||||
|
import { AccountService, Account } from "@bitwarden/common/auth/abstractions/account.service";
|
||||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||||
import { SyncService } from "@bitwarden/common/platform/sync";
|
import { SyncService } from "@bitwarden/common/platform/sync";
|
||||||
|
import { UserId } from "@bitwarden/common/types/guid";
|
||||||
import { LayoutComponent, NavigationModule } from "@bitwarden/components";
|
import { LayoutComponent, NavigationModule } from "@bitwarden/components";
|
||||||
import { I18nMockService } from "@bitwarden/components/src/utils/i18n-mock.service";
|
import { I18nMockService } from "@bitwarden/components/src/utils/i18n-mock.service";
|
||||||
|
|
||||||
@@ -22,11 +24,14 @@ import { NavigationProductSwitcherComponent } from "./navigation-switcher.compon
|
|||||||
})
|
})
|
||||||
class MockOrganizationService implements Partial<OrganizationService> {
|
class MockOrganizationService implements Partial<OrganizationService> {
|
||||||
private static _orgs = new BehaviorSubject<Organization[]>([]);
|
private static _orgs = new BehaviorSubject<Organization[]>([]);
|
||||||
organizations$ = MockOrganizationService._orgs; // eslint-disable-line rxjs/no-exposed-subjects
|
|
||||||
|
organizations$(): Observable<Organization[]> {
|
||||||
|
return MockOrganizationService._orgs.asObservable();
|
||||||
|
}
|
||||||
|
|
||||||
@Input()
|
@Input()
|
||||||
set mockOrgs(orgs: Organization[]) {
|
set mockOrgs(orgs: Organization[]) {
|
||||||
this.organizations$.next(orgs);
|
MockOrganizationService._orgs.next(orgs);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -52,6 +57,15 @@ class MockSyncService implements Partial<SyncService> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class MockAccountService implements Partial<AccountService> {
|
||||||
|
activeAccount$?: Observable<Account> = of({
|
||||||
|
id: "test-user-id" as UserId,
|
||||||
|
name: "Test User 1",
|
||||||
|
email: "test@email.com",
|
||||||
|
emailVerified: true,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: "story-layout",
|
selector: "story-layout",
|
||||||
template: `<ng-content></ng-content>`,
|
template: `<ng-content></ng-content>`,
|
||||||
@@ -86,6 +100,7 @@ export default {
|
|||||||
imports: [NavigationModule, RouterModule, LayoutComponent],
|
imports: [NavigationModule, RouterModule, LayoutComponent],
|
||||||
providers: [
|
providers: [
|
||||||
{ provide: OrganizationService, useClass: MockOrganizationService },
|
{ provide: OrganizationService, useClass: MockOrganizationService },
|
||||||
|
{ provide: AccountService, useClass: MockAccountService },
|
||||||
{ provide: ProviderService, useClass: MockProviderService },
|
{ provide: ProviderService, useClass: MockProviderService },
|
||||||
{ provide: SyncService, useClass: MockSyncService },
|
{ provide: SyncService, useClass: MockSyncService },
|
||||||
ProductSwitcherService,
|
ProductSwitcherService,
|
||||||
|
|||||||
@@ -1,15 +1,17 @@
|
|||||||
import { Component, Directive, importProvidersFrom, Input } from "@angular/core";
|
import { Component, Directive, importProvidersFrom, Input } from "@angular/core";
|
||||||
import { RouterModule } from "@angular/router";
|
import { RouterModule } from "@angular/router";
|
||||||
import { applicationConfig, Meta, moduleMetadata, StoryObj } from "@storybook/angular";
|
import { applicationConfig, Meta, moduleMetadata, StoryObj } from "@storybook/angular";
|
||||||
import { BehaviorSubject, firstValueFrom } from "rxjs";
|
import { BehaviorSubject, firstValueFrom, Observable, of } from "rxjs";
|
||||||
|
|
||||||
import { JslibModule } from "@bitwarden/angular/jslib.module";
|
import { JslibModule } from "@bitwarden/angular/jslib.module";
|
||||||
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
||||||
import { ProviderService } from "@bitwarden/common/admin-console/abstractions/provider.service";
|
import { ProviderService } from "@bitwarden/common/admin-console/abstractions/provider.service";
|
||||||
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
|
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
|
||||||
import { Provider } from "@bitwarden/common/admin-console/models/domain/provider";
|
import { Provider } from "@bitwarden/common/admin-console/models/domain/provider";
|
||||||
|
import { AccountService, Account } from "@bitwarden/common/auth/abstractions/account.service";
|
||||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||||
import { SyncService } from "@bitwarden/common/platform/sync";
|
import { SyncService } from "@bitwarden/common/platform/sync";
|
||||||
|
import { UserId } from "@bitwarden/common/types/guid";
|
||||||
import { IconButtonModule, LinkModule, MenuModule } from "@bitwarden/components";
|
import { IconButtonModule, LinkModule, MenuModule } from "@bitwarden/components";
|
||||||
import { I18nMockService } from "@bitwarden/components/src/utils/i18n-mock.service";
|
import { I18nMockService } from "@bitwarden/components/src/utils/i18n-mock.service";
|
||||||
|
|
||||||
@@ -22,11 +24,14 @@ import { ProductSwitcherService } from "./shared/product-switcher.service";
|
|||||||
})
|
})
|
||||||
class MockOrganizationService implements Partial<OrganizationService> {
|
class MockOrganizationService implements Partial<OrganizationService> {
|
||||||
private static _orgs = new BehaviorSubject<Organization[]>([]);
|
private static _orgs = new BehaviorSubject<Organization[]>([]);
|
||||||
organizations$ = MockOrganizationService._orgs; // eslint-disable-line rxjs/no-exposed-subjects
|
|
||||||
|
organizations$(): Observable<Organization[]> {
|
||||||
|
return MockOrganizationService._orgs.asObservable();
|
||||||
|
}
|
||||||
|
|
||||||
@Input()
|
@Input()
|
||||||
set mockOrgs(orgs: Organization[]) {
|
set mockOrgs(orgs: Organization[]) {
|
||||||
this.organizations$.next(orgs);
|
MockOrganizationService._orgs.next(orgs);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -52,6 +57,15 @@ class MockSyncService implements Partial<SyncService> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class MockAccountService implements Partial<AccountService> {
|
||||||
|
activeAccount$?: Observable<Account> = of({
|
||||||
|
id: "test-user-id" as UserId,
|
||||||
|
name: "Test User 1",
|
||||||
|
email: "test@email.com",
|
||||||
|
emailVerified: true,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: "story-layout",
|
selector: "story-layout",
|
||||||
template: `<ng-content></ng-content>`,
|
template: `<ng-content></ng-content>`,
|
||||||
@@ -78,6 +92,8 @@ export default {
|
|||||||
],
|
],
|
||||||
imports: [JslibModule, MenuModule, IconButtonModule, LinkModule, RouterModule],
|
imports: [JslibModule, MenuModule, IconButtonModule, LinkModule, RouterModule],
|
||||||
providers: [
|
providers: [
|
||||||
|
{ provide: AccountService, useClass: MockAccountService },
|
||||||
|
MockAccountService,
|
||||||
{ provide: OrganizationService, useClass: MockOrganizationService },
|
{ provide: OrganizationService, useClass: MockOrganizationService },
|
||||||
MockOrganizationService,
|
MockOrganizationService,
|
||||||
{ provide: ProviderService, useClass: MockProviderService },
|
{ provide: ProviderService, useClass: MockProviderService },
|
||||||
@@ -134,7 +150,9 @@ export default {
|
|||||||
],
|
],
|
||||||
} as Meta<ProductSwitcherComponent>;
|
} as Meta<ProductSwitcherComponent>;
|
||||||
|
|
||||||
type Story = StoryObj<ProductSwitcherComponent & MockProviderService & MockOrganizationService>;
|
type Story = StoryObj<
|
||||||
|
ProductSwitcherComponent & MockProviderService & MockOrganizationService & MockAccountService
|
||||||
|
>;
|
||||||
|
|
||||||
const Template: Story = {
|
const Template: Story = {
|
||||||
render: (args) => ({
|
render: (args) => ({
|
||||||
|
|||||||
@@ -10,7 +10,11 @@ import { OrganizationService } from "@bitwarden/common/admin-console/abstraction
|
|||||||
import { ProviderService } from "@bitwarden/common/admin-console/abstractions/provider.service";
|
import { ProviderService } from "@bitwarden/common/admin-console/abstractions/provider.service";
|
||||||
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
|
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
|
||||||
import { Provider } from "@bitwarden/common/admin-console/models/domain/provider";
|
import { Provider } from "@bitwarden/common/admin-console/models/domain/provider";
|
||||||
|
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
||||||
|
import { Utils } from "@bitwarden/common/platform/misc/utils";
|
||||||
import { SyncService } from "@bitwarden/common/platform/sync";
|
import { SyncService } from "@bitwarden/common/platform/sync";
|
||||||
|
import { FakeAccountService, mockAccountServiceWith } from "@bitwarden/common/spec";
|
||||||
|
import { UserId } from "@bitwarden/common/types/guid";
|
||||||
|
|
||||||
import { ProductSwitcherService } from "./product-switcher.service";
|
import { ProductSwitcherService } from "./product-switcher.service";
|
||||||
|
|
||||||
@@ -19,8 +23,10 @@ describe("ProductSwitcherService", () => {
|
|||||||
let router: { url: string; events: Observable<unknown> };
|
let router: { url: string; events: Observable<unknown> };
|
||||||
let organizationService: MockProxy<OrganizationService>;
|
let organizationService: MockProxy<OrganizationService>;
|
||||||
let providerService: MockProxy<ProviderService>;
|
let providerService: MockProxy<ProviderService>;
|
||||||
|
let accountService: FakeAccountService;
|
||||||
let activeRouteParams = convertToParamMap({ organizationId: "1234" });
|
let activeRouteParams = convertToParamMap({ organizationId: "1234" });
|
||||||
const getLastSync = jest.fn().mockResolvedValue(new Date("2024-05-14"));
|
const getLastSync = jest.fn().mockResolvedValue(new Date("2024-05-14"));
|
||||||
|
const userId = Utils.newGuid() as UserId;
|
||||||
|
|
||||||
// The service is dependent on the SyncService, which is behind a `setTimeout`
|
// The service is dependent on the SyncService, which is behind a `setTimeout`
|
||||||
// Most of the tests don't need to test this aspect so `advanceTimersByTime`
|
// Most of the tests don't need to test this aspect so `advanceTimersByTime`
|
||||||
@@ -36,10 +42,11 @@ describe("ProductSwitcherService", () => {
|
|||||||
router = mock<Router>();
|
router = mock<Router>();
|
||||||
organizationService = mock<OrganizationService>();
|
organizationService = mock<OrganizationService>();
|
||||||
providerService = mock<ProviderService>();
|
providerService = mock<ProviderService>();
|
||||||
|
accountService = mockAccountServiceWith(userId);
|
||||||
|
|
||||||
router.url = "/";
|
router.url = "/";
|
||||||
router.events = of({});
|
router.events = of({});
|
||||||
organizationService.organizations$ = of([{}] as Organization[]);
|
organizationService.organizations$.mockReturnValue(of([{}] as Organization[]));
|
||||||
providerService.getAll.mockResolvedValue([] as Provider[]);
|
providerService.getAll.mockResolvedValue([] as Provider[]);
|
||||||
|
|
||||||
TestBed.configureTestingModule({
|
TestBed.configureTestingModule({
|
||||||
@@ -47,6 +54,7 @@ describe("ProductSwitcherService", () => {
|
|||||||
{ provide: Router, useValue: router },
|
{ provide: Router, useValue: router },
|
||||||
{ provide: OrganizationService, useValue: organizationService },
|
{ provide: OrganizationService, useValue: organizationService },
|
||||||
{ provide: ProviderService, useValue: providerService },
|
{ provide: ProviderService, useValue: providerService },
|
||||||
|
{ provide: AccountService, useValue: accountService },
|
||||||
{
|
{
|
||||||
provide: ActivatedRoute,
|
provide: ActivatedRoute,
|
||||||
useValue: {
|
useValue: {
|
||||||
@@ -111,13 +119,15 @@ describe("ProductSwitcherService", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("is included in bento when there is an organization with SM", async () => {
|
it("is included in bento when there is an organization with SM", async () => {
|
||||||
organizationService.organizations$ = of([
|
organizationService.organizations$.mockReturnValue(
|
||||||
{
|
of([
|
||||||
id: "1234",
|
{
|
||||||
canAccessSecretsManager: true,
|
id: "1234",
|
||||||
enabled: true,
|
canAccessSecretsManager: true,
|
||||||
},
|
enabled: true,
|
||||||
] as Organization[]);
|
},
|
||||||
|
] as Organization[]),
|
||||||
|
);
|
||||||
|
|
||||||
initiateService();
|
initiateService();
|
||||||
|
|
||||||
@@ -138,7 +148,9 @@ describe("ProductSwitcherService", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("includes Admin Console in bento when a user has access to it", async () => {
|
it("includes Admin Console in bento when a user has access to it", async () => {
|
||||||
organizationService.organizations$ = of([{ id: "1234", isOwner: true }] as Organization[]);
|
organizationService.organizations$.mockReturnValue(
|
||||||
|
of([{ id: "1234", isOwner: true }] as Organization[]),
|
||||||
|
);
|
||||||
|
|
||||||
initiateService();
|
initiateService();
|
||||||
|
|
||||||
@@ -194,7 +206,9 @@ describe("ProductSwitcherService", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("marks Admin Console as active", async () => {
|
it("marks Admin Console as active", async () => {
|
||||||
organizationService.organizations$ = of([{ id: "1234", isOwner: true }] as Organization[]);
|
organizationService.organizations$.mockReturnValue(
|
||||||
|
of([{ id: "1234", isOwner: true }] as Organization[]),
|
||||||
|
);
|
||||||
activeRouteParams = convertToParamMap({ organizationId: "1" });
|
activeRouteParams = convertToParamMap({ organizationId: "1" });
|
||||||
router.url = "/organizations/";
|
router.url = "/organizations/";
|
||||||
|
|
||||||
@@ -225,20 +239,22 @@ describe("ProductSwitcherService", () => {
|
|||||||
it("updates secrets manager path when the org id is found in the path", async () => {
|
it("updates secrets manager path when the org id is found in the path", async () => {
|
||||||
router.url = "/sm/4243";
|
router.url = "/sm/4243";
|
||||||
|
|
||||||
organizationService.organizations$ = of([
|
organizationService.organizations$.mockReturnValue(
|
||||||
{
|
of([
|
||||||
id: "23443234",
|
{
|
||||||
canAccessSecretsManager: true,
|
id: "23443234",
|
||||||
enabled: true,
|
canAccessSecretsManager: true,
|
||||||
name: "Org 2",
|
enabled: true,
|
||||||
},
|
name: "Org 2",
|
||||||
{
|
},
|
||||||
id: "4243",
|
{
|
||||||
canAccessSecretsManager: true,
|
id: "4243",
|
||||||
enabled: true,
|
canAccessSecretsManager: true,
|
||||||
name: "Org 32",
|
enabled: true,
|
||||||
},
|
name: "Org 32",
|
||||||
] as Organization[]);
|
},
|
||||||
|
] as Organization[]),
|
||||||
|
);
|
||||||
|
|
||||||
initiateService();
|
initiateService();
|
||||||
|
|
||||||
@@ -253,10 +269,12 @@ describe("ProductSwitcherService", () => {
|
|||||||
it("updates admin console path when the org id is found in the path", async () => {
|
it("updates admin console path when the org id is found in the path", async () => {
|
||||||
router.url = "/organizations/111-22-33";
|
router.url = "/organizations/111-22-33";
|
||||||
|
|
||||||
organizationService.organizations$ = of([
|
organizationService.organizations$.mockReturnValue(
|
||||||
{ id: "111-22-33", isOwner: true, name: "Test Org" },
|
of([
|
||||||
{ id: "4243", isOwner: true, name: "My Org" },
|
{ id: "111-22-33", isOwner: true, name: "Test Org" },
|
||||||
] as Organization[]);
|
{ id: "4243", isOwner: true, name: "My Org" },
|
||||||
|
] as Organization[]),
|
||||||
|
);
|
||||||
|
|
||||||
initiateService();
|
initiateService();
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,16 @@
|
|||||||
// @ts-strict-ignore
|
// @ts-strict-ignore
|
||||||
import { Injectable } from "@angular/core";
|
import { Injectable } from "@angular/core";
|
||||||
import { ActivatedRoute, NavigationEnd, NavigationStart, ParamMap, Router } from "@angular/router";
|
import { ActivatedRoute, NavigationEnd, NavigationStart, ParamMap, Router } from "@angular/router";
|
||||||
import { combineLatest, concatMap, filter, map, Observable, ReplaySubject, startWith } from "rxjs";
|
import {
|
||||||
|
combineLatest,
|
||||||
|
concatMap,
|
||||||
|
filter,
|
||||||
|
map,
|
||||||
|
Observable,
|
||||||
|
ReplaySubject,
|
||||||
|
startWith,
|
||||||
|
switchMap,
|
||||||
|
} from "rxjs";
|
||||||
|
|
||||||
import { I18nPipe } from "@bitwarden/angular/platform/pipes/i18n.pipe";
|
import { I18nPipe } from "@bitwarden/angular/platform/pipes/i18n.pipe";
|
||||||
import {
|
import {
|
||||||
@@ -11,6 +20,7 @@ import {
|
|||||||
} from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
} from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
||||||
import { ProviderService } from "@bitwarden/common/admin-console/abstractions/provider.service";
|
import { ProviderService } from "@bitwarden/common/admin-console/abstractions/provider.service";
|
||||||
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
|
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
|
||||||
|
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
||||||
import { SyncService } from "@bitwarden/common/platform/sync";
|
import { SyncService } from "@bitwarden/common/platform/sync";
|
||||||
|
|
||||||
export type ProductSwitcherItem = {
|
export type ProductSwitcherItem = {
|
||||||
@@ -90,18 +100,20 @@ export class ProductSwitcherService {
|
|||||||
private router: Router,
|
private router: Router,
|
||||||
private i18n: I18nPipe,
|
private i18n: I18nPipe,
|
||||||
private syncService: SyncService,
|
private syncService: SyncService,
|
||||||
|
private accountService: AccountService,
|
||||||
) {
|
) {
|
||||||
this.pollUntilSynced();
|
this.pollUntilSynced();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
organizations$ = this.accountService.activeAccount$.pipe(
|
||||||
|
map((a) => a?.id),
|
||||||
|
switchMap((id) => this.organizationService.organizations$(id)),
|
||||||
|
);
|
||||||
|
|
||||||
products$: Observable<{
|
products$: Observable<{
|
||||||
bento: ProductSwitcherItem[];
|
bento: ProductSwitcherItem[];
|
||||||
other: ProductSwitcherItem[];
|
other: ProductSwitcherItem[];
|
||||||
}> = combineLatest([
|
}> = combineLatest([this.organizations$, this.route.paramMap, this.triggerProductUpdate$]).pipe(
|
||||||
this.organizationService.organizations$,
|
|
||||||
this.route.paramMap,
|
|
||||||
this.triggerProductUpdate$,
|
|
||||||
]).pipe(
|
|
||||||
map(([orgs, ...rest]): [Organization[], ParamMap, void] => {
|
map(([orgs, ...rest]): [Organization[], ParamMap, void] => {
|
||||||
return [
|
return [
|
||||||
// Sort orgs by name to match the order within the sidebar
|
// Sort orgs by name to match the order within the sidebar
|
||||||
|
|||||||
@@ -3,9 +3,12 @@
|
|||||||
import { Component, OnInit } from "@angular/core";
|
import { Component, OnInit } from "@angular/core";
|
||||||
import { FormControl, FormGroup, Validators } from "@angular/forms";
|
import { FormControl, FormGroup, Validators } from "@angular/forms";
|
||||||
import { Router } from "@angular/router";
|
import { Router } from "@angular/router";
|
||||||
|
import { firstValueFrom } from "rxjs";
|
||||||
|
|
||||||
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
||||||
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
|
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 { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||||
import { Guid } from "@bitwarden/common/types/guid";
|
import { Guid } from "@bitwarden/common/types/guid";
|
||||||
import { NoItemsModule, SearchModule, ToastService } from "@bitwarden/components";
|
import { NoItemsModule, SearchModule, ToastService } from "@bitwarden/components";
|
||||||
@@ -39,10 +42,12 @@ export class RequestSMAccessComponent implements OnInit {
|
|||||||
private organizationService: OrganizationService,
|
private organizationService: OrganizationService,
|
||||||
private smLandingApiService: SmLandingApiService,
|
private smLandingApiService: SmLandingApiService,
|
||||||
private toastService: ToastService,
|
private toastService: ToastService,
|
||||||
|
private accountService: AccountService,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
async ngOnInit() {
|
async ngOnInit() {
|
||||||
this.organizations = (await this.organizationService.getAll())
|
const userId = await firstValueFrom(getUserId(this.accountService.activeAccount$));
|
||||||
|
this.organizations = (await firstValueFrom(this.organizationService.organizations$(userId)))
|
||||||
.filter((e) => e.enabled)
|
.filter((e) => e.enabled)
|
||||||
.sort((a, b) => a.name.localeCompare(b.name));
|
.sort((a, b) => a.name.localeCompare(b.name));
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +1,12 @@
|
|||||||
// FIXME: Update this file to be type safe and remove this and next line
|
// FIXME: Update this file to be type safe and remove this and next line
|
||||||
// @ts-strict-ignore
|
// @ts-strict-ignore
|
||||||
import { Component, OnInit } from "@angular/core";
|
import { Component, OnInit } from "@angular/core";
|
||||||
|
import { firstValueFrom } from "rxjs";
|
||||||
|
|
||||||
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
||||||
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
|
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 { NoItemsModule, SearchModule } from "@bitwarden/components";
|
import { NoItemsModule, SearchModule } from "@bitwarden/components";
|
||||||
|
|
||||||
import { HeaderModule } from "../../layouts/header/header.module";
|
import { HeaderModule } from "../../layouts/header/header.module";
|
||||||
@@ -22,10 +25,16 @@ export class SMLandingComponent implements OnInit {
|
|||||||
showSecretsManagerInformation: boolean = true;
|
showSecretsManagerInformation: boolean = true;
|
||||||
showGiveMembersAccessInstructions: boolean = false;
|
showGiveMembersAccessInstructions: boolean = false;
|
||||||
|
|
||||||
constructor(private organizationService: OrganizationService) {}
|
constructor(
|
||||||
|
private organizationService: OrganizationService,
|
||||||
|
private accountService: AccountService,
|
||||||
|
) {}
|
||||||
|
|
||||||
async ngOnInit() {
|
async ngOnInit() {
|
||||||
const enabledOrganizations = (await this.organizationService.getAll()).filter((e) => e.enabled);
|
const userId = await firstValueFrom(getUserId(this.accountService.activeAccount$));
|
||||||
|
const enabledOrganizations = (
|
||||||
|
await firstValueFrom(this.organizationService.organizations$(userId))
|
||||||
|
).filter((e) => e.enabled);
|
||||||
|
|
||||||
if (enabledOrganizations.length > 0) {
|
if (enabledOrganizations.length > 0) {
|
||||||
this.handleEnabledOrganizations(enabledOrganizations);
|
this.handleEnabledOrganizations(enabledOrganizations);
|
||||||
|
|||||||
@@ -1,11 +1,12 @@
|
|||||||
// FIXME: Update this file to be type safe and remove this and next line
|
// FIXME: Update this file to be type safe and remove this and next line
|
||||||
// @ts-strict-ignore
|
// @ts-strict-ignore
|
||||||
import { Directive, ViewChild, ViewContainerRef, OnDestroy } from "@angular/core";
|
import { Directive, ViewChild, ViewContainerRef, OnDestroy } from "@angular/core";
|
||||||
import { BehaviorSubject, Observable, Subject, takeUntil } from "rxjs";
|
import { BehaviorSubject, Observable, Subject, switchMap, takeUntil } from "rxjs";
|
||||||
|
|
||||||
import { ModalService } from "@bitwarden/angular/services/modal.service";
|
import { ModalService } from "@bitwarden/angular/services/modal.service";
|
||||||
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
||||||
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
|
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 { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||||
import { OrganizationId } from "@bitwarden/common/types/guid";
|
import { OrganizationId } from "@bitwarden/common/types/guid";
|
||||||
import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service";
|
import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service";
|
||||||
@@ -45,10 +46,13 @@ export class CipherReportComponent implements OnDestroy {
|
|||||||
private modalService: ModalService,
|
private modalService: ModalService,
|
||||||
protected passwordRepromptService: PasswordRepromptService,
|
protected passwordRepromptService: PasswordRepromptService,
|
||||||
protected organizationService: OrganizationService,
|
protected organizationService: OrganizationService,
|
||||||
|
protected accountService: AccountService,
|
||||||
protected i18nService: I18nService,
|
protected i18nService: I18nService,
|
||||||
private syncService: SyncService,
|
private syncService: SyncService,
|
||||||
) {
|
) {
|
||||||
this.organizations$ = this.organizationService.organizations$;
|
this.organizations$ = this.accountService.activeAccount$.pipe(
|
||||||
|
switchMap((account) => this.organizationService.organizations$(account?.id)),
|
||||||
|
);
|
||||||
this.organizations$.pipe(takeUntil(this.destroyed$)).subscribe((orgs) => {
|
this.organizations$.pipe(takeUntil(this.destroyed$)).subscribe((orgs) => {
|
||||||
this.organizations = orgs;
|
this.organizations = orgs;
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -7,7 +7,11 @@ import { I18nPipe } from "@bitwarden/angular/platform/pipes/i18n.pipe";
|
|||||||
import { ModalService } from "@bitwarden/angular/services/modal.service";
|
import { ModalService } from "@bitwarden/angular/services/modal.service";
|
||||||
import { AuditService } from "@bitwarden/common/abstractions/audit.service";
|
import { AuditService } from "@bitwarden/common/abstractions/audit.service";
|
||||||
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
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 { 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 { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service";
|
import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service";
|
||||||
import { SyncService } from "@bitwarden/common/vault/abstractions/sync/sync.service.abstraction";
|
import { SyncService } from "@bitwarden/common/vault/abstractions/sync/sync.service.abstraction";
|
||||||
import { PasswordRepromptService } from "@bitwarden/vault";
|
import { PasswordRepromptService } from "@bitwarden/vault";
|
||||||
@@ -21,12 +25,15 @@ describe("ExposedPasswordsReportComponent", () => {
|
|||||||
let auditService: MockProxy<AuditService>;
|
let auditService: MockProxy<AuditService>;
|
||||||
let organizationService: MockProxy<OrganizationService>;
|
let organizationService: MockProxy<OrganizationService>;
|
||||||
let syncServiceMock: MockProxy<SyncService>;
|
let syncServiceMock: MockProxy<SyncService>;
|
||||||
|
let accountService: FakeAccountService;
|
||||||
|
const userId = Utils.newGuid() as UserId;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
syncServiceMock = mock<SyncService>();
|
syncServiceMock = mock<SyncService>();
|
||||||
auditService = mock<AuditService>();
|
auditService = mock<AuditService>();
|
||||||
organizationService = mock<OrganizationService>();
|
organizationService = mock<OrganizationService>();
|
||||||
organizationService.organizations$ = of([]);
|
organizationService.organizations$.mockReturnValue(of([]));
|
||||||
|
accountService = mockAccountServiceWith(userId);
|
||||||
// FIXME: Verify that this floating promise is intentional. If it is, add an explanatory comment and ensure there is proper error handling.
|
// FIXME: Verify that this floating promise is intentional. If it is, add an explanatory comment and ensure there is proper error handling.
|
||||||
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
||||||
TestBed.configureTestingModule({
|
TestBed.configureTestingModule({
|
||||||
@@ -44,6 +51,10 @@ describe("ExposedPasswordsReportComponent", () => {
|
|||||||
provide: OrganizationService,
|
provide: OrganizationService,
|
||||||
useValue: organizationService,
|
useValue: organizationService,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
provide: AccountService,
|
||||||
|
useValue: accountService,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
provide: ModalService,
|
provide: ModalService,
|
||||||
useValue: mock<ModalService>(),
|
useValue: mock<ModalService>(),
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import { Component, OnInit } from "@angular/core";
|
|||||||
import { ModalService } from "@bitwarden/angular/services/modal.service";
|
import { ModalService } from "@bitwarden/angular/services/modal.service";
|
||||||
import { AuditService } from "@bitwarden/common/abstractions/audit.service";
|
import { AuditService } from "@bitwarden/common/abstractions/audit.service";
|
||||||
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
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 { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||||
import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service";
|
import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service";
|
||||||
import { SyncService } from "@bitwarden/common/vault/abstractions/sync/sync.service.abstraction";
|
import { SyncService } from "@bitwarden/common/vault/abstractions/sync/sync.service.abstraction";
|
||||||
@@ -25,6 +26,7 @@ export class ExposedPasswordsReportComponent extends CipherReportComponent imple
|
|||||||
protected cipherService: CipherService,
|
protected cipherService: CipherService,
|
||||||
protected auditService: AuditService,
|
protected auditService: AuditService,
|
||||||
protected organizationService: OrganizationService,
|
protected organizationService: OrganizationService,
|
||||||
|
accountService: AccountService,
|
||||||
modalService: ModalService,
|
modalService: ModalService,
|
||||||
passwordRepromptService: PasswordRepromptService,
|
passwordRepromptService: PasswordRepromptService,
|
||||||
i18nService: I18nService,
|
i18nService: I18nService,
|
||||||
@@ -35,6 +37,7 @@ export class ExposedPasswordsReportComponent extends CipherReportComponent imple
|
|||||||
modalService,
|
modalService,
|
||||||
passwordRepromptService,
|
passwordRepromptService,
|
||||||
organizationService,
|
organizationService,
|
||||||
|
accountService,
|
||||||
i18nService,
|
i18nService,
|
||||||
syncService,
|
syncService,
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -6,8 +6,12 @@ import { of } from "rxjs";
|
|||||||
import { I18nPipe } from "@bitwarden/angular/platform/pipes/i18n.pipe";
|
import { I18nPipe } from "@bitwarden/angular/platform/pipes/i18n.pipe";
|
||||||
import { ModalService } from "@bitwarden/angular/services/modal.service";
|
import { ModalService } from "@bitwarden/angular/services/modal.service";
|
||||||
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
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 { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||||
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
|
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
|
||||||
|
import { Utils } from "@bitwarden/common/platform/misc/utils";
|
||||||
|
import { FakeAccountService, mockAccountServiceWith } from "@bitwarden/common/spec";
|
||||||
|
import { UserId } from "@bitwarden/common/types/guid";
|
||||||
import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service";
|
import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service";
|
||||||
import { SyncService } from "@bitwarden/common/vault/abstractions/sync/sync.service.abstraction";
|
import { SyncService } from "@bitwarden/common/vault/abstractions/sync/sync.service.abstraction";
|
||||||
import { PasswordRepromptService } from "@bitwarden/vault";
|
import { PasswordRepromptService } from "@bitwarden/vault";
|
||||||
@@ -20,11 +24,14 @@ describe("InactiveTwoFactorReportComponent", () => {
|
|||||||
let fixture: ComponentFixture<InactiveTwoFactorReportComponent>;
|
let fixture: ComponentFixture<InactiveTwoFactorReportComponent>;
|
||||||
let organizationService: MockProxy<OrganizationService>;
|
let organizationService: MockProxy<OrganizationService>;
|
||||||
let syncServiceMock: MockProxy<SyncService>;
|
let syncServiceMock: MockProxy<SyncService>;
|
||||||
|
let accountService: FakeAccountService;
|
||||||
|
const userId = Utils.newGuid() as UserId;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
organizationService = mock<OrganizationService>();
|
organizationService = mock<OrganizationService>();
|
||||||
organizationService.organizations$ = of([]);
|
organizationService.organizations$.mockReturnValue(of([]));
|
||||||
syncServiceMock = mock<SyncService>();
|
syncServiceMock = mock<SyncService>();
|
||||||
|
accountService = mockAccountServiceWith(userId);
|
||||||
// FIXME: Verify that this floating promise is intentional. If it is, add an explanatory comment and ensure there is proper error handling.
|
// FIXME: Verify that this floating promise is intentional. If it is, add an explanatory comment and ensure there is proper error handling.
|
||||||
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
||||||
TestBed.configureTestingModule({
|
TestBed.configureTestingModule({
|
||||||
@@ -38,6 +45,10 @@ describe("InactiveTwoFactorReportComponent", () => {
|
|||||||
provide: OrganizationService,
|
provide: OrganizationService,
|
||||||
useValue: organizationService,
|
useValue: organizationService,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
provide: AccountService,
|
||||||
|
useValue: accountService,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
provide: ModalService,
|
provide: ModalService,
|
||||||
useValue: mock<ModalService>(),
|
useValue: mock<ModalService>(),
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import { Component, OnInit } from "@angular/core";
|
|||||||
|
|
||||||
import { ModalService } from "@bitwarden/angular/services/modal.service";
|
import { ModalService } from "@bitwarden/angular/services/modal.service";
|
||||||
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
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 { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||||
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
|
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
|
||||||
import { Utils } from "@bitwarden/common/platform/misc/utils";
|
import { Utils } from "@bitwarden/common/platform/misc/utils";
|
||||||
@@ -27,6 +28,7 @@ export class InactiveTwoFactorReportComponent extends CipherReportComponent impl
|
|||||||
constructor(
|
constructor(
|
||||||
protected cipherService: CipherService,
|
protected cipherService: CipherService,
|
||||||
protected organizationService: OrganizationService,
|
protected organizationService: OrganizationService,
|
||||||
|
accountService: AccountService,
|
||||||
modalService: ModalService,
|
modalService: ModalService,
|
||||||
private logService: LogService,
|
private logService: LogService,
|
||||||
passwordRepromptService: PasswordRepromptService,
|
passwordRepromptService: PasswordRepromptService,
|
||||||
@@ -38,6 +40,7 @@ export class InactiveTwoFactorReportComponent extends CipherReportComponent impl
|
|||||||
modalService,
|
modalService,
|
||||||
passwordRepromptService,
|
passwordRepromptService,
|
||||||
organizationService,
|
organizationService,
|
||||||
|
accountService,
|
||||||
i18nService,
|
i18nService,
|
||||||
syncService,
|
syncService,
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -6,7 +6,11 @@ import { of } from "rxjs";
|
|||||||
import { I18nPipe } from "@bitwarden/angular/platform/pipes/i18n.pipe";
|
import { I18nPipe } from "@bitwarden/angular/platform/pipes/i18n.pipe";
|
||||||
import { ModalService } from "@bitwarden/angular/services/modal.service";
|
import { ModalService } from "@bitwarden/angular/services/modal.service";
|
||||||
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
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 { 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 { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service";
|
import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service";
|
||||||
import { SyncService } from "@bitwarden/common/vault/abstractions/sync/sync.service.abstraction";
|
import { SyncService } from "@bitwarden/common/vault/abstractions/sync/sync.service.abstraction";
|
||||||
import { PasswordRepromptService } from "@bitwarden/vault";
|
import { PasswordRepromptService } from "@bitwarden/vault";
|
||||||
@@ -19,11 +23,15 @@ describe("ReusedPasswordsReportComponent", () => {
|
|||||||
let fixture: ComponentFixture<ReusedPasswordsReportComponent>;
|
let fixture: ComponentFixture<ReusedPasswordsReportComponent>;
|
||||||
let organizationService: MockProxy<OrganizationService>;
|
let organizationService: MockProxy<OrganizationService>;
|
||||||
let syncServiceMock: MockProxy<SyncService>;
|
let syncServiceMock: MockProxy<SyncService>;
|
||||||
|
let accountService: FakeAccountService;
|
||||||
|
const userId = Utils.newGuid() as UserId;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
organizationService = mock<OrganizationService>();
|
organizationService = mock<OrganizationService>();
|
||||||
organizationService.organizations$ = of([]);
|
organizationService.organizations$.mockReturnValue(of([]));
|
||||||
syncServiceMock = mock<SyncService>();
|
syncServiceMock = mock<SyncService>();
|
||||||
|
accountService = mockAccountServiceWith(userId);
|
||||||
|
|
||||||
// FIXME: Verify that this floating promise is intentional. If it is, add an explanatory comment and ensure there is proper error handling.
|
// FIXME: Verify that this floating promise is intentional. If it is, add an explanatory comment and ensure there is proper error handling.
|
||||||
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
||||||
TestBed.configureTestingModule({
|
TestBed.configureTestingModule({
|
||||||
@@ -37,6 +45,10 @@ describe("ReusedPasswordsReportComponent", () => {
|
|||||||
provide: OrganizationService,
|
provide: OrganizationService,
|
||||||
useValue: organizationService,
|
useValue: organizationService,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
provide: AccountService,
|
||||||
|
useValue: accountService,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
provide: ModalService,
|
provide: ModalService,
|
||||||
useValue: mock<ModalService>(),
|
useValue: mock<ModalService>(),
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import { Component, OnInit } from "@angular/core";
|
|||||||
|
|
||||||
import { ModalService } from "@bitwarden/angular/services/modal.service";
|
import { ModalService } from "@bitwarden/angular/services/modal.service";
|
||||||
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
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 { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||||
import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service";
|
import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service";
|
||||||
import { SyncService } from "@bitwarden/common/vault/abstractions/sync/sync.service.abstraction";
|
import { SyncService } from "@bitwarden/common/vault/abstractions/sync/sync.service.abstraction";
|
||||||
@@ -24,6 +25,7 @@ export class ReusedPasswordsReportComponent extends CipherReportComponent implem
|
|||||||
constructor(
|
constructor(
|
||||||
protected cipherService: CipherService,
|
protected cipherService: CipherService,
|
||||||
protected organizationService: OrganizationService,
|
protected organizationService: OrganizationService,
|
||||||
|
accountService: AccountService,
|
||||||
modalService: ModalService,
|
modalService: ModalService,
|
||||||
passwordRepromptService: PasswordRepromptService,
|
passwordRepromptService: PasswordRepromptService,
|
||||||
i18nService: I18nService,
|
i18nService: I18nService,
|
||||||
@@ -34,6 +36,7 @@ export class ReusedPasswordsReportComponent extends CipherReportComponent implem
|
|||||||
modalService,
|
modalService,
|
||||||
passwordRepromptService,
|
passwordRepromptService,
|
||||||
organizationService,
|
organizationService,
|
||||||
|
accountService,
|
||||||
i18nService,
|
i18nService,
|
||||||
syncService,
|
syncService,
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -7,7 +7,11 @@ import { CollectionService } from "@bitwarden/admin-console/common";
|
|||||||
import { I18nPipe } from "@bitwarden/angular/platform/pipes/i18n.pipe";
|
import { I18nPipe } from "@bitwarden/angular/platform/pipes/i18n.pipe";
|
||||||
import { ModalService } from "@bitwarden/angular/services/modal.service";
|
import { ModalService } from "@bitwarden/angular/services/modal.service";
|
||||||
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
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 { 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 { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service";
|
import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service";
|
||||||
import { SyncService } from "@bitwarden/common/vault/abstractions/sync/sync.service.abstraction";
|
import { SyncService } from "@bitwarden/common/vault/abstractions/sync/sync.service.abstraction";
|
||||||
import { PasswordRepromptService } from "@bitwarden/vault";
|
import { PasswordRepromptService } from "@bitwarden/vault";
|
||||||
@@ -21,12 +25,15 @@ describe("UnsecuredWebsitesReportComponent", () => {
|
|||||||
let organizationService: MockProxy<OrganizationService>;
|
let organizationService: MockProxy<OrganizationService>;
|
||||||
let syncServiceMock: MockProxy<SyncService>;
|
let syncServiceMock: MockProxy<SyncService>;
|
||||||
let collectionService: MockProxy<CollectionService>;
|
let collectionService: MockProxy<CollectionService>;
|
||||||
|
let accountService: FakeAccountService;
|
||||||
|
const userId = Utils.newGuid() as UserId;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
organizationService = mock<OrganizationService>();
|
organizationService = mock<OrganizationService>();
|
||||||
organizationService.organizations$ = of([]);
|
organizationService.organizations$.mockReturnValue(of([]));
|
||||||
syncServiceMock = mock<SyncService>();
|
syncServiceMock = mock<SyncService>();
|
||||||
collectionService = mock<CollectionService>();
|
collectionService = mock<CollectionService>();
|
||||||
|
accountService = mockAccountServiceWith(userId);
|
||||||
// FIXME: Verify that this floating promise is intentional. If it is, add an explanatory comment and ensure there is proper error handling.
|
// FIXME: Verify that this floating promise is intentional. If it is, add an explanatory comment and ensure there is proper error handling.
|
||||||
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
||||||
TestBed.configureTestingModule({
|
TestBed.configureTestingModule({
|
||||||
@@ -40,6 +47,10 @@ describe("UnsecuredWebsitesReportComponent", () => {
|
|||||||
provide: OrganizationService,
|
provide: OrganizationService,
|
||||||
useValue: organizationService,
|
useValue: organizationService,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
provide: AccountService,
|
||||||
|
useValue: accountService,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
provide: ModalService,
|
provide: ModalService,
|
||||||
useValue: mock<ModalService>(),
|
useValue: mock<ModalService>(),
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import { Component, OnInit } from "@angular/core";
|
|||||||
import { CollectionService, Collection } from "@bitwarden/admin-console/common";
|
import { CollectionService, Collection } from "@bitwarden/admin-console/common";
|
||||||
import { ModalService } from "@bitwarden/angular/services/modal.service";
|
import { ModalService } from "@bitwarden/angular/services/modal.service";
|
||||||
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
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 { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||||
import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service";
|
import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service";
|
||||||
import { SyncService } from "@bitwarden/common/vault/abstractions/sync/sync.service.abstraction";
|
import { SyncService } from "@bitwarden/common/vault/abstractions/sync/sync.service.abstraction";
|
||||||
@@ -22,6 +23,7 @@ export class UnsecuredWebsitesReportComponent extends CipherReportComponent impl
|
|||||||
constructor(
|
constructor(
|
||||||
protected cipherService: CipherService,
|
protected cipherService: CipherService,
|
||||||
protected organizationService: OrganizationService,
|
protected organizationService: OrganizationService,
|
||||||
|
accountService: AccountService,
|
||||||
modalService: ModalService,
|
modalService: ModalService,
|
||||||
passwordRepromptService: PasswordRepromptService,
|
passwordRepromptService: PasswordRepromptService,
|
||||||
i18nService: I18nService,
|
i18nService: I18nService,
|
||||||
@@ -33,6 +35,7 @@ export class UnsecuredWebsitesReportComponent extends CipherReportComponent impl
|
|||||||
modalService,
|
modalService,
|
||||||
passwordRepromptService,
|
passwordRepromptService,
|
||||||
organizationService,
|
organizationService,
|
||||||
|
accountService,
|
||||||
i18nService,
|
i18nService,
|
||||||
syncService,
|
syncService,
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -6,8 +6,12 @@ import { of } from "rxjs";
|
|||||||
import { I18nPipe } from "@bitwarden/angular/platform/pipes/i18n.pipe";
|
import { I18nPipe } from "@bitwarden/angular/platform/pipes/i18n.pipe";
|
||||||
import { ModalService } from "@bitwarden/angular/services/modal.service";
|
import { ModalService } from "@bitwarden/angular/services/modal.service";
|
||||||
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
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 { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||||
|
import { Utils } from "@bitwarden/common/platform/misc/utils";
|
||||||
|
import { FakeAccountService, mockAccountServiceWith } from "@bitwarden/common/spec";
|
||||||
import { PasswordStrengthServiceAbstraction } from "@bitwarden/common/tools/password-strength";
|
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 { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service";
|
||||||
import { SyncService } from "@bitwarden/common/vault/abstractions/sync/sync.service.abstraction";
|
import { SyncService } from "@bitwarden/common/vault/abstractions/sync/sync.service.abstraction";
|
||||||
import { PasswordRepromptService } from "@bitwarden/vault";
|
import { PasswordRepromptService } from "@bitwarden/vault";
|
||||||
@@ -21,12 +25,15 @@ describe("WeakPasswordsReportComponent", () => {
|
|||||||
let passwordStrengthService: MockProxy<PasswordStrengthServiceAbstraction>;
|
let passwordStrengthService: MockProxy<PasswordStrengthServiceAbstraction>;
|
||||||
let organizationService: MockProxy<OrganizationService>;
|
let organizationService: MockProxy<OrganizationService>;
|
||||||
let syncServiceMock: MockProxy<SyncService>;
|
let syncServiceMock: MockProxy<SyncService>;
|
||||||
|
let accountService: FakeAccountService;
|
||||||
|
const userId = Utils.newGuid() as UserId;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
syncServiceMock = mock<SyncService>();
|
syncServiceMock = mock<SyncService>();
|
||||||
passwordStrengthService = mock<PasswordStrengthServiceAbstraction>();
|
passwordStrengthService = mock<PasswordStrengthServiceAbstraction>();
|
||||||
organizationService = mock<OrganizationService>();
|
organizationService = mock<OrganizationService>();
|
||||||
organizationService.organizations$ = of([]);
|
organizationService.organizations$.mockReturnValue(of([]));
|
||||||
|
accountService = mockAccountServiceWith(userId);
|
||||||
// FIXME: Verify that this floating promise is intentional. If it is, add an explanatory comment and ensure there is proper error handling.
|
// FIXME: Verify that this floating promise is intentional. If it is, add an explanatory comment and ensure there is proper error handling.
|
||||||
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
||||||
TestBed.configureTestingModule({
|
TestBed.configureTestingModule({
|
||||||
@@ -44,6 +51,10 @@ describe("WeakPasswordsReportComponent", () => {
|
|||||||
provide: OrganizationService,
|
provide: OrganizationService,
|
||||||
useValue: organizationService,
|
useValue: organizationService,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
provide: AccountService,
|
||||||
|
useValue: accountService,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
provide: ModalService,
|
provide: ModalService,
|
||||||
useValue: mock<ModalService>(),
|
useValue: mock<ModalService>(),
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import { Component, OnInit } from "@angular/core";
|
|||||||
|
|
||||||
import { ModalService } from "@bitwarden/angular/services/modal.service";
|
import { ModalService } from "@bitwarden/angular/services/modal.service";
|
||||||
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
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 { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||||
import { Utils } from "@bitwarden/common/platform/misc/utils";
|
import { Utils } from "@bitwarden/common/platform/misc/utils";
|
||||||
import { PasswordStrengthServiceAbstraction } from "@bitwarden/common/tools/password-strength";
|
import { PasswordStrengthServiceAbstraction } from "@bitwarden/common/tools/password-strength";
|
||||||
@@ -32,6 +33,7 @@ export class WeakPasswordsReportComponent extends CipherReportComponent implemen
|
|||||||
protected cipherService: CipherService,
|
protected cipherService: CipherService,
|
||||||
protected passwordStrengthService: PasswordStrengthServiceAbstraction,
|
protected passwordStrengthService: PasswordStrengthServiceAbstraction,
|
||||||
protected organizationService: OrganizationService,
|
protected organizationService: OrganizationService,
|
||||||
|
protected accountService: AccountService,
|
||||||
modalService: ModalService,
|
modalService: ModalService,
|
||||||
passwordRepromptService: PasswordRepromptService,
|
passwordRepromptService: PasswordRepromptService,
|
||||||
i18nService: I18nService,
|
i18nService: I18nService,
|
||||||
@@ -42,6 +44,7 @@ export class WeakPasswordsReportComponent extends CipherReportComponent implemen
|
|||||||
modalService,
|
modalService,
|
||||||
passwordRepromptService,
|
passwordRepromptService,
|
||||||
organizationService,
|
organizationService,
|
||||||
|
accountService,
|
||||||
i18nService,
|
i18nService,
|
||||||
syncService,
|
syncService,
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import { ChangeDetectorRef, Component, Inject, OnDestroy, OnInit } from "@angula
|
|||||||
import { AbstractControl, FormBuilder, Validators } from "@angular/forms";
|
import { AbstractControl, FormBuilder, Validators } from "@angular/forms";
|
||||||
import {
|
import {
|
||||||
combineLatest,
|
combineLatest,
|
||||||
|
firstValueFrom,
|
||||||
map,
|
map,
|
||||||
Observable,
|
Observable,
|
||||||
of,
|
of,
|
||||||
@@ -24,8 +25,13 @@ import {
|
|||||||
CollectionResponse,
|
CollectionResponse,
|
||||||
CollectionView,
|
CollectionView,
|
||||||
} from "@bitwarden/admin-console/common";
|
} from "@bitwarden/admin-console/common";
|
||||||
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 { 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 { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||||
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
||||||
import { Utils } from "@bitwarden/common/platform/misc/utils";
|
import { Utils } from "@bitwarden/common/platform/misc/utils";
|
||||||
@@ -110,6 +116,7 @@ export class CollectionDialogComponent implements OnInit, OnDestroy {
|
|||||||
private organizationUserApiService: OrganizationUserApiService,
|
private organizationUserApiService: OrganizationUserApiService,
|
||||||
private dialogService: DialogService,
|
private dialogService: DialogService,
|
||||||
private changeDetectorRef: ChangeDetectorRef,
|
private changeDetectorRef: ChangeDetectorRef,
|
||||||
|
private accountService: AccountService,
|
||||||
private toastService: ToastService,
|
private toastService: ToastService,
|
||||||
) {
|
) {
|
||||||
this.tabIndex = params.initialTab ?? CollectionDialogTabType.Info;
|
this.tabIndex = params.initialTab ?? CollectionDialogTabType.Info;
|
||||||
@@ -122,7 +129,10 @@ export class CollectionDialogComponent implements OnInit, OnDestroy {
|
|||||||
this.formGroup.controls.selectedOrg.valueChanges
|
this.formGroup.controls.selectedOrg.valueChanges
|
||||||
.pipe(takeUntil(this.destroy$))
|
.pipe(takeUntil(this.destroy$))
|
||||||
.subscribe((id) => this.loadOrg(id));
|
.subscribe((id) => this.loadOrg(id));
|
||||||
this.organizations$ = this.organizationService.organizations$.pipe(
|
const userId = await firstValueFrom(
|
||||||
|
this.accountService.activeAccount$.pipe(map((a) => a?.id)),
|
||||||
|
);
|
||||||
|
this.organizations$ = this.organizationService.organizations$(userId).pipe(
|
||||||
first(),
|
first(),
|
||||||
map((orgs) =>
|
map((orgs) =>
|
||||||
orgs
|
orgs
|
||||||
@@ -140,8 +150,10 @@ export class CollectionDialogComponent implements OnInit, OnDestroy {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async loadOrg(orgId: string) {
|
async loadOrg(orgId: string) {
|
||||||
|
const userId = await firstValueFrom(getUserId(this.accountService.activeAccount$));
|
||||||
const organization$ = this.organizationService
|
const organization$ = this.organizationService
|
||||||
.get$(orgId)
|
.organizations$(userId)
|
||||||
|
.pipe(getOrganizationById(orgId))
|
||||||
.pipe(shareReplay({ refCount: true, bufferSize: 1 }));
|
.pipe(shareReplay({ refCount: true, bufferSize: 1 }));
|
||||||
const groups$ = organization$.pipe(
|
const groups$ = organization$.pipe(
|
||||||
switchMap((organization) => {
|
switchMap((organization) => {
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ describe("AddEditComponentV2", () => {
|
|||||||
} as Organization;
|
} as Organization;
|
||||||
|
|
||||||
organizationService = mock<OrganizationService>();
|
organizationService = mock<OrganizationService>();
|
||||||
organizationService.organizations$ = of([mockOrganization]);
|
organizationService.organizations$.mockReturnValue(of([mockOrganization]));
|
||||||
|
|
||||||
policyService = mock<PolicyService>();
|
policyService = mock<PolicyService>();
|
||||||
policyService.policyAppliesToActiveUser$.mockImplementation((policyType: PolicyType) =>
|
policyService.policyAppliesToActiveUser$.mockImplementation((policyType: PolicyType) =>
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import { CollectionService, CollectionView } from "@bitwarden/admin-console/comm
|
|||||||
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
||||||
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
|
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
|
||||||
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
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 { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||||
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
|
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
|
||||||
import { Checkable, isChecked } from "@bitwarden/common/types/checkable";
|
import { Checkable, isChecked } from "@bitwarden/common/types/checkable";
|
||||||
@@ -76,7 +77,8 @@ export class BulkShareDialogComponent implements OnInit, OnDestroy {
|
|||||||
this.nonShareableCount = this.ciphers.length - this.shareableCiphers.length;
|
this.nonShareableCount = this.ciphers.length - this.shareableCiphers.length;
|
||||||
const allCollections = await this.collectionService.getAllDecrypted();
|
const allCollections = await this.collectionService.getAllDecrypted();
|
||||||
this.writeableCollections = allCollections.filter((c) => !c.readOnly);
|
this.writeableCollections = allCollections.filter((c) => !c.readOnly);
|
||||||
this.organizations = await this.organizationService.getAll();
|
const userId = await firstValueFrom(getUserId(this.accountService.activeAccount$));
|
||||||
|
this.organizations = await firstValueFrom(this.organizationService.organizations$(userId));
|
||||||
if (this.organizationId == null && this.organizations.length > 0) {
|
if (this.organizationId == null && this.organizations.length > 0) {
|
||||||
this.organizationId = this.organizations[0].id;
|
this.organizationId = this.organizations[0].id;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,16 @@
|
|||||||
// FIXME: Update this file to be type safe and remove this and next line
|
// FIXME: Update this file to be type safe and remove this and next line
|
||||||
// @ts-strict-ignore
|
// @ts-strict-ignore
|
||||||
import { Component, Inject, OnDestroy, OnInit } from "@angular/core";
|
import { Component, Inject, OnDestroy, OnInit } from "@angular/core";
|
||||||
import { combineLatest, map, Observable, of, Subject, switchMap, takeUntil } from "rxjs";
|
import {
|
||||||
|
combineLatest,
|
||||||
|
firstValueFrom,
|
||||||
|
map,
|
||||||
|
Observable,
|
||||||
|
of,
|
||||||
|
Subject,
|
||||||
|
switchMap,
|
||||||
|
takeUntil,
|
||||||
|
} from "rxjs";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
OrganizationUserApiService,
|
OrganizationUserApiService,
|
||||||
@@ -15,7 +24,9 @@ import { PolicyService } from "@bitwarden/common/admin-console/abstractions/poli
|
|||||||
import { PolicyType } from "@bitwarden/common/admin-console/enums";
|
import { PolicyType } from "@bitwarden/common/admin-console/enums";
|
||||||
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
|
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
|
||||||
import { Policy } from "@bitwarden/common/admin-console/models/domain/policy";
|
import { Policy } from "@bitwarden/common/admin-console/models/domain/policy";
|
||||||
|
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
||||||
import { UserVerificationService } from "@bitwarden/common/auth/abstractions/user-verification/user-verification.service.abstraction";
|
import { UserVerificationService } from "@bitwarden/common/auth/abstractions/user-verification/user-verification.service.abstraction";
|
||||||
|
import { getUserId } from "@bitwarden/common/auth/services/account.service";
|
||||||
import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum";
|
import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum";
|
||||||
import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
|
import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
|
||||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||||
@@ -60,6 +71,7 @@ export class OrganizationOptionsComponent implements OnInit, OnDestroy {
|
|||||||
private toastService: ToastService,
|
private toastService: ToastService,
|
||||||
private configService: ConfigService,
|
private configService: ConfigService,
|
||||||
private organizationService: OrganizationService,
|
private organizationService: OrganizationService,
|
||||||
|
private accountService: AccountService,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
async ngOnInit() {
|
async ngOnInit() {
|
||||||
@@ -67,16 +79,19 @@ export class OrganizationOptionsComponent implements OnInit, OnDestroy {
|
|||||||
map((policies) => policies.filter((policy) => policy.type === PolicyType.ResetPassword)),
|
map((policies) => policies.filter((policy) => policy.type === PolicyType.ResetPassword)),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const userId = await firstValueFrom(getUserId(this.accountService.activeAccount$));
|
||||||
const managingOrg$ = this.configService
|
const managingOrg$ = this.configService
|
||||||
.getFeatureFlag$(FeatureFlag.AccountDeprovisioning)
|
.getFeatureFlag$(FeatureFlag.AccountDeprovisioning)
|
||||||
.pipe(
|
.pipe(
|
||||||
switchMap((isAccountDeprovisioningEnabled) =>
|
switchMap((isAccountDeprovisioningEnabled) =>
|
||||||
isAccountDeprovisioningEnabled
|
isAccountDeprovisioningEnabled
|
||||||
? this.organizationService.organizations$.pipe(
|
? this.organizationService
|
||||||
map((organizations) =>
|
.organizations$(userId)
|
||||||
organizations.find((o) => o.userIsManagedByOrganization === true),
|
.pipe(
|
||||||
),
|
map((organizations) =>
|
||||||
)
|
organizations.find((o) => o.userIsManagedByOrganization === true),
|
||||||
|
),
|
||||||
|
)
|
||||||
: of(null),
|
: of(null),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -62,7 +62,7 @@ describe("vault filter service", () => {
|
|||||||
personalOwnershipPolicy = new ReplaySubject<boolean>(1);
|
personalOwnershipPolicy = new ReplaySubject<boolean>(1);
|
||||||
singleOrgPolicy = new ReplaySubject<boolean>(1);
|
singleOrgPolicy = new ReplaySubject<boolean>(1);
|
||||||
|
|
||||||
organizationService.memberOrganizations$ = organizations;
|
organizationService.memberOrganizations$.mockReturnValue(organizations);
|
||||||
folderService.folderViews$.mockReturnValue(folderViews);
|
folderService.folderViews$.mockReturnValue(folderViews);
|
||||||
collectionService.decryptedCollections$ = collectionViews;
|
collectionService.decryptedCollections$ = collectionViews;
|
||||||
policyService.policyAppliesToActiveUser$
|
policyService.policyAppliesToActiveUser$
|
||||||
|
|||||||
@@ -48,8 +48,12 @@ const NestingDelimiter = "/";
|
|||||||
export class VaultFilterService implements VaultFilterServiceAbstraction {
|
export class VaultFilterService implements VaultFilterServiceAbstraction {
|
||||||
private activeUserId$ = this.accountService.activeAccount$.pipe(map((a) => a?.id));
|
private activeUserId$ = this.accountService.activeAccount$.pipe(map((a) => a?.id));
|
||||||
|
|
||||||
|
memberOrganizations$ = this.activeUserId$.pipe(
|
||||||
|
switchMap((id) => this.organizationService.memberOrganizations$(id)),
|
||||||
|
);
|
||||||
|
|
||||||
organizationTree$: Observable<TreeNode<OrganizationFilter>> = combineLatest([
|
organizationTree$: Observable<TreeNode<OrganizationFilter>> = combineLatest([
|
||||||
this.organizationService.memberOrganizations$,
|
this.memberOrganizations$,
|
||||||
this.policyService.policyAppliesToActiveUser$(PolicyType.SingleOrg),
|
this.policyService.policyAppliesToActiveUser$(PolicyType.SingleOrg),
|
||||||
this.policyService.policyAppliesToActiveUser$(PolicyType.PersonalOwnership),
|
this.policyService.policyAppliesToActiveUser$(PolicyType.PersonalOwnership),
|
||||||
]).pipe(
|
]).pipe(
|
||||||
|
|||||||
@@ -47,7 +47,10 @@ import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
|||||||
import { EventCollectionService } from "@bitwarden/common/abstractions/event/event-collection.service";
|
import { EventCollectionService } from "@bitwarden/common/abstractions/event/event-collection.service";
|
||||||
import { SearchService } from "@bitwarden/common/abstractions/search.service";
|
import { SearchService } from "@bitwarden/common/abstractions/search.service";
|
||||||
import { OrganizationApiServiceAbstraction } from "@bitwarden/common/admin-console/abstractions/organization/organization-api.service.abstraction";
|
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 { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
|
||||||
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
||||||
import { OrganizationBillingServiceAbstraction } from "@bitwarden/common/billing/abstractions";
|
import { OrganizationBillingServiceAbstraction } from "@bitwarden/common/billing/abstractions";
|
||||||
@@ -193,7 +196,11 @@ export class VaultComponent implements OnInit, OnDestroy {
|
|||||||
private hasSubscription$ = new BehaviorSubject<boolean>(false);
|
private hasSubscription$ = new BehaviorSubject<boolean>(false);
|
||||||
|
|
||||||
private vaultItemDialogRef?: DialogRef<VaultItemDialogResult> | undefined;
|
private vaultItemDialogRef?: DialogRef<VaultItemDialogResult> | undefined;
|
||||||
private readonly unpaidSubscriptionDialog$ = this.organizationService.organizations$.pipe(
|
private organizations$ = this.accountService.activeAccount$
|
||||||
|
.pipe(map((a) => a?.id))
|
||||||
|
.pipe(switchMap((id) => this.organizationService.organizations$(id)));
|
||||||
|
|
||||||
|
private readonly unpaidSubscriptionDialog$ = this.organizations$.pipe(
|
||||||
filter((organizations) => organizations.length === 1),
|
filter((organizations) => organizations.length === 1),
|
||||||
map(([organization]) => organization),
|
map(([organization]) => organization),
|
||||||
switchMap((organization) =>
|
switchMap((organization) =>
|
||||||
@@ -212,9 +219,8 @@ export class VaultComponent implements OnInit, OnDestroy {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
protected organizationsPaymentStatus$: Observable<FreeTrial[]> = combineLatest([
|
protected organizationsPaymentStatus$: Observable<FreeTrial[]> = combineLatest([
|
||||||
this.organizationService.organizations$.pipe(
|
this.organizations$.pipe(
|
||||||
map(
|
map(
|
||||||
(organizations) =>
|
(organizations) =>
|
||||||
organizations?.filter((org) => org.isOwner && org.canViewBillingHistory) ?? [],
|
organizations?.filter((org) => org.isOwner && org.canViewBillingHistory) ?? [],
|
||||||
@@ -501,7 +507,7 @@ export class VaultComponent implements OnInit, OnDestroy {
|
|||||||
filter$,
|
filter$,
|
||||||
this.billingAccountProfileStateService.hasPremiumFromAnySource$(this.activeUserId),
|
this.billingAccountProfileStateService.hasPremiumFromAnySource$(this.activeUserId),
|
||||||
allCollections$,
|
allCollections$,
|
||||||
this.organizationService.organizations$,
|
this.organizations$,
|
||||||
ciphers$,
|
ciphers$,
|
||||||
collections$,
|
collections$,
|
||||||
selectedCollection$,
|
selectedCollection$,
|
||||||
@@ -646,7 +652,9 @@ export class VaultComponent implements OnInit, OnDestroy {
|
|||||||
this.messagingService.send("premiumRequired");
|
this.messagingService.send("premiumRequired");
|
||||||
return;
|
return;
|
||||||
} else if (cipher.organizationId != null) {
|
} else if (cipher.organizationId != null) {
|
||||||
const org = await this.organizationService.get(cipher.organizationId);
|
const org = await firstValueFrom(
|
||||||
|
this.organizations$.pipe(getOrganizationById(cipher.organizationId)),
|
||||||
|
);
|
||||||
if (org != null && (org.maxStorageGb == null || org.maxStorageGb === 0)) {
|
if (org != null && (org.maxStorageGb == null || org.maxStorageGb === 0)) {
|
||||||
this.messagingService.send("upgradeOrganization", {
|
this.messagingService.send("upgradeOrganization", {
|
||||||
organizationId: cipher.organizationId,
|
organizationId: cipher.organizationId,
|
||||||
@@ -971,7 +979,9 @@ export class VaultComponent implements OnInit, OnDestroy {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async deleteCollection(collection: CollectionView): Promise<void> {
|
async deleteCollection(collection: CollectionView): Promise<void> {
|
||||||
const organization = await this.organizationService.get(collection.organizationId);
|
const organization = await firstValueFrom(
|
||||||
|
this.organizations$.pipe(getOrganizationById(collection.organizationId)),
|
||||||
|
);
|
||||||
if (!collection.canDelete(organization)) {
|
if (!collection.canDelete(organization)) {
|
||||||
this.showMissingPermissionsError();
|
this.showMissingPermissionsError();
|
||||||
return;
|
return;
|
||||||
@@ -1136,9 +1146,7 @@ export class VaultComponent implements OnInit, OnDestroy {
|
|||||||
.filter((i) => i.cipher === undefined)
|
.filter((i) => i.cipher === undefined)
|
||||||
.map((i) => i.collection.organizationId);
|
.map((i) => i.collection.organizationId);
|
||||||
const orgs = await firstValueFrom(
|
const orgs = await firstValueFrom(
|
||||||
this.organizationService.organizations$.pipe(
|
this.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);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { DIALOG_DATA, DialogRef } from "@angular/cdk/dialog";
|
import { DIALOG_DATA, DialogRef } from "@angular/cdk/dialog";
|
||||||
import { ComponentFixture, TestBed } from "@angular/core/testing";
|
import { ComponentFixture, TestBed } from "@angular/core/testing";
|
||||||
import { mock } from "jest-mock-extended";
|
import { mock } from "jest-mock-extended";
|
||||||
|
import { of } from "rxjs";
|
||||||
|
|
||||||
import { CollectionService } from "@bitwarden/admin-console/common";
|
import { CollectionService } from "@bitwarden/admin-console/common";
|
||||||
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
||||||
@@ -11,7 +12,8 @@ import { ConfigService } from "@bitwarden/common/platform/abstractions/config/co
|
|||||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||||
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
|
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
|
||||||
import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service";
|
import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service";
|
||||||
import { mockAccountServiceWith } from "@bitwarden/common/spec";
|
import { Utils } from "@bitwarden/common/platform/misc/utils";
|
||||||
|
import { FakeAccountService, mockAccountServiceWith } from "@bitwarden/common/spec";
|
||||||
import { UserId } from "@bitwarden/common/types/guid";
|
import { UserId } from "@bitwarden/common/types/guid";
|
||||||
import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service";
|
import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service";
|
||||||
import { FolderService } from "@bitwarden/common/vault/abstractions/folder/folder.service.abstraction";
|
import { FolderService } from "@bitwarden/common/vault/abstractions/folder/folder.service.abstraction";
|
||||||
@@ -41,6 +43,8 @@ describe("ViewComponent", () => {
|
|||||||
const mockParams: ViewCipherDialogParams = {
|
const mockParams: ViewCipherDialogParams = {
|
||||||
cipher: mockCipher,
|
cipher: mockCipher,
|
||||||
};
|
};
|
||||||
|
const userId = Utils.newGuid() as UserId;
|
||||||
|
const accountService: FakeAccountService = mockAccountServiceWith(userId);
|
||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
await TestBed.configureTestingModule({
|
await TestBed.configureTestingModule({
|
||||||
@@ -53,10 +57,14 @@ describe("ViewComponent", () => {
|
|||||||
{ provide: CipherService, useValue: mock<CipherService>() },
|
{ provide: CipherService, useValue: mock<CipherService>() },
|
||||||
{ provide: ToastService, useValue: mock<ToastService>() },
|
{ provide: ToastService, useValue: mock<ToastService>() },
|
||||||
{ provide: MessagingService, useValue: mock<MessagingService>() },
|
{ provide: MessagingService, useValue: mock<MessagingService>() },
|
||||||
|
{
|
||||||
|
provide: AccountService,
|
||||||
|
useValue: accountService,
|
||||||
|
},
|
||||||
{ provide: LogService, useValue: mock<LogService>() },
|
{ provide: LogService, useValue: mock<LogService>() },
|
||||||
{
|
{
|
||||||
provide: OrganizationService,
|
provide: OrganizationService,
|
||||||
useValue: { get: jest.fn().mockResolvedValue(mockOrganization) },
|
useValue: { organizations$: jest.fn().mockReturnValue(of([mockOrganization])) },
|
||||||
},
|
},
|
||||||
{ provide: CollectionService, useValue: mock<CollectionService>() },
|
{ provide: CollectionService, useValue: mock<CollectionService>() },
|
||||||
{ provide: FolderService, useValue: mock<FolderService>() },
|
{ provide: FolderService, useValue: mock<FolderService>() },
|
||||||
|
|||||||
@@ -3,11 +3,13 @@
|
|||||||
import { DIALOG_DATA, DialogConfig, DialogRef } from "@angular/cdk/dialog";
|
import { DIALOG_DATA, DialogConfig, DialogRef } from "@angular/cdk/dialog";
|
||||||
import { CommonModule } from "@angular/common";
|
import { CommonModule } from "@angular/common";
|
||||||
import { Component, EventEmitter, Inject, OnInit } from "@angular/core";
|
import { Component, EventEmitter, Inject, OnInit } from "@angular/core";
|
||||||
import { Observable } from "rxjs";
|
import { Observable, firstValueFrom, map } from "rxjs";
|
||||||
|
|
||||||
import { CollectionView } from "@bitwarden/admin-console/common";
|
import { CollectionView } from "@bitwarden/admin-console/common";
|
||||||
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
||||||
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
|
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 { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||||
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
|
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
|
||||||
import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service";
|
import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service";
|
||||||
@@ -94,6 +96,7 @@ export class ViewComponent implements OnInit {
|
|||||||
private toastService: ToastService,
|
private toastService: ToastService,
|
||||||
private organizationService: OrganizationService,
|
private organizationService: OrganizationService,
|
||||||
private cipherAuthorizationService: CipherAuthorizationService,
|
private cipherAuthorizationService: CipherAuthorizationService,
|
||||||
|
private accountService: AccountService,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -103,8 +106,17 @@ export class ViewComponent implements OnInit {
|
|||||||
this.cipher = this.params.cipher;
|
this.cipher = this.params.cipher;
|
||||||
this.collections = this.params.collections;
|
this.collections = this.params.collections;
|
||||||
this.cipherTypeString = this.getCipherViewTypeString();
|
this.cipherTypeString = this.getCipherViewTypeString();
|
||||||
|
|
||||||
|
const userId = await firstValueFrom(getUserId(this.accountService.activeAccount$));
|
||||||
|
|
||||||
if (this.cipher.organizationId) {
|
if (this.cipher.organizationId) {
|
||||||
this.organization = await this.organizationService.get(this.cipher.organizationId);
|
this.organization = await firstValueFrom(
|
||||||
|
this.organizationService
|
||||||
|
.organizations$(userId)
|
||||||
|
.pipe(
|
||||||
|
map((organizations) => organizations.find((o) => o.id === this.cipher.organizationId)),
|
||||||
|
),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.canDeleteCipher$ = this.cipherAuthorizationService.canDeleteCipher$(this.cipher, [
|
this.canDeleteCipher$ = this.cipherAuthorizationService.canDeleteCipher$(this.cipher, [
|
||||||
|
|||||||
@@ -10,8 +10,12 @@ import {
|
|||||||
OrganizationUserApiService,
|
OrganizationUserApiService,
|
||||||
CollectionView,
|
CollectionView,
|
||||||
} from "@bitwarden/admin-console/common";
|
} from "@bitwarden/admin-console/common";
|
||||||
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 { 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 { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||||
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
||||||
import { DialogService, ToastService } from "@bitwarden/components";
|
import { DialogService, ToastService } from "@bitwarden/components";
|
||||||
@@ -63,6 +67,7 @@ export class BulkCollectionsDialogComponent implements OnDestroy {
|
|||||||
private dialogRef: DialogRef<BulkCollectionsDialogResult>,
|
private dialogRef: DialogRef<BulkCollectionsDialogResult>,
|
||||||
private formBuilder: FormBuilder,
|
private formBuilder: FormBuilder,
|
||||||
private organizationService: OrganizationService,
|
private organizationService: OrganizationService,
|
||||||
|
private accountService: AccountService,
|
||||||
private groupService: GroupApiService,
|
private groupService: GroupApiService,
|
||||||
private organizationUserApiService: OrganizationUserApiService,
|
private organizationUserApiService: OrganizationUserApiService,
|
||||||
private platformUtilsService: PlatformUtilsService,
|
private platformUtilsService: PlatformUtilsService,
|
||||||
@@ -71,7 +76,13 @@ export class BulkCollectionsDialogComponent implements OnDestroy {
|
|||||||
private toastService: ToastService,
|
private toastService: ToastService,
|
||||||
) {
|
) {
|
||||||
this.numCollections = this.params.collections.length;
|
this.numCollections = this.params.collections.length;
|
||||||
const organization$ = this.organizationService.get$(this.params.organizationId);
|
const organization$ = this.accountService.activeAccount$.pipe(
|
||||||
|
switchMap((account) =>
|
||||||
|
this.organizationService
|
||||||
|
.organizations$(account?.id)
|
||||||
|
.pipe(getOrganizationById(this.params.organizationId)),
|
||||||
|
),
|
||||||
|
);
|
||||||
const groups$ = organization$.pipe(
|
const groups$ = organization$.pipe(
|
||||||
switchMap((organization) => {
|
switchMap((organization) => {
|
||||||
if (!organization.useGroups) {
|
if (!organization.useGroups) {
|
||||||
|
|||||||
@@ -7,9 +7,11 @@ import { OrganizationService } from "@bitwarden/common/admin-console/abstraction
|
|||||||
import { PolicyService } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction";
|
import { PolicyService } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction";
|
||||||
import { OrganizationUserStatusType } from "@bitwarden/common/admin-console/enums";
|
import { OrganizationUserStatusType } from "@bitwarden/common/admin-console/enums";
|
||||||
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
|
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
|
||||||
|
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
||||||
import { CipherId } from "@bitwarden/common/types/guid";
|
import { CipherId } from "@bitwarden/common/types/guid";
|
||||||
import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service";
|
import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service";
|
||||||
|
|
||||||
|
import { Account } from "../../../../../../../libs/importer/src/importers/lastpass/access/models";
|
||||||
import { RoutedVaultFilterService } from "../../individual-vault/vault-filter/services/routed-vault-filter.service";
|
import { RoutedVaultFilterService } from "../../individual-vault/vault-filter/services/routed-vault-filter.service";
|
||||||
|
|
||||||
import { AdminConsoleCipherFormConfigService } from "./admin-console-cipher-form-config.service";
|
import { AdminConsoleCipherFormConfigService } from "./admin-console-cipher-form-config.service";
|
||||||
@@ -50,8 +52,7 @@ describe("AdminConsoleCipherFormConfigService", () => {
|
|||||||
readOnly: false,
|
readOnly: false,
|
||||||
} as CollectionAdminView;
|
} as CollectionAdminView;
|
||||||
|
|
||||||
const organization$ = new BehaviorSubject<Organization>(testOrg as Organization);
|
const orgs$ = new BehaviorSubject<Organization[]>([testOrg, testOrg2] as Organization[]);
|
||||||
const organizations$ = new BehaviorSubject<Organization[]>([testOrg, testOrg2] as Organization[]);
|
|
||||||
const getCipherAdmin = jest.fn().mockResolvedValue(null);
|
const getCipherAdmin = jest.fn().mockResolvedValue(null);
|
||||||
const getCipher = jest.fn().mockResolvedValue(null);
|
const getCipher = jest.fn().mockResolvedValue(null);
|
||||||
|
|
||||||
@@ -65,7 +66,7 @@ describe("AdminConsoleCipherFormConfigService", () => {
|
|||||||
TestBed.configureTestingModule({
|
TestBed.configureTestingModule({
|
||||||
providers: [
|
providers: [
|
||||||
AdminConsoleCipherFormConfigService,
|
AdminConsoleCipherFormConfigService,
|
||||||
{ provide: OrganizationService, useValue: { get$: () => organization$, organizations$ } },
|
{ provide: OrganizationService, useValue: { organizations$: () => orgs$ } },
|
||||||
{
|
{
|
||||||
provide: CollectionAdminService,
|
provide: CollectionAdminService,
|
||||||
useValue: { getAll: () => Promise.resolve([collection, collection2]) },
|
useValue: { getAll: () => Promise.resolve([collection, collection2]) },
|
||||||
@@ -80,6 +81,10 @@ describe("AdminConsoleCipherFormConfigService", () => {
|
|||||||
},
|
},
|
||||||
{ provide: ApiService, useValue: { getCipherAdmin } },
|
{ provide: ApiService, useValue: { getCipherAdmin } },
|
||||||
{ provide: CipherService, useValue: { get: getCipher } },
|
{ provide: CipherService, useValue: { get: getCipher } },
|
||||||
|
{
|
||||||
|
provide: AccountService,
|
||||||
|
useValue: { activeAccount$: new BehaviorSubject<Account>(new Account()) },
|
||||||
|
},
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
adminConsoleConfigService = TestBed.inject(AdminConsoleCipherFormConfigService);
|
adminConsoleConfigService = TestBed.inject(AdminConsoleCipherFormConfigService);
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import { OrganizationService } from "@bitwarden/common/admin-console/abstraction
|
|||||||
import { PolicyService } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction";
|
import { PolicyService } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction";
|
||||||
import { OrganizationUserStatusType, PolicyType } from "@bitwarden/common/admin-console/enums";
|
import { OrganizationUserStatusType, PolicyType } from "@bitwarden/common/admin-console/enums";
|
||||||
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
|
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
|
||||||
|
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
||||||
import { CipherId } from "@bitwarden/common/types/guid";
|
import { CipherId } from "@bitwarden/common/types/guid";
|
||||||
import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service";
|
import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service";
|
||||||
import { CipherType } from "@bitwarden/common/vault/enums";
|
import { CipherType } from "@bitwarden/common/vault/enums";
|
||||||
@@ -31,6 +32,7 @@ export class AdminConsoleCipherFormConfigService implements CipherFormConfigServ
|
|||||||
private collectionAdminService: CollectionAdminService = inject(CollectionAdminService);
|
private collectionAdminService: CollectionAdminService = inject(CollectionAdminService);
|
||||||
private cipherService: CipherService = inject(CipherService);
|
private cipherService: CipherService = inject(CipherService);
|
||||||
private apiService: ApiService = inject(ApiService);
|
private apiService: ApiService = inject(ApiService);
|
||||||
|
private accountService: AccountService = inject(AccountService);
|
||||||
|
|
||||||
private allowPersonalOwnership$ = this.policyService
|
private allowPersonalOwnership$ = this.policyService
|
||||||
.policyAppliesToActiveUser$(PolicyType.PersonalOwnership)
|
.policyAppliesToActiveUser$(PolicyType.PersonalOwnership)
|
||||||
@@ -41,12 +43,16 @@ export class AdminConsoleCipherFormConfigService implements CipherFormConfigServ
|
|||||||
filter((filter) => filter !== undefined),
|
filter((filter) => filter !== undefined),
|
||||||
);
|
);
|
||||||
|
|
||||||
private allOrganizations$ = this.organizationService.organizations$.pipe(
|
private allOrganizations$ = this.accountService.activeAccount$.pipe(
|
||||||
map((orgs) => {
|
switchMap((account) =>
|
||||||
return orgs.filter(
|
this.organizationService.organizations$(account?.id).pipe(
|
||||||
(o) => o.isMember && o.enabled && o.status === OrganizationUserStatusType.Confirmed,
|
map((orgs) => {
|
||||||
);
|
return orgs.filter(
|
||||||
}),
|
(o) => o.isMember && o.enabled && o.status === OrganizationUserStatusType.Confirmed,
|
||||||
|
);
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
private organization$ = combineLatest([this.allOrganizations$, this.organizationId$]).pipe(
|
private organization$ = combineLatest([this.allOrganizations$, this.organizationId$]).pipe(
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user