Merge pull request #1266 from Budibase/middleware-tests
Middleware tests
This commit is contained in:
commit
39f5bdc184
|
@ -31,6 +31,7 @@ module.exports = async (ctx, next) => {
|
|||
token = ctx.cookies.get(getCookieName())
|
||||
authType = AuthTypes.BUILDER
|
||||
}
|
||||
|
||||
if (!token && appId) {
|
||||
token = ctx.cookies.get(getCookieName(appId))
|
||||
authType = AuthTypes.APP
|
||||
|
@ -58,6 +59,7 @@ module.exports = async (ctx, next) => {
|
|||
role: await getRole(appId, jwtPayload.roleId),
|
||||
}
|
||||
} catch (err) {
|
||||
console.log(err)
|
||||
if (authType === AuthTypes.BUILDER) {
|
||||
clearCookie(ctx)
|
||||
ctx.status = 200
|
||||
|
|
|
@ -24,6 +24,7 @@ module.exports = (permType, permLevel = null) => async (ctx, next) => {
|
|||
if (!env.CLOUD && LOCAL_PASS.test(ctx.request.url)) {
|
||||
return next()
|
||||
}
|
||||
|
||||
if (env.CLOUD && ctx.headers["x-api-key"] && ctx.headers["x-instanceid"]) {
|
||||
// api key header passed by external webhook
|
||||
if (await isAPIKeyValid(ctx.headers["x-api-key"])) {
|
||||
|
@ -37,14 +38,14 @@ module.exports = (permType, permLevel = null) => async (ctx, next) => {
|
|||
return next()
|
||||
}
|
||||
|
||||
ctx.throw(403, "API key invalid")
|
||||
return ctx.throw(403, "API key invalid")
|
||||
}
|
||||
|
||||
// don't expose builder endpoints in the cloud
|
||||
if (env.CLOUD && permType === PermissionTypes.BUILDER) return
|
||||
|
||||
if (!ctx.user) {
|
||||
ctx.throw(403, "No user info found")
|
||||
return ctx.throw(403, "No user info found")
|
||||
}
|
||||
|
||||
const role = ctx.user.role
|
||||
|
@ -52,7 +53,7 @@ module.exports = (permType, permLevel = null) => async (ctx, next) => {
|
|||
ctx.appId,
|
||||
role._id
|
||||
)
|
||||
const isAdmin = ADMIN_ROLES.indexOf(role._id) !== -1
|
||||
const isAdmin = ADMIN_ROLES.includes(role._id)
|
||||
const isAuthed = ctx.auth.authenticated
|
||||
|
||||
// this may need to change in the future, right now only admins
|
||||
|
@ -61,7 +62,7 @@ module.exports = (permType, permLevel = null) => async (ctx, next) => {
|
|||
if (isAdmin && isAuthed) {
|
||||
return next()
|
||||
} else if (permType === PermissionTypes.BUILDER) {
|
||||
ctx.throw(403, "Not Authorized")
|
||||
return ctx.throw(403, "Not Authorized")
|
||||
}
|
||||
|
||||
if (
|
||||
|
|
|
@ -36,6 +36,8 @@ class ResourceIdGetter {
|
|||
}
|
||||
}
|
||||
|
||||
module.exports.ResourceIdGetter = ResourceIdGetter
|
||||
|
||||
module.exports.paramResource = main => {
|
||||
return new ResourceIdGetter("params").mainResource(main).build()
|
||||
}
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`Authenticated middleware sets the correct APP auth type information when the user is not in the builder 1`] = `
|
||||
Object {
|
||||
"apiKey": "1234",
|
||||
"appId": "budibase:app:local",
|
||||
"role": Role {
|
||||
"_id": "ADMIN",
|
||||
"inherits": "POWER",
|
||||
"name": "Admin",
|
||||
"permissionId": "admin",
|
||||
},
|
||||
"roleId": "ADMIN",
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`Authenticated middleware sets the correct BUILDER auth type information when the x-budibase-type header is not 'client' 1`] = `
|
||||
Object {
|
||||
"apiKey": "1234",
|
||||
"appId": "budibase:builder:local",
|
||||
"role": Role {
|
||||
"_id": "BUILDER",
|
||||
"name": "Builder",
|
||||
"permissionId": "admin",
|
||||
},
|
||||
"roleId": "BUILDER",
|
||||
}
|
||||
`;
|
|
@ -0,0 +1,126 @@
|
|||
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: {},
|
||||
request: {},
|
||||
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,196 @@
|
|||
const authorizedMiddleware = require("../authorized")
|
||||
const env = require("../../environment")
|
||||
const apiKey = require("../../utilities/security/apikey")
|
||||
const { AuthTypes } = require("../../constants")
|
||||
const { PermissionTypes, PermissionLevels } = require("../../utilities/security/permissions")
|
||||
const { Test } = require("supertest")
|
||||
jest.mock("../../environment")
|
||||
jest.mock("../../utilities/security/apikey")
|
||||
|
||||
class TestConfiguration {
|
||||
constructor(role) {
|
||||
this.middleware = authorizedMiddleware(role)
|
||||
this.next = jest.fn()
|
||||
this.throw = jest.fn()
|
||||
this.ctx = {
|
||||
headers: {},
|
||||
request: {
|
||||
url: ""
|
||||
},
|
||||
auth: {},
|
||||
next: this.next,
|
||||
throw: this.throw
|
||||
}
|
||||
}
|
||||
|
||||
executeMiddleware() {
|
||||
return this.middleware(this.ctx, this.next)
|
||||
}
|
||||
|
||||
setUser(user) {
|
||||
this.ctx.user = user
|
||||
}
|
||||
|
||||
setMiddlewareRequiredPermission(...perms) {
|
||||
this.middleware = authorizedMiddleware(...perms)
|
||||
}
|
||||
|
||||
setResourceId(id) {
|
||||
this.ctx.resourceId = id
|
||||
}
|
||||
|
||||
setAuthenticated(isAuthed) {
|
||||
this.ctx.auth = { authenticated: isAuthed }
|
||||
}
|
||||
|
||||
setRequestUrl(url) {
|
||||
this.ctx.request.url = url
|
||||
}
|
||||
|
||||
setCloudEnv(isCloud) {
|
||||
env.CLOUD = isCloud
|
||||
}
|
||||
|
||||
setRequestHeaders(headers) {
|
||||
this.ctx.headers = headers
|
||||
}
|
||||
|
||||
afterEach() {
|
||||
jest.clearAllMocks()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
describe("Authorization middleware", () => {
|
||||
const next = jest.fn()
|
||||
let config
|
||||
|
||||
afterEach(() => {
|
||||
config.afterEach()
|
||||
})
|
||||
|
||||
beforeEach(() => {
|
||||
config = new TestConfiguration()
|
||||
})
|
||||
|
||||
it("passes the middleware for local webhooks", async () => {
|
||||
config.setRequestUrl("https://something/webhooks/trigger")
|
||||
await config.executeMiddleware()
|
||||
expect(config.next).toHaveBeenCalled()
|
||||
})
|
||||
|
||||
describe("external web hook call", () => {
|
||||
let ctx = {}
|
||||
let middleware
|
||||
|
||||
beforeEach(() => {
|
||||
config = new TestConfiguration()
|
||||
config.setCloudEnv(true)
|
||||
config.setRequestHeaders({
|
||||
"x-api-key": "abc123",
|
||||
"x-instanceid": "instance123",
|
||||
})
|
||||
})
|
||||
|
||||
it("passes to next() if api key is valid", async () => {
|
||||
apiKey.isAPIKeyValid.mockResolvedValueOnce(true)
|
||||
|
||||
await config.executeMiddleware()
|
||||
|
||||
expect(config.next).toHaveBeenCalled()
|
||||
expect(config.ctx.auth).toEqual({
|
||||
authenticated: AuthTypes.EXTERNAL,
|
||||
apiKey: config.ctx.headers["x-api-key"],
|
||||
})
|
||||
expect(config.ctx.user).toEqual({
|
||||
appId: config.ctx.headers["x-instanceid"],
|
||||
})
|
||||
})
|
||||
|
||||
it("throws if api key is invalid", async () => {
|
||||
apiKey.isAPIKeyValid.mockResolvedValueOnce(false)
|
||||
|
||||
await config.executeMiddleware()
|
||||
|
||||
expect(config.throw).toHaveBeenCalledWith(403, "API key invalid")
|
||||
})
|
||||
})
|
||||
|
||||
describe("non-webhook call", () => {
|
||||
let config
|
||||
|
||||
beforeEach(() => {
|
||||
config = new TestConfiguration()
|
||||
config.setCloudEnv(true)
|
||||
config.setAuthenticated(true)
|
||||
})
|
||||
|
||||
it("throws when no user data is present in context", async () => {
|
||||
await config.executeMiddleware()
|
||||
|
||||
expect(config.throw).toHaveBeenCalledWith(403, "No user info found")
|
||||
})
|
||||
|
||||
it("passes on to next() middleware if user is an admin", async () => {
|
||||
config.setUser({
|
||||
role: {
|
||||
_id: "ADMIN",
|
||||
}
|
||||
})
|
||||
|
||||
await config.executeMiddleware()
|
||||
|
||||
expect(config.next).toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it("throws if the user has only builder permissions", async () => {
|
||||
config.setCloudEnv(false)
|
||||
config.setMiddlewareRequiredPermission(PermissionTypes.BUILDER)
|
||||
config.setUser({
|
||||
role: {
|
||||
_id: ""
|
||||
}
|
||||
})
|
||||
await config.executeMiddleware()
|
||||
|
||||
expect(config.throw).toHaveBeenCalledWith(403, "Not Authorized")
|
||||
})
|
||||
|
||||
it("passes on to next() middleware if the user has resource permission", async () => {
|
||||
config.setResourceId(PermissionTypes.QUERY)
|
||||
config.setUser({
|
||||
role: {
|
||||
_id: ""
|
||||
}
|
||||
})
|
||||
config.setMiddlewareRequiredPermission(PermissionTypes.QUERY)
|
||||
|
||||
await config.executeMiddleware()
|
||||
expect(config.next).toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it("throws if the user session is not authenticated after permission checks", async () => {
|
||||
config.setUser({
|
||||
role: {
|
||||
_id: ""
|
||||
},
|
||||
})
|
||||
config.setAuthenticated(false)
|
||||
|
||||
await config.executeMiddleware()
|
||||
expect(config.throw).toHaveBeenCalledWith(403, "Session not authenticated")
|
||||
})
|
||||
|
||||
it("throws if the user does not have base permissions to perform the operation", async () => {
|
||||
config.setUser({
|
||||
role: {
|
||||
_id: ""
|
||||
},
|
||||
})
|
||||
config.setMiddlewareRequiredPermission(PermissionTypes.ADMIN, PermissionLevels.BASIC)
|
||||
|
||||
await config.executeMiddleware()
|
||||
expect(config.throw).toHaveBeenCalledWith(403, "User does not have permission")
|
||||
})
|
||||
})
|
||||
})
|
|
@ -0,0 +1,105 @@
|
|||
const {
|
||||
paramResource,
|
||||
paramSubResource,
|
||||
bodyResource,
|
||||
bodySubResource,
|
||||
ResourceIdGetter
|
||||
} = require("../resourceId")
|
||||
|
||||
class TestConfiguration {
|
||||
constructor(middleware) {
|
||||
this.middleware = middleware
|
||||
this.ctx = {
|
||||
request: {},
|
||||
}
|
||||
this.next = jest.fn()
|
||||
}
|
||||
|
||||
setParams(params) {
|
||||
this.ctx.params = params
|
||||
}
|
||||
|
||||
setBody(body) {
|
||||
this.ctx.body = body
|
||||
}
|
||||
|
||||
executeMiddleware() {
|
||||
return this.middleware(this.ctx, this.next)
|
||||
}
|
||||
}
|
||||
|
||||
describe("resourceId middleware", () => {
|
||||
it("calls next() when there is no request object to parse", () => {
|
||||
const config = new TestConfiguration(paramResource("main"))
|
||||
|
||||
config.executeMiddleware()
|
||||
|
||||
expect(config.next).toHaveBeenCalled()
|
||||
expect(config.ctx.resourceId).toBeUndefined()
|
||||
})
|
||||
|
||||
it("generates a resourceId middleware for context query parameters", () => {
|
||||
const config = new TestConfiguration(paramResource("main"))
|
||||
config.setParams({
|
||||
main: "test"
|
||||
})
|
||||
|
||||
config.executeMiddleware()
|
||||
|
||||
expect(config.ctx.resourceId).toEqual("test")
|
||||
})
|
||||
|
||||
it("generates a resourceId middleware for context query sub parameters", () => {
|
||||
const config = new TestConfiguration(paramSubResource("main", "sub"))
|
||||
config.setParams({
|
||||
main: "main",
|
||||
sub: "test"
|
||||
})
|
||||
|
||||
config.executeMiddleware()
|
||||
|
||||
expect(config.ctx.resourceId).toEqual("main")
|
||||
expect(config.ctx.subResourceId).toEqual("test")
|
||||
})
|
||||
|
||||
it("generates a resourceId middleware for context request body", () => {
|
||||
const config = new TestConfiguration(bodyResource("main"))
|
||||
config.setBody({
|
||||
main: "test"
|
||||
})
|
||||
|
||||
config.executeMiddleware()
|
||||
|
||||
expect(config.ctx.resourceId).toEqual("test")
|
||||
})
|
||||
|
||||
it("generates a resourceId middleware for context request body sub fields", () => {
|
||||
const config = new TestConfiguration(bodySubResource("main", "sub"))
|
||||
config.setBody({
|
||||
main: "main",
|
||||
sub: "test"
|
||||
})
|
||||
|
||||
config.executeMiddleware()
|
||||
|
||||
expect(config.ctx.resourceId).toEqual("main")
|
||||
expect(config.ctx.subResourceId).toEqual("test")
|
||||
})
|
||||
|
||||
it("parses resourceIds correctly for custom middlewares", () => {
|
||||
const middleware = new ResourceIdGetter("body")
|
||||
.mainResource("custom")
|
||||
.subResource("customSub")
|
||||
.build()
|
||||
config = new TestConfiguration(middleware)
|
||||
config.setBody({
|
||||
custom: "test",
|
||||
customSub: "subtest"
|
||||
})
|
||||
|
||||
config.executeMiddleware()
|
||||
|
||||
expect(config.ctx.resourceId).toEqual("test")
|
||||
expect(config.ctx.subResourceId).toEqual("subtest")
|
||||
})
|
||||
})
|
|
@ -0,0 +1,75 @@
|
|||
const selfHostMiddleware = require("../selfhost");
|
||||
const env = require("../../environment")
|
||||
const hosting = require("../../utilities/builder/hosting");
|
||||
jest.mock("../../environment")
|
||||
jest.mock("../../utilities/builder/hosting")
|
||||
|
||||
class TestConfiguration {
|
||||
constructor() {
|
||||
this.next = jest.fn()
|
||||
this.throw = jest.fn()
|
||||
this.middleware = selfHostMiddleware
|
||||
|
||||
this.ctx = {
|
||||
next: this.next,
|
||||
throw: this.throw
|
||||
}
|
||||
}
|
||||
|
||||
executeMiddleware() {
|
||||
return this.middleware(this.ctx, this.next)
|
||||
}
|
||||
|
||||
setCloudHosted() {
|
||||
env.CLOUD = 1
|
||||
env.SELF_HOSTED = 0
|
||||
}
|
||||
|
||||
setSelfHosted() {
|
||||
env.CLOUD = 0
|
||||
env.SELF_HOSTED = 1
|
||||
}
|
||||
|
||||
afterEach() {
|
||||
jest.clearAllMocks()
|
||||
}
|
||||
}
|
||||
|
||||
describe("Self host middleware", () => {
|
||||
let config
|
||||
|
||||
beforeEach(() => {
|
||||
config = new TestConfiguration()
|
||||
})
|
||||
|
||||
afterEach(() => {
|
||||
config.afterEach()
|
||||
})
|
||||
|
||||
it("calls next() when CLOUD and SELF_HOSTED env vars are set", async () => {
|
||||
env.CLOUD = 1
|
||||
env.SELF_HOSTED = 1
|
||||
|
||||
await config.executeMiddleware()
|
||||
expect(config.next).toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it("throws when hostingInfo type is cloud", async () => {
|
||||
config.setSelfHosted()
|
||||
|
||||
hosting.getHostingInfo.mockImplementationOnce(() => ({ type: hosting.HostingTypes.CLOUD }))
|
||||
|
||||
await config.executeMiddleware()
|
||||
expect(config.throw).toHaveBeenCalledWith(400, "Endpoint unavailable in cloud hosting.")
|
||||
expect(config.next).not.toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it("calls the self hosting middleware to pass through to next() when the hostingInfo type is self", async () => {
|
||||
config.setSelfHosted()
|
||||
|
||||
hosting.getHostingInfo.mockImplementationOnce(() => ({ type: hosting.HostingTypes.SELF }))
|
||||
|
||||
await config.executeMiddleware()
|
||||
expect(config.next).toHaveBeenCalled()
|
||||
})
|
||||
})
|
|
@ -0,0 +1,129 @@
|
|||
const usageQuotaMiddleware = require("../usageQuota")
|
||||
const usageQuota = require("../../utilities/usageQuota")
|
||||
const CouchDB = require("../../db")
|
||||
const env = require("../../environment")
|
||||
|
||||
jest.mock("../../db");
|
||||
jest.mock("../../utilities/usageQuota")
|
||||
jest.mock("../../environment")
|
||||
|
||||
class TestConfiguration {
|
||||
constructor() {
|
||||
this.throw = jest.fn()
|
||||
this.next = jest.fn()
|
||||
this.middleware = usageQuotaMiddleware
|
||||
this.ctx = {
|
||||
throw: this.throw,
|
||||
next: this.next,
|
||||
user: {
|
||||
appId: "test"
|
||||
},
|
||||
request: {
|
||||
body: {}
|
||||
},
|
||||
req: {
|
||||
method: "POST",
|
||||
url: "/rows"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
executeMiddleware() {
|
||||
return this.middleware(this.ctx, this.next)
|
||||
}
|
||||
|
||||
cloudHosted(bool) {
|
||||
if (bool) {
|
||||
env.CLOUD = 1
|
||||
this.ctx.auth = { apiKey: "test" }
|
||||
} else {
|
||||
env.CLOUD = 0
|
||||
}
|
||||
}
|
||||
|
||||
setMethod(method) {
|
||||
this.ctx.req.method = method
|
||||
}
|
||||
|
||||
setUrl(url) {
|
||||
this.ctx.req.url = url
|
||||
}
|
||||
|
||||
setBody(body) {
|
||||
this.ctx.request.body = body
|
||||
}
|
||||
|
||||
setFiles(files) {
|
||||
this.ctx.request.files = { file: files }
|
||||
}
|
||||
}
|
||||
|
||||
describe("usageQuota middleware", () => {
|
||||
let config
|
||||
|
||||
beforeEach(() => {
|
||||
config = new TestConfiguration()
|
||||
})
|
||||
|
||||
it("skips the middleware if there is no usage property or method", async () => {
|
||||
await config.executeMiddleware()
|
||||
expect(config.next).toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it("passes through to next middleware if document already exists", async () => {
|
||||
config.setBody({
|
||||
_id: "test"
|
||||
})
|
||||
|
||||
CouchDB.mockImplementationOnce(() => ({
|
||||
get: async () => true
|
||||
}))
|
||||
|
||||
await config.executeMiddleware()
|
||||
|
||||
expect(config.next).toHaveBeenCalled()
|
||||
expect(config.ctx.preExisting).toBe(true)
|
||||
})
|
||||
|
||||
it("throws if request has _id, but the document no longer exists", async () => {
|
||||
config.setBody({
|
||||
_id: "123"
|
||||
})
|
||||
|
||||
CouchDB.mockImplementationOnce(() => ({
|
||||
get: async () => {
|
||||
throw new Error()
|
||||
}
|
||||
}))
|
||||
|
||||
await config.executeMiddleware()
|
||||
expect(config.throw).toHaveBeenCalledWith(404, `${config.ctx.request.body._id} does not exist`)
|
||||
})
|
||||
|
||||
it("calculates and persists the correct usage quota for the relevant action", async () => {
|
||||
config.setUrl("/rows")
|
||||
config.cloudHosted(true)
|
||||
|
||||
await config.executeMiddleware()
|
||||
|
||||
expect(usageQuota.update).toHaveBeenCalledWith("test", "rows", 1)
|
||||
expect(config.next).toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it("calculates the correct file size from a file upload call and adds it to quota", async () => {
|
||||
config.setUrl("/upload")
|
||||
config.cloudHosted(true)
|
||||
config.setFiles([
|
||||
{
|
||||
size: 100
|
||||
},
|
||||
{
|
||||
size: 10000
|
||||
},
|
||||
])
|
||||
await config.executeMiddleware()
|
||||
|
||||
expect(usageQuota.update).toHaveBeenCalledWith("test", "storage", 10100)
|
||||
expect(config.next).toHaveBeenCalled()
|
||||
})
|
||||
})
|
|
@ -43,6 +43,7 @@ module.exports = async (ctx, next) => {
|
|||
return
|
||||
}
|
||||
}
|
||||
|
||||
// if running in builder or a self hosted cloud usage quotas should not be executed
|
||||
if (!env.CLOUD || env.SELF_HOSTED) {
|
||||
return next()
|
||||
|
|
Loading…
Reference in New Issue