This repository has been archived by the owner on Oct 17, 2019. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
permissions.py
89 lines (74 loc) · 3.4 KB
/
permissions.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
# NONE OF THESE ARE ACTUALLY PULLED FROM HERE YET, DO NOT CHANGE
avatar_reset = 'avatar.reset'
ban_watch = 'ban.watch'
class PermissionHolderMixin(object):
"""
This mixin should be inherited by objects that holds permissions.
"""
def get_permissions(self):
"""
This method is the only one that needs to be implemented by permission holders. Values are not cached, this
needs to be managed by the implementation.
:return: A list of permissions the holder has access to.
"""
raise NotImplementedError("Classes using PermissionHolderMixin should implement get_permissions(self)")
def has_permission(self, permission):
"""
Check if the holder has access to the supplied permission. Gets permissions by calling self.get_permissions().
:param permission:
:return: True if the holder has access to the permission, false if not.
"""
node = unicode(permission)
permissions = self.get_permissions()
# Start off by checking for negative permissions.
for permission in permissions:
if permission.startswith(u"-"):
if permission.endswith(u"*"):
if node.startswith(permission[1:-1]):
return False
else:
if permission[1:] == node:
return False
# Then check positive permissions.
for permission in permissions:
if permission.endswith(u"*"):
if node.startswith(permission[:-1]):
return True
else:
if permission == node:
return True
# We didn't find the role.
return False
def can(self, alias):
"""
This method will look up the supplied alias in 'permissions.role_bindings' and make sure the holder has all the
permissions in it.
:param alias: The alias to look up.
:return: True if the holder has all permissions in the alias, false if not.
"""
roles = role_bindings[alias]
for role in roles:
if not self.has_permission(role):
return False
return True
# Not sure if this is a good idea, I am welcome to input.
# The idea is that instead of checking for permission nodes everywhere in the code (quickly turns into a mess, we need
# to look around the code to check what permission nodes to use where), we define all nodes in this file. Instead of
# giving templates access to this file directly, they can use aliases (binds a role -> an action that the ui needs to
# do). Instead of doing {% if current_user.has_permission('alt.view') %}, we can now do
# {% if current_user.can("show alts"). As I said previously, I am not sure if this makes sense to do, but I will try
# it out.
class RoleBindingManager(dict):
def add(self, alias, roles):
self[alias] = roles
role_bindings = RoleBindingManager()
# Alts
role_bindings.add("view alts", ['alt.view'])
role_bindings.add("graph alts", ['alt.view'])
# Bans and Appeals
role_bindings.add("create bans", ['ban.create'])
role_bindings.add("manage ban appeals", ['ban.appeal.manage'])
role_bindings.add("reply to ban appeals", ['ban.appeal.manage.reply'])
role_bindings.add("edit appeal replies", ['ban.appeal.manage.edit_reply'])
role_bindings.add("watch bans", [ban_watch])
role_bindings.add("edit ban reasons", ['ban.edit'])