mirror of
https://github.com/StarFleetCPTN/GoMFT.git
synced 2026-11-03 10:37:28 +01:00
feat: Add connection testing functionality for Rclone providers
- Introduced a new endpoint to test connections for source and destination providers. - Implemented a TestResult component to display success or error messages based on connection outcomes. - Enhanced the configuration form with buttons to initiate connection tests, improving user experience. - Updated backend logic to handle connection testing and return appropriate feedback to the frontend. - Refactored existing handlers and routes to accommodate the new testing functionality.
This commit is contained in:
1 parent
f95720758e
commit
68dd9fc173
7 files changed
+452
-4
No files matched your search
@@ -11,7 +11,9 @@ import (
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/starfleetcptn/gomft/components"
|
||||
|
||||
"github.com/starfleetcptn/gomft/internal/db"
|
||||
"github.com/starfleetcptn/gomft/internal/rclone_service" // Assuming we create this package
|
||||
)
|
||||
|
||||
// HandleConfigs handles the GET /configs route
|
||||
@@ -686,3 +688,89 @@ func (h *Handlers) HandleDuplicateConfig(c *gin.Context) {
|
||||
c.Header("HX-Refresh", "true")
|
||||
c.JSON(http.StatusOK, gin.H{"message": "Config duplicated successfully"})
|
||||
}
|
||||
|
||||
// HandleTestProviderConnection handles the POST /configs/test-connection route
|
||||
func (h *Handlers) HandleTestProviderConnection(c *gin.Context) {
|
||||
var config db.TransferConfig
|
||||
providerType := c.PostForm("providerType") // "source" or "destination"
|
||||
|
||||
// Bind all form data into a temporary config struct
|
||||
// We don't save this, just use it to gather the necessary fields
|
||||
if err := c.ShouldBind(&config); err != nil {
|
||||
log.Printf("Error binding test connection form: %v", err)
|
||||
// Render error using the TestResult component
|
||||
components.TestResult(false, fmt.Sprintf("Invalid form data: %v", err)).Render(c, c.Writer)
|
||||
return
|
||||
}
|
||||
|
||||
// Process boolean fields manually as ShouldBind might not handle 'on' correctly for pointers
|
||||
if providerType == "source" {
|
||||
sourcePassiveModeVal := c.Request.FormValue("source_passive_mode")
|
||||
sourcePassiveModeValue := sourcePassiveModeVal == "on" || sourcePassiveModeVal == "true"
|
||||
config.SourcePassiveMode = &sourcePassiveModeValue
|
||||
|
||||
sourceReadOnlyVal := c.Request.FormValue("source_read_only")
|
||||
sourceReadOnlyValue := sourceReadOnlyVal == "on" || sourceReadOnlyVal == "true"
|
||||
config.SourceReadOnly = &sourceReadOnlyValue
|
||||
|
||||
sourceIncludeArchivedVal := c.Request.FormValue("source_include_archived")
|
||||
sourceIncludeArchivedValue := sourceIncludeArchivedVal == "on" || sourceIncludeArchivedVal == "true"
|
||||
config.SourceIncludeArchived = &sourceIncludeArchivedValue
|
||||
|
||||
useBuiltinAuthSourceVal := c.Request.FormValue("use_builtin_auth_source")
|
||||
useBuiltinAuthSourceValue := useBuiltinAuthSourceVal == "on" || useBuiltinAuthSourceVal == "true"
|
||||
config.UseBuiltinAuthSource = &useBuiltinAuthSourceValue
|
||||
} else if providerType == "destination" {
|
||||
destPassiveModeVal := c.Request.FormValue("dest_passive_mode")
|
||||
destPassiveModeValue := destPassiveModeVal == "on" || destPassiveModeVal == "true"
|
||||
config.DestPassiveMode = &destPassiveModeValue
|
||||
|
||||
destReadOnlyVal := c.Request.FormValue("dest_read_only")
|
||||
destReadOnlyValue := destReadOnlyVal == "on" || destReadOnlyVal == "true"
|
||||
config.DestReadOnly = &destReadOnlyValue
|
||||
|
||||
destIncludeArchivedVal := c.Request.FormValue("dest_include_archived")
|
||||
destIncludeArchivedValue := destIncludeArchivedVal == "on" || destIncludeArchivedVal == "true"
|
||||
config.DestIncludeArchived = &destIncludeArchivedValue
|
||||
|
||||
useBuiltinAuthDestVal := c.Request.FormValue("use_builtin_auth_dest")
|
||||
useBuiltinAuthDestValue := useBuiltinAuthDestVal == "on" || useBuiltinAuthDestVal == "true"
|
||||
config.UseBuiltinAuthDest = &useBuiltinAuthDestValue
|
||||
}
|
||||
|
||||
// Call the rclone test function (to be implemented)
|
||||
success, message, err := rclone_service.TestRcloneConnection(config, providerType, h.DB) // Pass DB if needed for built-in auth
|
||||
toastType := "info" // Default type
|
||||
if err != nil {
|
||||
log.Printf("Error testing rclone connection: %v. Message: %s", err, message) // Log both err and message
|
||||
toastType = "error"
|
||||
// Use the message from TestRcloneConnection for the toast
|
||||
} else if success {
|
||||
toastType = "success"
|
||||
} else {
|
||||
// If no error but not success, treat as error/warning
|
||||
toastType = "error"
|
||||
}
|
||||
|
||||
// Prepare data for HX-Trigger
|
||||
toastData := map[string]interface{}{
|
||||
"showToast": map[string]string{
|
||||
"message": message,
|
||||
"type": toastType,
|
||||
},
|
||||
}
|
||||
|
||||
// Marshal data to JSON for the header
|
||||
jsonData, err := json.Marshal(toastData)
|
||||
if err != nil {
|
||||
// Log the error, but maybe still try to send a basic trigger? Or just fail?
|
||||
log.Printf("Error marshaling toast data for HX-Trigger: %v", err)
|
||||
// Fallback or error handling - for now, just proceed without trigger maybe?
|
||||
c.Status(http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
// Trigger toast notification on the frontend via HX-Trigger header
|
||||
c.Header("HX-Trigger", string(jsonData))
|
||||
c.Status(http.StatusOK) // Return 200 OK, but with no body swap intended
|
||||
}
|
||||
@@ -57,6 +57,7 @@ func (h *Handlers) RegisterRoutes(router *gin.Engine) {
|
||||
authorized.POST("/configs/:id", h.HandleUpdateConfig)
|
||||
authorized.DELETE("/configs/:id", h.HandleDeleteConfig)
|
||||
authorized.POST("/configs/:id/duplicate", h.HandleDuplicateConfig)
|
||||
authorized.POST("/configs/test-connection", h.HandleTestProviderConnection)
|
||||
|
||||
// Path validation endpoint
|
||||
authorized.GET("/check-path", h.HandleCheckPath)
|
||||
|
||||
Reference in new issue
Block a user