Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.
import { formatDate } from "@angular/common";
import { Component, EventEmitter, Input, Output, OnInit } from "@angular/core";
import { ApiService } from "@bitwarden/common/abstractions/api.service";
import { I18nService } from "@bitwarden/common/abstractions/i18n.service";
import { LogService } from "@bitwarden/common/abstractions/log.service";
import { PlatformUtilsService } from "@bitwarden/common/abstractions/platformUtils.service";
import { Organization } from "@bitwarden/common/models/domain/organization";
@Component({
selector: "[sponsoring-org-row]",
templateUrl: "sponsoring-org-row.component.html",
})
export class SponsoringOrgRowComponent implements OnInit {
@Input() sponsoringOrg: Organization = null;
@Input() isSelfHosted = false;
@Output() sponsorshipRemoved = new EventEmitter();
statusMessage = "loading";
statusClass: "text-success" | "text-danger" = "text-success";
revokeSponsorshipPromise: Promise<any>;
resendEmailPromise: Promise<any>;
constructor(
private apiService: ApiService,
private i18nService: I18nService,
private logService: LogService,
private platformUtilsService: PlatformUtilsService
) {}
ngOnInit(): void {
this.setStatus(
this.isSelfHosted,
this.sponsoringOrg.familySponsorshipToDelete,
this.sponsoringOrg.familySponsorshipValidUntil,
this.sponsoringOrg.familySponsorshipLastSyncDate
);
}
async revokeSponsorship() {
try {
this.revokeSponsorshipPromise = this.doRevokeSponsorship();
await this.revokeSponsorshipPromise;
} catch (e) {
this.logService.error(e);
this.revokeSponsorshipPromise = null;
async resendEmail() {
this.resendEmailPromise = this.apiService.postResendSponsorshipOffer(this.sponsoringOrg.id);
await this.resendEmailPromise;
this.platformUtilsService.showToast("success", null, this.i18nService.t("emailSent"));
this.resendEmailPromise = null;
get isSentAwaitingSync() {
return this.isSelfHosted && !this.sponsoringOrg.familySponsorshipLastSyncDate;
private async doRevokeSponsorship() {
const isConfirmed = await this.platformUtilsService.showDialog(
this.i18nService.t("revokeSponsorshipConfirmation"),
`${this.i18nService.t("remove")} ${this.sponsoringOrg.familySponsorshipFriendlyName}?`,
this.i18nService.t("remove"),
this.i18nService.t("cancel"),
"warning"
if (!isConfirmed) {
return;
await this.apiService.deleteRevokeSponsorship(this.sponsoringOrg.id);
this.platformUtilsService.showToast("success", null, this.i18nService.t("reclaimedFreePlan"));
this.sponsorshipRemoved.emit();
private setStatus(
selfHosted: boolean,
toDelete?: boolean,
validUntil?: Date,
lastSyncDate?: Date
) {
/*
* Possible Statuses:
* Requested (self-hosted only)
* Sent
* Active
* RequestRevoke
* RevokeWhenExpired
*/
if (toDelete && validUntil) {
// They want to delete but there is a valid until date which means there is an active sponsorship
this.statusMessage = this.i18nService.t(
"revokeWhenExpired",
formatDate(validUntil, "MM/dd/yyyy", this.i18nService.locale)
this.statusClass = "text-danger";
} else if (toDelete) {
// They want to delete and we don't have a valid until date so we can
// this should only happen on a self-hosted install
this.statusMessage = this.i18nService.t("requestRemoved");
} else if (validUntil) {
// They don't want to delete and they have a valid until date
// that means they are actively sponsoring someone
this.statusMessage = this.i18nService.t("active");
this.statusClass = "text-success";
} else if (selfHosted && lastSyncDate) {
// We are on a self-hosted install and it has been synced but we have not gotten
// a valid until date so we can't know if they are actively sponsoring someone
this.statusMessage = this.i18nService.t("sent");
} else if (!selfHosted) {
// We are in cloud and all other status checks have been false therefore we have
// sent the request but it hasn't been accepted yet
} else {
// We are on a self-hosted install and we have not synced yet
this.statusMessage = this.i18nService.t("requested");