mirror of
https://github.com/gristlabs/grist-core.git
synced 2024-10-27 20:44:07 +00:00
(core) Removing temporary pro site
Summary: Creating a pro team site after Stripe checkout. Previously a stub site was always created and never removed, even if a user cancels the checkout process, which resulted in multiple 'ghost' sites that can't be removed. Test Plan: Updated and added Reviewers: paulfitz Reviewed By: paulfitz Differential Revision: https://phab.getgrist.com/D3985
This commit is contained in:
parent
f1a0b61e15
commit
fad421b7c0
@ -229,7 +229,8 @@ export class BillingAPIImpl extends BaseAPI implements BillingAPI {
|
||||
body: JSON.stringify({
|
||||
domain,
|
||||
name,
|
||||
planType: 'team'
|
||||
planType: 'team',
|
||||
next: window.location.href
|
||||
})
|
||||
});
|
||||
return data.checkoutUrl;
|
||||
|
@ -7,6 +7,8 @@ import {Request} from 'express';
|
||||
import {ApiError} from 'app/common/ApiError';
|
||||
import {FullUser} from 'app/common/LoginSessionAPI';
|
||||
import {OrganizationProperties} from 'app/common/UserAPI';
|
||||
import {User} from 'app/gen-server/entity/User';
|
||||
import {BillingOptions, HomeDBManager, QueryResult, Scope} from 'app/gen-server/lib/HomeDBManager';
|
||||
import {getAuthorizedUserId, getUserId, getUserProfiles, RequestWithLogin} from 'app/server/lib/Authorizer';
|
||||
import {getSessionUser, linkOrgWithEmail} from 'app/server/lib/BrowserSession';
|
||||
import {expressWrap} from 'app/server/lib/expressWrap';
|
||||
@ -16,9 +18,6 @@ import log from 'app/server/lib/log';
|
||||
import {addPermit, clearSessionCacheIfNeeded, getDocScope, getScope, integerParam,
|
||||
isParameterOn, optStringParam, sendOkReply, sendReply, stringParam} from 'app/server/lib/requestUtils';
|
||||
import {IWidgetRepository} from 'app/server/lib/WidgetRepository';
|
||||
|
||||
import {User} from './entity/User';
|
||||
import {HomeDBManager, QueryResult, Scope} from './lib/HomeDBManager';
|
||||
import {getCookieDomain} from 'app/server/lib/gristSessions';
|
||||
|
||||
// exposed for testing purposes
|
||||
@ -64,7 +63,7 @@ export function getOrgKey(req: Request): string|number {
|
||||
return orgKey;
|
||||
}
|
||||
|
||||
// Adds an non-personal org with a new billingAccout, with the given name and domain.
|
||||
// Adds an non-personal org with a new billingAccount, with the given name and domain.
|
||||
// Returns a QueryResult with the orgId on success.
|
||||
export function addOrg(
|
||||
dbManager: HomeDBManager,
|
||||
@ -72,6 +71,7 @@ export function addOrg(
|
||||
props: Partial<OrganizationProperties>,
|
||||
options?: {
|
||||
planType?: string,
|
||||
billing?: BillingOptions,
|
||||
}
|
||||
): Promise<number> {
|
||||
return dbManager.connection.transaction(async manager => {
|
||||
|
@ -27,7 +27,7 @@ import {
|
||||
} from "app/common/UserAPI";
|
||||
import {AclRule, AclRuleDoc, AclRuleOrg, AclRuleWs} from "app/gen-server/entity/AclRule";
|
||||
import {Alias} from "app/gen-server/entity/Alias";
|
||||
import {BillingAccount, ExternalBillingOptions} from "app/gen-server/entity/BillingAccount";
|
||||
import {BillingAccount} from "app/gen-server/entity/BillingAccount";
|
||||
import {BillingAccountManager} from "app/gen-server/entity/BillingAccountManager";
|
||||
import {Document} from "app/gen-server/entity/Document";
|
||||
import {Group} from "app/gen-server/entity/Group";
|
||||
@ -260,6 +260,20 @@ interface CreateWorkspaceOptions {
|
||||
ownerId?: number
|
||||
}
|
||||
|
||||
/**
|
||||
* Available options for creating a new org with a new billing account.
|
||||
*/
|
||||
export type BillingOptions = Partial<Pick<BillingAccount,
|
||||
'product' |
|
||||
'stripeCustomerId' |
|
||||
'stripeSubscriptionId' |
|
||||
'stripePlanId' |
|
||||
'externalId' |
|
||||
'externalOptions' |
|
||||
'inGoodStanding' |
|
||||
'status'
|
||||
>>;
|
||||
|
||||
/**
|
||||
* HomeDBManager handles interaction between the ApiServer and the Home database,
|
||||
* encapsulating the typeorm logic.
|
||||
@ -1348,14 +1362,13 @@ export class HomeDBManager extends EventEmitter {
|
||||
* NOTE: Currently it is always a true - billing account is one to one with org.
|
||||
* @param planType: if set, controls the type of plan used for the org. Only
|
||||
* meaningful for team sites currently.
|
||||
*
|
||||
* @param billing: if set, controls the billing account settings for the org.
|
||||
*/
|
||||
public async addOrg(user: User, props: Partial<OrganizationProperties>,
|
||||
options: { setUserAsOwner: boolean,
|
||||
useNewPlan: boolean,
|
||||
planType?: string,
|
||||
externalId?: string,
|
||||
externalOptions?: ExternalBillingOptions },
|
||||
billing?: BillingOptions},
|
||||
transaction?: EntityManager): Promise<QueryResult<number>> {
|
||||
const notifications: Array<() => void> = [];
|
||||
const name = props.name;
|
||||
@ -1405,12 +1418,26 @@ export class HomeDBManager extends EventEmitter {
|
||||
billingAccountManager.user = user;
|
||||
billingAccountManager.billingAccount = billingAccount;
|
||||
billingAccountEntities.push(billingAccountManager);
|
||||
if (options.externalId) {
|
||||
// save will fail if externalId is a duplicate.
|
||||
billingAccount.externalId = options.externalId;
|
||||
}
|
||||
if (options.externalOptions) {
|
||||
billingAccount.externalOptions = options.externalOptions;
|
||||
// Apply billing settings if requested, but not all of them.
|
||||
if (options.billing) {
|
||||
const billing = options.billing;
|
||||
const allowedKeys: Array<keyof BillingOptions> = [
|
||||
'product',
|
||||
'stripeCustomerId',
|
||||
'stripeSubscriptionId',
|
||||
'stripePlanId',
|
||||
// save will fail if externalId is a duplicate.
|
||||
'externalId',
|
||||
'externalOptions',
|
||||
'inGoodStanding',
|
||||
'status'
|
||||
];
|
||||
Object.keys(billing).forEach(key => {
|
||||
if (!allowedKeys.includes(key as any)) {
|
||||
delete (billing as any)[key];
|
||||
}
|
||||
});
|
||||
Object.assign(billingAccount, billing);
|
||||
}
|
||||
} else {
|
||||
log.warn("Creating org with shared billing account");
|
||||
@ -1421,7 +1448,7 @@ export class HomeDBManager extends EventEmitter {
|
||||
.leftJoinAndSelect('billing_accounts.orgs', 'orgs')
|
||||
.where('orgs.owner_id = :userId', {userId: user.id})
|
||||
.getOne();
|
||||
if (options.externalId && billingAccount?.externalId !== options.externalId) {
|
||||
if (options.billing?.externalId && billingAccount?.externalId !== options.billing?.externalId) {
|
||||
throw new ApiError('Conflicting external identifier', 400);
|
||||
}
|
||||
if (!billingAccount) {
|
||||
|
Loading…
Reference in New Issue
Block a user