def __init__(self, configuration=None, baseurl=""): self.conf_info = configuration or {} self.resource_set = MemResourceSetDB() self.rpt = {} self.baseurl = baseurl if not self.baseurl.endswith("/"): self.baseurl += "/" self.session = Session() self.permit = Permission() self.permission_requests = PermissionRequests() self.map_rsid_id = {} self.map_id_rsid = {} self.map_user_id = {} self.eid2rpt = {} self.get_requester = get_requester
class UmaAS(object): endp = [ AuthorizationEndpoint, DynamicClientEndpoint, IntrospectionEndpoint, PermissionRegistrationEndpoint, RequestingPartyClaimsEndpoint, ResourceSetRegistrationEndpoint, RPTEndpoint, TokenEndpoint, ClientInfoEndpoint, ] def __init__(self, configuration=None, baseurl=""): self.conf_info = configuration or {} self.resource_set = MemResourceSetDB() self.rpt = {} self.baseurl = baseurl if not self.baseurl.endswith("/"): self.baseurl += "/" self.session = Session() self.permit = Permission() self.permission_requests = PermissionRequests() self.map_rsid_id = {} self.map_id_rsid = {} self.map_user_id = {} self.eid2rpt = {} self.get_requester = get_requester def endpoints(self): for endp in self.endp: yield endp(None).name def services(self): for endp in self.endp: yield endp.etype # def rpt_endpoint_(self, requestor, client_id, **kwargs): # """ # The endpoint URI at which the client asks the authorization server for # a RPT. # """ # #res = self.client_authentication(authn) # #if isinstance(res, Response): # # return res # # # create RPT, just overwrites whatever was there before # rpt = rndstr(32) # self.rpt[rpt] = {"requestor": requestor, "client_id": client_id} # self.session.set(rpt) # # msg = RPTResponse(rpt=rpt) # return Response(msg.to_json(), content="application/json") def resource_set_registration_endpoint_(self, entity, path, method, client_id, body="", if_match="", **kwargs): """ The endpoint at which the resource server handles resource sets descriptions. :param entity: The entity that controls the resource set :param path: :param method: HTTP method :param body: The resource set registration message :paran client_id: Which client I'm talking to :param if_match: The HTTP If-Match header if any :param kwargs: possible other arguments :returns: A Response instance """ # path should be /resource_set/{rsid} or /resource_set # Path may or may not start with '/' if path.startswith("/"): assert path[1:].startswith(RSR_PATH) rsid = path[PLEN + 1 :] else: assert path.startswith(RSR_PATH) rsid = path[PLEN:] if rsid.startswith("/"): rsid = rsid[1:] _user = safe_name(entity, client_id) logger.debug("handling resource set belonging to '%s'" % _user) # self.resource_set.set_collection(_user) if method == "POST": # create args = {"oid": _user, "data": body} func = self.resource_set.create elif method == "PUT": # update args = { "oid": _user, "data": body, "rsid": rsid, # "if_match": if_match } func = self.resource_set.update elif method == "GET": args = {"oid": _user} if not rsid: # List func = self.resource_set.list else: # Read func = self.resource_set.read args["rsid"] = rsid elif method == "DELETE": args = {"rsid": rsid, "oid": _user} func = self.resource_set.delete else: return BadRequest("Message error") logger.debug("operation: %s" % func) logger.debug("operation args: %s" % (args,)) try: body = func(**args) except MessageException as err: _err = ErrorResponse(error="invalid_request", error_description=str(err)) response = BadRequest(_err.to_json(), content="application/json") except UnknownObject: _err = ErrorResponse(error="not_found") response = NotFound(_err.to_json(), content="application/json") else: response = None if isinstance(body, ErrorResponse): pass else: if func == self.resource_set.delete: # As a side effect all permissions assigned that references # this resource set should be deleted self.permit.delete_permit_by_resource_id(entity, rsid) response = NoContent() elif func == self.resource_set.create: _etag = self.resource_set.etag[body["_id"]] response = Created( body.to_json(), content="application/json", headers=[("ETag", _etag), ("Location", "/{}/{}".format(RSR_PATH, body["_id"]))], ) elif func == self.resource_set.update: _etag = self.resource_set.etag[body["_id"]] response = NoContent(content="application/json", headers=[("ETag", _etag)]) elif func == self.resource_set.list: response = Response(json.dumps(body)) if not response: response = Response(body.to_json(), content="application/json") return response def _collapse(self, items): referenced = {} ibrsid = {} for item in items: try: for rsid in item["subsets"]: if rsid not in referenced: referenced[rsid] = 1 else: referenced[rsid] += 1 except KeyError: pass _rsid = self.map_id_rsid[item["_id"]] if _rsid not in referenced: referenced[_rsid] = 0 ibrsid[_rsid] = item res = [] for key, val in list(referenced.items()): if val == 0: res.append(ibrsid[key]) return res def resource_sets_by_user(self, entity, client_id, collapse=False): """ :param entity: The entity for which resource set descriptions has been registered. :return: A list of ResourceSetDescriptions """ res = [] _user = safe_name(entity, client_id) try: rss = self.resource_set.list(_user) except KeyError: return [] for _id in rss: try: res.append(self.resource_set.read(_user, _id)) except Exception: raise if collapse: res = self._collapse(res) return res # def resource_set_tree_by_rsid(self, owner, rsid): # rs = self.resource_set.read(owner, rsid) # _name = rs["name"].split("/")[-1] # try: # _rsids = rs["subsets"] # except KeyError: # return rsid, _name # else: # res = {} # for _rsid in _rsids: # _rs = self.resource_set_tree_by_rsid(owner, _rsid) # try: # res.update(_rs) # except ValueError: # try: # res.append(_rs) # except AttributeError: # res = [_rs] # # return {(rsid, _name): res} # # def resource_set_name(self, rsid): # rs = self.resource_set.read(self.map_rsid_id[rsid]) # return rs["name"] def permits_by_user(self, owner): """ :param owner: The owner of the resource :return: A dictionary with requestors as keys and permissions as values """ return self.permit.get_permits(owner) def authz_session_info(self, token): pass def introspection_endpoint_(self, entity, **kwargs): """ The endpoint URI at which the resource server introspects an RPT presented to it by a client. """ request = kwargs["request"] logger.debug("requestor: %s, request: %s" % (entity, request)) ir = IntrospectionRequest().from_json(request) owner = safe_name(entity, kwargs["client_id"]) try: try: # requestor = self.rpt[ir["token"]]["requestor"] perms = self.permit.get_accepted(owner, ir["token"]) except KeyError: response = BadRequest() else: if perms: irep = IntrospectionResponse(active=True, exp=perms[0]["exp"], permissions=perms) logger.debug("response: %s" % irep.to_json()) response = Response(irep.to_json(), content="application/json") else: logger.info("No permissions bound to this RPT") response = BadRequest() except ToOld: logger.info("RPT expired") irep = IntrospectionResponse(valid=False) response = Response(irep.to_json(), content="application/json") except KeyError: response = BadRequest() return response def permission_registration_endpoint_(self, entity, **kwargs): """ The endpoint URI at which the resource server registers a client-requested permission with the authorization server. This is a proposed permission waiting for the user to accept it. """ request = kwargs["request"] _ticket = rndstr(24) logging.debug("Registering permission request: %s" % request) resp = PermissionRegistrationResponse(ticket=_ticket) self.permission_requests.add_request(_ticket, request) return Created(resp.to_json(), content="application/json") def requesting_party_claims_endpoint(self, request="", **kwargs): """ The endpoint at which the resource server gathers the consent of the end-user resource owner or the client gathers the consent of the end-user requesting party, if the "authorization_code" grant type is used. """ pass def dynamic_client_endpoint(self, request="", **kwargs): pass def token_endpoint(self, request="", **kwargs): pass def authorization_endpoint(self, request="", **kwargs): pass @staticmethod def token_scope_check(areq, info): """ verifies that the scope that is demanded for the access token is one that I'm comfortable with. :param areq: AccessTokenRequest :param info: What's in the session db :return: None if OK otherwise and error response. """ try: assert areq["scope"] in info["scope"] except AssertionError: logger.error("Not the same scope as for the AuthzRequest") err = TokenErrorResponse(error="invalid_scope") return Response(err.to_json(), content="application/json") try: assert areq["scope"] in list(UMA_SCOPE.values()) except AssertionError: logger.error("Asked for scope which I don't deal with") err = TokenErrorResponse(error="invalid_scope") return Response(err.to_json(), content="application/json") return None def create_uma_providerinfo(self, pcr_class=ProviderConfiguration): kwargs = dict([(k, v) for k, v in list(self.conf_info.items()) if k in pcr_class.c_param]) _response = pcr_class(**kwargs) for endp in UmaAS.endp: _response.update(endpoint_ava(endp, self.baseurl)) logger.debug("provider_info_response: %s" % (_response.to_dict(),)) return _response # noinspection PyUnusedLocal def providerinfo_endpoint_(self, handle="", **kwargs): logger.debug("@providerinfo_endpoint") try: _response = self.create_uma_providerinfo() headers = [("Cache-Control", "no-store"), ("x-ffo", "bar")] # if handle: # (key, timestamp) = handle # if key.startswith(STR) and key.endswith(STR): # cookie = self.cookie_func(key, self.cookie_name, "pinfo", # self.sso_ttl) # headers.append(cookie) resp = Response(_response.to_json(), content="application/json", headers=headers) except Exception as err: message = traceback.format_exception(*sys.exc_info()) logger.error(message) resp = Response(message, content="html/text") return resp def get_subsets(self, owner, requestor, scopes): res = {} try: permits = self.permit.get_permit_by_requestor(owner, requestor) except KeyError: return res for permit, (_scopes, time_stamp) in list(permits.items()): _scs = [] for scope in scopes: try: assert scope in _scopes except AssertionError: pass else: _scs.append(scope) if _scs: res[permit] = _scs return res def register_permission(self, owner, rpt, rsid, scopes): now = utc_time_sans_frac() perm = AuthzDescription(resource_set_id=rsid, scopes=scopes, exp=now + self.session.lifetime, iat=now) self.permit.set_accepted(owner, rpt, perm) def rpt_endpoint_(self, entity, client_id, **kwargs): """ Registers an Authorization Description :param entity: Who's on the other side :param client_id: The UMA client :return: A Response instance """ adr = AuthorizationDataRequest().from_json(kwargs["request"]) # Get request permission that the resource server has registered try: prr_list = self.permission_requests.get_request(adr["ticket"]) except KeyError: errmsg = ErrorResponse(error="invalid_ticket") return BadRequest(errmsg.to_json(), content="application/json") self.permission_requests.del_request(adr["ticket"]) try: _rpt = adr["rpt"] except KeyError: _rpt = rndstr(32) for prr in prr_list: _rsid = prr["resource_set_id"] # Verify that the scopes are defined for the resource set owner = self.resource_set.rsid2oid[_rsid] rsd = self.resource_set.read(owner, _rsid) for scope in prr["scopes"]: try: assert scope in rsd["scopes"] except AssertionError: errmsg = ErrorResponse(error="not_authorized", error_description="Undefined scopes") return BadRequest(errmsg.to_json(), content="application/json") # Is there any permissions registered by the owner, if so verify # that it allows what is requested. Return what is allowed ! try: allow_scopes, timestamp = self.permit.get_permit(owner, entity, _rsid) except KeyError: # errmsg = ErrorResponse(error="not_authorized", error_description="No permission given") return BadRequest(errmsg.to_json(), content="application/json") else: _scopes = [] for scope in prr["scopes"]: try: assert scope in allow_scopes except AssertionError: pass else: _scopes.append(scope) # bind _requester to specific RPT for this user try: self.eid2rpt[owner][entity] = _rpt except KeyError: self.eid2rpt[owner] = {entity: _rpt} self.register_permission(owner, _rpt, _rsid, _scopes) rsp = AuthorizationDataResponse(rpt=_rpt) return Response(rsp.to_json()) def name2id(self, owner, requestor, rsid): _user = safe_name(owner, requestor) obj = self.resource_set.read(_user, rsid) return obj["_id"] def remove_permission(self, owner, requestor, resource_name): """ :param owner: The resource owner :param requestor: The SP entity ID :param resource_name: The name of the resource set """ _id = self.name2id(owner, requestor, resource_name) try: self.permit.delete_permit(owner, requestor, _id) except KeyError: pass try: _user = "******" % (owner, requestor) rm_rpt = self.permit.rm_accepted(_user, _id) except KeyError: pass else: for _rpt in rm_rpt: # immediate expiration self.session.update(_rpt, expires_at=0) def store_permission(self, user, requestor, rsids): """ :param user: The resource owner :param requestor: The requestor ID :param rsids: dictionary with Resource set IDs as keys and scopes as values """ logger.info("store: (%s, %s, %s)" % (user, requestor, rsids)) present = self.permit.get_rsid_permits(user, requestor) _new = [k for k in list(rsids.keys()) if k not in present] _user = safe_name(user, requestor) for rsid in _new: scopes = rsids[rsid] if scopes is None: rs = self.resource_set.read(_user, rsid) scopes = rs["scopes"] self.permit.set_permit(user, requestor, rsid, scopes) _rem = [k for k in present if k not in rsids] for rsid in _rem: self.permit.delete_permit(user, requestor, rsid) def read_permission(self, user, requestor, rsid): return self.permit.get_permit(user, requestor, rsid) def rec_rm_permission(self, user, requestor, rsid): """ If the resource set is a complex set, remove all subset permissions :param user: The owner of the resource :param requestor: Who the permission is applying to :param rsid: The resource set name """ _user = safe_name(user, requestor) rs = self.resource_set.read(_user, rsid) if "subsets" in rs: for ss in rs["subsets"]: self.rec_rm_permission(user, requestor, ss) try: self.permit.delete_permit(user, requestor, rsid) except KeyError: pass def rm_permission(self, user, requestor, rsid): """ If the resource set is a complex set, remove all subset permissions :param user: The owner of the resource :param requestor: Who the permission is applying to :param rsid: The resource set name """ logger.info("remove: (%s, %s, %s)" % (user, requestor, rsid)) self.rec_rm_permission(user, requestor, rsid) return True def rsid_permits(self, user, requestor): return self.permit.get_rsid_permits(user, requestor)
class UmaAS(object): endp = [ AuthorizationEndpoint, DynamicClientEndpoint, IntrospectionEndpoint, PermissionRegistrationEndpoint, RequestingPartyClaimsEndpoint, ResourceSetRegistrationEndpoint, RPTEndpoint, TokenEndpoint, ClientInfoEndpoint ] def __init__(self, configuration=None, baseurl=""): self.conf_info = configuration or {} self.resource_set = MemResourceSetDB() self.rpt = {} self.baseurl = baseurl if not self.baseurl.endswith("/"): self.baseurl += "/" self.session = Session() self.permit = Permission() self.permission_requests = PermissionRequests() self.map_rsid_id = {} self.map_id_rsid = {} self.map_user_id = {} self.eid2rpt = {} self.get_requester = get_requester def endpoints(self): for endp in self.endp: yield endp(None).name def services(self): for endp in self.endp: yield endp.etype # def rpt_endpoint_(self, requestor, client_id, **kwargs): # """ # The endpoint URI at which the client asks the authorization server for # a RPT. # """ # #res = self.client_authentication(authn) # #if isinstance(res, Response): # # return res # # # create RPT, just overwrites whatever was there before # rpt = rndstr(32) # self.rpt[rpt] = {"requestor": requestor, "client_id": client_id} # self.session.set(rpt) # # msg = RPTResponse(rpt=rpt) # return Response(msg.to_json(), content="application/json") def resource_set_registration_endpoint_(self, entity, path, method, client_id, body="", if_match="", **kwargs): """ The endpoint at which the resource server handles resource sets descriptions. :param entity: The entity that controls the resource set :param path: :param method: HTTP method :param body: The resource set registration message :paran client_id: Which client I'm talking to :param if_match: The HTTP If-Match header if any :param kwargs: possible other arguments :returns: A Response instance """ # path should be /resource_set/{rsid} or /resource_set # Path may or may not start with '/' if path.startswith("/"): assert path[1:].startswith(RSR_PATH) rsid = path[PLEN + 1:] else: assert path.startswith(RSR_PATH) rsid = path[PLEN:] if rsid.startswith("/"): rsid = rsid[1:] _user = safe_name(entity, client_id) logger.debug("handling resource set belonging to '%s'" % _user) # self.resource_set.set_collection(_user) if method == "POST": # create args = {"oid": _user, "data": body} func = self.resource_set.create elif method == "PUT": # update args = { "oid": _user, "data": body, "rsid": rsid, # "if_match": if_match } func = self.resource_set.update elif method == "GET": args = {"oid": _user} if not rsid: # List func = self.resource_set.list else: # Read func = self.resource_set.read args["rsid"] = rsid elif method == "DELETE": args = {"rsid": rsid, "oid": _user} func = self.resource_set.delete else: return BadRequest("Message error") logger.debug("operation: %s" % func) logger.debug("operation args: %s" % (args, )) try: body = func(**args) except MessageException as err: _err = ErrorResponse(error="invalid_request", error_description=str(err)) response = BadRequest(_err.to_json(), content="application/json") except UnknownObject: _err = ErrorResponse(error="not_found") response = NotFound(_err.to_json(), content="application/json") else: response = None if isinstance(body, ErrorResponse): pass else: if func == self.resource_set.delete: # As a side effect all permissions assigned that references # this resource set should be deleted self.permit.delete_permit_by_resource_id(entity, rsid) response = NoContent() elif func == self.resource_set.create: _etag = self.resource_set.etag[body["_id"]] response = Created(body.to_json(), content="application/json", headers=[("ETag", _etag), ("Location", "/{}/{}".format( RSR_PATH, body["_id"]))]) elif func == self.resource_set.update: _etag = self.resource_set.etag[body["_id"]] response = NoContent(content="application/json", headers=[("ETag", _etag)]) elif func == self.resource_set.list: response = Response(json.dumps(body)) if not response: response = Response(body.to_json(), content="application/json") return response def _collapse(self, items): referenced = {} ibrsid = {} for item in items: try: for rsid in item["subsets"]: if rsid not in referenced: referenced[rsid] = 1 else: referenced[rsid] += 1 except KeyError: pass _rsid = self.map_id_rsid[item["_id"]] if _rsid not in referenced: referenced[_rsid] = 0 ibrsid[_rsid] = item res = [] for key, val in list(referenced.items()): if val == 0: res.append(ibrsid[key]) return res def resource_sets_by_user(self, entity, client_id, collapse=False): """ :param entity: The entity for which resource set descriptions has been registered. :return: A list of ResourceSetDescriptions """ res = [] _user = safe_name(entity, client_id) try: rss = self.resource_set.list(_user) except KeyError: return [] for _id in rss: try: res.append(self.resource_set.read(_user, _id)) except Exception: raise if collapse: res = self._collapse(res) return res # def resource_set_tree_by_rsid(self, owner, rsid): # rs = self.resource_set.read(owner, rsid) # _name = rs["name"].split("/")[-1] # try: # _rsids = rs["subsets"] # except KeyError: # return rsid, _name # else: # res = {} # for _rsid in _rsids: # _rs = self.resource_set_tree_by_rsid(owner, _rsid) # try: # res.update(_rs) # except ValueError: # try: # res.append(_rs) # except AttributeError: # res = [_rs] # # return {(rsid, _name): res} # # def resource_set_name(self, rsid): # rs = self.resource_set.read(self.map_rsid_id[rsid]) # return rs["name"] def permits_by_user(self, owner): """ :param owner: The owner of the resource :return: A dictionary with requestors as keys and permissions as values """ return self.permit.get_permits(owner) def authz_session_info(self, token): pass def introspection_endpoint_(self, entity, **kwargs): """ The endpoint URI at which the resource server introspects an RPT presented to it by a client. """ request = kwargs["request"] logger.debug("requestor: %s, request: %s" % (entity, request)) ir = IntrospectionRequest().from_json(request) owner = safe_name(entity, kwargs["client_id"]) try: try: # requestor = self.rpt[ir["token"]]["requestor"] perms = self.permit.get_accepted(owner, ir["token"]) except KeyError: response = BadRequest() else: if perms: irep = IntrospectionResponse(active=True, exp=perms[0]["exp"], permissions=perms) logger.debug("response: %s" % irep.to_json()) response = Response(irep.to_json(), content="application/json") else: logger.info("No permissions bound to this RPT") response = BadRequest() except ToOld: logger.info("RPT expired") irep = IntrospectionResponse(valid=False) response = Response(irep.to_json(), content="application/json") except KeyError: response = BadRequest() return response def permission_registration_endpoint_(self, entity, **kwargs): """ The endpoint URI at which the resource server registers a client-requested permission with the authorization server. This is a proposed permission waiting for the user to accept it. """ request = kwargs["request"] _ticket = rndstr(24) logging.debug("Registering permission request: %s" % request) resp = PermissionRegistrationResponse(ticket=_ticket) self.permission_requests.add_request(_ticket, request) return Created(resp.to_json(), content="application/json") def requesting_party_claims_endpoint(self, request="", **kwargs): """ The endpoint at which the resource server gathers the consent of the end-user resource owner or the client gathers the consent of the end-user requesting party, if the "authorization_code" grant type is used. """ pass def dynamic_client_endpoint(self, request="", **kwargs): pass def token_endpoint(self, request="", **kwargs): pass def authorization_endpoint(self, request="", **kwargs): pass @staticmethod def token_scope_check(areq, info): """ verifies that the scope that is demanded for the access token is one that I'm comfortable with. :param areq: AccessTokenRequest :param info: What's in the session db :return: None if OK otherwise and error response. """ try: assert areq["scope"] in info["scope"] except AssertionError: logger.error("Not the same scope as for the AuthzRequest") err = TokenErrorResponse(error="invalid_scope") return Response(err.to_json(), content="application/json") try: assert areq["scope"] in list(UMA_SCOPE.values()) except AssertionError: logger.error("Asked for scope which I don't deal with") err = TokenErrorResponse(error="invalid_scope") return Response(err.to_json(), content="application/json") return None def create_uma_providerinfo(self, pcr_class=ProviderConfiguration): kwargs = dict([(k, v) for k, v in list(self.conf_info.items()) if k in pcr_class.c_param]) _response = pcr_class(**kwargs) for endp in UmaAS.endp: _response.update(endpoint_ava(endp, self.baseurl)) logger.debug("provider_info_response: %s" % (_response.to_dict(), )) return _response # noinspection PyUnusedLocal def providerinfo_endpoint_(self, handle="", **kwargs): logger.debug("@providerinfo_endpoint") try: _response = self.create_uma_providerinfo() headers = [("Cache-Control", "no-store"), ("x-ffo", "bar")] # if handle: # (key, timestamp) = handle # if key.startswith(STR) and key.endswith(STR): # cookie = self.cookie_func(key, self.cookie_name, "pinfo", # self.sso_ttl) # headers.append(cookie) resp = Response(_response.to_json(), content="application/json", headers=headers) except Exception as err: message = traceback.format_exception(*sys.exc_info()) logger.error(message) resp = Response(message, content="html/text") return resp def get_subsets(self, owner, requestor, scopes): res = {} try: permits = self.permit.get_permit_by_requestor(owner, requestor) except KeyError: return res for permit, (_scopes, time_stamp) in list(permits.items()): _scs = [] for scope in scopes: try: assert scope in _scopes except AssertionError: pass else: _scs.append(scope) if _scs: res[permit] = _scs return res def register_permission(self, owner, rpt, rsid, scopes): now = utc_time_sans_frac() perm = AuthzDescription(resource_set_id=rsid, scopes=scopes, exp=now + self.session.lifetime, iat=now) self.permit.set_accepted(owner, rpt, perm) def rpt_endpoint_(self, entity, client_id, **kwargs): """ Registers an Authorization Description :param entity: Who's on the other side :param client_id: The UMA client :return: A Response instance """ adr = AuthorizationDataRequest().from_json(kwargs["request"]) # Get request permission that the resource server has registered try: prr_list = self.permission_requests.get_request(adr["ticket"]) except KeyError: errmsg = ErrorResponse(error="invalid_ticket") return BadRequest(errmsg.to_json(), content="application/json") self.permission_requests.del_request(adr["ticket"]) try: _rpt = adr["rpt"] except KeyError: _rpt = rndstr(32) for prr in prr_list: _rsid = prr["resource_set_id"] # Verify that the scopes are defined for the resource set owner = self.resource_set.rsid2oid[_rsid] rsd = self.resource_set.read(owner, _rsid) for scope in prr["scopes"]: try: assert scope in rsd["scopes"] except AssertionError: errmsg = ErrorResponse( error="not_authorized", error_description="Undefined scopes") return BadRequest(errmsg.to_json(), content="application/json") # Is there any permissions registered by the owner, if so verify # that it allows what is requested. Return what is allowed ! try: allow_scopes, timestamp = self.permit.get_permit( owner, entity, _rsid) except KeyError: # errmsg = ErrorResponse(error="not_authorized", error_description="No permission given") return BadRequest(errmsg.to_json(), content="application/json") else: _scopes = [] for scope in prr["scopes"]: try: assert scope in allow_scopes except AssertionError: pass else: _scopes.append(scope) # bind _requester to specific RPT for this user try: self.eid2rpt[owner][entity] = _rpt except KeyError: self.eid2rpt[owner] = {entity: _rpt} self.register_permission(owner, _rpt, _rsid, _scopes) rsp = AuthorizationDataResponse(rpt=_rpt) return Response(rsp.to_json()) def name2id(self, owner, requestor, rsid): _user = safe_name(owner, requestor) obj = self.resource_set.read(_user, rsid) return obj["_id"] def remove_permission(self, owner, requestor, resource_name): """ :param owner: The resource owner :param requestor: The SP entity ID :param resource_name: The name of the resource set """ _id = self.name2id(owner, requestor, resource_name) try: self.permit.delete_permit(owner, requestor, _id) except KeyError: pass try: _user = "******" % (owner, requestor) rm_rpt = self.permit.rm_accepted(_user, _id) except KeyError: pass else: for _rpt in rm_rpt: # immediate expiration self.session.update(_rpt, expires_at=0) def store_permission(self, user, requestor, rsids): """ :param user: The resource owner :param requestor: The requestor ID :param rsids: dictionary with Resource set IDs as keys and scopes as values """ logger.info("store: (%s, %s, %s)" % (user, requestor, rsids)) present = self.permit.get_rsid_permits(user, requestor) _new = [k for k in list(rsids.keys()) if k not in present] _user = safe_name(user, requestor) for rsid in _new: scopes = rsids[rsid] if scopes is None: rs = self.resource_set.read(_user, rsid) scopes = rs["scopes"] self.permit.set_permit(user, requestor, rsid, scopes) _rem = [k for k in present if k not in rsids] for rsid in _rem: self.permit.delete_permit(user, requestor, rsid) def read_permission(self, user, requestor, rsid): return self.permit.get_permit(user, requestor, rsid) def rec_rm_permission(self, user, requestor, rsid): """ If the resource set is a complex set, remove all subset permissions :param user: The owner of the resource :param requestor: Who the permission is applying to :param rsid: The resource set name """ _user = safe_name(user, requestor) rs = self.resource_set.read(_user, rsid) if "subsets" in rs: for ss in rs["subsets"]: self.rec_rm_permission(user, requestor, ss) try: self.permit.delete_permit(user, requestor, rsid) except KeyError: pass def rm_permission(self, user, requestor, rsid): """ If the resource set is a complex set, remove all subset permissions :param user: The owner of the resource :param requestor: Who the permission is applying to :param rsid: The resource set name """ logger.info("remove: (%s, %s, %s)" % (user, requestor, rsid)) self.rec_rm_permission(user, requestor, rsid) return True def rsid_permits(self, user, requestor): return self.permit.get_rsid_permits(user, requestor)