Skip to content

Commit

Permalink
feat(sessions): store session's meatadata
Browse files Browse the repository at this point in the history
  • Loading branch information
raoxiaoyan committed Dec 9, 2024
1 parent 88ffdda commit b033733
Show file tree
Hide file tree
Showing 10 changed files with 143 additions and 18 deletions.
3 changes: 3 additions & 0 deletions kong-3.10.0-0.rockspec
Original file line number Diff line number Diff line change
Expand Up @@ -555,10 +555,13 @@ build = {
["kong.plugins.session.header_filter"] = "kong/plugins/session/header_filter.lua",
["kong.plugins.session.session"] = "kong/plugins/session/session.lua",
["kong.plugins.session.daos"] = "kong/plugins/session/daos.lua",
["kong.plugins.session.daos.session_metadatas"] = "kong/plugins/session/daos/session_metadatas.lua",
["kong.plugins.session.strategies.postgres.session_metadatas"] = "kong/plugins/session/strategies/postgres/session_metadatas.lua",
["kong.plugins.session.storage.kong"] = "kong/plugins/session/storage/kong.lua",
["kong.plugins.session.migrations.000_base_session"] = "kong/plugins/session/migrations/000_base_session.lua",
["kong.plugins.session.migrations.001_add_ttl_index"] = "kong/plugins/session/migrations/001_add_ttl_index.lua",
["kong.plugins.session.migrations.002_320_to_330"] = "kong/plugins/session/migrations/002_320_to_330.lua",
["kong.plugins.session.migrations.003_330_to_3100"] = "kong/plugins/session/migrations/003_330_to_3100.lua",
["kong.plugins.session.migrations"] = "kong/plugins/session/migrations/init.lua",

["kong.plugins.proxy-cache.handler"] = "kong/plugins/proxy-cache/handler.lua",
Expand Down
49 changes: 34 additions & 15 deletions kong/plugins/session/daos.lua
Original file line number Diff line number Diff line change
@@ -1,20 +1,39 @@
local typedefs = require "kong.db.schema.typedefs"


return {
{
primary_key = { "id" },
endpoint_key = "session_id",
name = "sessions",
cache_key = { "session_id" },
ttl = true,
db_export = false,
fields = {
{ id = typedefs.uuid },
{ session_id = { type = "string", unique = true, required = true } },
{ expires = { type = "integer" } },
{ data = { type = "string" } },
{ created_at = typedefs.auto_timestamp_s },
}
local sessions = {
primary_key = { "id" },
endpoint_key = "session_id",
name = "sessions",
cache_key = { "session_id" },
ttl = true,
db_export = false,
fields = {
{ id = typedefs.uuid },
{ session_id = { type = "string", unique = true, required = true } },
{ expires = { type = "integer" } },
{ data = { type = "string" } },
{ created_at = typedefs.auto_timestamp_s },
}
}

local session_metadatas = {
primary_key = { "id" },
name = "session_metadatas",
dao = "kong.plugins.session.daos.session_metadatas",
generate_admin_api = false,
db_export = false,
fields = {
{ id = typedefs.uuid },
{ session = { type = "foreign", reference = "sessions", required = true, on_delete = "cascade" } },
{ sid = { type = "string" } },
{ audience = { type = "string" } },
{ subject = { type = "string" } },
{ created_at = typedefs.auto_timestamp_s },
}
}

return {
sessions,
session_metadatas,
}
18 changes: 18 additions & 0 deletions kong/plugins/session/daos/session_metadatas.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
local session_metadatas = {}

function session_metadatas:select_by_audience_and_subject(audience, subject)
return self.strategy:select_by_audience_and_subject(audience, subject)
end

function session_metadatas:select_by_sid(sid)
local cache_key = kong.db.sessions:cache_key(sid)
local session = kong.cache:get(cache_key) or {}

local res = {}
for row in kong.db.session_metadatas:each_for_session({ id = session.id }) do
table.insert(res, row)
end
return res
end

return session_metadatas
22 changes: 22 additions & 0 deletions kong/plugins/session/migrations/003_330_to_3100.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
return {
postgres = {
up = [[
CREATE TABLE IF NOT EXISTS session_metadatas(
id uuid,
session_id uuid REFERENCES "sessions" ("id") ON DELETE CASCADE,
sid text UNIQUE,
subject text,
audience text,
created_at timestamp WITH TIME ZONE,
PRIMARY KEY (id)
);
DO $$
BEGIN
CREATE INDEX IF NOT EXISTS "session_id_idx" ON "session_metadatas" ("session_id");
EXCEPTION WHEN UNDEFINED_COLUMN THEN
-- Do nothing, accept existing state
END$$;
]],
},
}
1 change: 1 addition & 0 deletions kong/plugins/session/migrations/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@ return {
"000_base_session",
"001_add_ttl_index",
"002_320_to_330",
"003_330_to_3100",
}
8 changes: 8 additions & 0 deletions kong/plugins/session/schema.lua
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,14 @@ return {
default = "session_logout"
}
},
{
store_metadata = {
description =
"Whether to also store metadata of sessions, such as collecting data of sessions for a specific audience belonging to a specific subject.",
type = "boolean",
default = false
}
},
},
shorthand_fields = {
-- TODO: deprecated forms, to be removed in Kong 4.0
Expand Down
1 change: 1 addition & 0 deletions kong/plugins/session/session.lua
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ function _M.open_session(conf)
remember_absolute_timeout = conf.remember_absolute_timeout,
response_headers = conf.response_headers,
request_headers = conf.request_headers,
store_metadata = conf.store_metadata or false,
})
end

Expand Down
27 changes: 24 additions & 3 deletions kong/plugins/session/storage/kong.lua
Original file line number Diff line number Diff line change
Expand Up @@ -38,15 +38,36 @@ local function load_session_from_cache(key)
return kong.cache:get(cache_key, nil, load_session_from_db, key)
end

local function insert_session_metadata(metadata, session)
if not metadata then
return
end

local function insert_session(key, value, ttl, current_time, old_key, stale_ttl, remember)
local audiences = metadata.audiences
local subjects = metadata.subjects
local count = #audiences
for i = 1, count do
kong.db.session_metadatas:insert({
sid = session.session_id,
audience = audiences[i],
subject = subjects[i],
session = session,
})
end
end

local function insert_session(key, value, ttl, current_time, old_key, stale_ttl, metadata, remember)
DATA.session_id = key
DATA.data = value
DATA.expires = current_time + ttl

TTL.ttl = ttl

local insert_ok, insert_err = kong.db.sessions:insert(DATA, TTL)
if not insert_err then
insert_session_metadata(metadata, insert_ok)
end

if not old_key then
return insert_ok, insert_err
end
Expand Down Expand Up @@ -103,11 +124,11 @@ end

function storage:set(name, key, value, ttl, current_time, old_key, stale_ttl, metadata, remember)
if get_phase() == "header_filter" then
timer_at(0, insert_session_timer, key, value, ttl, current_time, old_key, stale_ttl, remember)
timer_at(0, insert_session_timer, key, value, ttl, current_time, old_key, stale_ttl, metadata, remember)
return true
end

return insert_session(key, value, ttl, current_time, old_key, stale_ttl, remember)
return insert_session(key, value, ttl, current_time, old_key, stale_ttl, metadata, remember)
end


Expand Down
14 changes: 14 additions & 0 deletions kong/plugins/session/strategies/postgres/session_metadatas.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
local fmt = string.format

local session_metadatas = {}

function session_metadatas:select_by_audience_and_subject(audience, subject)
local qs = fmt(
"SELECT * FROM session_metadatas WHERE audience = %s AND subject = %s;",
kong.db.connector:escape_literal(audience),
kong.db.connector:escape_literal(subject))

return kong.db.connector:query(qs, "read")
end

return session_metadatas
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
local uh = require "spec/upgrade_helpers"

describe("database migration", function ()
if uh.database_type() == "postgres" then
uh.all_phases("has created the expected new columns", function()
assert.table_has_column("session_metadatas", "id", "uuid")
assert.table_has_column("session_metadatas", "session_id", "uuid")
assert.table_has_column("session_metadatas", "sid", "text")
assert.table_has_column("session_metadatas", "subject", "text")
assert.table_has_column("session_metadatas", "audience", "text")
assert.table_has_column("session_metadatas", "created_at", "timestamp with time zone", "timestamp")
end)

uh.all_phases("has created the expected indexes", function()
assert.table_has_index("session_metadatas", "session_id_idx")
end)
end
end)

0 comments on commit b033733

Please sign in to comment.