Completed
Pull Request — master (#24)
by
unknown
56s
created

User.is_in_cluster()   A

Complexity

Conditions 1

Size

Total Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2
Metric Value
cc 1
dl 0
loc 2
ccs 0
cts 1
cp 0
crap 2
rs 10
1
from django.db import models
2
from django.db.models import Q
3
4
from django.contrib.auth.models import AbstractBaseUser, BaseUserManager
5
from dry_rest_permissions.generics import allow_staff_or_superuser
6
7
8
class UserManager(BaseUserManager):
9
    def get_queryset(self):
10
        return super().get_queryset().prefetch_related('clusters')
11
12
    def create_user(self, email, lastname, firstname, password=None):
13
        """
14
        Creates and saves a User with the given email, lastname, firstname and password
15
        TODO - Generate a unique username.
16
        """
17
        if not email:
18
            raise ValueError('Users must have an email address')
19
20
        # username = email # TODO - Generate unique username
21
22
        user = self.model(
23
            email=self.normalize_email(email),
24
            lastname=lastname,
25
            firstname=firstname
26
        )
27
28
        user.set_password(password)
29
        user.save()
30
        return user
31
32
    def create_superuser(self, email, lastname, firstname, password):
33
        """
34
        Creates and saves a superuser with the given email, lastname, firstname and password.
35
        """
36
        user = self.create_user(email, lastname, firstname, password)
37
        user.is_superuser = True
38
        user.is_staff = True
39
        user.save()
40
        return user
41
42
43
class User(AbstractBaseUser):
44
    """
45
    User are identified by their email. Lastname and firstname are required.
46
    """
47
    email = models.EmailField(max_length=254, unique=True)
48
    lastname = models.CharField(max_length=255)
49
    firstname = models.CharField(max_length=128)
50
    # username = models.CharField(max_length=128, unique=True) # TODO - Add unique username for frontend URLs
51
    phone = models.CharField(max_length=20, blank=True)
52
    photo = models.OneToOneField('sigma_files.Image', blank=True, null=True, on_delete=models.SET_NULL)
53
54
    is_active = models.BooleanField(default=True)
55
    last_modified = models.DateTimeField(auto_now=True)
56
    join_date = models.DateTimeField(auto_now_add=True)
57
58
    is_superuser = models.BooleanField(default=False)
59
    is_staff = models.BooleanField(default=False)
60
61
    clusters = models.ManyToManyField('Cluster', related_name="cluster_users") # users should be members of at least one cluster
62
63
    objects = UserManager()
64
65 1
    invited_to_groups = models.ManyToManyField('Group', blank=True, related_name="invited_users");
66
    groups = models.ManyToManyField('Group', through='GroupMember', related_name='users')
67
68
    # Related fields:
69
    #   - memberships (model GroupMember)
70
71
    USERNAME_FIELD = 'email'
72
    REQUIRED_FIELDS = ['lastname', 'firstname']
73
74
    def __str__(self):
75
        return self.email
76
77
    def get_full_name(self):
78
        return "{} {}".format(self.lastname, self.firstname)
79
80
    def get_short_name(self):
81
        return self.email
82
83
    def is_sigma_admin(self):
84 1
        return self.is_staff or self.is_superuser
85
86
    def is_in_cluster(self, cluster):
87
        return cluster in self.clusters.all()
88
89
    def has_common_cluster(self, user):
90
        """
91 1
        Return True iff self has a cluster in common with user.
92
        """
93
        return len(set(self.clusters.all().values_list('id', flat=True)).intersection(user.clusters.all().values_list('id', flat=True))) > 0
94
95
    def has_common_group(self, user):
96
        """
97
        Return True iff self has a group in common with user.
98
        """
99 1
        return len(set(self.memberships.all().values_list('group', flat=True)).intersection(user.memberships.all().values_list('group', flat=True))) > 0
100
101
    def get_group_membership(self, group):
102
        from sigma_core.models.group_member import GroupMember
103
        from sigma_core.models.group import Group
104
        try:
105
            return self.memberships.get(group=group)
106
        except GroupMember.DoesNotExist:
107 1
            return None
108
109
    def is_group_member(self, g):
110
        from sigma_core.models.group_member import GroupMember
111
        mem = self.get_group_membership(g)
112
        return mem is not None and mem.is_accepted()
113 1
114
    def can_invite(self, group):
115
        from sigma_core.models.group_member import GroupMember
116
        mem = self.get_group_membership(group)
117
        return mem is not None and mem.perm_rank >= group.req_rank_invite
118
119
    def can_accept_join_requests(self, group):
120 1
        from sigma_core.models.group_member import GroupMember
121
        if self.is_sigma_admin():
122
            return True
123
        mem = self.get_group_membership(group)
124
        return mem is not None and mem.perm_rank >= group.req_rank_accept_join_requests
125
126
    def can_modify_group_infos(self, group):
127
        from sigma_core.models.group_member import GroupMember
128
        mem = self.get_group_membership(group)
129
        return mem is not None and mem.perm_rank >= group.req_rank_modify_group_infos
130
131
    def has_group_admin_perm(self, group):
132
        from sigma_core.models.group_member import GroupMember
133
        from sigma_core.models.group import Group
134
        if self.is_sigma_admin():
135
            return True
136
        mem = self.get_group_membership(group)
137
        return mem is not None and mem.perm_rank == Group.ADMINISTRATOR_RANK
138
139
    def is_invited_to_group_id(self, groupId):
140
        return self.invited_to_groups.filter(pk=groupId).exists()
141
142
    def get_groups_with_confirmed_membership(self):
143
        from sigma_core.models.group_member import GroupMember
144
        return GroupMember.objects.filter(Q(user=self) & Q(perm_rank__gte=1)).values_list('group', flat=True)
145
146
    ###############
147
    # Permissions #
148
    ###############
149
150
    # Perms for admin site
151
    def has_perm(self, perm, obj=None):
152
        return True
153
154
    def has_module_perms(self, app_label):
155
        return True
156
    # End of admin site permissions
157
158
    @staticmethod
159
    def has_read_permission(request):
160
        """
161
        Only authenticated users can retrieve an users list.
162
        """
163
        return True
164
165
    @allow_staff_or_superuser
166
    def has_object_read_permission(self, request):
167
        """
168
        One can see an user if one is in the same cluster, or is member of a group in common.
169
        """
170
        if request.user.id == self.id:
171
            return True
172
        if request.user.has_common_cluster(self):
173
            return True
174
        if request.user.has_common_group(self):
175
            return True
176
        return False
177
178
    @staticmethod
179
    def has_write_permission(request):
180
        """
181
        Everybody can edit or create users, but with certain restraints specified in below functions.
182
        By the way, everybody can change one's password or reset it.
183
        """
184
        return True
185
186
    @staticmethod
187
    @allow_staff_or_superuser
188
    def has_create_permission(request):
189
        """
190
        Only Cluster admins can create users, inside their cluster
191
        """
192
        return True
193
194
    def has_object_write_permission(self, request):
195
        """
196
        Nobody has all write permissions on an user (especially, nobody can delete an user).
197
        """
198
        return False
199
200
    @allow_staff_or_superuser
201
    def has_object_update_permission(self, request):
202
        """
203
        Only Sigma admin and oneself can edit an user.
204
        """
205
        return request.user.id == self.id
206