Update modules/database/sql_db.py
Browse files- modules/database/sql_db.py +69 -44
modules/database/sql_db.py
CHANGED
@@ -8,6 +8,8 @@ import uuid
|
|
8 |
|
9 |
logger = logging.getLogger(__name__)
|
10 |
|
|
|
|
|
11 |
def get_user(username, role=None):
|
12 |
container = get_container("users")
|
13 |
try:
|
@@ -15,14 +17,16 @@ def get_user(username, role=None):
|
|
15 |
if role:
|
16 |
query += f" AND c.role = '{role}'"
|
17 |
items = list(container.query_items(
|
18 |
-
query=query
|
19 |
-
enable_cross_partition_query=True
|
20 |
))
|
21 |
return items[0] if items else None
|
22 |
except Exception as e:
|
23 |
logger.error(f"Error al obtener usuario {username}: {str(e)}")
|
24 |
return None
|
25 |
|
|
|
|
|
|
|
26 |
def get_admin_user(username):
|
27 |
return get_user(username, role='Administrador')
|
28 |
|
@@ -32,34 +36,26 @@ def get_student_user(username):
|
|
32 |
def get_teacher_user(username):
|
33 |
return get_user(username, role='Profesor')
|
34 |
|
35 |
-
#################################################################################
|
36 |
-
#El error ocurre porque el par谩metro `partition_key`
|
37 |
-
#no es soportado en la versi贸n actual del SDK.
|
38 |
-
#Modifiquemos la funci贸n `create_user()` para incluir la partici贸n en el cuerpo del documento:
|
39 |
-
|
40 |
def create_user(username, password, role, additional_info=None):
|
|
|
41 |
container = get_container("users")
|
42 |
if not container:
|
43 |
logger.error("No se pudo obtener el contenedor de usuarios")
|
44 |
return False
|
45 |
|
46 |
try:
|
47 |
-
# Generar salt y hash de la contrase帽a
|
48 |
-
salt = bcrypt.gensalt()
|
49 |
-
hashed = bcrypt.hashpw(password.encode('utf-8'), salt)
|
50 |
-
|
51 |
user_data = {
|
52 |
'id': username,
|
53 |
-
'password':
|
54 |
-
'salt': salt.decode('utf-8'),
|
55 |
'role': role,
|
56 |
'timestamp': datetime.now(timezone.utc).isoformat(),
|
57 |
-
'additional_info': additional_info or {}
|
58 |
-
# La partici贸n va dentro del documento
|
59 |
-
'partitionKey': username
|
60 |
}
|
61 |
|
62 |
-
container.create_item(
|
|
|
|
|
|
|
63 |
logger.info(f"Usuario {role} creado: {username}")
|
64 |
return True
|
65 |
|
@@ -67,7 +63,6 @@ def create_user(username, password, role, additional_info=None):
|
|
67 |
logger.error(f"Error al crear usuario {role}: {str(e)}")
|
68 |
return False
|
69 |
|
70 |
-
#########################################################################
|
71 |
def create_student_user(username, password, additional_info=None):
|
72 |
return create_user(username, password, 'Estudiante', additional_info)
|
73 |
|
@@ -96,14 +91,11 @@ def record_login(username):
|
|
96 |
"username": username,
|
97 |
"loginTime": datetime.now(timezone.utc).isoformat(),
|
98 |
"additional_info": {},
|
99 |
-
# El campo para partition key debe estar en el documento
|
100 |
"partitionKey": username
|
101 |
}
|
102 |
|
103 |
-
# Crear el documento usando options
|
104 |
result = container.create_item(
|
105 |
-
body=session_doc
|
106 |
-
enable_cross_partition_query=True
|
107 |
)
|
108 |
logger.info(f"Sesi贸n {session_id} registrada para {username}")
|
109 |
return session_id
|
@@ -111,7 +103,6 @@ def record_login(username):
|
|
111 |
logger.error(f"Error registrando login: {str(e)}")
|
112 |
return None
|
113 |
|
114 |
-
|
115 |
###########################################################
|
116 |
|
117 |
def record_logout(username, session_id):
|
@@ -122,7 +113,6 @@ def record_logout(username, session_id):
|
|
122 |
logger.error("No se pudo obtener el contenedor users_sessions")
|
123 |
return False
|
124 |
|
125 |
-
# Obtener la sesi贸n actual
|
126 |
query = "SELECT * FROM c WHERE c.id = @id AND c.username = @username"
|
127 |
params = [
|
128 |
{"name": "@id", "value": session_id},
|
@@ -131,8 +121,7 @@ def record_logout(username, session_id):
|
|
131 |
|
132 |
items = list(container.query_items(
|
133 |
query=query,
|
134 |
-
parameters=params
|
135 |
-
enable_cross_partition_query=True
|
136 |
))
|
137 |
|
138 |
if not items:
|
@@ -146,12 +135,12 @@ def record_logout(username, session_id):
|
|
146 |
|
147 |
session.update({
|
148 |
"logoutTime": logout_time.isoformat(),
|
149 |
-
"sessionDuration": duration
|
|
|
150 |
})
|
151 |
|
152 |
-
# Actualizar el documento
|
153 |
container.upsert_item(
|
154 |
-
body=session
|
155 |
)
|
156 |
logger.info(f"Sesi贸n {session_id} cerrada para {username}, duraci贸n: {duration}s")
|
157 |
return True
|
@@ -180,11 +169,9 @@ def get_recent_sessions(limit=10):
|
|
180 |
|
181 |
sessions = list(container.query_items(
|
182 |
query=query,
|
183 |
-
parameters=[{"name": "@limit", "value": limit}]
|
184 |
-
enable_cross_partition_query=True
|
185 |
))
|
186 |
|
187 |
-
# Validar y limpiar los datos
|
188 |
clean_sessions = []
|
189 |
for session in sessions:
|
190 |
try:
|
@@ -224,8 +211,7 @@ def get_user_total_time(username):
|
|
224 |
|
225 |
result = list(container.query_items(
|
226 |
query=query,
|
227 |
-
parameters=[{"name": "@username", "value": username}]
|
228 |
-
enable_cross_partition_query=True
|
229 |
))
|
230 |
|
231 |
return result[0] if result and result[0] is not None else 0
|
@@ -251,6 +237,7 @@ def update_student_user(username, new_info):
|
|
251 |
return False
|
252 |
|
253 |
|
|
|
254 |
def delete_student_user(username):
|
255 |
user_container, _, _ = get_sql_containers()
|
256 |
try:
|
@@ -266,9 +253,21 @@ def delete_student_user(username):
|
|
266 |
logger.error(f"Error al eliminar estudiante {username}: {str(e)}")
|
267 |
return False
|
268 |
|
|
|
|
|
|
|
|
|
269 |
def store_application_request(name, lastname, email, institution, current_role, desired_role, reason):
|
270 |
-
|
271 |
try:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
272 |
application_request = {
|
273 |
"id": str(uuid.uuid4()),
|
274 |
"name": name,
|
@@ -278,30 +277,56 @@ def store_application_request(name, lastname, email, institution, current_role,
|
|
278 |
"current_role": current_role,
|
279 |
"desired_role": desired_role,
|
280 |
"reason": reason,
|
281 |
-
"requestDate": datetime.utcnow().isoformat()
|
|
|
|
|
282 |
}
|
283 |
-
|
284 |
-
|
|
|
|
|
|
|
|
|
285 |
return True
|
|
|
286 |
except Exception as e:
|
287 |
logger.error(f"Error al almacenar la solicitud de aplicaci贸n: {str(e)}")
|
|
|
288 |
return False
|
289 |
|
|
|
290 |
def store_student_feedback(username, name, email, feedback):
|
291 |
-
|
292 |
try:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
293 |
feedback_item = {
|
294 |
"id": str(uuid.uuid4()),
|
295 |
-
"username": username,
|
296 |
"name": name,
|
297 |
"email": email,
|
298 |
"feedback": feedback,
|
299 |
"role": "Estudiante",
|
300 |
-
|
|
|
301 |
}
|
302 |
-
|
303 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
304 |
return True
|
|
|
305 |
except Exception as e:
|
306 |
-
logger.error(f"Error al almacenar el feedback del estudiante {username}
|
|
|
307 |
return False
|
|
|
8 |
|
9 |
logger = logging.getLogger(__name__)
|
10 |
|
11 |
+
###########################################
|
12 |
+
|
13 |
def get_user(username, role=None):
|
14 |
container = get_container("users")
|
15 |
try:
|
|
|
17 |
if role:
|
18 |
query += f" AND c.role = '{role}'"
|
19 |
items = list(container.query_items(
|
20 |
+
query=query # Removido enable_cross_partition_query
|
|
|
21 |
))
|
22 |
return items[0] if items else None
|
23 |
except Exception as e:
|
24 |
logger.error(f"Error al obtener usuario {username}: {str(e)}")
|
25 |
return None
|
26 |
|
27 |
+
###########################################
|
28 |
+
|
29 |
+
|
30 |
def get_admin_user(username):
|
31 |
return get_user(username, role='Administrador')
|
32 |
|
|
|
36 |
def get_teacher_user(username):
|
37 |
return get_user(username, role='Profesor')
|
38 |
|
|
|
|
|
|
|
|
|
|
|
39 |
def create_user(username, password, role, additional_info=None):
|
40 |
+
"""Crea un nuevo usuario"""
|
41 |
container = get_container("users")
|
42 |
if not container:
|
43 |
logger.error("No se pudo obtener el contenedor de usuarios")
|
44 |
return False
|
45 |
|
46 |
try:
|
|
|
|
|
|
|
|
|
47 |
user_data = {
|
48 |
'id': username,
|
49 |
+
'password': password,
|
|
|
50 |
'role': role,
|
51 |
'timestamp': datetime.now(timezone.utc).isoformat(),
|
52 |
+
'additional_info': additional_info or {}
|
|
|
|
|
53 |
}
|
54 |
|
55 |
+
container.create_item(
|
56 |
+
body=user_data,
|
57 |
+
partition_key=username
|
58 |
+
)
|
59 |
logger.info(f"Usuario {role} creado: {username}")
|
60 |
return True
|
61 |
|
|
|
63 |
logger.error(f"Error al crear usuario {role}: {str(e)}")
|
64 |
return False
|
65 |
|
|
|
66 |
def create_student_user(username, password, additional_info=None):
|
67 |
return create_user(username, password, 'Estudiante', additional_info)
|
68 |
|
|
|
91 |
"username": username,
|
92 |
"loginTime": datetime.now(timezone.utc).isoformat(),
|
93 |
"additional_info": {},
|
|
|
94 |
"partitionKey": username
|
95 |
}
|
96 |
|
|
|
97 |
result = container.create_item(
|
98 |
+
body=session_doc # Solo el body
|
|
|
99 |
)
|
100 |
logger.info(f"Sesi贸n {session_id} registrada para {username}")
|
101 |
return session_id
|
|
|
103 |
logger.error(f"Error registrando login: {str(e)}")
|
104 |
return None
|
105 |
|
|
|
106 |
###########################################################
|
107 |
|
108 |
def record_logout(username, session_id):
|
|
|
113 |
logger.error("No se pudo obtener el contenedor users_sessions")
|
114 |
return False
|
115 |
|
|
|
116 |
query = "SELECT * FROM c WHERE c.id = @id AND c.username = @username"
|
117 |
params = [
|
118 |
{"name": "@id", "value": session_id},
|
|
|
121 |
|
122 |
items = list(container.query_items(
|
123 |
query=query,
|
124 |
+
parameters=params # Removido enable_cross_partition_query
|
|
|
125 |
))
|
126 |
|
127 |
if not items:
|
|
|
135 |
|
136 |
session.update({
|
137 |
"logoutTime": logout_time.isoformat(),
|
138 |
+
"sessionDuration": duration,
|
139 |
+
"partitionKey": username # Asegurar que partitionKey est茅 presente
|
140 |
})
|
141 |
|
|
|
142 |
container.upsert_item(
|
143 |
+
body=session # Solo el body
|
144 |
)
|
145 |
logger.info(f"Sesi贸n {session_id} cerrada para {username}, duraci贸n: {duration}s")
|
146 |
return True
|
|
|
169 |
|
170 |
sessions = list(container.query_items(
|
171 |
query=query,
|
172 |
+
parameters=[{"name": "@limit", "value": limit}] # Removido enable_cross_partition_query
|
|
|
173 |
))
|
174 |
|
|
|
175 |
clean_sessions = []
|
176 |
for session in sessions:
|
177 |
try:
|
|
|
211 |
|
212 |
result = list(container.query_items(
|
213 |
query=query,
|
214 |
+
parameters=[{"name": "@username", "value": username}] # Removido enable_cross_partition_query
|
|
|
215 |
))
|
216 |
|
217 |
return result[0] if result and result[0] is not None else 0
|
|
|
237 |
return False
|
238 |
|
239 |
|
240 |
+
#########################################################
|
241 |
def delete_student_user(username):
|
242 |
user_container, _, _ = get_sql_containers()
|
243 |
try:
|
|
|
253 |
logger.error(f"Error al eliminar estudiante {username}: {str(e)}")
|
254 |
return False
|
255 |
|
256 |
+
|
257 |
+
|
258 |
+
#########################################################
|
259 |
+
|
260 |
def store_application_request(name, lastname, email, institution, current_role, desired_role, reason):
|
261 |
+
"""Almacena una solicitud de aplicaci贸n"""
|
262 |
try:
|
263 |
+
# Obtener el contenedor usando get_container() que s铆 funciona
|
264 |
+
container = get_container("application_requests")
|
265 |
+
if not container:
|
266 |
+
logger.error("No se pudo obtener el contenedor de solicitudes")
|
267 |
+
return False
|
268 |
+
|
269 |
+
# Crear documento con la solicitud
|
270 |
+
# N贸tese que incluimos email como partition key en el cuerpo del documento
|
271 |
application_request = {
|
272 |
"id": str(uuid.uuid4()),
|
273 |
"name": name,
|
|
|
277 |
"current_role": current_role,
|
278 |
"desired_role": desired_role,
|
279 |
"reason": reason,
|
280 |
+
"requestDate": datetime.utcnow().isoformat(),
|
281 |
+
# El campo para partition key debe estar en el documento
|
282 |
+
"partitionKey": email
|
283 |
}
|
284 |
+
|
285 |
+
# Crear el item en el contenedor - sin el par谩metro enable_cross_partition_query
|
286 |
+
container.create_item(
|
287 |
+
body=application_request # Solo pasamos el body
|
288 |
+
)
|
289 |
+
logger.info(f"Solicitud de aplicaci贸n almacenada para: {email}")
|
290 |
return True
|
291 |
+
|
292 |
except Exception as e:
|
293 |
logger.error(f"Error al almacenar la solicitud de aplicaci贸n: {str(e)}")
|
294 |
+
logger.error(f"Detalles del error: {str(e)}")
|
295 |
return False
|
296 |
|
297 |
+
############################################################
|
298 |
def store_student_feedback(username, name, email, feedback):
|
299 |
+
"""Almacena el feedback de un estudiante"""
|
300 |
try:
|
301 |
+
# Obtener el contenedor - verificar disponibilidad
|
302 |
+
logger.info(f"Intentando obtener contenedor user_feedback para usuario: {username}")
|
303 |
+
container = get_container("user_feedback")
|
304 |
+
if not container:
|
305 |
+
logger.error("No se pudo obtener el contenedor user_feedback")
|
306 |
+
return False
|
307 |
+
|
308 |
+
# Crear documento de feedback - asegurar que el username est茅 como partition key
|
309 |
feedback_item = {
|
310 |
"id": str(uuid.uuid4()),
|
311 |
+
"username": username, # Campo regular
|
312 |
"name": name,
|
313 |
"email": email,
|
314 |
"feedback": feedback,
|
315 |
"role": "Estudiante",
|
316 |
+
"timestamp": datetime.now(timezone.utc).isoformat(),
|
317 |
+
"partitionKey": username # Campo de partici贸n
|
318 |
}
|
319 |
+
|
320 |
+
# Crear el item - sin el par谩metro enable_cross_partition_query
|
321 |
+
logger.info(f"Intentando almacenar feedback para usuario: {username}")
|
322 |
+
result = container.create_item(
|
323 |
+
body=feedback_item # Solo el body, no par谩metros adicionales
|
324 |
+
)
|
325 |
+
|
326 |
+
logger.info(f"Feedback almacenado exitosamente para el usuario: {username}")
|
327 |
return True
|
328 |
+
|
329 |
except Exception as e:
|
330 |
+
logger.error(f"Error al almacenar el feedback del estudiante {username}")
|
331 |
+
logger.error(f"Detalles del error: {str(e)}")
|
332 |
return False
|