Spaces:
Running
Running
| """ | |
| Script de verificación de correcciones de seguridad y límites de la API. | |
| Este script valida: | |
| 1. Permiso de CRUD en letras grupales: el administrador del grupo o miembros con perm_crud_letras pueden editar/borrar letras del grupo creadas por otros usuarios. | |
| 2. Restricción de montos negativos y cero en finanzas: la API rechaza montos <= 0 con error 422. | |
| """ | |
| import requests | |
| import uuid | |
| BASE_URL = "http://127.0.0.1:8000" | |
| def test_lyrics_and_finances_fixes(): | |
| print("=" * 60) | |
| print("INICIANDO PRUEBAS DE VERIFICACIÓN DE FIXES") | |
| print("=" * 60) | |
| # 1. Crear usuarios de prueba | |
| suffix = str(uuid.uuid4())[:8] | |
| user_a = f"admin_fix_{suffix}" | |
| user_b = f"member_fix_{suffix}" | |
| password = "password123" | |
| print("\n[1] Registrando y logueando usuarios...") | |
| for u in [user_a, user_b]: | |
| reg_res = requests.post(f"{BASE_URL}/auth/register", json={ | |
| "username": u, | |
| "email": f"{u}@example.com", | |
| "password": password | |
| }) | |
| assert reg_res.status_code in (200, 400), f"Error al registrar {u}: {reg_res.text}" | |
| # Login User A | |
| tok_a_res = requests.post(f"{BASE_URL}/auth/token", data={ | |
| "username": f"{user_a}@example.com", | |
| "password": password, | |
| "device_id": f"dev_a_{suffix}", | |
| "device_name": "Device Admin" | |
| }) | |
| assert tok_a_res.status_code == 200, f"Error login A: {tok_a_res.text}" | |
| token_a = tok_a_res.json()["access_token"] | |
| headers_a = {"Authorization": f"Bearer {token_a}"} | |
| # Login User B | |
| tok_b_res = requests.post(f"{BASE_URL}/auth/token", data={ | |
| "username": f"{user_b}@example.com", | |
| "password": password, | |
| "device_id": f"dev_b_{suffix}", | |
| "device_name": "Device Member" | |
| }) | |
| assert tok_b_res.status_code == 200, f"Error login B: {tok_b_res.text}" | |
| token_b = tok_b_res.json()["access_token"] | |
| headers_b = {"Authorization": f"Bearer {token_b}"} | |
| print(" [OK] Usuarios autenticados correctamente.") | |
| # 2. User A crea un grupo | |
| print("\n[2] User A (Admin) creando grupo...") | |
| group_res = requests.post(f"{BASE_URL}/lyrics/groups", json={"name": f"Grupo Fix {suffix}"}, headers=headers_a) | |
| assert group_res.status_code == 200, f"Error al crear grupo: {group_res.text}" | |
| group_id = group_res.json()["id"] | |
| print(f" [OK] Grupo creado con ID {group_id}") | |
| # 3. Invitar a User B al grupo | |
| print("\n[3] Generando invitación y User B uniéndose...") | |
| invite_res = requests.post(f"{BASE_URL}/lyrics/groups/{group_id}/invite", headers=headers_a) | |
| assert invite_res.status_code == 200, f"Error al crear invitación: {invite_res.text}" | |
| code = invite_res.json()["code"] | |
| join_res = requests.post(f"{BASE_URL}/lyrics/join/{code}", headers=headers_b) | |
| assert join_res.status_code == 200, f"Error al unirse: {join_res.text}" | |
| print(" [OK] User B se unió exitosamente al grupo.") | |
| # 4. User B crea una letra en el grupo | |
| print("\n[4] User B creando letra en el grupo...") | |
| lyric_res = requests.post(f"{BASE_URL}/lyrics", json={ | |
| "title": "Letra de Prueba Fix", | |
| "artist": "Artista Fix", | |
| "content": "Contenido de la letra", | |
| "group_id": group_id | |
| }, headers=headers_b) | |
| assert lyric_res.status_code == 200, f"Error al crear letra: {lyric_res.text}" | |
| lyric_id = lyric_res.json()["id"] | |
| print(f" [OK] Letra creada por User B con ID {lyric_id}") | |
| # 5. User A (Admin del grupo) intenta editar la letra creada por User B | |
| print("\n[5] User A (Admin) intenta editar la letra de User B (Prueba de Fix Bug 3)...") | |
| edit_res = requests.put(f"{BASE_URL}/lyrics/{lyric_id}", json={ | |
| "title": "Letra de Prueba Modificada por Admin", | |
| "artist": "Artista Fix Modificado", | |
| "content": "Nuevo contenido editado por el administrador", | |
| "group_id": group_id | |
| }, headers=headers_a) | |
| print(f" Código de estado de edición: {edit_res.status_code}") | |
| assert edit_res.status_code == 200, f"ERROR: El administrador del grupo no pudo editar la letra (Fix Bug 3 no funciona). Respuesta: {edit_res.text}" | |
| print(" [OK] ¡ÉXITO! El administrador del grupo pudo editar la letra sin ser el creador original.") | |
| # 6. User A (Admin) intenta eliminar la letra creada por User B | |
| print("\n[6] User A (Admin) intenta eliminar la letra de User B...") | |
| del_res = requests.delete(f"{BASE_URL}/lyrics/{lyric_id}", headers=headers_a) | |
| print(f" Código de estado de eliminación: {del_res.status_code}") | |
| assert del_res.status_code == 200, f"ERROR: El administrador no pudo borrar la letra. Respuesta: {del_res.text}" | |
| print(" [OK] ¡ÉXITO! El administrador del grupo pudo eliminar la letra sin ser el creador original.") | |
| # 7. Registrar Iglesia para probar Finanzas | |
| print("\n[7] Registrando iglesia para pruebas de finanzas...") | |
| church_res = requests.post(f"{BASE_URL}/iglesia/crear", json={ | |
| "nombre": f"Iglesia Fix {suffix}", | |
| "pastor": "Pastor Fix" | |
| }, headers=headers_a) | |
| assert church_res.status_code == 200, f"Error creando iglesia: {church_res.text}" | |
| print(" [OK] Iglesia creada correctamente.") | |
| # 8. Intentar crear finanza con monto negativo (esperado: 422 Unprocessable Entity) | |
| print("\n[8] Probando montos negativos en finanzas (Prueba de Fix Bug 4)...") | |
| fin_neg_res = requests.post(f"{BASE_URL}/iglesia/finanzas", json={ | |
| "tipo": "entrada", | |
| "monto": -150.0, | |
| "concepto": "Intento de monto negativo", | |
| "responsable": "Admin", | |
| "reference_uuid": f"ref_neg_{suffix}" | |
| }, headers=headers_a) | |
| print(f" Código de estado (negativo): {fin_neg_res.status_code}") | |
| assert fin_neg_res.status_code == 422, f"ERROR: La API aceptó un monto negativo (-150.0). Código: {fin_neg_res.status_code}" | |
| print(" [OK] ¡ÉXITO! La API rechazó correctamente un monto negativo con código 422.") | |
| # 9. Intentar crear finanza con monto cero (esperado: 422 Unprocessable Entity) | |
| print("\n[9] Probando monto cero en finanzas...") | |
| fin_zero_res = requests.post(f"{BASE_URL}/iglesia/finanzas", json={ | |
| "tipo": "entrada", | |
| "monto": 0.0, | |
| "concepto": "Intento de monto cero", | |
| "responsable": "Admin", | |
| "reference_uuid": f"ref_zero_{suffix}" | |
| }, headers=headers_a) | |
| print(f" Código de estado (cero): {fin_zero_res.status_code}") | |
| assert fin_zero_res.status_code == 422, f"ERROR: La API aceptó un monto de cero (0.0). Código: {fin_zero_res.status_code}" | |
| print(" [OK] ¡ÉXITO! La API rechazó correctamente un monto de cero con código 422.") | |
| # 10. Intentar crear finanza con monto positivo (esperado: 200 OK) | |
| print("\n[10] Probando monto positivo en finanzas...") | |
| fin_pos_res = requests.post(f"{BASE_URL}/iglesia/finanzas", json={ | |
| "tipo": "entrada", | |
| "monto": 75.50, | |
| "concepto": "Ofrenda válida", | |
| "responsable": "Admin", | |
| "reference_uuid": f"ref_pos_{suffix}" | |
| }, headers=headers_a) | |
| print(f" Código de estado (positivo): {fin_pos_res.status_code}") | |
| assert fin_pos_res.status_code == 200, f"ERROR: La API rechazó un monto positivo válido (75.50). Código: {fin_pos_res.status_code}. Respuesta: {fin_pos_res.text}" | |
| print(" [OK] ¡ÉXITO! La API registró correctamente el movimiento positivo.") | |
| print("\n" + "=" * 60) | |
| print(" ¡TODAS LAS PRUEBAS DE FIXES DE SEGURIDAD PASARON CON EXITO!") | |
| print("=" * 60 + "\n") | |
| if __name__ == "__main__": | |
| test_lyrics_and_finances_fixes() | |