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

Commit de49329

Browse files
committed
Merge remote-tracking branch 'origin/main' into unittest-coverage-yihao-sprint15
2 parents b8a5bdf + 9326d68 commit de49329

File tree

11 files changed

+326
-56
lines changed

11 files changed

+326
-56
lines changed

app/main.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88

99
from app.database import init_db, get_db, MONGODB_URL
1010

11-
from app.routes import auth, chat, document, user, faq
11+
from app.routes import auth, chat, document, user, faq, setting
1212
from app.repositories.user_repository import UserRepository
1313

1414
load_dotenv()
@@ -77,3 +77,4 @@ async def lifespan(app: FastAPI):
7777
app.include_router(document.router)
7878
app.include_router(user.router)
7979
app.include_router(faq.router)
80+
app.include_router(setting.router)

app/repositories/chat_repository.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,9 @@ async def update_chat(self, chat_id, data):
5555
)
5656

5757
async def add_message(self, chat_id, message: schemas.MessageCreate):
58+
"""
59+
Aggiunge un messaggio alla chat.
60+
"""
5861
message_data = {
5962
"_id": ObjectId(),
6063
"sender": message.sender,
@@ -71,6 +74,9 @@ async def add_message(self, chat_id, message: schemas.MessageCreate):
7174
return message_data
7275

7376
async def update_chat_title(self, chat_id, title):
77+
"""
78+
Aggiorna il titolo della chat.
79+
"""
7480
return await self.collection.update_one(
7581
{"_id": ObjectId(chat_id)}, {"$set": {"name": title}}
7682
)
Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
from fastapi import Depends, HTTPException, status
2+
from motor.motor_asyncio import AsyncIOMotorDatabase
3+
4+
from app.database import get_db
5+
from app.schemas import Settings
6+
7+
8+
def get_setting_repository(db: AsyncIOMotorDatabase = Depends(get_db)):
9+
"""
10+
Restituisce il repository della collection settings.
11+
"""
12+
return SettingRepository(db)
13+
14+
15+
class SettingRepository:
16+
def __init__(self, database):
17+
self.database = database
18+
self.collection = database.get_collection("settings")
19+
20+
print("SettingRepository initialization")
21+
22+
insert_payload = {
23+
"color_primary": "#5e5c64",
24+
"color_primary_hover": "#44424a",
25+
"color_primary_text": "white",
26+
"message_history": 100,
27+
}
28+
self.collection.update_one(
29+
{"_id": "main"},
30+
{
31+
"$setOnInsert": insert_payload,
32+
},
33+
upsert=True,
34+
)
35+
36+
async def get_settings(self):
37+
"""
38+
Restituisce le impostazioni dell'applicazione.
39+
"""
40+
return await self.collection.find_one({"_id": "main"})
41+
42+
async def update_settings(self, settings: Settings):
43+
"""
44+
Aggiorna le impostazioni dell'applicazione.
45+
"""
46+
try:
47+
current_settings = await self.get_settings()
48+
49+
if not current_settings:
50+
raise HTTPException(
51+
status_code=status.HTTP_404_NOT_FOUND,
52+
detail="Settings not found",
53+
)
54+
55+
# Controlla se le impostazioni sono state modificate
56+
if (
57+
current_settings.get("color_primary") == settings.color_primary
58+
and current_settings.get("color_primary_hover")
59+
== settings.color_primary_hover
60+
and current_settings.get("color_primary_text")
61+
== settings.color_primary_text
62+
and current_settings.get("message_history") == settings.message_history
63+
):
64+
print("Settings data is already up to date.")
65+
raise HTTPException(
66+
status_code=status.HTTP_304_NOT_MODIFIED,
67+
detail="Settings data is already up to date.",
68+
)
69+
70+
# Prepara il payload di aggiornamento
71+
update_payload = {
72+
"color_primary": (
73+
settings.color_primary
74+
if settings.color_primary
75+
else current_settings.get("color_primary")
76+
),
77+
"color_primary_hover": (
78+
settings.color_primary_hover
79+
if settings.color_primary_hover
80+
else current_settings.get("color_primary_hover")
81+
),
82+
"color_primary_text": (
83+
settings.color_primary_text
84+
if settings.color_primary_text
85+
else current_settings.get("color_primary_text")
86+
),
87+
"message_history": (
88+
settings.message_history
89+
if settings.message_history
90+
else current_settings.get("message_history")
91+
),
92+
}
93+
94+
result = await self.collection.update_one(
95+
{"_id": "main"},
96+
{
97+
"$set": update_payload,
98+
},
99+
)
100+
101+
# Controlla se l'aggiornamento ha avuto effetto
102+
if result.matched_count == 0:
103+
raise HTTPException(
104+
status_code=status.HTTP_404_NOT_FOUND,
105+
detail="Settings not found during update attempt",
106+
)
107+
except Exception as e:
108+
print(f"Error updating settings: {e}")
109+
raise Exception(f"Error updating settings: {e}")

app/repositories/user_repository.py

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
1-
import uuid
21
from fastapi import HTTPException, status, Depends
32
from pydantic import EmailStr
43
from motor.motor_asyncio import AsyncIOMotorDatabase
5-
from bson import ObjectId
64
from app.database import get_db
75

86

@@ -124,14 +122,18 @@ async def update_user(self, user_id: EmailStr, user_data: schemas.UserUpdate):
124122
update_payload["remember_me"] = user_data.remember_me
125123
if user_data.scopes is not None and user_data.scopes != user_current_data.get("scopes"):
126124
update_payload["scopes"] = user_data.scopes
127-
128-
# Controlla se ci sono stati cambiamenti nei dati
129-
if update_payload == {}:
125+
if user_data.name is not None and user_data.name != user_current_data.get(
126+
"name"
127+
):
128+
update_payload["name"] = user_data.name
129+
130+
print(f"[USER REPO] Update payload: {update_payload}")
131+
if not update_payload or len(update_payload) == 0:
132+
print("empty update payload")
130133
raise HTTPException(
131134
status_code=status.HTTP_304_NOT_MODIFIED,
132135
detail="User data provided matches existing data. No update performed.",
133136
)
134-
135137

136138
try:
137139
result = await self.collection.update_one(
@@ -145,6 +147,7 @@ async def update_user(self, user_id: EmailStr, user_data: schemas.UserUpdate):
145147
detail=f"Failed to update user: {e}",
146148
)
147149

150+
148151
def get_user_repository(db: AsyncIOMotorDatabase = Depends(get_db)):
149152
"""
150153
Restituisce il repository della collection users.

app/routes/auth.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,10 @@
3232
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="auth/token")
3333
pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")
3434

35+
def init_router(app_instance):
36+
yield
37+
38+
3539
def security_check(): # pragma: no cover
3640
if SECRET_KEY_JWT == "$2b$12$zqt9Rgv1PzORjG5ghJSb6OSdYrt7f7cLc38a21DgX/DMyqt80AUCi":
3741
print(
@@ -40,6 +44,7 @@ def security_check(): # pragma: no cover
4044
print("Please set SECRET_KEY_JWT in your environment variables.")
4145
security_check()
4246

47+
4348
async def authenticate_user(email: str, password: str, user_repo: UserRepository):
4449
"""
4550
Ritorna true se l'utente esiste e se la password inserita è quella associata alla mail passata come parametro; altrimenti false.

app/routes/document.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,9 @@ async def upload_document(
5656
)
5757

5858

59-
@router.get("/", response_model=List[schemas.DocumentResponse], status_code=status.HTTP_200_OK)
59+
@router.get(
60+
"", response_model=List[schemas.DocumentResponse]
61+
)
6062
async def get_documents(
6163
current_user=Depends(verify_admin),
6264
document_repository=Depends(get_document_repository),

app/routes/faq.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,9 @@
22
from motor.motor_asyncio import AsyncIOMotorDatabase
33
from pymongo.errors import DuplicateKeyError
44
from bson import ObjectId
5-
from bson.errors import InvalidId
65

76
import app.schemas as schemas
87
from typing import List
9-
from app.database import get_db
108
from app.repositories.faq_repository import FaqRepository, get_faq_repository
119
from app.repositories.user_repository import UserRepository, get_user_repository
1210
from app.routes.auth import verify_admin, authenticate_user
@@ -80,7 +78,9 @@ async def get_faqs(
8078
return faqs
8179

8280

83-
@router.put("/{faq_id}")
81+
@router.patch(
82+
"/{faq_id}",
83+
)
8484
async def update_faq(
8585
faq_id: str,
8686
faq: schemas.FAQUpdate,

app/routes/setting.py

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
from fastapi import APIRouter, Depends, HTTPException, status
2+
3+
import app.schemas as schemas
4+
from app.routes.auth import verify_admin
5+
from app.repositories.setting_repository import (
6+
SettingRepository,
7+
get_setting_repository,
8+
)
9+
10+
router = APIRouter(prefix="/settings", tags=["setting"])
11+
12+
13+
@router.get(
14+
"",
15+
response_model=schemas.Settings,
16+
)
17+
async def get_settings(
18+
setting_repository: SettingRepository = Depends(get_setting_repository),
19+
):
20+
"""
21+
Restituisce le impostazioni dell'applicazione.
22+
23+
### Returns:
24+
* **schemas.Settings**: Le impostazioni dell'applicazione.
25+
26+
### Raises:
27+
* **HTTPException.HTTP_404_NOT_FOUND**: Se le impostazioni non sono state trovate.
28+
* **HTTPException.HTTP_500_INTERNAL_SERVER_ERROR**: Se si verifica un errore durante il recupero delle impostazioni.
29+
"""
30+
try:
31+
settings = await setting_repository.get_settings()
32+
if not settings:
33+
raise HTTPException(
34+
status_code=404,
35+
detail="Settings not found",
36+
)
37+
return settings
38+
except Exception as e:
39+
raise HTTPException(
40+
status_code=500,
41+
detail=f"Error retrieving settings: {str(e)}",
42+
)
43+
44+
45+
@router.patch(
46+
"",
47+
)
48+
async def update_settings(
49+
settings: schemas.Settings,
50+
current_user=Depends(verify_admin),
51+
setting_repository: SettingRepository = Depends(get_setting_repository),
52+
):
53+
"""
54+
Aggiorna le impostazioni dell'applicazione.
55+
56+
### Args:
57+
* **settings**: Le impostazioni da aggiornare.
58+
59+
### Raises:
60+
* **HTTPException.HTTP_401_UNAUTHORIZED**: Se l'utente non è autorizzato a compiere questa azione.
61+
* **HTTPException.HTTP_500_INTERNAL_SERVER_ERROR**: Se si verifica un errore durante l'aggiornamento delle impostazioni.
62+
* **HTTPException.HTTP_304_NOT_MODIFIED**: Se le impostazioni non sono state modificate.
63+
* **HTTPException.HTTP_404_NOT_FOUND**: Se le impostazioni non sono state trovate.
64+
"""
65+
if not current_user:
66+
raise HTTPException(
67+
status_code=status.HTTP_401_UNAUTHORIZED,
68+
detail="Not authorized",
69+
)
70+
71+
try:
72+
await setting_repository.update_settings(settings)
73+
except Exception as e:
74+
raise HTTPException(
75+
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
76+
detail=f"Error updating settings: {str(e)}",
77+
)

0 commit comments

Comments
 (0)