1
0
mirror of https://github.com/bitwarden/browser synced 2025-12-21 18:53:29 +00:00

Merge branch 'feature/sm-billing' into AC-1418-add-secrets-manager-manage-subscription-component

This commit is contained in:
Shane Melton
2023-06-27 15:23:14 -07:00
74 changed files with 1019 additions and 472 deletions

View File

@@ -6,6 +6,7 @@ import { OrganizationSsoResponse } from "../../../auth/models/response/organizat
import { OrganizationSubscriptionUpdateRequest } from "../../../billing/models/request/organization-subscription-update.request";
import { OrganizationTaxInfoUpdateRequest } from "../../../billing/models/request/organization-tax-info-update.request";
import { PaymentRequest } from "../../../billing/models/request/payment.request";
import { SecretsManagerSubscribeRequest } from "../../../billing/models/request/sm-subscribe.request";
import { BillingResponse } from "../../../billing/models/response/billing.response";
import { OrganizationSubscriptionResponse } from "../../../billing/models/response/organization-subscription.response";
import { PaymentResponse } from "../../../billing/models/response/payment.response";
@@ -16,7 +17,6 @@ import { StorageRequest } from "../../../models/request/storage.request";
import { VerifyBankRequest } from "../../../models/request/verify-bank.request";
import { ListResponse } from "../../../models/response/list.response";
import { OrganizationApiKeyType } from "../../enums";
import { OrganizationEnrollSecretsManagerRequest } from "../../models/request/organization/organization-enroll-secrets-manager.request";
import { OrganizationCreateRequest } from "../../models/request/organization-create.request";
import { OrganizationKeysRequest } from "../../models/request/organization-keys.request";
import { OrganizationUpdateRequest } from "../../models/request/organization-update.request";
@@ -37,7 +37,10 @@ export class OrganizationApiServiceAbstraction {
save: (id: string, request: OrganizationUpdateRequest) => Promise<OrganizationResponse>;
updatePayment: (id: string, request: PaymentRequest) => Promise<void>;
upgrade: (id: string, request: OrganizationUpgradeRequest) => Promise<PaymentResponse>;
updateSubscription: (id: string, request: OrganizationSubscriptionUpdateRequest) => Promise<void>;
updatePasswordManagerSeats: (
id: string,
request: OrganizationSubscriptionUpdateRequest
) => Promise<void>;
updateSeats: (id: string, request: SeatRequest) => Promise<PaymentResponse>;
updateStorage: (id: string, request: StorageRequest) => Promise<PaymentResponse>;
verifyBank: (id: string, request: VerifyBankRequest) => Promise<void>;
@@ -60,8 +63,5 @@ export class OrganizationApiServiceAbstraction {
getSso: (id: string) => Promise<OrganizationSsoResponse>;
updateSso: (id: string, request: OrganizationSsoRequest) => Promise<OrganizationSsoResponse>;
selfHostedSyncLicense: (id: string) => Promise<void>;
updateEnrollSecretsManager: (
id: string,
request: OrganizationEnrollSecretsManagerRequest
) => Promise<void>;
subscribeToSecretsManager: (id: string, request: SecretsManagerSubscribeRequest) => Promise<void>;
}

View File

@@ -23,4 +23,8 @@ export class OrganizationCreateRequest {
billingAddressState: string;
billingAddressPostalCode: string;
billingAddressCountry: string;
useSecretsManager: boolean;
additionalSmSeats: number;
additionalServiceAccounts: number;
}

View File

@@ -11,4 +11,8 @@ export class OrganizationUpgradeRequest {
billingAddressCountry: string;
billingAddressPostalCode: string;
keys: OrganizationKeysRequest;
useSecretsManager: boolean;
additionalSmSeats: number;
additionalServiceAccounts: number;
}

View File

@@ -1,3 +0,0 @@
export class OrganizationEnrollSecretsManagerRequest {
enabled: boolean;
}

View File

@@ -7,6 +7,7 @@ import { OrganizationSsoResponse } from "../../../auth/models/response/organizat
import { OrganizationSubscriptionUpdateRequest } from "../../../billing/models/request/organization-subscription-update.request";
import { OrganizationTaxInfoUpdateRequest } from "../../../billing/models/request/organization-tax-info-update.request";
import { PaymentRequest } from "../../../billing/models/request/payment.request";
import { SecretsManagerSubscribeRequest } from "../../../billing/models/request/sm-subscribe.request";
import { BillingResponse } from "../../../billing/models/response/billing.response";
import { OrganizationSubscriptionResponse } from "../../../billing/models/response/organization-subscription.response";
import { PaymentResponse } from "../../../billing/models/response/payment.response";
@@ -19,7 +20,6 @@ import { ListResponse } from "../../../models/response/list.response";
import { SyncService } from "../../../vault/abstractions/sync/sync.service.abstraction";
import { OrganizationApiServiceAbstraction } from "../../abstractions/organization/organization-api.service.abstraction";
import { OrganizationApiKeyType } from "../../enums";
import { OrganizationEnrollSecretsManagerRequest } from "../../models/request/organization/organization-enroll-secrets-manager.request";
import { OrganizationCreateRequest } from "../../models/request/organization-create.request";
import { OrganizationKeysRequest } from "../../models/request/organization-keys.request";
import { OrganizationUpdateRequest } from "../../models/request/organization-update.request";
@@ -120,7 +120,7 @@ export class OrganizationApiService implements OrganizationApiServiceAbstraction
return new PaymentResponse(r);
}
async updateSubscription(
async updatePasswordManagerSeats(
id: string,
request: OrganizationSubscriptionUpdateRequest
): Promise<void> {
@@ -294,13 +294,16 @@ export class OrganizationApiService implements OrganizationApiServiceAbstraction
);
}
async updateEnrollSecretsManager(id: string, request: OrganizationEnrollSecretsManagerRequest) {
await this.apiService.send(
async subscribeToSecretsManager(
id: string,
request: SecretsManagerSubscribeRequest
): Promise<void> {
return await this.apiService.send(
"POST",
"/organizations/" + id + "/enroll-secrets-manager",
"/organizations/" + id + "/subscribe-secrets-manager",
request,
true,
true
false
);
}
}

View File

@@ -304,13 +304,16 @@ export class AuthService implements AuthServiceAbstraction {
).encKey,
pubKey.buffer
);
const encryptedMasterPassword = await this.cryptoService.rsaEncrypt(
Utils.fromUtf8ToArray(await this.stateService.getKeyHash()),
pubKey.buffer
);
let encryptedMasterPassword = null;
if ((await this.stateService.getKeyHash()) != null) {
encryptedMasterPassword = await this.cryptoService.rsaEncrypt(
Utils.fromUtf8ToArray(await this.stateService.getKeyHash()),
pubKey.buffer
);
}
const request = new PasswordlessAuthRequest(
encryptedKey.encryptedString,
encryptedMasterPassword.encryptedString,
encryptedMasterPassword?.encryptedString,
await this.appIdService.getAppId(),
requestApproved
);

View File

@@ -0,0 +1,4 @@
export class SecretsManagerSubscribeRequest {
additionalSmSeats: number;
additionalServiceAccounts: number;
}

View File

@@ -6,9 +6,9 @@ import { BitwardenProductType } from "../../enums/bitwarden-product-type.enum";
export class PlanResponse extends BaseResponse {
type: PlanType;
product: ProductType;
bitwardenProduct: BitwardenProductType;
name: string;
isAnnual: boolean;
bitwardenProduct: BitwardenProductType;
nameLocalizationKey: string;
descriptionLocalizationKey: string;
canBeUsedByBusiness: boolean;
@@ -99,6 +99,7 @@ export class PlanResponse extends BaseResponse {
this.seatPrice = this.getResponseProperty("SeatPrice");
this.additionalStoragePricePerGb = this.getResponseProperty("AdditionalStoragePricePerGb");
this.premiumAccessOptionPrice = this.getResponseProperty("PremiumAccessOptionPrice");
this.bitwardenProduct = this.getResponseProperty("BitwardenProduct");
this.additionalPricePerServiceAccount = this.getResponseProperty(
"AdditionalPricePerServiceAccount"

View File

@@ -28,6 +28,7 @@ export abstract class EnvironmentService {
usUrls: Urls;
euUrls: Urls;
selectedRegion?: Region;
initialized = true;
hasBaseUrl: () => boolean;
getNotificationsUrl: () => string;

View File

@@ -12,6 +12,7 @@ export class EnvironmentService implements EnvironmentServiceAbstraction {
private readonly urlsSubject = new Subject<void>();
urls: Observable<void> = this.urlsSubject.asObservable();
selectedRegion?: Region;
initialized = true;
protected baseUrl: string;
protected webVaultUrl: string;
@@ -49,6 +50,9 @@ export class EnvironmentService implements EnvironmentServiceAbstraction {
this.stateService.activeAccount$
.pipe(
concatMap(async () => {
if (!this.initialized) {
return;
}
await this.setUrlsFromStorage();
})
)
@@ -157,22 +161,23 @@ export class EnvironmentService implements EnvironmentServiceAbstraction {
// fix environment urls for old users
if (savedUrls.base === "https://vault.bitwarden.com") {
this.setRegion(Region.US);
await this.setRegion(Region.US);
return;
}
if (savedUrls.base === "https://vault.bitwarden.eu") {
this.setRegion(Region.EU);
await this.setRegion(Region.EU);
return;
}
switch (region) {
case Region.EU:
this.setRegion(Region.EU);
await this.setRegion(Region.EU);
return;
case Region.US:
this.setRegion(Region.US);
await this.setRegion(Region.US);
return;
case Region.SelfHosted:
case null:
default:
this.baseUrl = envUrls.base = savedUrls.base;
this.webVaultUrl = savedUrls.webVault;
@@ -182,9 +187,9 @@ export class EnvironmentService implements EnvironmentServiceAbstraction {
this.notificationsUrl = savedUrls.notifications;
this.eventsUrl = envUrls.events = savedUrls.events;
this.keyConnectorUrl = savedUrls.keyConnector;
await this.setRegion(Region.SelfHosted);
// scimUrl is not saved to storage
this.urlsSubject.next();
this.setRegion(Region.SelfHosted);
break;
}
}
@@ -270,7 +275,7 @@ export class EnvironmentService implements EnvironmentServiceAbstraction {
case Region.SelfHosted:
// if user saves with empty fields, default to US
if (this.isEmpty()) {
this.setRegion(Region.US);
await this.setRegion(Region.US);
}
break;
}

View File

@@ -881,7 +881,7 @@ export class ApiService implements ApiServiceAbstraction {
// Plan APIs
async getPlans(): Promise<ListResponse<PlanResponse>> {
const r = await this.send("GET", "/plans/", null, false, true);
const r = await this.send("GET", "/plans/all", null, false, true);
return new ListResponse(r, PlanResponse);
}