Skip to content

Commit

Permalink
feat(api) restrict data manipulation operations on off db with errors
Browse files Browse the repository at this point in the history
  • Loading branch information
bungle authored and hishamhm committed Feb 15, 2019
1 parent 187e41f commit 95bfe6a
Show file tree
Hide file tree
Showing 3 changed files with 193 additions and 2 deletions.
8 changes: 6 additions & 2 deletions kong/api/endpoints.lua
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ local ERRORS_HTTP_CODES = {
[Errors.codes.INVALID_SIZE] = 400,
[Errors.codes.INVALID_UNIQUE] = 400,
[Errors.codes.INVALID_OPTIONS] = 400,
[Errors.codes.OPERATION_UNSUPPORTED] = 405,
}


Expand Down Expand Up @@ -113,8 +114,11 @@ local function handle_error(err_t)
return app_helpers.yield_error(err_t)
end

local body = utils.get_default_exit_body(status, err_t)
return kong.response.exit(status, body)
if err_t.code == Errors.codes.OPERATION_UNSUPPORTED then
return kong.response.exit(status, err_t)
end

return kong.response.exit(status, utils.get_default_exit_body(status, err_t))
end


Expand Down
5 changes: 5 additions & 0 deletions kong/api/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,11 @@ local function new_db_on_error(self)
return kong.response.exit(404, err)
end

if err.code == Errors.codes.OPERATION_UNSUPPORTED then
kong.log.err(err)
return kong.response.exit(405, err)
end

if err.code == Errors.codes.PRIMARY_KEY_VIOLATION
or err.code == Errors.codes.UNIQUE_VIOLATION
then
Expand Down
182 changes: 182 additions & 0 deletions spec/02-integration/04-admin_api/14-off_spec.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,182 @@
local cjson = require "cjson"
local utils = require "kong.tools.utils"
local helpers = require "spec.helpers"
local Errors = require "kong.db.errors"


local function it_content_types(title, fn)
local test_form_encoded = fn("application/x-www-form-urlencoded")
local test_multipart = fn("multipart/form-data")
local test_json = fn("application/json")

it(title .. " with application/www-form-urlencoded", test_form_encoded)
it(title .. " with multipart/form-data", test_multipart)
it(title .. " with application/json", test_json)
end

describe("Admin API #off", function()
local client

lazy_setup(function()
assert(helpers.start_kong({
database = "off",
}))
end)

lazy_teardown(function()
helpers.stop_kong(nil, true)
end)

before_each(function()
client = assert(helpers.admin_client())
end)

after_each(function()
if client then
client:close()
end
end)

describe("/routes", function()
describe("POST", function()
it_content_types("doesn't allow to creates a route", function(content_type)
return function()
if content_type == "multipart/form-data" then
-- the client doesn't play well with this
return
end

local res = client:post("/routes", {
body = {
protocols = { "http" },
hosts = { "my.route.com" },
service = { id = utils.uuid() },
},
headers = { ["Content-Type"] = content_type }
})
local body = assert.res_status(405, res)
local json = cjson.decode(body)
assert.same({
code = Errors.codes.OPERATION_UNSUPPORTED,
name = Errors.names[Errors.codes.OPERATION_UNSUPPORTED],
message = "cannot create 'routes' entities when not using a database",
}, json)
end
end)

it_content_types("doesn't allow to creates a complex route", function(content_type)
return function()
if content_type == "multipart/form-data" then
-- the client doesn't play well with this
return
end

local res = client:post("/routes", {
body = {
protocols = { "http" },
methods = { "GET", "POST", "PATCH" },
hosts = { "foo.api.com", "bar.api.com" },
paths = { "/foo", "/bar" },
service = { id = utils.uuid() },
},
headers = { ["Content-Type"] = content_type }
})

local body = assert.res_status(405, res)
local json = cjson.decode(body)
assert.same({
code = Errors.codes.OPERATION_UNSUPPORTED,
name = Errors.names[Errors.codes.OPERATION_UNSUPPORTED],
message = "cannot create 'routes' entities when not using a database",
}, json)
end
end)
end)

describe("GET", function()
describe("errors", function()
it("handles invalid offsets", function()
local res = client:get("/routes", { query = { offset = "x" } })
local body = assert.res_status(400, res)
assert.same({
code = Errors.codes.INVALID_OFFSET,
name = "invalid offset",
message = "'x' is not a valid offset: bad base64 encoding"
}, cjson.decode(body))

res = client:get("/routes", { query = { offset = "|potato|" } })
body = assert.res_status(400, res)

local json = cjson.decode(body)
json.message = nil

assert.same({
code = Errors.codes.INVALID_OFFSET,
name = "invalid offset",
}, json)
end)
end)
end)

it("returns HTTP 405 on invalid method", function()
local methods = { "DELETE", "PUT", "PATCH", "POST" }
for i = 1, #methods do
local res = assert(client:send {
method = methods[i],
path = "/routes",
body = {
paths = { "/" },
service = { id = utils.uuid() }
},
headers = {
["Content-Type"] = "application/json"
}
})
local body = assert.response(res).has.status(405)
local json = cjson.decode(body)
if methods[i] == "POST" then
assert.same({
code = Errors.codes.OPERATION_UNSUPPORTED,
name = Errors.names[Errors.codes.OPERATION_UNSUPPORTED],
message = "cannot create 'routes' entities when not using a database",
}, json)

else
assert.same({ message = "Method not allowed" }, json)
end
end
end)
end)

describe("/routes/{route}", function()
it("returns HTTP 405 on invalid method", function()
local methods = { "PUT", "POST" }
for i = 1, #methods do
local res = assert(client:send {
method = methods[i],
path = "/routes/" .. utils.uuid(),
body = {
paths = { "/" },
service = { id = utils.uuid() }
},
headers = {
["Content-Type"] = "application/json"
}
})

local body = assert.response(res).has.status(405)
local json = cjson.decode(body)
if methods[i] ~= "POST" then
assert.same({
code = Errors.codes.OPERATION_UNSUPPORTED,
name = Errors.names[Errors.codes.OPERATION_UNSUPPORTED],
message = "cannot create or update 'routes' entities when not using a database",
}, json)

else
assert.same({ message = "Method not allowed" }, json)
end
end
end)
end)
end)

0 comments on commit 95bfe6a

Please sign in to comment.