mirror of
https://github.com/bitwarden/browser
synced 2026-01-16 23:43:37 +00:00
Refactor environment service to emit a single observable. This required significant changes to how the environment service behaves and tackles much of the tech debt planned for it.
183 lines
6.5 KiB
TypeScript
183 lines
6.5 KiB
TypeScript
import { Component, OnDestroy, OnInit } from "@angular/core";
|
|
import { FormControl, FormGroup } from "@angular/forms";
|
|
import { ActivatedRoute } from "@angular/router";
|
|
import { concatMap, firstValueFrom, Subject, takeUntil } from "rxjs";
|
|
|
|
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
|
import { OrganizationApiServiceAbstraction } from "@bitwarden/common/admin-console/abstractions/organization/organization-api.service.abstraction";
|
|
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
|
import { OrganizationConnectionType } from "@bitwarden/common/admin-console/enums";
|
|
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
|
|
import { OrganizationConnectionResponse } from "@bitwarden/common/admin-console/models/response/organization-connection.response";
|
|
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 { EnvironmentService } from "@bitwarden/common/platform/abstractions/environment.service";
|
|
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
|
import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service";
|
|
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
|
import { DialogService } from "@bitwarden/components";
|
|
|
|
import { BillingSyncKeyComponent } from "./billing-sync-key.component";
|
|
|
|
enum LicenseOptions {
|
|
SYNC = 0,
|
|
UPLOAD = 1,
|
|
}
|
|
|
|
@Component({
|
|
templateUrl: "organization-subscription-selfhost.component.html",
|
|
})
|
|
export class OrganizationSubscriptionSelfhostComponent implements OnInit, OnDestroy {
|
|
subscription: SelfHostedOrganizationSubscriptionView;
|
|
organizationId: string;
|
|
userOrg: Organization;
|
|
cloudWebVaultUrl: string;
|
|
|
|
licenseOptions = LicenseOptions;
|
|
form = new FormGroup({
|
|
updateMethod: new FormControl(LicenseOptions.UPLOAD),
|
|
});
|
|
|
|
disableLicenseSyncControl = false;
|
|
|
|
firstLoaded = false;
|
|
loading = false;
|
|
|
|
private _existingBillingSyncConnection: OrganizationConnectionResponse<BillingSyncConfigApi>;
|
|
|
|
private destroy$ = new Subject<void>();
|
|
|
|
set existingBillingSyncConnection(value: OrganizationConnectionResponse<BillingSyncConfigApi>) {
|
|
this._existingBillingSyncConnection = value;
|
|
|
|
this.form
|
|
.get("updateMethod")
|
|
.setValue(this.billingSyncEnabled ? LicenseOptions.SYNC : LicenseOptions.UPLOAD);
|
|
}
|
|
|
|
get existingBillingSyncConnection() {
|
|
return this._existingBillingSyncConnection;
|
|
}
|
|
|
|
get billingSyncEnabled() {
|
|
return this.existingBillingSyncConnection?.enabled;
|
|
}
|
|
|
|
/**
|
|
* Render the subscription as expired.
|
|
*/
|
|
get showAsExpired() {
|
|
return this.subscription.hasSeparateGracePeriod
|
|
? this.subscription.isExpiredWithoutGracePeriod
|
|
: this.subscription.isExpiredAndOutsideGracePeriod;
|
|
}
|
|
|
|
constructor(
|
|
private messagingService: MessagingService,
|
|
private apiService: ApiService,
|
|
private organizationService: OrganizationService,
|
|
private route: ActivatedRoute,
|
|
private organizationApiService: OrganizationApiServiceAbstraction,
|
|
private platformUtilsService: PlatformUtilsService,
|
|
private i18nService: I18nService,
|
|
private environmentService: EnvironmentService,
|
|
private dialogService: DialogService,
|
|
) {}
|
|
|
|
async ngOnInit() {
|
|
this.cloudWebVaultUrl = await firstValueFrom(this.environmentService.cloudWebVaultUrl$);
|
|
|
|
this.route.params
|
|
.pipe(
|
|
concatMap(async (params) => {
|
|
this.organizationId = params.organizationId;
|
|
await this.load();
|
|
await this.loadOrganizationConnection();
|
|
this.firstLoaded = true;
|
|
}),
|
|
takeUntil(this.destroy$),
|
|
)
|
|
.subscribe();
|
|
}
|
|
|
|
ngOnDestroy() {
|
|
this.destroy$.next();
|
|
this.destroy$.complete();
|
|
}
|
|
|
|
async load() {
|
|
if (this.loading) {
|
|
return;
|
|
}
|
|
this.loading = true;
|
|
this.userOrg = await this.organizationService.get(this.organizationId);
|
|
if (this.userOrg.canViewSubscription) {
|
|
const subscriptionResponse = await this.organizationApiService.getSubscription(
|
|
this.organizationId,
|
|
);
|
|
this.subscription = new SelfHostedOrganizationSubscriptionView(subscriptionResponse);
|
|
}
|
|
|
|
this.loading = false;
|
|
}
|
|
|
|
async loadOrganizationConnection() {
|
|
if (!this.firstLoaded) {
|
|
const cloudCommunicationEnabled = await this.apiService.getCloudCommunicationsEnabled();
|
|
this.disableLicenseSyncControl = !cloudCommunicationEnabled;
|
|
}
|
|
|
|
if (this.disableLicenseSyncControl) {
|
|
return;
|
|
}
|
|
|
|
this.existingBillingSyncConnection = await this.apiService.getOrganizationConnection(
|
|
this.organizationId,
|
|
OrganizationConnectionType.CloudBillingSync,
|
|
BillingSyncConfigApi,
|
|
);
|
|
}
|
|
|
|
licenseUploaded() {
|
|
// 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
|
|
this.load();
|
|
this.messagingService.send("updatedOrgLicense");
|
|
}
|
|
|
|
manageBillingSyncSelfHosted() {
|
|
BillingSyncKeyComponent.open(this.dialogService, {
|
|
entityId: this.organizationId,
|
|
existingConnectionId: this.existingBillingSyncConnection?.id,
|
|
billingSyncKey: this.existingBillingSyncConnection?.config?.billingSyncKey,
|
|
setParentConnection: (connection: OrganizationConnectionResponse<BillingSyncConfigApi>) => {
|
|
this.existingBillingSyncConnection = connection;
|
|
},
|
|
});
|
|
}
|
|
|
|
syncLicense = async () => {
|
|
this.form.get("updateMethod").setValue(LicenseOptions.SYNC);
|
|
await this.organizationApiService.selfHostedSyncLicense(this.organizationId);
|
|
|
|
// 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
|
|
this.load();
|
|
await this.loadOrganizationConnection();
|
|
this.messagingService.send("updatedOrgLicense");
|
|
this.platformUtilsService.showToast("success", null, this.i18nService.t("licenseSyncSuccess"));
|
|
};
|
|
|
|
get billingSyncSetUp() {
|
|
return this.existingBillingSyncConnection?.id != null;
|
|
}
|
|
|
|
get updateMethod() {
|
|
return this.form.get("updateMethod").value;
|
|
}
|
|
|
|
get lastLicenseSync() {
|
|
return this.existingBillingSyncConnection?.config?.lastLicenseSync;
|
|
}
|
|
}
|