veza/veza-backend-api/internal/api/routes_education.go
senke 46362581ba
Some checks failed
Backend API CI / test-unit (push) Failing after 2s
Frontend CI / test (push) Failing after 2s
Backend API CI / test-integration (push) Failing after 4s
Storybook Audit / Build & audit Storybook (push) Failing after 9s
feat(v0.12.3): F276-F305 video upload, HLS transcoding, education tests
- Add video upload endpoint POST /courses/:id/lessons/:lesson_id/video
- Add VideoTranscodeService for multi-bitrate HLS (720p/480p/360p)
- Add VideoTranscodeWorker for async lesson video processing
- Add SetLessonVideoPath and UpdateLessonTranscoding to education service
- Add uploadLessonVideo to frontend educationService with progress
- Add comprehensive handler tests (video upload, auth, validation)
- Add service-level tests (models, slugs, clamping, errors, UUIDs)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 19:20:48 +01:00

70 lines
2.6 KiB
Go

package api
import (
"github.com/gin-gonic/gin"
"veza-backend-api/internal/core/education"
"veza-backend-api/internal/handlers"
)
// setupEducationRoutes configures routes for Formation & Éducation (v0.12.3 F276-F305)
func (r *APIRouter) setupEducationRoutes(router *gin.RouterGroup) {
svc := education.NewService(r.db.GormDB, r.logger)
handler := handlers.NewEducationHandler(svc, r.logger)
// Public course catalog
coursePublic := router.Group("/courses")
coursePublic.GET("", handler.ListPublishedCourses)
coursePublic.GET("/:id", handler.GetCourse)
coursePublic.GET("/:id/lessons", handler.GetCourseLessons)
coursePublic.GET("/:id/reviews", handler.GetCourseReviews)
coursePublic.GET("/slug/:slug", handler.GetCourseBySlug)
// Public certificate verification
router.GET("/certificates/:code", handler.VerifyCertificate)
if r.config.AuthMiddleware == nil {
return
}
// Course management (requires auth)
courseAuth := router.Group("/courses")
courseAuth.Use(r.config.AuthMiddleware.RequireAuth())
r.applyCSRFProtection(courseAuth)
courseAuth.POST("", handler.CreateCourse)
courseAuth.PUT("/:id", handler.UpdateCourse)
courseAuth.DELETE("/:id", handler.DeleteCourse)
courseAuth.POST("/:id/publish", handler.PublishCourse)
courseAuth.POST("/:id/archive", handler.ArchiveCourse)
courseAuth.POST("/:id/lessons", handler.CreateLesson)
courseAuth.PUT("/:id/lessons/:lesson_id", handler.UpdateLesson)
courseAuth.DELETE("/:id/lessons/:lesson_id", handler.DeleteLesson)
courseAuth.POST("/:id/lessons/reorder", handler.ReorderLessons)
courseAuth.POST("/:id/lessons/:lesson_id/video", handler.UploadLessonVideo)
courseAuth.POST("/:id/enroll", handler.Enroll)
courseAuth.GET("/:id/progress", handler.GetCourseProgress)
courseAuth.POST("/:id/certificate", handler.IssueCertificate)
courseAuth.POST("/:id/reviews", handler.CreateReview)
// Enrollments (requires auth)
enrollAuth := router.Group("/enrollments")
enrollAuth.Use(r.config.AuthMiddleware.RequireAuth())
enrollAuth.GET("", handler.GetMyEnrollments)
// Progress (requires auth)
lessonAuth := router.Group("/lessons")
lessonAuth.Use(r.config.AuthMiddleware.RequireAuth())
r.applyCSRFProtection(lessonAuth)
lessonAuth.POST("/:lesson_id/progress", handler.UpdateProgress)
// Certificates (requires auth for user's own)
certAuth := router.Group("/certificates")
certAuth.Use(r.config.AuthMiddleware.RequireAuth())
certAuth.GET("", handler.GetMyCertificates)
// Creator courses list
creatorAuth := router.Group("/creators/me")
creatorAuth.Use(r.config.AuthMiddleware.RequireAuth())
creatorAuth.GET("/courses", handler.ListCreatorCourses)
}