| 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
 |