ecodev-core 0.0.53__py3-none-any.whl → 0.0.55__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 ecodev-core might be problematic. Click here for more details.
- ecodev_core/__init__.py +3 -1
- ecodev_core/authentication.py +40 -2
- ecodev_core/db_upsertion.py +3 -1
- ecodev_core/token_banlist.py +18 -0
- {ecodev_core-0.0.53.dist-info → ecodev_core-0.0.55.dist-info}/METADATA +2 -2
- {ecodev_core-0.0.53.dist-info → ecodev_core-0.0.55.dist-info}/RECORD +8 -7
- {ecodev_core-0.0.53.dist-info → ecodev_core-0.0.55.dist-info}/LICENSE.md +0 -0
- {ecodev_core-0.0.53.dist-info → ecodev_core-0.0.55.dist-info}/WHEEL +0 -0
ecodev_core/__init__.py
CHANGED
|
@@ -12,6 +12,7 @@ from ecodev_core.app_user import select_user
|
|
|
12
12
|
from ecodev_core.app_user import upsert_app_users
|
|
13
13
|
from ecodev_core.auth_configuration import AUTH
|
|
14
14
|
from ecodev_core.authentication import attempt_to_log
|
|
15
|
+
from ecodev_core.authentication import ban_token
|
|
15
16
|
from ecodev_core.authentication import get_access_token
|
|
16
17
|
from ecodev_core.authentication import get_app_services
|
|
17
18
|
from ecodev_core.authentication import get_current_user
|
|
@@ -88,6 +89,7 @@ from ecodev_core.safe_utils import SimpleReturn
|
|
|
88
89
|
from ecodev_core.safe_utils import stringify
|
|
89
90
|
from ecodev_core.settings import SETTINGS
|
|
90
91
|
from ecodev_core.settings import Settings
|
|
92
|
+
from ecodev_core.token_banlist import TokenBanlist
|
|
91
93
|
from ecodev_core.version import db_to_value
|
|
92
94
|
from ecodev_core.version import get_row_versions
|
|
93
95
|
from ecodev_core.version import get_versions
|
|
@@ -108,4 +110,4 @@ __all__ = [
|
|
|
108
110
|
'sort_by_keys', 'sort_by_values', 'Settings', 'load_yaml_file', 'Deployment', 'Version',
|
|
109
111
|
'sfield', 'field', 'upsert_df_data', 'upsert_deletor', 'get_row_versions', 'get_versions',
|
|
110
112
|
'db_to_value', 'upsert_data', 'upsert_selector', 'get_sfield_columns', 'filter_to_sfield_dict',
|
|
111
|
-
'SETTINGS', 'add_missing_enum_values']
|
|
113
|
+
'SETTINGS', 'add_missing_enum_values', 'ban_token', 'TokenBanlist']
|
ecodev_core/authentication.py
CHANGED
|
@@ -33,7 +33,7 @@ from ecodev_core.db_connection import engine
|
|
|
33
33
|
from ecodev_core.logger import logger_get
|
|
34
34
|
from ecodev_core.permissions import Permission
|
|
35
35
|
from ecodev_core.pydantic_utils import Frozen
|
|
36
|
-
|
|
36
|
+
from ecodev_core.token_banlist import TokenBanlist
|
|
37
37
|
|
|
38
38
|
SCHEME = OAuth2PasswordBearer(tokenUrl='login')
|
|
39
39
|
auth_router = APIRouter(tags=['authentication'])
|
|
@@ -44,6 +44,7 @@ INVALID_USER = 'Invalid User'
|
|
|
44
44
|
INVALID_TFA = 'Invalid TFA code'
|
|
45
45
|
ADMIN_ERROR = 'Could not validate credentials. You need admin rights to call this'
|
|
46
46
|
INVALID_CREDENTIALS = 'Invalid Credentials'
|
|
47
|
+
REVOKED_TOKEN = 'This token has been revoked (by a logout action), please login again.'
|
|
47
48
|
log = logger_get(__name__)
|
|
48
49
|
|
|
49
50
|
|
|
@@ -62,7 +63,7 @@ class TokenData(Frozen):
|
|
|
62
63
|
id: int
|
|
63
64
|
|
|
64
65
|
|
|
65
|
-
def get_access_token(token: Dict[str, Any]):
|
|
66
|
+
def get_access_token(token: Dict[str, Any]) -> str | None:
|
|
66
67
|
"""
|
|
67
68
|
Robust method to return access token or None
|
|
68
69
|
"""
|
|
@@ -158,6 +159,9 @@ def is_authorized_user(token: str = Depends(SCHEME)) -> bool:
|
|
|
158
159
|
"""
|
|
159
160
|
Check if the passed token corresponds to an authorized user
|
|
160
161
|
"""
|
|
162
|
+
if _is_banned(token):
|
|
163
|
+
return False
|
|
164
|
+
|
|
161
165
|
try:
|
|
162
166
|
return get_current_user(token) is not None
|
|
163
167
|
except Exception:
|
|
@@ -180,12 +184,38 @@ def get_user(token: str = Depends(SCHEME),
|
|
|
180
184
|
"""
|
|
181
185
|
Retrieves (if it exists) the db user corresponding to the passed token
|
|
182
186
|
"""
|
|
187
|
+
if _is_banned(token):
|
|
188
|
+
raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail=REVOKED_TOKEN,
|
|
189
|
+
headers={'WWW-Authenticate': 'Bearer'})
|
|
183
190
|
if user := get_current_user(token, tfa_value, tfa_check):
|
|
184
191
|
return user
|
|
185
192
|
raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail=INVALID_CREDENTIALS,
|
|
186
193
|
headers={'WWW-Authenticate': 'Bearer'})
|
|
187
194
|
|
|
188
195
|
|
|
196
|
+
def ban_token(token: str, session: Session) -> None:
|
|
197
|
+
"""
|
|
198
|
+
Ban the passed token
|
|
199
|
+
"""
|
|
200
|
+
session.add(TokenBanlist(token=token))
|
|
201
|
+
session.commit()
|
|
202
|
+
|
|
203
|
+
|
|
204
|
+
def _is_banned(token: str) -> bool:
|
|
205
|
+
"""
|
|
206
|
+
Check if the passed token is banned.
|
|
207
|
+
|
|
208
|
+
NB: Clean the TokenBanlist table (deleting old entries) on the fly
|
|
209
|
+
"""
|
|
210
|
+
with Session(engine) as session:
|
|
211
|
+
threshold = datetime.now() - timedelta(minutes=EXPIRATION_LENGTH)
|
|
212
|
+
for token_banned in session.exec(
|
|
213
|
+
select(TokenBanlist).where(TokenBanlist.created_at <= threshold)).all():
|
|
214
|
+
session.delete(token_banned)
|
|
215
|
+
session.commit()
|
|
216
|
+
return token in session.exec(select(TokenBanlist.token)).all()
|
|
217
|
+
|
|
218
|
+
|
|
189
219
|
def get_current_user(token: str,
|
|
190
220
|
tfa_value: Optional[str] = None,
|
|
191
221
|
tfa_check: bool = False
|
|
@@ -202,6 +232,10 @@ def is_admin_user(token: str = Depends(SCHEME)) -> AppUser:
|
|
|
202
232
|
"""
|
|
203
233
|
Retrieves (if it exists) the admin (meaning who has valid credentials) user from the db
|
|
204
234
|
"""
|
|
235
|
+
if _is_banned(token):
|
|
236
|
+
raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail=REVOKED_TOKEN,
|
|
237
|
+
headers={'WWW-Authenticate': 'Bearer'})
|
|
238
|
+
|
|
205
239
|
if (user := get_current_user(token)) and user.permission == Permission.ADMIN:
|
|
206
240
|
return user
|
|
207
241
|
raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail=ADMIN_ERROR,
|
|
@@ -212,6 +246,10 @@ def is_monitoring_user(token: str = Depends(SCHEME)) -> AppUser:
|
|
|
212
246
|
"""
|
|
213
247
|
Retrieves (if it exists) the monitoring user from the db
|
|
214
248
|
"""
|
|
249
|
+
if _is_banned(token):
|
|
250
|
+
raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail=REVOKED_TOKEN,
|
|
251
|
+
headers={'WWW-Authenticate': 'Bearer'})
|
|
252
|
+
|
|
215
253
|
if (user := get_current_user(token)) and user.user == MONITORING:
|
|
216
254
|
return user
|
|
217
255
|
raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED,
|
ecodev_core/db_upsertion.py
CHANGED
|
@@ -32,7 +32,9 @@ SA_COLUMN_KWARGS = 'sa_column_kwargs'
|
|
|
32
32
|
def add_missing_enum_values(enum: EnumType, session: Session, new_vals: list | None = None) -> None:
|
|
33
33
|
"""
|
|
34
34
|
Add to an existing enum its missing db values. Do so by retrieving what is already in db, and
|
|
35
|
-
insert what is new
|
|
35
|
+
insert what is new.
|
|
36
|
+
|
|
37
|
+
NB: new_val argument is there for testing purposes
|
|
36
38
|
"""
|
|
37
39
|
|
|
38
40
|
for val in [e.name for e in new_vals or enum if e.name not in get_enum_values(enum, session)]:
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Module implementing the token ban list table
|
|
3
|
+
"""
|
|
4
|
+
from datetime import datetime
|
|
5
|
+
from typing import Optional
|
|
6
|
+
|
|
7
|
+
from sqlmodel import Field
|
|
8
|
+
from sqlmodel import SQLModel
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class TokenBanlist(SQLModel, table=True): # type: ignore
|
|
12
|
+
"""
|
|
13
|
+
A token banlist: timestamped banned token.
|
|
14
|
+
"""
|
|
15
|
+
__tablename__ = 'token_banlist'
|
|
16
|
+
id: Optional[int] = Field(default=None, primary_key=True)
|
|
17
|
+
created_at: datetime = Field(default_factory=datetime.utcnow)
|
|
18
|
+
token: str = Field(index=True)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: ecodev-core
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.55
|
|
4
4
|
Summary: Low level sqlmodel/fastapi/pydantic building blocks
|
|
5
5
|
License: MIT
|
|
6
6
|
Author: Thomas Epelbaum
|
|
@@ -43,7 +43,7 @@ Requires-Dist: pandas (>=2,<3)
|
|
|
43
43
|
Requires-Dist: passlib[bcyrypt] (>=1,<2)
|
|
44
44
|
Requires-Dist: progressbar2 (>=4.4.2,<5.0.0)
|
|
45
45
|
Requires-Dist: psycopg2-binary (>=2,<3)
|
|
46
|
-
Requires-Dist: pydantic (==2.
|
|
46
|
+
Requires-Dist: pydantic (==2.11.7)
|
|
47
47
|
Requires-Dist: pydantic-settings (>=2,<3)
|
|
48
48
|
Requires-Dist: python-jose[cryptography] (>=3,<4)
|
|
49
49
|
Requires-Dist: pyyaml (>=6,<7)
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
ecodev_core/__init__.py,sha256=
|
|
1
|
+
ecodev_core/__init__.py,sha256=xS1h7Xtp-LBGeKkxFfJFqyxeBiznow7c1MPNAeYLtOg,6218
|
|
2
2
|
ecodev_core/app_activity.py,sha256=KBtI-35LBLPDppFB7xjxWthXQrY3Z_aGDnC-HrW8Ea0,4641
|
|
3
3
|
ecodev_core/app_rights.py,sha256=RZPdDtydFqc_nFj96huKAc56BS0qS6ScKv4Kghqd6lc,726
|
|
4
4
|
ecodev_core/app_user.py,sha256=r1bqA4H08x53XmxmjwyGKl_PFjYQazzBbVErdkztqeE,2947
|
|
5
5
|
ecodev_core/auth_configuration.py,sha256=qZ1Dkk7n1AH7w0tVKQ8AYswukOeMZH6mmbixPEAQnJ8,764
|
|
6
|
-
ecodev_core/authentication.py,sha256=
|
|
6
|
+
ecodev_core/authentication.py,sha256=HuA8o_A_jjnTzG6NKqIeh5LP1tb0yyCR1RvXcPy2Xks,11559
|
|
7
7
|
ecodev_core/backup.py,sha256=N5AtoqtHJRp92Bj0Nr7WW5WDcpjTIET8haxZoYDOtyI,3890
|
|
8
8
|
ecodev_core/check_dependencies.py,sha256=aFn8GI4eBbuJT8RxsfhSSnlpNYYj_LPOH-tZF0EqfKQ,6917
|
|
9
9
|
ecodev_core/custom_equal.py,sha256=2gRn0qpyJ8-Kw9GQSueu0nLngLrRrwyMPlP6zqPac0U,899
|
|
@@ -11,7 +11,7 @@ ecodev_core/db_connection.py,sha256=hhqeyTrl0DlQA7RkUs6pIOpZeE3yS_Q5mqj5uGPfG_Y,
|
|
|
11
11
|
ecodev_core/db_filters.py,sha256=T_5JVF27UEu7sC6NOm7-W3_Y0GLfbWQO_EeTXcD2cv8,5041
|
|
12
12
|
ecodev_core/db_insertion.py,sha256=k-r798MMrW1sRb-gb8lQTxyJrb4QP5iZT8GDzCYYwlo,4544
|
|
13
13
|
ecodev_core/db_retrieval.py,sha256=sCP7TDGIcTOK5gT3Inga91bE4S31HbQPw4yI22WJbss,7392
|
|
14
|
-
ecodev_core/db_upsertion.py,sha256=
|
|
14
|
+
ecodev_core/db_upsertion.py,sha256=Nri5innUEcUBc5zFWDq9oqyzC5sjkX7xQHwqriZ6OUI,6814
|
|
15
15
|
ecodev_core/deployment.py,sha256=z8ACI00EtKknXOB8xyPwYIXTvPjIDOH9z9cBGEU0YrA,281
|
|
16
16
|
ecodev_core/email_sender.py,sha256=V3UGweuq6Iy09Z9to8HzM6JOVDVGHZXHGjUSkW94Tac,1912
|
|
17
17
|
ecodev_core/enum_utils.py,sha256=BkQ4YQ97tXBYmMcQiSIi0mbioD5CgVU79myg1BBAXuA,556
|
|
@@ -25,8 +25,9 @@ ecodev_core/read_write.py,sha256=YIGRERvFHU7vy-JIaCWAza4CPMysLRUHKJxN-ZgFmu0,120
|
|
|
25
25
|
ecodev_core/safe_utils.py,sha256=Q8N15El1tSxZJJsy1i_1CCycuBN1_98QQoHmYJRcLIY,6904
|
|
26
26
|
ecodev_core/settings.py,sha256=UvaTv8S_HvfFAL-m1Rfqv_geSGcccuV3ziR1o1d5wu4,1795
|
|
27
27
|
ecodev_core/sqlmodel_utils.py,sha256=t57H3QPtKRy4ujic1clMK_2L4p0yjGJLZbDjHPZ8M94,453
|
|
28
|
+
ecodev_core/token_banlist.py,sha256=rKXG9QkfCpjOTr8gBgdX-KYNHAkKvQ9TRnGS99VC9Co,491
|
|
28
29
|
ecodev_core/version.py,sha256=eyIf8KkW_t-hMuYFIoy0cUlNaMewLe6i45m2HKZKh0Q,4403
|
|
29
|
-
ecodev_core-0.0.
|
|
30
|
-
ecodev_core-0.0.
|
|
31
|
-
ecodev_core-0.0.
|
|
32
|
-
ecodev_core-0.0.
|
|
30
|
+
ecodev_core-0.0.55.dist-info/LICENSE.md,sha256=8dqVJEbwXjPWjjRKjdLMym5k9Gi8hwtrHh84sti6KIs,1068
|
|
31
|
+
ecodev_core-0.0.55.dist-info/METADATA,sha256=JBynrhYq46elNowZb9yfgMTyjedizyKOpiLyGqLhEp8,3510
|
|
32
|
+
ecodev_core-0.0.55.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
|
|
33
|
+
ecodev_core-0.0.55.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|