def permissions_get(request): # Invert the permissions inheritance tree. perms_descending_tree = {} for obtained, obtained_from in PERMISSIONS_INHERITANCE_TREE.items(): on_resource, obtained_perm = obtained.split(':', 1) for from_resource, perms in obtained_from.items(): for perm in perms: perms_descending_tree.setdefault(from_resource, {})\ .setdefault(perm, {})\ .setdefault(on_resource, set())\ .add(obtained_perm) # Obtain current principals. principals = request.effective_principals if Authenticated in principals: # Since this view does not require any permission (can be used to # obtain public users permissions), we have to add the prefixed userid # among the principals (see :mode:`kinto.core.authentication`) userid = request.prefixed_userid principals.append(userid) # Query every possible permission of the current user from backend. # Since there is no "full-list" method, we query for each possible # permission (read, write, group:create, collection:create, record:create). # XXX: could be optimized into one call to backend when needed. possible_perms = set([k.split(':', 1)[1] for k in PERMISSIONS_INHERITANCE_TREE.keys()]) backend = request.registry.permission perms_by_object_uri = {} for perm in possible_perms: object_uris = backend.get_accessible_objects(principals, perm) for object_uri in object_uris: perms_by_object_uri.setdefault(object_uri, []).append(perm) entries = [] for object_uri, perms in perms_by_object_uri.items(): # Obtain associated resource from object URI resource_name, matchdict = core_utils.view_lookup(request, object_uri) # For consistency with events payloads, prefix id with resource name matchdict[resource_name + '_id'] = matchdict.get('id') # Expand implicit permissions using descending tree. permissions = set(perms) for perm in perms: obtained = perms_descending_tree[resource_name][perm] # Related to same resource only and not every sub-objects. # (e.g "bucket:write" gives "bucket:read" but not "group:read") permissions |= obtained[resource_name] entry = dict(uri=object_uri, resource_name=resource_name, permissions=list(permissions), **matchdict) entries.append(entry) return {"data": entries}
def permissions_get(request): # Invert the permissions inheritance tree. perms_descending_tree = {} for obtained, obtained_from in PERMISSIONS_INHERITANCE_TREE.items(): on_resource, obtained_perm = obtained.split(':', 1) for from_resource, perms in obtained_from.items(): for perm in perms: perms_descending_tree.setdefault(from_resource, {})\ .setdefault(perm, {})\ .setdefault(on_resource, set())\ .add(obtained_perm) # Obtain current principals. principals = request.effective_principals if Authenticated in principals: # Since this view does not require any permission (can be used to # obtain public users permissions), we have to add the prefixed userid # among the principals (see :mode:`kinto.core.authentication`) userid = request.prefixed_userid principals.append(userid) # Query every possible permission of the current user from backend. backend = request.registry.permission perms_by_object_uri = backend.get_accessible_objects(principals) entries = [] for object_uri, perms in perms_by_object_uri.items(): try: # Obtain associated resource from object URI resource_name, matchdict = core_utils.view_lookup( request, object_uri) except ValueError: # Skip permissions entries that are not linked to an object URI. continue # For consistency with events payloads, prefix id with resource name matchdict[resource_name + '_id'] = matchdict.get('id') # Expand implicit permissions using descending tree. permissions = set(perms) for perm in perms: obtained = perms_descending_tree[resource_name][perm] # Related to same resource only and not every sub-objects. # (e.g "bucket:write" gives "bucket:read" but not "group:read") permissions |= obtained[resource_name] entry = dict(uri=object_uri, resource_name=resource_name, permissions=list(permissions), **matchdict) entries.append(entry) return {"data": entries}
def get_records(self, filters=None, sorting=None, pagination_rules=None, limit=None, include_deleted=False, parent_id=None): # Invert the permissions inheritance tree. perms_descending_tree = {} for on_resource, tree in PERMISSIONS_INHERITANCE_TREE.items(): for obtained_perm, obtained_from in tree.items(): for from_resource, perms in obtained_from.items(): for perm in perms: perms_descending_tree.setdefault(from_resource, {})\ .setdefault(perm, {})\ .setdefault(on_resource, set())\ .add(obtained_perm) # Obtain current principals. principals = self.request.prefixed_principals # Query every possible permission of the current user from backend. backend = self.request.registry.permission perms_by_object_uri = backend.get_accessible_objects(principals) # Check settings for every allowed resources. from_settings = allowed_from_settings(self.request.registry.settings, principals) # Expand permissions obtained from backend with the object URIs that # correspond to permissions allowed from settings. allowed_resources = {'bucket', 'collection', 'group'} & set( from_settings.keys()) if allowed_resources: storage = self.request.registry.storage every_bucket, _ = storage.get_all(parent_id='', collection_id='bucket') for bucket in every_bucket: bucket_uri = '/buckets/{id}'.format(**bucket) for res in allowed_resources: resource_perms = from_settings[res] # Bucket is always fetched. if res == 'bucket': perms_by_object_uri.setdefault( bucket_uri, set()).update(resource_perms) continue # Fetch bucket collections and groups. # XXX: wrong approach: query in a loop! every_subobjects, _ = storage.get_all(parent_id=bucket_uri, collection_id=res) for subobject in every_subobjects: subobj_uri = bucket_uri + '/{0}s/{1}'.format( res, subobject['id']) perms_by_object_uri.setdefault( subobj_uri, set()).update(resource_perms) entries = [] for object_uri, perms in perms_by_object_uri.items(): try: # Obtain associated res from object URI resource_name, matchdict = core_utils.view_lookup( self.request, object_uri) except ValueError: # Skip permissions entries that are not linked to an object URI continue # For consistency with event payloads, prefix id with resource name matchdict[resource_name + '_id'] = matchdict.get('id') # Expand implicit permissions using descending tree. permissions = set(perms) for perm in perms: obtained = perms_descending_tree[resource_name][perm] # Related to same resource only and not every sub-objects. # (e.g "bucket:write" gives "bucket:read" but not "group:read") permissions |= obtained[resource_name] entry = dict(uri=object_uri, resource_name=resource_name, permissions=list(permissions), **matchdict) entries.append(entry) return extract_record_set(entries, filters=filters, sorting=sorting, pagination_rules=pagination_rules, limit=limit)
def get_records( self, filters=None, sorting=None, pagination_rules=None, limit=None, include_deleted=False, parent_id=None, ): # Invert the permissions inheritance tree. perms_descending_tree = {} for on_resource, tree in PERMISSIONS_INHERITANCE_TREE.items(): for obtained_perm, obtained_from in tree.items(): for from_resource, perms in obtained_from.items(): for perm in perms: perms_descending_tree.setdefault(from_resource, {}).setdefault( perm, {} ).setdefault(on_resource, set()).add(obtained_perm) # Obtain current principals. principals = self.request.prefixed_principals # Query every possible permission of the current user from backend. backend = self.request.registry.permission perms_by_object_uri = backend.get_accessible_objects(principals) # Check settings for every allowed resources. from_settings = allowed_from_settings(self.request.registry.settings, principals) # Add additional resources and permissions defined in settings/plugins for root_perm in from_settings.get("root", []): resource_name, _ = root_perm.split(":") perms_by_object_uri.setdefault("/", set()).add(root_perm) perms_descending_tree.setdefault("root", {}).update({root_perm: {"root": {root_perm}}}) # Expand permissions obtained from backend with the object URIs that # correspond to permissions allowed from settings. allowed_resources = {"bucket", "collection", "group"} & set(from_settings.keys()) if allowed_resources: storage = self.request.registry.storage every_bucket, _ = storage.get_all(parent_id="", collection_id="bucket") for bucket in every_bucket: bucket_uri = "/buckets/{id}".format_map(bucket) for res in allowed_resources: resource_perms = from_settings[res] # Bucket is always fetched. if res == "bucket": perms_by_object_uri.setdefault(bucket_uri, set()).update(resource_perms) continue # Fetch bucket collections and groups. # XXX: wrong approach: query in a loop! every_subobjects, _ = storage.get_all(parent_id=bucket_uri, collection_id=res) for subobject in every_subobjects: subobj_uri = bucket_uri + "/{0}s/{1}".format(res, subobject["id"]) perms_by_object_uri.setdefault(subobj_uri, set()).update(resource_perms) entries = [] for object_uri, perms in perms_by_object_uri.items(): try: # Obtain associated res from object URI resource_name, matchdict = core_utils.view_lookup(self.request, object_uri) except ValueError: # Skip permissions entries that are not linked to an object URI continue # For consistency with event payloads, if resource has an id, # prefix it with its resource name if "id" in matchdict: matchdict[resource_name + "_id"] = matchdict["id"] # The imaginary "root" resource gets mapped to the hello # view. Handle it explicitly. if resource_name == "hello": resource_name = "root" # Expand implicit permissions using descending tree. permissions = set(perms) for perm in perms: obtained = perms_descending_tree[resource_name][perm] # Related to same resource only and not every sub-objects. # (e.g "bucket:write" gives "bucket:read" but not "group:read") permissions |= obtained[resource_name] entry = dict( uri=object_uri, resource_name=resource_name, permissions=list(permissions), **matchdict ) entries.append(entry) return extract_record_set( entries, filters=filters, sorting=sorting, id_field="uri", pagination_rules=pagination_rules, limit=limit, )
def get_objects( self, filters=None, sorting=None, pagination_rules=None, limit=None, include_deleted=False, parent_id=None, ): # Invert the permissions inheritance tree. perms_descending_tree = {} for on_resource, tree in PERMISSIONS_INHERITANCE_TREE.items(): for obtained_perm, obtained_from in tree.items(): for from_resource, perms in obtained_from.items(): for perm in perms: perms_descending_tree.setdefault( from_resource, {}).setdefault(perm, {}).setdefault( on_resource, set()).add(obtained_perm) # Obtain current principals. principals = self.request.prefixed_principals # Query every possible permission of the current user from backend. backend = self.request.registry.permission perms_by_object_uri = backend.get_accessible_objects(principals) # Check settings for every allowed resources. from_settings = allowed_from_settings(self.request.registry.settings, principals) # Add additional resources and permissions defined in settings/plugins for root_perm in from_settings.get("root", []): resource_name, _ = root_perm.split(":") perms_by_object_uri.setdefault("/", set()).add(root_perm) perms_descending_tree.setdefault("root", {}).update( {root_perm: { "root": {root_perm} }}) # Expand permissions obtained from backend with the object URIs that # correspond to permissions allowed from settings. allowed_resources = {"bucket", "collection", "group"} & set( from_settings.keys()) if allowed_resources: storage = self.request.registry.storage every_bucket, _ = storage.get_all(parent_id="", resource_name="bucket") for bucket in every_bucket: bucket_uri = "/buckets/{id}".format_map(bucket) for res in allowed_resources: resource_perms = from_settings[res] # Bucket is always fetched. if res == "bucket": perms_by_object_uri.setdefault( bucket_uri, set()).update(resource_perms) continue # Fetch bucket collections and groups. # XXX: wrong approach: query in a loop! every_subobjects, _ = storage.get_all(parent_id=bucket_uri, resource_name=res) for subobject in every_subobjects: subobj_uri = bucket_uri + f"/{res}s/{subobject['id']}" perms_by_object_uri.setdefault( subobj_uri, set()).update(resource_perms) entries = [] for object_uri, perms in perms_by_object_uri.items(): try: # Obtain associated res from object URI resource_name, matchdict = core_utils.view_lookup( self.request, object_uri) except ValueError: # Skip permissions entries that are not linked to an object URI continue # For consistency with event payloads, if resource has an id, # prefix it with its resource name if "id" in matchdict: matchdict[resource_name + "_id"] = matchdict["id"] # The imaginary "root" resource gets mapped to the hello # view. Handle it explicitly. if resource_name == "hello": resource_name = "root" # Expand implicit permissions using descending tree. permissions = set(perms) for perm in perms: obtained = perms_descending_tree[resource_name][perm] # Related to same resource only and not every sub-objects. # (e.g "bucket:write" gives "bucket:read" but not "group:read") permissions |= obtained[resource_name] entry = dict( uri=object_uri, resource_name=resource_name, permissions=list(permissions), **matchdict, ) entries.append(entry) return extract_object_set( entries, filters=filters, sorting=sorting, id_field="uri", pagination_rules=pagination_rules, limit=limit, )