347 lines
13 KiB
Go
347 lines
13 KiB
Go
package router
|
|
|
|
import (
|
|
"tm/internal/assets"
|
|
"tm/internal/cms"
|
|
"tm/internal/company"
|
|
"tm/internal/company_category"
|
|
"tm/internal/contact"
|
|
"tm/internal/customer"
|
|
"tm/internal/dashboard"
|
|
"tm/internal/document_scraper"
|
|
"tm/internal/feedback"
|
|
"tm/internal/inquiry"
|
|
"tm/internal/kanban"
|
|
"tm/internal/notification"
|
|
"tm/internal/tender"
|
|
"tm/internal/tender_approval"
|
|
"tm/internal/user"
|
|
"tm/pkg/filestore"
|
|
"tm/pkg/security"
|
|
|
|
"github.com/labstack/echo/v4"
|
|
)
|
|
|
|
// SetupCSPSecurity registers global CSP middleware and the CSP report endpoint once.
|
|
func SetupCSPSecurity(e *echo.Echo) {
|
|
adminCSPConfig := security.DefaultCSPConfig()
|
|
adminCSPConfig.ScriptSrc = []string{"'self'"} // No unsafe-inline for admin
|
|
adminCSPConfig.StyleSrc = []string{"'self'"} // No unsafe-inline for admin
|
|
|
|
publicCSPConfig := security.DefaultCSPConfig()
|
|
|
|
e.Use(security.CSPMiddlewareForPaths("/admin", adminCSPConfig, "/api/v1", publicCSPConfig))
|
|
e.POST("/api/v1/csp-report", security.CSPReportHandler)
|
|
}
|
|
|
|
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")
|
|
|
|
// Admin Users Routes
|
|
adminUsersGP := adminV1.Group("/users")
|
|
{
|
|
adminUsersGP.Use(userHandler.AuthMiddleware())
|
|
adminUsersGP.POST("", userHandler.CreateUser)
|
|
adminUsersGP.GET("", userHandler.ListUsers)
|
|
adminUsersGP.GET("/:id", userHandler.GetUserByID)
|
|
adminUsersGP.PUT("/:id", userHandler.UpdateUser)
|
|
adminUsersGP.DELETE("/:id", userHandler.DeleteUser)
|
|
adminUsersGP.PUT("/:id/status", userHandler.UpdateUserStatus)
|
|
adminUsersGP.POST("/:id/reset-password", userHandler.ResetUserPassword)
|
|
}
|
|
|
|
// Admin user profile
|
|
profileGP := adminV1.Group("/profile")
|
|
{
|
|
userAuthorizationGP := profileGP.Group("")
|
|
userAuthorizationGP.POST("/login", userHandler.Login)
|
|
userAuthorizationGP.POST("/refresh-token", userHandler.RefreshToken)
|
|
userAuthorizationGP.POST("/reset-password", userHandler.ResetPassword)
|
|
|
|
userProfileGP := profileGP.Group("")
|
|
userProfileGP.Use(userHandler.AuthMiddleware())
|
|
userProfileGP.GET("", userHandler.GetProfile)
|
|
userProfileGP.PUT("", userHandler.UpdateProfile)
|
|
userProfileGP.PUT("/change-password", userHandler.ChangePassword)
|
|
userProfileGP.DELETE("/logout", userHandler.Logout)
|
|
}
|
|
|
|
// Admin Companies Routes
|
|
companiesGP := adminV1.Group("/companies")
|
|
{
|
|
companiesGP.Use(userHandler.AuthMiddleware())
|
|
companiesGP.POST("", companyHandler.Create)
|
|
companiesGP.GET("", companyHandler.Search)
|
|
companiesGP.GET("/:id", companyHandler.Get)
|
|
companiesGP.PUT("/:id", companyHandler.Update)
|
|
companiesGP.DELETE("/:id", companyHandler.Delete)
|
|
companiesGP.PATCH("/:id/status", companyHandler.UpdateStatus)
|
|
companiesGP.PATCH("/:id/verification", companyHandler.UpdateVerification)
|
|
}
|
|
|
|
// Admin Categories Routes
|
|
categoriesGP := adminV1.Group("/company-categories")
|
|
{
|
|
categoriesGP.Use(userHandler.AuthMiddleware())
|
|
categoriesGP.POST("", categoryHandler.Create)
|
|
categoriesGP.GET("", categoryHandler.Search)
|
|
categoriesGP.GET("/:id", categoryHandler.Get)
|
|
categoriesGP.PUT("/:id", categoryHandler.Update)
|
|
categoriesGP.DELETE("/:id", categoryHandler.Delete)
|
|
categoriesGP.PATCH("/:id/publish", categoryHandler.TogglePublish)
|
|
}
|
|
|
|
// Admin Customers Routes
|
|
customersGP := adminV1.Group("/customers")
|
|
{
|
|
customersGP.Use(userHandler.AuthMiddleware())
|
|
customersGP.POST("", customerHandler.CreateCustomer)
|
|
customersGP.GET("", customerHandler.Search)
|
|
customersGP.GET("/:id", customerHandler.GetCustomerByID)
|
|
customersGP.PUT("/:id", customerHandler.UpdateCustomer)
|
|
customersGP.DELETE("/:id", customerHandler.DeleteCustomer)
|
|
customersGP.PUT("/:id/status", customerHandler.UpdateStatus)
|
|
customersGP.POST("/:id/reset-password", customerHandler.ResetCustomerPassword)
|
|
customersGP.PATCH("/:id/role", customerHandler.AssignRole)
|
|
customersGP.PATCH("/:id/companies", customerHandler.AssignCompanies)
|
|
}
|
|
|
|
// Admin Tenders Routes
|
|
tendersGP := adminV1.Group("/tenders")
|
|
{
|
|
tendersGP.Use(userHandler.AuthMiddleware())
|
|
tendersGP.GET("", tenderHandler.Search)
|
|
tendersGP.GET("/ai-summaries", tenderHandler.GetAllAISummaries)
|
|
tendersGP.GET("/scraped-documents", tenderHandler.ListTendersWithScrapedDocuments)
|
|
tendersGP.GET("/:id", tenderHandler.Get)
|
|
tendersGP.PUT("/:id", tenderHandler.Update)
|
|
tendersGP.DELETE("/:id", tenderHandler.Delete)
|
|
tendersGP.GET("/:id/documents", tenderHandler.GetDocuments)
|
|
tendersGP.GET("/:id/documents/download", tenderHandler.DownloadDocuments)
|
|
tendersGP.GET("/:id/ai-summary", tenderHandler.GetAISummary)
|
|
tendersGP.POST("/:id/ai-summarize", tenderHandler.TriggerAISummarize)
|
|
tendersGP.POST("/:id/ai-translate", tenderHandler.TriggerAITranslate)
|
|
}
|
|
|
|
// Admin Feedback Routes
|
|
feedbackGP := adminV1.Group("/feedback")
|
|
{
|
|
feedbackGP.Use(userHandler.AuthMiddleware())
|
|
feedbackGP.GET("", feedbackHandler.Search)
|
|
feedbackGP.GET("/:id", feedbackHandler.Get)
|
|
feedbackGP.DELETE("/:id", feedbackHandler.Delete)
|
|
}
|
|
|
|
// Admin Tender-Approvals Routes
|
|
tenderApprovalGP := adminV1.Group("/tender-approvals")
|
|
{
|
|
tenderApprovalGP.Use(userHandler.AuthMiddleware())
|
|
tenderApprovalGP.GET("", tenderApprovalHandler.ListTenderApprovals)
|
|
tenderApprovalGP.GET("/:id", tenderApprovalHandler.GetTenderApproval)
|
|
tenderApprovalGP.GET("/stats", tenderApprovalHandler.GetTenderApprovalStats)
|
|
tenderApprovalGP.GET("/submission-mode/:submission_mode", tenderApprovalHandler.GetTenderApprovalsBySubmissionMode)
|
|
tenderApprovalGP.GET("/status/:status", tenderApprovalHandler.GetTenderApprovalsByStatus)
|
|
}
|
|
|
|
// Admin Inquiry Routes
|
|
inquiryGP := adminV1.Group("/inquiries")
|
|
{
|
|
inquiryGP.Use(userHandler.AuthMiddleware())
|
|
inquiryGP.GET("", inquiryHandler.SearchInquiries)
|
|
inquiryGP.GET("/:id", inquiryHandler.GetInquiryByID)
|
|
inquiryGP.PUT("/:id/status", inquiryHandler.UpdateInquiryStatus)
|
|
inquiryGP.DELETE("/:id", inquiryHandler.DeleteInquiry)
|
|
}
|
|
|
|
// Admin Flags Routes
|
|
flagsGP := adminV1.Group("/flags")
|
|
{
|
|
flagsGP.GET("/:country_code", flagHandler.AdminGetFlagSVG)
|
|
}
|
|
|
|
// Admin Notifications Routes
|
|
notificationsGP := adminV1.Group("/notifications")
|
|
{
|
|
notificationsGP.Use(userHandler.AuthMiddleware())
|
|
notificationsGP.POST("", notificationHandler.Send)
|
|
notificationsGP.GET("", notificationHandler.GetNotifications)
|
|
notificationsGP.GET("/view/:id", notificationHandler.ViewNotification)
|
|
notificationsGP.GET("/mark-seen/:id", notificationHandler.MarkSeen)
|
|
notificationsGP.GET("/my", notificationHandler.AdminNotifications)
|
|
}
|
|
|
|
// Admin Contact Routes
|
|
contactsGP := adminV1.Group("/contacts")
|
|
{
|
|
contactsGP.Use(userHandler.AuthMiddleware())
|
|
contactsGP.GET("", contactHandler.Search)
|
|
contactsGP.GET("/stats", contactHandler.GetStats)
|
|
contactsGP.GET("/:id", contactHandler.GetByID)
|
|
contactsGP.PUT("/:id/status", contactHandler.UpdateStatus)
|
|
contactsGP.DELETE("/:id", contactHandler.Delete)
|
|
}
|
|
|
|
// Admin CMS Routes
|
|
cmsGP := adminV1.Group("/cms")
|
|
{
|
|
cmsGP.Use(userHandler.AuthMiddleware())
|
|
cmsGP.POST("", cmsHandler.Create)
|
|
cmsGP.GET("", cmsHandler.Search)
|
|
cmsGP.GET("/:id", cmsHandler.GetByID)
|
|
cmsGP.PUT("/:id", cmsHandler.Update)
|
|
cmsGP.DELETE("/:id", cmsHandler.Delete)
|
|
}
|
|
|
|
// Kanban Routes
|
|
kanbanGP := adminV1.Group("/kanban")
|
|
{
|
|
kanbanGP.Use(userHandler.AuthMiddleware())
|
|
kanbanHandler.RegisterRoutes(kanbanGP)
|
|
}
|
|
|
|
// File Store Routes
|
|
filesGP := adminV1.Group("/files")
|
|
{
|
|
filesGP.Use(userHandler.AuthMiddleware())
|
|
filesGP.POST("/upload", fileStoreHandler.Upload)
|
|
filesGP.GET("", fileStoreHandler.ListFiles)
|
|
filesGP.GET("/:file_id/info", fileStoreHandler.GetInfo)
|
|
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, xssPolicy *security.XSSPolicy) {
|
|
v1 := e.Group("/api/v1")
|
|
|
|
customerGP := v1.Group("/profile")
|
|
{
|
|
customerGP.POST("/login", customerHandler.Login)
|
|
customerGP.POST("/refresh-token", customerHandler.RefreshToken)
|
|
|
|
// Forgot password routes
|
|
customerGP.POST("/forgot-password", customerHandler.RequestResetPassword)
|
|
customerGP.POST("/verify-otp", customerHandler.VerifyOTP)
|
|
customerGP.POST("/reset-password", customerHandler.ResetPassword)
|
|
|
|
profileGP := customerGP.Group("")
|
|
profileGP.Use(customerHandler.AuthMiddleware())
|
|
profileGP.GET("", customerHandler.GetProfile)
|
|
profileGP.PUT("/keywords", customerHandler.UpdateProfileKeywords)
|
|
profileGP.DELETE("/logout", customerHandler.Logout)
|
|
}
|
|
|
|
// Public Tenders Routes
|
|
tendersGP := v1.Group("/tenders")
|
|
tendersGP.Use(customerHandler.AuthMiddleware())
|
|
{
|
|
tendersGP.GET("", tenderHandler.GetPublicTenders)
|
|
tendersGP.GET("/recommend", tenderHandler.RecommendTenders)
|
|
tendersGP.GET("/details/:id", tenderHandler.GetPublicTenderDetails)
|
|
tendersGP.GET("/:id/documents", tenderHandler.GetDocuments)
|
|
tendersGP.GET("/:id/documents/download", tenderHandler.DownloadDocuments)
|
|
tendersGP.GET("/:id/document-summaries", tenderHandler.GetDocumentSummaries)
|
|
tendersGP.GET("/:id/ai-summary", tenderHandler.GetPublicAISummary)
|
|
tendersGP.POST("/:id/ai-translate", tenderHandler.TriggerPublicAITranslate)
|
|
}
|
|
|
|
// Public Feedback Routes
|
|
feedbackGP := v1.Group("/feedback")
|
|
{
|
|
feedbackGP.Use(customerHandler.AuthMiddleware())
|
|
feedbackGP.POST("", feedbackHandler.Toggle)
|
|
feedbackGP.GET("", feedbackHandler.PublicList)
|
|
feedbackGP.GET("/tender/:tender_id", feedbackHandler.PublicGetByTenderID)
|
|
feedbackGP.GET("/:id", feedbackHandler.PublicGet)
|
|
feedbackGP.GET("/stats/company", feedbackHandler.GetCompanyStats)
|
|
}
|
|
|
|
// Public Tender Approvals Routes
|
|
tenderApprovalGP := v1.Group("/tender-approvals")
|
|
{
|
|
tenderApprovalGP.Use(customerHandler.AuthMiddleware())
|
|
tenderApprovalGP.POST("", tenderApprovalHandler.ToggleTenderApproval)
|
|
tenderApprovalGP.GET("", tenderApprovalHandler.PublicGetTenderApprovals)
|
|
tenderApprovalGP.GET("/:id", tenderApprovalHandler.GetPublicTenderApproval)
|
|
tenderApprovalGP.GET("/tender/:tender_id", tenderApprovalHandler.GetTenderApprovalByTenderAndCompany)
|
|
tenderApprovalGP.GET("/stats", tenderApprovalHandler.GetCompanyTenderApprovalStats)
|
|
}
|
|
|
|
// Public Company Routes
|
|
companiesGP := v1.Group("/companies")
|
|
{
|
|
companiesGP.Use(customerHandler.AuthMiddleware())
|
|
companiesGP.GET("", companyHandler.MyCompany)
|
|
}
|
|
|
|
// Public Inquiry Routes
|
|
inquiryGP := v1.Group("/inquiries")
|
|
{
|
|
inquiryGP.POST("", inquiryHandler.CreateInquiry)
|
|
}
|
|
|
|
// Public Flags Routes
|
|
flagsGP := v1.Group("/flags")
|
|
{
|
|
flagsGP.GET("/:country_code", flagHandler.GetFlagSVG)
|
|
}
|
|
|
|
// Public Notifications Routes
|
|
notificationsGP := v1.Group("/notifications")
|
|
{
|
|
notificationsGP.Use(customerHandler.AuthMiddleware())
|
|
notificationsGP.GET("", notificationHandler.CustomerNotifications)
|
|
notificationsGP.GET("/view/:id", notificationHandler.PublicViewNotification)
|
|
notificationsGP.GET("/mark", notificationHandler.PublicAllMarkSeen)
|
|
notificationsGP.GET("/mark/:id", notificationHandler.PublicMarkSeen)
|
|
}
|
|
|
|
// Public Contact Routes
|
|
contactsPublicGP := v1.Group("/contacts")
|
|
{
|
|
contactsPublicGP.POST("", contactHandler.Create)
|
|
}
|
|
|
|
// Public CMS Routes
|
|
cmsGP := v1.Group("/cms")
|
|
{
|
|
cmsGP.GET("/:key", cmsHandler.GetByKey)
|
|
}
|
|
|
|
// File Store Routes
|
|
publicFilesGP := v1.Group("/files")
|
|
{
|
|
publicFilesGP.Use(customerHandler.AuthMiddleware())
|
|
publicFilesGP.POST("/upload", fileStoreHandler.Upload)
|
|
publicFilesGP.GET("", fileStoreHandler.ListFiles)
|
|
publicFilesGP.GET("/:file_id/info", fileStoreHandler.GetInfo)
|
|
publicFilesGP.GET("/:file_id/download", fileStoreHandler.Download)
|
|
publicFilesGP.DELETE("/:file_id", fileStoreHandler.Delete)
|
|
}
|
|
}
|
|
|
|
func RegisterDocumentScraperRoutes(e *echo.Echo, docScraperHandler *document_scraper.Handler, apiKey string) {
|
|
v1 := e.Group("/api/v1/scraper")
|
|
|
|
// Apply API key middleware to all document scraper routes
|
|
v1.Use(document_scraper.APIKeyMiddleware(apiKey))
|
|
|
|
// Document Scraper Routes
|
|
{
|
|
v1.GET("/tenders", docScraperHandler.ListPendingTenders)
|
|
v1.GET("/tenders/:notice_id", docScraperHandler.GetTenderByNoticeID)
|
|
}
|
|
}
|