maquinaweb-shared-auth 0.2.32__tar.gz → 0.2.34__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of maquinaweb-shared-auth might be problematic. Click here for more details.
- {maquinaweb_shared_auth-0.2.32 → maquinaweb_shared_auth-0.2.34}/PKG-INFO +1 -1
- {maquinaweb_shared_auth-0.2.32 → maquinaweb_shared_auth-0.2.34}/maquinaweb_shared_auth.egg-info/PKG-INFO +1 -1
- {maquinaweb_shared_auth-0.2.32 → maquinaweb_shared_auth-0.2.34}/maquinaweb_shared_auth.egg-info/SOURCES.txt +2 -0
- {maquinaweb_shared_auth-0.2.32 → maquinaweb_shared_auth-0.2.34}/pyproject.toml +1 -1
- maquinaweb_shared_auth-0.2.34/shared_auth/__init__.py +21 -0
- maquinaweb_shared_auth-0.2.32/shared_auth/models.py → maquinaweb_shared_auth-0.2.34/shared_auth/abstract_models.py +123 -30
- {maquinaweb_shared_auth-0.2.32 → maquinaweb_shared_auth-0.2.34}/shared_auth/authentication.py +12 -4
- {maquinaweb_shared_auth-0.2.32 → maquinaweb_shared_auth-0.2.34}/shared_auth/decorators.py +10 -5
- {maquinaweb_shared_auth-0.2.32 → maquinaweb_shared_auth-0.2.34}/shared_auth/managers.py +15 -8
- {maquinaweb_shared_auth-0.2.32 → maquinaweb_shared_auth-0.2.34}/shared_auth/middleware.py +18 -8
- {maquinaweb_shared_auth-0.2.32 → maquinaweb_shared_auth-0.2.34}/shared_auth/mixins.py +15 -11
- maquinaweb_shared_auth-0.2.34/shared_auth/models.py +58 -0
- {maquinaweb_shared_auth-0.2.32 → maquinaweb_shared_auth-0.2.34}/shared_auth/permissions.py +4 -3
- {maquinaweb_shared_auth-0.2.32 → maquinaweb_shared_auth-0.2.34}/shared_auth/router.py +1 -1
- {maquinaweb_shared_auth-0.2.32 → maquinaweb_shared_auth-0.2.34}/shared_auth/serializers.py +29 -4
- maquinaweb_shared_auth-0.2.34/shared_auth/utils.py +113 -0
- maquinaweb_shared_auth-0.2.32/shared_auth/__init__.py +0 -6
- {maquinaweb_shared_auth-0.2.32 → maquinaweb_shared_auth-0.2.34}/README.md +0 -0
- {maquinaweb_shared_auth-0.2.32 → maquinaweb_shared_auth-0.2.34}/maquinaweb_shared_auth.egg-info/dependency_links.txt +0 -0
- {maquinaweb_shared_auth-0.2.32 → maquinaweb_shared_auth-0.2.34}/maquinaweb_shared_auth.egg-info/requires.txt +0 -0
- {maquinaweb_shared_auth-0.2.32 → maquinaweb_shared_auth-0.2.34}/maquinaweb_shared_auth.egg-info/top_level.txt +0 -0
- {maquinaweb_shared_auth-0.2.32 → maquinaweb_shared_auth-0.2.34}/setup.cfg +0 -0
- {maquinaweb_shared_auth-0.2.32 → maquinaweb_shared_auth-0.2.34}/setup.py +0 -0
- {maquinaweb_shared_auth-0.2.32 → maquinaweb_shared_auth-0.2.34}/shared_auth/app.py +0 -0
- {maquinaweb_shared_auth-0.2.32 → maquinaweb_shared_auth-0.2.34}/shared_auth/conf.py +0 -0
- {maquinaweb_shared_auth-0.2.32 → maquinaweb_shared_auth-0.2.34}/shared_auth/exceptions.py +0 -0
- {maquinaweb_shared_auth-0.2.32 → maquinaweb_shared_auth-0.2.34}/shared_auth/fields.py +0 -0
- {maquinaweb_shared_auth-0.2.32 → maquinaweb_shared_auth-0.2.34}/shared_auth/storage_backend.py +0 -0
- {maquinaweb_shared_auth-0.2.32 → maquinaweb_shared_auth-0.2.34}/shared_auth/urls.py +0 -0
- {maquinaweb_shared_auth-0.2.32 → maquinaweb_shared_auth-0.2.34}/shared_auth/views.py +0 -0
|
@@ -7,6 +7,7 @@ maquinaweb_shared_auth.egg-info/dependency_links.txt
|
|
|
7
7
|
maquinaweb_shared_auth.egg-info/requires.txt
|
|
8
8
|
maquinaweb_shared_auth.egg-info/top_level.txt
|
|
9
9
|
shared_auth/__init__.py
|
|
10
|
+
shared_auth/abstract_models.py
|
|
10
11
|
shared_auth/app.py
|
|
11
12
|
shared_auth/authentication.py
|
|
12
13
|
shared_auth/conf.py
|
|
@@ -22,4 +23,5 @@ shared_auth/router.py
|
|
|
22
23
|
shared_auth/serializers.py
|
|
23
24
|
shared_auth/storage_backend.py
|
|
24
25
|
shared_auth/urls.py
|
|
26
|
+
shared_auth/utils.py
|
|
25
27
|
shared_auth/views.py
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "maquinaweb-shared-auth"
|
|
7
|
-
version = "0.2.
|
|
7
|
+
version = "0.2.34"
|
|
8
8
|
description = "Models read-only para autenticação compartilhada entre projetos Django."
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.13"
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Biblioteca compartilhada para acesso aos models de autenticação
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
__version__ = '1.0.0'
|
|
6
|
+
default_app_config = "shared_auth.app.SharedAuthConfig"
|
|
7
|
+
|
|
8
|
+
# Exportar utilitários para facilitar importação
|
|
9
|
+
from .utils import (
|
|
10
|
+
get_member_model,
|
|
11
|
+
get_organization_model,
|
|
12
|
+
get_token_model,
|
|
13
|
+
get_user_model,
|
|
14
|
+
)
|
|
15
|
+
|
|
16
|
+
__all__ = [
|
|
17
|
+
'get_token_model',
|
|
18
|
+
'get_organization_model',
|
|
19
|
+
'get_user_model',
|
|
20
|
+
'get_member_model',
|
|
21
|
+
]
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"""
|
|
2
|
-
Models
|
|
3
|
-
|
|
2
|
+
Models abstratos para customização
|
|
3
|
+
Estes models podem ser herdados nos apps clientes para adicionar campos e métodos customizados
|
|
4
4
|
"""
|
|
5
5
|
|
|
6
6
|
import os
|
|
@@ -14,10 +14,33 @@ from .managers import SharedMemberManager, SharedOrganizationManager, UserManage
|
|
|
14
14
|
from .storage_backend import Storage
|
|
15
15
|
|
|
16
16
|
|
|
17
|
-
|
|
17
|
+
def organization_image_path(instance, filename):
|
|
18
|
+
return os.path.join(
|
|
19
|
+
"organization",
|
|
20
|
+
str(instance.pk),
|
|
21
|
+
"images",
|
|
22
|
+
filename,
|
|
23
|
+
)
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class AbstractSharedToken(models.Model):
|
|
18
27
|
"""
|
|
19
|
-
Model READ-ONLY da tabela authtoken_token
|
|
28
|
+
Model abstrato READ-ONLY da tabela authtoken_token
|
|
20
29
|
Usado para validar tokens em outros sistemas
|
|
30
|
+
|
|
31
|
+
Para customizar, crie um model no seu app:
|
|
32
|
+
|
|
33
|
+
from shared_auth.abstract_models import AbstractSharedToken
|
|
34
|
+
|
|
35
|
+
class CustomToken(AbstractSharedToken):
|
|
36
|
+
# Adicione campos customizados
|
|
37
|
+
custom_field = models.CharField(max_length=100)
|
|
38
|
+
|
|
39
|
+
class Meta(AbstractSharedToken.Meta):
|
|
40
|
+
pass
|
|
41
|
+
|
|
42
|
+
E configure no settings.py:
|
|
43
|
+
SHARED_AUTH_TOKEN_MODEL = 'seu_app.CustomToken'
|
|
21
44
|
"""
|
|
22
45
|
|
|
23
46
|
key = models.CharField(max_length=40, primary_key=True)
|
|
@@ -27,6 +50,7 @@ class SharedToken(models.Model):
|
|
|
27
50
|
objects = models.Manager()
|
|
28
51
|
|
|
29
52
|
class Meta:
|
|
53
|
+
abstract = True
|
|
30
54
|
managed = False
|
|
31
55
|
db_table = TOKEN_TABLE
|
|
32
56
|
|
|
@@ -36,7 +60,10 @@ class SharedToken(models.Model):
|
|
|
36
60
|
@property
|
|
37
61
|
def user(self):
|
|
38
62
|
"""Acessa usuário do token"""
|
|
63
|
+
from .utils import get_user_model
|
|
64
|
+
|
|
39
65
|
if not hasattr(self, "_cached_user"):
|
|
66
|
+
User = get_user_model()
|
|
40
67
|
self._cached_user = User.objects.get_or_fail(self.user_id)
|
|
41
68
|
return self._cached_user
|
|
42
69
|
|
|
@@ -46,19 +73,24 @@ class SharedToken(models.Model):
|
|
|
46
73
|
return True
|
|
47
74
|
|
|
48
75
|
|
|
49
|
-
|
|
50
|
-
return os.path.join(
|
|
51
|
-
"organization",
|
|
52
|
-
str(instance.pk),
|
|
53
|
-
"images",
|
|
54
|
-
filename,
|
|
55
|
-
)
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
class SharedOrganization(models.Model):
|
|
76
|
+
class AbstractSharedOrganization(models.Model):
|
|
59
77
|
"""
|
|
60
|
-
Model READ-ONLY da tabela organization
|
|
78
|
+
Model abstrato READ-ONLY da tabela organization
|
|
61
79
|
Usado para acessar dados de organizações em outros sistemas
|
|
80
|
+
|
|
81
|
+
Para customizar, crie um model no seu app:
|
|
82
|
+
|
|
83
|
+
from shared_auth.abstract_models import AbstractSharedOrganization
|
|
84
|
+
|
|
85
|
+
class CustomOrganization(AbstractSharedOrganization):
|
|
86
|
+
# Adicione campos customizados
|
|
87
|
+
custom_field = models.CharField(max_length=100)
|
|
88
|
+
|
|
89
|
+
class Meta(AbstractSharedOrganization.Meta):
|
|
90
|
+
pass
|
|
91
|
+
|
|
92
|
+
E configure no settings.py:
|
|
93
|
+
SHARED_AUTH_ORGANIZATION_MODEL = 'seu_app.CustomOrganization'
|
|
62
94
|
"""
|
|
63
95
|
|
|
64
96
|
# Campos principais
|
|
@@ -75,7 +107,8 @@ class SharedOrganization(models.Model):
|
|
|
75
107
|
# Relacionamentos
|
|
76
108
|
main_organization_id = models.IntegerField(null=True, blank=True)
|
|
77
109
|
is_branch = models.BooleanField(default=False)
|
|
78
|
-
|
|
110
|
+
metadata = models.JSONField(default=dict)
|
|
111
|
+
|
|
79
112
|
# Metadados
|
|
80
113
|
created_at = models.DateTimeField()
|
|
81
114
|
updated_at = models.DateTimeField()
|
|
@@ -84,7 +117,8 @@ class SharedOrganization(models.Model):
|
|
|
84
117
|
objects = SharedOrganizationManager()
|
|
85
118
|
|
|
86
119
|
class Meta:
|
|
87
|
-
|
|
120
|
+
abstract = True
|
|
121
|
+
managed = False
|
|
88
122
|
db_table = ORGANIZATION_TABLE
|
|
89
123
|
|
|
90
124
|
def __str__(self):
|
|
@@ -99,8 +133,11 @@ class SharedOrganization(models.Model):
|
|
|
99
133
|
if org.is_branch:
|
|
100
134
|
main = org.main_organization
|
|
101
135
|
"""
|
|
136
|
+
from .utils import get_organization_model
|
|
137
|
+
|
|
102
138
|
if self.main_organization_id:
|
|
103
|
-
|
|
139
|
+
Organization = get_organization_model()
|
|
140
|
+
return Organization.objects.get_or_fail(self.main_organization_id)
|
|
104
141
|
return None
|
|
105
142
|
|
|
106
143
|
@property
|
|
@@ -111,7 +148,10 @@ class SharedOrganization(models.Model):
|
|
|
111
148
|
Usage:
|
|
112
149
|
branches = org.branches
|
|
113
150
|
"""
|
|
114
|
-
|
|
151
|
+
from .utils import get_organization_model
|
|
152
|
+
|
|
153
|
+
Organization = get_organization_model()
|
|
154
|
+
return Organization.objects.filter(main_organization_id=self.pk)
|
|
115
155
|
|
|
116
156
|
@property
|
|
117
157
|
def members(self):
|
|
@@ -123,7 +163,10 @@ class SharedOrganization(models.Model):
|
|
|
123
163
|
for member in members:
|
|
124
164
|
print(member.user.email)
|
|
125
165
|
"""
|
|
126
|
-
|
|
166
|
+
from .utils import get_member_model
|
|
167
|
+
|
|
168
|
+
Member = get_member_model()
|
|
169
|
+
return Member.objects.for_organization(self.pk)
|
|
127
170
|
|
|
128
171
|
@property
|
|
129
172
|
def users(self):
|
|
@@ -133,6 +176,9 @@ class SharedOrganization(models.Model):
|
|
|
133
176
|
Usage:
|
|
134
177
|
users = org.users
|
|
135
178
|
"""
|
|
179
|
+
from .utils import get_user_model
|
|
180
|
+
|
|
181
|
+
User = get_user_model()
|
|
136
182
|
return User.objects.filter(
|
|
137
183
|
id__in=self.members.values_list("user_id", flat=True)
|
|
138
184
|
)
|
|
@@ -142,14 +188,29 @@ class SharedOrganization(models.Model):
|
|
|
142
188
|
return self.deleted_at is None
|
|
143
189
|
|
|
144
190
|
|
|
145
|
-
class
|
|
191
|
+
class AbstractUser(AbstractUser):
|
|
146
192
|
"""
|
|
147
|
-
Model READ-ONLY da tabela auth_user
|
|
193
|
+
Model abstrato READ-ONLY da tabela auth_user
|
|
194
|
+
|
|
195
|
+
Para customizar, crie um model no seu app:
|
|
196
|
+
|
|
197
|
+
from shared_auth.abstract_models import AbstractUser
|
|
198
|
+
|
|
199
|
+
class CustomUser(AbstractUser):
|
|
200
|
+
# Adicione campos customizados
|
|
201
|
+
custom_field = models.CharField(max_length=100)
|
|
202
|
+
|
|
203
|
+
class Meta(AbstractUser.Meta):
|
|
204
|
+
pass
|
|
205
|
+
|
|
206
|
+
E configure no settings.py:
|
|
207
|
+
SHARED_AUTH_USER_MODEL = 'seu_app.CustomUser'
|
|
148
208
|
"""
|
|
149
209
|
|
|
150
210
|
date_joined = models.DateTimeField()
|
|
151
211
|
last_login = models.DateTimeField(null=True, blank=True)
|
|
152
212
|
avatar = models.ImageField(storage=Storage, blank=True, null=True)
|
|
213
|
+
|
|
153
214
|
# Campos customizados
|
|
154
215
|
createdat = models.DateTimeField()
|
|
155
216
|
updatedat = models.DateTimeField()
|
|
@@ -158,6 +219,7 @@ class User(AbstractUser):
|
|
|
158
219
|
objects = UserManager()
|
|
159
220
|
|
|
160
221
|
class Meta:
|
|
222
|
+
abstract = True
|
|
161
223
|
managed = False
|
|
162
224
|
db_table = USER_TABLE
|
|
163
225
|
|
|
@@ -166,8 +228,13 @@ class User(AbstractUser):
|
|
|
166
228
|
"""
|
|
167
229
|
Retorna todas as organizações associadas ao usuário.
|
|
168
230
|
"""
|
|
169
|
-
|
|
170
|
-
|
|
231
|
+
from .utils import get_organization_model, get_member_model
|
|
232
|
+
|
|
233
|
+
Organization = get_organization_model()
|
|
234
|
+
Member = get_member_model()
|
|
235
|
+
|
|
236
|
+
return Organization.objects.filter(
|
|
237
|
+
id__in=Member.objects.filter(user_id=self.id).values_list(
|
|
171
238
|
"organization_id", flat=True
|
|
172
239
|
)
|
|
173
240
|
)
|
|
@@ -176,14 +243,19 @@ class User(AbstractUser):
|
|
|
176
243
|
"""
|
|
177
244
|
Retorna a organização especificada pelo ID, se o usuário for membro.
|
|
178
245
|
"""
|
|
246
|
+
from .utils import get_organization_model, get_member_model
|
|
247
|
+
|
|
248
|
+
Organization = get_organization_model()
|
|
249
|
+
Member = get_member_model()
|
|
250
|
+
|
|
179
251
|
try:
|
|
180
|
-
organization =
|
|
181
|
-
except
|
|
252
|
+
organization = Organization.objects.get(id=organization_id)
|
|
253
|
+
except Organization.DoesNotExist:
|
|
182
254
|
raise OrganizationNotFoundError(
|
|
183
255
|
f"Organização com ID {organization_id} não encontrada."
|
|
184
256
|
)
|
|
185
257
|
|
|
186
|
-
if not
|
|
258
|
+
if not Member.objects.filter(
|
|
187
259
|
user_id=self.id, organization_id=organization.id
|
|
188
260
|
).exists():
|
|
189
261
|
raise OrganizationNotFoundError("Usuário não é membro desta organização.")
|
|
@@ -191,10 +263,24 @@ class User(AbstractUser):
|
|
|
191
263
|
return organization
|
|
192
264
|
|
|
193
265
|
|
|
194
|
-
class
|
|
266
|
+
class AbstractSharedMember(models.Model):
|
|
195
267
|
"""
|
|
196
|
-
Model READ-ONLY da tabela organization_member
|
|
268
|
+
Model abstrato READ-ONLY da tabela organization_member
|
|
197
269
|
Relacionamento entre User e Organization
|
|
270
|
+
|
|
271
|
+
Para customizar, crie um model no seu app:
|
|
272
|
+
|
|
273
|
+
from shared_auth.abstract_models import AbstractSharedMember
|
|
274
|
+
|
|
275
|
+
class CustomMember(AbstractSharedMember):
|
|
276
|
+
# Adicione campos customizados
|
|
277
|
+
custom_field = models.CharField(max_length=100)
|
|
278
|
+
|
|
279
|
+
class Meta(AbstractSharedMember.Meta):
|
|
280
|
+
pass
|
|
281
|
+
|
|
282
|
+
E configure no settings.py:
|
|
283
|
+
SHARED_AUTH_MEMBER_MODEL = 'seu_app.CustomMember'
|
|
198
284
|
"""
|
|
199
285
|
|
|
200
286
|
user_id = models.IntegerField()
|
|
@@ -204,6 +290,7 @@ class SharedMember(models.Model):
|
|
|
204
290
|
objects = SharedMemberManager()
|
|
205
291
|
|
|
206
292
|
class Meta:
|
|
293
|
+
abstract = True
|
|
207
294
|
managed = False
|
|
208
295
|
db_table = MEMBER_TABLE
|
|
209
296
|
|
|
@@ -220,6 +307,9 @@ class SharedMember(models.Model):
|
|
|
220
307
|
user = member.user
|
|
221
308
|
print(user.email)
|
|
222
309
|
"""
|
|
310
|
+
from .utils import get_user_model
|
|
311
|
+
|
|
312
|
+
User = get_user_model()
|
|
223
313
|
return User.objects.get_or_fail(self.user_id)
|
|
224
314
|
|
|
225
315
|
@property
|
|
@@ -232,4 +322,7 @@ class SharedMember(models.Model):
|
|
|
232
322
|
org = member.organization
|
|
233
323
|
print(org.name)
|
|
234
324
|
"""
|
|
235
|
-
|
|
325
|
+
from .utils import get_organization_model
|
|
326
|
+
|
|
327
|
+
Organization = get_organization_model()
|
|
328
|
+
return Organization.objects.get_or_fail(self.organization_id)
|
{maquinaweb_shared_auth-0.2.32 → maquinaweb_shared_auth-0.2.34}/shared_auth/authentication.py
RENAMED
|
@@ -6,13 +6,15 @@ from django.utils.translation import gettext_lazy as _
|
|
|
6
6
|
from rest_framework import exceptions
|
|
7
7
|
from rest_framework.authentication import TokenAuthentication
|
|
8
8
|
|
|
9
|
-
from .
|
|
9
|
+
from .utils import get_token_model, get_user_model
|
|
10
10
|
|
|
11
11
|
|
|
12
12
|
class SharedTokenAuthentication(TokenAuthentication):
|
|
13
13
|
"""
|
|
14
14
|
Autentica usando tokens do banco de dados compartilhado
|
|
15
15
|
|
|
16
|
+
Usa get_token_model() e get_user_model() para suportar models customizados.
|
|
17
|
+
|
|
16
18
|
Usage em settings.py:
|
|
17
19
|
REST_FRAMEWORK = {
|
|
18
20
|
'DEFAULT_AUTHENTICATION_CLASSES': [
|
|
@@ -21,15 +23,21 @@ class SharedTokenAuthentication(TokenAuthentication):
|
|
|
21
23
|
}
|
|
22
24
|
"""
|
|
23
25
|
|
|
24
|
-
|
|
26
|
+
@property
|
|
27
|
+
def model(self):
|
|
28
|
+
"""Retorna o model de Token configurado"""
|
|
29
|
+
return get_token_model()
|
|
25
30
|
|
|
26
31
|
def authenticate_credentials(self, key):
|
|
27
32
|
"""
|
|
28
33
|
Valida o token no banco de dados compartilhado
|
|
29
34
|
"""
|
|
35
|
+
Token = get_token_model()
|
|
36
|
+
User = get_user_model()
|
|
37
|
+
|
|
30
38
|
try:
|
|
31
|
-
token =
|
|
32
|
-
except
|
|
39
|
+
token = Token.objects.get(key=key)
|
|
40
|
+
except Token.DoesNotExist:
|
|
33
41
|
raise exceptions.AuthenticationFailed(_("Token inválido."))
|
|
34
42
|
|
|
35
43
|
# Buscar usuário completo
|
|
@@ -6,7 +6,7 @@ from functools import wraps
|
|
|
6
6
|
|
|
7
7
|
from django.http import JsonResponse
|
|
8
8
|
|
|
9
|
-
from .
|
|
9
|
+
from .utils import get_organization_model, get_token_model, get_user_model
|
|
10
10
|
|
|
11
11
|
|
|
12
12
|
def require_auth(view_func):
|
|
@@ -28,8 +28,11 @@ def require_auth(view_func):
|
|
|
28
28
|
return JsonResponse({"error": "Token não fornecido"}, status=401)
|
|
29
29
|
|
|
30
30
|
# Validar token
|
|
31
|
+
Token = get_token_model()
|
|
32
|
+
User = get_user_model()
|
|
33
|
+
|
|
31
34
|
try:
|
|
32
|
-
token_obj =
|
|
35
|
+
token_obj = Token.objects.get(key=token)
|
|
33
36
|
user = User.objects.get(pk=token_obj.user_id)
|
|
34
37
|
|
|
35
38
|
if not user.is_active or user.deleted_at is not None:
|
|
@@ -38,7 +41,7 @@ def require_auth(view_func):
|
|
|
38
41
|
request.user = user
|
|
39
42
|
request.auth = token_obj
|
|
40
43
|
|
|
41
|
-
except (
|
|
44
|
+
except (Token.DoesNotExist, User.DoesNotExist):
|
|
42
45
|
return JsonResponse({"error": "Token inválido"}, status=401)
|
|
43
46
|
|
|
44
47
|
return view_func(request, *args, **kwargs)
|
|
@@ -58,15 +61,17 @@ def require_organization(view_func):
|
|
|
58
61
|
return JsonResponse({"error": "Organização não definida"}, status=403)
|
|
59
62
|
|
|
60
63
|
# Buscar organização
|
|
64
|
+
Organization = get_organization_model()
|
|
65
|
+
|
|
61
66
|
try:
|
|
62
|
-
org =
|
|
67
|
+
org = Organization.objects.get(pk=request.organization_id)
|
|
63
68
|
|
|
64
69
|
if not org.is_active():
|
|
65
70
|
return JsonResponse({"error": "Organização inativa"}, status=403)
|
|
66
71
|
|
|
67
72
|
request.organization = org
|
|
68
73
|
|
|
69
|
-
except
|
|
74
|
+
except Organization.DoesNotExist:
|
|
70
75
|
return JsonResponse({"error": "Organização não encontrada"}, status=404)
|
|
71
76
|
|
|
72
77
|
return view_func(request, *args, **kwargs)
|
|
@@ -95,7 +95,7 @@ class OrganizationQuerySetMixin:
|
|
|
95
95
|
Lista de objetos com _cached_organization
|
|
96
96
|
"""
|
|
97
97
|
objects = list(self.all())
|
|
98
|
-
from .
|
|
98
|
+
from .utils import get_organization_model
|
|
99
99
|
|
|
100
100
|
if not objects:
|
|
101
101
|
return objects
|
|
@@ -104,8 +104,9 @@ class OrganizationQuerySetMixin:
|
|
|
104
104
|
org_ids = set(obj.organization_id for obj in objects)
|
|
105
105
|
|
|
106
106
|
# Buscar todas de uma vez
|
|
107
|
+
Organization = get_organization_model()
|
|
107
108
|
organizations = {
|
|
108
|
-
org.pk: org for org in
|
|
109
|
+
org.pk: org for org in Organization.objects.filter(pk__in=org_ids)
|
|
109
110
|
}
|
|
110
111
|
|
|
111
112
|
# Cachear nos objetos
|
|
@@ -130,7 +131,7 @@ class UserQuerySetMixin:
|
|
|
130
131
|
"""
|
|
131
132
|
Pré-carrega dados de usuários (evita N+1)
|
|
132
133
|
"""
|
|
133
|
-
from .
|
|
134
|
+
from .utils import get_user_model
|
|
134
135
|
|
|
135
136
|
objects = list(self.all())
|
|
136
137
|
|
|
@@ -139,6 +140,7 @@ class UserQuerySetMixin:
|
|
|
139
140
|
|
|
140
141
|
user_ids = set(obj.user_id for obj in objects)
|
|
141
142
|
|
|
143
|
+
User = get_user_model()
|
|
142
144
|
users = {user.pk: user for user in User.objects.filter(pk__in=user_ids)}
|
|
143
145
|
|
|
144
146
|
for obj in objects:
|
|
@@ -154,7 +156,7 @@ class OrganizationUserQuerySetMixin(OrganizationQuerySetMixin, UserQuerySetMixin
|
|
|
154
156
|
"""
|
|
155
157
|
Pré-carrega dados de organizações E usuários (evita N+1)
|
|
156
158
|
"""
|
|
157
|
-
from .
|
|
159
|
+
from .utils import get_organization_model, get_user_model
|
|
158
160
|
|
|
159
161
|
objects = list(self.all())
|
|
160
162
|
|
|
@@ -166,8 +168,11 @@ class OrganizationUserQuerySetMixin(OrganizationQuerySetMixin, UserQuerySetMixin
|
|
|
166
168
|
user_ids = set(obj.user_id for obj in objects)
|
|
167
169
|
|
|
168
170
|
# Buscar em batch
|
|
171
|
+
Organization = get_organization_model()
|
|
172
|
+
User = get_user_model()
|
|
173
|
+
|
|
169
174
|
organizations = {
|
|
170
|
-
org.pk: org for org in
|
|
175
|
+
org.pk: org for org in Organization.objects.filter(pk__in=org_ids)
|
|
171
176
|
}
|
|
172
177
|
|
|
173
178
|
users = {user.pk: user for user in User.objects.filter(pk__in=user_ids)}
|
|
@@ -183,13 +188,15 @@ class OrganizationUserQuerySetMixin(OrganizationQuerySetMixin, UserQuerySetMixin
|
|
|
183
188
|
"""
|
|
184
189
|
Cria objeto com validação de organização e usuário
|
|
185
190
|
"""
|
|
186
|
-
from .
|
|
191
|
+
from .utils import get_member_model, get_organization_model
|
|
187
192
|
|
|
188
193
|
# Valida organização
|
|
189
|
-
|
|
194
|
+
Organization = get_organization_model()
|
|
195
|
+
Organization.objects.get_or_fail(organization_id)
|
|
190
196
|
|
|
191
197
|
# Valida usuário pertence à organização
|
|
192
|
-
|
|
198
|
+
Member = get_member_model()
|
|
199
|
+
if not Member.objects.filter(
|
|
193
200
|
user_id=user_id, organization_id=organization_id
|
|
194
201
|
).exists():
|
|
195
202
|
raise ValueError(
|
|
@@ -6,7 +6,12 @@ from django.http import JsonResponse
|
|
|
6
6
|
from django.utils.deprecation import MiddlewareMixin
|
|
7
7
|
|
|
8
8
|
from .authentication import SharedTokenAuthentication
|
|
9
|
-
from .
|
|
9
|
+
from .utils import (
|
|
10
|
+
get_member_model,
|
|
11
|
+
get_organization_model,
|
|
12
|
+
get_token_model,
|
|
13
|
+
get_user_model,
|
|
14
|
+
)
|
|
10
15
|
|
|
11
16
|
|
|
12
17
|
class SharedAuthMiddleware(MiddlewareMixin):
|
|
@@ -50,8 +55,11 @@ class SharedAuthMiddleware(MiddlewareMixin):
|
|
|
50
55
|
return None
|
|
51
56
|
|
|
52
57
|
# Validar token e buscar usuário
|
|
58
|
+
Token = get_token_model()
|
|
59
|
+
User = get_user_model()
|
|
60
|
+
|
|
53
61
|
try:
|
|
54
|
-
token_obj =
|
|
62
|
+
token_obj = Token.objects.get(key=token)
|
|
55
63
|
user = User.objects.get(pk=token_obj.user_id)
|
|
56
64
|
|
|
57
65
|
if not user.is_active or user.deleted_at is not None:
|
|
@@ -63,7 +71,7 @@ class SharedAuthMiddleware(MiddlewareMixin):
|
|
|
63
71
|
# request.user = user
|
|
64
72
|
request.auth = token_obj
|
|
65
73
|
|
|
66
|
-
except (
|
|
74
|
+
except (Token.DoesNotExist, User.DoesNotExist):
|
|
67
75
|
# request.user = None
|
|
68
76
|
request.auth = None
|
|
69
77
|
|
|
@@ -159,9 +167,8 @@ class OrganizationMiddleware(MiddlewareMixin):
|
|
|
159
167
|
return
|
|
160
168
|
|
|
161
169
|
request.organization_id = organization_id
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
).first()
|
|
170
|
+
Organization = get_organization_model()
|
|
171
|
+
request.organization = Organization.objects.filter(pk=organization_id).first()
|
|
165
172
|
|
|
166
173
|
@staticmethod
|
|
167
174
|
def _authenticate_user(request):
|
|
@@ -194,7 +201,8 @@ class OrganizationMiddleware(MiddlewareMixin):
|
|
|
194
201
|
return None
|
|
195
202
|
|
|
196
203
|
# Buscar a primeira organização que o usuário pertence
|
|
197
|
-
|
|
204
|
+
Member = get_member_model()
|
|
205
|
+
member = Member.objects.filter(user_id=request.user.pk).first()
|
|
198
206
|
|
|
199
207
|
return member.organization_id if member else None
|
|
200
208
|
|
|
@@ -210,6 +218,8 @@ class OrganizationMiddleware(MiddlewareMixin):
|
|
|
210
218
|
|
|
211
219
|
|
|
212
220
|
def get_member(user_id, organization_id):
|
|
213
|
-
|
|
221
|
+
"""Busca membro usando o model configurado"""
|
|
222
|
+
Member = get_member_model()
|
|
223
|
+
return Member.objects.filter(
|
|
214
224
|
user_id=user_id, organization_id=organization_id
|
|
215
225
|
).first()
|
|
@@ -44,9 +44,10 @@ class OrganizationMixin(models.Model):
|
|
|
44
44
|
Acessa organização do banco de auth (lazy loading com cache)
|
|
45
45
|
"""
|
|
46
46
|
if not hasattr(self, "_cached_organization"):
|
|
47
|
-
from shared_auth.
|
|
47
|
+
from shared_auth.utils import get_organization_model
|
|
48
48
|
|
|
49
|
-
|
|
49
|
+
Organization = get_organization_model()
|
|
50
|
+
self._cached_organization = Organization.objects.get_or_fail(
|
|
50
51
|
self.organization_id
|
|
51
52
|
)
|
|
52
53
|
return self._cached_organization
|
|
@@ -69,7 +70,7 @@ class OrganizationMixin(models.Model):
|
|
|
69
70
|
"""Retorna nome da organização (safe)"""
|
|
70
71
|
try:
|
|
71
72
|
return self.organization.name
|
|
72
|
-
except:
|
|
73
|
+
except Exception:
|
|
73
74
|
return None
|
|
74
75
|
|
|
75
76
|
|
|
@@ -108,8 +109,9 @@ class UserMixin(models.Model):
|
|
|
108
109
|
Acessa usuário do banco de auth (lazy loading com cache)
|
|
109
110
|
"""
|
|
110
111
|
if not hasattr(self, "_cached_user"):
|
|
111
|
-
from shared_auth.
|
|
112
|
+
from shared_auth.utils import get_user_model
|
|
112
113
|
|
|
114
|
+
User = get_user_model()
|
|
113
115
|
self._cached_user = User.objects.get_or_fail(self.user_id)
|
|
114
116
|
return self._cached_user
|
|
115
117
|
|
|
@@ -118,7 +120,7 @@ class UserMixin(models.Model):
|
|
|
118
120
|
"""Retorna email do usuário (safe)"""
|
|
119
121
|
try:
|
|
120
122
|
return self.user.email
|
|
121
|
-
except:
|
|
123
|
+
except Exception:
|
|
122
124
|
return None
|
|
123
125
|
|
|
124
126
|
@property
|
|
@@ -126,7 +128,7 @@ class UserMixin(models.Model):
|
|
|
126
128
|
"""Retorna nome completo do usuário (safe)"""
|
|
127
129
|
try:
|
|
128
130
|
return self.user.get_full_name()
|
|
129
|
-
except:
|
|
131
|
+
except Exception:
|
|
130
132
|
return None
|
|
131
133
|
|
|
132
134
|
@property
|
|
@@ -138,7 +140,7 @@ class UserMixin(models.Model):
|
|
|
138
140
|
"""Verifica se o usuário está ativo"""
|
|
139
141
|
try:
|
|
140
142
|
return self.user.is_active and self.user.deleted_at is None
|
|
141
|
-
except:
|
|
143
|
+
except Exception:
|
|
142
144
|
return False
|
|
143
145
|
|
|
144
146
|
|
|
@@ -171,9 +173,10 @@ class OrganizationUserMixin(OrganizationMixin, UserMixin):
|
|
|
171
173
|
Returns:
|
|
172
174
|
bool: True se pertence, False caso contrário
|
|
173
175
|
"""
|
|
174
|
-
from shared_auth.
|
|
176
|
+
from shared_auth.utils import get_member_model
|
|
175
177
|
|
|
176
|
-
|
|
178
|
+
Member = get_member_model()
|
|
179
|
+
return Member.objects.filter(
|
|
177
180
|
user_id=self.user_id, organization_id=self.organization_id
|
|
178
181
|
).exists()
|
|
179
182
|
|
|
@@ -182,9 +185,10 @@ class OrganizationUserMixin(OrganizationMixin, UserMixin):
|
|
|
182
185
|
Verifica se um usuário pode acessar este registro
|
|
183
186
|
(se pertence à mesma organização)
|
|
184
187
|
"""
|
|
185
|
-
from shared_auth.
|
|
188
|
+
from shared_auth.utils import get_member_model
|
|
186
189
|
|
|
187
|
-
|
|
190
|
+
Member = get_member_model()
|
|
191
|
+
return Member.objects.filter(
|
|
188
192
|
user_id=user_id, organization_id=self.organization_id
|
|
189
193
|
).exists()
|
|
190
194
|
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Models READ-ONLY para acesso aos dados de autenticação
|
|
3
|
+
ATENÇÃO: Estes models NÃO devem ser usados para criar migrations
|
|
4
|
+
|
|
5
|
+
Para customizar estes models, herde dos models abstratos em shared_auth.abstract_models
|
|
6
|
+
e configure no settings.py. Veja a documentação em abstract_models.py
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from .abstract_models import (
|
|
10
|
+
AbstractSharedMember,
|
|
11
|
+
AbstractSharedOrganization,
|
|
12
|
+
AbstractSharedToken,
|
|
13
|
+
AbstractUser,
|
|
14
|
+
)
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class SharedToken(AbstractSharedToken):
|
|
18
|
+
"""
|
|
19
|
+
Model READ-ONLY padrão da tabela authtoken_token
|
|
20
|
+
|
|
21
|
+
Para customizar, crie seu próprio model herdando de AbstractSharedToken
|
|
22
|
+
"""
|
|
23
|
+
|
|
24
|
+
class Meta(AbstractSharedToken.Meta):
|
|
25
|
+
pass
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
class SharedOrganization(AbstractSharedOrganization):
|
|
29
|
+
"""
|
|
30
|
+
Model READ-ONLY padrão da tabela organization
|
|
31
|
+
|
|
32
|
+
Para customizar, crie seu próprio model herdando de AbstractSharedOrganization
|
|
33
|
+
"""
|
|
34
|
+
|
|
35
|
+
class Meta(AbstractSharedOrganization.Meta):
|
|
36
|
+
pass
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
class User(AbstractUser):
|
|
40
|
+
"""
|
|
41
|
+
Model READ-ONLY padrão da tabela auth_user
|
|
42
|
+
|
|
43
|
+
Para customizar, crie seu próprio model herdando de AbstractUser
|
|
44
|
+
"""
|
|
45
|
+
|
|
46
|
+
class Meta(AbstractUser.Meta):
|
|
47
|
+
pass
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
class SharedMember(AbstractSharedMember):
|
|
51
|
+
"""
|
|
52
|
+
Model READ-ONLY padrão da tabela organization_member
|
|
53
|
+
|
|
54
|
+
Para customizar, crie seu próprio model herdando de AbstractSharedMember
|
|
55
|
+
"""
|
|
56
|
+
|
|
57
|
+
class Meta(AbstractSharedMember.Meta):
|
|
58
|
+
pass
|
|
@@ -5,6 +5,7 @@ Permissões customizadas para DRF
|
|
|
5
5
|
from rest_framework import permissions
|
|
6
6
|
|
|
7
7
|
from shared_auth.middleware import get_member
|
|
8
|
+
from shared_auth.utils import get_organization_model
|
|
8
9
|
|
|
9
10
|
|
|
10
11
|
class IsAuthenticated(permissions.BasePermission):
|
|
@@ -35,12 +36,12 @@ class HasActiveOrganization(permissions.BasePermission):
|
|
|
35
36
|
return False
|
|
36
37
|
|
|
37
38
|
# Verificar se organização está ativa
|
|
38
|
-
|
|
39
|
+
Organization = get_organization_model()
|
|
39
40
|
|
|
40
41
|
try:
|
|
41
|
-
org =
|
|
42
|
+
org = Organization.objects.get(pk=request.organization_id)
|
|
42
43
|
return org.is_active()
|
|
43
|
-
except
|
|
44
|
+
except Organization.DoesNotExist:
|
|
44
45
|
return False
|
|
45
46
|
|
|
46
47
|
|
|
@@ -3,7 +3,7 @@ class SharedAuthRouter:
|
|
|
3
3
|
Direciona queries dos models compartilhados para o banco correto
|
|
4
4
|
"""
|
|
5
5
|
|
|
6
|
-
route_app_labels = {"shared_auth", "auth", "admin"}
|
|
6
|
+
route_app_labels = {"shared_auth", "auth", "admin", "contenttypes"}
|
|
7
7
|
|
|
8
8
|
def db_for_read(self, model, **hints):
|
|
9
9
|
if model._meta.app_label in self.route_app_labels:
|
|
@@ -13,7 +13,7 @@ Se quiser usar separadamente:
|
|
|
13
13
|
|
|
14
14
|
from rest_framework import serializers
|
|
15
15
|
|
|
16
|
-
from .
|
|
16
|
+
from .utils import get_organization_model, get_user_model
|
|
17
17
|
|
|
18
18
|
|
|
19
19
|
class OrganizationCreateSerializerMixin(serializers.ModelSerializer):
|
|
@@ -28,6 +28,8 @@ class OrganizationCreateSerializerMixin(serializers.ModelSerializer):
|
|
|
28
28
|
fields = ['id', 'titulo', 'conteudo']
|
|
29
29
|
"""
|
|
30
30
|
|
|
31
|
+
organization_id = serializers.IntegerField(required=False)
|
|
32
|
+
|
|
31
33
|
def create(self, validated_data):
|
|
32
34
|
"""Automatically set organization_id from request context"""
|
|
33
35
|
if self.context.get("request") and hasattr(
|
|
@@ -116,8 +118,17 @@ class OrganizationListCreateSerializerMixin(
|
|
|
116
118
|
|
|
117
119
|
|
|
118
120
|
class OrganizationSerializer(serializers.ModelSerializer):
|
|
121
|
+
"""
|
|
122
|
+
Serializer para o model de Organization configurado.
|
|
123
|
+
Usa get_organization_model() para suportar models customizados.
|
|
124
|
+
"""
|
|
125
|
+
|
|
126
|
+
def __init__(self, *args, **kwargs):
|
|
127
|
+
super().__init__(*args, **kwargs)
|
|
128
|
+
self.Meta.model = get_organization_model()
|
|
129
|
+
|
|
119
130
|
class Meta:
|
|
120
|
-
model =
|
|
131
|
+
model = None # Será definido dinamicamente no __init__
|
|
121
132
|
fields = "__all__"
|
|
122
133
|
|
|
123
134
|
|
|
@@ -133,6 +144,8 @@ class UserCreateSerializerMixin(serializers.ModelSerializer):
|
|
|
133
144
|
fields = ['id', 'titulo', 'conteudo']
|
|
134
145
|
"""
|
|
135
146
|
|
|
147
|
+
user_id = serializers.IntegerField(required=False)
|
|
148
|
+
|
|
136
149
|
def create(self, validated_data):
|
|
137
150
|
"""Automatically set user_id from request context"""
|
|
138
151
|
if self.context.get("request") and hasattr(self.context["request"], "user"):
|
|
@@ -182,7 +195,7 @@ class UserSerializerMixin(serializers.ModelSerializer):
|
|
|
182
195
|
def get_user(self, obj):
|
|
183
196
|
"""Retorna dados do usuário como objeto"""
|
|
184
197
|
try:
|
|
185
|
-
user
|
|
198
|
+
user = obj.user
|
|
186
199
|
return {
|
|
187
200
|
"id": user.pk,
|
|
188
201
|
"username": user.username,
|
|
@@ -213,8 +226,17 @@ class UserListCreateSerializerMixin(UserSerializerMixin, UserCreateSerializerMix
|
|
|
213
226
|
|
|
214
227
|
|
|
215
228
|
class UserSerializer(serializers.ModelSerializer):
|
|
229
|
+
"""
|
|
230
|
+
Serializer para o model de User configurado.
|
|
231
|
+
Usa get_user_model() para suportar models customizados.
|
|
232
|
+
"""
|
|
233
|
+
|
|
234
|
+
def __init__(self, *args, **kwargs):
|
|
235
|
+
super().__init__(*args, **kwargs)
|
|
236
|
+
self.Meta.model = get_user_model()
|
|
237
|
+
|
|
216
238
|
class Meta:
|
|
217
|
-
model =
|
|
239
|
+
model = None # Será definido dinamicamente no __init__
|
|
218
240
|
fields = [
|
|
219
241
|
"id",
|
|
220
242
|
"username",
|
|
@@ -241,6 +263,9 @@ class OrganizationUserCreateSerializerMixin(serializers.ModelSerializer):
|
|
|
241
263
|
fields = ['id', 'titulo', 'conteudo']
|
|
242
264
|
"""
|
|
243
265
|
|
|
266
|
+
organization_id = serializers.IntegerField(required=False)
|
|
267
|
+
user_id = serializers.IntegerField(required=False)
|
|
268
|
+
|
|
244
269
|
def create(self, validated_data):
|
|
245
270
|
"""Automatically set both organization_id and user_id from request context"""
|
|
246
271
|
if self.context.get("request"):
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Utilitários para obter os models configurados
|
|
3
|
+
Similar ao get_user_model() do Django
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
from django.apps import apps
|
|
7
|
+
from django.core.exceptions import ImproperlyConfigured
|
|
8
|
+
|
|
9
|
+
from .conf import get_setting
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def get_token_model():
|
|
13
|
+
"""
|
|
14
|
+
Retorna o model de Token configurado ou o padrão.
|
|
15
|
+
|
|
16
|
+
Usage:
|
|
17
|
+
from shared_auth.utils import get_token_model
|
|
18
|
+
|
|
19
|
+
Token = get_token_model()
|
|
20
|
+
token = Token.objects.get(key='abc123')
|
|
21
|
+
"""
|
|
22
|
+
model_string = get_setting('SHARED_AUTH_TOKEN_MODEL', 'shared_auth.SharedToken')
|
|
23
|
+
|
|
24
|
+
try:
|
|
25
|
+
return apps.get_model(model_string, require_ready=False)
|
|
26
|
+
except ValueError:
|
|
27
|
+
raise ImproperlyConfigured(
|
|
28
|
+
f"SHARED_AUTH_TOKEN_MODEL deve estar no formato 'app_label.model_name'. "
|
|
29
|
+
f"Recebido: '{model_string}'"
|
|
30
|
+
)
|
|
31
|
+
except LookupError:
|
|
32
|
+
raise ImproperlyConfigured(
|
|
33
|
+
f"SHARED_AUTH_TOKEN_MODEL refere-se ao model '{model_string}' "
|
|
34
|
+
f"que não foi instalado ou é inválido."
|
|
35
|
+
)
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def get_organization_model():
|
|
39
|
+
"""
|
|
40
|
+
Retorna o model de Organization configurado ou o padrão.
|
|
41
|
+
|
|
42
|
+
Usage:
|
|
43
|
+
from shared_auth.utils import get_organization_model
|
|
44
|
+
|
|
45
|
+
Organization = get_organization_model()
|
|
46
|
+
org = Organization.objects.get(id=1)
|
|
47
|
+
"""
|
|
48
|
+
model_string = get_setting('SHARED_AUTH_ORGANIZATION_MODEL', 'shared_auth.SharedOrganization')
|
|
49
|
+
|
|
50
|
+
try:
|
|
51
|
+
return apps.get_model(model_string, require_ready=False)
|
|
52
|
+
except ValueError:
|
|
53
|
+
raise ImproperlyConfigured(
|
|
54
|
+
f"SHARED_AUTH_ORGANIZATION_MODEL deve estar no formato 'app_label.model_name'. "
|
|
55
|
+
f"Recebido: '{model_string}'"
|
|
56
|
+
)
|
|
57
|
+
except LookupError:
|
|
58
|
+
raise ImproperlyConfigured(
|
|
59
|
+
f"SHARED_AUTH_ORGANIZATION_MODEL refere-se ao model '{model_string}' "
|
|
60
|
+
f"que não foi instalado ou é inválido."
|
|
61
|
+
)
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
def get_user_model():
|
|
65
|
+
"""
|
|
66
|
+
Retorna o model de User configurado ou o padrão.
|
|
67
|
+
|
|
68
|
+
Usage:
|
|
69
|
+
from shared_auth.utils import get_user_model
|
|
70
|
+
|
|
71
|
+
User = get_user_model()
|
|
72
|
+
user = User.objects.get(id=1)
|
|
73
|
+
"""
|
|
74
|
+
model_string = get_setting('SHARED_AUTH_USER_MODEL', 'shared_auth.User')
|
|
75
|
+
|
|
76
|
+
try:
|
|
77
|
+
return apps.get_model(model_string, require_ready=False)
|
|
78
|
+
except ValueError:
|
|
79
|
+
raise ImproperlyConfigured(
|
|
80
|
+
f"SHARED_AUTH_USER_MODEL deve estar no formato 'app_label.model_name'. "
|
|
81
|
+
f"Recebido: '{model_string}'"
|
|
82
|
+
)
|
|
83
|
+
except LookupError:
|
|
84
|
+
raise ImproperlyConfigured(
|
|
85
|
+
f"SHARED_AUTH_USER_MODEL refere-se ao model '{model_string}' "
|
|
86
|
+
f"que não foi instalado ou é inválido."
|
|
87
|
+
)
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
def get_member_model():
|
|
91
|
+
"""
|
|
92
|
+
Retorna o model de Member configurado ou o padrão.
|
|
93
|
+
|
|
94
|
+
Usage:
|
|
95
|
+
from shared_auth.utils import get_member_model
|
|
96
|
+
|
|
97
|
+
Member = get_member_model()
|
|
98
|
+
member = Member.objects.get(id=1)
|
|
99
|
+
"""
|
|
100
|
+
model_string = get_setting('SHARED_AUTH_MEMBER_MODEL', 'shared_auth.SharedMember')
|
|
101
|
+
|
|
102
|
+
try:
|
|
103
|
+
return apps.get_model(model_string, require_ready=False)
|
|
104
|
+
except ValueError:
|
|
105
|
+
raise ImproperlyConfigured(
|
|
106
|
+
f"SHARED_AUTH_MEMBER_MODEL deve estar no formato 'app_label.model_name'. "
|
|
107
|
+
f"Recebido: '{model_string}'"
|
|
108
|
+
)
|
|
109
|
+
except LookupError:
|
|
110
|
+
raise ImproperlyConfigured(
|
|
111
|
+
f"SHARED_AUTH_MEMBER_MODEL refere-se ao model '{model_string}' "
|
|
112
|
+
f"que não foi instalado ou é inválido."
|
|
113
|
+
)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{maquinaweb_shared_auth-0.2.32 → maquinaweb_shared_auth-0.2.34}/shared_auth/storage_backend.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|