mirror of
https://github.com/gristlabs/grist-core.git
synced 2024-10-27 20:44:07 +00:00
(core) add free team site product
Summary: This adds a Feature object that is an approximation of what we plan for free team sites. It includes restrictions that are not yet implemented, and an endpoint for testing. Test Plan: added a test Reviewers: georgegevoian Reviewed By: georgegevoian Differential Revision: https://phab.getgrist.com/D3243
This commit is contained in:
parent
64abfcb0ac
commit
4890a1fe89
@ -34,6 +34,18 @@ export interface Features {
|
|||||||
// (default: unlimited)
|
// (default: unlimited)
|
||||||
|
|
||||||
readOnlyDocs?: boolean; // if set, docs can only be read, not written.
|
readOnlyDocs?: boolean; // if set, docs can only be read, not written.
|
||||||
|
|
||||||
|
snapshotWindow?: { // if set, controls how far back snapshots are kept.
|
||||||
|
count: number; // TODO: not honored at time of writing.
|
||||||
|
unit: 'month'|'year';
|
||||||
|
};
|
||||||
|
|
||||||
|
baseMaxRowsPerDocument?: number; // If set, establishes a default maximum on the
|
||||||
|
// number of rows (total) in a single document.
|
||||||
|
// Actual max for a document may be higher.
|
||||||
|
// TODO: not honored at time of writing.
|
||||||
|
// TODO: nuances about how rows are counted.
|
||||||
|
baseMaxApiUnitsPerDocumentPerDay?: number; // Similar for api calls.
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check whether it is possible to add members at the org level. There's no flag
|
// Check whether it is possible to add members at the org level. There's no flag
|
||||||
|
@ -72,11 +72,15 @@ export function addOrg(
|
|||||||
dbManager: HomeDBManager,
|
dbManager: HomeDBManager,
|
||||||
userId: number,
|
userId: number,
|
||||||
props: Partial<OrganizationProperties>,
|
props: Partial<OrganizationProperties>,
|
||||||
|
options?: {
|
||||||
|
planType?: 'free'
|
||||||
|
}
|
||||||
): Promise<number> {
|
): Promise<number> {
|
||||||
return dbManager.connection.transaction(async manager => {
|
return dbManager.connection.transaction(async manager => {
|
||||||
const user = await manager.findOne(User, userId);
|
const user = await manager.findOne(User, userId);
|
||||||
if (!user) { return handleDeletedUser(); }
|
if (!user) { return handleDeletedUser(); }
|
||||||
const query = await dbManager.addOrg(user, props, {
|
const query = await dbManager.addOrg(user, props, {
|
||||||
|
...options,
|
||||||
setUserAsOwner: false,
|
setUserAsOwner: false,
|
||||||
useNewPlan: true
|
useNewPlan: true
|
||||||
}, manager);
|
}, manager);
|
||||||
|
@ -24,6 +24,21 @@ export const teamFeatures: Features = {
|
|||||||
maxSharesPerDoc: 2
|
maxSharesPerDoc: 2
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A summary of features available in free team sites.
|
||||||
|
* At time of writing, this is a placeholder, as free sites are fleshed out.
|
||||||
|
*/
|
||||||
|
export const teamFreeFeatures: Features = {
|
||||||
|
workspaces: true,
|
||||||
|
vanityDomain: true,
|
||||||
|
maxSharesPerWorkspace: 0, // all workspace shares need to be org members.
|
||||||
|
maxSharesPerDoc: 2,
|
||||||
|
maxDocsPerOrg: 20,
|
||||||
|
snapshotWindow: { count: 1, unit: 'month' },
|
||||||
|
baseMaxRowsPerDocument: 5000,
|
||||||
|
baseMaxApiUnitsPerDocumentPerDay: 5000
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A summary of features used in unrestricted grandfathered accounts, and also
|
* A summary of features used in unrestricted grandfathered accounts, and also
|
||||||
* in some test settings.
|
* in some test settings.
|
||||||
@ -101,6 +116,10 @@ const PRODUCTS: IProduct[] = [
|
|||||||
name: 'suspended',
|
name: 'suspended',
|
||||||
features: suspendedFeatures,
|
features: suspendedFeatures,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: 'teamFree',
|
||||||
|
features: teamFreeFeatures,
|
||||||
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -112,6 +131,7 @@ export function getDefaultProductNames() {
|
|||||||
teamInitial: 'stub', // Team site starts off on a limited plan, requiring subscription.
|
teamInitial: 'stub', // Team site starts off on a limited plan, requiring subscription.
|
||||||
teamCancel: 'suspended', // Team site that has been 'turned off'.
|
teamCancel: 'suspended', // Team site that has been 'turned off'.
|
||||||
team: 'team', // Functional team site.
|
team: 'team', // Functional team site.
|
||||||
|
teamFree: 'teamFree',
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1077,11 +1077,14 @@ export class HomeDBManager extends EventEmitter {
|
|||||||
* @param useNewPlan: by default, the individual billing account associated with the
|
* @param useNewPlan: by default, the individual billing account associated with the
|
||||||
* user's personal org will be used for all other orgs they create. Set useNewPlan
|
* user's personal org will be used for all other orgs they create. Set useNewPlan
|
||||||
* to force a distinct non-individual billing account to be used for this org.
|
* to force a distinct non-individual billing account to be used for this org.
|
||||||
|
* @param planType: if set, controls the type of plan used for the org. Only
|
||||||
|
* meaningful for team sites currently.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public async addOrg(user: User, props: Partial<OrganizationProperties>,
|
public async addOrg(user: User, props: Partial<OrganizationProperties>,
|
||||||
options: { setUserAsOwner: boolean,
|
options: { setUserAsOwner: boolean,
|
||||||
useNewPlan: boolean,
|
useNewPlan: boolean,
|
||||||
|
planType?: 'free',
|
||||||
externalId?: string,
|
externalId?: string,
|
||||||
externalOptions?: ExternalBillingOptions },
|
externalOptions?: ExternalBillingOptions },
|
||||||
transaction?: EntityManager): Promise<QueryResult<number>> {
|
transaction?: EntityManager): Promise<QueryResult<number>> {
|
||||||
@ -1110,10 +1113,11 @@ export class HomeDBManager extends EventEmitter {
|
|||||||
let billingAccount;
|
let billingAccount;
|
||||||
if (options.useNewPlan) {
|
if (options.useNewPlan) {
|
||||||
const productNames = getDefaultProductNames();
|
const productNames = getDefaultProductNames();
|
||||||
let productName = options.setUserAsOwner ? productNames.personal : productNames.teamInitial;
|
let productName = options.setUserAsOwner ? productNames.personal :
|
||||||
|
options.planType === 'free' ? productNames.teamFree : productNames.teamInitial;
|
||||||
// A bit fragile: this is called during creation of support@ user, before
|
// A bit fragile: this is called during creation of support@ user, before
|
||||||
// getSupportUserId() is available, but with setUserAsOwner of true.
|
// getSupportUserId() is available, but with setUserAsOwner of true.
|
||||||
if (!options.setUserAsOwner && user.id === this.getSupportUserId()) {
|
if (!options.setUserAsOwner && user.id === this.getSupportUserId() && options.planType !== 'free') {
|
||||||
// For teams created by support@getgrist.com, set the product to something
|
// For teams created by support@getgrist.com, set the product to something
|
||||||
// good so payment not needed. This is useful for testing.
|
// good so payment not needed. This is useful for testing.
|
||||||
productName = productNames.team;
|
productName = productNames.team;
|
||||||
|
Loading…
Reference in New Issue
Block a user