Files
landing_page/backend/internal/router/router.go
T
Godopu 3f452468d6 feat(console,api): implement /console Admin Dashboard and Go backend full CRUD REST APIs
- Add comprehensive /console admin web UI for managing research projects, areas, members, publications, patents, lectures, and standards
- Implement Admin token authentication middleware (RequireAdminToken) with Bearer token validation
- Implement POST, PUT, DELETE REST API endpoints for all database entities across 5 domains
- Add typed admin API client in refer_landing_page/lib/adminApi.ts with localStorage session persistence
- Enhance E2E test runner to manage backend server lifecycle during automated tests
- Pass all 12 quality gates cleanly with unanimous reviewer PASS verdicts
2026-08-24 22:21:12 +09:00

132 lines
4.7 KiB
Go

package router
import (
"database/sql"
"net/http"
"git.godopu.com/lab/landing_page/backend/internal/handlers"
"git.godopu.com/lab/landing_page/backend/internal/httpx"
"git.godopu.com/lab/landing_page/backend/internal/repository"
"github.com/gin-gonic/gin"
)
func SetupRouter(db *sql.DB, adminToken string, corsOrigins ...string) *gin.Engine {
r := gin.Default()
allowOrigin := "*"
if len(corsOrigins) > 0 && corsOrigins[0] != "" {
allowOrigin = corsOrigins[0]
}
// CORS Middleware
r.Use(func(c *gin.Context) {
c.Writer.Header().Set("Access-Control-Allow-Origin", allowOrigin)
c.Writer.Header().Set("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS")
c.Writer.Header().Set("Access-Control-Allow-Headers", "Origin, Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, Authorization")
if c.Request.Method == "OPTIONS" {
c.AbortWithStatus(http.StatusNoContent)
return
}
c.Next()
})
// Repositories
homeRepo := repository.NewHomeRepository(db)
membersRepo := repository.NewMembersRepository(db)
pubsRepo := repository.NewPublicationsRepository(db)
lecturesRepo := repository.NewLecturesRepository(db)
standardsRepo := repository.NewStandardizationRepository(db)
// Handlers
homeHandler := handlers.NewHomeHandler(homeRepo)
membersHandler := handlers.NewMembersHandler(membersRepo)
pubsHandler := handlers.NewPublicationsHandler(pubsRepo)
lecturesHandler := handlers.NewLecturesHandler(lecturesRepo)
standardsHandler := handlers.NewStandardizationHandler(standardsRepo)
// API v1 Public Group (Read-only)
v1 := r.Group("/api/v1")
{
v1.GET("/health", func(c *gin.Context) {
httpx.OK(c, gin.H{"status": "ok", "service": "anl-backend-api"})
})
// Home
v1.GET("/research-projects", homeHandler.GetResearchProjects)
v1.GET("/research-areas", homeHandler.GetResearchAreas)
v1.GET("/stats/summary", homeHandler.GetStatsSummary)
// Members & Alumni
v1.GET("/members", membersHandler.GetMembers)
v1.GET("/alumni", membersHandler.GetAlumni)
// Publications & Patents
v1.GET("/publications", pubsHandler.GetPublications)
v1.GET("/publications/highlights", pubsHandler.GetHighlights)
v1.GET("/patents", pubsHandler.GetPatents)
// Lectures
v1.GET("/semesters", lecturesHandler.GetSemesters)
// Standardization
v1.GET("/standards-bodies", standardsHandler.GetStandardsBodies)
}
// API v1 Admin Group (Mutating operations requiring Bearer token)
admin := v1.Group("")
admin.Use(httpx.RequireAdminToken(adminToken))
{
admin.GET("/admin/verify", func(c *gin.Context) {
httpx.OK(c, gin.H{"status": "authenticated"})
})
// Research Projects
admin.POST("/research-projects", homeHandler.CreateResearchProject)
admin.PUT("/research-projects/:id", homeHandler.UpdateResearchProject)
admin.DELETE("/research-projects/:id", homeHandler.DeleteResearchProject)
// Research Areas
admin.POST("/research-areas", homeHandler.CreateResearchArea)
admin.PUT("/research-areas/:id", homeHandler.UpdateResearchArea)
admin.DELETE("/research-areas/:id", homeHandler.DeleteResearchArea)
// Members & Alumni
admin.POST("/members", membersHandler.CreateMember)
admin.PUT("/members/:id", membersHandler.UpdateMember)
admin.DELETE("/members/:id", membersHandler.DeleteMember)
admin.POST("/alumni", membersHandler.CreateAlumnus)
admin.PUT("/alumni/:id", membersHandler.UpdateAlumnus)
admin.DELETE("/alumni/:id", membersHandler.DeleteAlumnus)
// Publications & Patents
admin.POST("/publications", pubsHandler.CreatePublication)
admin.PUT("/publications/:id", pubsHandler.UpdatePublication)
admin.DELETE("/publications/:id", pubsHandler.DeletePublication)
admin.POST("/patents", pubsHandler.CreatePatent)
admin.PUT("/patents/:id", pubsHandler.UpdatePatent)
admin.DELETE("/patents/:id", pubsHandler.DeletePatent)
// Lectures (Semesters & Courses)
admin.POST("/semesters", lecturesHandler.CreateSemester)
admin.PUT("/semesters/:id", lecturesHandler.UpdateSemester)
admin.DELETE("/semesters/:id", lecturesHandler.DeleteSemester)
admin.POST("/semesters/:semesterId/courses", lecturesHandler.CreateCourse)
admin.PUT("/courses/:id", lecturesHandler.UpdateCourse)
admin.DELETE("/courses/:id", lecturesHandler.DeleteCourse)
// Standardization (Bodies & Documents)
admin.POST("/standards-bodies", standardsHandler.CreateStandardsBody)
admin.PUT("/standards-bodies/:id", standardsHandler.UpdateStandardsBody)
admin.DELETE("/standards-bodies/:id", standardsHandler.DeleteStandardsBody)
admin.POST("/standards-bodies/:bodyId/documents", standardsHandler.CreateStandardDocument)
admin.PUT("/standard-documents/:id", standardsHandler.UpdateStandardDocument)
admin.DELETE("/standard-documents/:id", standardsHandler.DeleteStandardDocument)
}
return r
}