feat: Add maintenance scripts and testing utilities
- Added password management utilities for user administration - Added PowerShell scripts for testing attachment endpoints - Enhanced development and testing workflow capabilities - Completed v1.4.0 with all maintenance tools included"
This commit is contained in:
77
backend/check_test_user_password.py
Normal file
77
backend/check_test_user_password.py
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
"""
|
||||||
|
Script para verificar y actualizar password del test_user
|
||||||
|
"""
|
||||||
|
import asyncio
|
||||||
|
import sys
|
||||||
|
import os
|
||||||
|
from sqlalchemy import select
|
||||||
|
from passlib.context import CryptContext
|
||||||
|
|
||||||
|
# Configurar el path
|
||||||
|
backend_path = os.path.join(os.path.dirname(__file__), 'backend')
|
||||||
|
sys.path.insert(0, backend_path)
|
||||||
|
|
||||||
|
from app.core.database import AsyncSessionLocal
|
||||||
|
from app.models.user import User
|
||||||
|
|
||||||
|
# Configurar passlib igual que en security.py
|
||||||
|
pwd_context = CryptContext(
|
||||||
|
schemes=["argon2", "bcrypt"],
|
||||||
|
deprecated="auto",
|
||||||
|
argon2__memory_cost=65536,
|
||||||
|
argon2__time_cost=3,
|
||||||
|
argon2__parallelism=4,
|
||||||
|
)
|
||||||
|
|
||||||
|
async def check_and_fix_test_user():
|
||||||
|
"""Verificar y actualizar password del test_user"""
|
||||||
|
|
||||||
|
# Contraseñas posibles
|
||||||
|
possible_passwords = [
|
||||||
|
"admin123",
|
||||||
|
"TestPassword123!",
|
||||||
|
"password123",
|
||||||
|
"test123",
|
||||||
|
"hashed_password"
|
||||||
|
]
|
||||||
|
|
||||||
|
async with AsyncSessionLocal() as session:
|
||||||
|
try:
|
||||||
|
# Buscar test_user
|
||||||
|
result = await session.execute(
|
||||||
|
select(User).where(User.email == "test_user@example.com")
|
||||||
|
)
|
||||||
|
user = result.scalar_one_or_none()
|
||||||
|
|
||||||
|
if not user:
|
||||||
|
print("❌ Usuario test_user@example.com no encontrado")
|
||||||
|
return
|
||||||
|
|
||||||
|
print(f"✅ Usuario encontrado: {user.email}")
|
||||||
|
print(f"Hash actual: {user.password_hash}")
|
||||||
|
|
||||||
|
# Probar contraseñas posibles
|
||||||
|
found_password = None
|
||||||
|
for password in possible_passwords:
|
||||||
|
if pwd_context.verify(password, user.password_hash):
|
||||||
|
found_password = password
|
||||||
|
break
|
||||||
|
|
||||||
|
if found_password:
|
||||||
|
print(f"🎉 Contraseña encontrada: {found_password}")
|
||||||
|
else:
|
||||||
|
print("❌ Ninguna contraseña coincide")
|
||||||
|
print("Estableciendo nueva contraseña: admin123")
|
||||||
|
|
||||||
|
# Establecer nueva contraseña
|
||||||
|
new_password = "admin123"
|
||||||
|
user.password_hash = pwd_context.hash(new_password)
|
||||||
|
await session.commit()
|
||||||
|
print(f"✅ Contraseña actualizada a: {new_password}")
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print(f"❌ Error: {e}")
|
||||||
|
await session.rollback()
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
asyncio.run(check_and_fix_test_user())
|
||||||
59
backend/set_test_password.py
Normal file
59
backend/set_test_password.py
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
"""
|
||||||
|
Script para establecer contraseña real al test_user
|
||||||
|
"""
|
||||||
|
import asyncio
|
||||||
|
import sys
|
||||||
|
import os
|
||||||
|
from sqlalchemy import select
|
||||||
|
from passlib.context import CryptContext
|
||||||
|
|
||||||
|
# Configurar el path
|
||||||
|
backend_path = os.path.join(os.path.dirname(__file__), 'backend')
|
||||||
|
sys.path.insert(0, backend_path)
|
||||||
|
|
||||||
|
from app.core.database import AsyncSessionLocal
|
||||||
|
from app.models.user import User
|
||||||
|
|
||||||
|
# Configurar passlib
|
||||||
|
pwd_context = CryptContext(
|
||||||
|
schemes=["argon2", "bcrypt"],
|
||||||
|
deprecated="auto",
|
||||||
|
argon2__memory_cost=65536,
|
||||||
|
argon2__time_cost=3,
|
||||||
|
argon2__parallelism=4,
|
||||||
|
)
|
||||||
|
|
||||||
|
async def set_test_user_password():
|
||||||
|
"""Establecer contraseña admin123 para test_user"""
|
||||||
|
|
||||||
|
new_password = "admin123"
|
||||||
|
password_hash = pwd_context.hash(new_password)
|
||||||
|
|
||||||
|
async with AsyncSessionLocal() as session:
|
||||||
|
try:
|
||||||
|
# Buscar test_user
|
||||||
|
result = await session.execute(
|
||||||
|
select(User).where(User.email == "test_user@example.com")
|
||||||
|
)
|
||||||
|
user = result.scalar_one_or_none()
|
||||||
|
|
||||||
|
if not user:
|
||||||
|
print("❌ Usuario test_user@example.com no encontrado")
|
||||||
|
return
|
||||||
|
|
||||||
|
print(f"✅ Usuario encontrado: {user.email}")
|
||||||
|
print(f"Hash anterior: {user.password_hash}")
|
||||||
|
|
||||||
|
# Establecer nueva contraseña hash
|
||||||
|
user.password_hash = password_hash
|
||||||
|
await session.commit()
|
||||||
|
|
||||||
|
print(f"🎉 Contraseña establecida: {new_password}")
|
||||||
|
print(f"✅ Nuevo hash: {password_hash[:50]}...")
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print(f"❌ Error: {e}")
|
||||||
|
await session.rollback()
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
asyncio.run(set_test_user_password())
|
||||||
34
test_attachments.ps1
Normal file
34
test_attachments.ps1
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
# Test de Attachments API
|
||||||
|
# Ejecutar desde PowerShell
|
||||||
|
|
||||||
|
# 1. Login
|
||||||
|
$body = '{"email":"admin@aduanasoft.com","password":"admin123","tenant_slug":"aduanasoft"}'
|
||||||
|
$login = Invoke-RestMethod -Uri "http://localhost:8000/v1/auth/login" -Method POST -Body $body -ContentType "application/json"
|
||||||
|
|
||||||
|
$token = $login.data.access_token
|
||||||
|
$tenantId = $login.data.user.tenant_id
|
||||||
|
|
||||||
|
$headers = @{
|
||||||
|
"Authorization" = "Bearer $token"
|
||||||
|
"X-Tenant-ID" = $tenantId
|
||||||
|
}
|
||||||
|
|
||||||
|
Write-Host "Autenticacion exitosa" -ForegroundColor Green
|
||||||
|
|
||||||
|
# 2. Listar tickets
|
||||||
|
$tickets = Invoke-RestMethod -Uri "http://localhost:8000/v1/tickets" -Headers $headers
|
||||||
|
$ticketId = $tickets.data[0].id
|
||||||
|
|
||||||
|
Write-Host "Ticket ID obtenido: $ticketId" -ForegroundColor Green
|
||||||
|
|
||||||
|
# 3. Listar attachments del ticket
|
||||||
|
$attachments = Invoke-RestMethod -Uri "http://localhost:8000/v1/tickets/$ticketId/attachments" -Headers $headers
|
||||||
|
|
||||||
|
Write-Host "Attachments listados: $($attachments.Count) encontrados" -ForegroundColor Green
|
||||||
|
|
||||||
|
if ($attachments.Count -gt 0) {
|
||||||
|
$attachments | Format-Table id, original_filename, file_size, created_at
|
||||||
|
}
|
||||||
|
|
||||||
|
Write-Host ""
|
||||||
|
Write-Host "TEST COMPLETADO" -ForegroundColor Cyan
|
||||||
45
test_attachments_endpoint.ps1
Normal file
45
test_attachments_endpoint.ps1
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
# Test script para attachments endpoint
|
||||||
|
Write-Host "=== Testing Attachments Endpoint ===" -ForegroundColor Cyan
|
||||||
|
|
||||||
|
# 1. Login
|
||||||
|
$body = '{"email":"admin@aduanasoft.com","password":"admin123","tenant_slug":"aduanasoft"}'
|
||||||
|
try {
|
||||||
|
$login = Invoke-RestMethod -Uri "http://localhost:8000/v1/auth/login" -Method POST -Body $body -ContentType "application/json"
|
||||||
|
Write-Host "[OK] Login exitoso" -ForegroundColor Green
|
||||||
|
|
||||||
|
$token = $login.access_token
|
||||||
|
$tenantId = $login.user.tenant_id
|
||||||
|
|
||||||
|
Write-Host "Token: $($token.Substring(0,20))..." -ForegroundColor Gray
|
||||||
|
Write-Host "Tenant ID: $tenantId" -ForegroundColor Gray
|
||||||
|
|
||||||
|
# 2. Test attachments endpoint
|
||||||
|
$headers = @{
|
||||||
|
"Authorization" = "Bearer $token"
|
||||||
|
"X-Tenant-ID" = $tenantId
|
||||||
|
}
|
||||||
|
|
||||||
|
$url = "http://localhost:8000/v1/tickets/68eaf0fe-b5c3-4d42-9b36-895b439be583/attachments"
|
||||||
|
Write-Host "`nProbando GET $url" -ForegroundColor Yellow
|
||||||
|
|
||||||
|
try {
|
||||||
|
$response = Invoke-WebRequest -Uri $url -Headers $headers -Method GET
|
||||||
|
Write-Host "[OK] Status Code: $($response.StatusCode)" -ForegroundColor Green
|
||||||
|
|
||||||
|
$data = $response.Content | ConvertFrom-Json
|
||||||
|
Write-Host "[OK] Attachments encontrados: $($data.Count)" -ForegroundColor Green
|
||||||
|
|
||||||
|
if ($data.Count -gt 0) {
|
||||||
|
$data | Format-Table id, original_filename, file_size
|
||||||
|
} else {
|
||||||
|
Write-Host " (No hay attachments para este ticket)" -ForegroundColor Gray
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch {
|
||||||
|
Write-Host "[ERROR] En request: $($_.Exception.Message)" -ForegroundColor Red
|
||||||
|
Write-Host "Status Code: $($_.Exception.Response.StatusCode.value__)" -ForegroundColor Red
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch {
|
||||||
|
Write-Host "[ERROR] En login: $($_.Exception.Message)" -ForegroundColor Red
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user