Files
GoMFT/internal/web/handlers/api_handlers.go
T
StarFleetCPTN 46df27e8c6 feat: Add rclone config regeneration after API updates
- Implemented logic to regenerate the rclone config file after updating configurations in the database.
- Added logging to capture warnings if the regeneration fails, while ensuring the update process continues smoothly.
- Enhanced user feedback by logging successful regeneration of the rclone config.
2025-04-07 19:02:02 -07:00

310 lines
9.3 KiB
Go

package handlers
import (
"fmt"
"log"
"net/http"
"github.com/gin-gonic/gin"
"github.com/starfleetcptn/gomft/internal/db"
"golang.org/x/crypto/bcrypt"
)
// HandleAPILogin handles the POST /api/login route
func (h *Handlers) HandleAPILogin(c *gin.Context) {
var loginData struct {
Email string `json:"email"`
Password string `json:"password"`
}
if err := c.ShouldBindJSON(&loginData); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid request data"})
return
}
// Get user by email
var user db.User
if err := h.DB.Where("email = ?", loginData.Email).First(&user).Error; err != nil {
c.JSON(http.StatusUnauthorized, gin.H{"error": "Invalid credentials"})
return
}
// Check password
if err := bcrypt.CompareHashAndPassword([]byte(user.PasswordHash), []byte(loginData.Password)); err != nil {
c.JSON(http.StatusUnauthorized, gin.H{"error": "Invalid credentials"})
return
}
// Generate JWT token
token, err := h.GenerateJWT(user.ID, user.Email, user.GetIsAdmin())
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to generate token"})
return
}
c.JSON(http.StatusOK, gin.H{
"token": token,
"user": gin.H{
"id": user.ID,
"email": user.Email,
"is_admin": user.IsAdmin,
},
})
}
// HandleAPIConfigs handles the GET /api/configs route
func (h *Handlers) HandleAPIConfigs(c *gin.Context) {
userID := c.GetUint("userID")
var configs []db.TransferConfig
h.DB.Where("created_by = ?", userID).Find(&configs)
c.JSON(http.StatusOK, gin.H{"configs": configs})
}
// HandleAPIConfig handles the GET /api/configs/:id route
func (h *Handlers) HandleAPIConfig(c *gin.Context) {
id := c.Param("id")
userID := c.GetUint("userID")
var config db.TransferConfig
if err := h.DB.First(&config, id).Error; err != nil {
c.JSON(http.StatusNotFound, gin.H{"error": "Config not found"})
return
}
// Check if user owns this config
if config.CreatedBy != userID {
// Check if user is admin
isAdmin, exists := c.Get("isAdmin")
if !exists || isAdmin != true {
c.JSON(http.StatusForbidden, gin.H{"error": "You do not have permission to view this config"})
return
}
}
c.JSON(http.StatusOK, gin.H{"config": config})
}
// HandleAPICreateConfig handles the POST /api/configs route
func (h *Handlers) HandleAPICreateConfig(c *gin.Context) {
var config db.TransferConfig
if err := c.ShouldBindJSON(&config); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": fmt.Sprintf("Invalid request data: %v", err)})
return
}
userID := c.GetUint("userID")
config.CreatedBy = userID
if err := h.DB.Create(&config).Error; err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": fmt.Sprintf("Failed to create config: %v", err)})
return
}
c.JSON(http.StatusCreated, gin.H{"config": config})
}
// HandleAPIUpdateConfig handles the PUT /api/configs/:id route
func (h *Handlers) HandleAPIUpdateConfig(c *gin.Context) {
id := c.Param("id")
userID := c.GetUint("userID")
var config db.TransferConfig
if err := h.DB.First(&config, id).Error; err != nil {
c.JSON(http.StatusNotFound, gin.H{"error": "Config not found"})
return
}
// Check if user owns this config
if config.CreatedBy != userID {
// Check if user is admin
isAdmin, exists := c.Get("isAdmin")
if !exists || isAdmin != true {
c.JSON(http.StatusForbidden, gin.H{"error": "You do not have permission to update this config"})
return
}
}
// Get the old config values for comparison
oldConfig := config
// Bind JSON data to config
if err := c.ShouldBindJSON(&config); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": fmt.Sprintf("Invalid request data: %v", err)})
return
}
// Preserve fields that shouldn't be updated
config.CreatedBy = oldConfig.CreatedBy
if err := h.DB.Save(&config).Error; err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": fmt.Sprintf("Failed to update config: %v", err)})
return
}
// Regenerate the rclone config file
if err := h.DB.GenerateRcloneConfig(&config); err != nil {
log.Printf("Warning: Failed to regenerate rclone config after API update: %v", err)
// Continue anyway, as the config was updated in the database
}
c.JSON(http.StatusOK, gin.H{"config": config})
}
// HandleAPIDeleteConfig handles the DELETE /api/configs/:id route
func (h *Handlers) HandleAPIDeleteConfig(c *gin.Context) {
id := c.Param("id")
userID := c.GetUint("userID")
var config db.TransferConfig
if err := h.DB.First(&config, id).Error; err != nil {
c.JSON(http.StatusNotFound, gin.H{"error": "Config not found"})
return
}
// Check if user owns this config
if config.CreatedBy != userID {
// Check if user is admin
isAdmin, exists := c.Get("isAdmin")
if !exists || isAdmin != true {
c.JSON(http.StatusForbidden, gin.H{"error": "You do not have permission to delete this config"})
return
}
}
// Check if config is in use by any jobs
var jobCount int64
h.DB.Model(&db.Job{}).Where("config_id = ?", config.ID).Count(&jobCount)
if jobCount > 0 {
c.JSON(http.StatusBadRequest, gin.H{"error": "Config is in use by jobs and cannot be deleted"})
return
}
// Delete config
if err := h.DB.Delete(&config).Error; err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": fmt.Sprintf("Failed to delete config: %v", err)})
return
}
c.JSON(http.StatusOK, gin.H{"message": "Config deleted successfully"})
}
// HandleAPIJobs handles the API jobs request
func (h *Handlers) HandleAPIJobs(c *gin.Context) {
// Implementation will be moved from the old handlers.go
c.JSON(http.StatusOK, gin.H{"message": "API jobs handler stub"})
}
// HandleAPIJob handles the API job request
func (h *Handlers) HandleAPIJob(c *gin.Context) {
// Implementation will be moved from the old handlers.go
c.JSON(http.StatusOK, gin.H{"message": "API job handler stub"})
}
// HandleAPICreateJob handles the API create job request
func (h *Handlers) HandleAPICreateJob(c *gin.Context) {
// Implementation will be moved from the old handlers.go
c.JSON(http.StatusOK, gin.H{"message": "API create job handler stub"})
}
// HandleAPIUpdateJob handles the API update job request
func (h *Handlers) HandleAPIUpdateJob(c *gin.Context) {
// Implementation will be moved from the old handlers.go
c.JSON(http.StatusOK, gin.H{"message": "API update job handler stub"})
}
// HandleAPIDeleteJob handles the API delete job request
func (h *Handlers) HandleAPIDeleteJob(c *gin.Context) {
// Implementation will be moved from the old handlers.go
c.JSON(http.StatusOK, gin.H{"message": "API delete job handler stub"})
}
// HandleAPIRunJob handles the API run job request
func (h *Handlers) HandleAPIRunJob(c *gin.Context) {
id := c.Param("id")
userID := c.GetUint("userID")
var job db.Job
if err := h.DB.First(&job, id).Error; err != nil {
c.JSON(http.StatusNotFound, gin.H{"error": "Job not found"})
return
}
// Check if user owns this job
if job.CreatedBy != userID {
// Check if user is admin
isAdmin, exists := c.Get("isAdmin")
if !exists || isAdmin != true {
c.JSON(http.StatusForbidden, gin.H{"error": "You do not have permission to run this job"})
return
}
}
// Determine job name for response
jobName := job.Name
if jobName == "" {
// If job name is empty, try to get config name
var config db.TransferConfig
if err := h.DB.First(&config, job.ConfigID).Error; err == nil {
jobName = config.Name
} else {
jobName = fmt.Sprintf("Job #%d", job.ID)
}
}
// Run the job immediately using the scheduler
if err := h.Scheduler.RunJobNow(job.ID); err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to run job: " + err.Error()})
return
}
c.JSON(http.StatusOK, gin.H{
"message": "Job started successfully",
"jobId": job.ID,
"jobName": jobName,
})
}
// HandleAPIHistory handles the API history request
func (h *Handlers) HandleAPIHistory(c *gin.Context) {
// Implementation will be moved from the old handlers.go
c.JSON(http.StatusOK, gin.H{"message": "API history handler stub"})
}
// HandleAPIJobRun handles the API job run request
func (h *Handlers) HandleAPIJobRun(c *gin.Context) {
// Implementation will be moved from the old handlers.go
c.JSON(http.StatusOK, gin.H{"message": "API job run handler stub"})
}
// HandleAPIUsers handles the API users request
func (h *Handlers) HandleAPIUsers(c *gin.Context) {
// Implementation will be moved from the old handlers.go
c.JSON(http.StatusOK, gin.H{"message": "API users handler stub"})
}
// HandleAPIUser handles the API user request
func (h *Handlers) HandleAPIUser(c *gin.Context) {
// Implementation will be moved from the old handlers.go
c.JSON(http.StatusOK, gin.H{"message": "API user handler stub"})
}
// HandleAPICreateUser handles the API create user request
func (h *Handlers) HandleAPICreateUser(c *gin.Context) {
// Implementation will be moved from the old handlers.go
c.JSON(http.StatusOK, gin.H{"message": "API create user handler stub"})
}
// HandleAPIUpdateUser handles the API update user request
func (h *Handlers) HandleAPIUpdateUser(c *gin.Context) {
// Implementation will be moved from the old handlers.go
c.JSON(http.StatusOK, gin.H{"message": "API update user handler stub"})
}
// HandleAPIDeleteUser handles the API delete user request
func (h *Handlers) HandleAPIDeleteUser(c *gin.Context) {
// Implementation will be moved from the old handlers.go
c.JSON(http.StatusOK, gin.H{"message": "API delete user handler stub"})
}