Skip to content

Commit 256b9c1

Browse files
committed
Added logs for crud operations
1 parent 2c91bbf commit 256b9c1

File tree

11 files changed

+730
-230
lines changed

11 files changed

+730
-230
lines changed

backend/app/crud/api_key.py

Lines changed: 71 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import uuid
22
import secrets
3+
import logging
34
from sqlmodel import Session, select
45
from app.core.security import (
56
get_password_hash,
@@ -11,11 +12,19 @@
1112
from app.core.exception_handlers import HTTPException
1213
from app.models.api_key import APIKey, APIKeyPublic
1314

15+
logger = logging.getLogger(__name__)
16+
1417

1518
def generate_api_key() -> tuple[str, str]:
1619
"""Generate a new API key and its hash."""
20+
logger.info(
21+
f"[generate_api_key] Generating new API key | {{'action': 'generate'}}"
22+
)
1723
raw_key = "ApiKey " + secrets.token_urlsafe(32)
1824
hashed_key = get_password_hash(raw_key)
25+
logger.info(
26+
f"[generate_api_key] API key generated successfully | {{'action': 'generated'}}"
27+
)
1928
return raw_key, hashed_key
2029

2130

@@ -26,11 +35,15 @@ def create_api_key(
2635
Generates a new API key for an organization and associates it with a user.
2736
Returns the API key details with the raw key (shown only once).
2837
"""
38+
logger.info(
39+
f"[create_api_key] Starting API key creation | {{'organization_id': {organization_id}, 'user_id': {user_id}, 'project_id': {project_id}}}"
40+
)
2941
# Generate raw key and its hash using the helper function
3042
raw_key, hashed_key = generate_api_key()
31-
encrypted_key = encrypt_api_key(
32-
raw_key
33-
) # Encrypt the raw key instead of hashed key
43+
encrypted_key = encrypt_api_key(raw_key) # Encrypt the raw key instead of hashed key
44+
logger.info(
45+
f"[create_api_key] API key encrypted | {{'user_id': {user_id}, 'project_id': {project_id}}}"
46+
)
3447

3548
# Create API key record with encrypted raw key
3649
api_key = APIKey(
@@ -43,11 +56,17 @@ def create_api_key(
4356
session.add(api_key)
4457
session.commit()
4558
session.refresh(api_key)
59+
logger.info(
60+
f"[create_api_key] API key created and stored | {{'api_key_id': {api_key.id}, 'user_id': {user_id}, 'project_id': {project_id}}}"
61+
)
4662

4763
# Set the raw key in the response (shown only once)
4864
api_key_dict = api_key.model_dump()
4965
api_key_dict["key"] = raw_key # Return the raw key to the user
5066

67+
logger.info(
68+
f"[create_api_key] API key creation completed | {{'api_key_id': {api_key.id}, 'user_id': {user_id}, 'project_id': {project_id}}}"
69+
)
5170
return APIKeyPublic.model_validate(api_key_dict)
5271

5372

@@ -56,6 +75,9 @@ def get_api_key(session: Session, api_key_id: int) -> APIKeyPublic | None:
5675
Retrieves an API key by its ID if it exists and is not deleted.
5776
Returns the API key in its original format.
5877
"""
78+
logger.info(
79+
f"[get_api_key] Retrieving API key | {{'api_key_id': {api_key_id}}}"
80+
)
5981
api_key = session.exec(
6082
select(APIKey).where(APIKey.id == api_key_id, APIKey.is_deleted == False)
6183
).first()
@@ -66,41 +88,67 @@ def get_api_key(session: Session, api_key_id: int) -> APIKeyPublic | None:
6688
# Decrypt the key
6789
decrypted_key = decrypt_api_key(api_key.key)
6890
api_key_dict["key"] = decrypted_key
69-
91+
logger.info(
92+
f"[get_api_key] API key retrieved successfully | {{'api_key_id': {api_key_id}}}"
93+
)
7094
return APIKeyPublic.model_validate(api_key_dict)
95+
96+
logger.warning(
97+
f"[get_api_key] API key not found | {{'api_key_id': {api_key_id}}}"
98+
)
7199
return None
72100

73101

74102
def delete_api_key(session: Session, api_key_id: int) -> None:
75103
"""
76104
Soft deletes (revokes) an API key by marking it as deleted.
77105
"""
106+
logger.info(
107+
f"[delete_api_key] Starting API key deletion | {{'api_key_id': {api_key_id}}}"
108+
)
78109
api_key = session.get(APIKey, api_key_id)
79110

111+
if not api_key:
112+
logger.error(
113+
f"[delete_api_key] API key not found | {{'api_key_id': {api_key_id}}}"
114+
)
115+
return
116+
80117
api_key.is_deleted = True
81118
api_key.deleted_at = now()
82119
api_key.updated_at = now()
83120

84121
session.add(api_key)
85122
session.commit()
123+
logger.info(
124+
f"[delete_api_key] API key soft deleted successfully | {{'api_key_id': {api_key_id}}}"
125+
)
86126

87127

88128
def get_api_key_by_value(session: Session, api_key_value: str) -> APIKeyPublic | None:
89129
"""
90130
Retrieve an API Key record by verifying the provided key against stored hashes.
91131
Returns the API key in its original format.
92132
"""
133+
logger.info(
134+
f"[get_api_key_by_value] Retrieving API key by value | {{'action': 'lookup'}}"
135+
)
93136
# Get all active API keys
94137
api_keys = session.exec(select(APIKey).where(APIKey.is_deleted == False)).all()
95138

96139
for api_key in api_keys:
97140
decrypted_key = decrypt_api_key(api_key.key)
98141
if api_key_value == decrypted_key:
99142
api_key_dict = api_key.model_dump()
100-
101143
api_key_dict["key"] = decrypted_key
102-
144+
logger.info(
145+
f"[get_api_key_by_value] API key found | {{'api_key_id': {api_key.id}}}"
146+
)
103147
return APIKeyPublic.model_validate(api_key_dict)
148+
149+
logger.warning(
150+
f"[get_api_key_by_value] API key not found | {{'action': 'not_found'}}"
151+
)
104152
return None
105153

106154

@@ -110,6 +158,9 @@ def get_api_key_by_project_user(
110158
"""
111159
Retrieves the single API key associated with a project.
112160
"""
161+
logger.info(
162+
f"[get_api_key_by_project_user] Retrieving API key | {{'project_id': {project_id}, 'user_id': '{user_id}'}}"
163+
)
113164
statement = select(APIKey).where(
114165
APIKey.user_id == user_id,
115166
APIKey.project_id == project_id,
@@ -120,15 +171,24 @@ def get_api_key_by_project_user(
120171
if api_key:
121172
api_key_dict = api_key.model_dump()
122173
api_key_dict["key"] = decrypt_api_key(api_key.key)
174+
logger.info(
175+
f"[get_api_key_by_project_user] API key retrieved successfully | {{'api_key_id': {api_key.id}, 'project_id': {project_id}, 'user_id': '{user_id}'}}"
176+
)
123177
return APIKeyPublic.model_validate(api_key_dict)
124178

179+
logger.warning(
180+
f"[get_api_key_by_project_user] API key not found | {{'project_id': {project_id}, 'user_id': '{user_id}'}}"
181+
)
125182
return None
126183

127184

128185
def get_api_keys_by_project(session: Session, project_id: int) -> list[APIKeyPublic]:
129186
"""
130187
Retrieves all API keys associated with a project.
131188
"""
189+
logger.info(
190+
f"[get_api_keys_by_project] Retrieving API keys for project | {{'project_id': {project_id}}}"
191+
)
132192
statement = select(APIKey).where(
133193
APIKey.project_id == project_id, APIKey.is_deleted == False
134194
)
@@ -139,5 +199,8 @@ def get_api_keys_by_project(session: Session, project_id: int) -> list[APIKeyPub
139199
key_dict = key.model_dump()
140200
key_dict["key"] = decrypt_api_key(key.key)
141201
result.append(APIKeyPublic.model_validate(key_dict))
142-
143-
return result
202+
203+
logger.info(
204+
f"[get_api_keys_by_project] API keys retrieved successfully | {{'project_id': {project_id}, 'key_count': {len(result)}}}"
205+
)
206+
return result

backend/app/crud/collection.py

Lines changed: 64 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import logging
12
import functools as ft
23
from uuid import UUID
34
from typing import Optional
@@ -10,29 +11,52 @@
1011

1112
from .document_collection import DocumentCollectionCrud
1213

14+
logger = logging.getLogger(__name__)
15+
1316

1417
class CollectionCrud:
1518
def __init__(self, session: Session, owner_id: int):
1619
self.session = session
1720
self.owner_id = owner_id
21+
logger.info(
22+
f"[CollectionCrud.init] Initialized CollectionCrud | {{'owner_id': {owner_id}}}"
23+
)
1824

1925
def _update(self, collection: Collection):
26+
logger.info(
27+
f"[CollectionCrud._update] Starting collection update | {{'collection_id': '{collection.id}', 'owner_id': {self.owner_id}}}"
28+
)
2029
if not collection.owner_id:
30+
logger.info(
31+
f"[CollectionCrud._update] Assigning owner ID | {{'collection_id': '{collection.id}', 'owner_id': {self.owner_id}}}"
32+
)
2133
collection.owner_id = self.owner_id
2234
elif collection.owner_id != self.owner_id:
35+
logger.warning(
36+
f"[CollectionCrud._update] Ownership mismatch detected | {{'collection_id': '{collection.id}', 'owner_id': {collection.owner_id}, 'attempted_owner_id': {self.owner_id}}}"
37+
)
2338
err = "Invalid collection ownership: owner={} attempter={}".format(
2439
self.owner_id,
2540
collection.owner_id,
2641
)
42+
logger.error(
43+
f"[CollectionCrud._update] Permission error | {{'collection_id': '{collection.id}', 'error': '{err}'}}"
44+
)
2745
raise PermissionError(err)
2846

2947
self.session.add(collection)
3048
self.session.commit()
3149
self.session.refresh(collection)
50+
logger.info(
51+
f"[CollectionCrud._update] Collection updated successfully | {{'collection_id': '{collection.id}'}}"
52+
)
3253

3354
return collection
3455

3556
def _exists(self, collection: Collection):
57+
logger.info(
58+
f"[CollectionCrud._exists] Checking if collection exists | {{'llm_service_id': '{collection.llm_service_id}', 'llm_service_name': '{collection.llm_service_name}'}}"
59+
)
3660
present = (
3761
self.session.query(func.count(Collection.id))
3862
.filter(
@@ -41,6 +65,9 @@ def _exists(self, collection: Collection):
4165
)
4266
.scalar()
4367
)
68+
logger.info(
69+
f"[CollectionCrud._exists] Existence check completed | {{'llm_service_id': '{collection.llm_service_id}', 'exists': {bool(present)}}}"
70+
)
4471

4572
return bool(present)
4673

@@ -66,37 +93,64 @@ def create(
6693
return collection
6794

6895
def read_one(self, collection_id: UUID):
96+
logger.info(
97+
f"[CollectionCrud.read_one] Retrieving collection | {{'collection_id': '{collection_id}', 'owner_id': {self.owner_id}}}"
98+
)
6999
statement = select(Collection).where(
70100
and_(
71101
Collection.owner_id == self.owner_id,
72102
Collection.id == collection_id,
73103
)
74104
)
75105

76-
return self.session.exec(statement).one()
106+
collection = self.session.exec(statement).one()
107+
logger.info(
108+
f"[CollectionCrud.read_one] Collection retrieved successfully | {{'collection_id': '{collection_id}'}}"
109+
)
110+
return collection
77111

78112
def read_all(self):
113+
logger.info(
114+
f"[CollectionCrud.read_all] Retrieving all collections | {{'owner_id': {self.owner_id}}}"
115+
)
79116
statement = select(Collection).where(
80117
and_(
81118
Collection.owner_id == self.owner_id,
82119
Collection.deleted_at.is_(None),
83120
)
84121
)
85122

86-
return self.session.exec(statement).all()
123+
collections = self.session.exec(statement).all()
124+
logger.info(
125+
f"[CollectionCrud.read_all] Collections retrieved successfully | {{'owner_id': {self.owner_id}, 'collection_count': {len(collections)}}}"
126+
)
127+
return collections
87128

88129
@ft.singledispatchmethod
89130
def delete(self, model, remote): # remote should be an OpenAICrud
131+
logger.error(
132+
f"[CollectionCrud.delete] Invalid model type | {{'model_type': '{type(model).__name__}'}}"
133+
)
90134
raise TypeError(type(model))
91135

92136
@delete.register
93137
def _(self, model: Collection, remote):
138+
logger.info(
139+
f"[CollectionCrud.delete] Starting collection deletion | {{'collection_id': '{model.id}', 'llm_service_id': '{model.llm_service_id}'}}"
140+
)
94141
remote.delete(model.llm_service_id)
95142
model.deleted_at = now()
96-
return self._update(model)
143+
collection = self._update(model)
144+
logger.info(
145+
f"[CollectionCrud.delete] Collection deleted successfully | {{'collection_id': '{model.id}'}}"
146+
)
147+
return collection
97148

98149
@delete.register
99150
def _(self, model: Document, remote):
151+
logger.info(
152+
f"[CollectionCrud.delete] Starting document deletion from collections | {{'document_id': '{model.id}'}}"
153+
)
100154
statement = (
101155
select(Collection)
102156
.join(
@@ -108,7 +162,13 @@ def _(self, model: Document, remote):
108162
)
109163

110164
for c in self.session.execute(statement):
165+
logger.info(
166+
f"[CollectionCrud.delete] Deleting collection associated with document | {{'document_id': '{model.id}', 'collection_id': '{c.Collection.id}'}}"
167+
)
111168
self.delete(c.Collection, remote)
112169
self.session.refresh(model)
170+
logger.info(
171+
f"[CollectionCrud.delete] Document deletion from collections completed | {{'document_id': '{model.id}'}}"
172+
)
113173

114-
return model
174+
return model

0 commit comments

Comments
 (0)