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)
Beispiel #3
0
    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)
Beispiel #4
0
    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"}')
Beispiel #7
0
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']))