Skip to content

Commit 9dded31

Browse files
authored
fix(dbless): nest unique field errors for child entities (#14017)
* fix(dbless): nest unique field errors for child entities This applies the same fix as b8891eb but to a different code path that checks fields with a unique constraint. * improve docstring
1 parent 2af3a76 commit 9dded31

File tree

3 files changed

+179
-18
lines changed

3 files changed

+179
-18
lines changed
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
message: "Fixed an issue where `POST /config?flatten_errors=1` could not return a proper response if the input contained duplicate consumer credentials."
2+
type: bugfix
3+
scope: Core

kong/db/schema/others/declarative_config.lua

Lines changed: 20 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -361,6 +361,22 @@ local function uniqueness_error_msg(entity, key, value)
361361
"with " .. key .. " set to '" .. value .. "' already declared"
362362
end
363363

364+
local function add_error(errs, parent_entity, parent_idx, entity, entity_idx, err)
365+
if parent_entity and parent_idx then
366+
errs[parent_entity] = errs[parent_entity] or {}
367+
errs[parent_entity][parent_idx] = errs[parent_entity][parent_idx] or {}
368+
errs[parent_entity][parent_idx][entity] = errs[parent_entity][parent_idx][entity] or {}
369+
370+
-- e.g. errs["upstreams"][5]["targets"][2]
371+
errs[parent_entity][parent_idx][entity][entity_idx] = err
372+
373+
else
374+
errs[entity] = errs[entity] or {}
375+
376+
-- e.g. errs["consumers"][3]
377+
errs[entity][entity_idx] = err
378+
end
379+
end
364380

365381
local function populate_references(input, known_entities, by_id, by_key, expected, errs, parent_entity, parent_idx)
366382
for _, entity in ipairs(known_entities) do
@@ -400,31 +416,17 @@ local function populate_references(input, known_entities, by_id, by_key, expecte
400416
if key and key ~= ngx.null then
401417
local ok = add_to_by_key(by_key, entity_schema, item, entity, key)
402418
if not ok then
403-
errs[entity] = errs[entity] or {}
404-
errs[entity][i] = uniqueness_error_msg(entity, endpoint_key, key)
419+
add_error(errs, parent_entity, parent_idx, entity, i,
420+
uniqueness_error_msg(entity, endpoint_key, key))
405421
failed = true
406422
end
407423
end
408424

409425
if item_id then
410426
by_id[entity] = by_id[entity] or {}
411427
if (not failed) and by_id[entity][item_id] then
412-
local err_t
413-
414-
if parent_entity and parent_idx then
415-
errs[parent_entity] = errs[parent_entity] or {}
416-
errs[parent_entity][parent_idx] = errs[parent_entity][parent_idx] or {}
417-
errs[parent_entity][parent_idx][entity] = errs[parent_entity][parent_idx][entity] or {}
418-
419-
-- e.g. errs["upstreams"][5]["targets"]
420-
err_t = errs[parent_entity][parent_idx][entity]
421-
422-
else
423-
errs[entity] = errs[entity] or {}
424-
err_t = errs[entity]
425-
end
426-
427-
err_t[i] = uniqueness_error_msg(entity, "primary key", item_id)
428+
add_error(errs, parent_entity, parent_idx, entity, i,
429+
uniqueness_error_msg(entity, "primary key", item_id))
428430

429431
else
430432
by_id[entity][item_id] = item

spec/02-integration/04-admin_api/15-off_spec.lua

Lines changed: 156 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2323,6 +2323,162 @@ R6InCcH2Wh8wSeY5AuDXvu2tv9g/PW9wIJmPuKSHMA==
23232323
}, post_config(input))
23242324
end)
23252325

2326+
it("correctly handles nested entity errors", function()
2327+
local consumers = {
2328+
{
2329+
id = "cdac30ee-cd7e-465c-99b6-84f3e4e17015",
2330+
username = "consumer-01",
2331+
tags = { "consumer-01" },
2332+
basicauth_credentials = {
2333+
{
2334+
id = "089091f4-cb8b-48f5-8463-8319097be716",
2335+
username = "user-01", password = "pwd",
2336+
tags = { "consumer-01-credential-01" },
2337+
},
2338+
{
2339+
id = "b1443d61-ccd9-4359-b82a-f37515442295",
2340+
username = "user-11", password = "pwd",
2341+
tags = { "consumer-01-credential-02" },
2342+
},
2343+
{
2344+
id = "2603d010-edbe-4713-94ef-145e281cbf4c",
2345+
username = "user-02", password = "pwd",
2346+
tags = { "consumer-01-credential-03" },
2347+
},
2348+
{
2349+
id = "760cf441-613c-48a2-b377-36aebc9f9ed0",
2350+
-- unique violation!
2351+
username = "user-11", password = "pwd",
2352+
tags = { "consumer-01-credential-04" },
2353+
}
2354+
},
2355+
},
2356+
{
2357+
id = "c0c021f5-dae1-4031-bcf6-42e3c4d9ced9",
2358+
username = "consumer-02",
2359+
tags = { "consumer-02" },
2360+
basicauth_credentials = {
2361+
{
2362+
id = "d0cd1919-bb07-4c85-b407-f33feb74f6e2",
2363+
username = "user-99", password = "pwd",
2364+
tags = { "consumer-02-credential-01" },
2365+
}
2366+
},
2367+
},
2368+
{
2369+
id = "9acb0270-73aa-4968-b9e4-a4924e4aced5",
2370+
username = "consumer-03",
2371+
tags = { "consumer-03" },
2372+
basicauth_credentials = {
2373+
{
2374+
id = "7e8bcd10-cdcd-41f1-8c4d-9790d34aa67d",
2375+
-- unique violation!
2376+
username = "user-01", password = "pwd",
2377+
tags = { "consumer-03-credential-01" },
2378+
},
2379+
{
2380+
id = "7fe186bd-44e5-4b97-854d-85a24929889d",
2381+
username = "user-33", password = "pwd",
2382+
tags = { "consumer-03-credential-02" },
2383+
},
2384+
{
2385+
id = "6547c325-5332-41fc-a954-d4972926cdb5",
2386+
-- unique violation!
2387+
username = "user-02", password = "pwd",
2388+
tags = { "consumer-03-credential-03" },
2389+
},
2390+
{
2391+
id = "e091a955-9ee1-4403-8d0a-a7f1f8bafaca",
2392+
-- unique violation!
2393+
username = "user-33", password = "pwd",
2394+
tags = { "consumer-03-credential-04" },
2395+
}
2396+
},
2397+
}
2398+
}
2399+
2400+
local input = {
2401+
_format_version = "3.0",
2402+
consumers = consumers,
2403+
}
2404+
2405+
validate({
2406+
-- consumer 1 / credential 4
2407+
{
2408+
entity = {
2409+
consumer = { id = consumers[1].id },
2410+
id = consumers[1].basicauth_credentials[4].id,
2411+
tags = consumers[1].basicauth_credentials[4].tags,
2412+
password = "pwd",
2413+
username = "user-11"
2414+
},
2415+
entity_id = consumers[1].basicauth_credentials[4].id,
2416+
entity_tags = consumers[1].basicauth_credentials[4].tags,
2417+
entity_type = "basicauth_credential",
2418+
errors = { {
2419+
message = "uniqueness violation: 'basicauth_credentials' entity with username set to 'user-11' already declared",
2420+
type = "entity"
2421+
} }
2422+
},
2423+
2424+
-- consumer 3 / credential 1
2425+
{
2426+
entity = {
2427+
consumer = { id = consumers[3].id },
2428+
id = consumers[3].basicauth_credentials[1].id,
2429+
tags = consumers[3].basicauth_credentials[1].tags,
2430+
password = "pwd",
2431+
username = "user-01"
2432+
},
2433+
entity_id = consumers[3].basicauth_credentials[1].id,
2434+
entity_tags = consumers[3].basicauth_credentials[1].tags,
2435+
entity_type = "basicauth_credential",
2436+
errors = { {
2437+
message = "uniqueness violation: 'basicauth_credentials' entity with username set to 'user-01' already declared",
2438+
type = "entity"
2439+
} }
2440+
},
2441+
2442+
-- consumer 3 / credential 3
2443+
{
2444+
entity = {
2445+
consumer = { id = consumers[3].id },
2446+
id = consumers[3].basicauth_credentials[3].id,
2447+
tags = consumers[3].basicauth_credentials[3].tags,
2448+
password = "pwd",
2449+
username = "user-02"
2450+
},
2451+
entity_id = consumers[3].basicauth_credentials[3].id,
2452+
entity_tags = consumers[3].basicauth_credentials[3].tags,
2453+
entity_type = "basicauth_credential",
2454+
errors = { {
2455+
message = "uniqueness violation: 'basicauth_credentials' entity with username set to 'user-02' already declared",
2456+
type = "entity"
2457+
} }
2458+
},
2459+
2460+
-- consumer 3 / credential 4
2461+
{
2462+
entity = {
2463+
consumer = { id = consumers[3].id },
2464+
id = consumers[3].basicauth_credentials[4].id,
2465+
tags = consumers[3].basicauth_credentials[4].tags,
2466+
password = "pwd",
2467+
username = "user-33"
2468+
},
2469+
entity_id = consumers[3].basicauth_credentials[4].id,
2470+
entity_tags = consumers[3].basicauth_credentials[4].tags,
2471+
entity_type = "basicauth_credential",
2472+
errors = { {
2473+
message = "uniqueness violation: 'basicauth_credentials' entity with username set to 'user-33' already declared",
2474+
type = "entity"
2475+
} }
2476+
},
2477+
2478+
2479+
}, post_config(input))
2480+
end)
2481+
23262482
it("preserves IDs from the input", function()
23272483
local id = "0175e0e8-3de9-56b4-96f1-b12dcb4b6691"
23282484
local service = {

0 commit comments

Comments
 (0)