1
# Python
2 0
import threading
3 0
import re
4

5
# Django
6 0
from django.db import models
7 0
from django.contrib.contenttypes.models import ContentType
8 0
from django.contrib.contenttypes.fields import GenericForeignKey
9 0
from django.utils.translation import ugettext_lazy as _
10

11
# CyBorgBackup
12 0
from cyborgbackup.api.versioning import reverse
13 0
from django.contrib.auth.models import User # noqa
14 0
from cyborgbackup.main.models.base import * # noqa
15

16 0
__all__ = [
17
    'Role',
18
    'batch_role_ancestor_rebuilding',
19
    'get_roles_on_resource',
20
    'ROLE_SINGLETON_SYSTEM_ADMINISTRATOR',
21
    'ROLE_SINGLETON_SYSTEM_AUDITOR',
22
    'role_summary_fields_generator'
23
]
24

25 0
ROLE_SINGLETON_SYSTEM_ADMINISTRATOR = 'system_administrator'
26 0
ROLE_SINGLETON_SYSTEM_AUDITOR = 'system_auditor'
27

28 0
role_names = {
29
    'system_administrator': _('System Administrator'),
30
    'system_auditor': _('System Auditor'),
31
    'admin_role': _('Admin'),
32
    'client_admin_role': _('Client Admin'),
33
    'policy_admin_role': _('Policy Admin'),
34
    'schedules_admin_role': _('Schedules Admin'),
35
    'auditor_role': _('Auditor'),
36
    'execute_role': _('Execute'),
37
    'member_role': _('Member'),
38
    'read_role': _('Read'),
39
    'update_role': _('Update'),
40
    'use_role': _('Use'),
41
}
42

43 0
role_descriptions = {
44
    'system_administrator': _('Can manage all aspects of the system'),
45
    'system_auditor': _('Can view all settings on the system'),
46
    'admin_role': _('Can manage all aspects of the %s'),
47
    'client_admin_role': _('Can manage all clients of the %s'),
48
    'policy_admin_role': _('Can manage all policies of the %s'),
49
    'schedules_admin_role': _('Can manage all schedules of the %s'),
50
    'auditor_role': _('Can view all settings for the %s'),
51
    'execute_role': {
52
        'organization': _('May run any executable resources in the organization'),
53
        'default': _('May run the %s'),
54
    },
55
    'member_role': _('User is a member of the %s'),
56
    'read_role': _('May view settings for the %s'),
57
    'update_role': _('May update project or inventory or group using the configured source update system'),
58
    'use_role': _('Can use the %s in a job template'),
59
}
60

61

62 0
tls = threading.local()  # thread local storage
63

64

65 0
def check_singleton(func):
66
    '''
67
    check_singleton is a decorator that checks if a user given
68
    to a `visible_roles` method is in either of our singleton roles (Admin, Auditor)
69
    and if so, returns their full list of roles without filtering.
70
    '''
71 0
    def wrapper(*args, **kwargs):
72 0
        sys_admin = Role.singleton(ROLE_SINGLETON_SYSTEM_ADMINISTRATOR)
73 0
        sys_audit = Role.singleton(ROLE_SINGLETON_SYSTEM_AUDITOR)
74 0
        user = args[0]
75 0
        if user in sys_admin or user in sys_audit:
76 0
            if len(args) == 2:
77 0
                return args[1]
78 0
            return Role.objects.all()
79 0
        return func(*args, **kwargs)
80 0
    return wrapper
81

82

83 0
class Role(models.Model):
84
    '''
85
    Role model
86
    '''
87

88 0
    class Meta:
89 0
        app_label = 'main'
90 0
        verbose_name_plural = _('roles')
91 0
        db_table = 'main_rbac_roles'
92 0
        index_together = [
93
            ("content_type", "object_id")
94
        ]
95

96 0
    role_field = models.TextField(null=False)
97 0
    singleton_name = models.TextField(null=True, default=None, db_index=True, unique=True)
98 0
    parents = models.ManyToManyField('Role', related_name='children')
99 0
    implicit_parents = models.TextField(null=False, default='[]')
100 0
    members = models.ManyToManyField('auth.User', related_name='roles')
101 0
    content_type = models.ForeignKey(ContentType, null=True, default=None)
102 0
    object_id = models.PositiveIntegerField(null=True, default=None)
103 0
    content_object = GenericForeignKey('content_type', 'object_id')
104

105 0
    def __unicode__(self):
106 0
        if 'role_field' in self.__dict__:
107 0
            return u'%s-%s' % (self.name, self.pk)
108
        else:
109 0
            return u'%s-%s' % (self._meta.verbose_name, self.pk)
110

111 0
    def save(self, *args, **kwargs):
112 0
        super(Role, self).save(*args, **kwargs)
113

114 0
    def get_absolute_url(self, request=None):
115 0
        return reverse('api:role_detail', kwargs={'pk': self.pk}, request=request)
116

117 0
    def __contains__(self, accessor):
118 0
        if type(accessor) == User:
119 0
            return self.ancestors.filter(members=accessor).exists()
120 0
        elif accessor.__class__.__name__ == 'Team':
121 0
            return self.ancestors.filter(pk=accessor.member_role.id).exists()
122 0
        elif type(accessor) == Role:
123 0
            return self.ancestors.filter(pk=accessor).exists()
124
        else:
125 0
            accessor_type = ContentType.objects.get_for_model(accessor)
126 0
            roles = Role.objects.filter(content_type__pk=accessor_type.id,
127
                                        object_id=accessor.id)
128 0
            return self.ancestors.filter(pk__in=roles).exists()
129

130 0
    @property
131
    def name(self):
132
        global role_names
133 0
        return role_names[self.role_field]
134

135 0
    @property
136
    def description(self):
137
        global role_descriptions
138 0
        description = role_descriptions[self.role_field]
139 0
        content_type = self.content_type
140

141 0
        model_name = None
142 0
        if content_type:
143 0
            model = content_type.model_class()
144 0
            model_name = re.sub(r'([a-z])([A-Z])', r'\1 \2', model.__name__).lower()
145

146 0
        value = description
147 0
        if type(description) == dict:
148 0
            value = description.get(model_name)
149 0
            if value is None:
150 0
                value = description.get('default')
151

152 0
        if '%s' in value and content_type:
153 0
                    value = value % model_name
154

155 0
        return value
156

157 0
    @staticmethod
158
    def visible_roles(user):
159 0
        return Role.filter_visible_roles(user, Role.objects.all())
160

161 0
    @staticmethod
162
    def singleton(name):
163 0
        role, _ = Role.objects.get_or_create(singleton_name=name, role_field=name)
164 0
        return role
165

166 0
    def is_ancestor_of(self, role):
167 0
        return role.ancestors.filter(id=self.id).exists()
168

169 0
    def is_singleton(self):
170 0
        return self.singleton_name in [ROLE_SINGLETON_SYSTEM_ADMINISTRATOR, ROLE_SINGLETON_SYSTEM_AUDITOR]
171

172

173 0
def role_summary_fields_generator(content_object, role_field):
174
    global role_descriptions
175
    global role_names
176 0
    summary = {}
177 0
    description = role_descriptions[role_field]
178

179 0
    model_name = None
180 0
    content_type = ContentType.objects.get_for_model(content_object)
181 0
    if content_type:
182 0
        model = content_object.__class__
183 0
        model_name = re.sub(r'([a-z])([A-Z])', r'\1 \2', model.__name__).lower()
184

185 0
    value = description
186 0
    if type(description) == dict:
187 0
        value = None
188 0
        if model_name:
189 0
            value = description.get(model_name)
190 0
        if value is None:
191 0
            value = description.get('default')
192

193 0
    if '%s' in value and model_name:
194 0
        value = value % model_name
195

196 0
    summary['description'] = value
197 0
    summary['name'] = role_names[role_field]
198 0
    summary['id'] = getattr(content_object, '{}_id'.format(role_field))
199 0
    return summary
200

201

202 0
def get_roles_on_resource(resource, accessor):
203
    '''
204
    Returns a string list of the roles a accessor has for a given resource.
205
    An accessor can be either a User, Role, or an arbitrary resource that
206
    contains one or more Roles associated with it.
207
    '''
208

209 0
    if type(accessor) == User:
210 0
        roles = accessor.roles.all()
211 0
    elif type(accessor) == Role:
212 0
        roles = [accessor]
213
    else:
214 0
        accessor_type = ContentType.objects.get_for_model(accessor)
215 0
        roles = Role.objects.filter(content_type__pk=accessor_type.id,
216
                                    object_id=accessor.id)
217

218 0
    return [
219
        role_field for role_field in
220
        RoleAncestorEntry.objects.filter(
221
            ancestor__in=roles,
222
            content_type_id=ContentType.objects.get_for_model(resource).id,
223
            object_id=resource.id
224
        ).values_list('role_field', flat=True).distinct()
225
    ]

Read our documentation on viewing source code .

Loading