forked from tsai/budibase
6 changed files with 150 additions and 211 deletions
@ -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()
|
|
||||
// }
|
|
||||
@ -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") |
|
||||
}) |
|
||||
}) |
|
||||
@ -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) |
||||
|
}) |
||||
|
}) |
||||
|
|
||||
|
}) |
||||
@ -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() |
|
||||
} |
|
||||
} |
|
||||
Loading…
Reference in new issue