diff --git a/cmd/web/main.go b/cmd/web/main.go index a20f02f..98216da 100644 --- a/cmd/web/main.go +++ b/cmd/web/main.go @@ -249,8 +249,8 @@ func main() { e := bootstrap.InitHTTPServer(conf, logger) // Register routes - router.RegisterAdminRoutes(e, userHandler, companyHandler, customerHandler, tenderHandler, feedbackHandler, tenderApprovalHandler, inquiryHandler, categoryHandler, flagHandler, notificationHandler, contactHandler, cmsHandler, kanbanHandler, fileStoreHandler, xssPolicy) - router.RegisterPublicRoutes(e, customerHandler, tenderHandler, feedbackHandler, tenderApprovalHandler, companyHandler, inquiryHandler, categoryHandler, flagHandler, notificationHandler, contactHandler, cmsHandler, fileStoreHandler, dashboardHandler, userHandler, xssPolicy) + router.RegisterAdminRoutes(e, userHandler, companyHandler, customerHandler, tenderHandler, feedbackHandler, tenderApprovalHandler, inquiryHandler, categoryHandler, flagHandler, notificationHandler, contactHandler, cmsHandler, kanbanHandler, fileStoreHandler, dashboardHandler, xssPolicy) + router.RegisterPublicRoutes(e, customerHandler, tenderHandler, feedbackHandler, tenderApprovalHandler, companyHandler, inquiryHandler, categoryHandler, flagHandler, notificationHandler, contactHandler, cmsHandler, fileStoreHandler, xssPolicy) router.RegisterDocumentScraperRoutes(e, documentScraperHandler, conf.DocumentScraper.APIKey) // Start server diff --git a/cmd/web/router/routes.go b/cmd/web/router/routes.go index 74df0c0..9b15f05 100644 --- a/cmd/web/router/routes.go +++ b/cmd/web/router/routes.go @@ -22,7 +22,7 @@ import ( "github.com/labstack/echo/v4" ) -func RegisterAdminRoutes(e *echo.Echo, userHandler *user.Handler, companyHandler *company.Handler, customerHandler *customer.Handler, tenderHandler *tender.TenderHandler, feedbackHandler *feedback.Handler, tenderApprovalHandler *tender_approval.Handler, inquiryHandler *inquiry.Handler, categoryHandler *company_category.Handler, flagHandler *assets.Handler, notificationHandler *notification.NotificationHandler, contactHandler *contact.Handler, cmsHandler *cms.Handler, kanbanHandler *kanban.Handler, fileStoreHandler *filestore.Handler, xssPolicy *security.XSSPolicy) { +func RegisterAdminRoutes(e *echo.Echo, userHandler *user.Handler, companyHandler *company.Handler, customerHandler *customer.Handler, tenderHandler *tender.TenderHandler, feedbackHandler *feedback.Handler, tenderApprovalHandler *tender_approval.Handler, inquiryHandler *inquiry.Handler, categoryHandler *company_category.Handler, flagHandler *assets.Handler, notificationHandler *notification.NotificationHandler, contactHandler *contact.Handler, cmsHandler *cms.Handler, kanbanHandler *kanban.Handler, fileStoreHandler *filestore.Handler, dashboardHandler *dashboard.Handler, xssPolicy *security.XSSPolicy) { adminV1 := e.Group("/admin/v1") // Add CSP middleware to admin routes (stricter policy) @@ -204,9 +204,21 @@ func RegisterAdminRoutes(e *echo.Echo, userHandler *user.Handler, companyHandler filesGP.GET("/:file_id/download", fileStoreHandler.Download) filesGP.DELETE("/:file_id", fileStoreHandler.Delete) } + + // Dashboard Routes + dashboardGP := adminV1.Group("/dashboard") + { + dashboardGP.Use(userHandler.AuthMiddleware()) + dashboardGP.GET("/summary", dashboardHandler.Summary) + dashboardGP.GET("/trend", dashboardHandler.Trend) + dashboardGP.GET("/countries", dashboardHandler.Countries) + dashboardGP.GET("/notice-types", dashboardHandler.NoticeTypes) + dashboardGP.GET("/closing-soon", dashboardHandler.ClosingSoon) + dashboardGP.GET("/recent", dashboardHandler.Recent) + } } -func RegisterPublicRoutes(e *echo.Echo, customerHandler *customer.Handler, tenderHandler *tender.TenderHandler, feedbackHandler *feedback.Handler, tenderApprovalHandler *tender_approval.Handler, companyHandler *company.Handler, inquiryHandler *inquiry.Handler, categoryHandler *company_category.Handler, flagHandler *assets.Handler, notificationHandler *notification.NotificationHandler, contactHandler *contact.Handler, cmsHandler *cms.Handler, fileStoreHandler *filestore.Handler, dashboardHandler *dashboard.Handler, userHandler *user.Handler, xssPolicy *security.XSSPolicy) { +func RegisterPublicRoutes(e *echo.Echo, customerHandler *customer.Handler, tenderHandler *tender.TenderHandler, feedbackHandler *feedback.Handler, tenderApprovalHandler *tender_approval.Handler, companyHandler *company.Handler, inquiryHandler *inquiry.Handler, categoryHandler *company_category.Handler, flagHandler *assets.Handler, notificationHandler *notification.NotificationHandler, contactHandler *contact.Handler, cmsHandler *cms.Handler, fileStoreHandler *filestore.Handler, xssPolicy *security.XSSPolicy) { v1 := e.Group("/api/v1") // Add CSP middleware to public routes @@ -310,18 +322,6 @@ func RegisterPublicRoutes(e *echo.Echo, customerHandler *customer.Handler, tende cmsGP.GET("/:key", cmsHandler.GetByKey) } - // Dashboard Routes (admin auth on public API prefix per dashboard-api.md) - dashboardGP := v1.Group("/dashboard") - { - dashboardGP.Use(userHandler.AuthMiddleware()) - dashboardGP.GET("/summary", dashboardHandler.Summary) - dashboardGP.GET("/trend", dashboardHandler.Trend) - dashboardGP.GET("/countries", dashboardHandler.Countries) - dashboardGP.GET("/notice-types", dashboardHandler.NoticeTypes) - dashboardGP.GET("/closing-soon", dashboardHandler.ClosingSoon) - dashboardGP.GET("/recent", dashboardHandler.Recent) - } - // File Store Routes publicFilesGP := v1.Group("/files") { diff --git a/internal/dashboard/handler.go b/internal/dashboard/handler.go index b45c003..642790b 100644 --- a/internal/dashboard/handler.go +++ b/internal/dashboard/handler.go @@ -25,7 +25,7 @@ func NewHandler(service Service) *Handler { // @Param closing_window query int false "Hours considered closing soon (default 168)" // @Success 200 {object} response.APIResponse{data=SummaryResponse} // @Failure 500 {object} response.APIResponse -// @Router /api/v1/dashboard/summary [get] +// @Router /admin/v1/dashboard/summary [get] // @Security BearerAuth func (h *Handler) Summary(c echo.Context) error { query := SummaryQuery{ @@ -50,7 +50,7 @@ func (h *Handler) Summary(c echo.Context) error { // @Param metric query string false "created|published|awarded (default created)" // @Success 200 {object} response.APIResponse{data=TrendResponse} // @Failure 500 {object} response.APIResponse -// @Router /api/v1/dashboard/trend [get] +// @Router /admin/v1/dashboard/trend [get] // @Security BearerAuth func (h *Handler) Trend(c echo.Context) error { query := TrendQuery{ @@ -75,7 +75,7 @@ func (h *Handler) Trend(c echo.Context) error { // @Param limit query int false "Top N countries (default 6)" // @Success 200 {object} response.APIResponse{data=CountriesResponse} // @Failure 500 {object} response.APIResponse -// @Router /api/v1/dashboard/countries [get] +// @Router /admin/v1/dashboard/countries [get] // @Security BearerAuth func (h *Handler) Countries(c echo.Context) error { query := CountriesQuery{ @@ -98,7 +98,7 @@ func (h *Handler) Countries(c echo.Context) error { // @Produce json // @Success 200 {object} response.APIResponse{data=NoticeTypesResponse} // @Failure 500 {object} response.APIResponse -// @Router /api/v1/dashboard/notice-types [get] +// @Router /admin/v1/dashboard/notice-types [get] // @Security BearerAuth func (h *Handler) NoticeTypes(c echo.Context) error { out, err := h.service.NoticeTypes(c.Request().Context()) @@ -119,7 +119,7 @@ func (h *Handler) NoticeTypes(c echo.Context) error { // @Param window query int false "Hours horizon (default 168)" // @Success 200 {object} response.APIResponse{data=ClosingSoonResponse} // @Failure 500 {object} response.APIResponse -// @Router /api/v1/dashboard/closing-soon [get] +// @Router /admin/v1/dashboard/closing-soon [get] // @Security BearerAuth func (h *Handler) ClosingSoon(c echo.Context) error { query := ClosingSoonQuery{ @@ -144,7 +144,7 @@ func (h *Handler) ClosingSoon(c echo.Context) error { // @Param cursor query string false "Opaque pagination cursor" // @Success 200 {object} response.APIResponse{data=RecentResponse} // @Failure 500 {object} response.APIResponse -// @Router /api/v1/dashboard/recent [get] +// @Router /admin/v1/dashboard/recent [get] // @Security BearerAuth func (h *Handler) Recent(c echo.Context) error { query := RecentQuery{