bsw/jbe@1309: Token = mondelefant.new_class() bsw/jbe@1309: Token.table = 'token' bsw/jbe@1309: bsw/jbe@1309: Token:add_reference{ bsw/jbe@1309: mode = '1m', bsw/jbe@1309: to = "TokenScope", bsw/jbe@1309: this_key = 'id', bsw/jbe@1309: that_key = 'token_id', bsw/jbe@1309: ref = 'token_scopes', bsw/jbe@1309: back_ref = 'token', bsw/jbe@1309: default_order = 'token_scope.index' bsw/jbe@1309: } bsw/jbe@1309: bsw/jbe@1309: Token:add_reference{ bsw/jbe@1309: mode = 'm1', bsw/jbe@1309: to = "Member", bsw/jbe@1309: this_key = 'member_id', bsw/jbe@1309: that_key = 'id', bsw/jbe@1309: ref = 'member', bsw/jbe@1309: } bsw/jbe@1309: bsw/jbe@1309: Token:add_reference{ bsw/jbe@1309: mode = 'm1', bsw/jbe@1309: to = "Session", bsw/jbe@1309: this_key = 'session_id', bsw/jbe@1309: that_key = 'id', bsw/jbe@1309: ref = 'session', bsw/jbe@1309: } bsw/jbe@1309: bsw/jbe@1309: Token:add_reference{ bsw/jbe@1309: mode = 'm1', bsw/jbe@1309: to = "SystemApplication", bsw/jbe@1309: this_key = 'system_application_id', bsw/jbe@1309: that_key = 'id', bsw/jbe@1309: ref = 'system_application', bsw/jbe@1309: } bsw/jbe@1309: bsw/jbe@1309: function Token:new() bsw/jbe@1309: local token = self.prototype.new(self) bsw/jbe@1309: token.token = multirand.string(16, "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789") bsw/jbe@1309: return token bsw/jbe@1309: end bsw/jbe@1309: bsw/jbe@1309: function Token:create_authorization(member_id, system_application_id, domain, session_id, redirect_uri, redirect_uri_explicit, scopes, state) bsw/jbe@1309: bsw/jbe@1309: local detached = false bsw/jbe@1309: for i = 0, #scopes do bsw/jbe@1309: if scopes[i] then bsw/jbe@1309: for s in string.gmatch(scopes[i], "[^ ]+") do bsw/jbe@1309: if s == "detached" then bsw/jbe@1309: detached = true bsw/jbe@1309: end bsw/jbe@1309: end bsw/jbe@1309: end bsw/jbe@1309: end bsw/jbe@1309: bsw/jbe@1309: local requested_scopes = {} bsw/jbe@1309: bsw/jbe@1309: for i = 0, #scopes do bsw/jbe@1309: if scopes[i] then bsw/jbe@1309: for scope in string.gmatch(scopes[i], "[^ ]+") do bsw/jbe@1309: requested_scopes[scope] = true bsw/jbe@1309: end bsw/jbe@1309: end bsw/jbe@1309: end bsw/jbe@1309: bsw/jbe@1309: local requested_scopes_list = {} bsw/jbe@1309: bsw/jbe@1309: for k, v in pairs(requested_scopes) do bsw/jbe@1309: requested_scopes_list[#requested_scopes_list+1] = k bsw/jbe@1309: end bsw/jbe@1309: bsw/jbe@1309: local requested_scopes_string = table.concat(requested_scopes_list, " ") bsw/jbe@1309: bsw/jbe@1309: local expiry = db:query({"SELECT now() + (? || 'sec')::interval AS expiry", config.oauth2.authorization_code_lifetime }, "object").expiry bsw/jbe@1309: bsw/jbe@1309: local token = Token:new() bsw/jbe@1309: token.token_type = "authorization" bsw/jbe@1309: token.member_id = member_id bsw/jbe@1309: token.system_application_id = system_application_id bsw/jbe@1309: token.domain = domain bsw/jbe@1309: if not detached then bsw/jbe@1309: token.session_id = session_id bsw/jbe@1309: end bsw/jbe@1309: token.redirect_uri = redirect_uri bsw/jbe@1309: token.redirect_uri_explicit = redirect_uri_explicit bsw/jbe@1309: token.expiry = expiry bsw/jbe@1309: token.scope = requested_scopes_string bsw/jbe@1309: bsw/jbe@1309: token:save() bsw/jbe@1309: bsw/jbe@1309: for i = 0, #scopes do bsw/jbe@1309: if scopes[i] then bsw/jbe@1309: local token_scope = TokenScope:new() bsw/jbe@1309: token_scope.token_id = token.id bsw/jbe@1309: token_scope.index = i bsw/jbe@1309: token_scope.scope = scopes[i] bsw/jbe@1309: token_scope:save() bsw/jbe@1309: end bsw/jbe@1309: end bsw/jbe@1309: bsw/jbe@1309: bsw/jbe@1309: return token, target_uri bsw/jbe@1309: end bsw/jbe@1309: bsw/jbe@1309: function Token:by_token_type_and_token(token_type, token) bsw/jbe@1309: local selector = Token:new_selector() bsw/jbe@1309: selector:add_where{ "token_type = ?", token_type } bsw/jbe@1309: selector:add_where{ "token = ?", token } bsw/jbe@1309: selector:add_where{ "expiry > now()" } bsw/jbe@1309: selector:optional_object_mode() bsw/jbe@1309: if token_type == "authorization_code" then bsw/jbe@1309: selector:for_update() bsw/jbe@1309: end bsw/jbe@1309: if token_type == "access_token" then bsw/jbe@1309: selector:add_field("FLOOR(EXTRACT(EPOCH FROM expiry - now()))", "expiry_in") bsw/jbe@1309: end bsw/jbe@1309: return selector:exec() bsw/jbe@1309: end bsw/jbe@1309: bsw/jbe@1309: function Token:refresh_token_by_token_selector(token) bsw/jbe@1309: local selector = Token:new_selector() bsw/jbe@1309: selector:add_where{ "token_type = ?", "refresh" } bsw/jbe@1309: selector:add_where{ "member_id = ?", token.member_id } bsw/jbe@1309: if token.system_application_id then bsw/jbe@1309: selector:add_where{ "system_application_id = ?", token.system_application_id } bsw/jbe@1309: else bsw/jbe@1309: selector:add_where{ "domain = ?", token.domain } bsw/jbe@1309: end bsw/jbe@1309: return selector bsw/jbe@1309: end bsw/jbe@1309: bsw/jbe@1309: function Token:fresh_refresh_token_by_token(token) bsw/jbe@1309: local selector = Token:refresh_token_by_token_selector(token) bsw/jbe@1309: selector:add_where{ "created + ('?' || ' sec')::interval > now()", config.oauth2.refresh_pause } bsw/jbe@1309: selector:add_where{ "regexp_split_to_array(scope, E'\\\\s+') <@ regexp_split_to_array(?, E'\\\\s+')", token.scope } bsw/jbe@1309: selector:add_where{ "regexp_split_to_array(scope, E'\\\\s+') @> regexp_split_to_array(?, E'\\\\s+')", token.scope } bsw/jbe@1309: return selector:exec() bsw/jbe@1309: end bsw/jbe@1309: bsw/jbe@1309: function Token:old_refresh_token_by_token(token, scopes) bsw/jbe@1309: local selector = Token:refresh_token_by_token_selector(token) bsw/jbe@1309: selector:add_where{ "id < ?", token.id } bsw/jbe@1309: selector:add_where{ "created + ('?' || ' sec')::interval <= now()", config.oauth2.refresh_grace_period } bsw/jbe@1309: selector:add_where{ "regexp_split_to_array(scope, E'\\\\s+') && regexp_split_to_array(?, E'\\\\s+')", scopes } bsw/jbe@1309: return selector:exec() bsw/jbe@1309: end