We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Memory permission backend implementation of remove_principal() is wrong
According to the `PermissionBase` docstring, `remove_principal` is supposed to `Remove a principal from every user`. In other words, `remove_principal(principal)` is equivalent to `remove_user_principal(user_id, principal) for user_id in all_possible_user_ids`. However, the current implementation stores all permissions of all kinds in one hash table, and removes the principal from permissions of non-user things as well.

--- 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/core/permission/memory.py`
Content:
```
1 import re
2 
3 from kinto.core.decorators import synchronized
4 from kinto.core.permission import PermissionBase
5 
6 
7 class Permission(PermissionBase):
8     """Permission backend implementation in local process memory.
9 
10     Enable in configuration::
11 
12         kinto.permission_backend = kinto.core.permission.memory
13 
14     :noindex:
15     """
16 
17     def __init__(self, *args, **kwargs):
18         super().__init__(*args, **kwargs)
19         self.flush()
20 
21     def initialize_schema(self, dry_run=False):
22         # Nothing to do.
23         pass
24 
25     def flush(self):
26         self._store = {}
27 
28     @synchronized
29     def add_user_principal(self, user_id, principal):
30         user_key = f"user:{user_id}"
31         user_principals = self._store.get(user_key, set())
32         user_principals.add(principal)
33         self._store[user_key] = user_principals
34 
35     @synchronized
36     def remove_user_principal(self, user_id, principal):
37         user_key = f"user:{user_id}"
38         user_principals = self._store.get(user_key, set())
39         try:
40             user_principals.remove(principal)
41         except KeyError:
42             pass
43         if len(user_principals) == 0:
44             if user_key in self._store:
45                 del self._store[user_key]
46         else:
47             self._store[user_key] = user_principals
48 
49     @synchronized
50     def remove_principal(self, principal):
51         for user_principals in self._store.values():
52             try:
53                 user_principals.remove(principal)
54             except KeyError:
55                 pass
56 
57     @synchronized
58     def get_user_principals(self, user_id):
59         # Fetch the groups the user is in.
60         user_key = f"user:{user_id}"
61         members = self._store.get(user_key, set())
62         # Fetch the groups system.Authenticated is in.
63         group_authenticated = self._store.get("user:system.Authenticated", set())
64         return members | group_authenticated
65 
66     @synchronized
67     def add_principal_to_ace(self, object_id, permission, principal):
68         permission_key = f"permission:{object_id}:{permission}"
69         object_permission_principals = self._store.get(permission_key, set())
70         object_permission_principals.add(principal)
71         self._store[permission_key] = object_permission_principals
72 
73     @synchronized
74     def remove_principal_from_ace(self, object_id, permission, principal):
75         permission_key = f"permission:{object_id}:{permission}"
76         object_permission_principals = self._store.get(permission_key, set())
77         try:
78             object_permission_principals.remove(principal)
79         except KeyError:
80             pass
81         if len(object_permission_principals) == 0:
82             if permission_key in self._store:
83                 del self._store[permission_key]
84         else:
85             self._store[permission_key] = object_permission_principals
86 
87     @synchronized
88     def get_object_permission_principals(self, object_id, permission):
89         permission_key = f"permission:{object_id}:{permission}"
90         members = self._store.get(permission_key, set())
91         return members
92 
93     @synchronized
94     def get_accessible_objects(self, principals, bound_permissions=None, with_children=True):
95         principals = set(principals)
96         candidates = []
97         if bound_permissions is None:
98             for key, value in self._store.items():
99                 _, object_id, permission = key.split(":", 2)
100                 candidates.append((object_id, permission, value))
101         else:
102             for pattern, perm in bound_permissions:
103                 id_match = ".*" if with_children else "[^/]+"
104                 regexp = re.compile(f"^{pattern.replace('*', id_match)}$")
105                 for key, value in self._store.items():
106                     if key.endswith(perm):
107                         object_id = key.split(":")[1]
108                         if regexp.match(object_id):
109                             candidates.append((object_id, perm, value))
110 
111         perms_by_object_id = {}
112         for (object_id, perm, value) in candidates:
113             if len(principals & value) > 0:
114                 perms_by_object_id.setdefault(object_id, set()).add(perm)
115         return perms_by_object_id
116 
117     @synchronized
118     def get_authorized_principals(self, bound_permissions):
119         principals = set()
120         for obj_id, perm in bound_permissions:
121             principals |= self.get_object_permission_principals(obj_id, perm)
122         return principals
123 
124     @synchronized
125     def get_objects_permissions(self, objects_ids, permissions=None):
126         result = []
127         for object_id in objects_ids:
128             if permissions is None:
129                 aces = [k for k in self._store.keys() if k.startswith(f"permission:{object_id}:")]
130             else:
131                 aces = [f"permission:{object_id}:{permission}" for permission in permissions]
132             perms = {}
133             for ace in aces:
134                 # Should work with 'permission:/url/id:object:create'.
135                 permission = ace.split(":", 2)[2]
136                 perms[permission] = set(self._store[ace])
137             result.append(perms)
138         return result
139 
140     @synchronized
141     def replace_object_permissions(self, object_id, permissions):
142         for permission, principals in permissions.items():
143             permission_key = f"permission:{object_id}:{permission}"
144             if permission_key in self._store and len(principals) == 0:
145                 del self._store[permission_key]
146             elif principals:
147                 self._store[permission_key] = set(principals)
148         return permissions
149 
150     @synchronized
151     def delete_object_permissions(self, *object_id_list):
152         to_delete = []
153         for key in self._store.keys():
154             object_id = key.split(":")[1]
155             for pattern in object_id_list:
156                 regexp = re.compile(f"^{pattern.replace('*', '.*')}$")
157                 if regexp.match(object_id):
158                     to_delete.append(key)
159         for k in to_delete:
160             del self._store[k]
161 
162 
163 def load_from_config(config):
164     return Permission()
165
```
--- 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/core/permission/memory.py b/kinto/core/permission/memory.py
--- a/kinto/core/permission/memory.py
+++ b/kinto/core/permission/memory.py
@@ -48,7 +48,9 @@
 
     @synchronized
     def remove_principal(self, principal):
-        for user_principals in self._store.values():
+        for key, user_principals in self._store.items():
+            if not key.startswith("user:"):
+                continue
             try:
                 user_principals.remove(principal)
             except KeyError:

{"golden_diff": "diff --git a/kinto/core/permission/memory.py b/kinto/core/permission/memory.py\n--- a/kinto/core/permission/memory.py\n+++ b/kinto/core/permission/memory.py\n@@ -48,7 +48,9 @@\n \n     @synchronized\n     def remove_principal(self, principal):\n-        for user_principals in self._store.values():\n+        for key, user_principals in self._store.items():\n+            if not key.startswith(\"user:\"):\n+                continue\n             try:\n                 user_principals.remove(principal)\n             except KeyError:\n", "issue": "Memory permission backend implementation of remove_principal() is wrong\nAccording to the `PermissionBase` docstring, `remove_principal` is supposed to `Remove a principal from every user`. In other words, `remove_principal(principal)` is equivalent to `remove_user_principal(user_id, principal) for user_id in all_possible_user_ids`. However, the current implementation stores all permissions of all kinds in one hash table, and removes the principal from permissions of non-user things as well.\n", "before_files": [{"content": "import re\n\nfrom kinto.core.decorators import synchronized\nfrom kinto.core.permission import PermissionBase\n\n\nclass Permission(PermissionBase):\n    \"\"\"Permission backend implementation in local process memory.\n\n    Enable in configuration::\n\n        kinto.permission_backend = kinto.core.permission.memory\n\n    :noindex:\n    \"\"\"\n\n    def __init__(self, *args, **kwargs):\n        super().__init__(*args, **kwargs)\n        self.flush()\n\n    def initialize_schema(self, dry_run=False):\n        # Nothing to do.\n        pass\n\n    def flush(self):\n        self._store = {}\n\n    @synchronized\n    def add_user_principal(self, user_id, principal):\n        user_key = f\"user:{user_id}\"\n        user_principals = self._store.get(user_key, set())\n        user_principals.add(principal)\n        self._store[user_key] = user_principals\n\n    @synchronized\n    def remove_user_principal(self, user_id, principal):\n        user_key = f\"user:{user_id}\"\n        user_principals = self._store.get(user_key, set())\n        try:\n            user_principals.remove(principal)\n        except KeyError:\n            pass\n        if len(user_principals) == 0:\n            if user_key in self._store:\n                del self._store[user_key]\n        else:\n            self._store[user_key] = user_principals\n\n    @synchronized\n    def remove_principal(self, principal):\n        for user_principals in self._store.values():\n            try:\n                user_principals.remove(principal)\n            except KeyError:\n                pass\n\n    @synchronized\n    def get_user_principals(self, user_id):\n        # Fetch the groups the user is in.\n        user_key = f\"user:{user_id}\"\n        members = self._store.get(user_key, set())\n        # Fetch the groups system.Authenticated is in.\n        group_authenticated = self._store.get(\"user:system.Authenticated\", set())\n        return members | group_authenticated\n\n    @synchronized\n    def add_principal_to_ace(self, object_id, permission, principal):\n        permission_key = f\"permission:{object_id}:{permission}\"\n        object_permission_principals = self._store.get(permission_key, set())\n        object_permission_principals.add(principal)\n        self._store[permission_key] = object_permission_principals\n\n    @synchronized\n    def remove_principal_from_ace(self, object_id, permission, principal):\n        permission_key = f\"permission:{object_id}:{permission}\"\n        object_permission_principals = self._store.get(permission_key, set())\n        try:\n            object_permission_principals.remove(principal)\n        except KeyError:\n            pass\n        if len(object_permission_principals) == 0:\n            if permission_key in self._store:\n                del self._store[permission_key]\n        else:\n            self._store[permission_key] = object_permission_principals\n\n    @synchronized\n    def get_object_permission_principals(self, object_id, permission):\n        permission_key = f\"permission:{object_id}:{permission}\"\n        members = self._store.get(permission_key, set())\n        return members\n\n    @synchronized\n    def get_accessible_objects(self, principals, bound_permissions=None, with_children=True):\n        principals = set(principals)\n        candidates = []\n        if bound_permissions is None:\n            for key, value in self._store.items():\n                _, object_id, permission = key.split(\":\", 2)\n                candidates.append((object_id, permission, value))\n        else:\n            for pattern, perm in bound_permissions:\n                id_match = \".*\" if with_children else \"[^/]+\"\n                regexp = re.compile(f\"^{pattern.replace('*', id_match)}$\")\n                for key, value in self._store.items():\n                    if key.endswith(perm):\n                        object_id = key.split(\":\")[1]\n                        if regexp.match(object_id):\n                            candidates.append((object_id, perm, value))\n\n        perms_by_object_id = {}\n        for (object_id, perm, value) in candidates:\n            if len(principals & value) > 0:\n                perms_by_object_id.setdefault(object_id, set()).add(perm)\n        return perms_by_object_id\n\n    @synchronized\n    def get_authorized_principals(self, bound_permissions):\n        principals = set()\n        for obj_id, perm in bound_permissions:\n            principals |= self.get_object_permission_principals(obj_id, perm)\n        return principals\n\n    @synchronized\n    def get_objects_permissions(self, objects_ids, permissions=None):\n        result = []\n        for object_id in objects_ids:\n            if permissions is None:\n                aces = [k for k in self._store.keys() if k.startswith(f\"permission:{object_id}:\")]\n            else:\n                aces = [f\"permission:{object_id}:{permission}\" for permission in permissions]\n            perms = {}\n            for ace in aces:\n                # Should work with 'permission:/url/id:object:create'.\n                permission = ace.split(\":\", 2)[2]\n                perms[permission] = set(self._store[ace])\n            result.append(perms)\n        return result\n\n    @synchronized\n    def replace_object_permissions(self, object_id, permissions):\n        for permission, principals in permissions.items():\n            permission_key = f\"permission:{object_id}:{permission}\"\n            if permission_key in self._store and len(principals) == 0:\n                del self._store[permission_key]\n            elif principals:\n                self._store[permission_key] = set(principals)\n        return permissions\n\n    @synchronized\n    def delete_object_permissions(self, *object_id_list):\n        to_delete = []\n        for key in self._store.keys():\n            object_id = key.split(\":\")[1]\n            for pattern in object_id_list:\n                regexp = re.compile(f\"^{pattern.replace('*', '.*')}$\")\n                if regexp.match(object_id):\n                    to_delete.append(key)\n        for k in to_delete:\n            del self._store[k]\n\n\ndef load_from_config(config):\n    return Permission()\n", "path": "kinto/core/permission/memory.py"}], "after_files": [{"content": "import re\n\nfrom kinto.core.decorators import synchronized\nfrom kinto.core.permission import PermissionBase\n\n\nclass Permission(PermissionBase):\n    \"\"\"Permission backend implementation in local process memory.\n\n    Enable in configuration::\n\n        kinto.permission_backend = kinto.core.permission.memory\n\n    :noindex:\n    \"\"\"\n\n    def __init__(self, *args, **kwargs):\n        super().__init__(*args, **kwargs)\n        self.flush()\n\n    def initialize_schema(self, dry_run=False):\n        # Nothing to do.\n        pass\n\n    def flush(self):\n        self._store = {}\n\n    @synchronized\n    def add_user_principal(self, user_id, principal):\n        user_key = f\"user:{user_id}\"\n        user_principals = self._store.get(user_key, set())\n        user_principals.add(principal)\n        self._store[user_key] = user_principals\n\n    @synchronized\n    def remove_user_principal(self, user_id, principal):\n        user_key = f\"user:{user_id}\"\n        user_principals = self._store.get(user_key, set())\n        try:\n            user_principals.remove(principal)\n        except KeyError:\n            pass\n        if len(user_principals) == 0:\n            if user_key in self._store:\n                del self._store[user_key]\n        else:\n            self._store[user_key] = user_principals\n\n    @synchronized\n    def remove_principal(self, principal):\n        for key, user_principals in self._store.items():\n            if not key.startswith(\"user:\"):\n                continue\n            try:\n                user_principals.remove(principal)\n            except KeyError:\n                pass\n\n    @synchronized\n    def get_user_principals(self, user_id):\n        # Fetch the groups the user is in.\n        user_key = f\"user:{user_id}\"\n        members = self._store.get(user_key, set())\n        # Fetch the groups system.Authenticated is in.\n        group_authenticated = self._store.get(\"user:system.Authenticated\", set())\n        return members | group_authenticated\n\n    @synchronized\n    def add_principal_to_ace(self, object_id, permission, principal):\n        permission_key = f\"permission:{object_id}:{permission}\"\n        object_permission_principals = self._store.get(permission_key, set())\n        object_permission_principals.add(principal)\n        self._store[permission_key] = object_permission_principals\n\n    @synchronized\n    def remove_principal_from_ace(self, object_id, permission, principal):\n        permission_key = f\"permission:{object_id}:{permission}\"\n        object_permission_principals = self._store.get(permission_key, set())\n        try:\n            object_permission_principals.remove(principal)\n        except KeyError:\n            pass\n        if len(object_permission_principals) == 0:\n            if permission_key in self._store:\n                del self._store[permission_key]\n        else:\n            self._store[permission_key] = object_permission_principals\n\n    @synchronized\n    def get_object_permission_principals(self, object_id, permission):\n        permission_key = f\"permission:{object_id}:{permission}\"\n        members = self._store.get(permission_key, set())\n        return members\n\n    @synchronized\n    def get_accessible_objects(self, principals, bound_permissions=None, with_children=True):\n        principals = set(principals)\n        candidates = []\n        if bound_permissions is None:\n            for key, value in self._store.items():\n                _, object_id, permission = key.split(\":\", 2)\n                candidates.append((object_id, permission, value))\n        else:\n            for pattern, perm in bound_permissions:\n                id_match = \".*\" if with_children else \"[^/]+\"\n                regexp = re.compile(f\"^{pattern.replace('*', id_match)}$\")\n                for key, value in self._store.items():\n                    if key.endswith(perm):\n                        object_id = key.split(\":\")[1]\n                        if regexp.match(object_id):\n                            candidates.append((object_id, perm, value))\n\n        perms_by_object_id = {}\n        for (object_id, perm, value) in candidates:\n            if len(principals & value) > 0:\n                perms_by_object_id.setdefault(object_id, set()).add(perm)\n        return perms_by_object_id\n\n    @synchronized\n    def get_authorized_principals(self, bound_permissions):\n        principals = set()\n        for obj_id, perm in bound_permissions:\n            principals |= self.get_object_permission_principals(obj_id, perm)\n        return principals\n\n    @synchronized\n    def get_objects_permissions(self, objects_ids, permissions=None):\n        result = []\n        for object_id in objects_ids:\n            if permissions is None:\n                aces = [k for k in self._store.keys() if k.startswith(f\"permission:{object_id}:\")]\n            else:\n                aces = [f\"permission:{object_id}:{permission}\" for permission in permissions]\n            perms = {}\n            for ace in aces:\n                # Should work with 'permission:/url/id:object:create'.\n                permission = ace.split(\":\", 2)[2]\n                perms[permission] = set(self._store[ace])\n            result.append(perms)\n        return result\n\n    @synchronized\n    def replace_object_permissions(self, object_id, permissions):\n        for permission, principals in permissions.items():\n            permission_key = f\"permission:{object_id}:{permission}\"\n            if permission_key in self._store and len(principals) == 0:\n                del self._store[permission_key]\n            elif principals:\n                self._store[permission_key] = set(principals)\n        return permissions\n\n    @synchronized\n    def delete_object_permissions(self, *object_id_list):\n        to_delete = []\n        for key in self._store.keys():\n            object_id = key.split(\":\")[1]\n            for pattern in object_id_list:\n                regexp = re.compile(f\"^{pattern.replace('*', '.*')}$\")\n                if regexp.match(object_id):\n                    to_delete.append(key)\n        for k in to_delete:\n            del self._store[k]\n\n\ndef load_from_config(config):\n    return Permission()\n", "path": "kinto/core/permission/memory.py"}]}