| rev | line source | 
| bsw/jbe@0 | 1 Session = mondelefant.new_class() | 
| bsw/jbe@0 | 2 Session.table = 'session' | 
| bsw/jbe@0 | 3 Session.primary_key = { 'ident' } | 
| bsw/jbe@0 | 4 | 
| bsw/jbe@0 | 5 Session:add_reference{ | 
| bsw/jbe@0 | 6   mode          = 'm1', | 
| bsw/jbe@0 | 7   to            = "Member", | 
| bsw/jbe@0 | 8   this_key      = 'member_id', | 
| bsw/jbe@0 | 9   that_key      = 'id', | 
| bsw/jbe@0 | 10   ref           = 'member', | 
| bsw/jbe@0 | 11 } | 
| bsw/jbe@0 | 12 | 
| bsw/jbe@1309 | 13 Session:add_reference{ | 
| bsw/jbe@1309 | 14   mode          = 'm1', | 
| bsw/jbe@1309 | 15   to            = "Member", | 
| bsw/jbe@1309 | 16   this_key      = 'real_member_id', | 
| bsw/jbe@1309 | 17   that_key      = 'id', | 
| bsw/jbe@1309 | 18   ref           = 'real_member', | 
| bsw/jbe@1309 | 19 } | 
| bsw/jbe@1309 | 20 | 
| bsw/jbe@1309 | 21 local secret_length = 24 | 
| bsw/jbe@1309 | 22 local secret_alphabet = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz' | 
| bsw@1494 | 23 local secret_purposes = { "oauth", "_other" } | 
| bsw/jbe@1309 | 24 for idx, purpose in ipairs(secret_purposes) do | 
| bsw/jbe@1309 | 25   secret_purposes[purpose] = idx | 
| bsw/jbe@1309 | 26 end | 
| bsw/jbe@1309 | 27 | 
| bsw/jbe@1309 | 28 local function random_string(length_multiplier) | 
| bsw/jbe@0 | 29   return multirand.string( | 
| bsw/jbe@1309 | 30     secret_length * (length_multiplier or 1), | 
| bsw/jbe@1309 | 31     secret_alphabet | 
| bsw/jbe@0 | 32   ) | 
| bsw/jbe@0 | 33 end | 
| bsw/jbe@0 | 34 | 
| bsw/jbe@0 | 35 function Session:new() | 
| bsw/jbe@0 | 36   local session = self.prototype.new(self)  -- super call | 
| bsw/jbe@0 | 37   session.ident             = random_string() | 
| bsw/jbe@1309 | 38   session.additional_secret = random_string(#secret_purposes) | 
| bsw/jbe@1309 | 39   session:save() | 
| bsw/jbe@0 | 40   return session | 
| bsw/jbe@0 | 41 end | 
| bsw/jbe@0 | 42 | 
| bsw@1511 | 43 function Session.object:set_cookie() | 
| bsw@1511 | 44   request.set_cookie{ | 
| bsw@1511 | 45     name = config.cookie_name, | 
| bsw@1511 | 46     value = self.ident, | 
| bsw@1511 | 47     samesite = "none" | 
| bsw@1511 | 48   } | 
| bsw@1511 | 49   request.set_cookie{ | 
| bsw@1521 | 50     name = config.cookie_name_samesite, | 
| bsw@1511 | 51     value = self.ident | 
| bsw@1511 | 52   } | 
| bsw@1511 | 53 end | 
| bsw@1511 | 54 | 
| bsw/jbe@1309 | 55 function Session.object:additional_secret_for(purpose) | 
| bsw/jbe@1309 | 56   local use_hash = false | 
| bsw/jbe@1309 | 57   local idx = secret_purposes[purpose] | 
| bsw/jbe@1309 | 58   if not idx then | 
| bsw/jbe@1309 | 59     idx = assert(secret_purposes._other, "No other secrets supported") | 
| bsw/jbe@1309 | 60     use_hash = true | 
| bsw/jbe@1309 | 61   end | 
| bsw/jbe@1309 | 62   local from_pos = secret_length * (idx-1) + 1 | 
| bsw/jbe@1309 | 63   local to_pos = from_pos + secret_length - 1 | 
| bsw/jbe@1309 | 64   local secret = string.sub(self.additional_secret, from_pos, to_pos) | 
| bsw/jbe@1309 | 65   if #secret ~=  secret_length then | 
| bsw/jbe@1309 | 66     self:destroy() | 
| bsw/jbe@1309 | 67     error("Session state invalid") | 
| bsw/jbe@1309 | 68   end | 
| bsw/jbe@1309 | 69   if use_hash then | 
| bsw/jbe@1309 | 70     local moonhash = require "moonhash"  -- TODO: auto loader for libraries in WebMCP? | 
| bsw/jbe@1309 | 71     secret = moonhash.shake256(secret .. "\0" .. purpose, secret_length, secret_alphabet) | 
| bsw/jbe@1309 | 72   end | 
| bsw/jbe@1309 | 73   return secret | 
| bsw/jbe@1309 | 74 end | 
| bsw/jbe@1309 | 75 | 
| bsw/jbe@0 | 76 function Session:by_ident(ident) | 
| bsw/jbe@0 | 77   local selector = self:new_selector() | 
| bsw/jbe@0 | 78   selector:add_where{ 'ident = ?', ident } | 
| bsw@1074 | 79   selector:add_field{ 'authority_uid' } | 
| bsw/jbe@0 | 80   selector:optional_object_mode() | 
| bsw/jbe@0 | 81   return selector:exec() | 
| bsw/jbe@0 | 82 end | 
| bsw@813 | 83 | 
| bsw@813 | 84 function Session.object:has_access(level) | 
| bsw@813 | 85   if level == "member" then | 
| bsw@813 | 86     if app.session.member_id then | 
| bsw@813 | 87       return true | 
| bsw@813 | 88     else | 
| bsw@813 | 89       return false | 
| bsw@813 | 90     end | 
| bsw@813 | 91 | 
| bsw@813 | 92   elseif level == "everything" then | 
| bsw@813 | 93     if self:has_access("member") or config.public_access == "everything" then | 
| bsw@813 | 94       return true | 
| bsw@813 | 95     else | 
| bsw@813 | 96       return false | 
| bsw@813 | 97     end | 
| bsw@813 | 98 | 
| bsw@813 | 99   elseif level == "all_pseudonymous" then | 
| bsw@813 | 100     if self:has_access("everything") or config.public_access == "all_pseudonymous" then | 
| bsw@813 | 101       return true | 
| bsw@813 | 102     else | 
| bsw@813 | 103       return false | 
| bsw@813 | 104     end | 
| bsw@813 | 105 | 
| bsw@813 | 106   elseif level == "authors_pseudonymous" then | 
| bsw@813 | 107     if self:has_access("all_pseudonymous") or config.public_access == "authors_pseudonymous" then | 
| bsw@813 | 108       return true | 
| bsw@813 | 109     else | 
| bsw@813 | 110       return false | 
| bsw@813 | 111     end | 
| bsw@813 | 112 | 
| bsw@813 | 113   elseif level == "anonymous" then | 
| bsw@813 | 114     if self:has_access("authors_pseudonymous") or config.public_access == "anonymous" then | 
| bsw@813 | 115       return true | 
| bsw@813 | 116     else | 
| bsw@813 | 117       return false | 
| bsw@813 | 118     end | 
| bsw@813 | 119 | 
| bsw@813 | 120   end | 
| bsw@813 | 121 | 
| bsw@813 | 122   error("invalid access level") | 
| bsw@813 | 123 end |