maquinaweb-shared-auth 0.1.6__py3-none-any.whl → 0.1.8__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.
- {maquinaweb_shared_auth-0.1.6.dist-info → maquinaweb_shared_auth-0.1.8.dist-info}/METADATA +1 -1
- maquinaweb_shared_auth-0.1.8.dist-info/RECORD +18 -0
- shared_auth/__init__.py +1 -16
- shared_auth/app.py +4 -1
- shared_auth/decorators.py +5 -8
- shared_auth/managers.py +2 -1
- shared_auth/middleware.py +33 -20
- shared_auth/models.py +5 -56
- shared_auth/permissions.py +15 -9
- maquinaweb_shared_auth-0.1.6.dist-info/RECORD +0 -18
- {maquinaweb_shared_auth-0.1.6.dist-info → maquinaweb_shared_auth-0.1.8.dist-info}/WHEEL +0 -0
- {maquinaweb_shared_auth-0.1.6.dist-info → maquinaweb_shared_auth-0.1.8.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
shared_auth/__init__.py,sha256=Ta8lIbyn22J6wU-TgWeSvdDHS4NBRf4Sv1Ag8VtY-bE,152
|
|
2
|
+
shared_auth/app.py,sha256=EHoLKlpW41o6ZxcH184aMhnWQxkVp9fH2_-89RjMz-4,215
|
|
3
|
+
shared_auth/authentication.py,sha256=btrTjBszPrKKfKA4F0pOOzaxnfASgXb1y2cxQwOWbnk,1515
|
|
4
|
+
shared_auth/conf.py,sha256=-jdnCokMvWvVKllfsxNYCsPk1Vo3MDRq4Y1MsO16oeA,411
|
|
5
|
+
shared_auth/decorators.py,sha256=k1GurkcJUL_WKK1wNEfFNfjo5Td_S7v5YI_3E-zi9kc,3336
|
|
6
|
+
shared_auth/exceptions.py,sha256=eiII-REupK6GeFinisteYO3FsGUDAN5zAajXPhTREm8,404
|
|
7
|
+
shared_auth/fields.py,sha256=RAcmFh1D_nkbai_7t_OrPZhfhAipesy5kKnEj4LUvvM,1254
|
|
8
|
+
shared_auth/managers.py,sha256=ykfa11rMR3axuc_Kl_ab_SJ_R6pufwJS2h3SVr318-w,7089
|
|
9
|
+
shared_auth/middleware.py,sha256=4IUr5qWEpJfhwCkUTxv8jkcltasn2ZFuCWL93qrK6jI,6270
|
|
10
|
+
shared_auth/mixins.py,sha256=3ARghQ4TvtENKoA5UTOHTrRHa6ufMRVJJHGFkV8-BL8,7550
|
|
11
|
+
shared_auth/models.py,sha256=tMT84SA99V7lt-nfvP73fklN6pAidWxgHO04NgEZh3M,5342
|
|
12
|
+
shared_auth/permissions.py,sha256=t1YVLBKnpAo4pmSNvqC9mW08CdOE99q2fpf-Heuo_Bs,2712
|
|
13
|
+
shared_auth/router.py,sha256=SbM5YEoxxg2zMns1kfFmsK9YrgqqVfc4-riniYY7rbQ,651
|
|
14
|
+
shared_auth/serializers.py,sha256=TDpuZVsOL-6igINSOOOyELWbTUeet4XWRoBkvcMGjW4,4290
|
|
15
|
+
maquinaweb_shared_auth-0.1.8.dist-info/METADATA,sha256=WMNJObfGD6DhTXlqScKnEBlL68x8qlWOPhEeJrNhuig,27150
|
|
16
|
+
maquinaweb_shared_auth-0.1.8.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
17
|
+
maquinaweb_shared_auth-0.1.8.dist-info/top_level.txt,sha256=msyYRy02ZV7zz7GR1raUI5LXGFIFn2TIkgkeKZqKufE,12
|
|
18
|
+
maquinaweb_shared_auth-0.1.8.dist-info/RECORD,,
|
shared_auth/__init__.py
CHANGED
|
@@ -1,21 +1,6 @@
|
|
|
1
1
|
"""
|
|
2
2
|
Biblioteca compartilhada para acesso aos models de autenticação
|
|
3
3
|
"""
|
|
4
|
-
from .models import (
|
|
5
|
-
SharedOrganization,
|
|
6
|
-
SharedUser,
|
|
7
|
-
SharedMember,
|
|
8
|
-
)
|
|
9
|
-
from .exceptions import (
|
|
10
|
-
OrganizationNotFoundError,
|
|
11
|
-
UserNotFoundError,
|
|
12
|
-
)
|
|
13
4
|
|
|
14
5
|
__version__ = '1.0.0'
|
|
15
|
-
|
|
16
|
-
'SharedOrganization',
|
|
17
|
-
'SharedUser',
|
|
18
|
-
'SharedMember',
|
|
19
|
-
'OrganizationNotFoundError',
|
|
20
|
-
'UserNotFoundError',
|
|
21
|
-
]
|
|
6
|
+
default_app_config = "shared_auth.app.SharedAuthConfig"
|
shared_auth/app.py
CHANGED
shared_auth/decorators.py
CHANGED
|
@@ -3,8 +3,10 @@ Decorators para views funcionais
|
|
|
3
3
|
"""
|
|
4
4
|
|
|
5
5
|
from functools import wraps
|
|
6
|
+
|
|
6
7
|
from django.http import JsonResponse
|
|
7
|
-
|
|
8
|
+
|
|
9
|
+
from .models import SharedOrganization, SharedToken, SharedUser
|
|
8
10
|
|
|
9
11
|
|
|
10
12
|
def require_auth(view_func):
|
|
@@ -52,16 +54,13 @@ def require_organization(view_func):
|
|
|
52
54
|
@wraps(view_func)
|
|
53
55
|
@require_auth
|
|
54
56
|
def wrapped_view(request, *args, **kwargs):
|
|
55
|
-
if (
|
|
56
|
-
not hasattr(request.user, "logged_organization_id")
|
|
57
|
-
or not request.user.logged_organization_id
|
|
58
|
-
):
|
|
57
|
+
if not hasattr(request, "organization_id") or not request.organization_id:
|
|
59
58
|
return JsonResponse({"error": "Organização não definida"}, status=403)
|
|
60
59
|
|
|
61
60
|
# Buscar organização
|
|
62
61
|
try:
|
|
63
62
|
org = SharedOrganization.objects.using("auth_db").get(
|
|
64
|
-
pk=request.
|
|
63
|
+
pk=request.organization_id
|
|
65
64
|
)
|
|
66
65
|
|
|
67
66
|
if not org.is_active():
|
|
@@ -94,8 +93,6 @@ def require_same_organization(view_func):
|
|
|
94
93
|
|
|
95
94
|
# Aqui você precisa buscar o objeto e verificar
|
|
96
95
|
# Exemplo genérico - adapte conforme seu model
|
|
97
|
-
from django.apps import apps
|
|
98
|
-
|
|
99
96
|
# Tentar identificar o model pelo path
|
|
100
97
|
# Esta é uma implementação básica
|
|
101
98
|
# Em produção, você pode passar o model como parâmetro
|
shared_auth/managers.py
CHANGED
|
@@ -3,6 +3,7 @@ Managers customizados para os models compartilhados
|
|
|
3
3
|
"""
|
|
4
4
|
|
|
5
5
|
from django.db import models
|
|
6
|
+
from django.contrib.auth.models import UserManager
|
|
6
7
|
from .exceptions import OrganizationNotFoundError, UserNotFoundError
|
|
7
8
|
|
|
8
9
|
|
|
@@ -43,7 +44,7 @@ class SharedOrganizationManager(models.Manager):
|
|
|
43
44
|
return self.filter(cnpj__contains=clean_cnpj).first()
|
|
44
45
|
|
|
45
46
|
|
|
46
|
-
class SharedUserManager(
|
|
47
|
+
class SharedUserManager(UserManager):
|
|
47
48
|
"""Manager para SharedUser"""
|
|
48
49
|
|
|
49
50
|
def get_or_fail(self, user_id):
|
shared_auth/middleware.py
CHANGED
|
@@ -2,12 +2,11 @@
|
|
|
2
2
|
Middlewares para autenticação compartilhada
|
|
3
3
|
"""
|
|
4
4
|
|
|
5
|
-
from django.utils.deprecation import MiddlewareMixin
|
|
6
5
|
from django.http import JsonResponse
|
|
6
|
+
from django.utils.deprecation import MiddlewareMixin
|
|
7
7
|
|
|
8
|
-
from . import SharedMember
|
|
9
8
|
from .authentication import SharedTokenAuthentication
|
|
10
|
-
from .models import SharedToken, SharedUser
|
|
9
|
+
from .models import SharedMember, SharedOrganization, SharedToken, SharedUser
|
|
11
10
|
|
|
12
11
|
|
|
13
12
|
class SharedAuthMiddleware(MiddlewareMixin):
|
|
@@ -46,7 +45,7 @@ class SharedAuthMiddleware(MiddlewareMixin):
|
|
|
46
45
|
token = self._get_token_from_request(request)
|
|
47
46
|
|
|
48
47
|
if not token:
|
|
49
|
-
request.user = None
|
|
48
|
+
# request.user = None
|
|
50
49
|
request.auth = None
|
|
51
50
|
return None
|
|
52
51
|
|
|
@@ -56,16 +55,16 @@ class SharedAuthMiddleware(MiddlewareMixin):
|
|
|
56
55
|
user = SharedUser.objects.using("auth_db").get(pk=token_obj.user_id)
|
|
57
56
|
|
|
58
57
|
if not user.is_active or user.deleted_at is not None:
|
|
59
|
-
request.user = None
|
|
58
|
+
# request.user = None
|
|
60
59
|
request.auth = None
|
|
61
60
|
return None
|
|
62
61
|
|
|
63
62
|
# Adicionar ao request
|
|
64
|
-
request.user = user
|
|
63
|
+
# request.user = user
|
|
65
64
|
request.auth = token_obj
|
|
66
65
|
|
|
67
66
|
except (SharedToken.DoesNotExist, SharedUser.DoesNotExist):
|
|
68
|
-
request.user = None
|
|
67
|
+
# request.user = None
|
|
69
68
|
request.auth = None
|
|
70
69
|
|
|
71
70
|
return None
|
|
@@ -149,6 +148,9 @@ class OrganizationMiddleware(MiddlewareMixin):
|
|
|
149
148
|
organization_id = self._determine_organization_id(request)
|
|
150
149
|
user = self._authenticate_user(request)
|
|
151
150
|
|
|
151
|
+
if not organization_id and not user:
|
|
152
|
+
return
|
|
153
|
+
|
|
152
154
|
if organization_id and user:
|
|
153
155
|
organization_id = self._validate_organization_membership(
|
|
154
156
|
user, organization_id
|
|
@@ -157,9 +159,12 @@ class OrganizationMiddleware(MiddlewareMixin):
|
|
|
157
159
|
return
|
|
158
160
|
|
|
159
161
|
request.organization_id = organization_id
|
|
160
|
-
request.organization =
|
|
161
|
-
|
|
162
|
-
|
|
162
|
+
request.organization = (
|
|
163
|
+
SharedOrganization.objects.using("auth_db")
|
|
164
|
+
.filter(pk=organization_id)
|
|
165
|
+
.first()
|
|
166
|
+
)
|
|
167
|
+
|
|
163
168
|
@staticmethod
|
|
164
169
|
def _authenticate_user(request):
|
|
165
170
|
data = SharedTokenAuthentication().authenticate(request)
|
|
@@ -172,6 +177,7 @@ class OrganizationMiddleware(MiddlewareMixin):
|
|
|
172
177
|
return org_id
|
|
173
178
|
|
|
174
179
|
return self._get_organization_from_user(request)
|
|
180
|
+
|
|
175
181
|
@staticmethod
|
|
176
182
|
def _get_organization_from_header(request):
|
|
177
183
|
if header_value := request.headers.get("X-Organization"):
|
|
@@ -180,22 +186,26 @@ class OrganizationMiddleware(MiddlewareMixin):
|
|
|
180
186
|
except (ValueError, TypeError):
|
|
181
187
|
pass
|
|
182
188
|
return None
|
|
189
|
+
|
|
183
190
|
@staticmethod
|
|
184
191
|
def _get_organization_from_user(request):
|
|
192
|
+
"""
|
|
193
|
+
Retorna a primeira organização do usuário autenticado
|
|
194
|
+
"""
|
|
185
195
|
if not request.user.is_authenticated:
|
|
186
196
|
return None
|
|
187
197
|
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
198
|
+
# Buscar a primeira organização que o usuário pertence
|
|
199
|
+
member = (
|
|
200
|
+
SharedMember.objects.using("auth_db")
|
|
201
|
+
.filter(user_id=request.user.pk)
|
|
202
|
+
.first()
|
|
203
|
+
)
|
|
204
|
+
|
|
205
|
+
return member.organization_id if member else None
|
|
193
206
|
|
|
194
|
-
return None
|
|
195
207
|
@staticmethod
|
|
196
|
-
def _validate_organization_membership(
|
|
197
|
-
user, organization_id
|
|
198
|
-
):
|
|
208
|
+
def _validate_organization_membership(user, organization_id):
|
|
199
209
|
try:
|
|
200
210
|
member = get_member(user, organization_id)
|
|
201
211
|
if not member and not user.is_superuser:
|
|
@@ -204,5 +214,8 @@ class OrganizationMiddleware(MiddlewareMixin):
|
|
|
204
214
|
except Exception:
|
|
205
215
|
return None
|
|
206
216
|
|
|
217
|
+
|
|
207
218
|
def get_member(user, organization_id):
|
|
208
|
-
return SharedMember.objects.filter(
|
|
219
|
+
return SharedMember.objects.filter(
|
|
220
|
+
user_id=user.pk, organization_id=organization_id
|
|
221
|
+
).first()
|
shared_auth/models.py
CHANGED
|
@@ -3,12 +3,14 @@ Models READ-ONLY para acesso aos dados de autenticação
|
|
|
3
3
|
ATENÇÃO: Estes models NÃO devem ser usados para criar migrations
|
|
4
4
|
"""
|
|
5
5
|
|
|
6
|
+
from django.contrib.auth.models import AbstractUser
|
|
6
7
|
from django.db import models
|
|
7
|
-
|
|
8
|
+
|
|
9
|
+
from .conf import MEMBER_TABLE, ORGANIZATION_TABLE, USER_TABLE
|
|
8
10
|
from .managers import (
|
|
11
|
+
SharedMemberManager,
|
|
9
12
|
SharedOrganizationManager,
|
|
10
13
|
SharedUserManager,
|
|
11
|
-
SharedMemberManager,
|
|
12
14
|
)
|
|
13
15
|
|
|
14
16
|
|
|
@@ -132,23 +134,15 @@ class SharedOrganization(models.Model):
|
|
|
132
134
|
return self.deleted_at is None
|
|
133
135
|
|
|
134
136
|
|
|
135
|
-
class SharedUser(
|
|
137
|
+
class SharedUser(AbstractUser):
|
|
136
138
|
"""
|
|
137
139
|
Model READ-ONLY da tabela auth_user
|
|
138
140
|
"""
|
|
139
141
|
|
|
140
|
-
username = models.CharField(max_length=150)
|
|
141
|
-
first_name = models.CharField(max_length=150, blank=True)
|
|
142
|
-
last_name = models.CharField(max_length=150, blank=True)
|
|
143
|
-
email = models.EmailField()
|
|
144
|
-
is_staff = models.BooleanField(default=False)
|
|
145
|
-
is_active = models.BooleanField(default=True)
|
|
146
|
-
is_superuser = models.BooleanField(default=False)
|
|
147
142
|
date_joined = models.DateTimeField()
|
|
148
143
|
last_login = models.DateTimeField(null=True, blank=True)
|
|
149
144
|
|
|
150
145
|
# Campos customizados
|
|
151
|
-
logged_organization_id = models.IntegerField(null=True, blank=True)
|
|
152
146
|
createdat = models.DateTimeField()
|
|
153
147
|
updatedat = models.DateTimeField()
|
|
154
148
|
deleted_at = models.DateTimeField(null=True, blank=True)
|
|
@@ -160,51 +154,6 @@ class SharedUser(models.Model):
|
|
|
160
154
|
db_table = USER_TABLE
|
|
161
155
|
app_label = "shared_auth"
|
|
162
156
|
|
|
163
|
-
def __str__(self):
|
|
164
|
-
return self.get_full_name() or self.username
|
|
165
|
-
|
|
166
|
-
def get_full_name(self):
|
|
167
|
-
"""Retorna nome completo"""
|
|
168
|
-
return f"{self.first_name} {self.last_name}".strip()
|
|
169
|
-
|
|
170
|
-
@property
|
|
171
|
-
def logged_organization(self):
|
|
172
|
-
"""
|
|
173
|
-
Acessa organização logada (lazy loading)
|
|
174
|
-
|
|
175
|
-
Usage:
|
|
176
|
-
user = SharedUser.objects.get(pk=1)
|
|
177
|
-
org = user.logged_organization
|
|
178
|
-
print(org.name)
|
|
179
|
-
"""
|
|
180
|
-
if self.logged_organization_id:
|
|
181
|
-
return SharedOrganization.objects.get_or_fail(self.logged_organization_id)
|
|
182
|
-
return None
|
|
183
|
-
|
|
184
|
-
@property
|
|
185
|
-
def organizations(self):
|
|
186
|
-
"""
|
|
187
|
-
Retorna todas as organizações do usuário
|
|
188
|
-
|
|
189
|
-
Usage:
|
|
190
|
-
orgs = user.organizations
|
|
191
|
-
"""
|
|
192
|
-
member_orgs = SharedMember.objects.for_user(self.pk)
|
|
193
|
-
org_ids = member_orgs.values_list("organization_id", flat=True)
|
|
194
|
-
return SharedOrganization.objects.filter(pk__in=org_ids)
|
|
195
|
-
|
|
196
|
-
@property
|
|
197
|
-
def memberships(self):
|
|
198
|
-
"""
|
|
199
|
-
Retorna memberships do usuário
|
|
200
|
-
|
|
201
|
-
Usage:
|
|
202
|
-
memberships = user.memberships
|
|
203
|
-
for m in memberships:
|
|
204
|
-
print(m.organization.name)
|
|
205
|
-
"""
|
|
206
|
-
return SharedMember.objects.for_user(self.pk)
|
|
207
|
-
|
|
208
157
|
|
|
209
158
|
class SharedMember(models.Model):
|
|
210
159
|
"""
|
shared_auth/permissions.py
CHANGED
|
@@ -4,6 +4,8 @@ Permissões customizadas para DRF
|
|
|
4
4
|
|
|
5
5
|
from rest_framework import permissions
|
|
6
6
|
|
|
7
|
+
from shared_auth.middleware import get_member
|
|
8
|
+
|
|
7
9
|
|
|
8
10
|
class IsAuthenticated(permissions.BasePermission):
|
|
9
11
|
"""
|
|
@@ -26,10 +28,10 @@ class HasActiveOrganization(permissions.BasePermission):
|
|
|
26
28
|
message = "Organização ativa necessária."
|
|
27
29
|
|
|
28
30
|
def has_permission(self, request, view):
|
|
29
|
-
if not request.user or not hasattr(request
|
|
31
|
+
if not request.user or not hasattr(request, "organization_id"):
|
|
30
32
|
return False
|
|
31
33
|
|
|
32
|
-
if not request.
|
|
34
|
+
if not request.organization_id:
|
|
33
35
|
return False
|
|
34
36
|
|
|
35
37
|
# Verificar se organização está ativa
|
|
@@ -37,7 +39,7 @@ class HasActiveOrganization(permissions.BasePermission):
|
|
|
37
39
|
|
|
38
40
|
try:
|
|
39
41
|
org = SharedOrganization.objects.using("auth_db").get(
|
|
40
|
-
pk=request.
|
|
42
|
+
pk=request.organization_id
|
|
41
43
|
)
|
|
42
44
|
return org.is_active()
|
|
43
45
|
except SharedOrganization.DoesNotExist:
|
|
@@ -54,13 +56,17 @@ class IsSameOrganization(permissions.BasePermission):
|
|
|
54
56
|
message = "Você não tem permissão para acessar este recurso."
|
|
55
57
|
|
|
56
58
|
def has_object_permission(self, request, view, obj):
|
|
57
|
-
if not hasattr(request
|
|
59
|
+
if not hasattr(request, "organization_id"):
|
|
58
60
|
return False
|
|
59
61
|
|
|
60
62
|
if not hasattr(obj, "organization_id"):
|
|
61
63
|
return True # Se objeto não tem org, permite
|
|
62
64
|
|
|
63
|
-
|
|
65
|
+
# Verifica se o usuário é membro da organização do objeto
|
|
66
|
+
if not get_member(request.user, obj.organization_id):
|
|
67
|
+
return False
|
|
68
|
+
|
|
69
|
+
return obj.organization_id == request.organization_id
|
|
64
70
|
|
|
65
71
|
|
|
66
72
|
class IsOwnerOrSameOrganization(permissions.BasePermission):
|
|
@@ -78,9 +84,9 @@ class IsOwnerOrSameOrganization(permissions.BasePermission):
|
|
|
78
84
|
return True
|
|
79
85
|
|
|
80
86
|
# Verificar se é da mesma organização
|
|
81
|
-
if hasattr(obj, "organization_id") and hasattr(
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
87
|
+
if hasattr(obj, "organization_id") and hasattr(request, "organization_id"):
|
|
88
|
+
# Verifica se o usuário é membro da organização do objeto
|
|
89
|
+
if get_member(request.user, obj.organization_id):
|
|
90
|
+
return obj.organization_id == request.organization_id
|
|
85
91
|
|
|
86
92
|
return False
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
shared_auth/__init__.py,sha256=WbDmRRdOp0nn5I_ksYjhAa2HRtXe0wxtGY6qnaiPlB8,397
|
|
2
|
-
shared_auth/app.py,sha256=aOgzojmmabOvWfNqw7YFaM6L_dB8lsnF_No5HiRTFPk,152
|
|
3
|
-
shared_auth/authentication.py,sha256=btrTjBszPrKKfKA4F0pOOzaxnfASgXb1y2cxQwOWbnk,1515
|
|
4
|
-
shared_auth/conf.py,sha256=-jdnCokMvWvVKllfsxNYCsPk1Vo3MDRq4Y1MsO16oeA,411
|
|
5
|
-
shared_auth/decorators.py,sha256=LTDHiVX36O65jbcCUqtoNPNkQ1suDH4fICXVyduZ1BM,3444
|
|
6
|
-
shared_auth/exceptions.py,sha256=eiII-REupK6GeFinisteYO3FsGUDAN5zAajXPhTREm8,404
|
|
7
|
-
shared_auth/fields.py,sha256=RAcmFh1D_nkbai_7t_OrPZhfhAipesy5kKnEj4LUvvM,1254
|
|
8
|
-
shared_auth/managers.py,sha256=yPv40NxoOWyrJygLt6xYAHGAlKcvOYGRoUb6zKqLm4Y,7041
|
|
9
|
-
shared_auth/middleware.py,sha256=y2blhI44nJL39UqyOxBgJjiafwuZEb7G0Zlvfge6rlo,6068
|
|
10
|
-
shared_auth/mixins.py,sha256=3ARghQ4TvtENKoA5UTOHTrRHa6ufMRVJJHGFkV8-BL8,7550
|
|
11
|
-
shared_auth/models.py,sha256=iszFHOhpD78tqcXaxxZ9_57wLdRq9i_ZsHWrfy5W9Nc,6997
|
|
12
|
-
shared_auth/permissions.py,sha256=kkEMtClmV9VB3EOhKDyinSr4r5v9g-3DCCKNtqpaTz8,2473
|
|
13
|
-
shared_auth/router.py,sha256=SbM5YEoxxg2zMns1kfFmsK9YrgqqVfc4-riniYY7rbQ,651
|
|
14
|
-
shared_auth/serializers.py,sha256=TDpuZVsOL-6igINSOOOyELWbTUeet4XWRoBkvcMGjW4,4290
|
|
15
|
-
maquinaweb_shared_auth-0.1.6.dist-info/METADATA,sha256=5iR99adsbbr8A5lCgPUrMDsfACRDdJyUnq1E48Jlc7w,27150
|
|
16
|
-
maquinaweb_shared_auth-0.1.6.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
17
|
-
maquinaweb_shared_auth-0.1.6.dist-info/top_level.txt,sha256=msyYRy02ZV7zz7GR1raUI5LXGFIFn2TIkgkeKZqKufE,12
|
|
18
|
-
maquinaweb_shared_auth-0.1.6.dist-info/RECORD,,
|
|
File without changes
|
{maquinaweb_shared_auth-0.1.6.dist-info → maquinaweb_shared_auth-0.1.8.dist-info}/top_level.txt
RENAMED
|
File without changes
|