vos.py 5.27 KB
Newer Older
1
2
3
4
5
6
7

import logging
import re

from polymorphic.models import PolymorphicModel
from django.db import models

8
from feudal.backend.models.auth import OIDCConfig
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

LOGGER = logging.getLogger(__name__)


class EntitlementNameSpace(models.Model):

    name = models.CharField(
        max_length=200,
        unique=True,
    )

    @classmethod
    def get_name_space(cls, name):
        try:
            return cls.objects.get(
                name=name,
            )
        except cls.DoesNotExist:
            name_space = cls(
                name=name,
            )

            name_space.save()
            return name_space

    def __str__(self):
        return self.name


class VO(PolymorphicModel):

    name = models.CharField(
        max_length=200,
        unique=True,
    )

    idp = models.ForeignKey(
        OIDCConfig,
        related_name='vos',
        on_delete=models.CASCADE,
        blank=True,
        null=True,
    )

    description = models.TextField(
        max_length=1000,
        blank=True,
        null=True,
    )

    @property
    def pretty_name(self):
        return self.name

Lukas Burgey's avatar
Lukas Burgey committed
63
64
65
66
67
    @property
    def broker_exchange(self):
        # overridden in the implementations
        return None

68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
    def __str__(self):
        return self.name


class Group(VO):

    @classmethod
    def get_group(cls, name, idp=None):
        try:
            # searching only by name!
            group = cls.objects.get(
                name=name,
            )

            # use case: a client caused the group to be created
            # we apply the idp here
            if group.idp is None and idp is not None:
                group.idp = idp
                group.save()

            return group

        except cls.DoesNotExist:
            group = cls(
                name=name,
                idp=idp,
            )

            group.save()
            return group

    @property
    def pretty_name(self):
        return self.name

    @property
    def broker_exchange(self):
        return 'groups'

    def __str__(self):
        return 'VO-GROUP-'+self.name


class Entitlement(VO):

    name_space = models.ForeignKey(
        EntitlementNameSpace,
        related_name='entitlements',
        on_delete=models.SET_NULL,
        blank=True,
        null=True,
    )

    group_authority = models.CharField(
        max_length=200,
        blank=True,
        null=True,
    )

    role = models.CharField(
        max_length=200,
        blank=True,
        null=True,
    )

Lukas Burgey's avatar
Lukas Burgey committed
133
134
135
136
137
138
139
    # optional
    alias = models.CharField(
        max_length=200,
        blank=True,
        null=True,
    )

140
141
    @property
    def pretty_name(self):
Lukas Burgey's avatar
Lukas Burgey committed
142
143
144
145
        if self.alias is not None:
            return self.alias

        # or not
146
        name_search = re.search('group:(.*)$', self.name)
Lukas Burgey's avatar
Lukas Burgey committed
147
        if name_search and name_search.group(1) != '':
Lukas Burgey's avatar
Lukas Burgey committed
148
            return name_search.group(1)
149
150
        return self.name

151
152
153
154
155
156
    @property
    def full_name(self):
        if self.group_authority != '':
            return '{}#{}'.format(self.name, self.group_authority)
        return self.name

157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
    @property
    def broker_exchange(self):
        return 'entitlements'

    @staticmethod
    def extract_name(raw_name):
        name_search = re.search('^(.*)#', raw_name)
        if name_search:
            return name_search.group(1)
        return raw_name

    @staticmethod
    def extract_group_authority(raw_name):
        group_authority_search = re.search('#(.*)$', raw_name)
        if group_authority_search:
            return group_authority_search.group(1)
        return ''

    @staticmethod
    def extract_role(raw_name):
        role_search = re.search(':role=(.*)#', raw_name)
        if role_search:
            return role_search.group(1)
        return ''

    @classmethod
    def get_entitlement(cls, name, idp=None):
        try:
            # searching only by name! not idp
            entitlement = cls.objects.get(
                name=cls.extract_name(name),
            )

Lukas Burgey's avatar
Lukas Burgey committed
190
191
            # group authority changed / added
            group_authority = cls.extract_group_authority(name)
Lukas Burgey's avatar
Lukas Burgey committed
192
            if group_authority not in ('', entitlement.group_authority):
Lukas Burgey's avatar
Lukas Burgey committed
193
194
195
                entitlement.group_authority = group_authority
                entitlement.save()

196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
            # use case: a client caused the group to be created
            # we apply the idp here
            if entitlement.idp is None and idp is not None:
                entitlement.idp = idp
                entitlement.save()

            return entitlement

        except cls.DoesNotExist:
            entitlement = cls(
                name=cls.extract_name(name),
                group_authority=cls.extract_group_authority(name),
                role=cls.extract_role(name),
                idp=idp,
            )

            name_space_search = re.search('^(.*):group', name)
            if name_space_search:
                entitlement.name_space = EntitlementNameSpace.get_name_space(name_space_search.group(1))

            entitlement.save()
            return entitlement

    @classmethod
    def exists(cls, raw_name):
        try:
            cls.objects.get(
                name=cls.extract_name(raw_name),
            )
            return True
        except cls.DoesNotExist:
            return False

    def __str__(self):
230
        return 'VO-ENTITLEMENT-'+self.pretty_name