897 lines
22 KiB
Lua
897 lines
22 KiB
Lua
local Errors = require "kong.db.errors"
|
|
local uuid = require "kong.tools.uuid"
|
|
local arguments = require "kong.api.arguments"
|
|
local workspaces = require "kong.workspaces"
|
|
local app_helpers = require "lapis.application"
|
|
|
|
|
|
local kong = kong
|
|
local escape_uri = ngx.escape_uri
|
|
local unescape_uri = ngx.unescape_uri
|
|
local tonumber = tonumber
|
|
local tostring = tostring
|
|
local select = select
|
|
local pairs = pairs
|
|
local null = ngx.null
|
|
local type = type
|
|
local fmt = string.format
|
|
local concat = table.concat
|
|
local re_match = ngx.re.match
|
|
local splitn = require("kong.tools.string").splitn
|
|
local get_default_exit_body = require("kong.tools.http").get_default_exit_body
|
|
|
|
|
|
-- error codes http status codes
|
|
local ERRORS_HTTP_CODES = {
|
|
[Errors.codes.INVALID_PRIMARY_KEY] = 400,
|
|
[Errors.codes.SCHEMA_VIOLATION] = 400,
|
|
[Errors.codes.PRIMARY_KEY_VIOLATION] = 400,
|
|
[Errors.codes.FOREIGN_KEY_VIOLATION] = 400,
|
|
[Errors.codes.UNIQUE_VIOLATION] = 409,
|
|
[Errors.codes.NOT_FOUND] = 404,
|
|
[Errors.codes.INVALID_OFFSET] = 400,
|
|
[Errors.codes.DATABASE_ERROR] = 500,
|
|
[Errors.codes.INVALID_SIZE] = 400,
|
|
[Errors.codes.INVALID_UNIQUE] = 400,
|
|
[Errors.codes.INVALID_OPTIONS] = 400,
|
|
[Errors.codes.OPERATION_UNSUPPORTED] = 405,
|
|
[Errors.codes.FOREIGN_KEYS_UNRESOLVED] = 400,
|
|
[Errors.codes.REFERENCED_BY_OTHERS] = 400,
|
|
}
|
|
|
|
local TAGS_AND_REGEX
|
|
local TAGS_OR_REGEX
|
|
do
|
|
-- printable ASCII (0x20-0x7E except ','(0x2C) and '/'(0x2F),
|
|
-- plus non-ASCII utf8 (0x80-0xF4)
|
|
local tag_bytes = [[\x20-\x2B\x2D\x2E\x30-\x7E\x80-\xF4]]
|
|
|
|
TAGS_AND_REGEX = "^([" .. tag_bytes .. "]+(?:,|$))+$"
|
|
TAGS_OR_REGEX = "^([" .. tag_bytes .. "]+(?:/|$))+$"
|
|
end
|
|
|
|
local function get_message(default, ...)
|
|
local message
|
|
local n = select("#", ...)
|
|
if n > 0 then
|
|
if n == 1 then
|
|
local arg = select(1, ...)
|
|
if type(arg) == "table" then
|
|
message = arg
|
|
elseif arg ~= nil then
|
|
message = tostring(arg)
|
|
end
|
|
|
|
else
|
|
message = {}
|
|
for i = 1, n do
|
|
local arg = select(i, ...)
|
|
message[i] = tostring(arg)
|
|
end
|
|
message = concat(message)
|
|
end
|
|
end
|
|
|
|
if not message then
|
|
message = default
|
|
end
|
|
|
|
if type(message) == "string" then
|
|
message = { message = message }
|
|
end
|
|
|
|
return message
|
|
end
|
|
|
|
|
|
local function ok(...)
|
|
return kong.response.exit(200, get_message(nil, ...))
|
|
end
|
|
|
|
|
|
local function created(...)
|
|
return kong.response.exit(201, get_message(nil, ...))
|
|
end
|
|
|
|
|
|
local function no_content()
|
|
return kong.response.exit(204)
|
|
end
|
|
|
|
|
|
local function not_found(...)
|
|
return kong.response.exit(404, get_message("Not found", ...))
|
|
end
|
|
|
|
|
|
local function method_not_allowed(...)
|
|
return kong.response.exit(405, get_message("Method not allowed", ...))
|
|
end
|
|
|
|
|
|
local function unexpected(...)
|
|
return kong.response.exit(500, get_message("An unexpected error occurred", ...))
|
|
end
|
|
|
|
|
|
local function handle_error(err_t)
|
|
if type(err_t) ~= "table" then
|
|
kong.log.err(err_t)
|
|
return unexpected()
|
|
end
|
|
|
|
if err_t.strategy then
|
|
err_t.strategy = nil
|
|
end
|
|
|
|
local status = ERRORS_HTTP_CODES[err_t.code]
|
|
if not status or status == 500 then
|
|
return app_helpers.yield_error(err_t)
|
|
end
|
|
|
|
if err_t.code == Errors.codes.OPERATION_UNSUPPORTED then
|
|
return kong.response.exit(status, err_t)
|
|
end
|
|
|
|
return kong.response.exit(status, get_default_exit_body(status, err_t))
|
|
end
|
|
|
|
|
|
local function extract_options(db, args, schema, context)
|
|
local options = {
|
|
nulls = true,
|
|
pagination = {
|
|
page_size = 100,
|
|
max_page_size = 1000,
|
|
},
|
|
workspace = workspaces.get_workspace_id(),
|
|
}
|
|
|
|
if args and schema and context then
|
|
if schema.ttl == true and args.ttl ~= nil and (context == "insert" or
|
|
context == "update" or
|
|
context == "upsert") then
|
|
options.ttl = args.ttl
|
|
args.ttl = nil
|
|
end
|
|
|
|
if schema.fields.tags and args.tags ~= nil and context == "page" then
|
|
if args.tags == null or #args.tags == 0 then
|
|
local error_message = "cannot be null"
|
|
return nil, error_message, db[schema.name].errors:invalid_options({tags = error_message})
|
|
end
|
|
|
|
local tags = args.tags
|
|
if type(tags) == "table" then
|
|
tags = tags[1]
|
|
end
|
|
|
|
if re_match(tags, TAGS_AND_REGEX, 'jo') then
|
|
-- 'a,b,c' or 'a'
|
|
options.tags_cond = 'and'
|
|
options.tags = splitn(tags, ',')
|
|
elseif re_match(tags, TAGS_OR_REGEX, 'jo') then
|
|
-- 'a/b/c'
|
|
options.tags_cond = 'or'
|
|
options.tags = splitn(tags, '/')
|
|
else
|
|
options.tags = tags
|
|
-- not setting tags_cond since we can't determine the cond
|
|
-- will raise an error in db/dao/init.lua:validate_options_value
|
|
end
|
|
|
|
args.tags = nil
|
|
end
|
|
end
|
|
|
|
return options
|
|
end
|
|
|
|
|
|
local function get_page_size(args)
|
|
local size = args.size
|
|
if size ~= nil then
|
|
size = tonumber(size)
|
|
if size == nil then
|
|
return nil, "size must be a number"
|
|
end
|
|
|
|
return size
|
|
end
|
|
end
|
|
|
|
|
|
local function query_entity(context, self, db, schema, method)
|
|
local is_insert = context == "insert"
|
|
local is_update = context == "update" or context == "upsert"
|
|
|
|
local args
|
|
if is_update or is_insert then
|
|
args = self.args.post
|
|
else
|
|
args = self.args.uri
|
|
end
|
|
|
|
local opts, err, err_t = extract_options(db, args, schema, context)
|
|
if err then
|
|
return nil, err, err_t
|
|
end
|
|
|
|
local schema_name = schema.name
|
|
local dao = db[schema_name]
|
|
|
|
if is_insert then
|
|
return dao[method or context](dao, args, opts)
|
|
end
|
|
|
|
if context == "page" then
|
|
local size, err = get_page_size(args)
|
|
if err then
|
|
return nil, err, db[schema_name].errors:invalid_size(err)
|
|
end
|
|
|
|
if not method then
|
|
return dao[context](dao, size, args.offset, opts)
|
|
end
|
|
|
|
local key = self.params[schema_name]
|
|
if schema_name == "tags" then
|
|
key = unescape_uri(key)
|
|
end
|
|
return dao[method](dao, key, size, args.offset, opts)
|
|
end
|
|
|
|
local key = self.params[schema_name]
|
|
if key then
|
|
if type(key) ~= "table" then
|
|
if type(key) == "string" then
|
|
key = { id = unescape_uri(key) }
|
|
else
|
|
key = { id = key }
|
|
end
|
|
end
|
|
|
|
if key.id and not uuid.is_valid_uuid(key.id) then
|
|
local endpoint_key = schema.endpoint_key
|
|
if endpoint_key then
|
|
local field = schema.fields[endpoint_key]
|
|
local inferred_value = arguments.infer_value(key.id, field)
|
|
if is_update then
|
|
return dao[method or context .. "_by_" .. endpoint_key](dao, inferred_value, args, opts)
|
|
end
|
|
|
|
return dao[method or context .. "_by_" .. endpoint_key](dao, inferred_value, opts)
|
|
end
|
|
end
|
|
end
|
|
|
|
if is_update then
|
|
return dao[method or context](dao, key, args, opts)
|
|
end
|
|
|
|
return dao[method or context](dao, key, opts)
|
|
end
|
|
|
|
|
|
local function select_entity(...)
|
|
return query_entity("select", ...)
|
|
end
|
|
|
|
|
|
local function update_entity(...)
|
|
return query_entity("update", ...)
|
|
end
|
|
|
|
|
|
local function upsert_entity(...)
|
|
return query_entity("upsert", ...)
|
|
end
|
|
|
|
|
|
local function delete_entity(...)
|
|
return query_entity("delete", ...)
|
|
end
|
|
|
|
|
|
local function insert_entity(...)
|
|
return query_entity("insert", ...)
|
|
end
|
|
|
|
local function page_collection(...)
|
|
return query_entity("page", ...)
|
|
end
|
|
|
|
|
|
-- Generates admin api get collection endpoint functions
|
|
--
|
|
-- Examples:
|
|
--
|
|
-- /routes
|
|
-- /services/:services/routes
|
|
--
|
|
-- and
|
|
--
|
|
-- /services
|
|
local function get_collection_endpoint(schema, foreign_schema, foreign_field_name, method)
|
|
return not foreign_schema and function(self, db, helpers)
|
|
local next_page_tags = ""
|
|
local next_page_size = ""
|
|
|
|
local args = self.args.uri
|
|
if args.tags then
|
|
next_page_tags = "&tags=" .. escape_uri(type(args.tags) == "table" and args.tags[1] or args.tags)
|
|
end
|
|
|
|
if args.size then
|
|
next_page_size = "&size=" .. args.size
|
|
end
|
|
|
|
local data, _, err_t, offset = page_collection(self, db, schema, method)
|
|
if err_t then
|
|
return handle_error(err_t)
|
|
end
|
|
|
|
local next_page = offset and fmt("/%s?offset=%s%s%s",
|
|
schema.admin_api_name or
|
|
schema.name,
|
|
escape_uri(offset),
|
|
next_page_tags,
|
|
next_page_size) or null
|
|
|
|
return ok {
|
|
data = data,
|
|
offset = offset,
|
|
next = next_page,
|
|
}
|
|
|
|
end or function(self, db, helpers)
|
|
local foreign_entity, _, err_t = select_entity(self, db, foreign_schema)
|
|
if err_t then
|
|
return handle_error(err_t)
|
|
end
|
|
|
|
if not foreign_entity then
|
|
return not_found()
|
|
end
|
|
|
|
self.params[schema.name] = foreign_schema:extract_pk_values(foreign_entity)
|
|
|
|
local method = method or "page_for_" .. foreign_field_name
|
|
local data, _, err_t, offset = page_collection(self, db, schema, method)
|
|
if err_t then
|
|
return handle_error(err_t)
|
|
end
|
|
|
|
local foreign_key = self.params[foreign_schema.name]
|
|
local next_page = offset and fmt("/%s/%s/%s?offset=%s",
|
|
foreign_schema.admin_api_name or
|
|
foreign_schema.name,
|
|
foreign_key,
|
|
schema.admin_api_nested_name or
|
|
schema.admin_api_name or
|
|
schema.name,
|
|
escape_uri(offset)) or null
|
|
|
|
return ok {
|
|
data = data,
|
|
offset = offset,
|
|
next = next_page,
|
|
}
|
|
end
|
|
end
|
|
|
|
|
|
-- Generates admin api post collection endpoint functions
|
|
--
|
|
-- Examples:
|
|
--
|
|
-- /routes
|
|
-- /services/:services/routes
|
|
--
|
|
-- and
|
|
--
|
|
-- /services
|
|
local function post_collection_endpoint(schema, foreign_schema, foreign_field_name, method)
|
|
return function(self, db, helpers, post_process)
|
|
if foreign_schema then
|
|
local foreign_entity, _, err_t = select_entity(self, db, foreign_schema)
|
|
if err_t then
|
|
return handle_error(err_t)
|
|
end
|
|
|
|
if not foreign_entity then
|
|
return not_found()
|
|
end
|
|
|
|
self.args.post[foreign_field_name] = foreign_schema:extract_pk_values(foreign_entity)
|
|
end
|
|
|
|
local entity, _, err_t = insert_entity(self, db, schema, method)
|
|
if err_t then
|
|
return handle_error(err_t)
|
|
end
|
|
|
|
if post_process then
|
|
entity, _, err_t = post_process(entity)
|
|
if err_t then
|
|
return handle_error(err_t)
|
|
end
|
|
end
|
|
|
|
return created(entity)
|
|
end
|
|
end
|
|
|
|
|
|
-- Generates admin api get entity endpoint functions
|
|
--
|
|
-- Examples:
|
|
--
|
|
-- /routes/:routes
|
|
-- /routes/:routes/service
|
|
--
|
|
-- and
|
|
--
|
|
-- /services/:services
|
|
-- /services/:services/routes/:routes
|
|
local function get_entity_endpoint(schema, foreign_schema, foreign_field_name, method, is_foreign_entity_endpoint)
|
|
return function(self, db, helpers)
|
|
local entity, _, err_t
|
|
if foreign_schema then
|
|
entity, _, err_t = select_entity(self, db, schema)
|
|
else
|
|
entity, _, err_t = select_entity(self, db, schema, method)
|
|
end
|
|
|
|
if err_t then
|
|
return handle_error(err_t)
|
|
end
|
|
|
|
if not entity then
|
|
return not_found()
|
|
end
|
|
|
|
if foreign_schema then
|
|
local pk
|
|
if is_foreign_entity_endpoint then
|
|
pk = entity[foreign_field_name]
|
|
if not pk or pk == null then
|
|
return not_found()
|
|
end
|
|
|
|
self.params[foreign_schema.name] = pk
|
|
|
|
else
|
|
pk = schema:extract_pk_values(entity)
|
|
end
|
|
|
|
entity, _, err_t = select_entity(self, db, foreign_schema, method)
|
|
if err_t then
|
|
return handle_error(err_t)
|
|
end
|
|
|
|
if not entity then
|
|
return not_found()
|
|
end
|
|
|
|
if not is_foreign_entity_endpoint then
|
|
local fk = entity[foreign_field_name]
|
|
if not fk or fk == null then
|
|
return not_found()
|
|
end
|
|
|
|
fk = schema:extract_pk_values(fk)
|
|
for k, v in pairs(pk) do
|
|
if fk[k] ~= v then
|
|
return not_found()
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
return ok(entity)
|
|
end
|
|
end
|
|
|
|
|
|
-- Generates admin api put entity endpoint functions
|
|
--
|
|
-- Examples:
|
|
--
|
|
-- /routes/:routes
|
|
-- /routes/:routes/service
|
|
--
|
|
-- and
|
|
--
|
|
-- /services/:services
|
|
-- /services/:services/routes/:routes
|
|
local function put_entity_endpoint(schema, foreign_schema, foreign_field_name, method, is_foreign_entity_endpoint)
|
|
return not foreign_schema and function(self, db, helpers)
|
|
local entity, _, err_t = upsert_entity(self, db, schema, method)
|
|
if err_t then
|
|
return handle_error(err_t)
|
|
end
|
|
|
|
if not entity then
|
|
return not_found()
|
|
end
|
|
|
|
return ok(entity)
|
|
|
|
end or function(self, db, helpers)
|
|
local entity, _, err_t = select_entity(self, db, schema)
|
|
if err_t then
|
|
return handle_error(err_t)
|
|
end
|
|
|
|
if not entity then
|
|
return not_found()
|
|
end
|
|
|
|
local associate
|
|
|
|
if is_foreign_entity_endpoint then
|
|
local pk = entity[foreign_field_name]
|
|
if pk and pk ~= null then
|
|
self.params[foreign_schema.name] = pk
|
|
else
|
|
associate = true
|
|
self.params[foreign_schema.name] = uuid.uuid()
|
|
end
|
|
|
|
else
|
|
self.args.post[foreign_field_name] = schema:extract_pk_values(entity)
|
|
end
|
|
|
|
local foreign_entity
|
|
foreign_entity, _, err_t = upsert_entity(self, db, foreign_schema, method)
|
|
if err_t then
|
|
return handle_error(err_t)
|
|
end
|
|
|
|
if not foreign_entity then
|
|
return not_found()
|
|
end
|
|
|
|
if associate then
|
|
local pk = schema:extract_pk_values(entity)
|
|
local data = {
|
|
[foreign_field_name] = foreign_schema:extract_pk_values(foreign_entity)
|
|
}
|
|
|
|
_, _, err_t = db[schema.name]:update(pk, data)
|
|
if err_t then
|
|
return handle_error(err_t)
|
|
end
|
|
|
|
--if not entity then
|
|
-- route was deleted after service was created,
|
|
-- so we cannot associate anymore. perhaps not
|
|
-- worth it to handle, the service on the other
|
|
-- hand was updates just fine.
|
|
--end
|
|
end
|
|
|
|
return ok(foreign_entity)
|
|
end
|
|
end
|
|
|
|
|
|
-- Generates admin api patch entity endpoint functions
|
|
--
|
|
-- Examples:
|
|
--
|
|
-- /routes/:routes
|
|
-- /routes/:routes/service
|
|
--
|
|
-- and
|
|
--
|
|
-- /services/:services
|
|
-- /services/:services/routes/:routes
|
|
local function patch_entity_endpoint(schema, foreign_schema, foreign_field_name, method, is_foreign_entity_endpoint)
|
|
return not foreign_schema and function(self, db, helpers)
|
|
local entity, _, err_t = update_entity(self, db, schema, method)
|
|
if err_t then
|
|
return handle_error(err_t)
|
|
end
|
|
|
|
if not entity then
|
|
return not_found()
|
|
end
|
|
|
|
return ok(entity)
|
|
|
|
end or function(self, db, helpers)
|
|
local entity, _, err_t = select_entity(self, db, schema)
|
|
if err_t then
|
|
return handle_error(err_t)
|
|
end
|
|
|
|
if not entity then
|
|
return not_found()
|
|
end
|
|
|
|
if is_foreign_entity_endpoint then
|
|
local pk = entity[foreign_field_name]
|
|
if not pk or pk == null then
|
|
return not_found()
|
|
end
|
|
|
|
self.params[foreign_schema.name] = pk
|
|
|
|
else
|
|
if not self.args.post[foreign_field_name] then
|
|
self.args.post[foreign_field_name] = schema:extract_pk_values(entity)
|
|
end
|
|
|
|
local pk = schema:extract_pk_values(entity)
|
|
entity, _, err_t = select_entity(self, db, foreign_schema)
|
|
if err_t then
|
|
return handle_error(err_t)
|
|
end
|
|
|
|
if not entity then
|
|
return not_found()
|
|
end
|
|
|
|
local fk = entity[foreign_field_name]
|
|
if not fk or fk == null then
|
|
return not_found()
|
|
end
|
|
|
|
fk = schema:extract_pk_values(fk)
|
|
for k, v in pairs(pk) do
|
|
if fk[k] ~= v then
|
|
return not_found()
|
|
end
|
|
end
|
|
end
|
|
|
|
entity, _, err_t = update_entity(self, db, foreign_schema, method)
|
|
if err_t then
|
|
return handle_error(err_t)
|
|
end
|
|
|
|
if not entity then
|
|
return not_found()
|
|
end
|
|
|
|
return ok(entity)
|
|
end
|
|
end
|
|
|
|
|
|
-- Generates admin api delete entity endpoint functions
|
|
--
|
|
-- Examples:
|
|
--
|
|
-- /routes/:routes
|
|
-- /routes/:routes/service
|
|
--
|
|
-- and
|
|
--
|
|
-- /services/:services
|
|
-- /services/:services/routes/:routes
|
|
local function delete_entity_endpoint(schema, foreign_schema, foreign_field_name, method, is_foreign_entity_endpoint)
|
|
return not foreign_schema and function(self, db, helpers)
|
|
local _, _, err_t = delete_entity(self, db, schema, method)
|
|
if err_t then
|
|
return handle_error(err_t)
|
|
end
|
|
|
|
return no_content()
|
|
|
|
end or function(self, db, helpers)
|
|
local entity, _, err_t = select_entity(self, db, schema)
|
|
if err_t then
|
|
return handle_error(err_t)
|
|
end
|
|
|
|
if not entity then
|
|
return not_found()
|
|
end
|
|
|
|
if is_foreign_entity_endpoint then
|
|
local id = entity[foreign_field_name]
|
|
if not id or id == null then
|
|
return not_found()
|
|
end
|
|
|
|
return method_not_allowed()
|
|
end
|
|
|
|
local pk = schema:extract_pk_values(entity)
|
|
entity, _, err_t = select_entity(self, db, foreign_schema)
|
|
if err_t then
|
|
return handle_error(err_t)
|
|
end
|
|
|
|
if not entity then
|
|
return not_found()
|
|
end
|
|
|
|
local fk = entity[foreign_field_name]
|
|
if not fk or fk == null then
|
|
return not_found()
|
|
end
|
|
|
|
fk = schema:extract_pk_values(fk)
|
|
for k, v in pairs(pk) do
|
|
if fk[k] ~= v then
|
|
return not_found()
|
|
end
|
|
end
|
|
|
|
local _, _, err_t = delete_entity(self, db, foreign_schema, method)
|
|
if err_t then
|
|
return handle_error(err_t)
|
|
end
|
|
|
|
return no_content()
|
|
end
|
|
end
|
|
|
|
-- Generates admin api collection endpoint functions
|
|
--
|
|
-- Examples:
|
|
--
|
|
-- /routes
|
|
-- /services/:services/routes
|
|
--
|
|
-- and
|
|
--
|
|
-- /services
|
|
local function generate_collection_endpoints(endpoints, schema, foreign_schema, foreign_field_name)
|
|
local collection_path
|
|
if foreign_schema then
|
|
collection_path = fmt("/%s/:%s/%s", foreign_schema.admin_api_name or
|
|
foreign_schema.name,
|
|
foreign_schema.name,
|
|
schema.admin_api_nested_name or
|
|
schema.admin_api_name or
|
|
schema.name)
|
|
|
|
else
|
|
collection_path = fmt("/%s", schema.admin_api_name or
|
|
schema.name)
|
|
end
|
|
|
|
endpoints[collection_path] = {
|
|
schema = schema,
|
|
methods = {
|
|
--OPTIONS = method_not_allowed,
|
|
--HEAD = method_not_allowed,
|
|
GET = get_collection_endpoint(schema, foreign_schema, foreign_field_name),
|
|
POST = post_collection_endpoint(schema, foreign_schema, foreign_field_name),
|
|
--PUT = method_not_allowed,
|
|
--PATCH = method_not_allowed,
|
|
--DELETE = method_not_allowed,
|
|
},
|
|
}
|
|
end
|
|
|
|
|
|
-- Generates admin api entity endpoint functions
|
|
--
|
|
-- Examples:
|
|
--
|
|
-- /routes/:routes
|
|
-- /routes/:routes/service
|
|
--
|
|
-- and
|
|
--
|
|
-- /services/:services
|
|
-- /services/:services/routes/:routes
|
|
local function generate_entity_endpoints(endpoints, schema, foreign_schema, foreign_field_name, is_foreign_entity_endpoint)
|
|
local entity_path
|
|
if foreign_schema then
|
|
if is_foreign_entity_endpoint then
|
|
entity_path = fmt("/%s/:%s/%s", schema.admin_api_name or
|
|
schema.name,
|
|
schema.name,
|
|
foreign_field_name)
|
|
else
|
|
entity_path = fmt("/%s/:%s/%s/:%s", schema.admin_api_name or
|
|
schema.name,
|
|
schema.name,
|
|
foreign_schema.admin_api_nested_name or
|
|
foreign_schema.admin_api_name or
|
|
foreign_schema.name,
|
|
foreign_schema.name)
|
|
end
|
|
|
|
else
|
|
entity_path = fmt("/%s/:%s", schema.admin_api_name or
|
|
schema.name,
|
|
schema.name)
|
|
end
|
|
|
|
endpoints[entity_path] = {
|
|
schema = foreign_schema or schema,
|
|
methods = {
|
|
--OPTIONS = method_not_allowed,
|
|
--HEAD = method_not_allowed,
|
|
GET = get_entity_endpoint(schema, foreign_schema, foreign_field_name, nil, is_foreign_entity_endpoint),
|
|
--POST = method_not_allowed,
|
|
PUT = put_entity_endpoint(schema, foreign_schema, foreign_field_name, nil, is_foreign_entity_endpoint),
|
|
PATCH = patch_entity_endpoint(schema, foreign_schema, foreign_field_name, nil, is_foreign_entity_endpoint),
|
|
DELETE = delete_entity_endpoint(schema, foreign_schema, foreign_field_name, nil, is_foreign_entity_endpoint),
|
|
},
|
|
}
|
|
end
|
|
|
|
|
|
-- Generates admin api endpoint functions
|
|
--
|
|
-- Examples:
|
|
--
|
|
-- /routes
|
|
-- /routes/:routes
|
|
-- /routes/:routes/service
|
|
-- /services/:services/routes
|
|
--
|
|
-- and
|
|
--
|
|
-- /services
|
|
-- /services/:services
|
|
-- /services/:services/routes/:routes
|
|
local function generate_endpoints(schema, endpoints)
|
|
-- e.g. /routes
|
|
generate_collection_endpoints(endpoints, schema)
|
|
|
|
-- e.g. /routes/:routes
|
|
generate_entity_endpoints(endpoints, schema)
|
|
|
|
for foreign_field_name, foreign_field in schema:each_field() do
|
|
if foreign_field.type == "foreign" then
|
|
-- e.g. /routes/:routes/service
|
|
generate_entity_endpoints(endpoints, schema, foreign_field.schema, foreign_field_name, true)
|
|
|
|
-- e.g. /services/:services/routes
|
|
generate_collection_endpoints(endpoints, schema, foreign_field.schema, foreign_field_name)
|
|
|
|
-- e.g. /services/:services/routes/:routes
|
|
generate_entity_endpoints(endpoints, foreign_field.schema, schema, foreign_field_name)
|
|
end
|
|
end
|
|
|
|
return endpoints
|
|
end
|
|
|
|
|
|
-- A reusable handler for endpoints that are deactivated
|
|
-- (e.g. /targets/:targets)
|
|
local disable = {
|
|
before = function()
|
|
return not_found()
|
|
end
|
|
}
|
|
|
|
|
|
local Endpoints = {
|
|
disable = disable,
|
|
handle_error = handle_error,
|
|
get_page_size = get_page_size,
|
|
extract_options = extract_options,
|
|
select_entity = select_entity,
|
|
update_entity = update_entity,
|
|
upsert_entity = upsert_entity,
|
|
delete_entity = delete_entity,
|
|
insert_entity = insert_entity,
|
|
page_collection = page_collection,
|
|
get_entity_endpoint = get_entity_endpoint,
|
|
put_entity_endpoint = put_entity_endpoint,
|
|
patch_entity_endpoint = patch_entity_endpoint,
|
|
delete_entity_endpoint = delete_entity_endpoint,
|
|
get_collection_endpoint = get_collection_endpoint,
|
|
post_collection_endpoint = post_collection_endpoint,
|
|
}
|
|
|
|
|
|
function Endpoints.new(schema, endpoints)
|
|
return generate_endpoints(schema, endpoints)
|
|
end
|
|
|
|
|
|
return Endpoints
|