We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Crash when querying `GET /buckets/collections`
<details>
  <summary>

<code>ValueError: You cannot build children keys from its parent key.Trying to build type "collection" from object key "/buckets/collections"</code></summary>



```
    return authz_policy.permits(context, principals, permission)
  File "/home/mathieu/Code/Mozilla/kinto/kinto/core/authorization.py", line 76, in permits
    get_bound_permissions=self.get_bound_permissions)
  File "/home/mathieu/Code/Mozilla/kinto/kinto/core/authorization.py", line 169, in check_permission
    return self._check_permission(self.permission_object_id, *args, **kw)
  File "/home/mathieu/Code/Mozilla/kinto/kinto/core/permission/postgresql/__init__.py", line 237, in check_permission
    perms = get_bound_permissions(object_id, permission)
  File "/home/mathieu/Code/Mozilla/kinto/kinto/authorization.py", line 144, in get_bound_permissions
    return build_permissions_set(*args, **kwargs)
  File "/home/mathieu/Code/Mozilla/kinto/kinto/authorization.py", line 136, in build_permissions_set
    granters.add(build_permission_tuple(obj, permission, obj_parts))
  File "/home/mathieu/Code/Mozilla/kinto/kinto/authorization.py", line 105, in build_permission_tuple
    obj_type, '/'.join(obj_parts)))
ValueError: You cannot build children keys from its parent key.Trying to build type "collection" from object key "/buckets/collections". lang=None uid=7447fd40326a7840a5135b3fa2e1acef4c516ece4635b6ebad0522aaa9331c3a
```

</details>


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `kinto/authorization.py`
Content:
```
1 from kinto.core import authorization as core_authorization
2 from pyramid.security import IAuthorizationPolicy, Authenticated
3 from zope.interface import implementer
4 
5 
6 # Vocab really matters when you deal with permissions. Let's do a quick recap
7 # of the terms used here:
8 #
9 # Object URI:
10 #    An unique identifier for an object.
11 #    for instance, /buckets/blog/collections/articles/records/article1
12 #
13 # Object:
14 #    A common denomination of an object (e.g. "collection" or "record")
15 #
16 # Unbound permission:
17 #    A permission not bound to an object (e.g. "create")
18 #
19 # Bound permission:
20 #    A permission bound to an object (e.g. "collection:create")
21 
22 
23 # Dictionary which list all permissions a given permission enables.
24 PERMISSIONS_INHERITANCE_TREE = {
25     'bucket:write': {
26         'bucket': ['write']
27     },
28     'bucket:read': {
29         'bucket': ['write', 'read']
30     },
31     'bucket:group:create': {
32         'bucket': ['write', 'group:create']
33     },
34     'bucket:collection:create': {
35         'bucket': ['write', 'collection:create']
36     },
37     'group:write': {
38         'bucket': ['write'],
39         'group': ['write']
40     },
41     'group:read': {
42         'bucket': ['write', 'read'],
43         'group': ['write', 'read']
44     },
45     'collection:write': {
46         'bucket': ['write'],
47         'collection': ['write'],
48     },
49     'collection:read': {
50         'bucket': ['write', 'read'],
51         'collection': ['write', 'read'],
52     },
53     'collection:record:create': {
54         'bucket': ['write'],
55         'collection': ['write', 'record:create']
56     },
57     'record:write': {
58         'bucket': ['write'],
59         'collection': ['write'],
60         'record': ['write']
61     },
62     'record:read': {
63         'bucket': ['write', 'read'],
64         'collection': ['write', 'read'],
65         'record': ['write', 'read']
66     }
67 }
68 
69 
70 def get_object_type(object_uri):
71     """Return the type of an object from its id."""
72 
73     obj_parts = object_uri.split('/')
74     if len(obj_parts) % 2 == 0:
75         object_uri = '/'.join(obj_parts[:-1])
76 
77     # Order matters here. More precise is tested first.
78     if 'records' in object_uri:
79         obj_type = 'record'
80     elif 'collections' in object_uri:
81         obj_type = 'collection'
82     elif 'groups' in object_uri:
83         obj_type = 'group'
84     elif 'buckets' in object_uri:
85         obj_type = 'bucket'
86     else:
87         obj_type = None
88     return obj_type
89 
90 
91 def build_permission_tuple(obj_type, unbound_permission, obj_parts):
92     """Returns a tuple of (object_uri, unbound_permission)"""
93     PARTS_LENGTH = {
94         'bucket': 3,
95         'collection': 5,
96         'group': 5,
97         'record': 7
98     }
99     if obj_type not in PARTS_LENGTH:
100         raise ValueError('Invalid object type: %s' % obj_type)
101 
102     if PARTS_LENGTH[obj_type] > len(obj_parts):
103         raise ValueError('You cannot build children keys from its parent key.'
104                          'Trying to build type "%s" from object key "%s".' % (
105                              obj_type, '/'.join(obj_parts)))
106     length = PARTS_LENGTH[obj_type]
107     return ('/'.join(obj_parts[:length]), unbound_permission)
108 
109 
110 def build_permissions_set(object_uri, unbound_permission,
111                           inheritance_tree=None):
112     """Build a set of all permissions that can grant access to the given
113     object URI and unbound permission.
114 
115     >>> build_required_permissions('/buckets/blog', 'write')
116     set(('/buckets/blog', 'write'))
117 
118     """
119 
120     if inheritance_tree is None:
121         inheritance_tree = PERMISSIONS_INHERITANCE_TREE
122 
123     obj_type = get_object_type(object_uri)
124 
125     # Unknown object type, does not map the INHERITANCE_TREE.
126     # In that case, the set of related permissions is empty.
127     if obj_type is None:
128         return set()
129 
130     bound_permission = '%s:%s' % (obj_type, unbound_permission)
131     granters = set()
132 
133     obj_parts = object_uri.split('/')
134     for obj, permission_list in inheritance_tree[bound_permission].items():
135         for permission in permission_list:
136             granters.add(build_permission_tuple(obj, permission, obj_parts))
137 
138     return granters
139 
140 
141 @implementer(IAuthorizationPolicy)
142 class AuthorizationPolicy(core_authorization.AuthorizationPolicy):
143     def get_bound_permissions(self, *args, **kwargs):
144         return build_permissions_set(*args, **kwargs)
145 
146 
147 class RouteFactory(core_authorization.RouteFactory):
148     pass
149 
150 
151 class BucketRouteFactory(RouteFactory):
152     def fetch_shared_records(self, perm, principals, get_bound_permissions):
153         """Buckets list is authorized even if no object is accessible for
154         the current principals.
155         """
156         shared = super(BucketRouteFactory, self).fetch_shared_records(
157             perm, principals, get_bound_permissions)
158         if shared is None and Authenticated in principals:
159             self.shared_ids = []
160         return self.shared_ids
161
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/kinto/authorization.py b/kinto/authorization.py
--- a/kinto/authorization.py
+++ b/kinto/authorization.py
@@ -1,7 +1,9 @@
-from kinto.core import authorization as core_authorization
+import re
+
 from pyramid.security import IAuthorizationPolicy, Authenticated
 from zope.interface import implementer
 
+from kinto.core import authorization as core_authorization
 
 # Vocab really matters when you deal with permissions. Let's do a quick recap
 # of the terms used here:
@@ -69,23 +71,15 @@
 
 def get_object_type(object_uri):
     """Return the type of an object from its id."""
-
-    obj_parts = object_uri.split('/')
-    if len(obj_parts) % 2 == 0:
-        object_uri = '/'.join(obj_parts[:-1])
-
-    # Order matters here. More precise is tested first.
-    if 'records' in object_uri:
-        obj_type = 'record'
-    elif 'collections' in object_uri:
-        obj_type = 'collection'
-    elif 'groups' in object_uri:
-        obj_type = 'group'
-    elif 'buckets' in object_uri:
-        obj_type = 'bucket'
-    else:
-        obj_type = None
-    return obj_type
+    if re.match(r'/buckets/(.+)/collections/(.+)/records/(.+)?', object_uri):
+        return 'record'
+    if re.match(r'/buckets/(.+)/collections/(.+)?', object_uri):
+        return 'collection'
+    if re.match(r'/buckets/(.+)/groups/(.+)?', object_uri):
+        return 'group'
+    if re.match(r'/buckets/(.+)?', object_uri):
+        return 'bucket'
+    return None
 
 
 def build_permission_tuple(obj_type, unbound_permission, obj_parts):

{"golden_diff": "diff --git a/kinto/authorization.py b/kinto/authorization.py\n--- a/kinto/authorization.py\n+++ b/kinto/authorization.py\n@@ -1,7 +1,9 @@\n-from kinto.core import authorization as core_authorization\n+import re\n+\n from pyramid.security import IAuthorizationPolicy, Authenticated\n from zope.interface import implementer\n \n+from kinto.core import authorization as core_authorization\n \n # Vocab really matters when you deal with permissions. Let's do a quick recap\n # of the terms used here:\n@@ -69,23 +71,15 @@\n \n def get_object_type(object_uri):\n     \"\"\"Return the type of an object from its id.\"\"\"\n-\n-    obj_parts = object_uri.split('/')\n-    if len(obj_parts) % 2 == 0:\n-        object_uri = '/'.join(obj_parts[:-1])\n-\n-    # Order matters here. More precise is tested first.\n-    if 'records' in object_uri:\n-        obj_type = 'record'\n-    elif 'collections' in object_uri:\n-        obj_type = 'collection'\n-    elif 'groups' in object_uri:\n-        obj_type = 'group'\n-    elif 'buckets' in object_uri:\n-        obj_type = 'bucket'\n-    else:\n-        obj_type = None\n-    return obj_type\n+    if re.match(r'/buckets/(.+)/collections/(.+)/records/(.+)?', object_uri):\n+        return 'record'\n+    if re.match(r'/buckets/(.+)/collections/(.+)?', object_uri):\n+        return 'collection'\n+    if re.match(r'/buckets/(.+)/groups/(.+)?', object_uri):\n+        return 'group'\n+    if re.match(r'/buckets/(.+)?', object_uri):\n+        return 'bucket'\n+    return None\n \n \n def build_permission_tuple(obj_type, unbound_permission, obj_parts):\n", "issue": "Crash when querying `GET /buckets/collections`\n<details>\n  <summary>\n\n<code>ValueError: You cannot build children keys from its parent key.Trying to build type \"collection\" from object key \"/buckets/collections\"</code></summary>\n\n\n\n```\n    return authz_policy.permits(context, principals, permission)\n  File \"/home/mathieu/Code/Mozilla/kinto/kinto/core/authorization.py\", line 76, in permits\n    get_bound_permissions=self.get_bound_permissions)\n  File \"/home/mathieu/Code/Mozilla/kinto/kinto/core/authorization.py\", line 169, in check_permission\n    return self._check_permission(self.permission_object_id, *args, **kw)\n  File \"/home/mathieu/Code/Mozilla/kinto/kinto/core/permission/postgresql/__init__.py\", line 237, in check_permission\n    perms = get_bound_permissions(object_id, permission)\n  File \"/home/mathieu/Code/Mozilla/kinto/kinto/authorization.py\", line 144, in get_bound_permissions\n    return build_permissions_set(*args, **kwargs)\n  File \"/home/mathieu/Code/Mozilla/kinto/kinto/authorization.py\", line 136, in build_permissions_set\n    granters.add(build_permission_tuple(obj, permission, obj_parts))\n  File \"/home/mathieu/Code/Mozilla/kinto/kinto/authorization.py\", line 105, in build_permission_tuple\n    obj_type, '/'.join(obj_parts)))\nValueError: You cannot build children keys from its parent key.Trying to build type \"collection\" from object key \"/buckets/collections\". lang=None uid=7447fd40326a7840a5135b3fa2e1acef4c516ece4635b6ebad0522aaa9331c3a\n```\n\n</details>\n\n", "before_files": [{"content": "from kinto.core import authorization as core_authorization\nfrom pyramid.security import IAuthorizationPolicy, Authenticated\nfrom zope.interface import implementer\n\n\n# Vocab really matters when you deal with permissions. Let's do a quick recap\n# of the terms used here:\n#\n# Object URI:\n#    An unique identifier for an object.\n#    for instance, /buckets/blog/collections/articles/records/article1\n#\n# Object:\n#    A common denomination of an object (e.g. \"collection\" or \"record\")\n#\n# Unbound permission:\n#    A permission not bound to an object (e.g. \"create\")\n#\n# Bound permission:\n#    A permission bound to an object (e.g. \"collection:create\")\n\n\n# Dictionary which list all permissions a given permission enables.\nPERMISSIONS_INHERITANCE_TREE = {\n    'bucket:write': {\n        'bucket': ['write']\n    },\n    'bucket:read': {\n        'bucket': ['write', 'read']\n    },\n    'bucket:group:create': {\n        'bucket': ['write', 'group:create']\n    },\n    'bucket:collection:create': {\n        'bucket': ['write', 'collection:create']\n    },\n    'group:write': {\n        'bucket': ['write'],\n        'group': ['write']\n    },\n    'group:read': {\n        'bucket': ['write', 'read'],\n        'group': ['write', 'read']\n    },\n    'collection:write': {\n        'bucket': ['write'],\n        'collection': ['write'],\n    },\n    'collection:read': {\n        'bucket': ['write', 'read'],\n        'collection': ['write', 'read'],\n    },\n    'collection:record:create': {\n        'bucket': ['write'],\n        'collection': ['write', 'record:create']\n    },\n    'record:write': {\n        'bucket': ['write'],\n        'collection': ['write'],\n        'record': ['write']\n    },\n    'record:read': {\n        'bucket': ['write', 'read'],\n        'collection': ['write', 'read'],\n        'record': ['write', 'read']\n    }\n}\n\n\ndef get_object_type(object_uri):\n    \"\"\"Return the type of an object from its id.\"\"\"\n\n    obj_parts = object_uri.split('/')\n    if len(obj_parts) % 2 == 0:\n        object_uri = '/'.join(obj_parts[:-1])\n\n    # Order matters here. More precise is tested first.\n    if 'records' in object_uri:\n        obj_type = 'record'\n    elif 'collections' in object_uri:\n        obj_type = 'collection'\n    elif 'groups' in object_uri:\n        obj_type = 'group'\n    elif 'buckets' in object_uri:\n        obj_type = 'bucket'\n    else:\n        obj_type = None\n    return obj_type\n\n\ndef build_permission_tuple(obj_type, unbound_permission, obj_parts):\n    \"\"\"Returns a tuple of (object_uri, unbound_permission)\"\"\"\n    PARTS_LENGTH = {\n        'bucket': 3,\n        'collection': 5,\n        'group': 5,\n        'record': 7\n    }\n    if obj_type not in PARTS_LENGTH:\n        raise ValueError('Invalid object type: %s' % obj_type)\n\n    if PARTS_LENGTH[obj_type] > len(obj_parts):\n        raise ValueError('You cannot build children keys from its parent key.'\n                         'Trying to build type \"%s\" from object key \"%s\".' % (\n                             obj_type, '/'.join(obj_parts)))\n    length = PARTS_LENGTH[obj_type]\n    return ('/'.join(obj_parts[:length]), unbound_permission)\n\n\ndef build_permissions_set(object_uri, unbound_permission,\n                          inheritance_tree=None):\n    \"\"\"Build a set of all permissions that can grant access to the given\n    object URI and unbound permission.\n\n    >>> build_required_permissions('/buckets/blog', 'write')\n    set(('/buckets/blog', 'write'))\n\n    \"\"\"\n\n    if inheritance_tree is None:\n        inheritance_tree = PERMISSIONS_INHERITANCE_TREE\n\n    obj_type = get_object_type(object_uri)\n\n    # Unknown object type, does not map the INHERITANCE_TREE.\n    # In that case, the set of related permissions is empty.\n    if obj_type is None:\n        return set()\n\n    bound_permission = '%s:%s' % (obj_type, unbound_permission)\n    granters = set()\n\n    obj_parts = object_uri.split('/')\n    for obj, permission_list in inheritance_tree[bound_permission].items():\n        for permission in permission_list:\n            granters.add(build_permission_tuple(obj, permission, obj_parts))\n\n    return granters\n\n\n@implementer(IAuthorizationPolicy)\nclass AuthorizationPolicy(core_authorization.AuthorizationPolicy):\n    def get_bound_permissions(self, *args, **kwargs):\n        return build_permissions_set(*args, **kwargs)\n\n\nclass RouteFactory(core_authorization.RouteFactory):\n    pass\n\n\nclass BucketRouteFactory(RouteFactory):\n    def fetch_shared_records(self, perm, principals, get_bound_permissions):\n        \"\"\"Buckets list is authorized even if no object is accessible for\n        the current principals.\n        \"\"\"\n        shared = super(BucketRouteFactory, self).fetch_shared_records(\n            perm, principals, get_bound_permissions)\n        if shared is None and Authenticated in principals:\n            self.shared_ids = []\n        return self.shared_ids\n", "path": "kinto/authorization.py"}], "after_files": [{"content": "import re\n\nfrom pyramid.security import IAuthorizationPolicy, Authenticated\nfrom zope.interface import implementer\n\nfrom kinto.core import authorization as core_authorization\n\n# Vocab really matters when you deal with permissions. Let's do a quick recap\n# of the terms used here:\n#\n# Object URI:\n#    An unique identifier for an object.\n#    for instance, /buckets/blog/collections/articles/records/article1\n#\n# Object:\n#    A common denomination of an object (e.g. \"collection\" or \"record\")\n#\n# Unbound permission:\n#    A permission not bound to an object (e.g. \"create\")\n#\n# Bound permission:\n#    A permission bound to an object (e.g. \"collection:create\")\n\n\n# Dictionary which list all permissions a given permission enables.\nPERMISSIONS_INHERITANCE_TREE = {\n    'bucket:write': {\n        'bucket': ['write']\n    },\n    'bucket:read': {\n        'bucket': ['write', 'read']\n    },\n    'bucket:group:create': {\n        'bucket': ['write', 'group:create']\n    },\n    'bucket:collection:create': {\n        'bucket': ['write', 'collection:create']\n    },\n    'group:write': {\n        'bucket': ['write'],\n        'group': ['write']\n    },\n    'group:read': {\n        'bucket': ['write', 'read'],\n        'group': ['write', 'read']\n    },\n    'collection:write': {\n        'bucket': ['write'],\n        'collection': ['write'],\n    },\n    'collection:read': {\n        'bucket': ['write', 'read'],\n        'collection': ['write', 'read'],\n    },\n    'collection:record:create': {\n        'bucket': ['write'],\n        'collection': ['write', 'record:create']\n    },\n    'record:write': {\n        'bucket': ['write'],\n        'collection': ['write'],\n        'record': ['write']\n    },\n    'record:read': {\n        'bucket': ['write', 'read'],\n        'collection': ['write', 'read'],\n        'record': ['write', 'read']\n    }\n}\n\n\ndef get_object_type(object_uri):\n    \"\"\"Return the type of an object from its id.\"\"\"\n    if re.match(r'/buckets/(.+)/collections/(.+)/records/(.+)?', object_uri):\n        return 'record'\n    if re.match(r'/buckets/(.+)/collections/(.+)?', object_uri):\n        return 'collection'\n    if re.match(r'/buckets/(.+)/groups/(.+)?', object_uri):\n        return 'group'\n    if re.match(r'/buckets/(.+)?', object_uri):\n        return 'bucket'\n    return None\n\n\ndef build_permission_tuple(obj_type, unbound_permission, obj_parts):\n    \"\"\"Returns a tuple of (object_uri, unbound_permission)\"\"\"\n    PARTS_LENGTH = {\n        'bucket': 3,\n        'collection': 5,\n        'group': 5,\n        'record': 7\n    }\n    if obj_type not in PARTS_LENGTH:\n        raise ValueError('Invalid object type: %s' % obj_type)\n\n    if PARTS_LENGTH[obj_type] > len(obj_parts):\n        raise ValueError('You cannot build children keys from its parent key.'\n                         'Trying to build type \"%s\" from object key \"%s\".' % (\n                             obj_type, '/'.join(obj_parts)))\n    length = PARTS_LENGTH[obj_type]\n    return ('/'.join(obj_parts[:length]), unbound_permission)\n\n\ndef build_permissions_set(object_uri, unbound_permission,\n                          inheritance_tree=None):\n    \"\"\"Build a set of all permissions that can grant access to the given\n    object URI and unbound permission.\n\n    >>> build_required_permissions('/buckets/blog', 'write')\n    set(('/buckets/blog', 'write'))\n\n    \"\"\"\n\n    if inheritance_tree is None:\n        inheritance_tree = PERMISSIONS_INHERITANCE_TREE\n\n    obj_type = get_object_type(object_uri)\n\n    # Unknown object type, does not map the INHERITANCE_TREE.\n    # In that case, the set of related permissions is empty.\n    if obj_type is None:\n        return set()\n\n    bound_permission = '%s:%s' % (obj_type, unbound_permission)\n    granters = set()\n\n    obj_parts = object_uri.split('/')\n    for obj, permission_list in inheritance_tree[bound_permission].items():\n        for permission in permission_list:\n            granters.add(build_permission_tuple(obj, permission, obj_parts))\n\n    return granters\n\n\n@implementer(IAuthorizationPolicy)\nclass AuthorizationPolicy(core_authorization.AuthorizationPolicy):\n    def get_bound_permissions(self, *args, **kwargs):\n        return build_permissions_set(*args, **kwargs)\n\n\nclass RouteFactory(core_authorization.RouteFactory):\n    pass\n\n\nclass BucketRouteFactory(RouteFactory):\n    def fetch_shared_records(self, perm, principals, get_bound_permissions):\n        \"\"\"Buckets list is authorized even if no object is accessible for\n        the current principals.\n        \"\"\"\n        shared = super(BucketRouteFactory, self).fetch_shared_records(\n            perm, principals, get_bound_permissions)\n        if shared is None and Authenticated in principals:\n            self.shared_ids = []\n        return self.shared_ids\n", "path": "kinto/authorization.py"}]}