1
0
mirror of https://github.com/bitwarden/browser.git synced 2024-08-29 23:49:50 +02:00

Refactor OrganizationPlansComponent (#1045)

This commit is contained in:
Oscar Hinton 2021-06-24 17:37:59 +02:00 committed by GitHub
parent ef331aba0b
commit 57f952bc66
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 107 additions and 108 deletions

View File

@ -8,8 +8,7 @@
<div class="form-group">
<label for="file">{{'licenseFile' | i18n}}</label>
<input type="file" id="file" class="form-control-file" name="file" required>
<small
class="form-text text-muted">{{'licenseFileDesc' | i18n : 'bitwarden_organization_license.json'}}</small>
<small class="form-text text-muted">{{'licenseFileDesc' | i18n : 'bitwarden_organization_license.json'}}</small>
</div>
<button type="submit" class="btn btn-primary btn-submit" [disabled]="form.loading">
<i class="fa fa-spinner fa-spin" title="{{'loading' | i18n}}" aria-hidden="true"></i>

View File

@ -33,6 +33,7 @@ import { OrganizationCreateRequest } from 'jslib-common/models/request/organizat
import { OrganizationKeysRequest } from 'jslib-common/models/request/organizationKeysRequest';
import { OrganizationUpgradeRequest } from 'jslib-common/models/request/organizationUpgradeRequest';
import { EncString } from 'jslib-common/models/domain';
import { PlanResponse } from 'jslib-common/models/response/planResponse';
@Component({
@ -216,46 +217,16 @@ export class OrganizationPlansComponent implements OnInit {
}
async submit() {
this.singleOrgPolicyBlock = await this.userHasBlockingSingleOrgPolicy();
if (this.singleOrgPolicyBlock) {
return;
} else {
const policies = await this.policyService.getAll(PolicyType.SingleOrg);
const orgs = await this.userService.getAllOrganizations();
const orgsWithSingleOrgPolicy = policies
.filter(p => p.enabled && p.type === PolicyType.SingleOrg)
.map(p => p.organizationId);
this.singleOrgPolicyBlock = orgs.some(org =>
org.type !== OrganizationUserType.Owner &&
org.type !== OrganizationUserType.Admin &&
org.status !== OrganizationUserStatusType.Invited &&
orgsWithSingleOrgPolicy.includes(org.id));
if (this.singleOrgPolicyBlock) {
return;
}
}
let files: FileList = null;
if (this.createOrganization && this.selfHosted) {
const fileEl = document.getElementById('file') as HTMLInputElement;
files = fileEl.files;
if (files == null || files.length === 0) {
this.toasterService.popAsync('error', this.i18nService.t('errorOccurred'),
this.i18nService.t('selectFile'));
return;
}
}
try {
const doSubmit = async () => {
let orgId: string = null;
if (this.createOrganization) {
let tokenResult: [string, PaymentMethodType] = null;
if (!this.selfHosted && this.plan !== PlanType.Free) {
tokenResult = await this.paymentComponent.createPaymentToken();
}
const shareKey = await this.cryptoService.makeShareKey();
const key = shareKey[0].encryptedString;
const collection = await this.cryptoService.encrypt(
@ -264,85 +235,20 @@ export class OrganizationPlansComponent implements OnInit {
const orgKeys = await this.cryptoService.makeKeyPair(shareKey[1]);
if (this.selfHosted) {
const fd = new FormData();
fd.append('license', files[0]);
fd.append('key', key);
fd.append('collectionName', collectionCt);
const response = await this.apiService.postOrganizationLicense(fd);
orgId = response.id;
// Org Keys live outside of the OrganizationLicense - add the keys to the org here
const request = new OrganizationKeysRequest(orgKeys[0], orgKeys[1].encryptedString);
await this.apiService.postOrganizationKeys(orgId, request);
orgId = await this.createSelfHosted(key, collectionCt, orgKeys);
} else {
const request = new OrganizationCreateRequest();
request.key = key;
request.collectionName = collectionCt;
request.name = this.name;
request.billingEmail = this.billingEmail;
request.keys = new OrganizationKeysRequest(orgKeys[0], orgKeys[1].encryptedString);
if (this.selectedPlan.type === PlanType.Free) {
request.planType = PlanType.Free;
} else {
request.paymentToken = tokenResult[0];
request.paymentMethodType = tokenResult[1];
request.businessName = this.ownedBusiness ? this.businessName : null;
request.additionalSeats = this.additionalSeats;
request.additionalStorageGb = this.additionalStorage;
request.premiumAccessAddon = this.selectedPlan.hasPremiumAccessOption &&
this.premiumAccessAddon;
request.planType = this.selectedPlan.type;
request.billingAddressPostalCode = this.taxComponent.taxInfo.postalCode;
request.billingAddressCountry = this.taxComponent.taxInfo.country;
if (this.taxComponent.taxInfo.includeTaxId) {
request.taxIdNumber = this.taxComponent.taxInfo.taxId;
request.billingAddressLine1 = this.taxComponent.taxInfo.line1;
request.billingAddressLine2 = this.taxComponent.taxInfo.line2;
request.billingAddressCity = this.taxComponent.taxInfo.city;
request.billingAddressState = this.taxComponent.taxInfo.state;
}
}
const response = await this.apiService.postOrganization(request);
orgId = response.id;
orgId = await this.createCloudHosted(key, collectionCt, orgKeys);
}
this.toasterService.popAsync('success', this.i18nService.t('organizationCreated'), this.i18nService.t('organizationReadyToGo'));
} else {
const request = new OrganizationUpgradeRequest();
request.businessName = this.ownedBusiness ? this.businessName : null;
request.additionalSeats = this.additionalSeats;
request.additionalStorageGb = this.additionalStorage;
request.premiumAccessAddon = this.selectedPlan.hasPremiumAccessOption &&
this.premiumAccessAddon;
request.planType = this.selectedPlan.type;
request.billingAddressCountry = this.taxComponent.taxInfo.country;
request.billingAddressPostalCode = this.taxComponent.taxInfo.postalCode;
// Retrieve org info to backfill pub/priv key if necessary
const org = await this.userService.getOrganization(this.organizationId);
if (!org.hasPublicAndPrivateKeys) {
const orgShareKey = await this.cryptoService.getOrgKey(this.organizationId);
const orgKeys = await this.cryptoService.makeKeyPair(orgShareKey);
request.keys = new OrganizationKeysRequest(orgKeys[0], orgKeys[1].encryptedString);
}
const result = await this.apiService.postOrganizationUpgrade(this.organizationId, request);
if (!result.success && result.paymentIntentClientSecret != null) {
await this.paymentComponent.handleStripeCardPayment(result.paymentIntentClientSecret, null);
}
orgId = this.organizationId;
orgId = await this.updateOrganization(orgId);
this.toasterService.popAsync('success', null, this.i18nService.t('organizationUpgraded'));
}
if (orgId != null) {
await this.apiService.refreshIdentityToken();
await this.syncService.fullSync(true);
if (this.createOrganization) {
this.toasterService.popAsync('success',
this.i18nService.t('organizationCreated'), this.i18nService.t('organizationReadyToGo'));
} else {
this.toasterService.popAsync('success', null, this.i18nService.t('organizationUpgraded'));
}
this.router.navigate(['/organizations/' + orgId]);
}
await this.apiService.refreshIdentityToken();
await this.syncService.fullSync(true);
this.router.navigate(['/organizations/' + orgId]);
};
this.formPromise = doSubmit();
@ -351,4 +257,98 @@ export class OrganizationPlansComponent implements OnInit {
} catch { }
}
private async userHasBlockingSingleOrgPolicy() {
const policies = await this.policyService.getAll(PolicyType.SingleOrg);
const orgs = await this.userService.getAllOrganizations();
const orgsWithSingleOrgPolicy = policies
.filter(p => p.enabled && p.type === PolicyType.SingleOrg)
.map(p => p.organizationId);
return orgs.some(org => org.type !== OrganizationUserType.Owner &&
org.type !== OrganizationUserType.Admin &&
org.status !== OrganizationUserStatusType.Invited &&
orgsWithSingleOrgPolicy.includes(org.id));
}
private async updateOrganization(orgId: string) {
const request = new OrganizationUpgradeRequest();
request.businessName = this.ownedBusiness ? this.businessName : null;
request.additionalSeats = this.additionalSeats;
request.additionalStorageGb = this.additionalStorage;
request.premiumAccessAddon = this.selectedPlan.hasPremiumAccessOption && this.premiumAccessAddon;
request.planType = this.selectedPlan.type;
request.billingAddressCountry = this.taxComponent.taxInfo.country;
request.billingAddressPostalCode = this.taxComponent.taxInfo.postalCode;
// Retrieve org info to backfill pub/priv key if necessary
const org = await this.userService.getOrganization(this.organizationId);
if (!org.hasPublicAndPrivateKeys) {
const orgShareKey = await this.cryptoService.getOrgKey(this.organizationId);
const orgKeys = await this.cryptoService.makeKeyPair(orgShareKey);
request.keys = new OrganizationKeysRequest(orgKeys[0], orgKeys[1].encryptedString);
}
const result = await this.apiService.postOrganizationUpgrade(this.organizationId, request);
if (!result.success && result.paymentIntentClientSecret != null) {
await this.paymentComponent.handleStripeCardPayment(result.paymentIntentClientSecret, null);
}
return this.organizationId;
}
private async createCloudHosted(key: string, collectionCt: string, orgKeys: [string, EncString]) {
const request = new OrganizationCreateRequest();
request.key = key;
request.collectionName = collectionCt;
request.name = this.name;
request.billingEmail = this.billingEmail;
request.keys = new OrganizationKeysRequest(orgKeys[0], orgKeys[1].encryptedString);
if (this.selectedPlan.type === PlanType.Free) {
request.planType = PlanType.Free;
} else {
const tokenResult = await this.paymentComponent.createPaymentToken();
request.paymentToken = tokenResult[0];
request.paymentMethodType = tokenResult[1];
request.businessName = this.ownedBusiness ? this.businessName : null;
request.additionalSeats = this.additionalSeats;
request.additionalStorageGb = this.additionalStorage;
request.premiumAccessAddon = this.selectedPlan.hasPremiumAccessOption &&
this.premiumAccessAddon;
request.planType = this.selectedPlan.type;
request.billingAddressPostalCode = this.taxComponent.taxInfo.postalCode;
request.billingAddressCountry = this.taxComponent.taxInfo.country;
if (this.taxComponent.taxInfo.includeTaxId) {
request.taxIdNumber = this.taxComponent.taxInfo.taxId;
request.billingAddressLine1 = this.taxComponent.taxInfo.line1;
request.billingAddressLine2 = this.taxComponent.taxInfo.line2;
request.billingAddressCity = this.taxComponent.taxInfo.city;
request.billingAddressState = this.taxComponent.taxInfo.state;
}
}
const response = await this.apiService.postOrganization(request);
return response.id;
}
private async createSelfHosted(key: string, collectionCt: string, orgKeys: [string, EncString]) {
const fileEl = document.getElementById('file') as HTMLInputElement;
const files = fileEl.files;
if (files == null || files.length === 0) {
throw new Error(this.i18nService.t('selectFile'));
}
const fd = new FormData();
fd.append('license', files[0]);
fd.append('key', key);
fd.append('collectionName', collectionCt);
const response = await this.apiService.postOrganizationLicense(fd);
const orgId = response.id;
// Org Keys live outside of the OrganizationLicense - add the keys to the org here
const request = new OrganizationKeysRequest(orgKeys[0], orgKeys[1].encryptedString);
await this.apiService.postOrganizationKeys(orgId, request);
return orgId;
}
}