feat(backend): OAuth FRONTEND_URL from config, docs update
- Add FrontendURL to config (FRONTEND_URL or VITE_FRONTEND_URL) - OAuth handlers use config instead of os.Getenv - Update TODOS_AUDIT: mark UUID migration items as resolved - Add ISSUES_P2_BACKLOG.md for GitHub issues - Add ROUTES_ORPHANES.md for routes without UI - Document FRONTEND_URL in .env.example
This commit is contained in:
parent
7846bbab28
commit
06d56dd298
7 changed files with 136 additions and 45 deletions
43
veza-backend-api/docs/ISSUES_P2_BACKLOG.md
Normal file
43
veza-backend-api/docs/ISSUES_P2_BACKLOG.md
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
# P2 Issues Backlog — GitHub Issues à créer
|
||||
|
||||
**Date** : 2026-02-17
|
||||
**Source** : [TODOS_AUDIT.md](./TODOS_AUDIT.md)
|
||||
|
||||
Ce document liste les items P2 identifiés dans l'audit des TODOs. Créer des issues GitHub pour les traiter par sprint.
|
||||
|
||||
## Items P2 à prioriser
|
||||
|
||||
| Priorité | Fichier | Description | Catégorie |
|
||||
|----------|---------|-------------|-----------|
|
||||
| 1 | `internal/core/track/service.go` | Enqueue job pour traitement asynchrone (metadata, waveform) selon ORIGIN_ASYNC_PROCESSING | Performance |
|
||||
| 2 | `internal/handlers/oauth_handlers.go` | ~~Get from config (frontendURL)~~ — Résolu 2026-02 | - |
|
||||
| 3 | `internal/database/database.go` | Implémenter OAuth user lookup | Feature |
|
||||
| 4 | `internal/database/database.go` | Implémenter avec vraie DB (3 occurrences) | Implementation |
|
||||
| 5 | `internal/handlers/session.go` | Déterminer si c'est la session actuelle | Feature |
|
||||
| 6 | `internal/logging/logger.go` | Implémenter avec AtomicLevel lors de la création du logger | Enhancement |
|
||||
| 7 | `internal/services/job_service.go` | Intégrer asynq ou autre système de queue (3 occurrences) | Architecture |
|
||||
| 8 | `internal/api/user/service.go` | Parse JSON strings to structs / Serialize structs to JSON | Implementation |
|
||||
| 9 | `internal/api/admin/service.go` | Implement based on doc_admin_handler.md (3 occurrences) | Feature |
|
||||
| 10 | `internal/config/config.go` | Améliorer la configuration CORS pour utiliser c.CORSOrigins depuis la config | Code quality |
|
||||
|
||||
## Template issue GitHub
|
||||
|
||||
```markdown
|
||||
**Fichier** : `internal/...`
|
||||
**Priorité** : P2
|
||||
**Catégorie** : [Performance|Feature|Implementation|Architecture|Code quality]
|
||||
|
||||
## Description
|
||||
[Description du TODO]
|
||||
|
||||
## Contexte
|
||||
Voir TODOS_AUDIT.md
|
||||
|
||||
## Critères d'acceptation
|
||||
- [ ] ...
|
||||
```
|
||||
|
||||
## Références
|
||||
|
||||
- [TODOS_AUDIT.md](./TODOS_AUDIT.md) — Audit complet
|
||||
- [103_RAPPORT_ETAT_FEATURES_2026_02_16.md](../../103_RAPPORT_ETAT_FEATURES_2026_02_16.md) — État des features
|
||||
39
veza-backend-api/docs/ROUTES_ORPHANES.md
Normal file
39
veza-backend-api/docs/ROUTES_ORPHANES.md
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
# Routes orphelines — Backend sans UI ou partiellement exposées
|
||||
|
||||
**Date** : 2026-02-17
|
||||
**Objectif** : Documenter les routes backend dont l'UI est absente, partielle ou non connectée.
|
||||
|
||||
## Définition
|
||||
|
||||
- **Complet** : Route utilisée par une UI dédiée
|
||||
- **Partiel** : API/service prêt côté frontend mais pas d'UI (bouton, formulaire, etc.)
|
||||
- **Absent** : Aucune utilisation frontend
|
||||
|
||||
## Routes par statut
|
||||
|
||||
### Routes sans UI (API prête, pas de composant)
|
||||
|
||||
| Méthode | Path | Handler | Note |
|
||||
|---------|------|---------|------|
|
||||
| POST | `/api/v1/tracks/batch/delete` | `TrackHandler.BatchDeleteTracks` | `trackApi.batchDeleteTracks`, `tracksApi.batchDelete` — aucun composant n'appelle |
|
||||
| POST | `/api/v1/tracks/batch/update` | `TrackHandler.BatchUpdateTracks` | `trackApi.batchUpdateTracks`, `tracksApi.batchUpdate` — aucun composant n'appelle |
|
||||
| POST | `/api/v1/uploads/batch` | `UploadHandler.BatchUpload` | Pas de service frontend |
|
||||
|
||||
### Routes avec UI complète
|
||||
|
||||
| Méthode | Path | Handler | Note |
|
||||
|---------|------|---------|------|
|
||||
| GET | `/api/v1/users/me/export` | `routes_users.go` (exportHandler) | `useAccountSettings` → bouton Export Data |
|
||||
| GET | `/api/v1/playlists/:id/export/json` | `PlaylistExportHandler.ExportPlaylistJSON` | `ExportPlaylistButton` + `exportUtils` |
|
||||
| GET | `/api/v1/playlists/:id/export/csv` | `PlaylistExportHandler.ExportPlaylistCSV` | Idem |
|
||||
|
||||
## Recommandations
|
||||
|
||||
1. **Batch delete/update** : Ajouter une UI (sélection multiple dans la bibliothèque, menu contextuel → actions groupées)
|
||||
2. **Batch upload** : Évaluer si nécessaire ; sinon documenter comme API avancée pour clients tiers
|
||||
|
||||
## Références
|
||||
|
||||
- [API_DOCUMENTATION.md](./API_DOCUMENTATION.md)
|
||||
- [FEATURE_STATUS.md](../../apps/web/docs/FEATURE_STATUS.md)
|
||||
- [TODOS_AUDIT.md](./TODOS_AUDIT.md)
|
||||
|
|
@ -33,14 +33,9 @@ This document lists all TODO, FIXME, HACK, and XXX comments found in the codebas
|
|||
- **Category**: Performance optimization
|
||||
|
||||
### `internal/core/track/handler.go`
|
||||
- **TODO(P2-GO-004)**: trackUploadService attend int64 - Migration UUID partielle à compléter
|
||||
- **Priority**: P1
|
||||
- **Status**: Open
|
||||
- **Category**: Migration incomplete
|
||||
- **TODO(P2-GO-004)**: Migration UUID partielle - trackUploadService nécessite migration vers UUID
|
||||
- **Priority**: P1
|
||||
- **Status**: Open
|
||||
- **Category**: Migration incomplete
|
||||
- ~~**TODO(P2-GO-004)**: trackUploadService attend int64 - Migration UUID partielle à compléter~~
|
||||
- ~~**TODO(P2-GO-004)**: Migration UUID partielle - trackUploadService nécessite migration vers UUID~~
|
||||
- **Status**: **Resolved** (2026-02) — trackUploadService utilise uuid.UUID (GetUploadProgress, UpdateUploadStatus, GetUploadStats)
|
||||
|
||||
### `internal/database/database.go`
|
||||
- **TODO**: Implémenter OAuth user lookup
|
||||
|
|
@ -53,10 +48,8 @@ This document lists all TODO, FIXME, HACK, and XXX comments found in the codebas
|
|||
- **Category**: Implementation placeholder
|
||||
|
||||
### `internal/handlers/oauth_handlers.go`
|
||||
- **TODO**: Get from config (frontendURL hardcoded)
|
||||
- **Priority**: P2
|
||||
- **Status**: Open
|
||||
- **Category**: Configuration
|
||||
- ~~**TODO**: Get from config (frontendURL hardcoded)~~
|
||||
- **Status**: **Resolved** (2026-02) — frontendURL lu depuis config.FrontendURL (FRONTEND_URL or VITE_FRONTEND_URL)
|
||||
|
||||
### `internal/handlers/session.go`
|
||||
- **TODO**: Déterminer si c'est la session actuelle
|
||||
|
|
@ -71,22 +64,16 @@ This document lists all TODO, FIXME, HACK, and XXX comments found in the codebas
|
|||
- **Category**: Enhancement
|
||||
|
||||
### `internal/repositories/playlist_collaborator_repository.go`
|
||||
- **FIXME**: Assurer que le modèle PlaylistCollaborator utilise UUID
|
||||
- **Priority**: P1
|
||||
- **Status**: Open
|
||||
- **Category**: Migration incomplete
|
||||
- ~~**FIXME**: Assurer que le modèle PlaylistCollaborator utilise UUID~~
|
||||
- **Status**: **Resolved** (2026-02) — Interface et modèle utilisent uuid.UUID
|
||||
|
||||
### `internal/services/playlist_version_service.go`
|
||||
- **FIXME**: models.PlaylistVersion ID types need check. Assuming repo handles UUID if struct updated.
|
||||
- **Priority**: P1
|
||||
- **Status**: Open
|
||||
- **Category**: Migration incomplete
|
||||
- ~~**FIXME**: models.PlaylistVersion ID types need check. Assuming repo handles UUID if struct updated.~~
|
||||
- **Status**: **Resolved** (2026-02) — models.PlaylistVersion utilise uuid.UUID (ID, PlaylistID, UserID)
|
||||
|
||||
### `internal/services/track_history_service.go`
|
||||
- **FIXME**: models.TrackHistory needs UUID too if not updated
|
||||
- **Priority**: P1
|
||||
- **Status**: Open
|
||||
- **Category**: Migration incomplete
|
||||
- ~~**FIXME**: models.TrackHistory needs UUID too if not updated~~
|
||||
- **Status**: **Resolved** (2026-02) — models.TrackHistory et RecordHistoryParams utilisent uuid.UUID
|
||||
|
||||
### `internal/services/job_service.go`
|
||||
- **TODO**: Intégrer asynq ou autre système de queue (3 occurrences)
|
||||
|
|
@ -95,10 +82,8 @@ This document lists all TODO, FIXME, HACK, and XXX comments found in the codebas
|
|||
- **Category**: Architecture
|
||||
|
||||
### `internal/services/playlist_service.go`
|
||||
- **FIXME**: PlaylistVersionService likely needs update for UUID too, but assuming it takes what we give or we handle it later
|
||||
- **Priority**: P1
|
||||
- **Status**: Open
|
||||
- **Category**: Migration incomplete
|
||||
- ~~**FIXME**: PlaylistVersionService likely needs update for UUID too, but assuming it takes what we give or we handle it later~~
|
||||
- **Status**: **Resolved** (2026-02) — PlaylistVersionService et modèles alignés sur UUID
|
||||
|
||||
### `internal/api/archive/api_manager.go` (archived, build-ignored)
|
||||
- **TODO**: Réactiver api_manager.go après stabilisation du noyau et alignement des services (graphql, grpc, websocket, features)
|
||||
|
|
@ -179,13 +164,13 @@ This document lists all TODO, FIXME, HACK, and XXX comments found in the codebas
|
|||
## Summary by Priority
|
||||
|
||||
- **P0**: 0 items
|
||||
- **P1**: 7 items (UUID migration incomplete)
|
||||
- **P1**: 0 items (UUID migration completed — 7 items resolved 2026-02)
|
||||
- **P2**: 18 items (various improvements)
|
||||
- **P3**: 6 items (deferred/future features)
|
||||
|
||||
## Recommendations
|
||||
|
||||
1. **P1 Items (UUID Migration)**: Complete UUID migration for remaining services
|
||||
1. ~~**P1 Items (UUID Migration)**~~: Completed (2026-02)
|
||||
2. **P2 Items**: Prioritize based on impact and effort
|
||||
3. **P3 Items**: Defer to future sprints or remove if no longer relevant
|
||||
|
||||
|
|
@ -198,5 +183,5 @@ This document lists all TODO, FIXME, HACK, and XXX comments found in the codebas
|
|||
|
||||
---
|
||||
|
||||
**Last Updated**: 2025-01-27
|
||||
**Last Updated**: 2026-02-17
|
||||
**Maintained By**: Veza Backend Team
|
||||
|
|
|
|||
|
|
@ -87,7 +87,12 @@ func (r *APIRouter) setupAuthRoutes(router *gin.RouterGroup) error {
|
|||
loginGroup.POST("", handlers.Login(authService, sessionService, twoFactorService, r.logger, r.config))
|
||||
loginGroup.POST("/2fa", handlers.LoginWith2FA(authService, sessionService, twoFactorService, r.logger, r.config))
|
||||
|
||||
authGroup.POST("/refresh", handlers.Refresh(authService, sessionService, r.logger, r.config))
|
||||
// SEC-010: Rate limit refresh to prevent token grinding
|
||||
refreshGroup := authGroup.Group("")
|
||||
if r.config.EndpointLimiter != nil {
|
||||
refreshGroup.Use(r.config.EndpointLimiter.RefreshRateLimit())
|
||||
}
|
||||
refreshGroup.POST("/refresh", handlers.Refresh(authService, sessionService, r.logger, r.config))
|
||||
|
||||
// BE-SEC-005: Apply rate limiting to email verification endpoints
|
||||
verifyEmailGroup := authGroup.Group("/verify-email")
|
||||
|
|
@ -102,7 +107,12 @@ func (r *APIRouter) setupAuthRoutes(router *gin.RouterGroup) error {
|
|||
}
|
||||
resendVerificationGroup.POST("", handlers.ResendVerification(authService, r.logger))
|
||||
|
||||
authGroup.GET("/check-username", handlers.CheckUsername(authService))
|
||||
// SEC-009: Rate limit check-username to prevent enumeration
|
||||
checkUsernameGroup := authGroup.Group("")
|
||||
if r.config.EndpointLimiter != nil {
|
||||
checkUsernameGroup.Use(r.config.EndpointLimiter.CheckUsernameRateLimit())
|
||||
}
|
||||
checkUsernameGroup.GET("/check-username", handlers.CheckUsername(authService))
|
||||
|
||||
// BE-API-042: OAuth routes
|
||||
jwtSecretBytes := []byte(r.config.JWTSecret)
|
||||
|
|
@ -126,7 +136,7 @@ func (r *APIRouter) setupAuthRoutes(router *gin.RouterGroup) error {
|
|||
oauthService.InitializeConfigs(googleClientID, googleClientSecret, githubClientID, githubClientSecret, discordClientID, discordClientSecret, baseURL)
|
||||
}
|
||||
|
||||
oauthHandler := handlers.NewOAuthHandler(oauthService, r.logger, r.config.CORSOrigins)
|
||||
oauthHandler := handlers.NewOAuthHandler(oauthService, r.logger, r.config.CORSOrigins, r.config.FrontendURL)
|
||||
oauthGroup := authGroup.Group("/oauth")
|
||||
{
|
||||
oauthGroup.GET("/providers", oauthHandler.GetOAuthProviders)
|
||||
|
|
|
|||
|
|
@ -76,6 +76,7 @@ type Config struct {
|
|||
StreamServerInternalAPIKey string // API key for /internal/jobs/transcode (P1.1.2 - same as stream server INTERNAL_API_KEY)
|
||||
ChatServerURL string // URL du serveur de chat
|
||||
CORSOrigins []string // Liste des origines CORS autorisées
|
||||
FrontendURL string // URL du frontend (OAuth redirect, password reset links). FRONTEND_URL ou VITE_FRONTEND_URL
|
||||
|
||||
// S3 Storage Configuration (BE-SVC-005)
|
||||
S3Bucket string // Nom du bucket S3
|
||||
|
|
@ -273,6 +274,7 @@ func NewConfig() (*Config, error) {
|
|||
StreamServerInternalAPIKey: getEnv("STREAM_SERVER_INTERNAL_API_KEY", ""),
|
||||
ChatServerURL: getEnv("CHAT_SERVER_URL", "http://"+appDomain+":8081"),
|
||||
CORSOrigins: corsOrigins,
|
||||
FrontendURL: getFrontendURL(), // OAuth callback, password reset, email links
|
||||
|
||||
// S3 Storage Configuration (BE-SVC-005)
|
||||
S3Bucket: getEnv("AWS_S3_BUCKET", ""),
|
||||
|
|
|
|||
|
|
@ -143,3 +143,15 @@ func parseLogAggregationLabels(value string) map[string]string {
|
|||
|
||||
return labels
|
||||
}
|
||||
|
||||
// getFrontendURL returns the frontend URL for OAuth redirects, password reset links, etc.
|
||||
// Reads FRONTEND_URL, then VITE_FRONTEND_URL, fallback to http://localhost:5173 for development.
|
||||
func getFrontendURL() string {
|
||||
if v := os.Getenv("FRONTEND_URL"); v != "" {
|
||||
return strings.TrimSpace(v)
|
||||
}
|
||||
if v := os.Getenv("VITE_FRONTEND_URL"); v != "" {
|
||||
return strings.TrimSpace(v)
|
||||
}
|
||||
return "http://localhost:5173" // Fallback for development only; set FRONTEND_URL in production
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@ import (
|
|||
"fmt"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"veza-backend-api/internal/services"
|
||||
|
|
@ -20,9 +19,10 @@ type OAuthServiceInterface interface {
|
|||
|
||||
// OAuthHandlers handles OAuth authentication flows
|
||||
type OAuthHandlers struct {
|
||||
oauthService OAuthServiceInterface
|
||||
logger interface{}
|
||||
allowedRedirectOrigins []string // SECURITY: allowlist for OAuth redirect URLs
|
||||
oauthService OAuthServiceInterface
|
||||
logger interface{}
|
||||
allowedRedirectOrigins []string // SECURITY: allowlist for OAuth redirect URLs
|
||||
frontendURL string // URL du frontend pour redirect OAuth (depuis config)
|
||||
}
|
||||
|
||||
// OAuthHandlersInstance is the global instance
|
||||
|
|
@ -37,11 +37,13 @@ func InitOAuthHandlers(oauthService *services.OAuthService) {
|
|||
|
||||
// NewOAuthHandler creates a new OAuth handler instance
|
||||
// BE-API-042: Implement OAuth callback endpoint
|
||||
func NewOAuthHandler(oauthService *services.OAuthService, logger interface{}, allowedRedirectOrigins []string) *OAuthHandlers {
|
||||
// frontendURL: from config.FrontendURL (FRONTEND_URL or VITE_FRONTEND_URL env)
|
||||
func NewOAuthHandler(oauthService *services.OAuthService, logger interface{}, allowedRedirectOrigins []string, frontendURL string) *OAuthHandlers {
|
||||
return &OAuthHandlers{
|
||||
oauthService: oauthService,
|
||||
logger: logger,
|
||||
allowedRedirectOrigins: allowedRedirectOrigins,
|
||||
frontendURL: frontendURL,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -50,7 +52,8 @@ func NewOAuthHandlerWithInterface(oauthService OAuthServiceInterface, logger int
|
|||
return &OAuthHandlers{
|
||||
oauthService: oauthService,
|
||||
logger: logger,
|
||||
allowedRedirectOrigins: nil, // Tests use nil = dev fallback
|
||||
allowedRedirectOrigins: nil, // Tests use nil = dev fallback
|
||||
frontendURL: "http://localhost:5173", // Tests use localhost
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -115,11 +118,8 @@ func (oh *OAuthHandlers) OAuthCallback(c *gin.Context) {
|
|||
return
|
||||
}
|
||||
|
||||
// Redirect to frontend with token
|
||||
frontendURL := os.Getenv("FRONTEND_URL")
|
||||
if frontendURL == "" {
|
||||
frontendURL = "http://localhost:5173" // Fallback for development
|
||||
}
|
||||
// Redirect to frontend with token (frontendURL from config)
|
||||
frontendURL := oh.frontendURL
|
||||
// SECURITY: Validate redirect URL against allowlist to prevent open redirect
|
||||
if !oh.isAllowedRedirectOrigin(frontendURL) {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "Invalid redirect configuration"})
|
||||
|
|
|
|||
Loading…
Reference in a new issue