From c51dacd0fe592530764fc007f8fa8956305c9675 Mon Sep 17 00:00:00 2001 From: mike12345567 Date: Tue, 13 Apr 2021 13:32:09 +0100 Subject: [PATCH 1/3] Adding test cases for current app middleware as well as removing some old middlewares that were no longer used. --- .../server/src/middleware/authenticated.js | 73 --------- packages/server/src/middleware/currentapp.js | 4 +- .../middleware/tests/authenticated.spec.js | 124 --------------- .../src/middleware/tests/authorized.spec.js | 1 - .../src/middleware/tests/currentapp.spec.js | 148 ++++++++++++++++++ packages/worker/src/middleware/check-key.js | 11 -- 6 files changed, 150 insertions(+), 211 deletions(-) delete mode 100644 packages/server/src/middleware/authenticated.js delete mode 100644 packages/server/src/middleware/tests/authenticated.spec.js create mode 100644 packages/server/src/middleware/tests/currentapp.spec.js delete mode 100644 packages/worker/src/middleware/check-key.js diff --git a/packages/server/src/middleware/authenticated.js b/packages/server/src/middleware/authenticated.js deleted file mode 100644 index 848670d67a..0000000000 --- a/packages/server/src/middleware/authenticated.js +++ /dev/null @@ -1,73 +0,0 @@ -// const jwt = require("jsonwebtoken") -// const STATUS_CODES = require("../utilities/statusCodes") -// const { getRole, getBuiltinRoles } = require("../utilities/security/roles") -// const { AuthTypes } = require("../constants") -// const { -// getAppId, -// getCookieName, -// clearCookie, -// setCookie, -// isClient, -// } = require("../utilities") - -// module.exports = async (ctx, next) => { -// if (ctx.path === "/builder") { -// await next() -// return -// } - -// // do everything we can to make sure the appId is held correctly -// // we hold it in state as a -// let appId = getAppId(ctx) -// const cookieAppId = ctx.cookies.get(getCookieName("currentapp")) -// const builtinRoles = getBuiltinRoles() -// if (appId && cookieAppId !== appId) { -// setCookie(ctx, appId, "currentapp") -// } else if (cookieAppId) { -// appId = cookieAppId -// } -// let token, authType -// if (!isClient(ctx)) { -// token = ctx.cookies.get(getCookieName()) -// authType = AuthTypes.BUILDER -// } - -// if (!token && appId) { -// token = ctx.cookies.get(getCookieName(appId)) -// authType = AuthTypes.APP -// } - -// if (!token) { -// ctx.auth.authenticated = false -// ctx.appId = appId -// ctx.user = { -// role: builtinRoles.PUBLIC, -// } -// await next() -// return -// } - -// try { -// ctx.auth.authenticated = authType -// const jwtPayload = jwt.verify(token, ctx.config.jwtSecret) -// ctx.appId = appId -// ctx.auth.apiKey = jwtPayload.apiKey -// ctx.user = { -// ...jwtPayload, -// role: await getRole(appId, jwtPayload.roleId), -// } -// // appId no longer carried in user, make sure -// delete ctx.user.appId -// } catch (err) { -// console.log(err) -// if (authType === AuthTypes.BUILDER) { -// clearCookie(ctx) -// ctx.status = 200 -// return -// } else { -// ctx.throw(err.status || STATUS_CODES.FORBIDDEN, err.text) -// } -// } - -// await next() -// } diff --git a/packages/server/src/middleware/currentapp.js b/packages/server/src/middleware/currentapp.js index a591874e6f..fe08c923f9 100644 --- a/packages/server/src/middleware/currentapp.js +++ b/packages/server/src/middleware/currentapp.js @@ -39,13 +39,13 @@ module.exports = async (ctx, next) => { roleId = BUILTIN_ROLE_IDS.PUBLIC } else if ( requestAppId != null && - (appCookie == null || requestAppId === appCookie.appId) + (appCookie == null || requestAppId !== appCookie.appId) ) { const globalUser = await getGlobalUsers(ctx, requestAppId, ctx.user.email) updateCookie = true appId = requestAppId roleId = globalUser.roles[requestAppId] || BUILTIN_ROLE_IDS.PUBLIC - } else if (requestAppId == null && appCookie != null) { + } else if (appCookie != null) { appId = appCookie.appId roleId = appCookie.roleId || BUILTIN_ROLE_IDS.PUBLIC } diff --git a/packages/server/src/middleware/tests/authenticated.spec.js b/packages/server/src/middleware/tests/authenticated.spec.js deleted file mode 100644 index 94441b7a5e..0000000000 --- a/packages/server/src/middleware/tests/authenticated.spec.js +++ /dev/null @@ -1,124 +0,0 @@ -const { AuthTypes } = require("../../constants") -const authenticatedMiddleware = require("../authenticated") -const jwt = require("jsonwebtoken") -jest.mock("jsonwebtoken") - -class TestConfiguration { - constructor(middleware) { - this.middleware = authenticatedMiddleware - this.ctx = { - config: {}, - auth: {}, - cookies: { - set: jest.fn(), - get: jest.fn(), - }, - headers: {}, - params: {}, - path: "", - request: { - headers: {}, - }, - throw: jest.fn(), - } - this.next = jest.fn() - } - - setHeaders(headers) { - this.ctx.headers = headers - } - - executeMiddleware() { - return this.middleware(this.ctx, this.next) - } - - afterEach() { - jest.resetAllMocks() - } -} - -describe("Authenticated middleware", () => { - let config - - beforeEach(() => { - config = new TestConfiguration() - }) - - afterEach(() => { - config.afterEach() - }) - - it("calls next() when on the builder path", async () => { - config.ctx.path = "/builder" - - await config.executeMiddleware() - - expect(config.next).toHaveBeenCalled() - }) - - it("sets a new cookie when the current cookie does not match the app id from context", async () => { - const appId = "app_123" - config.setHeaders({ - "x-budibase-app-id": appId, - }) - config.ctx.cookies.get.mockImplementation(() => "cookieAppId") - - await config.executeMiddleware() - - expect(config.ctx.cookies.set).toHaveBeenCalledWith( - "budibase:currentapp:local", - appId, - expect.any(Object) - ) - }) - - it("sets the correct BUILDER auth type information when the x-budibase-type header is not 'client'", async () => { - config.ctx.cookies.get.mockImplementation(() => "budibase:builder:local") - jwt.verify.mockImplementationOnce(() => ({ - apiKey: "1234", - roleId: "BUILDER", - })) - - await config.executeMiddleware() - - expect(config.ctx.auth.authenticated).toEqual(AuthTypes.BUILDER) - expect(config.ctx.user).toMatchSnapshot() - }) - - it("sets the correct APP auth type information when the user is not in the builder", async () => { - config.setHeaders({ - "x-budibase-type": "client", - }) - config.ctx.cookies.get.mockImplementation(() => `budibase:app:local`) - jwt.verify.mockImplementationOnce(() => ({ - apiKey: "1234", - roleId: "ADMIN", - })) - - await config.executeMiddleware() - - expect(config.ctx.auth.authenticated).toEqual(AuthTypes.APP) - expect(config.ctx.user).toMatchSnapshot() - }) - - it("marks the user as unauthenticated when a token cannot be determined from the users cookie", async () => { - config.executeMiddleware() - expect(config.ctx.auth.authenticated).toBe(false) - expect(config.ctx.user.role).toEqual({ - _id: "PUBLIC", - name: "Public", - permissionId: "public", - }) - }) - - it("clears the cookie when there is an error authenticating in the builder", async () => { - config.ctx.cookies.get.mockImplementation(() => "budibase:builder:local") - jwt.verify.mockImplementationOnce(() => { - throw new Error() - }) - - await config.executeMiddleware() - - expect(config.ctx.cookies.set).toBeCalledWith("budibase:builder:local") - }) -}) diff --git a/packages/server/src/middleware/tests/authorized.spec.js b/packages/server/src/middleware/tests/authorized.spec.js index d1ab6bc48c..a3dd9bdfd2 100644 --- a/packages/server/src/middleware/tests/authorized.spec.js +++ b/packages/server/src/middleware/tests/authorized.spec.js @@ -1,6 +1,5 @@ const authorizedMiddleware = require("../authorized") const env = require("../../environment") -const { AuthTypes } = require("../../constants") const { PermissionTypes, PermissionLevels } = require("../../utilities/security/permissions") jest.mock("../../environment", () => ({ prod: false, diff --git a/packages/server/src/middleware/tests/currentapp.spec.js b/packages/server/src/middleware/tests/currentapp.spec.js new file mode 100644 index 0000000000..9e7c1e20e4 --- /dev/null +++ b/packages/server/src/middleware/tests/currentapp.spec.js @@ -0,0 +1,148 @@ +mockAuthWithNoCookie() +mockWorker() + +function mockWorker() { + jest.mock("../../utilities/workerRequests", () => ({ + getGlobalUsers: () => { + return { + email: "test@test.com", + roles: { + "app_test": "BASIC", + } + } + } + })) +} + +function mockReset() { + jest.resetModules() + mockWorker() +} + +function mockAuthWithNoCookie() { + jest.resetModules() + mockWorker() + jest.mock("@budibase/auth", () => ({ + getAppId: jest.fn(), + setCookie: jest.fn(), + getCookie: jest.fn(), + Cookies: {}, + })) +} + +function mockAuthWithCookie() { + jest.resetModules() + mockWorker() + jest.mock("@budibase/auth", () => ({ + getAppId: () => { + return "app_test" + }, + setCookie: jest.fn(), + getCookie: () => ({ appId: "app_different", roleId: "PUBLIC" }), + Cookies: { + Auth: "auth", + CurrentApp: "currentapp", + } + })) +} + +class TestConfiguration { + constructor() { + this.next = jest.fn() + this.throw = jest.fn() + + this.ctx = { + next: this.next, + throw: this.throw + } + } + + setUser() { + this.ctx.user = { + email: "test@test.com", + } + } + + executeMiddleware() { + // import as late as possible for mocks + const currentAppMiddleware = require("../currentapp") + return currentAppMiddleware(this.ctx, this.next) + } +} + +describe("Current app middleware", () => { + let config + + beforeEach(() => { + config = new TestConfiguration() + }) + + afterEach(() => { + jest.clearAllMocks() + }) + + describe("test having no cookies or app ID", () => { + it("should be able to proceed with nothing setup", async () => { + await config.executeMiddleware() + expect(config.next).toHaveBeenCalled() + }) + }) + + describe("check get public for app when not logged in", () => { + it("should be able to proceed with no login, but cookies configured", async () => { + mockAuthWithCookie() + await config.executeMiddleware() + expect(config.ctx.roleId).toEqual("PUBLIC") + expect(config.ctx.appId).toEqual("app_test") + expect(config.next).toHaveBeenCalled() + }) + }) + + describe("check functionality when logged in", () => { + async function checkExpected(setCookie) { + config.setUser() + await config.executeMiddleware() + const cookieFn = require("@budibase/auth").setCookie + if (setCookie) { + expect(cookieFn).toHaveBeenCalled() + } else { + expect(cookieFn).not.toHaveBeenCalled() + } + expect(config.ctx.roleId).toEqual("BASIC") + expect(config.ctx.appId).toEqual("app_test") + expect(config.next).toHaveBeenCalled() + } + + it("should be able to setup an app token when cookie not setup", async () => { + mockAuthWithCookie() + await checkExpected(true) + }) + + it("should perform correct when no cookie exists", async () => { + mockReset() + jest.mock("@budibase/auth", () => ({ + getAppId: () => { + return "app_test" + }, + setCookie: jest.fn(), + getCookie: jest.fn(), + Cookies: {}, + })) + await checkExpected(true) + }) + + it("lastly check what occurs when cookie doesn't need updated", async () => { + mockReset() + jest.mock("@budibase/auth", () => ({ + getAppId: () => { + return "app_test" + }, + setCookie: jest.fn(), + getCookie: () => ({ appId: "app_test", roleId: "BASIC" }), + Cookies: {}, + })) + await checkExpected(false) + }) + }) + +}) \ No newline at end of file diff --git a/packages/worker/src/middleware/check-key.js b/packages/worker/src/middleware/check-key.js deleted file mode 100644 index 03d54a9dd6..0000000000 --- a/packages/worker/src/middleware/check-key.js +++ /dev/null @@ -1,11 +0,0 @@ -const env = require("../environment") - -module.exports = async (ctx, next) => { - const selfHostKey = - ctx.request.headers["x-budibase-auth"] || ctx.request.body.selfHostKey - if (!selfHostKey || env.SELF_HOST_KEY !== selfHostKey) { - ctx.throw(401, "Request unauthorised") - } else { - await next() - } -} From 96b4549a4cb42fa1d78b0c058cdfd0b476513a70 Mon Sep 17 00:00:00 2001 From: mike12345567 Date: Tue, 13 Apr 2021 13:35:30 +0100 Subject: [PATCH 2/3] Formatting. --- packages/builder/src/builderStore/dataBinding.js | 5 +---- packages/builder/src/components/login/index.js | 2 +- .../pages/builder/[application]/data/datasource/index.svelte | 4 +--- packages/builder/src/pages/builder/_layout.svelte | 4 +--- 4 files changed, 4 insertions(+), 11 deletions(-) diff --git a/packages/builder/src/builderStore/dataBinding.js b/packages/builder/src/builderStore/dataBinding.js index 696d83932a..58c4d8f4b6 100644 --- a/packages/builder/src/builderStore/dataBinding.js +++ b/packages/builder/src/builderStore/dataBinding.js @@ -2,10 +2,7 @@ import { cloneDeep } from "lodash/fp" import { get } from "svelte/store" import { findComponent, findComponentPath } from "./storeUtils" import { store } from "builderStore" -import { - tables as tablesStore, - queries as queriesStores, -} from "stores/backend" +import { tables as tablesStore, queries as queriesStores } from "stores/backend" import { makePropSafe } from "@budibase/string-templates" import { TableNames } from "../constants" diff --git a/packages/builder/src/components/login/index.js b/packages/builder/src/components/login/index.js index 9c9e708614..6a35637cea 100644 --- a/packages/builder/src/components/login/index.js +++ b/packages/builder/src/components/login/index.js @@ -1 +1 @@ -export { LoginForm } from "./LoginForm.svelte" \ No newline at end of file +export { LoginForm } from "./LoginForm.svelte" diff --git a/packages/builder/src/pages/builder/[application]/data/datasource/index.svelte b/packages/builder/src/pages/builder/[application]/data/datasource/index.svelte index 9bf0f1325c..8cf45eef07 100644 --- a/packages/builder/src/pages/builder/[application]/data/datasource/index.svelte +++ b/packages/builder/src/pages/builder/[application]/data/datasource/index.svelte @@ -11,9 +11,7 @@ {#if $datasources.list.length === 0} Connect your first datasource to start building. -{:else} - Select a datasource to edit -{/if} +{:else}Select a datasource to edit{/if}