mirror of
https://github.com/bitwarden/browser
synced 2025-12-22 03:03:43 +00:00
* [AC-1423] Update organization subscription cloud page (#5614) * [AC-1423] Add ProgressModule to shared.module.ts * [AC-1423] Update cloud subscription page styles - Remove bootstrap styles - Use CL components where applicable - Use CL typography directives - Update heading levels to prepare for new SM sections * [AC-1423] Add usePasswordManager boolean to organization domain * [AC-1423] Introduce BitwardenProductType enum * [AC-1423] Update Organization subscription line items - Add product type prefix - Indent addon services like additional storage and service accounts - Show line items for free plans * [AC-1423] Simply sort function * [AC-1423] Remove header border * [AC-1423] Make "Password Manager" the default fallback for product name * [AC-1420] Add Secrets Manager subscribe component (#5617) * [AC-1418] Add secrets manager manage subscription component (#5661) * [AC-1423] Add minWidth input to bit-progress component * [AC-1423] Add ProgressModule to shared.module.ts * [AC-1423] Update cloud subscription page styles - Remove bootstrap styles - Use CL components where applicable - Use CL typography directives - Update heading levels to prepare for new SM sections * [AC-1423] Add usePasswordManager boolean to organization domain * [AC-1423] Introduce BitwardenProductType enum * [AC-1423] Update Organization subscription line items - Add product type prefix - Indent addon services like additional storage and service accounts - Show line items for free plans * [AC-1423] Simply sort function * [AC-1423] Remove header border * [AC-1423] Remove redundant condition * [AC-1423] Remove ineffective div * [AC-1423] Make "Password Manager" the default fallback for product name * Revert "[AC-1423] Add minWidth input to bit-progress component" This reverts commit95b2223a30. * [AC-1423] Remove minWidth attribute * [AC-1423] Switch to AddonProductType enum instead of boolean * Revert "[AC-1423] Switch to AddonProductType enum instead of boolean" This reverts commit204f64b4e7. * [AC-1423] Tweak sorting comment * [AC-1418] Add initial SecretsManagerAdjustSubscription component * [AC-1418] Add initial SM adjustment form * [AC-1418] Adjust organization-subscription-update.request.ts to support both PM and SM * [AC-1418] Rename service account fields in the options interface * [AC-1418] Add api service call to update SM subscription * [AC-1418] Cleanup form html * [AC-1418] Add missing SM plan properties * [AC-1418] Add SM subscription adjust form and logic to hide it * [AC-1418] Add better docs to options interface * [AC-1418] Fix conflicting required/optional labels for auto-scaling limits * [AC-1418] Adjust labels and appearance to better match design * [AC-1418] Use the SM plan for billing interval * [AC-1418] Hide SM billing adjustment component behind feature flag * [AC-1418] Update request model to match server * [AC-1418] Cleanup BitwardenProductType after merge Add to barrel file and update applicable imports. * [AC-1418] Revert change to update PM subscription request model * [AC-1418] Add new update SM subscription request model * [AC-1418] Add new service method to update SM subscription * [AC-1418] Use new model and service method * [AC-1418] Cleanup SM subscription UI flags * [AC-1418] Move SM adjust subscription component into SM billing module * [AC-1418] Update SM seat count minimum to 1 * [AC-1418] Add missing currency codes * [AC-1418] Simplify monthly price calculation * [AC-1418] Increase PM adjust subscription form input width * [AC-1418] Add check for null subscription --------- Co-authored-by: Thomas Rittson <31796059+eliykat@users.noreply.github.com> * add the additional properties (#5743) * Allow autoscale limits to be removed, update naming (#5781) * [AC-1488] Store Organization.SmServiceAccounts as total not additional (#5784) * Allow autoscale limits to be removed, update naming * Display additional service accounts only --------- Co-authored-by: Shane Melton <smelton@bitwarden.com> * [AC-1473] SM beta ending callout (#5719) * [AC-1423] Add minWidth input to bit-progress component * [AC-1423] Add ProgressModule to shared.module.ts * [AC-1423] Update cloud subscription page styles - Remove bootstrap styles - Use CL components where applicable - Use CL typography directives - Update heading levels to prepare for new SM sections * [AC-1423] Add usePasswordManager boolean to organization domain * [AC-1423] Introduce BitwardenProductType enum * [AC-1423] Update Organization subscription line items - Add product type prefix - Indent addon services like additional storage and service accounts - Show line items for free plans * [AC-1423] Simply sort function * [AC-1423] Remove header border * [AC-1423] Remove redundant condition * [AC-1423] Remove ineffective div * [AC-1423] Make "Password Manager" the default fallback for product name * Revert "[AC-1423] Add minWidth input to bit-progress component" This reverts commit95b2223a30. * [AC-1423] Remove minWidth attribute * [AC-1423] Switch to AddonProductType enum instead of boolean * Revert "[AC-1423] Switch to AddonProductType enum instead of boolean" This reverts commit204f64b4e7. * [AC-1423] Tweak sorting comment * [AC-1418] Add initial SecretsManagerAdjustSubscription component * [AC-1418] Add initial SM adjustment form * [AC-1418] Adjust organization-subscription-update.request.ts to support both PM and SM * [AC-1418] Rename service account fields in the options interface * [AC-1418] Add api service call to update SM subscription * [AC-1418] Cleanup form html * [AC-1418] Add missing SM plan properties * [AC-1418] Add SM subscription adjust form and logic to hide it * [AC-1418] Add better docs to options interface * [AC-1418] Fix conflicting required/optional labels for auto-scaling limits * [AC-1418] Adjust labels and appearance to better match design * [AC-1418] Use the SM plan for billing interval * [AC-1418] Hide SM billing adjustment component behind feature flag * [AC-1418] Update request model to match server * [AC-1418] Cleanup BitwardenProductType after merge Add to barrel file and update applicable imports. * [AC-1418] Revert change to update PM subscription request model * [AC-1418] Add new update SM subscription request model * [AC-1418] Add new service method to update SM subscription * [AC-1418] Use new model and service method * [AC-1418] Cleanup SM subscription UI flags * [AC-1418] Move SM adjust subscription component into SM billing module * [AC-1418] Update SM seat count minimum to 1 * [AC-1418] Add missing currency codes * [AC-1418] Simplify monthly price calculation * add daysRemaining util function and unit tests * [AC-1474] update organization models to include SM beta flag * add SM beta callout to org subscription page * update messages.json * remove beta field from profile org response * improve daysRemaining code clarity * set SM beta in org model constructor * tweak free SM row visibility * refactor callout description * Revert "remove beta field from profile org response" This reverts commit6c6249e1ec. * fix dates * [AC-1468]: hide adjust SM component if beta user * add sm beta field to org sub response; remove everywhere else * fix copy --------- Co-authored-by: Shane Melton <smelton@bitwarden.com> Co-authored-by: Thomas Rittson <31796059+eliykat@users.noreply.github.com> Co-authored-by: Thomas Rittson <trittson@bitwarden.com> * [AC-1531] Fix SM subscribe component not showing in free org billing tab (#5848) Also: * Fix spacing in layout * Send zero values for free plans * Fix: properly delete enroll component * remove the beta end message for free org (#5877) * [AC-1458] Update local organization data after subscribing to Secrets Manager (#5888) * [AC-1567] Fix max additional service account cost estimate (#5923) * Fix max additional service account cost estimate * Update i18n string ref * Make i18n string keys consistent * [AC-1461] Secrets Manager seat autoscaling cleanup (#5924) * Remove unused return value from putOrganizationUserBulkEnableSecretsManager * Fix service account limit validator (#5926) * Updated Utils.daysRemaining method to calculate result using Math.floor and updated unit tests. --------- Co-authored-by: Shane Melton <smelton@bitwarden.com> Co-authored-by: cyprain-okeke <108260115+cyprain-okeke@users.noreply.github.com> Co-authored-by: Rui Tome <rtome@bitwarden.com> Co-authored-by: Will Martin <contact@willmartian.com> Co-authored-by: Álison Fernandes <vvolkgang@users.noreply.github.com> Co-authored-by: Rui Tomé <108268980+r-tome@users.noreply.github.com>
326 lines
11 KiB
TypeScript
326 lines
11 KiB
TypeScript
import { ApiService } from "../../../abstractions/api.service";
|
|
import { OrganizationApiKeyRequest } from "../../../admin-console/models/request/organization-api-key.request";
|
|
import { OrganizationSsoRequest } from "../../../auth/models/request/organization-sso.request";
|
|
import { SecretVerificationRequest } from "../../../auth/models/request/secret-verification.request";
|
|
import { ApiKeyResponse } from "../../../auth/models/response/api-key.response";
|
|
import { OrganizationSsoResponse } from "../../../auth/models/response/organization-sso.response";
|
|
import { OrganizationSmSubscriptionUpdateRequest } from "../../../billing/models/request/organization-sm-subscription-update.request";
|
|
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";
|
|
import { TaxInfoResponse } from "../../../billing/models/response/tax-info.response";
|
|
import { ImportDirectoryRequest } from "../../../models/request/import-directory.request";
|
|
import { SeatRequest } from "../../../models/request/seat.request";
|
|
import { StorageRequest } from "../../../models/request/storage.request";
|
|
import { VerifyBankRequest } from "../../../models/request/verify-bank.request";
|
|
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 { OrganizationCreateRequest } from "../../models/request/organization-create.request";
|
|
import { OrganizationKeysRequest } from "../../models/request/organization-keys.request";
|
|
import { OrganizationUpdateRequest } from "../../models/request/organization-update.request";
|
|
import { OrganizationUpgradeRequest } from "../../models/request/organization-upgrade.request";
|
|
import { OrganizationApiKeyInformationResponse } from "../../models/response/organization-api-key-information.response";
|
|
import { OrganizationAutoEnrollStatusResponse } from "../../models/response/organization-auto-enroll-status.response";
|
|
import { OrganizationKeysResponse } from "../../models/response/organization-keys.response";
|
|
import { OrganizationResponse } from "../../models/response/organization.response";
|
|
import { ProfileOrganizationResponse } from "../../models/response/profile-organization.response";
|
|
|
|
export class OrganizationApiService implements OrganizationApiServiceAbstraction {
|
|
constructor(private apiService: ApiService, private syncService: SyncService) {}
|
|
|
|
async get(id: string): Promise<OrganizationResponse> {
|
|
const r = await this.apiService.send("GET", "/organizations/" + id, null, true, true);
|
|
return new OrganizationResponse(r);
|
|
}
|
|
|
|
async getBilling(id: string): Promise<BillingResponse> {
|
|
const r = await this.apiService.send(
|
|
"GET",
|
|
"/organizations/" + id + "/billing",
|
|
null,
|
|
true,
|
|
true
|
|
);
|
|
return new BillingResponse(r);
|
|
}
|
|
|
|
async getSubscription(id: string): Promise<OrganizationSubscriptionResponse> {
|
|
const r = await this.apiService.send(
|
|
"GET",
|
|
"/organizations/" + id + "/subscription",
|
|
null,
|
|
true,
|
|
true
|
|
);
|
|
return new OrganizationSubscriptionResponse(r);
|
|
}
|
|
|
|
async getLicense(id: string, installationId: string): Promise<unknown> {
|
|
return this.apiService.send(
|
|
"GET",
|
|
"/organizations/" + id + "/license?installationId=" + installationId,
|
|
null,
|
|
true,
|
|
true
|
|
);
|
|
}
|
|
|
|
async getAutoEnrollStatus(identifier: string): Promise<OrganizationAutoEnrollStatusResponse> {
|
|
const r = await this.apiService.send(
|
|
"GET",
|
|
"/organizations/" + identifier + "/auto-enroll-status",
|
|
null,
|
|
true,
|
|
true
|
|
);
|
|
return new OrganizationAutoEnrollStatusResponse(r);
|
|
}
|
|
|
|
async create(request: OrganizationCreateRequest): Promise<OrganizationResponse> {
|
|
const r = await this.apiService.send("POST", "/organizations", request, true, true);
|
|
// Forcing a sync will notify organization service that they need to repull
|
|
await this.syncService.fullSync(true);
|
|
return new OrganizationResponse(r);
|
|
}
|
|
|
|
async createLicense(data: FormData): Promise<OrganizationResponse> {
|
|
const r = await this.apiService.send(
|
|
"POST",
|
|
"/organizations/licenses/self-hosted",
|
|
data,
|
|
true,
|
|
true
|
|
);
|
|
return new OrganizationResponse(r);
|
|
}
|
|
|
|
async save(id: string, request: OrganizationUpdateRequest): Promise<OrganizationResponse> {
|
|
const r = await this.apiService.send("PUT", "/organizations/" + id, request, true, true);
|
|
const data = new OrganizationResponse(r);
|
|
await this.syncService.fullSync(true);
|
|
return data;
|
|
}
|
|
|
|
async updatePayment(id: string, request: PaymentRequest): Promise<void> {
|
|
return this.apiService.send("POST", "/organizations/" + id + "/payment", request, true, false);
|
|
}
|
|
|
|
async upgrade(id: string, request: OrganizationUpgradeRequest): Promise<PaymentResponse> {
|
|
const r = await this.apiService.send(
|
|
"POST",
|
|
"/organizations/" + id + "/upgrade",
|
|
request,
|
|
true,
|
|
true
|
|
);
|
|
return new PaymentResponse(r);
|
|
}
|
|
|
|
async updatePasswordManagerSeats(
|
|
id: string,
|
|
request: OrganizationSubscriptionUpdateRequest
|
|
): Promise<void> {
|
|
return this.apiService.send(
|
|
"POST",
|
|
"/organizations/" + id + "/subscription",
|
|
request,
|
|
true,
|
|
false
|
|
);
|
|
}
|
|
|
|
async updateSecretsManagerSubscription(
|
|
id: string,
|
|
request: OrganizationSmSubscriptionUpdateRequest
|
|
): Promise<void> {
|
|
return this.apiService.send(
|
|
"POST",
|
|
"/organizations/" + id + "/sm-subscription",
|
|
request,
|
|
true,
|
|
false
|
|
);
|
|
}
|
|
|
|
async updateSeats(id: string, request: SeatRequest): Promise<PaymentResponse> {
|
|
const r = await this.apiService.send(
|
|
"POST",
|
|
"/organizations/" + id + "/seat",
|
|
request,
|
|
true,
|
|
true
|
|
);
|
|
return new PaymentResponse(r);
|
|
}
|
|
|
|
async updateStorage(id: string, request: StorageRequest): Promise<PaymentResponse> {
|
|
const r = await this.apiService.send(
|
|
"POST",
|
|
"/organizations/" + id + "/storage",
|
|
request,
|
|
true,
|
|
true
|
|
);
|
|
return new PaymentResponse(r);
|
|
}
|
|
|
|
async verifyBank(id: string, request: VerifyBankRequest): Promise<void> {
|
|
await this.apiService.send(
|
|
"POST",
|
|
"/organizations/" + id + "/verify-bank",
|
|
request,
|
|
true,
|
|
false
|
|
);
|
|
}
|
|
|
|
async cancel(id: string): Promise<void> {
|
|
return this.apiService.send("POST", "/organizations/" + id + "/cancel", null, true, false);
|
|
}
|
|
|
|
async reinstate(id: string): Promise<void> {
|
|
return this.apiService.send("POST", "/organizations/" + id + "/reinstate", null, true, false);
|
|
}
|
|
|
|
async leave(id: string): Promise<void> {
|
|
await this.apiService.send("POST", "/organizations/" + id + "/leave", null, true, false);
|
|
await this.syncService.fullSync(true);
|
|
}
|
|
|
|
async delete(id: string, request: SecretVerificationRequest): Promise<void> {
|
|
await this.apiService.send("DELETE", "/organizations/" + id, request, true, false);
|
|
await this.syncService.fullSync(true);
|
|
}
|
|
|
|
async updateLicense(id: string, data: FormData): Promise<void> {
|
|
await this.apiService.send(
|
|
"POST",
|
|
"/organizations/licenses/self-hosted/" + id,
|
|
data,
|
|
true,
|
|
false
|
|
);
|
|
}
|
|
|
|
async importDirectory(organizationId: string, request: ImportDirectoryRequest): Promise<void> {
|
|
return this.apiService.send(
|
|
"POST",
|
|
"/organizations/" + organizationId + "/import",
|
|
request,
|
|
true,
|
|
false
|
|
);
|
|
}
|
|
|
|
async getOrCreateApiKey(id: string, request: OrganizationApiKeyRequest): Promise<ApiKeyResponse> {
|
|
const r = await this.apiService.send(
|
|
"POST",
|
|
"/organizations/" + id + "/api-key",
|
|
request,
|
|
true,
|
|
true
|
|
);
|
|
return new ApiKeyResponse(r);
|
|
}
|
|
|
|
async getApiKeyInformation(
|
|
id: string,
|
|
organizationApiKeyType: OrganizationApiKeyType = null
|
|
): Promise<ListResponse<OrganizationApiKeyInformationResponse>> {
|
|
const uri =
|
|
organizationApiKeyType === null
|
|
? "/organizations/" + id + "/api-key-information"
|
|
: "/organizations/" + id + "/api-key-information/" + organizationApiKeyType;
|
|
const r = await this.apiService.send("GET", uri, null, true, true);
|
|
return new ListResponse(r, OrganizationApiKeyInformationResponse);
|
|
}
|
|
|
|
async rotateApiKey(id: string, request: OrganizationApiKeyRequest): Promise<ApiKeyResponse> {
|
|
const r = await this.apiService.send(
|
|
"POST",
|
|
"/organizations/" + id + "/rotate-api-key",
|
|
request,
|
|
true,
|
|
true
|
|
);
|
|
return new ApiKeyResponse(r);
|
|
}
|
|
|
|
async getTaxInfo(id: string): Promise<TaxInfoResponse> {
|
|
const r = await this.apiService.send("GET", "/organizations/" + id + "/tax", null, true, true);
|
|
return new TaxInfoResponse(r);
|
|
}
|
|
|
|
async updateTaxInfo(id: string, request: OrganizationTaxInfoUpdateRequest): Promise<void> {
|
|
// Can't broadcast anything because the response doesn't have content
|
|
return this.apiService.send("PUT", "/organizations/" + id + "/tax", request, true, false);
|
|
}
|
|
|
|
async getKeys(id: string): Promise<OrganizationKeysResponse> {
|
|
const r = await this.apiService.send("GET", "/organizations/" + id + "/keys", null, true, true);
|
|
return new OrganizationKeysResponse(r);
|
|
}
|
|
|
|
async updateKeys(
|
|
id: string,
|
|
request: OrganizationKeysRequest
|
|
): Promise<OrganizationKeysResponse> {
|
|
const r = await this.apiService.send(
|
|
"POST",
|
|
"/organizations/" + id + "/keys",
|
|
request,
|
|
true,
|
|
true
|
|
);
|
|
// Not broadcasting anything because data on this response doesn't correspond to `Organization`
|
|
return new OrganizationKeysResponse(r);
|
|
}
|
|
|
|
async getSso(id: string): Promise<OrganizationSsoResponse> {
|
|
const r = await this.apiService.send("GET", "/organizations/" + id + "/sso", null, true, true);
|
|
return new OrganizationSsoResponse(r);
|
|
}
|
|
|
|
async updateSso(id: string, request: OrganizationSsoRequest): Promise<OrganizationSsoResponse> {
|
|
const r = await this.apiService.send(
|
|
"POST",
|
|
"/organizations/" + id + "/sso",
|
|
request,
|
|
true,
|
|
true
|
|
);
|
|
// Not broadcasting anything because data on this response doesn't correspond to `Organization`
|
|
return new OrganizationSsoResponse(r);
|
|
}
|
|
|
|
async selfHostedSyncLicense(id: string) {
|
|
await this.apiService.send(
|
|
"POST",
|
|
"/organizations/licenses/self-hosted/" + id + "/sync/",
|
|
null,
|
|
true,
|
|
false
|
|
);
|
|
}
|
|
|
|
async subscribeToSecretsManager(
|
|
id: string,
|
|
request: SecretsManagerSubscribeRequest
|
|
): Promise<ProfileOrganizationResponse> {
|
|
const r = await this.apiService.send(
|
|
"POST",
|
|
"/organizations/" + id + "/subscribe-secrets-manager",
|
|
request,
|
|
true,
|
|
true
|
|
);
|
|
return new ProfileOrganizationResponse(r);
|
|
}
|
|
}
|