Browse Source

Changed ACL key algorithm for less collisions

Rafał Pitoń 11 years ago
parent
commit
82fa7c5464
2 changed files with 10 additions and 4 deletions
  1. 1 3
      docs/developers/acls.rst
  2. 9 1
      misago/users/models/user.py

+ 1 - 3
docs/developers/acls.rst

@@ -36,9 +36,7 @@ Because ACL framework is very flexible, different features can have different wa
 Permissions cache
 Permissions cache
 -----------------
 -----------------
 
 
-Construction of User's ACLs can be costful process, especially once you start installing extensions adding new features to your site. Because of this, Misago is not assinging ACLs to Users, but to combinations of roles.
-
-This means that if one User has roles 1, 3 and 4 assigned to account, but no rank, while other User has roles 1 and 4 assigned to account and role 3 assigned to his rank, both will have same ACL. This means that ACL has to be generated once and cached for use by others.
+Construction of User's ACLs can be costful process, especially once you start installing extensions adding new features to your site. Because of this, Misago is not assinging ACLs to Users, but to combinations of roles. This means that each individual uses has own "ACL key", that allows Misago to associate this user roles with valid ACL cache.
 
 
 ACL's are cached in two places: in remote cache storage, for use between requests, and in thread memory, so you don't have to write your own caches and checks when you are checking multiple users ACL's during single request.
 ACL's are cached in two places: in remote cache storage, for use between requests, and in thread memory, so you don't have to write your own caches and checks when you are checking multiple users ACL's during single request.
 
 

+ 9 - 1
misago/users/models/user.py

@@ -274,18 +274,26 @@ class User(AbstractBaseUser, PermissionsMixin):
 
 
         for role in self.roles.all():
         for role in self.roles.all():
             roles_pks.append(role.pk)
             roles_pks.append(role.pk)
+            role.origin = self
             roles_dict[role.pk] = role
             roles_dict[role.pk] = role
 
 
         if self.rank:
         if self.rank:
             for role in self.rank.roles.all():
             for role in self.rank.roles.all():
                 if role.pk not in roles_pks:
                 if role.pk not in roles_pks:
+                    role.origin = self.rank
                     roles_pks.append(role.pk)
                     roles_pks.append(role.pk)
                     roles_dict[role.pk] = role
                     roles_dict[role.pk] = role
 
 
         return [roles_dict[r] for r in sorted(roles_pks)]
         return [roles_dict[r] for r in sorted(roles_pks)]
 
 
     def update_acl_key(self):
     def update_acl_key(self):
-        roles_pks = [unicode(r.pk) for r in self.get_roles()]
+        roles_pks = []
+        for role in self.get_roles():
+            if role.origin == 'self':
+                roles_pks.append('u%s' % role.pk)
+            else:
+                roles_pks.append('%s:%s' % (self.rank.pk, role.pk))
+
         self.acl_key = md5(','.join(roles_pks)).hexdigest()[:12]
         self.acl_key = md5(','.join(roles_pks)).hexdigest()[:12]