oxutils 0.1.6__py3-none-any.whl → 0.1.14__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.
- oxutils/__init__.py +2 -2
- oxutils/audit/migrations/0001_initial.py +2 -2
- oxutils/audit/models.py +2 -2
- oxutils/constants.py +6 -0
- oxutils/jwt/auth.py +150 -1
- oxutils/jwt/models.py +81 -0
- oxutils/jwt/tokens.py +69 -0
- oxutils/jwt/utils.py +45 -0
- oxutils/logger/__init__.py +10 -0
- oxutils/logger/receivers.py +10 -6
- oxutils/logger/settings.py +2 -2
- oxutils/models/base.py +102 -0
- oxutils/models/fields.py +79 -0
- oxutils/oxiliere/apps.py +9 -1
- oxutils/oxiliere/authorization.py +45 -0
- oxutils/oxiliere/caches.py +13 -11
- oxutils/oxiliere/checks.py +31 -0
- oxutils/oxiliere/constants.py +3 -0
- oxutils/oxiliere/context.py +16 -0
- oxutils/oxiliere/exceptions.py +16 -0
- oxutils/oxiliere/management/commands/grant_tenant_owners.py +19 -0
- oxutils/oxiliere/management/commands/init_oxiliere_system.py +30 -11
- oxutils/oxiliere/middleware.py +65 -11
- oxutils/oxiliere/models.py +146 -9
- oxutils/oxiliere/permissions.py +28 -35
- oxutils/oxiliere/schemas.py +16 -6
- oxutils/oxiliere/signals.py +5 -0
- oxutils/oxiliere/utils.py +36 -1
- oxutils/pagination/cursor.py +367 -0
- oxutils/permissions/__init__.py +0 -0
- oxutils/permissions/actions.py +57 -0
- oxutils/permissions/admin.py +3 -0
- oxutils/permissions/apps.py +10 -0
- oxutils/permissions/caches.py +33 -0
- oxutils/permissions/checks.py +188 -0
- oxutils/permissions/constants.py +0 -0
- oxutils/permissions/controllers.py +344 -0
- oxutils/permissions/exceptions.py +60 -0
- oxutils/permissions/management/__init__.py +0 -0
- oxutils/permissions/management/commands/__init__.py +0 -0
- oxutils/permissions/management/commands/load_permission_preset.py +112 -0
- oxutils/permissions/migrations/0001_initial.py +112 -0
- oxutils/permissions/migrations/0002_alter_grant_role.py +19 -0
- oxutils/permissions/migrations/0003_alter_grant_options_alter_group_options_and_more.py +33 -0
- oxutils/permissions/migrations/__init__.py +0 -0
- oxutils/permissions/models.py +171 -0
- oxutils/permissions/perms.py +201 -0
- oxutils/permissions/queryset.py +92 -0
- oxutils/permissions/schemas.py +276 -0
- oxutils/permissions/services.py +663 -0
- oxutils/permissions/tests.py +3 -0
- oxutils/permissions/utils.py +784 -0
- oxutils/settings.py +14 -194
- oxutils/users/apps.py +1 -1
- oxutils/users/migrations/0001_initial.py +47 -0
- oxutils/users/migrations/0002_alter_user_first_name_alter_user_last_name.py +23 -0
- oxutils/users/migrations/0003_user_photo.py +18 -0
- oxutils/users/models.py +3 -0
- oxutils/utils.py +25 -0
- {oxutils-0.1.6.dist-info → oxutils-0.1.14.dist-info}/METADATA +14 -11
- oxutils-0.1.14.dist-info/RECORD +123 -0
- oxutils/jwt/client.py +0 -123
- oxutils/jwt/constants.py +0 -1
- oxutils/s3/settings.py +0 -34
- oxutils/s3/storages.py +0 -130
- oxutils-0.1.6.dist-info/RECORD +0 -88
- /oxutils/{s3 → pagination}/__init__.py +0 -0
- {oxutils-0.1.6.dist-info → oxutils-0.1.14.dist-info}/WHEEL +0 -0
oxutils/jwt/client.py
DELETED
|
@@ -1,123 +0,0 @@
|
|
|
1
|
-
import jwt
|
|
2
|
-
import requests
|
|
3
|
-
from typing import Dict, Any, Optional
|
|
4
|
-
from datetime import datetime, timedelta
|
|
5
|
-
from django.core.exceptions import ImproperlyConfigured
|
|
6
|
-
from oxutils.settings import oxi_settings
|
|
7
|
-
from .constants import JWT_ALGORITHM
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
_jwks_cache: Optional[Dict[str, Any]] = None
|
|
11
|
-
_jwks_cache_time: Optional[datetime] = None
|
|
12
|
-
_jwks_cache_ttl = timedelta(hours=1)
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
def get_jwks_url() -> str:
|
|
16
|
-
"""
|
|
17
|
-
Get JWKS URL from settings.
|
|
18
|
-
|
|
19
|
-
Returns:
|
|
20
|
-
The configured JWKS URL.
|
|
21
|
-
|
|
22
|
-
Raises:
|
|
23
|
-
ImproperlyConfigured: If jwt_jwks_url is not configured.
|
|
24
|
-
"""
|
|
25
|
-
if not oxi_settings.jwt_jwks_url:
|
|
26
|
-
raise ImproperlyConfigured(
|
|
27
|
-
"JWT JWKS URL is not configured. Set OXI_JWT_JWKS_URL environment variable."
|
|
28
|
-
)
|
|
29
|
-
return oxi_settings.jwt_jwks_url
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
def fetch_jwks(force_refresh: bool = False) -> Dict[str, Any]:
|
|
33
|
-
"""
|
|
34
|
-
Fetch JWKS from the authentication server with caching.
|
|
35
|
-
|
|
36
|
-
Args:
|
|
37
|
-
force_refresh: Force refresh the cache even if not expired.
|
|
38
|
-
|
|
39
|
-
Returns:
|
|
40
|
-
Dict containing the JWKS.
|
|
41
|
-
|
|
42
|
-
Raises:
|
|
43
|
-
ImproperlyConfigured: If JWKS cannot be fetched.
|
|
44
|
-
"""
|
|
45
|
-
global _jwks_cache, _jwks_cache_time
|
|
46
|
-
|
|
47
|
-
now = datetime.now()
|
|
48
|
-
|
|
49
|
-
# Return cached JWKS if valid
|
|
50
|
-
if not force_refresh and _jwks_cache is not None and _jwks_cache_time is not None:
|
|
51
|
-
if now - _jwks_cache_time < _jwks_cache_ttl:
|
|
52
|
-
return _jwks_cache
|
|
53
|
-
|
|
54
|
-
# Fetch fresh JWKS
|
|
55
|
-
jwks_url = get_jwks_url()
|
|
56
|
-
try:
|
|
57
|
-
response = requests.get(jwks_url, timeout=10)
|
|
58
|
-
response.raise_for_status()
|
|
59
|
-
_jwks_cache = response.json()
|
|
60
|
-
_jwks_cache_time = now
|
|
61
|
-
return _jwks_cache
|
|
62
|
-
except requests.RequestException as e:
|
|
63
|
-
raise ImproperlyConfigured(
|
|
64
|
-
f"Failed to fetch JWKS from {jwks_url}: {str(e)}"
|
|
65
|
-
)
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
def get_key(kid: str):
|
|
69
|
-
"""
|
|
70
|
-
Get the public key for a given Key ID (kid).
|
|
71
|
-
|
|
72
|
-
Args:
|
|
73
|
-
kid: The Key ID from the JWT header.
|
|
74
|
-
|
|
75
|
-
Returns:
|
|
76
|
-
RSA public key for verification.
|
|
77
|
-
|
|
78
|
-
Raises:
|
|
79
|
-
ValueError: If the kid is not found in JWKS.
|
|
80
|
-
"""
|
|
81
|
-
jwks = fetch_jwks()
|
|
82
|
-
|
|
83
|
-
for key in jwks.get("keys", []):
|
|
84
|
-
if key.get("kid") == kid:
|
|
85
|
-
return jwt.algorithms.RSAAlgorithm.from_jwk(key)
|
|
86
|
-
|
|
87
|
-
raise ValueError(f"Unknown Key ID (kid): {kid}")
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
def verify_token(token: str) -> Dict[str, Any]:
|
|
91
|
-
"""
|
|
92
|
-
Verify and decode a JWT token.
|
|
93
|
-
|
|
94
|
-
Args:
|
|
95
|
-
token: The JWT token string to verify.
|
|
96
|
-
|
|
97
|
-
Returns:
|
|
98
|
-
Dict containing the decoded token payload.
|
|
99
|
-
|
|
100
|
-
Raises:
|
|
101
|
-
jwt.InvalidTokenError: If token is invalid or expired.
|
|
102
|
-
ValueError: If kid is not found.
|
|
103
|
-
"""
|
|
104
|
-
try:
|
|
105
|
-
headers = jwt.get_unverified_header(token)
|
|
106
|
-
kid = headers.get("kid")
|
|
107
|
-
|
|
108
|
-
if not kid:
|
|
109
|
-
raise ValueError("Token header missing 'kid' field")
|
|
110
|
-
|
|
111
|
-
key = get_key(kid)
|
|
112
|
-
return jwt.decode(token, key=key, algorithms=JWT_ALGORITHM)
|
|
113
|
-
except jwt.InvalidTokenError:
|
|
114
|
-
raise
|
|
115
|
-
except Exception as e:
|
|
116
|
-
raise jwt.InvalidTokenError(f"Token verification failed: {str(e)}")
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
def clear_jwks_cache() -> None:
|
|
120
|
-
"""Clear the cached JWKS. Useful for testing or key rotation."""
|
|
121
|
-
global _jwks_cache, _jwks_cache_time
|
|
122
|
-
_jwks_cache = None
|
|
123
|
-
_jwks_cache_time = None
|
oxutils/jwt/constants.py
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
JWT_ALGORITHM = ["RS256"]
|
oxutils/s3/settings.py
DELETED
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
import os
|
|
2
|
-
|
|
3
|
-
USE_S3 = os.getenv('USE_S3') == 'TRUE'
|
|
4
|
-
|
|
5
|
-
if USE_S3:
|
|
6
|
-
# aws settings
|
|
7
|
-
AWS_ACCESS_KEY_ID = os.getenv('AWS_ACCESS_KEY_ID')
|
|
8
|
-
AWS_SECRET_ACCESS_KEY = os.getenv('AWS_SECRET_ACCESS_KEY')
|
|
9
|
-
AWS_STORAGE_BUCKET_NAME = os.getenv('AWS_STORAGE_BUCKET_NAME')
|
|
10
|
-
AWS_DEFAULT_ACL = 'public-read'
|
|
11
|
-
AWS_S3_CUSTOM_DOMAIN = f'{AWS_STORAGE_BUCKET_NAME}.s3.amazonaws.com'
|
|
12
|
-
AWS_S3_OBJECT_PARAMETERS = {'CacheControl': 'max-age=86400'}
|
|
13
|
-
|
|
14
|
-
# s3 static settings
|
|
15
|
-
STATIC_LOCATION = 'static'
|
|
16
|
-
STATIC_URL = f'https://{AWS_S3_CUSTOM_DOMAIN}/{STATIC_LOCATION}/'
|
|
17
|
-
STATICFILES_STORAGE = 'oxutils.s3.storages.StaticStorage'
|
|
18
|
-
|
|
19
|
-
# s3 public media settings
|
|
20
|
-
PUBLIC_MEDIA_LOCATION = 'media'
|
|
21
|
-
MEDIA_URL = f'https://{AWS_S3_CUSTOM_DOMAIN}/{PUBLIC_MEDIA_LOCATION}/'
|
|
22
|
-
DEFAULT_FILE_STORAGE = 'oxutils.s3.storages.PublicMediaStorage'
|
|
23
|
-
|
|
24
|
-
# s3 private media settings
|
|
25
|
-
PRIVATE_MEDIA_LOCATION = 'private'
|
|
26
|
-
PRIVATE_FILE_STORAGE = 'oxutils.s3.storages.PrivateMediaStorage'
|
|
27
|
-
else:
|
|
28
|
-
STATIC_URL = '/static/'
|
|
29
|
-
STATIC_ROOT = os.path.join(BASE_DIR, 'static')
|
|
30
|
-
|
|
31
|
-
STATICFILES_DIRS = (os.path.join(BASE_DIR, 'static'),)
|
|
32
|
-
|
|
33
|
-
MEDIA_URL = '/media/'
|
|
34
|
-
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
|
oxutils/s3/storages.py
DELETED
|
@@ -1,130 +0,0 @@
|
|
|
1
|
-
from storages.backends.s3boto3 import S3Boto3Storage
|
|
2
|
-
from oxutils.settings import oxi_settings
|
|
3
|
-
from django.core.exceptions import ImproperlyConfigured
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
class StaticStorage(S3Boto3Storage):
|
|
7
|
-
def __init__(self, *args, **kwargs):
|
|
8
|
-
if not oxi_settings.use_static_s3:
|
|
9
|
-
raise ImproperlyConfigured(
|
|
10
|
-
"StaticStorage requires OXI_USE_STATIC_S3=True"
|
|
11
|
-
)
|
|
12
|
-
|
|
13
|
-
self.access_key = oxi_settings.static_access_key_id
|
|
14
|
-
self.secret_key = oxi_settings.static_secret_access_key
|
|
15
|
-
self.bucket_name = oxi_settings.static_storage_bucket_name
|
|
16
|
-
self.custom_domain = oxi_settings.static_s3_custom_domain
|
|
17
|
-
self.location = oxi_settings.static_location
|
|
18
|
-
self.default_acl = oxi_settings.static_default_acl
|
|
19
|
-
self.file_overwrite = False
|
|
20
|
-
|
|
21
|
-
self._validate_required_fields('StaticStorage', {
|
|
22
|
-
'access_key': self.access_key,
|
|
23
|
-
'secret_key': self.secret_key,
|
|
24
|
-
'bucket_name': self.bucket_name,
|
|
25
|
-
'custom_domain': self.custom_domain,
|
|
26
|
-
})
|
|
27
|
-
|
|
28
|
-
super().__init__(*args, **kwargs)
|
|
29
|
-
|
|
30
|
-
@staticmethod
|
|
31
|
-
def _validate_required_fields(storage_name: str, fields: dict):
|
|
32
|
-
"""Validate that all required fields are present."""
|
|
33
|
-
missing = [name for name, value in fields.items() if not value]
|
|
34
|
-
if missing:
|
|
35
|
-
raise ImproperlyConfigured(
|
|
36
|
-
f"{storage_name} is missing required configuration: {', '.join(missing)}"
|
|
37
|
-
)
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
class PublicMediaStorage(S3Boto3Storage):
|
|
41
|
-
def __init__(self, *args, **kwargs):
|
|
42
|
-
if not oxi_settings.use_default_s3:
|
|
43
|
-
raise ImproperlyConfigured(
|
|
44
|
-
"PublicMediaStorage requires OXI_USE_DEFAULT_S3=True"
|
|
45
|
-
)
|
|
46
|
-
|
|
47
|
-
if oxi_settings.use_static_s3_as_default:
|
|
48
|
-
self.access_key = oxi_settings.static_access_key_id
|
|
49
|
-
self.secret_key = oxi_settings.static_secret_access_key
|
|
50
|
-
self.bucket_name = oxi_settings.static_storage_bucket_name
|
|
51
|
-
self.custom_domain = oxi_settings.static_s3_custom_domain
|
|
52
|
-
else:
|
|
53
|
-
self.access_key = oxi_settings.default_s3_access_key_id
|
|
54
|
-
self.secret_key = oxi_settings.default_s3_secret_access_key
|
|
55
|
-
self.bucket_name = oxi_settings.default_s3_storage_bucket_name
|
|
56
|
-
self.custom_domain = oxi_settings.default_s3_custom_domain
|
|
57
|
-
|
|
58
|
-
self.location = oxi_settings.default_s3_location
|
|
59
|
-
self.default_acl = oxi_settings.default_s3_default_acl
|
|
60
|
-
self.file_overwrite = False
|
|
61
|
-
|
|
62
|
-
StaticStorage._validate_required_fields('PublicMediaStorage', {
|
|
63
|
-
'access_key': self.access_key,
|
|
64
|
-
'secret_key': self.secret_key,
|
|
65
|
-
'bucket_name': self.bucket_name,
|
|
66
|
-
'custom_domain': self.custom_domain,
|
|
67
|
-
})
|
|
68
|
-
|
|
69
|
-
super().__init__(*args, **kwargs)
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
class PrivateMediaStorage(S3Boto3Storage):
|
|
73
|
-
def __init__(self, *args, **kwargs):
|
|
74
|
-
if not oxi_settings.use_private_s3:
|
|
75
|
-
raise ImproperlyConfigured(
|
|
76
|
-
"PrivateMediaStorage requires OXI_USE_PRIVATE_S3=True"
|
|
77
|
-
)
|
|
78
|
-
|
|
79
|
-
self.access_key = oxi_settings.private_s3_access_key_id
|
|
80
|
-
self.secret_key = oxi_settings.private_s3_secret_access_key
|
|
81
|
-
self.bucket_name = oxi_settings.private_s3_storage_bucket_name
|
|
82
|
-
self.custom_domain = oxi_settings.private_s3_custom_domain
|
|
83
|
-
self.location = oxi_settings.private_s3_location
|
|
84
|
-
self.default_acl = oxi_settings.private_s3_default_acl
|
|
85
|
-
self.file_overwrite = False
|
|
86
|
-
self.querystring_auth = True
|
|
87
|
-
self.querystring_expire = 3600
|
|
88
|
-
|
|
89
|
-
StaticStorage._validate_required_fields('PrivateMediaStorage', {
|
|
90
|
-
'access_key': self.access_key,
|
|
91
|
-
'secret_key': self.secret_key,
|
|
92
|
-
'bucket_name': self.bucket_name,
|
|
93
|
-
'custom_domain': self.custom_domain,
|
|
94
|
-
})
|
|
95
|
-
|
|
96
|
-
super().__init__(*args, **kwargs)
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
class LogStorage(S3Boto3Storage):
|
|
100
|
-
def __init__(self, *args, **kwargs):
|
|
101
|
-
if not oxi_settings.use_log_s3:
|
|
102
|
-
raise ImproperlyConfigured(
|
|
103
|
-
"LogStorage requires OXI_USE_LOG_S3=True"
|
|
104
|
-
)
|
|
105
|
-
|
|
106
|
-
if oxi_settings.use_private_s3_as_log:
|
|
107
|
-
self.access_key = oxi_settings.private_s3_access_key_id
|
|
108
|
-
self.secret_key = oxi_settings.private_s3_secret_access_key
|
|
109
|
-
self.bucket_name = oxi_settings.private_s3_storage_bucket_name
|
|
110
|
-
self.custom_domain = oxi_settings.private_s3_custom_domain
|
|
111
|
-
else:
|
|
112
|
-
self.access_key = oxi_settings.log_s3_access_key_id
|
|
113
|
-
self.secret_key = oxi_settings.log_s3_secret_access_key
|
|
114
|
-
self.bucket_name = oxi_settings.log_s3_storage_bucket_name
|
|
115
|
-
self.custom_domain = oxi_settings.log_s3_custom_domain
|
|
116
|
-
|
|
117
|
-
self.location = f'{oxi_settings.log_s3_location}/{oxi_settings.service_name}'
|
|
118
|
-
self.default_acl = oxi_settings.log_s3_default_acl
|
|
119
|
-
self.file_overwrite = False
|
|
120
|
-
self.querystring_auth = True
|
|
121
|
-
self.querystring_expire = 3600
|
|
122
|
-
|
|
123
|
-
StaticStorage._validate_required_fields('LogStorage', {
|
|
124
|
-
'access_key': self.access_key,
|
|
125
|
-
'secret_key': self.secret_key,
|
|
126
|
-
'bucket_name': self.bucket_name,
|
|
127
|
-
'custom_domain': self.custom_domain,
|
|
128
|
-
})
|
|
129
|
-
|
|
130
|
-
super().__init__(*args, **kwargs)
|
oxutils-0.1.6.dist-info/RECORD
DELETED
|
@@ -1,88 +0,0 @@
|
|
|
1
|
-
oxutils/__init__.py,sha256=dR4pOinh8r-27oEc1KHgk1_rJ0MY6ieLFiQ0Y9gvIbQ,536
|
|
2
|
-
oxutils/apps.py,sha256=8pO8eXUZeKYn8fPo0rkoytmHACwDNuTNhdRcpkPTxGM,347
|
|
3
|
-
oxutils/audit/__init__.py,sha256=uonc00G73Xm7RwRHVWD-wBn8lJYNCq3iBgnRGMWAEWs,583
|
|
4
|
-
oxutils/audit/apps.py,sha256=xvnmB5Z6nLV7ejzhSeQbesTkwRoFygoPFob8H5QTHgU,304
|
|
5
|
-
oxutils/audit/export.py,sha256=MVf2RhLzXatBaGK7bIEvSY1VTwEojrPEKwYMvH1stwE,7992
|
|
6
|
-
oxutils/audit/masks.py,sha256=BRCz2m8dbaLgqn5umxpWCwn9mT6Z_ww_WIedl36AmPM,2345
|
|
7
|
-
oxutils/audit/migrations/0001_initial.py,sha256=xDOxV6NqkU8yuEDPvqG2AKANKrOJsOIAEJn5IbuLLFU,2151
|
|
8
|
-
oxutils/audit/migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
9
|
-
oxutils/audit/models.py,sha256=NWzZjwgRGB212PeSb0E_aSxSComrTSR0knt2aBCiWhg,2100
|
|
10
|
-
oxutils/audit/settings.py,sha256=NNCFaN6tilDj-0WsVRK9HJNcr2nJOBYJT9E8cY5n9iI,133
|
|
11
|
-
oxutils/audit/utils.py,sha256=VJESUbMb5bC155XNlkIvr8DMc_o6ZTAIn5r8NDr7k_E,581
|
|
12
|
-
oxutils/celery/__init__.py,sha256=29jo4DfdvOoThX-jfL0ZiDjsy3-Z_fNhwHVJaLO5rsk,29
|
|
13
|
-
oxutils/celery/base.py,sha256=qLlBU2XvT2zj8qszy8togqH7hM_wUYyWWA3JAQPPJx0,3378
|
|
14
|
-
oxutils/celery/settings.py,sha256=njhHBErpcFczV2e23NCPX_Jxs015jr4dIig4Is_wbgE,33
|
|
15
|
-
oxutils/conf.py,sha256=TR0RIVaLMHvG0gm3NgbKsoU25eJFBjItAhknFJdiOiQ,231
|
|
16
|
-
oxutils/constants.py,sha256=CW-ho9Vasys-L2ZNJHFMovG5NzHNU6GPldE9vqyVcLM,89
|
|
17
|
-
oxutils/context/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
18
|
-
oxutils/context/site_name_processor.py,sha256=1gc0Td_3HVlUn9ThhQBCQ8kfnRnI88bEflK9vEzTvEc,225
|
|
19
|
-
oxutils/currency/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
20
|
-
oxutils/currency/admin.py,sha256=cCd4tXIZTctr3Ksa1jTEpaECw-on7aRHibAfYxEjGek,1831
|
|
21
|
-
oxutils/currency/apps.py,sha256=w35QaiH3BIjCYv2IU6AadENAyBOw7Hmejy9kT5e_law,194
|
|
22
|
-
oxutils/currency/controllers.py,sha256=xDvPBpgXYjCiWyhRQ09fifbdPRSZAG_HC28_sGRfRYc,3042
|
|
23
|
-
oxutils/currency/enums.py,sha256=AHm8zpYCyGv0WMnh8XHLa3cAJnQx3aNOCjGug2Q94VQ,141
|
|
24
|
-
oxutils/currency/migrations/0001_initial.py,sha256=GHypakExy4jW5iQ6hB9x2UUjBoPgaz0OaHNTcBU64Pw,1707
|
|
25
|
-
oxutils/currency/migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
26
|
-
oxutils/currency/models.py,sha256=-NrVq-degRc4sAO2BZ_LqSuIAP-IzCwwZJVxfYlNL8o,2448
|
|
27
|
-
oxutils/currency/schemas.py,sha256=4DyEjpL_HaMNDhKyu48fZtcXfRdemVP4rdyHUFit8uI,658
|
|
28
|
-
oxutils/currency/tests.py,sha256=mrbGGRNg5jwbTJtWWa7zSKdDyeB4vmgZCRc2nk6VY-g,60
|
|
29
|
-
oxutils/currency/utils.py,sha256=eNa9CNlOFC6NMZLJn8VTwLrkME9q7quMTX7NMSZtTv8,2074
|
|
30
|
-
oxutils/enums/__init__.py,sha256=gFhZG8ER6ArGZO5agWhdfs7NiD2h9FzrzfQRHq18dD0,40
|
|
31
|
-
oxutils/enums/audit.py,sha256=ju2Z9CrtdyPziRQ7oOe4Ygw85t9sW3jynO_1DkgZoAM,126
|
|
32
|
-
oxutils/enums/invoices.py,sha256=E33QGQeutZUqvlovJY0VGDxWUb0i_kdfhEiir1ARKuQ,201
|
|
33
|
-
oxutils/exceptions.py,sha256=CCjENOD0of6_noif2ajrpfbBLoG16DWa46iB9_uEe3M,3592
|
|
34
|
-
oxutils/functions.py,sha256=4stHj94VebWX0s1XeWshubMD2v8w8QztTWppbkTE_Gg,3246
|
|
35
|
-
oxutils/jwt/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
36
|
-
oxutils/jwt/auth.py,sha256=rO-xWNfug9Ok6zA7EIPvVkpD8TBUdq05CdrnMrL-t9Q,1597
|
|
37
|
-
oxutils/jwt/client.py,sha256=bskLpmSBrehi_snbo3Qbq1m99Kbfg2GP7jqfcXKHvys,3341
|
|
38
|
-
oxutils/jwt/constants.py,sha256=MUahZjm8plTYpHjLOMQCuH0H18lkIwS45EtRm617wq8,26
|
|
39
|
-
oxutils/locale/fr/LC_MESSAGES/django.po,sha256=APXt_8R99seCWjJyS5ELOawvRLvUqqBT32O252BaG5s,7971
|
|
40
|
-
oxutils/logger/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
41
|
-
oxutils/logger/receivers.py,sha256=EBpkwMCHYacOJvuOPzUtM_8ttWWetz17kIwoudGiV34,488
|
|
42
|
-
oxutils/logger/settings.py,sha256=aiKiJqNNkw1g5vQgjk3Zfh6UgY7jx-lbmcFgATiXrGI,1805
|
|
43
|
-
oxutils/mixins/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
44
|
-
oxutils/mixins/base.py,sha256=0cGY4mGKhL-hJTEBsbETYiaKMVuUgio5DISCv5iYtGI,589
|
|
45
|
-
oxutils/mixins/schemas.py,sha256=DGW0GQBJc9K7hwOJLX-fEryi7KCoY1QaCLny8fjtQMI,319
|
|
46
|
-
oxutils/mixins/services.py,sha256=i4MrkCE3y1W7Xrrz6YeMMaY9xMtCQs4WgBIpM7hrDTI,5399
|
|
47
|
-
oxutils/models/__init__.py,sha256=mR9hhncZMGKefovg9xSPBtb9Yu2AssAdta26ihcNvI4,77
|
|
48
|
-
oxutils/models/base.py,sha256=1HGHB8MnhPpaa1SpnUVgiknCSHTwajz5LxprB2zicbc,2884
|
|
49
|
-
oxutils/models/billing.py,sha256=aCDZcMx4CUyAwh3wgJGypAJl_fSEuWrL27-cSYv3gCs,3323
|
|
50
|
-
oxutils/models/invoice.py,sha256=nqphkhlBhssODm2H4dBYyb1cOmHS29fToER40UN0cXo,13216
|
|
51
|
-
oxutils/oxiliere/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
52
|
-
oxutils/oxiliere/admin.py,sha256=suMo4x8I3JBxAFBVIdE-5qnqZ6JAZV0FESABHOSc-vg,63
|
|
53
|
-
oxutils/oxiliere/apps.py,sha256=DAb8O1Vt4XPTIlFg5NB6SISTYRHyW3TY55-l7TC08Lo,148
|
|
54
|
-
oxutils/oxiliere/cacheops.py,sha256=VGG5qG5IsxvWJTu1aTlmsaDXV2aiuIMVdVcvHGHeY3g,163
|
|
55
|
-
oxutils/oxiliere/caches.py,sha256=PljqpDxkaE5F8Gsmvdqoq8W0MDh6aDtgXxCrN2T8b-4,976
|
|
56
|
-
oxutils/oxiliere/controllers.py,sha256=hL_snutY1EuSO0n06NDbjkz-3A3hkqa3sYGie3Grbmg,847
|
|
57
|
-
oxutils/oxiliere/enums.py,sha256=etpHgzsHTQKMrPIxVH-d592_DYSRJ2_o0c8bOdIza-8,201
|
|
58
|
-
oxutils/oxiliere/management/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
59
|
-
oxutils/oxiliere/management/commands/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
60
|
-
oxutils/oxiliere/management/commands/init_oxiliere_system.py,sha256=ogNQGARqUUfTv4JgZsRuEh4FInfMUO4nFHHCbgeLLbk,3659
|
|
61
|
-
oxutils/oxiliere/middleware.py,sha256=mGOUs0bjtp_TKkZRgcC6kE7euZrZ6mIG1PgKHBhTDCc,4013
|
|
62
|
-
oxutils/oxiliere/migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
63
|
-
oxutils/oxiliere/models.py,sha256=IqASvymJ6EcLc9bhxnas7-XXZStQYz7_UqroFkqS8xE,1543
|
|
64
|
-
oxutils/oxiliere/permissions.py,sha256=BVSbXqMa9Ohb1joBA_uXRCkYsYc3_CabhAWL9-VS4IU,3227
|
|
65
|
-
oxutils/oxiliere/schemas.py,sha256=kjX6N1INx9wikatniEM5s-ECuuVtDCcu6VEBbbEIdZE,1897
|
|
66
|
-
oxutils/oxiliere/settings.py,sha256=ZuKppEyrucWxvvYC2-wLap4RzKfaEfaRdjJnsNZzpuY,440
|
|
67
|
-
oxutils/oxiliere/tests.py,sha256=mrbGGRNg5jwbTJtWWa7zSKdDyeB4vmgZCRc2nk6VY-g,60
|
|
68
|
-
oxutils/oxiliere/utils.py,sha256=iZc3BjaqVSrZkELVpYsYiwMHC5MfDeDQPKn8iTsB3Bk,2488
|
|
69
|
-
oxutils/pdf/__init__.py,sha256=Uu_yOEd-FcNHIB7CV6y76c53wjL5Hce2GMjho8gnkbM,236
|
|
70
|
-
oxutils/pdf/printer.py,sha256=VVvpGU5GdSNTOP06wLqgm36ICDfRTRaRjmmiS-vJ0wM,2449
|
|
71
|
-
oxutils/pdf/utils.py,sha256=cn1Yc7KnjuATSQKM3hrYptCo0IsQurBdrNHh7Nu08b8,3786
|
|
72
|
-
oxutils/pdf/views.py,sha256=DBxCh_UXVywlvlWZh9sVBtYc0gZxMo7ut1j1U_gqPA4,6523
|
|
73
|
-
oxutils/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
74
|
-
oxutils/s3/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
75
|
-
oxutils/s3/settings.py,sha256=NIlVhaOzWdsepOgCpxdTTJRHfM0tM5EcAoy4kaFC1R8,1190
|
|
76
|
-
oxutils/s3/storages.py,sha256=gjQg05edVn6NuyfJZ-NwUB2lRWwg8GqgzHB8I1D5vbI,5402
|
|
77
|
-
oxutils/settings.py,sha256=mp_ZSf8bcCUe2Zc9YdOe_EtltBgIY2n_8lUERQtsIFk,9742
|
|
78
|
-
oxutils/types.py,sha256=DIz8YK8xMpLc7FYbf88yEElyLsYN_-rbvaZXvENQkOQ,234
|
|
79
|
-
oxutils/users/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
80
|
-
oxutils/users/admin.py,sha256=suMo4x8I3JBxAFBVIdE-5qnqZ6JAZV0FESABHOSc-vg,63
|
|
81
|
-
oxutils/users/apps.py,sha256=u3PAY2AZGQXSWH2DSkQ1lOTIVm33qUbzeKls0J8H8No,142
|
|
82
|
-
oxutils/users/migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
83
|
-
oxutils/users/models.py,sha256=YXAHcXuhmHZfcRDOqA5lBiSRcJ24snBs9X6tcJPCcFs,2960
|
|
84
|
-
oxutils/users/tests.py,sha256=mrbGGRNg5jwbTJtWWa7zSKdDyeB4vmgZCRc2nk6VY-g,60
|
|
85
|
-
oxutils/users/utils.py,sha256=jY-zL8vLT5U3E2FV3DqCvrPORjKLutbkPZTQ-z96dCw,376
|
|
86
|
-
oxutils-0.1.6.dist-info/WHEEL,sha256=eh7sammvW2TypMMMGKgsM83HyA_3qQ5Lgg3ynoecH3M,79
|
|
87
|
-
oxutils-0.1.6.dist-info/METADATA,sha256=9frFJnEQATQH0nvB5a0WbDWVc7M-mI--wy9KkSOeKkA,8168
|
|
88
|
-
oxutils-0.1.6.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|