2025-12-20 00:01:08 +07:00

295 lines
12 KiB
Go

package routes
import (
"lost-and-found/internal/controllers"
"lost-and-found/internal/middleware"
"github.com/gin-gonic/gin"
"go.uber.org/zap"
"gorm.io/gorm"
)
// SetupRoutes configures all application routes
func SetupRoutes(router *gin.Engine, db *gorm.DB, logger *zap.Logger) {
// Initialize controllers
authController := controllers.NewAuthController(db, logger)
userController := controllers.NewUserController(db)
itemController := controllers.NewItemController(db)
lostItemController := controllers.NewLostItemController(db)
claimController := controllers.NewClaimController(db)
matchController := controllers.NewMatchController(db)
categoryController := controllers.NewCategoryController(db)
archiveController := controllers.NewArchiveController(db)
adminController := controllers.NewAdminController(db)
reportController := controllers.NewReportController(db)
uploadController := controllers.NewUploadController(db)
managerController := controllers.NewManagerController(db)
roleController := controllers.NewRoleController(db)
notificationController := controllers.NewNotificationController(db)
aiController := controllers.NewAIController(db)
// API group
api := router.Group("/api")
{
// ==========================================
// 1. Public Routes (No Auth)
// ==========================================
api.POST("/register", authController.Register)
api.POST("/login", authController.Login)
api.POST("/refresh-token", authController.RefreshToken)
api.GET("/categories", categoryController.GetAllCategories)
api.GET("/categories/:id", categoryController.GetCategoryByID)
// Optional Auth for Items (Public can view, Manager sees details)
itemsGroup := api.Group("/items")
itemsGroup.Use(middleware.OptionalJWTMiddleware(db))
{
itemsGroup.GET("", itemController.GetAllItems)
itemsGroup.GET("/:id", itemController.GetItemByID)
}
// ==========================================
// 2. Authenticated Routes (Basic User Access)
// ==========================================
// Middleware: Cek Token Valid & User Active
authenticated := api.Group("")
authenticated.Use(middleware.JWTMiddleware(db))
{
authenticated.POST("/ai/chat", aiController.Chat)
authenticated.GET("/ai/history", aiController.GetHistory)
authenticated.DELETE("/ai/history", aiController.ClearHistory)
// Profile (Siapapun yang login bisa akses ini)
authenticated.GET("/me", authController.GetMe)
authenticated.GET("/user/profile", userController.GetProfile)
authenticated.PUT("/user/profile", userController.UpdateProfile)
authenticated.POST("/user/change-password", userController.ChangePassword)
authenticated.GET("/user/stats", userController.GetStats)
authenticated.POST("/lost-items/:id/direct-claim", lostItemController.DirectClaimToOwner)
authenticated.POST("/user/lost-items/:id/direct-claim", lostItemController.DirectClaimToOwner)
authenticated.POST("/claims/:id/respond", claimController.UserApproveClaim)
authenticated.POST("/claims/:id/complete", claimController.UserConfirmCompletion)
// --- User Features (Permission: item:create) ---
authenticated.POST("/items",
middleware.RequirePermission("item:create"),
itemController.CreateItem)
authenticated.GET("/user/items",
middleware.RequirePermission("item:read"),
itemController.GetItemsByReporter)
// --- Lost Items (Permission: item:create) ---
// Asumsi: Hak akses lapor kehilangan sama dengan lapor temuan
authenticated.POST("/lost-items",
middleware.RequirePermission("item:create"),
lostItemController.CreateLostItem)
authenticated.GET("/user/lost-items", lostItemController.GetLostItemsByUser)
authenticated.GET("/lost-items", lostItemController.GetAllLostItems)
authenticated.GET("/lost-items/:id", lostItemController.GetLostItemByID)
authenticated.PUT("/lost-items/:id", lostItemController.UpdateLostItem)
authenticated.PATCH("/lost-items/:id/status", lostItemController.UpdateLostItemStatus)
// ✅ FIX: Delete Lost Item menggunakan controller yang benar
authenticated.DELETE("/lost-items/:id",
middleware.RequirePermission("lost_item:delete"), // Permission baru
lostItemController.DeleteLostItem)
// --- Claims (Permission: claim:create) ---
authenticated.POST("/claims",
middleware.RequirePermission("claim:create"),
middleware.IdempotencyMiddleware(), // Prevent double submit
claimController.CreateClaim)
authenticated.GET("/user/claims",
middleware.RequirePermission("claim:read"),
claimController.GetClaimsByUser)
// ✅ FIX: Tambahkan endpoint update dan delete claim user
authenticated.PUT("/claims/:id",
middleware.RequirePermission("claim:create"), // User boleh edit claim sendiri
claimController.UpdateClaim)
authenticated.DELETE("/claims/:id",
middleware.RequirePermission("claim:create"), // User boleh delete claim sendiri
claimController.DeleteClaim)
// --- Matching ---
authenticated.GET("/lost-items/:id/matches", matchController.GetMatchesForLostItem)
authenticated.POST("/lost-items/:id/find-similar", matchController.FindSimilarItems)
// --- Notifications ---
authenticated.GET("/notifications", notificationController.GetUserNotifications)
authenticated.PATCH("/notifications/:id/read", notificationController.MarkAsRead)
authenticated.PATCH("/notifications/read-all", notificationController.MarkAllAsRead)
authenticated.POST("/user/claims/:id/respond", claimController.UserApproveClaim)
authenticated.POST("/user/claims/:id/complete", claimController.UserConfirmCompletion)
// --- Uploads ---
upload := authenticated.Group("/upload")
{
upload.POST("/item-image", uploadController.UploadItemImage)
upload.POST("/claim-proof", uploadController.UploadClaimProof)
upload.POST("/multiple", uploadController.UploadMultipleImages)
upload.DELETE("/delete", uploadController.DeleteImage)
upload.GET("/info", uploadController.GetImageInfo)
}
}
// ==========================================
// 3. Protected Management Routes (Permission Based)
// ==========================================
// Area ini menggantikan Group Manager/Admin yang lama.
// Sekarang dikelompokkan berdasarkan FITUR, bukan ROLE.
management := api.Group("")
management.Use(middleware.JWTMiddleware(db))
{
// --- ITEM MANAGEMENT (Permission: item:update, item:delete) ---
management.PUT("/items/:id",
middleware.RequirePermission("item:update"),
itemController.UpdateItem)
management.PATCH("/items/:id/status",
middleware.RequirePermission("item:update"),
itemController.UpdateItemStatus)
management.DELETE("/items/:id",
middleware.RequirePermission("item:delete"),
itemController.DeleteItem)
management.GET("/items/:id/revisions",
middleware.RequirePermission("item:verify"),
itemController.GetItemRevisionHistory)
management.GET("/items/:id/matches",
middleware.RequirePermission("item:verify"),
matchController.GetMatchesForItem)
// --- CLAIM VERIFICATION (Permission: claim:approve, claim:reject) ---
management.GET("/claims",
middleware.RequirePermission("claim:read"), // Manager view all claims
claimController.GetAllClaims)
management.GET("/claims/:id",
middleware.RequirePermission("claim:read"),
claimController.GetClaimByID)
management.POST("/claims/:id/verify",
middleware.RequirePermission("claim:approve"),
middleware.IdempotencyMiddleware(),
claimController.VerifyClaim)
management.GET("/claims/:id/verification",
middleware.RequirePermission("claim:read"),
claimController.GetClaimVerification)
// ✅ FIX: Ganti endpoint CloseClaim -> CloseCase
management.POST("/claims/:id/close",
middleware.RequirePermission("claim:approve"),
claimController.CloseCase)
// ✅ FIX: Ganti endpoint ReopenClaim -> ReopenCase
management.POST("/claims/:id/reopen",
middleware.RequirePermission("claim:approve"),
claimController.ReopenCase)
// ✅ FIX: Ganti endpoint CancelApproval -> CancelClaimApproval
management.POST("/claims/:id/cancel-approval",
middleware.RequirePermission("claim:approve"),
claimController.CancelClaimApproval)
// --- ARCHIVES (Permission: item:read - for historical data) ---
management.GET("/archives",
middleware.RequirePermission("item:read"),
archiveController.GetAllArchives)
management.GET("/archives/:id",
middleware.RequirePermission("item:read"),
archiveController.GetArchiveByID)
management.GET("/archives/stats",
middleware.RequirePermission("item:read"),
archiveController.GetArchiveStats)
// --- REPORTS (Permission: report:export) ---
management.POST("/reports/export",
middleware.RequirePermission("report:export"),
reportController.ExportReport)
// --- DASHBOARD (Permission: user:read - as proxy for dashboard access) ---
management.GET("/manager/dashboard",
middleware.RequirePermission("item:verify"),
managerController.GetDashboardStats)
management.GET("/admin/dashboard",
middleware.RequirePermission("user:read"),
adminController.GetDashboardStats)
// --- USER MANAGEMENT (Permission: user:read, user:update, user:block) ---
// Biasa dilakukan oleh Admin
management.GET("/admin/users",
middleware.RequirePermission("user:read"),
userController.GetAllUsers)
management.GET("/admin/users/:id",
middleware.RequirePermission("user:read"),
userController.GetUserByID)
management.PATCH("/admin/users/:id/role",
middleware.RequirePermission("user:update"),
userController.UpdateUserRole)
management.POST("/admin/users/:id/block",
middleware.RequirePermission("user:block"),
userController.BlockUser)
management.POST("/admin/users/:id/unblock",
middleware.RequirePermission("user:block"),
userController.UnblockUser)
management.DELETE("/admin/users/:id",
middleware.RequirePermission("user:block"), // Menggunakan permission block untuk delete
userController.DeleteUser)
// --- AUDIT LOGS (Permission: user:read - biasanya Admin) ---
management.GET("/admin/audit-logs",
middleware.RequirePermission("user:read"),
adminController.GetAuditLogs)
// --- CATEGORY MANAGEMENT (Permission: item:update - Admin Only usually) ---
// Note: Anda mungkin perlu menambahkan permission 'category:create' di seed.sql
// Untuk sekarang kita gunakan 'item:update' atau 'user:update' sebagai proxy
management.POST("/categories",
middleware.RequirePermission("user:update"),
categoryController.CreateCategory)
management.PUT("/categories/:id",
middleware.RequirePermission("user:update"),
categoryController.UpdateCategory)
management.DELETE("/categories/:id",
middleware.RequirePermission("user:update"),
categoryController.DeleteCategory)
// ✅ Endpoint baru untuk test Procedure SQL
management.POST("/admin/archive/trigger",
middleware.RequireRole("admin"), // Hanya admin
adminController.TriggerAutoArchive)
management.GET("/admin/dashboard/fast",
middleware.RequireRole("admin", "manager"),
adminController.GetFastDashboardStats)
management.GET("/admin/roles", middleware.RequireRole("admin"), roleController.GetRoles)
management.GET("/admin/permissions", middleware.RequireRole("admin"), roleController.GetPermissions)
management.POST("/admin/roles", middleware.RequireRole("admin"), roleController.CreateRole)
management.PUT("/admin/roles/:id", middleware.RequireRole("admin"), roleController.UpdateRole)
management.DELETE("/admin/roles/:id", middleware.RequireRole("admin"), roleController.DeleteRole)
}
}
}