Skip to content
This repository was archived by the owner on Jun 7, 2025. It is now read-only.

Commit 0aca32b

Browse files
authored
Merge pull request #32 from CodeHex16/hotfix-bazzan-sprint15
Hotfix-bazzan-sprint15
2 parents 4ac9ffd + 35f3732 commit 0aca32b

File tree

10 files changed

+203
-83
lines changed

10 files changed

+203
-83
lines changed

.env.example

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ MAIL_PORT=587 # SMTP server port
2121
MAIL_USERNAME=""
2222
MAIL_PASSWORD="" # SMTP server username and password
2323
MAIL_ADDRESS="" # SMTP server email address
24-
MAIL_STARTTLS=true # Use TLS for secure connection
25-
MAIL_SSL_TLS=false # Use SSL for secure connection
26-
MAIL_USE_CREDENTIALS=true # Use credentials for authentication
27-
VALIDATE_CERTS=true # Validate SSL certificates
24+
MAIL_STARTTLS=True # Use TLS for secure connection
25+
MAIL_SSL_TLS=False # Use SSL for secure connection
26+
MAIL_USE_CREDENTIALS=True # Use credentials for authentication
27+
MAIL_VALIDATE_CERTS=True # Validate SSL certificates

.github/workflows/ci.yml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,11 @@ jobs:
3535
coverage run -m pytest
3636
coverage report
3737
coverage html
38+
env:
39+
MAIL_SERVER: ${{ secrets.MAIL_SERVER }}
40+
MAIL_PASSWORD: ${{ secrets.MAIL_PASSWORD }}
41+
MAIL_ADDRESS: ${{ secrets.MAIL_ADDRESS }}
42+
3843

3944
# Upload coverage data to Coveralls
4045
- name: Upload coverage to Coveralls

app/repositories/user_repository.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@ async def add_test_user(self):
2828
try:
2929
return await self.collection.insert_one(
3030
{
31-
# "_id": get_uuid3("test@test.it"),
3231
"_id": "test@test.it",
3332
"name": "Test User",
3433
"hashed_password": get_password_hash("testtest"),
@@ -46,7 +45,6 @@ async def add_test_admin(self):
4645
try:
4746
return await self.collection.insert_one(
4847
{
49-
# "_id": get_uuid3("admin@test.it"),
5048
"_id": os.getenv("ADMIN_EMAIL") or "admin@test.it",
5149
"name": "Test Admin",
5250
"hashed_password": get_password_hash(os.getenv("ADMIN_PASSWORD") or "admin"),

app/routes/auth.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -181,8 +181,8 @@ async def login_for_access_token(
181181

182182
# Crea il token di accesso
183183
if remember_me:
184-
access_token_expires = timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES)
185-
expires_in = ACCESS_TOKEN_EXPIRE_MINUTES * 60
184+
access_token_expires = timedelta(minutes=int(ACCESS_TOKEN_EXPIRE_MINUTES))
185+
expires_in = int(ACCESS_TOKEN_EXPIRE_MINUTES) * 60
186186
else:
187187
# se access_token_expires è None, il token dura 24 ore ma il cookie che lo contiene scade alla chiusura del browser
188188
access_token_expires = None

app/routes/user.py

Lines changed: 19 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ async def register_user(
7272
except DuplicateKeyError:
7373
raise HTTPException(
7474
status_code=status.HTTP_400_BAD_REQUEST,
75-
detail="User with this email already exists",
75+
detail="Esiste già un utente con questa email",
7676
)
7777
except Exception as e:
7878
raise HTTPException(
@@ -86,16 +86,12 @@ async def register_user(
8686
subject=f"[Suppl-AI] Registrazione utente",
8787
body=f"Benvenuto in Suppl-AI!\nEcco la tua password temporanea\n\n{password}\n\n Accedi e cambiala subito!",
8888
)
89-
except Exception:
90-
# raise HTTPException(
91-
# status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
92-
# detail=f"Failed to send email to user: {e}",
93-
# )
94-
print(" Error: Failed to send to user the password")
95-
print(f" To: {user_data.email}")
96-
print(f" Subject: [Suppl-AI] Registrazione utente")
97-
print(f" Body: Benvenuto in Suppl-AI!\nEcco la tua password temporanea\n\n{password}\n\n Accedi e cambiala subito!")
98-
print(" Error: Failed to send email to user")
89+
except Exception as e:
90+
raise HTTPException(
91+
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
92+
detail=f"Failed to send email to user: {e}",
93+
)
94+
# print(f" Error: Failed to send to user the password: {e}")
9995

10096
return {"message": "User registered successfully", "password": password}
10197

@@ -178,9 +174,17 @@ async def update_user(
178174
* **HTTPException.HTTP_500_INTERNAL_SERVER_ERROR**: Se si verifica un errore durante l'aggiornamento dell'utente.
179175
* **HTTPException.HTTP_304_NOT_MODIFIED**: Se i dati forniti corrispondono a quelli esistenti.
180176
"""
181-
# Rimove il campo password (usa /password per cambiarla)
182177
user_new_data.password = None
183-
178+
# Verifica che l'admin esista e che la password sia corretta
179+
valid_user = await authenticate_user(
180+
current_user.get("sub"), user_new_data.admin_password, user_repo
181+
)
182+
if not valid_user:
183+
raise HTTPException(
184+
status_code=status.HTTP_401_UNAUTHORIZED,
185+
detail="Invalid admin password",
186+
)
187+
184188
# Aggiorna i dati dell'utente nel database
185189
result = await user_repo.update_user(
186190
user_id=user_new_data.id,
@@ -360,16 +364,13 @@ async def reset_password(
360364
subject="[Suppl-AI] Password Reset",
361365
body=f"Ciao {user.get('name')},\n\nEcco la tua nuova password temporanea:\n\n{password}\n\nAccedi e cambiala subito!",
362366
)
363-
except Exception:
367+
except Exception as e:
364368
# raise HTTPException(
365369
# status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
366370
# detail=f"Failed to send email to user: {e}",
367371
# )
368372
print(" Error: Failed to send to user the password")
369-
print(f" To: {user_data.email}")
370-
print(f" Subject: [Suppl-AI] Password Reset")
371-
print(f" Body: Ciao {user.get('name')},\n\nEcco la tua nuova password temporanea:\n\n{password}\n\nAccedi e cambiala subito!")
372-
print(" Error: Failed to send email to user")
373+
373374
except Exception as e:
374375
raise HTTPException(
375376
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,

app/schemas.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,13 +63,13 @@ def check_password_complexity(cls, value: str):
6363

6464

6565
class UserUpdate(BaseModel):
66-
id: Optional[EmailStr] = Field(alias="_id")
66+
id: EmailStr = Field(alias="_id")
6767
name: Optional[str] = None
6868
password: Optional[str] = None
6969
is_initialized: Optional[bool] = None
7070
remember_me: Optional[bool] = None
7171
scopes: Optional[List[str]] = None
72-
72+
admin_password: Optional[str] = None
7373

7474
class UserDelete(BaseModel):
7575
id: EmailStr = Field(alias="_id")

app/service/email_service.py

Lines changed: 8 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -13,16 +13,16 @@
1313
class EmailService:
1414
def __init__(self):
1515
self.conf = ConnectionConfig(
16-
MAIL_USERNAME=os.getenv("MAIL_ADDRESS",""),
17-
MAIL_PASSWORD=os.getenv("MAIL_PASSWORD",""),
18-
MAIL_FROM=os.getenv("MAIL_ADDRESS","test@test.com"),
16+
MAIL_USERNAME=os.getenv("MAIL_ADDRESS","unipd.codehex16@gmail.com"),
17+
MAIL_PASSWORD=os.getenv("MAIL_PASSWORD","password"),
18+
MAIL_FROM=os.getenv("MAIL_ADDRESS","unipd.codehex16@gmail.com"),
1919
MAIL_FROM_NAME=os.getenv("MAIL_USERNAME",""),
2020
MAIL_PORT=os.getenv("MAIL_PORT",587),
21-
MAIL_SERVER=os.getenv("MAIL_SERVER",""),
21+
MAIL_SERVER=os.getenv("MAIL_SERVER","smtp.gmail.com"),
2222
MAIL_STARTTLS = os.getenv("MAIL_STARTTLS",True),
23-
MAIL_SSL_TLS = os.getenv("MAIL_USE_CREDENTIALS", False),
24-
USE_CREDENTIALS=os.getenv("USE_CREDENTIALS",True),
25-
VALIDATE_CERTS=os.getenv("VALIDATE_CERTS",True),
23+
MAIL_SSL_TLS = os.getenv("MAIL_SSL_TLS", False),
24+
USE_CREDENTIALS=os.getenv("MAIL_USE_CREDENTIALS",True),
25+
VALIDATE_CERTS=os.getenv("MAIL_VALIDATE_CERTS",True),
2626
)
2727
self.mail = FastMail(self.conf)
2828

@@ -39,11 +39,4 @@ def is_configuration_valid(self):
3939
return all([
4040
self.conf.MAIL_USERNAME,
4141
self.conf.MAIL_PASSWORD,
42-
self.conf.MAIL_FROM,
43-
self.conf.MAIL_PORT,
44-
self.conf.MAIL_SERVER,
45-
self.conf.MAIL_STARTTLS,
46-
self.conf.MAIL_SSL_TLS,
47-
self.conf.USE_CREDENTIALS,
48-
self.conf.VALIDATE_CERTS
49-
])
42+
])

requirements.txt

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
fastapi==0.115.12
22
passlib==1.7.4
3-
pydantic[email]==2.11.4
3+
pydantic[email]
44
pydantic_core==2.33.2
55
bcrypt==4.3.0
66
motor==3.7.0
@@ -13,9 +13,9 @@ jwt==1.3.1
1313
python-multipart==0.0.20
1414
fastapi-mail==1.4.2
1515
pytz==2025.2
16-
pytest-mock
17-
pytest-asyncio
18-
pytest-cov
19-
httpx
20-
coverage
21-
coveralls
16+
pytest-mock==3.14.0
17+
pytest-asyncio==0.26.0
18+
pytest-cov==6.1.1
19+
httpx==0.28.1
20+
coverage==7.8.0
21+
coveralls==4.0.1

tests/repositories/test_user_repository.py

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,8 @@ async def test__unit_test__update_user_success(user_repository, mock_database):
173173
password="newpass",
174174
is_initialized=True,
175175
remember_me=True,
176-
scopes=["admin"]
176+
scopes=["admin"],
177+
admin_password="adminadmin",
177178
)
178179

179180
result = await user_repository.update_user("user@test.com", update_data)
@@ -197,7 +198,8 @@ async def test__unit_test__update_user_success_with_no_password(user_repository,
197198
_id = "user@test.com",
198199
is_initialized=True,
199200
remember_me=True,
200-
scopes=["admin"]
201+
scopes=["admin"],
202+
admin_password="adminadmin"
201203
)
202204

203205
result = await user_repository.update_user("user@test.com", update_data)
@@ -223,7 +225,8 @@ async def test__unit_test__update_user_error(user_repository, mock_database):
223225
password="newpass",
224226
is_initialized=True,
225227
remember_me=True,
226-
scopes=["admin"]
228+
scopes=["admin"],
229+
admin_password="adminadmin",
227230
)
228231
with pytest.raises(HTTPException) as exc_info:
229232
result = await user_repository.update_user("user@test.com", update_data)
@@ -232,10 +235,10 @@ async def test__unit_test__update_user_error(user_repository, mock_database):
232235

233236
@pytest.mark.asyncio
234237
async def test__unit_test__update_user_no_changes_provide(user_repository, mock_database):
235-
update_data = UserUpdate(_id=None)
238+
update_data = UserUpdate(_id="user@test.com", password=None, is_initialized=None, remember_me=None, scopes=None, admin_password=None)
236239
with pytest.raises(HTTPException) as exc_info:
237240
await user_repository.update_user("user@test.com", update_data)
238-
assert exc_info.value.status_code == 400
241+
assert exc_info.value.status_code == 304
239242

240243
@pytest.mark.asyncio
241244
async def test__unit_test__update_user_no_modified(user_repository, mock_database):
@@ -254,7 +257,8 @@ async def test__unit_test__update_user_no_modified(user_repository, mock_databas
254257
password="test_password",
255258
is_initialized=False,
256259
remember_me=False,
257-
scopes=["admin"]
260+
scopes=["admin"],
261+
admin_password="adminadmin"
258262
)
259263

260264
with pytest.raises(HTTPException) as exc_info:
@@ -268,7 +272,7 @@ async def test__unit_test__update_user_not_found(user_repository, mock_database)
268272
mock_collection = mock_database.get_collection.return_value
269273
mock_collection.find_one.return_value = None
270274

271-
update_data = UserUpdate(_id="test@test.com",password="anypass")
275+
update_data = UserUpdate(_id="test@test.com",password="anypass", admin_password="adminadmin")
272276

273277
with pytest.raises(HTTPException) as exc_info:
274278
await user_repository.update_user("missing@test.com", update_data)

0 commit comments

Comments
 (0)