| 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/jbe@1309 | 23 local secret_purposes = { "oauth", "csrf", "_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/jbe@1309 | 43 function Session.object:additional_secret_for(purpose) | 
| bsw/jbe@1309 | 44   local use_hash = false | 
| bsw/jbe@1309 | 45   local idx = secret_purposes[purpose] | 
| bsw/jbe@1309 | 46   if not idx then | 
| bsw/jbe@1309 | 47     idx = assert(secret_purposes._other, "No other secrets supported") | 
| bsw/jbe@1309 | 48     use_hash = true | 
| bsw/jbe@1309 | 49   end | 
| bsw/jbe@1309 | 50   local from_pos = secret_length * (idx-1) + 1 | 
| bsw/jbe@1309 | 51   local to_pos = from_pos + secret_length - 1 | 
| bsw/jbe@1309 | 52   local secret = string.sub(self.additional_secret, from_pos, to_pos) | 
| bsw/jbe@1309 | 53   if #secret ~=  secret_length then | 
| bsw/jbe@1309 | 54     self:destroy() | 
| bsw/jbe@1309 | 55     error("Session state invalid") | 
| bsw/jbe@1309 | 56   end | 
| bsw/jbe@1309 | 57   if use_hash then | 
| bsw/jbe@1309 | 58     local moonhash = require "moonhash"  -- TODO: auto loader for libraries in WebMCP? | 
| bsw/jbe@1309 | 59     secret = moonhash.shake256(secret .. "\0" .. purpose, secret_length, secret_alphabet) | 
| bsw/jbe@1309 | 60   end | 
| bsw/jbe@1309 | 61   return secret | 
| bsw/jbe@1309 | 62 end | 
| bsw/jbe@1309 | 63 | 
| bsw/jbe@0 | 64 function Session:by_ident(ident) | 
| bsw/jbe@0 | 65   local selector = self:new_selector() | 
| bsw/jbe@0 | 66   selector:add_where{ 'ident = ?', ident } | 
| bsw@1074 | 67   selector:add_field{ 'authority_uid' } | 
| bsw/jbe@0 | 68   selector:optional_object_mode() | 
| bsw/jbe@0 | 69   return selector:exec() | 
| bsw/jbe@0 | 70 end | 
| bsw@813 | 71 | 
| bsw@813 | 72 function Session.object:has_access(level) | 
| bsw@813 | 73   if level == "member" then | 
| bsw@813 | 74     if app.session.member_id then | 
| bsw@813 | 75       return true | 
| bsw@813 | 76     else | 
| bsw@813 | 77       return false | 
| bsw@813 | 78     end | 
| bsw@813 | 79 | 
| bsw@813 | 80   elseif level == "everything" then | 
| bsw@813 | 81     if self:has_access("member") or config.public_access == "everything" then | 
| bsw@813 | 82       return true | 
| bsw@813 | 83     else | 
| bsw@813 | 84       return false | 
| bsw@813 | 85     end | 
| bsw@813 | 86 | 
| bsw@813 | 87   elseif level == "all_pseudonymous" then | 
| bsw@813 | 88     if self:has_access("everything") or config.public_access == "all_pseudonymous" then | 
| bsw@813 | 89       return true | 
| bsw@813 | 90     else | 
| bsw@813 | 91       return false | 
| bsw@813 | 92     end | 
| bsw@813 | 93 | 
| bsw@813 | 94   elseif level == "authors_pseudonymous" then | 
| bsw@813 | 95     if self:has_access("all_pseudonymous") or config.public_access == "authors_pseudonymous" then | 
| bsw@813 | 96       return true | 
| bsw@813 | 97     else | 
| bsw@813 | 98       return false | 
| bsw@813 | 99     end | 
| bsw@813 | 100 | 
| bsw@813 | 101   elseif level == "anonymous" then | 
| bsw@813 | 102     if self:has_access("authors_pseudonymous") or config.public_access == "anonymous" then | 
| bsw@813 | 103       return true | 
| bsw@813 | 104     else | 
| bsw@813 | 105       return false | 
| bsw@813 | 106     end | 
| bsw@813 | 107 | 
| bsw@813 | 108   end | 
| bsw@813 | 109 | 
| bsw@813 | 110   error("invalid access level") | 
| bsw@813 | 111 end |