From 70186524457044b959c844205a88c635dbb577be Mon Sep 17 00:00:00 2001 From: Rory Powell Date: Tue, 20 Sep 2022 10:13:40 +0100 Subject: [PATCH 1/4] Change 'Plugins' nav item badge to 'Beta' --- packages/builder/src/pages/builder/portal/_layout.svelte | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/builder/src/pages/builder/portal/_layout.svelte b/packages/builder/src/pages/builder/portal/_layout.svelte index bdf18ab508..38017fdc42 100644 --- a/packages/builder/src/pages/builder/portal/_layout.svelte +++ b/packages/builder/src/pages/builder/portal/_layout.svelte @@ -56,7 +56,7 @@ { title: "Plugins", href: "/builder/portal/manage/plugins", - badge: "New", + badge: "Beta", }, { From f699bf1b560412af1c1ad2615af57aa6aadb627b Mon Sep 17 00:00:00 2001 From: Rory Powell Date: Tue, 20 Sep 2022 10:15:28 +0100 Subject: [PATCH 2/4] Wrap licensing banners and modals in feature flag, disable logo --- .../portal/licensing/LicensingOverlays.svelte | 8 +- .../builder/src/stores/portal/licensing.js | 138 +++++++++--------- packages/client/src/licensing/constants.js | 1 + packages/client/src/licensing/features.js | 5 +- 4 files changed, 82 insertions(+), 70 deletions(-) diff --git a/packages/builder/src/components/portal/licensing/LicensingOverlays.svelte b/packages/builder/src/components/portal/licensing/LicensingOverlays.svelte index 8431b860e8..736aac862f 100644 --- a/packages/builder/src/components/portal/licensing/LicensingOverlays.svelte +++ b/packages/builder/src/components/portal/licensing/LicensingOverlays.svelte @@ -8,6 +8,7 @@ import { ExpiringKeys } from "./constants" import { getBanners } from "./licensingBanners" import { banner } from "@budibase/bbui" + import { FEATURE_FLAGS, isEnabled } from "../../../helpers/featureFlags" const oneDayInSeconds = 86400 @@ -81,7 +82,12 @@ } } - $: if (userLoaded && licensingLoaded && loaded) { + $: if ( + userLoaded && + licensingLoaded && + loaded && + isEnabled(FEATURE_FLAGS.LICENSING) + ) { queuedModals = processModals() queuedBanners = getBanners() showNextModal() diff --git a/packages/builder/src/stores/portal/licensing.js b/packages/builder/src/stores/portal/licensing.js index 9d63a9edb5..e2b4570302 100644 --- a/packages/builder/src/stores/portal/licensing.js +++ b/packages/builder/src/stores/portal/licensing.js @@ -3,10 +3,12 @@ import { API } from "api" import { auth } from "stores/portal" import { Constants } from "@budibase/frontend-core" import { StripeStatus } from "components/portal/licensing/constants" +import { FEATURE_FLAGS, isEnabled } from "../../helpers/featureFlags" export const createLicensingStore = () => { const DEFAULT = { plans: {}, + usageMetrics: {}, } const oneDayInMilliseconds = 86400000 @@ -27,78 +29,80 @@ export const createLicensingStore = () => { }) }, getUsageMetrics: async () => { - const quota = get(store).quotaUsage - const license = get(auth).user.license - const now = new Date() + if (isEnabled(FEATURE_FLAGS.LICENSING)) { + const quota = get(store).quotaUsage + const license = get(auth).user.license + const now = new Date() - const getMetrics = (keys, license, quota) => { - if (!license || !quota || !keys) { - return {} + const getMetrics = (keys, license, quota) => { + if (!license || !quota || !keys) { + return {} + } + return keys.reduce((acc, key) => { + const quotaLimit = license[key].value + const quotaUsed = (quota[key] / quotaLimit) * 100 + acc[key] = quotaLimit > -1 ? Math.round(quotaUsed) : -1 + return acc + }, {}) } - return keys.reduce((acc, key) => { - const quotaLimit = license[key].value - const quotaUsed = (quota[key] / quotaLimit) * 100 - acc[key] = quotaLimit > -1 ? Math.round(quotaUsed) : -1 - return acc - }, {}) - } - const monthlyMetrics = getMetrics( - ["dayPasses", "queries", "automations"], - license.quotas.usage.monthly, - quota.monthly.current - ) - const staticMetrics = getMetrics( - ["apps", "rows"], - license.quotas.usage.static, - quota.usageQuota - ) - - const getDaysBetween = (dateStart, dateEnd) => { - return dateEnd > dateStart - ? Math.round( - (dateEnd.getTime() - dateStart.getTime()) / oneDayInMilliseconds - ) - : 0 - } - - const quotaResetDate = new Date(quota.quotaReset) - const quotaResetDaysRemaining = getDaysBetween(now, quotaResetDate) - - const accountDowngraded = - license?.billing?.subscription?.downgradeAt && - license?.billing?.subscription?.downgradeAt <= now.getTime() && - license?.billing?.subscription?.status === StripeStatus.PAST_DUE && - license?.plan.type === Constants.PlanType.FREE - - const pastDueAtMilliseconds = license?.billing?.subscription?.pastDueAt - const downgradeAtMilliseconds = - license?.billing?.subscription?.downgradeAt - let pastDueDaysRemaining - let pastDueEndDate - - if (pastDueAtMilliseconds && downgradeAtMilliseconds) { - pastDueEndDate = new Date(downgradeAtMilliseconds) - pastDueDaysRemaining = getDaysBetween( - new Date(pastDueAtMilliseconds), - pastDueEndDate + const monthlyMetrics = getMetrics( + ["dayPasses", "queries", "automations"], + license.quotas.usage.monthly, + quota.monthly.current + ) + const staticMetrics = getMetrics( + ["apps", "rows"], + license.quotas.usage.static, + quota.usageQuota ) - } - store.update(state => { - return { - ...state, - usageMetrics: { ...monthlyMetrics, ...staticMetrics }, - quotaResetDaysRemaining, - quotaResetDate, - accountDowngraded, - accountPastDue: pastDueAtMilliseconds != null, - pastDueEndDate, - pastDueDaysRemaining, - isFreePlan: () => { - return license?.plan.type === Constants.PlanType.FREE - }, + const getDaysBetween = (dateStart, dateEnd) => { + return dateEnd > dateStart + ? Math.round( + (dateEnd.getTime() - dateStart.getTime()) / oneDayInMilliseconds + ) + : 0 } - }) + + const quotaResetDate = new Date(quota.quotaReset) + const quotaResetDaysRemaining = getDaysBetween(now, quotaResetDate) + + const accountDowngraded = + license?.billing?.subscription?.downgradeAt && + license?.billing?.subscription?.downgradeAt <= now.getTime() && + license?.billing?.subscription?.status === StripeStatus.PAST_DUE && + license?.plan.type === Constants.PlanType.FREE + + const pastDueAtMilliseconds = license?.billing?.subscription?.pastDueAt + const downgradeAtMilliseconds = + license?.billing?.subscription?.downgradeAt + let pastDueDaysRemaining + let pastDueEndDate + + if (pastDueAtMilliseconds && downgradeAtMilliseconds) { + pastDueEndDate = new Date(downgradeAtMilliseconds) + pastDueDaysRemaining = getDaysBetween( + new Date(pastDueAtMilliseconds), + pastDueEndDate + ) + } + + store.update(state => { + return { + ...state, + usageMetrics: { ...monthlyMetrics, ...staticMetrics }, + quotaResetDaysRemaining, + quotaResetDate, + accountDowngraded, + accountPastDue: pastDueAtMilliseconds != null, + pastDueEndDate, + pastDueDaysRemaining, + isFreePlan: () => { + return license?.plan.type === Constants.PlanType.FREE + }, + } + }) + } }, } diff --git a/packages/client/src/licensing/constants.js b/packages/client/src/licensing/constants.js index dd6e8eb405..57454bc37a 100644 --- a/packages/client/src/licensing/constants.js +++ b/packages/client/src/licensing/constants.js @@ -1,5 +1,6 @@ export const PlanType = { FREE: "free", + PRO: "pro", TEAM: "team", BUSINESS: "business", ENTERPRISE: "enterprise", diff --git a/packages/client/src/licensing/features.js b/packages/client/src/licensing/features.js index 1f0d4a4870..98e03b77d2 100644 --- a/packages/client/src/licensing/features.js +++ b/packages/client/src/licensing/features.js @@ -1,5 +1,6 @@ -import { isFreePlan } from "./utils.js" +// import { isFreePlan } from "./utils.js" export const logoEnabled = () => { - return isFreePlan() + return false + // return isFreePlan() } From f7ec431a450ca4a9be6af997ae7aec439a63d1e0 Mon Sep 17 00:00:00 2001 From: Rory Powell Date: Tue, 20 Sep 2022 10:20:36 +0100 Subject: [PATCH 3/4] Move tenancy/utils to db/tenancy to resolve circular imports between tenancy and db package. This should remove all reliance on the tenancy package from the db package --- packages/backend-core/src/context/index.ts | 2 +- .../backend-core/src/{tenancy/utils.ts => db/tenancy.ts} | 2 +- packages/backend-core/src/db/utils.ts | 3 ++- packages/backend-core/src/migrations/migrations.ts | 8 ++------ packages/backend-core/src/tenancy/index.ts | 2 -- packages/backend-core/src/tenancy/tenancy.ts | 4 ++-- packages/server/src/api/controllers/cloud.js | 7 ++----- 7 files changed, 10 insertions(+), 18 deletions(-) rename packages/backend-core/src/{tenancy/utils.ts => db/tenancy.ts} (91%) diff --git a/packages/backend-core/src/context/index.ts b/packages/backend-core/src/context/index.ts index 78ce764d55..8e3cf8a0a2 100644 --- a/packages/backend-core/src/context/index.ts +++ b/packages/backend-core/src/context/index.ts @@ -2,7 +2,7 @@ import env from "../environment" import { SEPARATOR, DocumentType } from "../db/constants" import cls from "./FunctionContext" import { dangerousGetDB, closeDB } from "../db" -import { baseGlobalDBName } from "../tenancy/utils" +import { baseGlobalDBName } from "../db/tenancy" import { IdentityContext } from "@budibase/types" import { DEFAULT_TENANT_ID as _DEFAULT_TENANT_ID } from "../constants" import { ContextKey } from "./constants" diff --git a/packages/backend-core/src/tenancy/utils.ts b/packages/backend-core/src/db/tenancy.ts similarity index 91% rename from packages/backend-core/src/tenancy/utils.ts rename to packages/backend-core/src/db/tenancy.ts index f99f1e30af..d920f7cd41 100644 --- a/packages/backend-core/src/tenancy/utils.ts +++ b/packages/backend-core/src/db/tenancy.ts @@ -1,5 +1,5 @@ import { DEFAULT_TENANT_ID } from "../constants" -import { StaticDatabases, SEPARATOR } from "../db/constants" +import { StaticDatabases, SEPARATOR } from "./constants" import { getTenantId } from "../context" export const getGlobalDBName = (tenantId?: string) => { diff --git a/packages/backend-core/src/db/utils.ts b/packages/backend-core/src/db/utils.ts index cc20b87a58..a12c6bed4f 100644 --- a/packages/backend-core/src/db/utils.ts +++ b/packages/backend-core/src/db/utils.ts @@ -3,7 +3,7 @@ import { DEFAULT_TENANT_ID, Configs } from "../constants" import env from "../environment" import { SEPARATOR, DocumentType, UNICODE_MAX, ViewName } from "./constants" import { getTenantId, getGlobalDB } from "../context" -import { getGlobalDBName } from "../tenancy" +import { getGlobalDBName } from "./tenancy" import fetch from "node-fetch" import { doWithDB, allDbs } from "./index" import { getCouchInfo } from "./pouch" @@ -16,6 +16,7 @@ import * as events from "../events" export * from "./constants" export * from "./conversions" export { default as Replication } from "./Replication" +export * from "./tenancy" /** * Generates a new app ID. diff --git a/packages/backend-core/src/migrations/migrations.ts b/packages/backend-core/src/migrations/migrations.ts index ca238ff80e..90a12acec2 100644 --- a/packages/backend-core/src/migrations/migrations.ts +++ b/packages/backend-core/src/migrations/migrations.ts @@ -3,12 +3,8 @@ import { doWithDB } from "../db" import { DocumentType, StaticDatabases } from "../db/constants" import { getAllApps } from "../db/utils" import environment from "../environment" -import { - doInTenant, - getTenantIds, - getGlobalDBName, - getTenantId, -} from "../tenancy" +import { doInTenant, getTenantIds, getTenantId } from "../tenancy" +import { getGlobalDBName } from "../db/tenancy" import * as context from "../context" import { DEFINITIONS } from "." import { diff --git a/packages/backend-core/src/tenancy/index.ts b/packages/backend-core/src/tenancy/index.ts index d1ccbbf001..e0006abab2 100644 --- a/packages/backend-core/src/tenancy/index.ts +++ b/packages/backend-core/src/tenancy/index.ts @@ -1,11 +1,9 @@ import * as context from "../context" import * as tenancy from "./tenancy" -import * as utils from "./utils" const pkg = { ...context, ...tenancy, - ...utils, } export = pkg diff --git a/packages/backend-core/src/tenancy/tenancy.ts b/packages/backend-core/src/tenancy/tenancy.ts index 1c71935eb0..a100888212 100644 --- a/packages/backend-core/src/tenancy/tenancy.ts +++ b/packages/backend-core/src/tenancy/tenancy.ts @@ -1,7 +1,7 @@ import { doWithDB } from "../db" import { queryPlatformView } from "../db/views" import { StaticDatabases, ViewName } from "../db/constants" -import { getGlobalDBName } from "./utils" +import { getGlobalDBName } from "../db/tenancy" import { getTenantId, DEFAULT_TENANT_ID, @@ -9,7 +9,7 @@ import { getTenantIDFromAppID, } from "../context" import env from "../environment" -import { PlatformUser, PlatformUserByEmail } from "@budibase/types" +import { PlatformUser } from "@budibase/types" const TENANT_DOC = StaticDatabases.PLATFORM_INFO.docs.tenants const PLATFORM_INFO_DB = StaticDatabases.PLATFORM_INFO.name diff --git a/packages/server/src/api/controllers/cloud.js b/packages/server/src/api/controllers/cloud.js index 7be8b14bcd..1e6abb1d3b 100644 --- a/packages/server/src/api/controllers/cloud.js +++ b/packages/server/src/api/controllers/cloud.js @@ -1,15 +1,12 @@ const env = require("../../environment") -const { getAllApps } = require("@budibase/backend-core/db") +const { getAllApps, getGlobalDBName } = require("@budibase/backend-core/db") const { exportDB, sendTempFile, readFileSync, } = require("../../utilities/fileSystem") const { stringToReadStream } = require("../../utilities") -const { - getGlobalDBName, - getGlobalDB, -} = require("@budibase/backend-core/tenancy") +const { getGlobalDB } = require("@budibase/backend-core/tenancy") const { create } = require("./application") const { getDocParams, DocumentType, isDevAppID } = require("../../db/utils") From 72abfd8e52ff9f7b13589681c913c9326bca1937 Mon Sep 17 00:00:00 2001 From: Rory Powell Date: Tue, 20 Sep 2022 10:59:12 +0100 Subject: [PATCH 4/4] Invert template display logic to fix cypress --- packages/builder/src/components/common/TemplateDisplay.svelte | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/builder/src/components/common/TemplateDisplay.svelte b/packages/builder/src/components/common/TemplateDisplay.svelte index 6041a904fd..d6ba4bd8e7 100644 --- a/packages/builder/src/components/common/TemplateDisplay.svelte +++ b/packages/builder/src/components/common/TemplateDisplay.svelte @@ -97,7 +97,7 @@ backgroundColour={templateEntry.background} icon={templateEntry.icon} > - {#if $licensing?.usageMetrics?.apps < 100} + {#if !($licensing?.usageMetrics?.apps >= 100)}