def test_get_prep_value_convert(self): field = StringSetField('testing') self.assertEqual(field.get_prep_value(set(["A", "B", "C"])), '["A", "B", "C"]') with self.assertRaises(ValueError): field.get_prep_value(5)
def test_get_prep_value_convert(self): field = StringSetField('testing') self.assertEqual(field.get_prep_value(set(["A", "B", "C"])), 'A,B,C') self.assertEqual(field.get_prep_value(set(["C", "B", "A"])), 'A,B,C') with self.assertRaises(ValueError): field.get_prep_value(5)
def test_to_python_already_done(self): field = StringSetField('testing') self.assertEqual(field.to_python([]), set()) self.assertEqual(field.to_python(set(["A","B","C"])), set(['A', 'B', 'C'])) with self.assertRaises(ValueError): field.to_python(4) with self.assertRaises(ValueError): field.to_python([1, 2, 3]) with self.assertRaises(ValueError): field.to_python(None)
def test_is_string_set(self): field = StringSetField('testing') self.assertTrue(field.is_string_set(set([]))) self.assertTrue(field.is_string_set(set(["hello", "goodbye"]))) self.assertFalse(field.is_string_set(["A", "B"])) self.assertFalse(field.is_string_set("boo")) self.assertFalse(field.is_string_set(3)) self.assertFalse(field.is_string_set('["A", "B"]'))
def test_to_python_convert(self): field = StringSetField('testing') # This that are legitimate to store in the DB self.assertEqual(field.to_python('[]'), set()) self.assertEqual(field.to_python('["A","B","C"]'), set(['A', 'B', 'C'])) # Erroneous values that should never end up in the database with self.assertRaises(ValueError): field.to_python('[1,2,3]') with self.assertRaises(ValueError): field.to_python('"hello"') with self.assertRaises(ValueError): field.to_python('{"hi": "foo"}')
class Role(ValidatingModel, models.Model): """ A PRBAC role, aka a Role parameterized by a set of named variables. Roles also model privileges: They differ only in that privileges only refer to real-world consequences when all parameters are instantiated. """ PRIVILEGES_BY_SLUG = "DJANGO_PRBAC_PRIVELEGES" ROLES_BY_ID = "DJANGO_PRBAC_ROLES" _default_instance = lambda s: None # Databaes fields # --------------- slug = models.CharField( max_length=256, help_text='The formal slug for this role, which should be unique', unique=True, ) name = models.CharField( max_length=256, help_text= 'The friendly name for this role to present to users; this need not be unique.', ) description = models.TextField( help_text= 'A long-form description of the intended semantics of this role.', blank=True, default='', ) parameters = StringSetField( help_text= 'A set of strings which are the parameters for this role. Entered as a JSON list.', blank=True, default=set, ) class Meta: app_label = 'django_prbac' # Methods # ------- @classmethod def get_cache(cls): try: cache = cls.cache except AttributeError: timeout = getattr(settings, 'DJANGO_PRBAC_CACHE_TIMEOUT', 60) cache = cls.cache = DictCache(timeout) return cache @classmethod def update_cache(cls): roles = cls.objects.prefetch_related('memberships_granted').all() roles = {role.id: role for role in roles} for role in roles.values(): role._granted_privileges = privileges = [] # Prevent extra queries by manually linking grants and roles # because Django 1.6 isn't smart enough to do this for us for membership in role.memberships_granted.all(): membership.to_role = roles[membership.to_role_id] membership.from_role = roles[membership.from_role_id] privileges.append(membership.instantiated_to_role({})) cache = cls.get_cache() cache.set(cls.ROLES_BY_ID, roles) cache.set(cls.PRIVILEGES_BY_SLUG, {role.slug: role.instantiate({}) for role in roles.values()}) @classmethod def get_privilege(cls, slug, assignment=None): """ Optimized lookup of privilege by slug This optimization is specifically geared toward cases where `assignments` is empty. """ cache = cls.get_cache() if cache.disabled: roles = Role.objects.filter(slug=slug) if roles: return roles[0].instantiate(assignment or {}) return None privileges = cache.get(cls.PRIVILEGES_BY_SLUG) if privileges is None: cls.update_cache() privileges = cache.get(cls.PRIVILEGES_BY_SLUG) privilege = privileges.get(slug) if privilege is None: return None if assignment: return privilege.role.instantiate(assignment) return privilege def get_cached_role(self): """ Optimized lookup of role by id """ cache = self.get_cache() if cache.disabled: return self roles = cache.get(self.ROLES_BY_ID) if roles is None or self.id not in roles: self.update_cache() roles = cache.get(self.ROLES_BY_ID) return roles.get(self.id, self) def get_privileges(self, assignment): if not assignment: try: return self._granted_privileges except AttributeError: pass return [ membership.instantiated_to_role(assignment) for membership in self.memberships_granted.all() ] def instantiate(self, assignment): """ An instantiation of this role with some parameters fixed via the provided assignments. """ if assignment: filtered_assignment = { key: assignment[key] for key in self.parameters & set(assignment.keys()) } else: value = self._default_instance() if value is not None: return value filtered_assignment = assignment value = RoleInstance(self, filtered_assignment) if not filtered_assignment: self._default_instance = weakref.ref(value) return value def has_privilege(self, privilege): """ Shortcut for checking privileges easily for roles with no params (aka probably users) """ role = self.get_cached_role() return role.instantiate({}).has_privilege(privilege) @property def assignment(self): """ A Role stored in the database always has an empty assignment. """ return {} def __repr__(self): return 'Role(%r, parameters=%r)' % (self.slug, self.parameters) def __str__(self): return '%s (%s)' % (self.name, self.slug)
def test_to_python_convert(self): field = StringSetField('testing') # This that are legitimate to store in the DB self.assertEqual(field.to_python(''), set()) self.assertEqual(field.to_python('"A","B","C"'), set(['A', 'B', 'C']))