diff --git a/README.md b/README.md index 0a65571..e7a30a8 100644 --- a/README.md +++ b/README.md @@ -1,35 +1,38 @@ -# GoMFT - Go Managed File Transfer +

+ GoMFT Logo +

+ +

GoMFT - Go Managed File Transfer

GoMFT is a web-based managed file transfer application built with Go, leveraging rclone for robust file transfer capabilities. It provides a user-friendly interface for configuring, scheduling, and monitoring file transfers across various storage providers. +
+

+ + + + WARNING: GoMFT is in active development and configuration may change often. Please make sure to carefully read the release notes before updating. +

+
+ ## Screenshots -### Dashboard -![Dashboard Overview](screenshots/dashboard.gomft.png) -*Dashboard showing active transfers and system status* - -![Dashboard Overview Dark](screenshots/dashboard.dark.gomft.png) -*Dashboard dark mode showing active transfers and system status* - -### Configuration Interface -![Transfer Configuration](screenshots/new.configuration.gomft.png) -*Setting up transfer configurations with multiple storage options* - -### Job Management -![Job Scheduling](screenshots/new.job.gomft.png) -*Scheduling transfers with flexible cron expressions* - -### File Metadata -![File Metadata](screenshots/file.metadata.gomft.png) -*Track and manage file metadata with detailed information about transferred files* - -### User Management -![User Management](screenshots/user.management.gomft.png) -*Create user accounts and manage them* - -### Admin Tools -![Admin Tools](screenshots/admin.tools.gomft.png) -*Admin dashboard with log viewer and system management tools* + + + + + +
+ + Dashboard Overview + +

Dashboard showing active transfers

+
+ + Dashboard Dark Mode + +

Dashboard dark mode

+
## Features @@ -345,8 +348,8 @@ User management features: ### Transfer Configuration Options 1. **Source/Destination Types**: - - Google Drive (with built-in or custom authentication) - - Google Photos (with built-in or custom authentication) + - Google Drive + - Google Photos - Local filesystem - Amazon S3 - MinIO (S3-compatible storage) @@ -562,10 +565,6 @@ air 4. Push to the branch 5. Create a Pull Request -## License - -MIT License - see LICENSE file for details - ## Directory Structure GoMFT uses the following directory structure: @@ -585,3 +584,14 @@ volumes: ``` These paths can be customized using the environment variables `DATA_DIR`, `BACKUP_DIR`, and `LOGS_DIR`. + + +## License + +[MIT License](LICENSE) - see the full license terms + +The GoMFT logo is licensed under the Creative Commons Attribution 4.0 International Public License. + +The gopher design is from https://github.com/egonelbre/gophers. + +The original Go gopher was designed by Renee French (http://reneefrench.blogspot.com/). diff --git a/components/config_form.templ b/components/config_form.templ index 6bb6ddc..710bc92 100644 --- a/components/config_form.templ +++ b/components/config_form.templ @@ -84,7 +84,8 @@ func getInitialData(config *db.TransferConfig) string { skipProcessedFiles := true maxConcurrentTransfers := 4 rcloneFlags := "" - useBuiltinAuth := true + useBuiltinAuthSource := true + useBuiltinAuthDest := true // If editing an existing config, populate with those values if config != nil { @@ -162,14 +163,19 @@ func getInitialData(config *db.TransferConfig) string { skipProcessedFiles = config.GetSkipProcessedFiles() maxConcurrentTransfers = config.MaxConcurrentTransfers rcloneFlags = config.RcloneFlags - if config.UseBuiltinAuth != nil { - useBuiltinAuth = *config.UseBuiltinAuth + if config.UseBuiltinAuthSource != nil { + useBuiltinAuthSource = *config.UseBuiltinAuthSource + } else if sourceClientId != "" || sourceClientSecret != "" { + useBuiltinAuthSource = false + } + if config.UseBuiltinAuthDest != nil { + useBuiltinAuthDest = *config.UseBuiltinAuthDest } else if destClientId != "" || destClientSecret != "" { - useBuiltinAuth = false + useBuiltinAuthDest = false } } - // Return the JSON-formatted string with all the data + // Return the JSON-formatted string with all the data, add new path validation states return fmt.Sprintf(`{ name: '%s', sourceType: '%s', @@ -223,7 +229,8 @@ func getInitialData(config *db.TransferConfig) string { destStartYear: %d, destIncludeArchived: %v, - useBuiltinAuth: %v, + useBuiltinAuthSource: %v, + useBuiltinAuthDest: %v, archivePath: '%s', archiveEnabled: %v, @@ -231,6 +238,32 @@ func getInitialData(config *db.TransferConfig) string { skipProcessedFiles: %v, maxConcurrentTransfers: %d, rcloneFlags: '%s', + + // Path validation states + sourcePathValid: null, + sourcePathError: '', + destPathValid: null, + destPathError: '', + + // Methods for path validation + checkPath(path, type) { + if (!path) { + this[type + 'PathValid'] = false; + this[type + 'PathError'] = 'Path cannot be empty'; + return; + } + + fetch('/check-path?path=' + encodeURIComponent(path)) + .then(response => response.json()) + .then(data => { + this[type + 'PathValid'] = data.valid; + this[type + 'PathError'] = data.error || ''; + }) + .catch(error => { + this[type + 'PathValid'] = false; + this[type + 'PathError'] = 'Error checking path: ' + error.message; + }); + } }`, name, sourceType, sourcePath, sourceHost, sourcePort, sourceUser, sourcePassword, sourceKeyFile, sourceAuthType, sourceBucket, sourceRegion, sourceAccessKey, sourceSecretKey, sourceEndpoint, sourceShare, sourceDomain, sourcePassiveMode, @@ -241,24 +274,24 @@ func getInitialData(config *db.TransferConfig) string { destBucket, destRegion, destAccessKey, destSecretKey, destEndpoint, destShare, destDomain, destPassiveMode, destClientId, destClientSecret, destDriveId, destTeamDrive, destReadOnly, destStartYear, destIncludeArchived, - useBuiltinAuth, + useBuiltinAuthSource, useBuiltinAuthDest, archivePath, archiveEnabled, deleteAfterTransfer, skipProcessedFiles, maxConcurrentTransfers, rcloneFlags) } templ ConfigForm(ctx context.Context, data ConfigFormData) { @LayoutWithContext(getConfigFormTitle(data.IsNew), ctx) { -
-
+
+
-
- +
+
-

+

{ getConfigFormTitle(data.IsNew) }

-

+

Set up your file transfer configuration

@@ -321,7 +354,7 @@ templ ConfigForm(ctx context.Context, data ConfigFormData) { @source.NextCloudSourceForm() -