3 from collections
import defaultdict
6 class Predicate(object):
8 Wrapper pour une fonction ``f(user, obj, cls)``.
10 Le paramètre ``user`` est l'utilisateur pour lequel la permission est testée.
12 Si le prédicat est testé sur un seul objet, cet objet est passé dans
13 le paramètre ``obj`` et le paramètre ``cls`` est ``None``. Inversement,
14 si le prédicat sert à filtrer un queryset, le modèle du queryset est
15 passé dans le paramètre ``cls`` et le paramètre ``obj`` est ``None``.
17 La fonction peut retourner un booléen ou un objet ``Q``. Un booléen
18 indique si le test a passé ou pas. Un objet ``Q`` indique les filtres à
19 appliquer pour ne garder que les objets qui passent le test. Si un objet
20 ``Q`` est retourné lors d'un test sur un seul objet, le test retournera
21 un booléen indiquant si l'objet satisfait au filtre.
23 Les prédicats peuvent être combinés à l'aide des opérateurs booléens
24 ``&``, ``|`` et ``~``.
27 def __init__(self
, func_or_value
):
29 On peut initialiser un prédicat avec une fonction ayant la signature
30 ``f(user, obj, cls)`` ou avec une valeur constante.
32 if callable(func_or_value
):
33 self
.func
= func_or_value
35 self
.func
= lambda user
, obj
, cls
: func_or_value
37 def __call__(self
, user
, obj
=None, cls
=None):
39 Appelle la fonction encapsulée.
41 return self
.func(user
, obj
, cls
)
43 def __and__(self
, other
):
44 def func(user
, obj
, cls
):
45 my_result
= self(user
, obj
, cls
)
46 if my_result
is False:
48 other_result
= other(user
, obj
, cls
)
51 elif other_result
is True:
54 return my_result
& other_result
55 return Predicate(func
)
57 def __or__(self
, other
):
58 def func(user
, obj
, cls
):
59 my_result
= self(user
, obj
, cls
)
62 other_result
= other(user
, obj
, cls
)
63 if my_result
is False:
65 elif other_result
is False:
68 return my_result | other_result
69 return Predicate(func
)
72 def func(user
, obj
, cls
):
73 result
= self(user
, obj
, cls
)
74 if isinstance(result
, bool):
78 return Predicate(func
)
83 def __init__(self
, allow_default
=None, deny_default
=None):
84 self
.allow_rules
= defaultdict(lambda: allow_default
or Predicate(False))
85 self
.deny_rules
= defaultdict(lambda: deny_default
or Predicate(False))
87 def allow(self
, perm
, cls
, predicate
):
88 if not isinstance(predicate
, Predicate
):
89 raise TypeError("the third argument to allow() must be a Predicate")
90 self
.allow_rules
[(perm
, cls
)] |
= predicate
92 def deny(self
, perm
, cls
, predicate
):
93 if not isinstance(predicate
, Predicate
):
94 raise TypeError("the third argument to deny() must be a Predicate")
95 self
.deny_rules
[(perm
, cls
)] |
= predicate
97 def predicate_for_perm(self
, perm
, cls
):
98 return self
.allow_rules
[(perm
, cls
)] & ~self
.deny_rules
[(perm
, cls
)]
100 def user_has_perm(self
, user
, perm
, obj
):
101 result
= self
.predicate_for_perm(perm
, obj
.__class__
)(user
, obj
)
102 if isinstance(result
, bool):
105 return obj
._default_manager
.filter(pk
=obj
.pk
).filter(result
).exists()
107 def filter_queryset(self
, user
, perm
, queryset
):
108 result
= self
.predicate_for_perm(perm
, queryset
.model
)(user
, cls
=queryset
.model
)
111 elif result
is False:
112 return queryset
.none()
114 return queryset
.filter(result
)
117 self
.allow_rules
.clear()
118 self
.deny_rules
.clear()
121 class AuthenticationBackend(object):
122 supports_anonymous_user
= True
123 supports_inactive_user
= True
124 supports_object_permissions
= True
127 def has_perm(self
, user
, perm
, obj
=None):
128 if self
.rules
is None or obj
is None:
130 return self
.rules
.user_has_perm(user
, perm
, obj
)
132 def authenticate(self
, username
=None, password
=None):
133 # We don't authenticate
136 def get_user(self
, user_id
):
137 # We don't authenticate