1
0
mirror of https://github.com/bitwarden/browser synced 2024-12-25 09:32:06 +01:00

org plan upgrade

This commit is contained in:
Kyle Spearrin 2019-03-21 21:38:56 -04:00
parent 0f3d71a504
commit ea4d1de772
4 changed files with 101 additions and 72 deletions

2
jslib

@ -1 +1 @@
Subproject commit aebd1b57fc0de80f5a8efbfee28e96b70e93db3d
Subproject commit 593870e9365d68e924955f1ec192a70216b63621

View File

@ -198,12 +198,15 @@
<div class="text-lg">
<strong>{{'total' | i18n}}:</strong> {{total | currency:'USD $'}} /{{interval | i18n}}
</div>
<small class="text-muted font-italic"
*ngIf="createOrganization">{{'paymentChargedWithTrial' | i18n : (interval | i18n) }}</small>
<h2 class="spaced-header mb-4">{{'paymentInformation' | i18n}}</h2>
<app-payment [hideCredit]="true" [hideBank]="!!organizationId"></app-payment>
<ng-container *ngIf="createOrganization">
<small class="text-muted font-italic">{{'paymentChargedWithTrial' | i18n : (interval | i18n) }}</small>
<h2 class="spaced-header mb-4">{{'paymentInformation' | i18n}}</h2>
<app-payment [hideCredit]="true"></app-payment>
</ng-container>
<small class="text-muted font-italic mt-2 d-block" *ngIf="!createOrganization">
{{'paymentCharged' | i18n : (interval | i18n) }}</small>
</ng-container>
<div [ngClass]="{'mt-4': plans[plan].noPayment}">
<div [ngClass]="{'mt-4': !createOrganization || plans[plan].noPayment}">
<button type="submit" class="btn btn-primary btn-submit" [disabled]="form.loading">
<i class="fa fa-spinner fa-spin" title="{{'loading' | i18n}}"></i>
<span>{{'submit' | i18n}}</span>

View File

@ -22,6 +22,7 @@ import { PaymentComponent } from './payment.component';
import { PlanType } from 'jslib/enums/planType';
import { OrganizationCreateRequest } from 'jslib/models/request/organizationCreateRequest';
import { OrganizationUpgradeRequest } from 'jslib/models/request/organizationUpgradeRequest';
@Component({
selector: 'app-organization-plans',
@ -110,7 +111,84 @@ export class OrganizationPlansComponent {
}
try {
this.formPromise = this.doSubmit(files);
const doSubmit = async () => {
let orgId: string = null;
if (this.createOrganization) {
let tokenResult: [string, PaymentMethodType] = null;
if (!this.selfHosted && this.plan !== 'free') {
tokenResult = await this.paymentComponent.createPaymentToken();
}
const shareKey = await this.cryptoService.makeShareKey();
const key = shareKey[0].encryptedString;
const collection = await this.cryptoService.encrypt(
this.i18nService.t('defaultCollection'), shareKey[1]);
const collectionCt = collection.encryptedString;
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;
} else {
const request = new OrganizationCreateRequest();
request.key = key;
request.collectionName = collectionCt;
request.name = this.name;
request.billingEmail = this.billingEmail;
if (this.plan === '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.plans[this.plan].canBuyPremiumAccessAddon &&
this.premiumAccessAddon;
if (this.interval === 'month') {
request.planType = this.plans[this.plan].monthPlanType;
} else {
request.planType = this.plans[this.plan].annualPlanType;
}
}
const response = await this.apiService.postOrganization(request);
orgId = response.id;
}
} else {
const request = new OrganizationUpgradeRequest();
request.businessName = this.ownedBusiness ? this.businessName : null;
request.additionalSeats = this.additionalSeats;
request.additionalStorageGb = this.additionalStorage;
request.premiumAccessAddon = this.plans[this.plan].canBuyPremiumAccessAddon &&
this.premiumAccessAddon;
if (this.interval === 'month') {
request.planType = this.plans[this.plan].monthPlanType;
} else {
request.planType = this.plans[this.plan].annualPlanType;
}
await this.apiService.postOrganizationUpgrade(this.organizationId, request);
orgId = this.organizationId;
}
if (orgId != null) {
await this.apiService.refreshIdentityToken();
await this.syncService.fullSync(true);
if (this.createOrganization) {
this.analytics.eventTrack.next({ action: 'Created Organization' });
this.toasterService.popAsync('success',
this.i18nService.t('organizationCreated'), this.i18nService.t('organizationReadyToGo'));
} else {
this.analytics.eventTrack.next({ action: 'Upgraded Organization' });
this.toasterService.popAsync('success', null, this.i18nService.t('organizationUpgraded'));
}
this.router.navigate(['/organizations/' + orgId]);
}
};
this.formPromise = doSubmit();
await this.formPromise;
this.onSuccess.emit();
} catch { }
@ -190,68 +268,4 @@ export class OrganizationPlansComponent {
get createOrganization() {
return this.organizationId == null;
}
private async doSubmit(files: FileList) {
let tokenResult: [string, PaymentMethodType] = null;
if (!this.selfHosted && this.plan !== 'free') {
tokenResult = await this.paymentComponent.createPaymentToken();
}
let orgId: string = null;
if (this.createOrganization) {
const shareKey = await this.cryptoService.makeShareKey();
const key = shareKey[0].encryptedString;
const collection = await this.cryptoService.encrypt(this.i18nService.t('defaultCollection'), shareKey[1]);
const collectionCt = collection.encryptedString;
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;
} else {
const request = new OrganizationCreateRequest();
request.key = key;
request.collectionName = collectionCt;
request.name = this.name;
request.billingEmail = this.billingEmail;
if (this.plan === '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.plans[this.plan].canBuyPremiumAccessAddon &&
this.premiumAccessAddon;
if (this.interval === 'month') {
request.planType = this.plans[this.plan].monthPlanType;
} else {
request.planType = this.plans[this.plan].annualPlanType;
}
}
const response = await this.apiService.postOrganization(request);
orgId = response.id;
}
} else {
// TODO
orgId = this.organizationId;
}
if (orgId != null) {
await this.apiService.refreshIdentityToken();
await this.syncService.fullSync(true);
this.analytics.eventTrack.next({
action: (this.createOrganization ? 'Created' : 'Upgraded') + ' Organization',
});
this.toasterService.popAsync('success',
this.i18nService.t(this.createOrganization ? 'organizationCreated' : ''), // TODO
this.i18nService.t('organizationReadyToGo'));
this.router.navigate(['/organizations/' + orgId]);
}
}
}

View File

@ -1613,12 +1613,21 @@
"paymentChargedAnnually": {
"message": "Your payment method will be charged immediately and then on a recurring basis each year. You may cancel at any time."
},
"paymentCharged": {
"message": "Your payment method will be charged immediately and then on a recurring basis each $INTERVAL$. You may cancel at any time.",
"placeholders": {
"interval": {
"content": "$1",
"example": "month or year"
}
}
},
"paymentChargedWithTrial": {
"message": "Your plan comes with a free 7 day trial. Your payment method will not be charged until the trial has ended. Billing will occur on a recurring basis each $INTERVAL$. You may cancel at any time.",
"placeholders": {
"interval": {
"content": "$1",
"example": "year"
"example": "month or year"
}
}
},
@ -1996,6 +2005,9 @@
"organizationReadyToGo": {
"message": "Your new organization is ready to go!"
},
"organizationUpgraded": {
"message": "Your organization has been upgraded."
},
"leave": {
"message": "Leave"
},