Merge pull request #12152 from Budibase/fix/revert-per-user-per-creator
[Fix] [Revert] per user per creator
This commit is contained in:
commit
6c4befbfb6
|
@ -119,8 +119,8 @@ export class Writethrough {
|
||||||
this.writeRateMs = writeRateMs
|
this.writeRateMs = writeRateMs
|
||||||
}
|
}
|
||||||
|
|
||||||
async put(doc: any, writeRateMs: number = this.writeRateMs) {
|
async put(doc: any) {
|
||||||
return put(this.db, doc, writeRateMs)
|
return put(this.db, doc, this.writeRateMs)
|
||||||
}
|
}
|
||||||
|
|
||||||
async get(id: string) {
|
async get(id: string) {
|
||||||
|
|
|
@ -25,17 +25,12 @@ import {
|
||||||
import {
|
import {
|
||||||
getAccountHolderFromUserIds,
|
getAccountHolderFromUserIds,
|
||||||
isAdmin,
|
isAdmin,
|
||||||
isCreator,
|
|
||||||
validateUniqueUser,
|
validateUniqueUser,
|
||||||
} from "./utils"
|
} from "./utils"
|
||||||
import { searchExistingEmails } from "./lookup"
|
import { searchExistingEmails } from "./lookup"
|
||||||
import { hash } from "../utils"
|
import { hash } from "../utils"
|
||||||
|
|
||||||
type QuotaUpdateFn = (
|
type QuotaUpdateFn = (change: number, cb?: () => Promise<any>) => Promise<any>
|
||||||
change: number,
|
|
||||||
creatorsChange: number,
|
|
||||||
cb?: () => Promise<any>
|
|
||||||
) => Promise<any>
|
|
||||||
type GroupUpdateFn = (groupId: string, userIds: string[]) => Promise<any>
|
type GroupUpdateFn = (groupId: string, userIds: string[]) => Promise<any>
|
||||||
type FeatureFn = () => Promise<Boolean>
|
type FeatureFn = () => Promise<Boolean>
|
||||||
type GroupGetFn = (ids: string[]) => Promise<UserGroup[]>
|
type GroupGetFn = (ids: string[]) => Promise<UserGroup[]>
|
||||||
|
@ -250,8 +245,7 @@ export class UserDB {
|
||||||
}
|
}
|
||||||
|
|
||||||
const change = dbUser ? 0 : 1 // no change if there is existing user
|
const change = dbUser ? 0 : 1 // no change if there is existing user
|
||||||
const creatorsChange = isCreator(dbUser) !== isCreator(user) ? 1 : 0
|
return UserDB.quotas.addUsers(change, async () => {
|
||||||
return UserDB.quotas.addUsers(change, creatorsChange, async () => {
|
|
||||||
await validateUniqueUser(email, tenantId)
|
await validateUniqueUser(email, tenantId)
|
||||||
|
|
||||||
let builtUser = await UserDB.buildUser(user, opts, tenantId, dbUser)
|
let builtUser = await UserDB.buildUser(user, opts, tenantId, dbUser)
|
||||||
|
@ -313,7 +307,6 @@ export class UserDB {
|
||||||
|
|
||||||
let usersToSave: any[] = []
|
let usersToSave: any[] = []
|
||||||
let newUsers: any[] = []
|
let newUsers: any[] = []
|
||||||
let newCreators: any[] = []
|
|
||||||
|
|
||||||
const emails = newUsersRequested.map((user: User) => user.email)
|
const emails = newUsersRequested.map((user: User) => user.email)
|
||||||
const existingEmails = await searchExistingEmails(emails)
|
const existingEmails = await searchExistingEmails(emails)
|
||||||
|
@ -334,66 +327,59 @@ export class UserDB {
|
||||||
}
|
}
|
||||||
newUser.userGroups = groups
|
newUser.userGroups = groups
|
||||||
newUsers.push(newUser)
|
newUsers.push(newUser)
|
||||||
if (isCreator(newUser)) {
|
|
||||||
newCreators.push(newUser)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const account = await accountSdk.getAccountByTenantId(tenantId)
|
const account = await accountSdk.getAccountByTenantId(tenantId)
|
||||||
return UserDB.quotas.addUsers(
|
return UserDB.quotas.addUsers(newUsers.length, async () => {
|
||||||
newUsers.length,
|
// create the promises array that will be called by bulkDocs
|
||||||
newCreators.length,
|
newUsers.forEach((user: any) => {
|
||||||
async () => {
|
usersToSave.push(
|
||||||
// create the promises array that will be called by bulkDocs
|
UserDB.buildUser(
|
||||||
newUsers.forEach((user: any) => {
|
user,
|
||||||
usersToSave.push(
|
{
|
||||||
UserDB.buildUser(
|
hashPassword: true,
|
||||||
user,
|
requirePassword: user.requirePassword,
|
||||||
{
|
},
|
||||||
hashPassword: true,
|
tenantId,
|
||||||
requirePassword: user.requirePassword,
|
undefined, // no dbUser
|
||||||
},
|
account
|
||||||
tenantId,
|
|
||||||
undefined, // no dbUser
|
|
||||||
account
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
})
|
)
|
||||||
|
})
|
||||||
|
|
||||||
const usersToBulkSave = await Promise.all(usersToSave)
|
const usersToBulkSave = await Promise.all(usersToSave)
|
||||||
await usersCore.bulkUpdateGlobalUsers(usersToBulkSave)
|
await usersCore.bulkUpdateGlobalUsers(usersToBulkSave)
|
||||||
|
|
||||||
// Post-processing of bulk added users, e.g. events and cache operations
|
// Post-processing of bulk added users, e.g. events and cache operations
|
||||||
for (const user of usersToBulkSave) {
|
for (const user of usersToBulkSave) {
|
||||||
// TODO: Refactor to bulk insert users into the info db
|
// TODO: Refactor to bulk insert users into the info db
|
||||||
// instead of relying on looping tenant creation
|
// instead of relying on looping tenant creation
|
||||||
await platform.users.addUser(tenantId, user._id, user.email)
|
await platform.users.addUser(tenantId, user._id, user.email)
|
||||||
await eventHelpers.handleSaveEvents(user, undefined)
|
await eventHelpers.handleSaveEvents(user, undefined)
|
||||||
}
|
|
||||||
|
|
||||||
const saved = usersToBulkSave.map(user => {
|
|
||||||
return {
|
|
||||||
_id: user._id,
|
|
||||||
email: user.email,
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
// now update the groups
|
|
||||||
if (Array.isArray(saved) && groups) {
|
|
||||||
const groupPromises = []
|
|
||||||
const createdUserIds = saved.map(user => user._id)
|
|
||||||
for (let groupId of groups) {
|
|
||||||
groupPromises.push(UserDB.groups.addUsers(groupId, createdUserIds))
|
|
||||||
}
|
|
||||||
await Promise.all(groupPromises)
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
successful: saved,
|
|
||||||
unsuccessful,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
)
|
|
||||||
|
const saved = usersToBulkSave.map(user => {
|
||||||
|
return {
|
||||||
|
_id: user._id,
|
||||||
|
email: user.email,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
// now update the groups
|
||||||
|
if (Array.isArray(saved) && groups) {
|
||||||
|
const groupPromises = []
|
||||||
|
const createdUserIds = saved.map(user => user._id)
|
||||||
|
for (let groupId of groups) {
|
||||||
|
groupPromises.push(UserDB.groups.addUsers(groupId, createdUserIds))
|
||||||
|
}
|
||||||
|
await Promise.all(groupPromises)
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
successful: saved,
|
||||||
|
unsuccessful,
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
static async bulkDelete(userIds: string[]): Promise<BulkUserDeleted> {
|
static async bulkDelete(userIds: string[]): Promise<BulkUserDeleted> {
|
||||||
|
@ -433,12 +419,11 @@ export class UserDB {
|
||||||
_deleted: true,
|
_deleted: true,
|
||||||
}))
|
}))
|
||||||
const dbResponse = await usersCore.bulkUpdateGlobalUsers(toDelete)
|
const dbResponse = await usersCore.bulkUpdateGlobalUsers(toDelete)
|
||||||
const creatorsToDelete = usersToDelete.filter(isCreator)
|
|
||||||
|
|
||||||
|
await UserDB.quotas.removeUsers(toDelete.length)
|
||||||
for (let user of usersToDelete) {
|
for (let user of usersToDelete) {
|
||||||
await bulkDeleteProcessing(user)
|
await bulkDeleteProcessing(user)
|
||||||
}
|
}
|
||||||
await UserDB.quotas.removeUsers(toDelete.length, creatorsToDelete.length)
|
|
||||||
|
|
||||||
// Build Response
|
// Build Response
|
||||||
// index users by id
|
// index users by id
|
||||||
|
@ -487,8 +472,7 @@ export class UserDB {
|
||||||
|
|
||||||
await db.remove(userId, dbUser._rev)
|
await db.remove(userId, dbUser._rev)
|
||||||
|
|
||||||
const creatorsToDelete = isCreator(dbUser) ? 1 : 0
|
await UserDB.quotas.removeUsers(1)
|
||||||
await UserDB.quotas.removeUsers(1, creatorsToDelete)
|
|
||||||
await eventHelpers.handleDeleteEvents(dbUser)
|
await eventHelpers.handleDeleteEvents(dbUser)
|
||||||
await cache.user.invalidateUser(userId)
|
await cache.user.invalidateUser(userId)
|
||||||
await sessions.invalidateSessions(userId, { reason: "deletion" })
|
await sessions.invalidateSessions(userId, { reason: "deletion" })
|
||||||
|
|
|
@ -14,16 +14,15 @@ import {
|
||||||
} from "../db"
|
} from "../db"
|
||||||
import {
|
import {
|
||||||
BulkDocsResponse,
|
BulkDocsResponse,
|
||||||
|
ContextUser,
|
||||||
SearchQuery,
|
SearchQuery,
|
||||||
SearchQueryOperators,
|
SearchQueryOperators,
|
||||||
SearchUsersRequest,
|
SearchUsersRequest,
|
||||||
User,
|
User,
|
||||||
ContextUser,
|
|
||||||
DatabaseQueryOpts,
|
DatabaseQueryOpts,
|
||||||
} from "@budibase/types"
|
} from "@budibase/types"
|
||||||
import { getGlobalDB } from "../context"
|
|
||||||
import * as context from "../context"
|
import * as context from "../context"
|
||||||
import { isCreator } from "./utils"
|
import { getGlobalDB } from "../context"
|
||||||
|
|
||||||
type GetOpts = { cleanup?: boolean }
|
type GetOpts = { cleanup?: boolean }
|
||||||
|
|
||||||
|
@ -287,19 +286,6 @@ export async function getUserCount() {
|
||||||
return response.total_rows
|
return response.total_rows
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function getCreatorCount() {
|
|
||||||
let creators = 0
|
|
||||||
async function iterate(startPage?: string) {
|
|
||||||
const page = await paginatedUsers({ bookmark: startPage })
|
|
||||||
creators += page.data.filter(isCreator).length
|
|
||||||
if (page.hasNextPage) {
|
|
||||||
await iterate(page.nextPage)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
await iterate()
|
|
||||||
return creators
|
|
||||||
}
|
|
||||||
|
|
||||||
// used to remove the builder/admin permissions, for processing the
|
// used to remove the builder/admin permissions, for processing the
|
||||||
// user as an app user (they may have some specific role/group
|
// user as an app user (they may have some specific role/group
|
||||||
export function removePortalUserPermissions(user: User | ContextUser) {
|
export function removePortalUserPermissions(user: User | ContextUser) {
|
||||||
|
|
|
@ -10,7 +10,6 @@ import { getAccountByTenantId } from "../accounts"
|
||||||
// extract from shared-core to make easily accessible from backend-core
|
// extract from shared-core to make easily accessible from backend-core
|
||||||
export const isBuilder = sdk.users.isBuilder
|
export const isBuilder = sdk.users.isBuilder
|
||||||
export const isAdmin = sdk.users.isAdmin
|
export const isAdmin = sdk.users.isAdmin
|
||||||
export const isCreator = sdk.users.isCreator
|
|
||||||
export const isGlobalBuilder = sdk.users.isGlobalBuilder
|
export const isGlobalBuilder = sdk.users.isGlobalBuilder
|
||||||
export const isAdminOrBuilder = sdk.users.isAdminOrBuilder
|
export const isAdminOrBuilder = sdk.users.isAdminOrBuilder
|
||||||
export const hasAdminPermissions = sdk.users.hasAdminPermissions
|
export const hasAdminPermissions = sdk.users.hasAdminPermissions
|
||||||
|
|
|
@ -1,54 +0,0 @@
|
||||||
const _ = require('lodash/fp')
|
|
||||||
const {structures} = require("../../../tests")
|
|
||||||
|
|
||||||
jest.mock("../../../src/context")
|
|
||||||
jest.mock("../../../src/db")
|
|
||||||
|
|
||||||
const context = require("../../../src/context")
|
|
||||||
const db = require("../../../src/db")
|
|
||||||
|
|
||||||
const {getCreatorCount} = require('../../../src/users/users')
|
|
||||||
|
|
||||||
describe("Users", () => {
|
|
||||||
|
|
||||||
let getGlobalDBMock
|
|
||||||
let getGlobalUserParamsMock
|
|
||||||
let paginationMock
|
|
||||||
|
|
||||||
beforeEach(() => {
|
|
||||||
jest.resetAllMocks()
|
|
||||||
|
|
||||||
getGlobalDBMock = jest.spyOn(context, "getGlobalDB")
|
|
||||||
getGlobalUserParamsMock = jest.spyOn(db, "getGlobalUserParams")
|
|
||||||
paginationMock = jest.spyOn(db, "pagination")
|
|
||||||
})
|
|
||||||
|
|
||||||
it("Retrieves the number of creators", async () => {
|
|
||||||
const getUsers = (offset, limit, creators = false) => {
|
|
||||||
const range = _.range(offset, limit)
|
|
||||||
const opts = creators ? {builder: {global: true}} : undefined
|
|
||||||
return range.map(() => structures.users.user(opts))
|
|
||||||
}
|
|
||||||
const page1Data = getUsers(0, 8)
|
|
||||||
const page2Data = getUsers(8, 12, true)
|
|
||||||
getGlobalDBMock.mockImplementation(() => ({
|
|
||||||
name : "fake-db",
|
|
||||||
allDocs: () => ({
|
|
||||||
rows: [...page1Data, ...page2Data]
|
|
||||||
})
|
|
||||||
}))
|
|
||||||
paginationMock.mockImplementationOnce(() => ({
|
|
||||||
data: page1Data,
|
|
||||||
hasNextPage: true,
|
|
||||||
nextPage: "1"
|
|
||||||
}))
|
|
||||||
paginationMock.mockImplementation(() => ({
|
|
||||||
data: page2Data,
|
|
||||||
hasNextPage: false,
|
|
||||||
nextPage: undefined
|
|
||||||
}))
|
|
||||||
const creatorsCount = await getCreatorCount()
|
|
||||||
expect(creatorsCount).toBe(4)
|
|
||||||
expect(paginationMock).toHaveBeenCalledTimes(2)
|
|
||||||
})
|
|
||||||
})
|
|
|
@ -72,11 +72,6 @@ export function quotas(): Quotas {
|
||||||
value: 1,
|
value: 1,
|
||||||
triggers: [],
|
triggers: [],
|
||||||
},
|
},
|
||||||
creators: {
|
|
||||||
name: "Creators",
|
|
||||||
value: 1,
|
|
||||||
triggers: [],
|
|
||||||
},
|
|
||||||
userGroups: {
|
userGroups: {
|
||||||
name: "User Groups",
|
name: "User Groups",
|
||||||
value: 1,
|
value: 1,
|
||||||
|
@ -123,10 +118,6 @@ export function customer(): Customer {
|
||||||
export function subscription(): Subscription {
|
export function subscription(): Subscription {
|
||||||
return {
|
return {
|
||||||
amount: 10000,
|
amount: 10000,
|
||||||
amounts: {
|
|
||||||
user: 10000,
|
|
||||||
creator: 0,
|
|
||||||
},
|
|
||||||
cancelAt: undefined,
|
cancelAt: undefined,
|
||||||
currency: "usd",
|
currency: "usd",
|
||||||
currentPeriodEnd: 0,
|
currentPeriodEnd: 0,
|
||||||
|
@ -135,10 +126,6 @@ export function subscription(): Subscription {
|
||||||
duration: PriceDuration.MONTHLY,
|
duration: PriceDuration.MONTHLY,
|
||||||
pastDueAt: undefined,
|
pastDueAt: undefined,
|
||||||
quantity: 0,
|
quantity: 0,
|
||||||
quantities: {
|
|
||||||
user: 0,
|
|
||||||
creator: 0,
|
|
||||||
},
|
|
||||||
status: "active",
|
status: "active",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { MonthlyQuotaName, QuotaUsage } from "@budibase/types"
|
import { MonthlyQuotaName, QuotaUsage } from "@budibase/types"
|
||||||
|
|
||||||
export const usage = (users: number = 0, creators: number = 0): QuotaUsage => {
|
export const usage = (): QuotaUsage => {
|
||||||
return {
|
return {
|
||||||
_id: "usage_quota",
|
_id: "usage_quota",
|
||||||
quotaReset: new Date().toISOString(),
|
quotaReset: new Date().toISOString(),
|
||||||
|
@ -58,8 +58,7 @@ export const usage = (users: number = 0, creators: number = 0): QuotaUsage => {
|
||||||
usageQuota: {
|
usageQuota: {
|
||||||
apps: 0,
|
apps: 0,
|
||||||
plugins: 0,
|
plugins: 0,
|
||||||
users,
|
users: 0,
|
||||||
creators,
|
|
||||||
userGroups: 0,
|
userGroups: 0,
|
||||||
rows: 0,
|
rows: 0,
|
||||||
triggers: {},
|
triggers: {},
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
Subproject commit 56d968bfe6998e1077d3fce4eb1c9e483d1d6fc9
|
Subproject commit f7e7cffe422086d9449c2075a74a378c16caff9d
|
|
@ -3,7 +3,6 @@ import * as syncApps from "./usageQuotas/syncApps"
|
||||||
import * as syncRows from "./usageQuotas/syncRows"
|
import * as syncRows from "./usageQuotas/syncRows"
|
||||||
import * as syncPlugins from "./usageQuotas/syncPlugins"
|
import * as syncPlugins from "./usageQuotas/syncPlugins"
|
||||||
import * as syncUsers from "./usageQuotas/syncUsers"
|
import * as syncUsers from "./usageQuotas/syncUsers"
|
||||||
import * as syncCreators from "./usageQuotas/syncCreators"
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Synchronise quotas to the state of the db.
|
* Synchronise quotas to the state of the db.
|
||||||
|
@ -14,6 +13,5 @@ export const run = async () => {
|
||||||
await syncRows.run()
|
await syncRows.run()
|
||||||
await syncPlugins.run()
|
await syncPlugins.run()
|
||||||
await syncUsers.run()
|
await syncUsers.run()
|
||||||
await syncCreators.run()
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,13 +0,0 @@
|
||||||
import { users } from "@budibase/backend-core"
|
|
||||||
import { quotas } from "@budibase/pro"
|
|
||||||
import { QuotaUsageType, StaticQuotaName } from "@budibase/types"
|
|
||||||
|
|
||||||
export const run = async () => {
|
|
||||||
const creatorCount = await users.getCreatorCount()
|
|
||||||
console.log(`Syncing creator count: ${creatorCount}`)
|
|
||||||
await quotas.setUsage(
|
|
||||||
creatorCount,
|
|
||||||
StaticQuotaName.CREATORS,
|
|
||||||
QuotaUsageType.STATIC
|
|
||||||
)
|
|
||||||
}
|
|
|
@ -1,26 +0,0 @@
|
||||||
import TestConfig from "../../../../tests/utilities/TestConfiguration"
|
|
||||||
import * as syncCreators from "../syncCreators"
|
|
||||||
import { quotas } from "@budibase/pro"
|
|
||||||
|
|
||||||
describe("syncCreators", () => {
|
|
||||||
let config = new TestConfig(false)
|
|
||||||
|
|
||||||
beforeEach(async () => {
|
|
||||||
await config.init()
|
|
||||||
})
|
|
||||||
|
|
||||||
afterAll(config.end)
|
|
||||||
|
|
||||||
it("syncs creators", async () => {
|
|
||||||
return config.doInContext(null, async () => {
|
|
||||||
await config.createUser({ admin: true })
|
|
||||||
|
|
||||||
await syncCreators.run()
|
|
||||||
|
|
||||||
const usageDoc = await quotas.getQuotaUsage()
|
|
||||||
// default + additional creator
|
|
||||||
const creatorsCount = 2
|
|
||||||
expect(usageDoc.usageQuota.creators).toBe(creatorsCount)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
|
@ -6,7 +6,6 @@ import {
|
||||||
InternalTable,
|
InternalTable,
|
||||||
} from "@budibase/types"
|
} from "@budibase/types"
|
||||||
import { getProdAppID } from "./applications"
|
import { getProdAppID } from "./applications"
|
||||||
import * as _ from "lodash/fp"
|
|
||||||
|
|
||||||
// checks if a user is specifically a builder, given an app ID
|
// checks if a user is specifically a builder, given an app ID
|
||||||
export function isBuilder(user: User | ContextUser, appId?: string): boolean {
|
export function isBuilder(user: User | ContextUser, appId?: string): boolean {
|
||||||
|
@ -59,18 +58,6 @@ export function hasAppBuilderPermissions(user?: User | ContextUser): boolean {
|
||||||
return !isGlobalBuilder && appLength != null && appLength > 0
|
return !isGlobalBuilder && appLength != null && appLength > 0
|
||||||
}
|
}
|
||||||
|
|
||||||
export function hasAppCreatorPermissions(user?: User | ContextUser): boolean {
|
|
||||||
if (!user) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
return _.flow(
|
|
||||||
_.get("roles"),
|
|
||||||
_.values,
|
|
||||||
_.find(x => ["CREATOR", "ADMIN"].includes(x)),
|
|
||||||
x => !!x
|
|
||||||
)(user)
|
|
||||||
}
|
|
||||||
|
|
||||||
// checks if a user is capable of building any app
|
// checks if a user is capable of building any app
|
||||||
export function hasBuilderPermissions(user?: User | ContextUser): boolean {
|
export function hasBuilderPermissions(user?: User | ContextUser): boolean {
|
||||||
if (!user) {
|
if (!user) {
|
||||||
|
@ -87,18 +74,6 @@ export function hasAdminPermissions(user?: User | ContextUser): boolean {
|
||||||
return !!user.admin?.global
|
return !!user.admin?.global
|
||||||
}
|
}
|
||||||
|
|
||||||
export function isCreator(user?: User | ContextUser): boolean {
|
|
||||||
if (!user) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
return (
|
|
||||||
isGlobalBuilder(user) ||
|
|
||||||
hasAdminPermissions(user) ||
|
|
||||||
hasAppBuilderPermissions(user) ||
|
|
||||||
hasAppCreatorPermissions(user)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
export function getGlobalUserID(userId?: string): string | undefined {
|
export function getGlobalUserID(userId?: string): string | undefined {
|
||||||
if (typeof userId !== "string") {
|
if (typeof userId !== "string") {
|
||||||
return userId
|
return userId
|
||||||
|
|
|
@ -32,7 +32,6 @@ export interface StaticUsage {
|
||||||
[StaticQuotaName.APPS]: number
|
[StaticQuotaName.APPS]: number
|
||||||
[StaticQuotaName.PLUGINS]: number
|
[StaticQuotaName.PLUGINS]: number
|
||||||
[StaticQuotaName.USERS]: number
|
[StaticQuotaName.USERS]: number
|
||||||
[StaticQuotaName.CREATORS]: number
|
|
||||||
[StaticQuotaName.USER_GROUPS]: number
|
[StaticQuotaName.USER_GROUPS]: number
|
||||||
[StaticQuotaName.ROWS]: number
|
[StaticQuotaName.ROWS]: number
|
||||||
triggers: {
|
triggers: {
|
||||||
|
|
|
@ -1,8 +1,5 @@
|
||||||
export enum FeatureFlag {
|
export enum FeatureFlag {
|
||||||
LICENSING = "LICENSING",
|
LICENSING = "LICENSING",
|
||||||
// Feature IDs in Posthog
|
|
||||||
PER_CREATOR_PER_USER_PRICE = "18873",
|
|
||||||
PER_CREATOR_PER_USER_PRICE_ALERT = "18530",
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface TenantFeatureFlags {
|
export interface TenantFeatureFlags {
|
||||||
|
|
|
@ -5,17 +5,10 @@ export interface Customer {
|
||||||
currency: string | null | undefined
|
currency: string | null | undefined
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface SubscriptionItems {
|
|
||||||
user: number | undefined
|
|
||||||
creator: number | undefined
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface Subscription {
|
export interface Subscription {
|
||||||
amount: number
|
amount: number
|
||||||
amounts: SubscriptionItems | undefined
|
|
||||||
currency: string
|
currency: string
|
||||||
quantity: number
|
quantity: number
|
||||||
quantities: SubscriptionItems | undefined
|
|
||||||
duration: PriceDuration
|
duration: PriceDuration
|
||||||
cancelAt: number | null | undefined
|
cancelAt: number | null | undefined
|
||||||
currentPeriodStart: number
|
currentPeriodStart: number
|
||||||
|
|
|
@ -4,9 +4,7 @@ export enum PlanType {
|
||||||
PRO = "pro",
|
PRO = "pro",
|
||||||
/** @deprecated */
|
/** @deprecated */
|
||||||
TEAM = "team",
|
TEAM = "team",
|
||||||
/** @deprecated */
|
|
||||||
PREMIUM = "premium",
|
PREMIUM = "premium",
|
||||||
PREMIUM_PLUS = "premium_plus",
|
|
||||||
BUSINESS = "business",
|
BUSINESS = "business",
|
||||||
ENTERPRISE = "enterprise",
|
ENTERPRISE = "enterprise",
|
||||||
}
|
}
|
||||||
|
@ -28,12 +26,10 @@ export interface AvailablePrice {
|
||||||
currency: string
|
currency: string
|
||||||
duration: PriceDuration
|
duration: PriceDuration
|
||||||
priceId: string
|
priceId: string
|
||||||
type?: string
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum PlanModel {
|
export enum PlanModel {
|
||||||
PER_USER = "perUser",
|
PER_USER = "perUser",
|
||||||
PER_CREATOR_PER_USER = "per_creator_per_user",
|
|
||||||
DAY_PASS = "dayPass",
|
DAY_PASS = "dayPass",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -14,7 +14,6 @@ export enum StaticQuotaName {
|
||||||
ROWS = "rows",
|
ROWS = "rows",
|
||||||
APPS = "apps",
|
APPS = "apps",
|
||||||
USERS = "users",
|
USERS = "users",
|
||||||
CREATORS = "creators",
|
|
||||||
USER_GROUPS = "userGroups",
|
USER_GROUPS = "userGroups",
|
||||||
PLUGINS = "plugins",
|
PLUGINS = "plugins",
|
||||||
}
|
}
|
||||||
|
@ -68,7 +67,6 @@ export type StaticQuotas = {
|
||||||
[StaticQuotaName.ROWS]: Quota
|
[StaticQuotaName.ROWS]: Quota
|
||||||
[StaticQuotaName.APPS]: Quota
|
[StaticQuotaName.APPS]: Quota
|
||||||
[StaticQuotaName.USERS]: Quota
|
[StaticQuotaName.USERS]: Quota
|
||||||
[StaticQuotaName.CREATORS]: Quota
|
|
||||||
[StaticQuotaName.USER_GROUPS]: Quota
|
[StaticQuotaName.USER_GROUPS]: Quota
|
||||||
[StaticQuotaName.PLUGINS]: Quota
|
[StaticQuotaName.PLUGINS]: Quota
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue