Completed
Pull Request — master (#20)
by
unknown
58s
created

Group.has_object_invite_permission()   A

Complexity

Conditions 1

Size

Total Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2
Metric Value
cc 1
dl 0
loc 3
ccs 0
cts 0
cp 0
crap 2
rs 10
1
from django.db import models
2
3
from dry_rest_permissions.generics import allow_staff_or_superuser
4
5
from sigma_core.models.custom_field import CustomField
6
from sigma_core.models.group_field import GroupField
7
8
9
class Group(models.Model):
10
    #########################
11
    # Constants and choices #
12
    #########################
13
    ADMINISTRATOR_RANK  = 10
14
15
    VIS_PUBLIC          = 'public'
16
    VIS_PRIVATE         = 'private'
17
    VISIBILITY_CHOICES = (
18
        (VIS_PUBLIC, 'Anyone can see the group'),
19
        (VIS_PRIVATE, 'Group is not visible')
20
    )
21
22
    TYPE_BASIC          = 'basic'
23
    TYPE_CURSUS         = 'cursus'
24
    TYPE_ASSO           = 'association'
25
    TYPE_PROMO          = 'school_promotion'
26
    TYPE_SCHOOL         = 'school'
27
    TYPE_CHOICES = (
28
        (TYPE_BASIC, 'Simple group'),
29
        (TYPE_CURSUS, 'Cursus or department'),
30
        (TYPE_ASSO, 'Association'),
31
        (TYPE_PROMO, 'School promotion'),
32
        (TYPE_SCHOOL, 'School')
33
    )
34
35
    ##########
36
    # Fields #
37
    ##########
38
    name = models.CharField(max_length=254)
39
    visibility = models.CharField(max_length=64, choices=VISIBILITY_CHOICES, default=VIS_PRIVATE)
40
    type = models.CharField(max_length=64, choices=TYPE_CHOICES, default=TYPE_BASIC)
41
42
    # The school responsible of the group in case of admin conflict (can be null for non-school-related groups)
43
    resp_school = models.ForeignKey('School', null=True, blank=True, on_delete=models.SET_NULL)
44
45
    # The permission a member has upon joining
46
    # A value of -1 means that no one can join the group.
47
    # A value of 0 means that anyone can request to join the group
48
    default_member_rank = models.SmallIntegerField(default=-1)
49
    # Invite new members on the group
50
    req_rank_invite = models.SmallIntegerField(default=1)
51
    # Remove a member from the group
52
    req_rank_kick = models.SmallIntegerField(default=ADMINISTRATOR_RANK)
53
    # Upgrade someone rank 0 to rank 1
54
    req_rank_accept_join_requests = models.SmallIntegerField(default=1)
55
    # Upgrade other users (up to $yourRank - 1)
56
    req_rank_promote = models.SmallIntegerField(default=ADMINISTRATOR_RANK)
57
    # Downgrade someone (to rank 1 minimum)
58
    req_rank_demote = models.SmallIntegerField(default=ADMINISTRATOR_RANK)
59
    # Modify group description
60
    req_rank_modify_group_infos = models.SmallIntegerField(default=ADMINISTRATOR_RANK)
61
62
    # Related fields:
63
    #   - invited_users (model User)
64
    #   - memberships (model UserGroup)
65
    #   - fields (model GroupField)
66
    # TODO: Determine whether 'memberships' fields needs to be retrieved every time or not...
67
68
    @property
69
    def subgroups(self):
70
        return [ga.subgroup for ga in self.subgroups.filter(validated=True).select_related('subgroup')]
71
72
    #################
73
    # Model methods #
74
    #################
75
    def can_anyone_join(self):
76
        return self.default_member_rank >= 0
77
78
    def __str__(self):
79
        return "%s (%s)" % (self.name, self.get_type_display())
80
81
    ###############
82
    # Permissions #
83
    ###############
84
85
    # Perms for admin site
86
    def has_perm(self, perm, obj=None):
87
        return True
88
89
    def has_module_perms(self, app_label):
90
        return True
91
92
    # DRY Permissions
93
    @staticmethod
94
    def has_read_permission(request):
95
        """
96
        All groups are visible by default.
97
        """
98
        return True
99
100
    def has_object_read_permission(self, request):
101
        """
102
        Public groups are visible by everybody. Private groups are only visible by members.
103
        """
104
        return self.visibility == Group.VIS_PUBLIC or request.user.is_group_member(self)
105
106
    @staticmethod
107
    def has_write_permission(request):
108
        return True
109
110
    @staticmethod
111
    @allow_staff_or_superuser
112
    def has_create_permission(request):
113
        """
114
        Everybody can create a private group. For other types, user must be school admin or sigma admin.
115
        """
116
        from sigma_core.models.school import School
117
        group_type = request.data.get('type', None)
118
        if group_type == Group.TYPE_BASIC:
119
            return True
120
121
        resp_school = request.data.get('resp_school', None)
122
        try:
123
            school = School.objects.get(pk=resp_school)
124
        except School.DoesNotExist:
125
            school = None
126
        return school is not None and request.user.has_group_admin_perm(school)
127
128
    @allow_staff_or_superuser
129
    def has_object_write_permission(self, request):
130
        return request.user.has_group_admin_perm(self)
131
132
    @allow_staff_or_superuser
133
    def has_object_update_permission(self, request):
134
        """
135
        Only group's admins and Sigma admins can edit a group.
136
        """
137
        return request.user.can_modify_group_infos(self)
138
139
140
class GroupAcknowledgment(models.Model):
141
    subgroup = models.ForeignKey(Group, related_name='group_parents')
142
    parent_group = models.ForeignKey(Group, related_name='subgroups')
143
    validated = models.BooleanField(default=False)
144
    created = models.DateTimeField(auto_now_add=True)
145
    updated = models.DateTimeField(auto_now=True)
146
147
    def __str__(self):
148
        if self.validated:
149
            return "Group %s acknowledged by Group %s" % (self.subgroup.__str__(), self.parent_group.__str__())
150
        else:
151
            return "Group %s awaiting for acknowledgment by Group %s since %s" % (self.subgroup.__str__(), self.parent_group.__str__(), self.created.strftime("%Y-%m-%d %H:%M"))
152