bunkerweb/lib/resty/session/file/thread.lua
Théophile Diot a3cd342f3e Squashed 'src/deps/src/lua-resty-session/' content from commit 8b5f8752f
git-subtree-dir: src/deps/src/lua-resty-session
git-subtree-split: 8b5f8752f3046396c414c5b97850e784c07e1641
2023-06-30 15:38:54 -04:00

209 lines
5.8 KiB
Lua

---
-- File storage backend worker thread module
--
-- @module resty.session.file.thread
local file_utils = require "resty.session.file.utils"
local utils = require "resty.session.utils"
local get_modification = file_utils.get_modification
local meta_get_key = file_utils.meta_get_key
local file_create = file_utils.file_create
local file_append = file_utils.file_append
local file_delete = file_utils.file_delete
local file_touch = file_utils.file_touch
local file_read = file_utils.file_read
local get_path = file_utils.get_path
local cleanup = file_utils.cleanup
local meta_get_latest = utils.meta_get_latest
local meta_get_value = utils.meta_get_value
local max = math.max
local function update_meta(path, prefix, suffix, name, meta_key, key, exp)
local meta_value = meta_get_value(key, exp)
if not meta_value then
return
end
local file_path = get_path(path, prefix, suffix, name, meta_key)
file_append(file_path, meta_value)
local current_expiry = get_modification(file_path) or 0
local new_expiry = max(current_expiry, exp)
file_touch(file_path, new_expiry)
end
---
-- Store session data.
--
-- @function module.set
-- @tparam string path the path where sessions are stored
-- @tparam string prefix the prefix for session files
-- @tparam string suffix the suffix for session files
-- @tparam string name the cookie name
-- @tparam string key session key
-- @tparam string value session value
-- @tparam number ttl session ttl
-- @tparam number current_time current time
-- @tparam[opt] string old_key old session id
-- @tparam string stale_ttl stale ttl
-- @tparam[opt] table metadata table of metadata
-- @tparam table remember whether storing persistent session or not
-- @treturn table|nil session metadata
-- @treturn string error message
local function set(path, prefix, suffix, name, key, value, ttl,
current_time, old_key, stale_ttl, metadata, remember)
local file_path = get_path(path, prefix, suffix, name, key)
if not metadata and not old_key then
local ok, err = file_create(file_path, value)
if ok and current_time and ttl then
file_touch(file_path, current_time + ttl)
end
cleanup(path, prefix, suffix, name, current_time)
return ok, err
end
local old_ttl, old_file_path
if old_key then
old_file_path = get_path(path, prefix, suffix, name, old_key)
if not remember then
local exp = get_modification(old_file_path)
if exp then
old_ttl = exp - current_time
end
end
end
local ok, err = file_create(file_path, value)
if ok and current_time and ttl then
file_touch(file_path, current_time + ttl)
end
if old_file_path then
if remember then
file_delete(old_file_path)
elseif not old_ttl or old_ttl > stale_ttl then
file_touch(old_file_path, current_time + stale_ttl)
end
end
if metadata then
local audiences = metadata.audiences
local subjects = metadata.subjects
local count = #audiences
for i = 1, count do
local meta_key = meta_get_key(audiences[i], subjects[i])
update_meta(path, prefix, suffix, name, meta_key, key, current_time + ttl)
if old_key then
update_meta(path, prefix, suffix, name, meta_key, old_key, 0)
end
end
end
cleanup(path, prefix, suffix, name, current_time)
return ok, err
end
---
-- Retrieve session data.
--
-- @function module.GET
-- @tparam string path the path where sessions are stored
-- @tparam string prefix the prefix for session files
-- @tparam string suffix the suffix for session files
-- @tparam string name cookie name
-- @tparam string key session key
-- @treturn string|nil session data
-- @treturn string error message
local function get(path, prefix, suffix, name, key, current_time)
local file_path = get_path(path, prefix, suffix, name, key)
-- TODO: do we want to check expiry here?
-- The cookie header already has the info and has a MAC too.
local exp = get_modification(file_path)
if exp and exp < current_time then
return nil, "expired"
end
return file_read(file_path)
end
---
-- Delete session data.
--
-- @function module.delete
-- @tparam string path the path where sessions are stored
-- @tparam string prefix the prefix for session files
-- @tparam string suffix the suffix for session files
-- @tparam string name the cookie name
-- @tparam string key session key
-- @tparam number current_time current time
-- @treturn table|nil session metadata
-- @treturn string error message
local function delete(path, prefix, suffix, name, key, current_time, metadata)
local file_path = get_path(path, prefix, suffix, name, key)
file_delete(file_path)
if metadata then
local audiences = metadata.audiences
local subjects = metadata.subjects
local count = #audiences
for i = 1, count do
local meta_key = meta_get_key(audiences[i], subjects[i])
update_meta(path, prefix, suffix, name, meta_key, key, 0)
end
end
cleanup(path, prefix, suffix, name, current_time)
return true
end
---
-- Read session metadata.
--
-- @function module.read_metadata
-- @tparam string path the path where sessions are stored
-- @tparam string prefix the prefix for session files
-- @tparam string suffix the suffix for session files
-- @tparam string name the cookie name
-- @tparam string audience session audience
-- @tparam string subject session subject
-- @tparam number current_time current time
-- @treturn table|nil session metadata
-- @treturn string error message
local function read_metadata(path, prefix, suffix, name, audience, subject, current_time)
local meta_key = meta_get_key(audience, subject)
local file_path = get_path(path, prefix, suffix, name, meta_key)
local metadata, err = file_read(file_path)
if not metadata then
return nil, err
end
return meta_get_latest(metadata, current_time)
end
return {
set = set,
get = get,
delete = delete,
read_metadata = read_metadata,
}