bsw/jbe@0: Session = mondelefant.new_class() bsw/jbe@0: Session.table = 'session' bsw/jbe@0: Session.primary_key = { 'ident' } bsw/jbe@0: bsw/jbe@0: Session:add_reference{ bsw/jbe@0: mode = 'm1', bsw/jbe@0: to = "Member", bsw/jbe@0: this_key = 'member_id', bsw/jbe@0: that_key = 'id', bsw/jbe@0: ref = 'member', bsw/jbe@0: } bsw/jbe@0: bsw/jbe@1309: Session:add_reference{ bsw/jbe@1309: mode = 'm1', bsw/jbe@1309: to = "Member", bsw/jbe@1309: this_key = 'real_member_id', bsw/jbe@1309: that_key = 'id', bsw/jbe@1309: ref = 'real_member', bsw/jbe@1309: } bsw/jbe@1309: bsw/jbe@1309: local secret_length = 24 bsw/jbe@1309: local secret_alphabet = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz' bsw@1494: local secret_purposes = { "oauth", "_other" } bsw/jbe@1309: for idx, purpose in ipairs(secret_purposes) do bsw/jbe@1309: secret_purposes[purpose] = idx bsw/jbe@1309: end bsw/jbe@1309: bsw/jbe@1309: local function random_string(length_multiplier) bsw/jbe@0: return multirand.string( bsw/jbe@1309: secret_length * (length_multiplier or 1), bsw/jbe@1309: secret_alphabet bsw/jbe@0: ) bsw/jbe@0: end bsw/jbe@0: bsw/jbe@0: function Session:new() bsw/jbe@0: local session = self.prototype.new(self) -- super call bsw/jbe@0: session.ident = random_string() bsw/jbe@1309: session.additional_secret = random_string(#secret_purposes) bsw/jbe@1309: session:save() bsw/jbe@0: return session bsw/jbe@0: end bsw/jbe@0: bsw@1511: function Session.object:set_cookie() bsw@1511: request.set_cookie{ bsw@1511: name = config.cookie_name, bsw@1511: value = self.ident, bsw@1511: samesite = "none" bsw@1511: } bsw@1511: request.set_cookie{ bsw@1521: name = config.cookie_name_samesite, bsw@1511: value = self.ident bsw@1511: } bsw@1511: end bsw@1511: bsw/jbe@1309: function Session.object:additional_secret_for(purpose) bsw/jbe@1309: local use_hash = false bsw/jbe@1309: local idx = secret_purposes[purpose] bsw/jbe@1309: if not idx then bsw/jbe@1309: idx = assert(secret_purposes._other, "No other secrets supported") bsw/jbe@1309: use_hash = true bsw/jbe@1309: end bsw/jbe@1309: local from_pos = secret_length * (idx-1) + 1 bsw/jbe@1309: local to_pos = from_pos + secret_length - 1 bsw/jbe@1309: local secret = string.sub(self.additional_secret, from_pos, to_pos) bsw/jbe@1309: if #secret ~= secret_length then bsw/jbe@1309: self:destroy() bsw/jbe@1309: error("Session state invalid") bsw/jbe@1309: end bsw/jbe@1309: if use_hash then bsw/jbe@1309: local moonhash = require "moonhash" -- TODO: auto loader for libraries in WebMCP? bsw/jbe@1309: secret = moonhash.shake256(secret .. "\0" .. purpose, secret_length, secret_alphabet) bsw/jbe@1309: end bsw/jbe@1309: return secret bsw/jbe@1309: end bsw/jbe@1309: bsw/jbe@0: function Session:by_ident(ident) bsw/jbe@0: local selector = self:new_selector() bsw/jbe@0: selector:add_where{ 'ident = ?', ident } bsw@1074: selector:add_field{ 'authority_uid' } bsw/jbe@0: selector:optional_object_mode() bsw/jbe@0: return selector:exec() bsw/jbe@0: end bsw@813: bsw@813: function Session.object:has_access(level) bsw@813: if level == "member" then bsw@813: if app.session.member_id then bsw@813: return true bsw@813: else bsw@813: return false bsw@813: end bsw@813: bsw@813: elseif level == "everything" then bsw@813: if self:has_access("member") or config.public_access == "everything" then bsw@813: return true bsw@813: else bsw@813: return false bsw@813: end bsw@813: bsw@813: elseif level == "all_pseudonymous" then bsw@813: if self:has_access("everything") or config.public_access == "all_pseudonymous" then bsw@813: return true bsw@813: else bsw@813: return false bsw@813: end bsw@813: bsw@813: elseif level == "authors_pseudonymous" then bsw@813: if self:has_access("all_pseudonymous") or config.public_access == "authors_pseudonymous" then bsw@813: return true bsw@813: else bsw@813: return false bsw@813: end bsw@813: bsw@813: elseif level == "anonymous" then bsw@813: if self:has_access("authors_pseudonymous") or config.public_access == "anonymous" then bsw@813: return true bsw@813: else bsw@813: return false bsw@813: end bsw@813: bsw@813: end bsw@813: bsw@813: error("invalid access level") bsw@813: end