¡Bienvenido a Gymmetry!
Este proyecto es una API robusta para la gestión de gimnasios, desarrollada con .NET 9, Azure Functions y MySQL. Implementa una arquitectura en capas, seguridad moderna y servicios en la nube AWS para ofrecer una solución escalable y mantenible.
- .NET 9
- Azure Functions (HttpTrigger, TimerTrigger)
- MySQL 8.0 (migrado desde SQL Server)
- Entity Framework Core con Pomelo MySQL provider
- Inyección de dependencias (
Microsoft.Extensions.DependencyInjection) - JWT Authentication
- AutoMapper
- Amazon S3 - Almacenamiento de archivos (imágenes de perfil, feed media, gym images)
- Amazon SES - Envío de emails transaccionales (notificaciones, recuperación de contraseña)
- Amazon Pinpoint - Envío de SMS y notificaciones push
- LocalStack - Emulador AWS para desarrollo local (S3, SES, Pinpoint en puerto 4566)
- Redis - Cache distribuido (opcional, configurable)
- Application Insights - Monitoreo y telemetría
- MercadoPago - Pasarela de pagos (con soporte multi-gateway)
El backend sigue una arquitectura en capas:
- Functions: Entrypoints HTTP y Timer (controladores tipo serverless)
- Services: Lógica de negocio desacoplada
- Repositories: Acceso a datos y persistencia
- DTOs: Objetos de transferencia de datos para requests/responses
- Models: Entidades de dominio
- Utils: Utilidades y helpers (validaciones, JWT, etc.)
✅ Inyección de dependencias y AutoMapper están configurados globalmente en Program.cs.
🛡️ Control de errores global con manejo de excepciones y respuestas estandarizadas.
🔐 Autenticación implementada con JWT, validada en cada endpoint protegido.
Gymmetry.Functions/ # Proyecto API (Azure Functions)
├── Functions/ # Azure Functions (HttpTrigger, TimerTrigger)
│ ├── UserFunctions/
│ ├── MachineFunction/
│ └── ... (más módulos)
├── Utils/ # Utilidades (JwtValidator, ModelValidator, etc)
├── local.settings.json # Variables de entorno locales
└── Program.cs # Configuración principal, DI, EF, seeds
Gymmetry.Domain/ # Capa de dominio
├── Models/ # Entidades de dominio
├── DTO/ # Data Transfer Objects
├── Enums/ # Enumeraciones
└── Options/ # Configuraciones
Gymmetry.Application/ # Capa de aplicación
├── Services/ # Servicios de negocio
└── Mapping/ # AutoMapper profiles
Gymmetry.Repository/ # Capa de persistencia
├── Services/ # Repositorios e implementaciones
└── Persistence/ # DbContext, migrations, seeds
La configuración local se gestiona en local.settings.json. Variables principales:
Jwt:SecretKey,Jwt:Issuer,Jwt:Audience: Configuración JWT
ConnectionStrings:Gymmetry: Conexión a MySQL- Local:
Server=localhost;Database=gymmetrydb;User=gymmetry;Password=gymmetry123;Port=3306
- Local:
"AwsS3:ServiceUrl": "http://localhost:4566",
"AwsS3:BucketName": "gymmetry-storage",
"AwsS3:AccessKeyId": "test",
"AwsS3:SecretAccessKey": "test",
"AwsS3:Region": "us-east-1",
"AwsS3:ForcePathStyle": "true""AwsSes:ServiceUrl": "http://localhost:4566",
"AwsSes:FromEmail": "no-reply@gymmetry.fit""AwsPinpoint:ServiceUrl": "http://localhost:4566",
"AwsPinpoint:ApplicationId": "test-app-id""Redis:ConnectionString": "localhost:6379",
"Redis:Enabled": "False"Payments:GatewayProvider:3(MercadoPago por defecto)- Variables de MercadoPago, PayU, Wompi, Stripe
📦 Ver local.settings.json.example para configuración completa
# Restaurar dependencias
dotnet restore
# Compilar la solución
dotnet build
# Ejecutar pruebas unitarias
dotnet test
# Configurar LocalStack (desarrollo local con AWS emulado)
.\setup-localstack.ps1
# O manualmente:
docker-compose up -d
# Ejecutar localmente (Azure Functions)
func start
# Ejecutar tests
dotnet test
# Otras utilidades
dotnet runPara desarrollo local sin costos de AWS, usamos LocalStack para emular S3, SES y Pinpoint:
# Iniciar contenedores
docker-compose up -d
# Verificar estado
docker ps
# Verificar salud de LocalStack
curl http://localhost:4566/_localstack/healthdocker exec gymmetry-localstack awslocal s3 mb s3://gymmetry-storage# Listar buckets
docker exec gymmetry-localstack awslocal s3 ls
# Listar archivos en bucket
docker exec gymmetry-localstack awslocal s3 ls s3://gymmetry-storage/ --recursive
# Ver tamaños de archivos
docker exec gymmetry-localstack awslocal s3 ls s3://gymmetry-storage/ --recursive --human-readable
# Descargar archivo para inspección
docker exec gymmetry-localstack awslocal s3 cp s3://gymmetry-storage/user-profiles/test.jpg ./test.jpgPara ver archivos gráficamente, configura S3 Browser (Windows) o Cyberduck (multiplataforma):
Configuración S3 Browser:
Account Type: S3 Compatible Storage
REST Endpoint: http://localhost:4566
Access Key ID: test
Secret Access Key: test
Region: us-east-1
☐ Use SSL/TLS (desmarcar)
☑ Use path-style requests (marcar)
gymmetry-storage/
├── user-profiles/ # Imágenes de perfil de usuario
│ └── {userId}.jpg
├── feed-media/ # Contenido multimedia del feed
│ └── {feedId}/
│ └── {filename}
├── gym-images/ # Imágenes de gimnasios
│ └── {gymId}.jpg
└── gym-logos/ # Logos de gimnasios
└── {gymId}.jpg
Ver docker-compose.yml para configuración de servicios Docker.
Este proyecto fue migrado de Azure Blob Storage a Amazon S3. La migración incluyó:
- ✅ Reemplazo de
Azure.Storage.BlobsporAWSSDK.S3 - ✅ Implementación de
AwsS3StorageServicecon interfazIBlobStorageService - ✅ Refactorización de 5 repositorios (User, Feed, Post, Gym, GymImage)
- ✅ Soporte de presigned URLs para acceso temporal
- ✅ Configuración de LocalStack para desarrollo local
- ✅ Eliminación de ~150 líneas de código Azure legacy
- ✅ Migración de MySQL (de SQL Server)
| Aspecto | Desarrollo Local | Producción AWS |
|---|---|---|
| S3 Endpoint | http://localhost:4566 |
https://s3.{region}.amazonaws.com |
| Credenciales | test / test |
IAM Role o Access Keys reales |
| SSL/TLS | Deshabilitado | Habilitado (HTTPS) |
| Bucket | gymmetry-storage (LocalStack) |
gymmetry-prod-storage |
| ForcePathStyle | true |
false |
- Configurar IAM Role con permisos
s3:PutObject,s3:GetObject,s3:DeleteObject - Habilitar presigned URLs (
AwsS3:UsePresignedUrls: true) - Configurar lifecycle policies para expiración de archivos temporales
- Implementar versioning en bucket de producción para recuperación
- Usar CloudFront para CDN y caché de imágenes públicas
Ver MIGRATION_STATUS.md para detalles completos de la migración.
- Registro y login de usuarios (con validaciones y JWT)
- Gestión de entidades: usuarios, gimnasios, rutinas, máquinas, empleados, planes, etc.
- Validaciones y lógica compartida centralizada
- Notificaciones vía Twilio (SMS/WhatsApp)
- Procesos automáticos con TimerTrigger (ej. actualización de precios)
- Seeds y migraciones automáticas en desarrollo
- Autenticación JWT: Todos los endpoints protegidos requieren un token válido
- Control de errores global: Respuestas estándar y manejo robusto de excepciones
- CORS: Configurable desde
local.settings.json - Manejo de claves sensible: No subir
local.settings.jsonal repositorio (está en.gitignore)
- Respetar la arquitectura en capas y el principio de responsabilidad única
- Exponer solo los datos necesarios con DTOs
- Validar siempre la entrada del usuario
- Mantener dependencias actualizadas
- Usar migraciones y seeds para base de datos
- Proteger claves (idealmente con Azure Key Vault en producción)
- Mantener cobertura de pruebas unitarias
Este proyecto está licenciado bajo la licencia MIT.
¡Las contribuciones son bienvenidas!
Por favor, abre un issue o pull request siguiendo las buenas prácticas de GitHub.
Asegúrate de mantener la arquitectura y estándares del proyecto.
¿Dudas o sugerencias? No dudes en abrir un issue 🚀