mirror of
https://github.com/bitwarden/browser.git
synced 2024-12-20 16:07:45 +01:00
[PM-13345]Add the new policy (#11894)
* Add the new policy
* Add the free family policy behind flag
* Patch build process
* Revert "Patch build process"
This reverts commit 4024e974b1
.
* [PM-13346] Email notification impacts (#11967)
* Changes error notification for disabled offer
* Add the feature to the change
* Add the missing dot
* Remove the authenicated endpoint
* Add the changes for error toast
* Resolve the lint issue
* rename file a correctly
* Remove the floating promise comments
* Delete unwanted comments
---------
Co-authored-by: Matt Bishop <mbishop@bitwarden.com>
This commit is contained in:
parent
0386b7f068
commit
c17f582768
@ -1,7 +1,12 @@
|
|||||||
import { Component } from "@angular/core";
|
import { Component, inject } from "@angular/core";
|
||||||
import { Params } from "@angular/router";
|
import { Params } from "@angular/router";
|
||||||
import { firstValueFrom } from "rxjs";
|
import { firstValueFrom } from "rxjs";
|
||||||
|
|
||||||
|
import { PolicyApiServiceAbstraction } from "@bitwarden/common/admin-console/abstractions/policy/policy-api.service.abstraction";
|
||||||
|
import { OrganizationSponsorshipResponse } from "@bitwarden/common/admin-console/models/response/organization-sponsorship.response";
|
||||||
|
import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
|
||||||
|
import { ToastService } from "@bitwarden/components";
|
||||||
|
|
||||||
import { BaseAcceptComponent } from "../../../common/base.accept.component";
|
import { BaseAcceptComponent } from "../../../common/base.accept.component";
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -19,17 +24,18 @@ export class AcceptFamilySponsorshipComponent extends BaseAcceptComponent {
|
|||||||
|
|
||||||
requiredParameters = ["email", "token"];
|
requiredParameters = ["email", "token"];
|
||||||
|
|
||||||
|
policyResponse!: OrganizationSponsorshipResponse;
|
||||||
|
policyApiService = inject(PolicyApiServiceAbstraction);
|
||||||
|
configService = inject(ConfigService);
|
||||||
|
toastService = inject(ToastService);
|
||||||
|
|
||||||
async authedHandler(qParams: Params) {
|
async authedHandler(qParams: Params) {
|
||||||
// FIXME: Verify that this floating promise is intentional. If it is, add an explanatory comment and ensure there is proper error handling.
|
await this.router.navigate(["/setup/families-for-enterprise"], { queryParams: qParams });
|
||||||
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
|
||||||
this.router.navigate(["/setup/families-for-enterprise"], { queryParams: qParams });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async unauthedHandler(qParams: Params) {
|
async unauthedHandler(qParams: Params) {
|
||||||
if (!qParams.register) {
|
if (!qParams.register) {
|
||||||
// FIXME: Verify that this floating promise is intentional. If it is, add an explanatory comment and ensure there is proper error handling.
|
await this.router.navigate(["/login"], { queryParams: { email: qParams.email } });
|
||||||
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
|
||||||
this.router.navigate(["/login"], { queryParams: { email: qParams.email } });
|
|
||||||
} else {
|
} else {
|
||||||
// TODO: update logic when email verification flag is removed
|
// TODO: update logic when email verification flag is removed
|
||||||
let queryParams: Params;
|
let queryParams: Params;
|
||||||
|
@ -9,6 +9,7 @@ import { OrganizationService } from "@bitwarden/common/admin-console/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 { 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 { 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";
|
||||||
@ -51,6 +52,7 @@ export class FamiliesForEnterpriseSetupComponent implements OnInit, OnDestroy {
|
|||||||
|
|
||||||
showNewOrganization = false;
|
showNewOrganization = false;
|
||||||
_organizationPlansComponent: OrganizationPlansComponent;
|
_organizationPlansComponent: OrganizationPlansComponent;
|
||||||
|
preValidateSponsorshipResponse: PreValidateSponsorshipResponse;
|
||||||
_selectedFamilyOrganizationId = "";
|
_selectedFamilyOrganizationId = "";
|
||||||
|
|
||||||
private _destroy = new Subject<void>();
|
private _destroy = new Subject<void>();
|
||||||
@ -92,7 +94,20 @@ export class FamiliesForEnterpriseSetupComponent implements OnInit, OnDestroy {
|
|||||||
this.token = qParams.token;
|
this.token = qParams.token;
|
||||||
|
|
||||||
await this.syncService.fullSync(true);
|
await this.syncService.fullSync(true);
|
||||||
this.badToken = !(await this.apiService.postPreValidateSponsorshipToken(this.token));
|
|
||||||
|
this.preValidateSponsorshipResponse = await this.apiService.postPreValidateSponsorshipToken(
|
||||||
|
this.token,
|
||||||
|
);
|
||||||
|
if (this.preValidateSponsorshipResponse.isFreeFamilyPolicyEnabled) {
|
||||||
|
this.toastService.showToast({
|
||||||
|
variant: "error",
|
||||||
|
title: this.i18nService.t("errorOccured"),
|
||||||
|
message: this.i18nService.t("offerNoLongerValid"),
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
this.badToken = !this.preValidateSponsorshipResponse.isTokenValid;
|
||||||
|
}
|
||||||
|
|
||||||
this.loading = false;
|
this.loading = false;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -6376,6 +6376,9 @@
|
|||||||
"idpSingleSignOnServiceUrlRequired": {
|
"idpSingleSignOnServiceUrlRequired": {
|
||||||
"message": "Required if Entity ID is not a URL."
|
"message": "Required if Entity ID is not a URL."
|
||||||
},
|
},
|
||||||
|
"offerNoLongerValid": {
|
||||||
|
"message": "This offer is no longer valid. Contact your organization administrators for more information."
|
||||||
|
},
|
||||||
"openIdOptionalCustomizations": {
|
"openIdOptionalCustomizations": {
|
||||||
"message": "Optional customizations"
|
"message": "Optional customizations"
|
||||||
},
|
},
|
||||||
@ -9727,5 +9730,11 @@
|
|||||||
},
|
},
|
||||||
"deletedSuccessfully": {
|
"deletedSuccessfully": {
|
||||||
"message": "Deleted successfully"
|
"message": "Deleted successfully"
|
||||||
|
},
|
||||||
|
"freeFamiliesSponsorship": {
|
||||||
|
"message": "Remove Free Bitwarden Families sponsorship"
|
||||||
|
},
|
||||||
|
"freeFamiliesSponsorshipPolicyDesc": {
|
||||||
|
"message": "Do not allow members to redeem a Families plan through this organization."
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,7 @@ import { ActivateAutofillPolicy } from "./admin-console/policies/activate-autofi
|
|||||||
import { AutomaticAppLoginPolicy } from "./admin-console/policies/automatic-app-login.component";
|
import { AutomaticAppLoginPolicy } from "./admin-console/policies/automatic-app-login.component";
|
||||||
import { DisablePersonalVaultExportPolicy } from "./admin-console/policies/disable-personal-vault-export.component";
|
import { DisablePersonalVaultExportPolicy } from "./admin-console/policies/disable-personal-vault-export.component";
|
||||||
import { MaximumVaultTimeoutPolicy } from "./admin-console/policies/maximum-vault-timeout.component";
|
import { MaximumVaultTimeoutPolicy } from "./admin-console/policies/maximum-vault-timeout.component";
|
||||||
|
import { FreeFamiliesSponsorshipPolicy } from "./billing/policies/free-families-sponsorship.component";
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: "app-root",
|
selector: "app-root",
|
||||||
@ -19,9 +20,17 @@ export class AppComponent extends BaseAppComponent implements OnInit {
|
|||||||
this.policyListService.addPolicies([
|
this.policyListService.addPolicies([
|
||||||
new MaximumVaultTimeoutPolicy(),
|
new MaximumVaultTimeoutPolicy(),
|
||||||
new DisablePersonalVaultExportPolicy(),
|
new DisablePersonalVaultExportPolicy(),
|
||||||
new ActivateAutofillPolicy(),
|
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
this.configService
|
||||||
|
.getFeatureFlag(FeatureFlag.DisableFreeFamiliesSponsorship)
|
||||||
|
.then((isFreeFamilyEnabled) => {
|
||||||
|
if (isFreeFamilyEnabled) {
|
||||||
|
this.policyListService.addPolicies([new FreeFamiliesSponsorshipPolicy()]);
|
||||||
|
}
|
||||||
|
this.policyListService.addPolicies([new ActivateAutofillPolicy()]);
|
||||||
|
});
|
||||||
|
|
||||||
this.configService.getFeatureFlag(FeatureFlag.IdpAutoSubmitLogin).then((enabled) => {
|
this.configService.getFeatureFlag(FeatureFlag.IdpAutoSubmitLogin).then((enabled) => {
|
||||||
if (
|
if (
|
||||||
enabled &&
|
enabled &&
|
||||||
|
@ -19,6 +19,7 @@ import { DisablePersonalVaultExportPolicyComponent } from "./admin-console/polic
|
|||||||
import { MaximumVaultTimeoutPolicyComponent } from "./admin-console/policies/maximum-vault-timeout.component";
|
import { MaximumVaultTimeoutPolicyComponent } from "./admin-console/policies/maximum-vault-timeout.component";
|
||||||
import { AppRoutingModule } from "./app-routing.module";
|
import { AppRoutingModule } from "./app-routing.module";
|
||||||
import { AppComponent } from "./app.component";
|
import { AppComponent } from "./app.component";
|
||||||
|
import { FreeFamiliesSponsorshipPolicyComponent } from "./billing/policies/free-families-sponsorship.component";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is the AppModule for the commercial version of Bitwarden.
|
* This is the AppModule for the commercial version of Bitwarden.
|
||||||
@ -49,6 +50,7 @@ import { AppComponent } from "./app.component";
|
|||||||
MaximumVaultTimeoutPolicyComponent,
|
MaximumVaultTimeoutPolicyComponent,
|
||||||
ActivateAutofillPolicyComponent,
|
ActivateAutofillPolicyComponent,
|
||||||
AutomaticAppLoginPolicyComponent,
|
AutomaticAppLoginPolicyComponent,
|
||||||
|
FreeFamiliesSponsorshipPolicyComponent,
|
||||||
],
|
],
|
||||||
bootstrap: [AppComponent],
|
bootstrap: [AppComponent],
|
||||||
})
|
})
|
||||||
|
@ -0,0 +1,4 @@
|
|||||||
|
<bit-form-control>
|
||||||
|
<input type="checkbox" id="enabled" bitCheckbox [formControl]="enabled" />
|
||||||
|
<bit-label>{{ "turnOn" | i18n }}</bit-label>
|
||||||
|
</bit-form-control>
|
@ -0,0 +1,20 @@
|
|||||||
|
import { Component } from "@angular/core";
|
||||||
|
|
||||||
|
import { PolicyType } from "@bitwarden/common/admin-console/enums";
|
||||||
|
import {
|
||||||
|
BasePolicy,
|
||||||
|
BasePolicyComponent,
|
||||||
|
} from "@bitwarden/web-vault/app/admin-console/organizations/policies/base-policy.component";
|
||||||
|
|
||||||
|
export class FreeFamiliesSponsorshipPolicy extends BasePolicy {
|
||||||
|
name = "freeFamiliesSponsorship";
|
||||||
|
description = "freeFamiliesSponsorshipPolicyDesc";
|
||||||
|
type = PolicyType.FreeFamiliesSponsorshipPolicy;
|
||||||
|
component = FreeFamiliesSponsorshipPolicyComponent;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: "policy-personal-ownership",
|
||||||
|
templateUrl: "free-families-sponsorship.component.html",
|
||||||
|
})
|
||||||
|
export class FreeFamiliesSponsorshipPolicyComponent extends BasePolicyComponent {}
|
@ -24,6 +24,7 @@ import {
|
|||||||
} from "../admin-console/models/response/organization-connection.response";
|
} from "../admin-console/models/response/organization-connection.response";
|
||||||
import { OrganizationExportResponse } from "../admin-console/models/response/organization-export.response";
|
import { OrganizationExportResponse } from "../admin-console/models/response/organization-export.response";
|
||||||
import { OrganizationSponsorshipSyncStatusResponse } from "../admin-console/models/response/organization-sponsorship-sync-status.response";
|
import { OrganizationSponsorshipSyncStatusResponse } from "../admin-console/models/response/organization-sponsorship-sync-status.response";
|
||||||
|
import { PreValidateSponsorshipResponse } from "../admin-console/models/response/pre-validate-sponsorship.response";
|
||||||
import {
|
import {
|
||||||
ProviderOrganizationOrganizationDetailsResponse,
|
ProviderOrganizationOrganizationDetailsResponse,
|
||||||
ProviderOrganizationResponse,
|
ProviderOrganizationResponse,
|
||||||
@ -490,7 +491,9 @@ export abstract class ApiService {
|
|||||||
) => Promise<OrganizationSponsorshipSyncStatusResponse>;
|
) => Promise<OrganizationSponsorshipSyncStatusResponse>;
|
||||||
deleteRevokeSponsorship: (sponsoringOrganizationId: string) => Promise<void>;
|
deleteRevokeSponsorship: (sponsoringOrganizationId: string) => Promise<void>;
|
||||||
deleteRemoveSponsorship: (sponsoringOrgId: string) => Promise<void>;
|
deleteRemoveSponsorship: (sponsoringOrgId: string) => Promise<void>;
|
||||||
postPreValidateSponsorshipToken: (sponsorshipToken: string) => Promise<boolean>;
|
postPreValidateSponsorshipToken: (
|
||||||
|
sponsorshipToken: string,
|
||||||
|
) => Promise<PreValidateSponsorshipResponse>;
|
||||||
postRedeemSponsorship: (
|
postRedeemSponsorship: (
|
||||||
sponsorshipToken: string,
|
sponsorshipToken: string,
|
||||||
request: OrganizationSponsorshipRedeemRequest,
|
request: OrganizationSponsorshipRedeemRequest,
|
||||||
|
@ -12,4 +12,5 @@ export enum PolicyType {
|
|||||||
DisablePersonalVaultExport = 10, // Disable personal vault export
|
DisablePersonalVaultExport = 10, // Disable personal vault export
|
||||||
ActivateAutofill = 11, // Activates autofill with page load on the browser extension
|
ActivateAutofill = 11, // Activates autofill with page load on the browser extension
|
||||||
AutomaticAppLogIn = 12, // Enables automatic log in of apps from configured identity provider
|
AutomaticAppLogIn = 12, // Enables automatic log in of apps from configured identity provider
|
||||||
|
FreeFamiliesSponsorshipPolicy = 13, // Disables free families plan for organization
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,10 @@
|
|||||||
|
import { BaseResponse } from "../../../models/response/base.response";
|
||||||
|
|
||||||
|
export class OrganizationSponsorshipResponse extends BaseResponse {
|
||||||
|
isPolicyEnabled: string;
|
||||||
|
|
||||||
|
constructor(response: any) {
|
||||||
|
super(response);
|
||||||
|
this.isPolicyEnabled = this.getResponseProperty("IsPolicyEnabled");
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,12 @@
|
|||||||
|
import { BaseResponse } from "../../../models/response/base.response";
|
||||||
|
|
||||||
|
export class PreValidateSponsorshipResponse extends BaseResponse {
|
||||||
|
isTokenValid: boolean;
|
||||||
|
isFreeFamilyPolicyEnabled: boolean;
|
||||||
|
|
||||||
|
constructor(response: any) {
|
||||||
|
super(response);
|
||||||
|
this.isTokenValid = this.getResponseProperty("IsTokenValid");
|
||||||
|
this.isFreeFamilyPolicyEnabled = this.getResponseProperty("IsFreeFamilyPolicyEnabled");
|
||||||
|
}
|
||||||
|
}
|
@ -39,6 +39,7 @@ export enum FeatureFlag {
|
|||||||
SecurityTasks = "security-tasks",
|
SecurityTasks = "security-tasks",
|
||||||
NewDeviceVerificationTemporaryDismiss = "new-device-temporary-dismiss",
|
NewDeviceVerificationTemporaryDismiss = "new-device-temporary-dismiss",
|
||||||
NewDeviceVerificationPermanentDismiss = "new-device-permanent-dismiss",
|
NewDeviceVerificationPermanentDismiss = "new-device-permanent-dismiss",
|
||||||
|
DisableFreeFamiliesSponsorship = "PM-12274-disable-free-families-sponsorship",
|
||||||
}
|
}
|
||||||
|
|
||||||
export type AllowedFeatureFlagTypes = boolean | number | string;
|
export type AllowedFeatureFlagTypes = boolean | number | string;
|
||||||
@ -88,6 +89,7 @@ export const DefaultFeatureFlagValue = {
|
|||||||
[FeatureFlag.SecurityTasks]: FALSE,
|
[FeatureFlag.SecurityTasks]: FALSE,
|
||||||
[FeatureFlag.NewDeviceVerificationTemporaryDismiss]: FALSE,
|
[FeatureFlag.NewDeviceVerificationTemporaryDismiss]: FALSE,
|
||||||
[FeatureFlag.NewDeviceVerificationPermanentDismiss]: FALSE,
|
[FeatureFlag.NewDeviceVerificationPermanentDismiss]: FALSE,
|
||||||
|
[FeatureFlag.DisableFreeFamiliesSponsorship]: FALSE,
|
||||||
} satisfies Record<FeatureFlag, AllowedFeatureFlagTypes>;
|
} satisfies Record<FeatureFlag, AllowedFeatureFlagTypes>;
|
||||||
|
|
||||||
export type DefaultFeatureFlagValueType = typeof DefaultFeatureFlagValue;
|
export type DefaultFeatureFlagValueType = typeof DefaultFeatureFlagValue;
|
||||||
|
@ -29,6 +29,7 @@ import {
|
|||||||
} from "../admin-console/models/response/organization-connection.response";
|
} from "../admin-console/models/response/organization-connection.response";
|
||||||
import { OrganizationExportResponse } from "../admin-console/models/response/organization-export.response";
|
import { OrganizationExportResponse } from "../admin-console/models/response/organization-export.response";
|
||||||
import { OrganizationSponsorshipSyncStatusResponse } from "../admin-console/models/response/organization-sponsorship-sync-status.response";
|
import { OrganizationSponsorshipSyncStatusResponse } from "../admin-console/models/response/organization-sponsorship-sync-status.response";
|
||||||
|
import { PreValidateSponsorshipResponse } from "../admin-console/models/response/pre-validate-sponsorship.response";
|
||||||
import {
|
import {
|
||||||
ProviderOrganizationOrganizationDetailsResponse,
|
ProviderOrganizationOrganizationDetailsResponse,
|
||||||
ProviderOrganizationResponse,
|
ProviderOrganizationResponse,
|
||||||
@ -1680,8 +1681,10 @@ export class ApiService implements ApiServiceAbstraction {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
async postPreValidateSponsorshipToken(sponsorshipToken: string): Promise<boolean> {
|
async postPreValidateSponsorshipToken(
|
||||||
const r = await this.send(
|
sponsorshipToken: string,
|
||||||
|
): Promise<PreValidateSponsorshipResponse> {
|
||||||
|
const response = await this.send(
|
||||||
"POST",
|
"POST",
|
||||||
"/organization/sponsorship/validate-token?sponsorshipToken=" +
|
"/organization/sponsorship/validate-token?sponsorshipToken=" +
|
||||||
encodeURIComponent(sponsorshipToken),
|
encodeURIComponent(sponsorshipToken),
|
||||||
@ -1689,7 +1692,8 @@ export class ApiService implements ApiServiceAbstraction {
|
|||||||
true,
|
true,
|
||||||
true,
|
true,
|
||||||
);
|
);
|
||||||
return r as boolean;
|
|
||||||
|
return new PreValidateSponsorshipResponse(response);
|
||||||
}
|
}
|
||||||
|
|
||||||
async postRedeemSponsorship(
|
async postRedeemSponsorship(
|
||||||
|
Loading…
Reference in New Issue
Block a user