ecodev-core 0.0.25__tar.gz → 0.0.27__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.
- {ecodev_core-0.0.25 → ecodev_core-0.0.27}/PKG-INFO +1 -1
- {ecodev_core-0.0.25 → ecodev_core-0.0.27}/ecodev_core/__init__.py +2 -1
- {ecodev_core-0.0.25 → ecodev_core-0.0.27}/ecodev_core/auth_configuration.py +3 -3
- {ecodev_core-0.0.25 → ecodev_core-0.0.27}/ecodev_core/authentication.py +4 -9
- {ecodev_core-0.0.25 → ecodev_core-0.0.27}/ecodev_core/db_connection.py +5 -5
- ecodev_core-0.0.27/ecodev_core/email_sender.py +54 -0
- {ecodev_core-0.0.25 → ecodev_core-0.0.27}/pyproject.toml +1 -1
- {ecodev_core-0.0.25 → ecodev_core-0.0.27}/LICENSE.md +0 -0
- {ecodev_core-0.0.25 → ecodev_core-0.0.27}/README.md +0 -0
- {ecodev_core-0.0.25 → ecodev_core-0.0.27}/ecodev_core/app_activity.py +0 -0
- {ecodev_core-0.0.25 → ecodev_core-0.0.27}/ecodev_core/app_rights.py +0 -0
- {ecodev_core-0.0.25 → ecodev_core-0.0.27}/ecodev_core/app_user.py +0 -0
- {ecodev_core-0.0.25 → ecodev_core-0.0.27}/ecodev_core/backup.py +0 -0
- {ecodev_core-0.0.25 → ecodev_core-0.0.27}/ecodev_core/check_dependencies.py +0 -0
- {ecodev_core-0.0.25 → ecodev_core-0.0.27}/ecodev_core/custom_equal.py +0 -0
- {ecodev_core-0.0.25 → ecodev_core-0.0.27}/ecodev_core/db_filters.py +0 -0
- {ecodev_core-0.0.25 → ecodev_core-0.0.27}/ecodev_core/db_insertion.py +0 -0
- {ecodev_core-0.0.25 → ecodev_core-0.0.27}/ecodev_core/db_retrieval.py +0 -0
- {ecodev_core-0.0.25 → ecodev_core-0.0.27}/ecodev_core/enum_utils.py +0 -0
- {ecodev_core-0.0.25 → ecodev_core-0.0.27}/ecodev_core/list_utils.py +0 -0
- {ecodev_core-0.0.25 → ecodev_core-0.0.27}/ecodev_core/logger.py +0 -0
- {ecodev_core-0.0.25 → ecodev_core-0.0.27}/ecodev_core/pandas_utils.py +0 -0
- {ecodev_core-0.0.25 → ecodev_core-0.0.27}/ecodev_core/permissions.py +0 -0
- {ecodev_core-0.0.25 → ecodev_core-0.0.27}/ecodev_core/pydantic_utils.py +0 -0
- {ecodev_core-0.0.25 → ecodev_core-0.0.27}/ecodev_core/read_write.py +0 -0
- {ecodev_core-0.0.25 → ecodev_core-0.0.27}/ecodev_core/safe_utils.py +0 -0
|
@@ -40,6 +40,7 @@ from ecodev_core.db_insertion import get_raw_df
|
|
|
40
40
|
from ecodev_core.db_retrieval import count_rows
|
|
41
41
|
from ecodev_core.db_retrieval import get_rows
|
|
42
42
|
from ecodev_core.db_retrieval import ServerSideField
|
|
43
|
+
from ecodev_core.email_sender import send_email
|
|
43
44
|
from ecodev_core.enum_utils import enum_converter
|
|
44
45
|
from ecodev_core.list_utils import first_or_default
|
|
45
46
|
from ecodev_core.list_utils import first_transformed_or_default
|
|
@@ -84,4 +85,4 @@ __all__ = [
|
|
|
84
85
|
'generic_insertion', 'custom_equal', 'is_authorized_user', 'get_method', 'AppActivity',
|
|
85
86
|
'fastapi_monitor', 'dash_monitor', 'is_monitoring_user', 'get_recent_activities', 'select_user',
|
|
86
87
|
'get_access_token', 'safe_get_user', 'backup', 'group_by', 'get_excelfile', 'upsert_new_user',
|
|
87
|
-
'datify', 'safe_drop_columns', 'get_value', 'is_null']
|
|
88
|
+
'datify', 'safe_drop_columns', 'get_value', 'is_null', 'send_email']
|
|
@@ -9,9 +9,9 @@ class AuthenticationConfiguration(BaseSettings):
|
|
|
9
9
|
"""
|
|
10
10
|
Simple authentication configuration class
|
|
11
11
|
"""
|
|
12
|
-
secret_key: str
|
|
13
|
-
algorithm: str
|
|
14
|
-
access_token_expire_minutes: int
|
|
12
|
+
secret_key: str = ''
|
|
13
|
+
algorithm: str = ''
|
|
14
|
+
access_token_expire_minutes: int = 0
|
|
15
15
|
model_config = SettingsConfigDict(env_file='.env')
|
|
16
16
|
|
|
17
17
|
|
|
@@ -152,14 +152,12 @@ def attempt_to_log(user: str,
|
|
|
152
152
|
'token_type': 'bearer'}
|
|
153
153
|
|
|
154
154
|
|
|
155
|
-
def is_authorized_user(token: str = Depends(SCHEME)
|
|
156
|
-
tfa_value: Optional[str] = None,
|
|
157
|
-
tfa_check: bool = False) -> bool:
|
|
155
|
+
def is_authorized_user(token: str = Depends(SCHEME)) -> bool:
|
|
158
156
|
"""
|
|
159
157
|
Check if the passed token corresponds to an authorized user
|
|
160
158
|
"""
|
|
161
159
|
try:
|
|
162
|
-
return get_current_user(token
|
|
160
|
+
return get_current_user(token) is not None
|
|
163
161
|
except Exception:
|
|
164
162
|
return False
|
|
165
163
|
|
|
@@ -198,14 +196,11 @@ def get_current_user(token: str,
|
|
|
198
196
|
return session.exec(select(AppUser).where(col(AppUser.id) == token.id)).first()
|
|
199
197
|
|
|
200
198
|
|
|
201
|
-
def is_admin_user(token: str = Depends(SCHEME)
|
|
202
|
-
tfa_value: Optional[str] = None,
|
|
203
|
-
tfa_check: bool = False) -> AppUser:
|
|
199
|
+
def is_admin_user(token: str = Depends(SCHEME)) -> AppUser:
|
|
204
200
|
"""
|
|
205
201
|
Retrieves (if it exists) the admin (meaning who has valid credentials) user from the db
|
|
206
202
|
"""
|
|
207
|
-
if (user := get_current_user(
|
|
208
|
-
token, tfa_value, tfa_check)) and user.permission == Permission.ADMIN:
|
|
203
|
+
if (user := get_current_user(token)) and user.permission == Permission.ADMIN:
|
|
209
204
|
return user
|
|
210
205
|
raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail=ADMIN_ERROR,
|
|
211
206
|
headers={'WWW-Authenticate': 'Bearer'})
|
|
@@ -20,11 +20,11 @@ class DbSettings(BaseSettings):
|
|
|
20
20
|
"""
|
|
21
21
|
Settings class used to connect to the postgresql database
|
|
22
22
|
"""
|
|
23
|
-
db_host: str
|
|
24
|
-
db_port: str
|
|
25
|
-
db_name: str
|
|
26
|
-
db_username: str
|
|
27
|
-
db_password: str
|
|
23
|
+
db_host: str = ''
|
|
24
|
+
db_port: str = ''
|
|
25
|
+
db_name: str = ''
|
|
26
|
+
db_username: str = ''
|
|
27
|
+
db_password: str = ''
|
|
28
28
|
model_config = SettingsConfigDict(env_file='.env')
|
|
29
29
|
|
|
30
30
|
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Module implementing generic email send
|
|
3
|
+
"""
|
|
4
|
+
from email.mime.image import MIMEImage
|
|
5
|
+
from email.mime.multipart import MIMEMultipart
|
|
6
|
+
from email.mime.text import MIMEText
|
|
7
|
+
from pathlib import Path
|
|
8
|
+
from smtplib import SMTP
|
|
9
|
+
from ssl import create_default_context
|
|
10
|
+
from typing import Dict
|
|
11
|
+
|
|
12
|
+
from pydantic_settings import BaseSettings
|
|
13
|
+
from pydantic_settings import SettingsConfigDict
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class EmailAuth(BaseSettings):
|
|
17
|
+
"""
|
|
18
|
+
Simple authentication configuration class
|
|
19
|
+
"""
|
|
20
|
+
email_smtp: str = ''
|
|
21
|
+
email_sender: str = ''
|
|
22
|
+
email_password: str = ''
|
|
23
|
+
model_config = SettingsConfigDict(env_file='.env')
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
EMAIL_AUTH = EmailAuth()
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def send_email(email: str, body: str, topic: str, images: Dict[str, Path]) -> None:
|
|
30
|
+
"""
|
|
31
|
+
Generic email sender.
|
|
32
|
+
|
|
33
|
+
Attributes are:
|
|
34
|
+
- email: The email to which to send
|
|
35
|
+
- body: the email body
|
|
36
|
+
- topic: the email topic
|
|
37
|
+
- images: if any, the Dict of image tags:image paths to incorporate in the email
|
|
38
|
+
"""
|
|
39
|
+
em = MIMEMultipart('related')
|
|
40
|
+
em['From'] = EMAIL_AUTH.email_sender
|
|
41
|
+
em['To'] = email
|
|
42
|
+
em['Subject'] = topic
|
|
43
|
+
em.attach(MIMEText(body, 'html'))
|
|
44
|
+
for tag, img_path in images.items():
|
|
45
|
+
with open(img_path, 'rb') as fp:
|
|
46
|
+
img = MIMEImage(fp.read())
|
|
47
|
+
img.add_header('Content-ID', f'<{tag}>')
|
|
48
|
+
em.attach(img)
|
|
49
|
+
|
|
50
|
+
with SMTP(EMAIL_AUTH.email_smtp, 587) as server:
|
|
51
|
+
server.ehlo()
|
|
52
|
+
server.starttls(context=create_default_context())
|
|
53
|
+
server.login(EMAIL_AUTH.email_sender, EMAIL_AUTH.email_password)
|
|
54
|
+
server.sendmail(EMAIL_AUTH.email_sender, email, em.as_string())
|
|
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
|
|
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
|