Skip to main content

STACK_PERFIL - Documentación para Desarrolladores

Descripción General

Stack core de perfiles de usuario MAS10. Gestiona el ciclo de vida completo del perfil: registro OAuth, CRUD, datos físicos/nutricionales, avatar (3 tamaños con background removal), resumen estadístico, trayectoria deportiva, ubicación con PostGIS, tips con tracking de acceso, figuritas (sticker borders), versión de app, idiomas, términos y condiciones, y calendario Google.

Arquitectura

STACK_PERFIL/
├── perfil.yaml # Template SAM
├── build_perfil.sh
├── layer/
│ ├── database_perfil/ # Lógica de dominio pesada
│ │ └── database.py # Queries complejos (CTEs, window functions)
│ ├── querys_perfil/
│ │ └── query.py
│ ├── response_formatter_perfil/
│ │ └── response_formatter.py
│ ├── s3_perfil/
│ │ └── s3.py # Avatares 3 tamaños, PDFs
│ └── utils_perfil/
│ └── utils.py
└── services/
├── check-version/ # Verificación semántica de versión
├── coach-athletes/ # Atletas del entrenador
├── e-mail/ # Envío SMTP (⚠️ credenciales hardcoded)
├── languages/ # GET idiomas, PUT cambiar idioma
├── like-note/ # Toggle like con contadores feed
├── location/ # CRUD con PostGIS + clustering Lambda
├── next-play-by-user/ # Próximo partido
├── profile/ # GET (512MB), PUT (1024MB), DELETE
├── register/ # POST registro OAuth (512MB)
├── sticker-border/ # Bordes de figuritas
├── summary/ # Estadísticas del usuario (CTEs complejos)
├── terms-and-conditions/ # Aceptar TyC
├── tips/ # Tips con access tracking
├── tocke/ # Token Google Calendar
├── tournament-history/ # Historial de ediciones
└── trajectory/ # Trayectoria deportiva

Runtime y Configuración

PropiedadValor
Python3.13
ArquitecturaARM64
Timeout default30s
Memoria default128MB
AuthCognito JWT (mayoría)

Funciones con configuración especial:

FunciónTimeoutMemoriaNotas
profile GET30s512MBCarga completa de perfil
profile PUT30s1024MBAvatar processing (3 tamaños) + background removal
register POST30s512MBOAuth + DynamoDB + PostgreSQL
summary GET30s256MBCTEs complejos de estadísticas

Pipeline de Avatar

PUT /profile (actualización con avatar):

  1. Recibe imagen como Base64 o URL
  2. Genera 3 versiones:
    • Original: Tamaño completo
    • 50px: Thumbnail para listas
    • 100px: Thumbnail para cards
  3. Invoca Lambda de background removal (async)
  4. Sube las 3 versiones a S3
  5. Actualiza URLs en PostgreSQL
  6. Sync con DynamoDB (tabla Profiles{ENV})
# Flujo de avatar
blob = utils.get_blob(body['avatar'])
s3.upload(blob, f"avatars/{user_id}/original")
s3.upload_resized(blob, f"avatars/{user_id}/50", 50)
s3.upload_resized(blob, f"avatars/{user_id}/100", 100)
aws.execute_lambda("background-removal", {"key": f"avatars/{user_id}/original"}, "Event")

Sistema de Registro

POST /register:

  1. Recibe datos OAuth (Google/Apple/Email)
  2. Verifica si usuario ya existe en PostgreSQL
  3. Si existe → retorna perfil existente
  4. Si no existe:
    • Crea en PostgreSQL (userprofile)
    • Crea en DynamoDB (Profiles{ENV})
    • Si tiene avatar provider → descarga y sube a S3
  5. Retorna perfil con flag is_new

Tabla userprofile (campos principales):

id, email, first_name, last_name, username, avatar, avatar_50, avatar_100,
position, dominant_foot, height, weight, date_of_birth, gender,
type_user (athlete|coach|seer|webuser), language, provider,
description, phone, created_at, updated_at

Resumen Estadístico (Summary)

GET /summary:

Usa CTEs (Common Table Expressions) complejos para agregar:

  • Goles, asistencias, tarjetas amarillas/rojas
  • Partidos jugados, ganados, empatados, perdidos
  • Puntos totales
  • Agrupado por año y torneo
  • Soporta userprofile y team
WITH player_stats AS (
SELECT ... FROM tournament_match_player
WHERE user_id = %(id)s AND year = %(year)s
GROUP BY tournament_id
),
team_stats AS (
SELECT ... FROM tournament_match
WHERE ... GROUP BY ...
)
SELECT * FROM player_stats
JOIN team_stats USING (tournament_id)

Trayectoria (Trajectory)

GET /trajectory:

Carrera deportiva con agrupación inteligente:

  • Por año → Por equipo → Estadísticas
  • Detecta cambios de equipo en el mismo año
  • Soporta userprofile (jugador) y team (equipo)

Sistema de Ubicación

CRUD /location/:

  • POST: Crea ubicación con PostGIS (ST_MakePoint(long, lat))
    • Dispara Lambda de re-clustering async
  • GET: Consulta por ID, perfil, o coordenadas
  • PUT: Actualiza campos
  • DELETE: Elimina ubicación

Clustering Lambda:

Después de crear/actualizar ubicación, se invoca Lambda de clustering que:

  1. Re-calcula clusters geográficos
  2. Actualiza tabla de recomendaciones del sistema de followers

Like Note

POST /like-note:

  • Toggle: si no hay like, lo crea; si ya hay, lo elimina
  • Actualiza contador en tabla feed_aggregate
  • No envía notificación push (solo counter update)

Tips con Access Tracking

GET /tips:

  1. Retorna tips por categoría
  2. Registra acceso del usuario al tip (tip_access table)
  3. Permite tracking de qué tips ha visto cada usuario

⚠️ Issues Conocidos

Credenciales SMTP hardcoded

e-mail/post.py tiene credenciales de Gmail hardcoded:

# ❌ Inseguro
smtp_user = "notificaciones@mas10.com"
smtp_pass = "xxxxx" # Hardcoded

# ✅ Debería usar AWS Secrets Manager
secret = aws.get_secret_aws("email_credentials")

Tablas de Base de Datos

PostgreSQL:

  • userprofile — Perfil completo del usuario
  • physical_data — Datos físicos (peso, altura, IMC)
  • nutrition_data — Datos nutricionales
  • location — Ubicaciones con geometría PostGIS
  • tip — Tips del sistema
  • tip_access — Tracking de acceso a tips
  • sticker_border — Bordes de figuritas disponibles
  • terms_conditions — Versiones de TyC
  • terms_conditions_user — Aceptaciones por usuario
  • language — Idiomas disponibles
  • feed_aggregate — Contadores de likes/engagement

DynamoDB:

  • Profiles{ENV} — Cache de perfiles (sync bidireccional)

Sync PostgreSQL ↔ DynamoDB

El perfil se mantiene sincronizado en ambas BDs:

  • Escritura: PUT /profile actualiza PostgreSQL primero, luego DynamoDB
  • Registro: POST /register crea en ambas
  • Delete: DELETE /profile elimina/anonimiza en ambas
  • Lectura: GET /profile lee de PostgreSQL (source of truth)

Build y Deploy

cd STACK_PERFIL
sudo bash ./build_perfil.sh 1 -d # Dev local
sudo bash ./build_perfil.sh 2 -d # Dev deploy
sudo bash ./build_perfil.sh 2 -q # QA deploy
sudo bash ./build_perfil.sh 2 -p # Prod deploy