maquinaweb-shared-auth 0.2.30__py3-none-any.whl → 0.2.31__py3-none-any.whl

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.

@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: maquinaweb-shared-auth
3
- Version: 0.2.30
3
+ Version: 0.2.31
4
4
  Summary: Models read-only para autenticação compartilhada entre projetos Django.
5
5
  Author-email: Seu Nome <seuemail@dominio.com>
6
6
  License: MIT
@@ -743,7 +743,7 @@ SharedOrganization.objects.main_organizations() # QuerySet (is_branch=False)
743
743
  SharedOrganization.objects.by_cnpj('12.345.678/0001-90') # Org | None
744
744
  ```
745
745
 
746
- #### SharedUserManager
746
+ #### UserManager
747
747
 
748
748
  ```python
749
749
  from shared_auth.models import User
@@ -5,17 +5,17 @@ shared_auth/conf.py,sha256=WlSXQB7p3BfE3BL6WR6EDYpCHQEjDlxQlyf8dTfClsk,621
5
5
  shared_auth/decorators.py,sha256=RT-Qfi7oGBo6PvWJRR1dqJUQdU6ZOf9p-8mV3rZmqQ0,3237
6
6
  shared_auth/exceptions.py,sha256=VKamHjBl2yjXG2RsMrLrXru1_Q9IJXmy4xmDcXlpWsU,627
7
7
  shared_auth/fields.py,sha256=RAcmFh1D_nkbai_7t_OrPZhfhAipesy5kKnEj4LUvvM,1254
8
- shared_auth/managers.py,sha256=A9y-X4ixVXhsNxgr3YD4DtuN4ufrX7LbM_JPwJ0Y3aA,9176
8
+ shared_auth/managers.py,sha256=NpIDMY7BWl1pKZKCepuNDxz7eekEUhKkOUYsWGbwyos,6715
9
9
  shared_auth/middleware.py,sha256=72GF8kGijbhw98v2Q-1sXBXk-7Bamfyvypm9h8xLX_I,6112
10
- shared_auth/mixins.py,sha256=9TJk07hlHXnTYu0tPNr7VAXd7VL9fyXayMaFERifLLY,7389
11
- shared_auth/models.py,sha256=vCyssDwKfWRE3ofl6LK_CB1-y5O-_6uvJyGZGoCnb44,6574
10
+ shared_auth/mixins.py,sha256=BSYNTWYjLRGuxfy7x-uAaNZmrTMsm67ogAQzjrU2DoQ,7388
11
+ shared_auth/models.py,sha256=QMY_Oyr4x7AtSNAFV3UfoJY0YBZwFKePvfVNWt-vQTc,6562
12
12
  shared_auth/permissions.py,sha256=FNIp12ePOUlXVp26zNMAyEtzX9kwyP7RuNIgaaCXtPA,2671
13
13
  shared_auth/router.py,sha256=zYidJ7j40lQLrhkCtAQAp-rQLhua_UF0X7SDzYRcV5w,668
14
- shared_auth/serializers.py,sha256=VmajFqnAHB5wyxsdd5_WVegAQygi0KNOMk7vScCPHiQ,7385
14
+ shared_auth/serializers.py,sha256=vziJOlBrPy5tgTCgfr6Sp6gihyI6_1Gkn05BtpmYZxY,11149
15
15
  shared_auth/storage_backend.py,sha256=Eqkjz8aF5UrOpRwYl-J0Td95IObfxnJ8eLQDJVFM3Io,184
16
16
  shared_auth/urls.py,sha256=591wWEWJPaHEGkcOZ8yvfgxddRyOcZLgOc0vNtF7XRI,289
17
17
  shared_auth/views.py,sha256=2hyLnYSWUscfq-jVcskt-ukzDt4vg6IXeKjRDRu9RXk,1519
18
- maquinaweb_shared_auth-0.2.30.dist-info/METADATA,sha256=bIuaOJDn7kPoK8tE16uQWf3qgqPO3RixJpJ9HiYYXUk,26331
19
- maquinaweb_shared_auth-0.2.30.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
20
- maquinaweb_shared_auth-0.2.30.dist-info/top_level.txt,sha256=msyYRy02ZV7zz7GR1raUI5LXGFIFn2TIkgkeKZqKufE,12
21
- maquinaweb_shared_auth-0.2.30.dist-info/RECORD,,
18
+ maquinaweb_shared_auth-0.2.31.dist-info/METADATA,sha256=EwURfIcN3-VtVx-YVE48f2Xsx_1nlf9xC_oIEhEZPi8,26325
19
+ maquinaweb_shared_auth-0.2.31.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
20
+ maquinaweb_shared_auth-0.2.31.dist-info/top_level.txt,sha256=msyYRy02ZV7zz7GR1raUI5LXGFIFn2TIkgkeKZqKufE,12
21
+ maquinaweb_shared_auth-0.2.31.dist-info/RECORD,,
shared_auth/managers.py CHANGED
@@ -45,8 +45,8 @@ class SharedOrganizationManager(models.Manager):
45
45
  return self.filter(cnpj__contains=clean_cnpj).first()
46
46
 
47
47
 
48
- class SharedUserManager(UserManager):
49
- """Manager para SharedUser"""
48
+ class UserManager(UserManager):
49
+ """Manager para User"""
50
50
 
51
51
  def get_or_fail(self, user_id):
52
52
  """Busca usuário ou lança exceção"""
@@ -89,38 +89,16 @@ class OrganizationQuerySetMixin:
89
89
 
90
90
  def with_organization_data(self):
91
91
  """
92
- Pré-carrega dados de organizações (evita N+1 queries)
93
-
94
- Faz uma única query bulk para buscar todas as organizações necessárias
95
- e cacheia nos objetos usando _cached_organization.
96
-
97
- IMPORTANTE: Este método força a avaliação do QuerySet e aplica cache.
98
- Para manter a chain de QuerySet, chame este método por último.
99
-
100
- Usage:
101
- # Sem otimização (N+1 queries)
102
- rascunhos = Rascunho.objects.all()
103
- for r in rascunhos:
104
- print(r.organization.name) # Query individual para cada
105
-
106
- # Com otimização (2 queries total)
107
- rascunhos = Rascunho.objects.all().with_organization_data()
108
- for r in rascunhos:
109
- print(r.organization.name) # Usa cache, sem queries extras
92
+ Pré-carrega dados de organizações (evita N+1)
110
93
 
111
94
  Returns:
112
- Self (QuerySet) com _prefetch_done=True e objetos cacheados
95
+ Lista de objetos com _cached_organization
113
96
  """
114
- # Marcar que o prefetch foi feito
115
- self._prefetch_done = True
116
-
117
- # Forçar avaliação do queryset
118
- objects = list(self)
97
+ objects = list(self.all())
98
+ from .models import SharedOrganization
119
99
 
120
100
  if not objects:
121
- return self
122
-
123
- from .models import SharedOrganization
101
+ return objects
124
102
 
125
103
  # Coletar IDs únicos
126
104
  org_ids = set(obj.organization_id for obj in objects)
@@ -134,10 +112,7 @@ class OrganizationQuerySetMixin:
134
112
  for obj in objects:
135
113
  obj._cached_organization = organizations.get(obj.organization_id)
136
114
 
137
- # Armazenar os objetos cacheados no queryset
138
- self._result_cache = objects
139
-
140
- return self
115
+ return objects
141
116
 
142
117
 
143
118
  class UserQuerySetMixin:
@@ -153,27 +128,14 @@ class UserQuerySetMixin:
153
128
 
154
129
  def with_user_data(self):
155
130
  """
156
- Pré-carrega dados de usuários (evita N+1 queries)
157
-
158
- Usage:
159
- # Com otimização (2 queries total)
160
- rascunhos = Rascunho.objects.all().with_user_data()
161
- for r in rascunhos:
162
- print(r.user.email) # Usa cache, sem queries extras
163
-
164
- Returns:
165
- Self (QuerySet) com objetos cacheados
131
+ Pré-carrega dados de usuários (evita N+1)
166
132
  """
167
133
  from .models import User
168
134
 
169
- # Marcar que o prefetch foi feito
170
- self._prefetch_done = True
171
-
172
- # Forçar avaliação do queryset
173
- objects = list(self)
135
+ objects = list(self.all())
174
136
 
175
137
  if not objects:
176
- return self
138
+ return objects
177
139
 
178
140
  user_ids = set(obj.user_id for obj in objects)
179
141
 
@@ -182,10 +144,7 @@ class UserQuerySetMixin:
182
144
  for obj in objects:
183
145
  obj._cached_user = users.get(obj.user_id)
184
146
 
185
- # Armazenar os objetos cacheados no queryset
186
- self._result_cache = objects
187
-
188
- return self
147
+ return objects
189
148
 
190
149
 
191
150
  class OrganizationUserQuerySetMixin(OrganizationQuerySetMixin, UserQuerySetMixin):
@@ -193,39 +152,14 @@ class OrganizationUserQuerySetMixin(OrganizationQuerySetMixin, UserQuerySetMixin
193
152
 
194
153
  def with_auth_data(self):
195
154
  """
196
- Pré-carrega dados de organizações E usuários (evita N+1 queries)
197
-
198
- Faz apenas 3 queries no total, independente da quantidade de objetos:
199
- 1. Query dos objetos principais
200
- 2. Query bulk das organizações
201
- 3. Query bulk dos usuários
202
-
203
- Usage:
204
- # Sem otimização (1 + N + N queries)
205
- rascunhos = Rascunho.objects.all() # 1 query
206
- for r in rascunhos:
207
- print(r.organization.name) # N queries
208
- print(r.user.email) # N queries
209
-
210
- # Com otimização (3 queries total)
211
- rascunhos = Rascunho.objects.all().with_auth_data()
212
- for r in rascunhos:
213
- print(r.organization.name) # Cache
214
- print(r.user.email) # Cache
215
-
216
- Returns:
217
- Self (QuerySet) com objetos cacheados
155
+ Pré-carrega dados de organizações E usuários (evita N+1)
218
156
  """
219
157
  from .models import SharedOrganization, User
220
158
 
221
- # Marcar que o prefetch foi feito
222
- self._prefetch_done = True
223
-
224
- # Forçar avaliação do queryset
225
- objects = list(self)
159
+ objects = list(self.all())
226
160
 
227
161
  if not objects:
228
- return self
162
+ return objects
229
163
 
230
164
  # Coletar IDs
231
165
  org_ids = set(obj.organization_id for obj in objects)
@@ -243,10 +177,7 @@ class OrganizationUserQuerySetMixin(OrganizationQuerySetMixin, UserQuerySetMixin
243
177
  obj._cached_organization = organizations.get(obj.organization_id)
244
178
  obj._cached_user = users.get(obj.user_id)
245
179
 
246
- # Armazenar os objetos cacheados no queryset
247
- self._result_cache = objects
248
-
249
- return self
180
+ return objects
250
181
 
251
182
  def create_with_validation(self, organization_id, user_id, **kwargs):
252
183
  """
shared_auth/mixins.py CHANGED
@@ -227,7 +227,6 @@ class LoggedOrganizationMixin(viewsets.ModelViewSet):
227
227
  return queryset.none()
228
228
 
229
229
  organization_id = self.get_organization_id()
230
-
231
230
  if hasattr(queryset.model, "organization_id"):
232
231
  return queryset.filter(organization_id=organization_id)
233
232
  elif hasattr(queryset.model, "organization"):
shared_auth/models.py CHANGED
@@ -10,7 +10,7 @@ from django.db import models
10
10
 
11
11
  from .conf import MEMBER_TABLE, ORGANIZATION_TABLE, TOKEN_TABLE, USER_TABLE
12
12
  from .exceptions import OrganizationNotFoundError
13
- from .managers import SharedMemberManager, SharedOrganizationManager, SharedUserManager
13
+ from .managers import SharedMemberManager, SharedOrganizationManager, UserManager
14
14
  from .storage_backend import Storage
15
15
 
16
16
 
@@ -155,7 +155,7 @@ class User(AbstractUser):
155
155
  updatedat = models.DateTimeField()
156
156
  deleted_at = models.DateTimeField(null=True, blank=True)
157
157
 
158
- objects = SharedUserManager()
158
+ objects = UserManager()
159
159
 
160
160
  class Meta:
161
161
  managed = False
@@ -1,11 +1,43 @@
1
1
  """
2
2
  Serializers compartilhados para DRF
3
+
4
+ Separação de responsabilidades:
5
+ - CreateSerializerMixin: apenas para criação (seta IDs do request)
6
+ - SerializerMixin: listagem com dados aninhados + criação (compatibilidade com código existente)
7
+
8
+ Se quiser usar separadamente:
9
+ - Use apenas *CreateSerializerMixin para create
10
+ - Use apenas *SerializerMixin para listagem
11
+ - Ou herde ambos se precisar
3
12
  """
4
13
 
5
14
  from rest_framework import serializers
6
15
 
7
16
  from .models import SharedOrganization, User
8
17
 
18
+ # ==================== ORGANIZATION SERIALIZERS ====================
19
+
20
+
21
+ class OrganizationCreateSerializerMixin(serializers.ModelSerializer):
22
+ """
23
+ Mixin APENAS para criação.
24
+ Automaticamente seta organization_id no create a partir do request context.
25
+
26
+ Usage:
27
+ class RascunhoCreateSerializer(OrganizationCreateSerializerMixin, serializers.ModelSerializer):
28
+ class Meta:
29
+ model = Rascunho
30
+ fields = ['id', 'titulo', 'conteudo']
31
+ """
32
+
33
+ def create(self, validated_data):
34
+ """Automatically set organization_id from request context"""
35
+ if self.context.get("request") and hasattr(
36
+ self.context["request"], "organization_id"
37
+ ):
38
+ validated_data["organization_id"] = self.context["request"].organization_id
39
+ return super().create(validated_data)
40
+
9
41
 
10
42
  class OrganizationSerializerMixin(serializers.ModelSerializer):
11
43
  """
@@ -30,6 +62,18 @@ class OrganizationSerializerMixin(serializers.ModelSerializer):
30
62
  class Meta:
31
63
  model = Rascunho
32
64
  fields = ['id', 'titulo', 'organization']
65
+
66
+ # Ou apenas para listagem (sem create):
67
+ class RascunhoListSerializer(OrganizationSerializerMixin, serializers.ModelSerializer):
68
+ class Meta:
69
+ model = Rascunho
70
+ fields = ['id', 'titulo', 'organization']
71
+
72
+ # Ou combinar com create:
73
+ class RascunhoFullSerializer(OrganizationSerializerMixin, OrganizationCreateSerializerMixin):
74
+ class Meta:
75
+ model = Rascunho
76
+ fields = ['id', 'titulo', 'organization']
33
77
  """
34
78
 
35
79
  organization = serializers.SerializerMethodField()
@@ -55,14 +99,6 @@ class OrganizationSerializerMixin(serializers.ModelSerializer):
55
99
  except Exception:
56
100
  return None
57
101
 
58
- def create(self, validated_data):
59
- """Automatically set organization_id from request context"""
60
- if self.context.get("request") and hasattr(
61
- self.context["request"], "organization_id"
62
- ):
63
- validated_data["organization_id"] = self.context["request"].organization_id
64
- return super().create(validated_data)
65
-
66
102
 
67
103
  class OrganizationSerializer(serializers.ModelSerializer):
68
104
  class Meta:
@@ -70,21 +106,26 @@ class OrganizationSerializer(serializers.ModelSerializer):
70
106
  fields = "__all__"
71
107
 
72
108
 
73
- class UserSerializer(serializers.ModelSerializer):
74
- class Meta:
75
- model = User
76
- fields = [
77
- "id",
78
- "username",
79
- "first_name",
80
- "last_name",
81
- "email",
82
- "is_active",
83
- "is_staff",
84
- "is_superuser",
85
- "date_joined",
86
- "last_login",
87
- ]
109
+ # ==================== USER SERIALIZERS ====================
110
+
111
+
112
+ class UserCreateSerializerMixin(serializers.ModelSerializer):
113
+ """
114
+ Mixin APENAS para criação.
115
+ Automaticamente seta user_id no create a partir do request context.
116
+
117
+ Usage:
118
+ class RascunhoCreateSerializer(UserCreateSerializerMixin, serializers.ModelSerializer):
119
+ class Meta:
120
+ model = Rascunho
121
+ fields = ['id', 'titulo', 'conteudo']
122
+ """
123
+
124
+ def create(self, validated_data):
125
+ """Automatically set user_id from request context"""
126
+ if self.context.get("request") and hasattr(self.context["request"], "user"):
127
+ validated_data["user_id"] = self.context["request"].user.id
128
+ return super().create(validated_data)
88
129
 
89
130
 
90
131
  class UserSerializerMixin(serializers.ModelSerializer):
@@ -110,6 +151,18 @@ class UserSerializerMixin(serializers.ModelSerializer):
110
151
  class Meta:
111
152
  model = Rascunho
112
153
  fields = ['id', 'titulo', 'user']
154
+
155
+ # Ou apenas para listagem (sem create):
156
+ class RascunhoListSerializer(UserSerializerMixin, serializers.ModelSerializer):
157
+ class Meta:
158
+ model = Rascunho
159
+ fields = ['id', 'titulo', 'user']
160
+
161
+ # Ou combinar com create:
162
+ class RascunhoFullSerializer(UserSerializerMixin, UserCreateSerializerMixin):
163
+ class Meta:
164
+ model = Rascunho
165
+ fields = ['id', 'titulo', 'user']
113
166
  """
114
167
 
115
168
  user = serializers.SerializerMethodField()
@@ -131,10 +184,47 @@ class UserSerializerMixin(serializers.ModelSerializer):
131
184
  except Exception:
132
185
  return None
133
186
 
187
+
188
+ class UserSerializer(serializers.ModelSerializer):
189
+ class Meta:
190
+ model = User
191
+ fields = [
192
+ "id",
193
+ "username",
194
+ "first_name",
195
+ "last_name",
196
+ "email",
197
+ "is_active",
198
+ "is_staff",
199
+ "is_superuser",
200
+ "date_joined",
201
+ "last_login",
202
+ ]
203
+
204
+
205
+ # ==================== COMBINED ORGANIZATION + USER SERIALIZERS ====================
206
+
207
+
208
+ class OrganizationUserCreateSerializerMixin(serializers.ModelSerializer):
209
+ """
210
+ Mixin APENAS para criação com organization + user.
211
+ Automaticamente seta organization_id e user_id no create a partir do request context.
212
+
213
+ Usage:
214
+ class RascunhoCreateSerializer(OrganizationUserCreateSerializerMixin, serializers.ModelSerializer):
215
+ class Meta:
216
+ model = Rascunho
217
+ fields = ['id', 'titulo', 'conteudo']
218
+ """
219
+
134
220
  def create(self, validated_data):
135
- """Automatically set user_id from request context"""
136
- if self.context.get("request") and hasattr(self.context["request"], "user"):
137
- validated_data["user_id"] = self.context["request"].user.id
221
+ """Automatically set both organization_id and user_id from request context"""
222
+ if self.context.get("request"):
223
+ request = self.context["request"]
224
+ if hasattr(request, "organization_id"):
225
+ validated_data["organization_id"] = request.organization_id
226
+ if hasattr(request, "user"):
227
+ validated_data["user_id"] = request.user.id
138
228
  return super().create(validated_data)
139
229
 
140
230
 
@@ -164,24 +254,43 @@ class OrganizationUserSerializerMixin(OrganizationSerializerMixin, UserSerialize
164
254
  class Meta:
165
255
  model = Rascunho
166
256
  fields = ['id', 'titulo', 'conteudo', 'organization', 'user']
257
+
258
+ # Ou apenas para listagem (sem create):
259
+ class RascunhoListSerializer(OrganizationUserSerializerMixin, serializers.ModelSerializer):
260
+ class Meta:
261
+ model = Rascunho
262
+ fields = ['id', 'titulo', 'organization', 'user']
263
+
264
+ # Ou combinar com create:
265
+ class RascunhoFullSerializer(OrganizationUserSerializerMixin, OrganizationUserCreateSerializerMixin):
266
+ class Meta:
267
+ model = Rascunho
268
+ fields = ['id', 'titulo', 'organization', 'user']
167
269
  """
168
270
 
169
- def create(self, validated_data):
170
- """Automatically set both organization_id and user_id from request context"""
171
- if self.context.get("request"):
172
- request = self.context["request"]
173
- if hasattr(request, "organization_id"):
174
- validated_data["organization_id"] = request.organization_id
175
- if hasattr(request, "user"):
176
- validated_data["user_id"] = request.user.id
177
- return super(UserSerializerMixin, self).create(validated_data)
271
+ pass
272
+
273
+
274
+ # ==================== SIMPLIFIED VERSIONS ====================
178
275
 
179
276
 
180
- # Versões simplificadas (opcional)
181
277
  class OrganizationSimpleSerializerMixin(serializers.ModelSerializer):
182
278
  """
183
279
  Versão simplificada que retorna apenas campos essenciais da organização
184
280
  e automaticamente seta organization_id no create a partir do request context.
281
+
282
+ Usage:
283
+ # Para listagem:
284
+ class RascunhoListSerializer(OrganizationSimpleSerializerMixin, serializers.ModelSerializer):
285
+ class Meta:
286
+ model = Rascunho
287
+ fields = ['id', 'titulo', 'organization']
288
+
289
+ # Para criar com organization:
290
+ class RascunhoCreateSerializer(OrganizationSimpleSerializerMixin, OrganizationCreateSerializerMixin):
291
+ class Meta:
292
+ model = Rascunho
293
+ fields = ['id', 'titulo', 'organization']
185
294
  """
186
295
 
187
296
  organization = serializers.SerializerMethodField()
@@ -194,22 +303,27 @@ class OrganizationSimpleSerializerMixin(serializers.ModelSerializer):
194
303
  "name": org.name,
195
304
  "cnpj": org.cnpj,
196
305
  }
197
- except:
306
+ except Exception:
198
307
  return None
199
308
 
200
- def create(self, validated_data):
201
- """Automatically set organization_id from request context"""
202
- if self.context.get("request") and hasattr(
203
- self.context["request"], "organization_id"
204
- ):
205
- validated_data["organization_id"] = self.context["request"].organization_id
206
- return super().create(validated_data)
207
-
208
309
 
209
310
  class UserSimpleSerializerMixin(serializers.ModelSerializer):
210
311
  """
211
312
  Versão simplificada que retorna apenas campos essenciais do usuário
212
313
  e automaticamente seta user_id no create a partir do request context.
314
+
315
+ Usage:
316
+ # Para listagem:
317
+ class RascunhoListSerializer(UserSimpleSerializerMixin, serializers.ModelSerializer):
318
+ class Meta:
319
+ model = Rascunho
320
+ fields = ['id', 'titulo', 'user']
321
+
322
+ # Para criar com user:
323
+ class RascunhoCreateSerializer(UserSimpleSerializerMixin, UserCreateSerializerMixin):
324
+ class Meta:
325
+ model = Rascunho
326
+ fields = ['id', 'titulo', 'user']
213
327
  """
214
328
 
215
329
  user = serializers.SerializerMethodField()
@@ -222,11 +336,5 @@ class UserSimpleSerializerMixin(serializers.ModelSerializer):
222
336
  "email": user.email,
223
337
  "full_name": user.get_full_name(),
224
338
  }
225
- except:
339
+ except Exception:
226
340
  return None
227
-
228
- def create(self, validated_data):
229
- """Automatically set user_id from request context"""
230
- if self.context.get("request") and hasattr(self.context["request"], "user"):
231
- validated_data["user_id"] = self.context["request"].user.id
232
- return super().create(validated_data)