From 87dbe66cccf5515f4b10de72956e1af8eadbd687 Mon Sep 17 00:00:00 2001 From: Adria Navarro Date: Tue, 22 Oct 2024 10:23:27 +0200 Subject: [PATCH 01/11] Update user column data on import --- .../server/src/api/controllers/application.ts | 70 +++++++++++++++++++ 1 file changed, 70 insertions(+) diff --git a/packages/server/src/api/controllers/application.ts b/packages/server/src/api/controllers/application.ts index 59f67540fe..1af797a14e 100644 --- a/packages/server/src/api/controllers/application.ts +++ b/packages/server/src/api/controllers/application.ts @@ -23,6 +23,7 @@ import { cache, context, db as dbCore, + docIds, env as envCore, ErrorCode, events, @@ -54,6 +55,10 @@ import { DuplicateAppResponse, UpdateAppRequest, UpdateAppResponse, + Database, + FieldType, + BBReferenceFieldSubType, + Row, } from "@budibase/types" import { BASE_LAYOUT_PROP_IDS } from "../../constants/layouts" import sdk from "../../sdk" @@ -279,6 +284,11 @@ async function performAppCreate(ctx: UserCtx) { const instance = await createInstance(appId, instanceConfig) const db = context.getAppDB() + const isTemplate = instanceConfig.templateString + if (!isTemplate) { + await updateUserColumns(appId, db, ctx.user._id!) + } + const newApplication: App = { _id: DocumentType.APP_METADATA, _rev: undefined, @@ -375,6 +385,66 @@ async function performAppCreate(ctx: UserCtx) { }) } +async function updateUserColumns( + appId: string, + db: Database, + toUserId: string +) { + await context.doInAppContext(appId, async () => { + const allTables = await sdk.tables.getAllTables() + const tablesWithUserColumns = [] + for (const table of allTables) { + const userColumns = Object.values(table.schema).filter( + f => + (f.type === FieldType.BB_REFERENCE || + f.type === FieldType.BB_REFERENCE_SINGLE) && + f.subtype === BBReferenceFieldSubType.USER + ) + if (!userColumns.length) { + continue + } + + tablesWithUserColumns.push({ + tableId: table._id!, + columns: userColumns.map(c => c.name), + }) + } + + const docsToUpdate = [] + + for (const { tableId, columns } of tablesWithUserColumns) { + const docs = await db.allDocs( + docIds.getRowParams(tableId, null, { include_docs: true }) + ) + const rows = docs.rows.map(d => d.doc!) + + for (const row of rows) { + let shouldUpdate = false + const updatedColumns = columns.reduce((newColumns, column) => { + if (row[column]) { + shouldUpdate = true + if (Array.isArray(row[column])) { + newColumns[column] = row[column]?.map(() => toUserId) + } else if (row[column]) { + newColumns[column] = toUserId + } + } + return newColumns + }, {}) + + if (shouldUpdate) { + docsToUpdate.push({ + ...row, + ...updatedColumns, + }) + } + } + } + + await db.bulkDocs(docsToUpdate) + }) +} + async function creationEvents(request: any, app: App) { let creationFns: ((app: App) => Promise)[] = [] From cb5082a0c0ec47129926681a1fc8eb4eff60231f Mon Sep 17 00:00:00 2001 From: Adria Navarro Date: Tue, 22 Oct 2024 10:25:09 +0200 Subject: [PATCH 02/11] Fix check --- packages/server/src/api/controllers/application.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/server/src/api/controllers/application.ts b/packages/server/src/api/controllers/application.ts index 1af797a14e..d0021db2cc 100644 --- a/packages/server/src/api/controllers/application.ts +++ b/packages/server/src/api/controllers/application.ts @@ -284,8 +284,7 @@ async function performAppCreate(ctx: UserCtx) { const instance = await createInstance(appId, instanceConfig) const db = context.getAppDB() - const isTemplate = instanceConfig.templateString - if (!isTemplate) { + if (instanceConfig.useTemplate) { await updateUserColumns(appId, db, ctx.user._id!) } From 8dee7b2c45504bfe7a9121f3ae9801d2d0f271c4 Mon Sep 17 00:00:00 2001 From: Adria Navarro Date: Tue, 22 Oct 2024 11:56:19 +0200 Subject: [PATCH 03/11] Remove obsolete templateString --- .../server/src/api/controllers/application.ts | 22 +++---------------- .../src/api/routes/tests/application.spec.ts | 1 - .../server/src/api/routes/utils/validators.ts | 8 ++----- packages/server/src/utilities/index.ts | 12 ---------- packages/types/src/api/web/application.ts | 1 - 5 files changed, 5 insertions(+), 39 deletions(-) diff --git a/packages/server/src/api/controllers/application.ts b/packages/server/src/api/controllers/application.ts index d0021db2cc..1be301dd9d 100644 --- a/packages/server/src/api/controllers/application.ts +++ b/packages/server/src/api/controllers/application.ts @@ -36,7 +36,6 @@ import { import { USERS_TABLE_SCHEMA, DEFAULT_BB_DATASOURCE_ID } from "../../constants" import { buildDefaultDocs } from "../../db/defaultData/datasource_bb_default" import { removeAppFromUserRoles } from "../../utilities/workerRequests" -import { stringToReadStream } from "../../utilities" import { doesUserHaveLock } from "../../utilities/redis" import { cleanupAutomations } from "../../automations/utils" import { getUniqueRows } from "../../utilities/usageQuota/rows" @@ -128,7 +127,6 @@ function checkAppName( } interface AppTemplate { - templateString?: string useTemplate?: string file?: { type?: string @@ -153,14 +151,7 @@ async function createInstance(appId: string, template: AppTemplate) { await createRoutingView() await createAllSearchIndex() - // replicate the template data to the instance DB - // this is currently very hard to test, downloading and importing template files - if (template && template.templateString) { - const { ok } = await db.load(stringToReadStream(template.templateString)) - if (!ok) { - throw "Error loading database dump from memory." - } - } else if (template && template.useTemplate === "true") { + if (template && template.useTemplate === "true") { await sdk.backups.importApp(appId, db, template) } else { // create the users table @@ -248,14 +239,8 @@ export async function fetchAppPackage( async function performAppCreate(ctx: UserCtx) { const apps = (await dbCore.getAllApps({ dev: true })) as App[] - const { - name, - url, - encryptionPassword, - useTemplate, - templateKey, - templateString, - } = ctx.request.body + const { name, url, encryptionPassword, useTemplate, templateKey } = + ctx.request.body checkAppName(ctx, apps, name) const appUrl = sdk.applications.getAppUrl({ name, url }) @@ -264,7 +249,6 @@ async function performAppCreate(ctx: UserCtx) { const instanceConfig: AppTemplate = { useTemplate, key: templateKey, - templateString, } if (ctx.request.files && ctx.request.files.templateFile) { instanceConfig.file = { diff --git a/packages/server/src/api/routes/tests/application.spec.ts b/packages/server/src/api/routes/tests/application.spec.ts index fe8250bde5..f10f4089bf 100644 --- a/packages/server/src/api/routes/tests/application.spec.ts +++ b/packages/server/src/api/routes/tests/application.spec.ts @@ -141,7 +141,6 @@ describe("/applications", () => { name: utils.newid(), useTemplate: "true", templateKey: "test", - templateString: "{}", }) expect(app._id).toBeDefined() expect(events.app.created).toHaveBeenCalledTimes(1) diff --git a/packages/server/src/api/routes/utils/validators.ts b/packages/server/src/api/routes/utils/validators.ts index d9dbd96b16..02a1a2d060 100644 --- a/packages/server/src/api/routes/utils/validators.ts +++ b/packages/server/src/api/routes/utils/validators.ts @@ -355,9 +355,7 @@ export function applicationValidator(opts = { isCreate: true }) { _id: OPTIONAL_STRING, _rev: OPTIONAL_STRING, url: OPTIONAL_STRING, - template: Joi.object({ - templateString: OPTIONAL_STRING, - }), + template: Joi.object({}), } const appNameValidator = Joi.string() @@ -390,9 +388,7 @@ export function applicationValidator(opts = { isCreate: true }) { _rev: OPTIONAL_STRING, name: appNameValidator, url: OPTIONAL_STRING, - template: Joi.object({ - templateString: OPTIONAL_STRING, - }).unknown(true), + template: Joi.object({}).unknown(true), snippets: snippetValidator, }).unknown(true) ) diff --git a/packages/server/src/utilities/index.ts b/packages/server/src/utilities/index.ts index ce6f2345ca..129137a72e 100644 --- a/packages/server/src/utilities/index.ts +++ b/packages/server/src/utilities/index.ts @@ -2,9 +2,6 @@ import env from "../environment" import { context } from "@budibase/backend-core" import { generateMetadataID } from "../db/utils" import { Document } from "@budibase/types" -import stream from "stream" - -const Readable = stream.Readable export function wait(ms: number) { return new Promise(resolve => setTimeout(resolve, ms)) @@ -98,15 +95,6 @@ export function escapeDangerousCharacters(string: string) { .replace(/[\t]/g, "\\t") } -export function stringToReadStream(string: string) { - return new Readable({ - read() { - this.push(string) - this.push(null) - }, - }) -} - export function formatBytes(bytes: string) { const units = ["B", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"] const byteIncrements = 1024 diff --git a/packages/types/src/api/web/application.ts b/packages/types/src/api/web/application.ts index bb4d8c7f72..8fa417fb64 100644 --- a/packages/types/src/api/web/application.ts +++ b/packages/types/src/api/web/application.ts @@ -10,7 +10,6 @@ export interface CreateAppRequest { templateFile?: string includeSampleData?: boolean encryptionPassword?: string - templateString?: string file?: { path: string } } From ea1d893ab8a127d5364e3e168935fa6a95a0f79a Mon Sep 17 00:00:00 2001 From: Adria Navarro Date: Tue, 22 Oct 2024 12:06:24 +0200 Subject: [PATCH 04/11] Remove unused fields --- packages/types/src/api/web/application.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/types/src/api/web/application.ts b/packages/types/src/api/web/application.ts index 8fa417fb64..e4a70c7fd4 100644 --- a/packages/types/src/api/web/application.ts +++ b/packages/types/src/api/web/application.ts @@ -8,7 +8,6 @@ export interface CreateAppRequest { templateName?: string templateKey?: string templateFile?: string - includeSampleData?: boolean encryptionPassword?: string file?: { path: string } } From 5fe2a1d33e8935d0dd185b627d163aa0c73cc039 Mon Sep 17 00:00:00 2001 From: Adria Navarro Date: Tue, 22 Oct 2024 12:23:36 +0200 Subject: [PATCH 05/11] Rename and pass just required data --- .../src/components/start/CreateAppModal.svelte | 13 ++++++++----- packages/server/src/api/controllers/application.ts | 4 ++-- .../server/src/api/routes/tests/application.spec.ts | 4 ++-- .../server/src/tests/utilities/api/application.ts | 4 ++-- packages/types/src/api/web/application.ts | 2 +- 5 files changed, 15 insertions(+), 12 deletions(-) diff --git a/packages/builder/src/components/start/CreateAppModal.svelte b/packages/builder/src/components/start/CreateAppModal.svelte index b5fed9cdc1..83ed089006 100644 --- a/packages/builder/src/components/start/CreateAppModal.svelte +++ b/packages/builder/src/components/start/CreateAppModal.svelte @@ -118,14 +118,17 @@ if ($values.url) { data.append("url", $values.url.trim()) } - data.append("useTemplate", template != null) - if (template) { - data.append("templateName", template.name) - data.append("templateKey", template.key) - data.append("templateFile", $values.file) + + if (template?.fromFile) { + data.append("useTemplate", true) + data.append("fileToImport", $values.file) if ($values.encryptionPassword?.trim()) { data.append("encryptionPassword", $values.encryptionPassword.trim()) } + } else if (template) { + data.append("useTemplate", true) + data.append("templateName", template.name) + data.append("templateKey", template.key) } // Create App diff --git a/packages/server/src/api/controllers/application.ts b/packages/server/src/api/controllers/application.ts index 1be301dd9d..fbcf51c1de 100644 --- a/packages/server/src/api/controllers/application.ts +++ b/packages/server/src/api/controllers/application.ts @@ -250,9 +250,9 @@ async function performAppCreate(ctx: UserCtx) { useTemplate, key: templateKey, } - if (ctx.request.files && ctx.request.files.templateFile) { + if (ctx.request.files && ctx.request.files.fileToImport) { instanceConfig.file = { - ...(ctx.request.files.templateFile as any), + ...(ctx.request.files.fileToImport as any), password: encryptionPassword, } } else if (typeof ctx.request.body.file?.path === "string") { diff --git a/packages/server/src/api/routes/tests/application.spec.ts b/packages/server/src/api/routes/tests/application.spec.ts index f10f4089bf..b654e577ba 100644 --- a/packages/server/src/api/routes/tests/application.spec.ts +++ b/packages/server/src/api/routes/tests/application.spec.ts @@ -151,7 +151,7 @@ describe("/applications", () => { const app = await config.api.application.create({ name: utils.newid(), useTemplate: "true", - templateFile: "src/api/routes/tests/data/export.txt", + fileToImport: "src/api/routes/tests/data/export.txt", }) expect(app._id).toBeDefined() expect(events.app.created).toHaveBeenCalledTimes(1) @@ -171,7 +171,7 @@ describe("/applications", () => { const app = await config.api.application.create({ name: utils.newid(), useTemplate: "true", - templateFile: "src/api/routes/tests/data/old-app.txt", + fileToImport: "src/api/routes/tests/data/old-app.txt", }) expect(app._id).toBeDefined() expect(app.navigation).toBeDefined() diff --git a/packages/server/src/tests/utilities/api/application.ts b/packages/server/src/tests/utilities/api/application.ts index 516af5c973..9dabc8cfe8 100644 --- a/packages/server/src/tests/utilities/api/application.ts +++ b/packages/server/src/tests/utilities/api/application.ts @@ -17,8 +17,8 @@ export class ApplicationAPI extends TestAPI { app: CreateAppRequest, expectations?: Expectations ): Promise => { - const files = app.templateFile ? { templateFile: app.templateFile } : {} - delete app.templateFile + const files = app.fileToImport ? { fileToImport: app.fileToImport } : {} + delete app.fileToImport return await this._post("/api/applications", { fields: app, files, diff --git a/packages/types/src/api/web/application.ts b/packages/types/src/api/web/application.ts index e4a70c7fd4..57422ceabc 100644 --- a/packages/types/src/api/web/application.ts +++ b/packages/types/src/api/web/application.ts @@ -7,7 +7,7 @@ export interface CreateAppRequest { useTemplate?: string templateName?: string templateKey?: string - templateFile?: string + fileToImport?: string encryptionPassword?: string file?: { path: string } } From 77c4140e76ccb008e276ab5449cdfd2083d0ce8a Mon Sep 17 00:00:00 2001 From: Adria Navarro Date: Tue, 22 Oct 2024 12:49:34 +0200 Subject: [PATCH 06/11] Type useTemplate as bool --- packages/server/scripts/load/utils.js | 2 +- .../server/src/api/controllers/application.ts | 27 +++++++++---------- .../src/api/routes/tests/application.spec.ts | 6 ++--- .../src/api/routes/tests/templates.spec.ts | 2 +- packages/types/src/api/web/application.ts | 2 +- 5 files changed, 19 insertions(+), 20 deletions(-) diff --git a/packages/server/scripts/load/utils.js b/packages/server/scripts/load/utils.js index 1dabdcec9a..57e03c471c 100644 --- a/packages/server/scripts/load/utils.js +++ b/packages/server/scripts/load/utils.js @@ -29,7 +29,7 @@ exports.createApp = async apiKey => { const body = { name, url: `/${name}`, - useTemplate: "true", + useTemplate: true, templateKey: "app/school-admin-panel", templateName: "School Admin Panel", } diff --git a/packages/server/src/api/controllers/application.ts b/packages/server/src/api/controllers/application.ts index fbcf51c1de..2484484ef8 100644 --- a/packages/server/src/api/controllers/application.ts +++ b/packages/server/src/api/controllers/application.ts @@ -58,6 +58,7 @@ import { FieldType, BBReferenceFieldSubType, Row, + BBRequest, } from "@budibase/types" import { BASE_LAYOUT_PROP_IDS } from "../../constants/layouts" import sdk from "../../sdk" @@ -127,7 +128,7 @@ function checkAppName( } interface AppTemplate { - useTemplate?: string + useTemplate?: boolean file?: { type?: string path: string @@ -151,7 +152,7 @@ async function createInstance(appId: string, template: AppTemplate) { await createRoutingView() await createAllSearchIndex() - if (template && template.useTemplate === "true") { + if (template && template.useTemplate) { await sdk.backups.importApp(appId, db, template) } else { // create the users table @@ -428,21 +429,21 @@ async function updateUserColumns( }) } -async function creationEvents(request: any, app: App) { +async function creationEvents(request: BBRequest, app: App) { let creationFns: ((app: App) => Promise)[] = [] - const body = request.body - if (body.useTemplate === "true") { + const { useTemplate, templateKey, file } = request.body + if (useTemplate) { // from template - if (body.templateKey && body.templateKey !== "undefined") { - creationFns.push(a => events.app.templateImported(a, body.templateKey)) + if (templateKey && templateKey !== "undefined") { + creationFns.push(a => events.app.templateImported(a, templateKey)) } // from file else if (request.files?.templateFile) { creationFns.push(a => events.app.fileImported(a)) } // from server file path - else if (request.body.file) { + else if (file) { // explicitly pass in the newly created app id creationFns.push(a => events.app.duplicated(a, app.appId)) } @@ -452,16 +453,14 @@ async function creationEvents(request: any, app: App) { } } - if (!request.duplicate) { - creationFns.push(a => events.app.created(a)) - } + creationFns.push(a => events.app.created(a)) for (let fn of creationFns) { await fn(app) } } -async function appPostCreate(ctx: UserCtx, app: App) { +async function appPostCreate(ctx: UserCtx, app: App) { const tenantId = tenancy.getTenantId() await migrations.backPopulateMigrations({ type: MigrationType.APP, @@ -472,7 +471,7 @@ async function appPostCreate(ctx: UserCtx, app: App) { await creationEvents(ctx.request, app) // app import, template creation and duplication - if (ctx.request.body.useTemplate === "true") { + if (ctx.request.body.useTemplate) { const { rows } = await getUniqueRows([app.appId]) const rowCount = rows ? rows.length : 0 if (rowCount) { @@ -742,7 +741,7 @@ export async function duplicateApp( const createRequestBody: CreateAppRequest = { name: appName, url: possibleUrl, - useTemplate: "true", + useTemplate: true, // The app export path file: { path: tmpPath, diff --git a/packages/server/src/api/routes/tests/application.spec.ts b/packages/server/src/api/routes/tests/application.spec.ts index b654e577ba..e905a86ed9 100644 --- a/packages/server/src/api/routes/tests/application.spec.ts +++ b/packages/server/src/api/routes/tests/application.spec.ts @@ -139,7 +139,7 @@ describe("/applications", () => { it("creates app from template", async () => { const app = await config.api.application.create({ name: utils.newid(), - useTemplate: "true", + useTemplate: true, templateKey: "test", }) expect(app._id).toBeDefined() @@ -150,7 +150,7 @@ describe("/applications", () => { it("creates app from file", async () => { const app = await config.api.application.create({ name: utils.newid(), - useTemplate: "true", + useTemplate: true, fileToImport: "src/api/routes/tests/data/export.txt", }) expect(app._id).toBeDefined() @@ -170,7 +170,7 @@ describe("/applications", () => { it("migrates navigation settings from old apps", async () => { const app = await config.api.application.create({ name: utils.newid(), - useTemplate: "true", + useTemplate: true, fileToImport: "src/api/routes/tests/data/old-app.txt", }) expect(app._id).toBeDefined() diff --git a/packages/server/src/api/routes/tests/templates.spec.ts b/packages/server/src/api/routes/tests/templates.spec.ts index d5483c54b4..4d9ccb2c17 100644 --- a/packages/server/src/api/routes/tests/templates.spec.ts +++ b/packages/server/src/api/routes/tests/templates.spec.ts @@ -95,7 +95,7 @@ describe("/templates", () => { const app = await config.api.application.create({ name, url, - useTemplate: "true", + useTemplate: true, templateName: "Agency Client Portal", templateKey: "app/agency-client-portal", }) diff --git a/packages/types/src/api/web/application.ts b/packages/types/src/api/web/application.ts index 57422ceabc..2606860fde 100644 --- a/packages/types/src/api/web/application.ts +++ b/packages/types/src/api/web/application.ts @@ -4,7 +4,7 @@ import type { Layout, App, Screen } from "../../documents" export interface CreateAppRequest { name: string url?: string - useTemplate?: string + useTemplate?: boolean templateName?: string templateKey?: string fileToImport?: string From 838d11e2534ee9f92be8d43671f3cca9bf773f44 Mon Sep 17 00:00:00 2001 From: Adria Navarro Date: Tue, 22 Oct 2024 13:01:33 +0200 Subject: [PATCH 07/11] Update only for templates --- packages/server/src/api/controllers/application.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/server/src/api/controllers/application.ts b/packages/server/src/api/controllers/application.ts index 2484484ef8..1d8724ed75 100644 --- a/packages/server/src/api/controllers/application.ts +++ b/packages/server/src/api/controllers/application.ts @@ -269,7 +269,7 @@ async function performAppCreate(ctx: UserCtx) { const instance = await createInstance(appId, instanceConfig) const db = context.getAppDB() - if (instanceConfig.useTemplate) { + if (instanceConfig.useTemplate && !instanceConfig.file) { await updateUserColumns(appId, db, ctx.user._id!) } From 020927ae6c193d5cce8d906bb5f712ef9d4d2a34 Mon Sep 17 00:00:00 2001 From: Adria Navarro Date: Tue, 22 Oct 2024 13:19:04 +0200 Subject: [PATCH 08/11] Fix types --- .../server/src/api/controllers/application.ts | 15 +++++++++++---- packages/types/src/api/web/application.ts | 2 +- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/packages/server/src/api/controllers/application.ts b/packages/server/src/api/controllers/application.ts index 1d8724ed75..50878861a1 100644 --- a/packages/server/src/api/controllers/application.ts +++ b/packages/server/src/api/controllers/application.ts @@ -240,8 +240,15 @@ export async function fetchAppPackage( async function performAppCreate(ctx: UserCtx) { const apps = (await dbCore.getAllApps({ dev: true })) as App[] - const { name, url, encryptionPassword, useTemplate, templateKey } = - ctx.request.body + const { body } = ctx.request + const { name, url, encryptionPassword, templateKey } = body + + let useTemplate + if (typeof body.useTemplate === "string") { + useTemplate = body.useTemplate === "true" + } else if (typeof body.useTemplate === "boolean") { + useTemplate = body.useTemplate + } checkAppName(ctx, apps, name) const appUrl = sdk.applications.getAppUrl({ name, url }) @@ -256,9 +263,9 @@ async function performAppCreate(ctx: UserCtx) { ...(ctx.request.files.fileToImport as any), password: encryptionPassword, } - } else if (typeof ctx.request.body.file?.path === "string") { + } else if (typeof body.file?.path === "string") { instanceConfig.file = { - path: ctx.request.body.file?.path, + path: body.file?.path, } } diff --git a/packages/types/src/api/web/application.ts b/packages/types/src/api/web/application.ts index 2606860fde..57422ceabc 100644 --- a/packages/types/src/api/web/application.ts +++ b/packages/types/src/api/web/application.ts @@ -4,7 +4,7 @@ import type { Layout, App, Screen } from "../../documents" export interface CreateAppRequest { name: string url?: string - useTemplate?: boolean + useTemplate?: string templateName?: string templateKey?: string fileToImport?: string From e1640cccf93a061155b72e9b4e5decc4fac6c827 Mon Sep 17 00:00:00 2001 From: Adria Navarro Date: Tue, 22 Oct 2024 14:04:57 +0200 Subject: [PATCH 09/11] Change api type back --- packages/server/src/api/controllers/application.ts | 2 +- packages/server/src/api/routes/tests/application.spec.ts | 6 +++--- packages/server/src/api/routes/tests/templates.spec.ts | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/server/src/api/controllers/application.ts b/packages/server/src/api/controllers/application.ts index 50878861a1..8102254a79 100644 --- a/packages/server/src/api/controllers/application.ts +++ b/packages/server/src/api/controllers/application.ts @@ -748,7 +748,7 @@ export async function duplicateApp( const createRequestBody: CreateAppRequest = { name: appName, url: possibleUrl, - useTemplate: true, + useTemplate: "true", // The app export path file: { path: tmpPath, diff --git a/packages/server/src/api/routes/tests/application.spec.ts b/packages/server/src/api/routes/tests/application.spec.ts index e905a86ed9..b654e577ba 100644 --- a/packages/server/src/api/routes/tests/application.spec.ts +++ b/packages/server/src/api/routes/tests/application.spec.ts @@ -139,7 +139,7 @@ describe("/applications", () => { it("creates app from template", async () => { const app = await config.api.application.create({ name: utils.newid(), - useTemplate: true, + useTemplate: "true", templateKey: "test", }) expect(app._id).toBeDefined() @@ -150,7 +150,7 @@ describe("/applications", () => { it("creates app from file", async () => { const app = await config.api.application.create({ name: utils.newid(), - useTemplate: true, + useTemplate: "true", fileToImport: "src/api/routes/tests/data/export.txt", }) expect(app._id).toBeDefined() @@ -170,7 +170,7 @@ describe("/applications", () => { it("migrates navigation settings from old apps", async () => { const app = await config.api.application.create({ name: utils.newid(), - useTemplate: true, + useTemplate: "true", fileToImport: "src/api/routes/tests/data/old-app.txt", }) expect(app._id).toBeDefined() diff --git a/packages/server/src/api/routes/tests/templates.spec.ts b/packages/server/src/api/routes/tests/templates.spec.ts index 4d9ccb2c17..d5483c54b4 100644 --- a/packages/server/src/api/routes/tests/templates.spec.ts +++ b/packages/server/src/api/routes/tests/templates.spec.ts @@ -95,7 +95,7 @@ describe("/templates", () => { const app = await config.api.application.create({ name, url, - useTemplate: true, + useTemplate: "true", templateName: "Agency Client Portal", templateKey: "app/agency-client-portal", }) From b85a28fdf612bd3fcdd179ccf514e0e869a24d0d Mon Sep 17 00:00:00 2001 From: Adria Navarro Date: Tue, 22 Oct 2024 16:19:25 +0200 Subject: [PATCH 10/11] Fixes --- packages/server/src/api/controllers/application.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/server/src/api/controllers/application.ts b/packages/server/src/api/controllers/application.ts index 8102254a79..d8d9d75336 100644 --- a/packages/server/src/api/controllers/application.ts +++ b/packages/server/src/api/controllers/application.ts @@ -440,13 +440,13 @@ async function creationEvents(request: BBRequest, app: App) { let creationFns: ((app: App) => Promise)[] = [] const { useTemplate, templateKey, file } = request.body - if (useTemplate) { + if (useTemplate === "true") { // from template if (templateKey && templateKey !== "undefined") { creationFns.push(a => events.app.templateImported(a, templateKey)) } // from file - else if (request.files?.templateFile) { + else if (request.files?.fileToImport) { creationFns.push(a => events.app.fileImported(a)) } // from server file path From f07cb6bd74b31dcf5fd8a753836ec7527162c05a Mon Sep 17 00:00:00 2001 From: Adria Navarro Date: Tue, 22 Oct 2024 16:37:58 +0200 Subject: [PATCH 11/11] Fix test --- .../server/src/api/routes/tests/application.spec.ts | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/packages/server/src/api/routes/tests/application.spec.ts b/packages/server/src/api/routes/tests/application.spec.ts index b654e577ba..47b6776610 100644 --- a/packages/server/src/api/routes/tests/application.spec.ts +++ b/packages/server/src/api/routes/tests/application.spec.ts @@ -21,6 +21,7 @@ import tk from "timekeeper" import * as uuid from "uuid" import { structures } from "@budibase/backend-core/tests" import nock from "nock" +import path from "path" describe("/applications", () => { let config = setup.getConfig() @@ -137,10 +138,17 @@ describe("/applications", () => { }) it("creates app from template", async () => { + nock("https://prod-budi-templates.s3-eu-west-1.amazonaws.com") + .get(`/templates/app/agency-client-portal.tar.gz`) + .replyWithFile( + 200, + path.resolve(__dirname, "data", "agency-client-portal.tar.gz") + ) + const app = await config.api.application.create({ name: utils.newid(), useTemplate: "true", - templateKey: "test", + templateKey: "app/agency-client-portal", }) expect(app._id).toBeDefined() expect(events.app.created).toHaveBeenCalledTimes(1)