diff --git a/go.mod b/go.mod
index c6f625b4..5a5a68c8 100644
--- a/go.mod
+++ b/go.mod
@@ -52,7 +52,7 @@ require (
github.com/rs/cors v1.11.0
github.com/rs/xid v1.5.0
github.com/rs/zerolog v1.32.0
- github.com/sftpgo/sdk v0.1.6-0.20240409173349-421b3dff3896
+ github.com/sftpgo/sdk v0.1.6-0.20240426175227-52f492b8b83b
github.com/shirou/gopsutil/v3 v3.24.3
github.com/spf13/afero v1.11.0
github.com/spf13/cobra v1.8.0
diff --git a/go.sum b/go.sum
index 89e84c8a..bf640401 100644
--- a/go.sum
+++ b/go.sum
@@ -351,8 +351,8 @@ github.com/secsy/goftp v0.0.0-20200609142545-aa2de14babf4 h1:PT+ElG/UUFMfqy5HrxJ
github.com/secsy/goftp v0.0.0-20200609142545-aa2de14babf4/go.mod h1:MnkX001NG75g3p8bhFycnyIjeQoOjGL6CEIsdE/nKSY=
github.com/segmentio/asm v1.2.0 h1:9BQrFxC+YOHJlTlHGkTrFWf59nbL3XnCoFLTwDCI7ys=
github.com/segmentio/asm v1.2.0/go.mod h1:BqMnlJP91P8d+4ibuonYZw9mfnzI9HfxselHZr5aAcs=
-github.com/sftpgo/sdk v0.1.6-0.20240409173349-421b3dff3896 h1:ykxybS9WKurHTatKJ9WjqYD+WH9YH/2QMxCkxUPTVLY=
-github.com/sftpgo/sdk v0.1.6-0.20240409173349-421b3dff3896/go.mod h1:AWoY2YYe/P1ymfTlRER/meERQjCcZZTbgVPGcPQgaqc=
+github.com/sftpgo/sdk v0.1.6-0.20240426175227-52f492b8b83b h1:BazWPub9GBUKvfM2O6MHhAwd9JbPD1i3UudhmHfGc2w=
+github.com/sftpgo/sdk v0.1.6-0.20240426175227-52f492b8b83b/go.mod h1:AWoY2YYe/P1ymfTlRER/meERQjCcZZTbgVPGcPQgaqc=
github.com/shirou/gopsutil/v3 v3.24.3 h1:eoUGJSmdfLzJ3mxIhmOAhgKEKgQkeOwKpz1NbhVnuPE=
github.com/shirou/gopsutil/v3 v3.24.3/go.mod h1:JpND7O217xa72ewWz9zN2eIIkPWsDN/3pl0H8Qt0uwg=
github.com/shoenig/go-m1cpu v0.1.6 h1:nxdKQNcEB6vzgA2E2bvzKIYRuNj7XNJ4S/aRSwKzFtM=
diff --git a/internal/cmd/portable.go b/internal/cmd/portable.go
index 4cf274b8..c9c32487 100644
--- a/internal/cmd/portable.go
+++ b/internal/cmd/portable.go
@@ -112,7 +112,7 @@ $ sftpgo portable
Please take a look at the usage below to customize the serving parameters`,
Run: func(_ *cobra.Command, _ []string) {
portableDir := directoryToServe
- fsProvider := sdk.GetProviderByName(portableFsProvider)
+ fsProvider := dataprovider.GetProviderFromValue(convertFsProvider())
if !filepath.IsAbs(portableDir) {
if fsProvider == sdk.LocalFilesystemProvider {
portableDir, _ = filepath.Abs(portableDir)
@@ -227,7 +227,7 @@ Please take a look at the usage below to customize the serving parameters`,
},
},
FsConfig: vfs.Filesystem{
- Provider: sdk.GetProviderByName(portableFsProvider),
+ Provider: fsProvider,
S3Config: vfs.S3FsConfig{
BaseS3FsConfig: sdk.BaseS3FsConfig{
Bucket: portableS3Bucket,
@@ -282,8 +282,9 @@ Please take a look at the usage below to customize the serving parameters`,
DisableCouncurrentReads: portableSFTPDisableConcurrentReads,
BufferSize: portableSFTPDBufferSize,
},
- Password: kms.NewPlainSecret(portableSFTPPassword),
- PrivateKey: kms.NewPlainSecret(portableSFTPPrivateKey),
+ Password: kms.NewPlainSecret(portableSFTPPassword),
+ PrivateKey: kms.NewPlainSecret(portableSFTPPrivateKey),
+ KeyPassphrase: kms.NewEmptySecret(),
},
},
},
@@ -524,3 +525,22 @@ func getFileContents(name string) (string, error) {
}
return string(contents), nil
}
+
+func convertFsProvider() string {
+ switch portableFsProvider {
+ case "osfs", "6": // httpfs (6) is not supported in portable mode, so return the default
+ return "0"
+ case "s3fs":
+ return "1"
+ case "gcsfs":
+ return "2"
+ case "azblobfs":
+ return "3"
+ case "cryptfs":
+ return "4"
+ case "sftpfs":
+ return "5"
+ default:
+ return portableFsProvider
+ }
+}
diff --git a/internal/dataprovider/dataprovider.go b/internal/dataprovider/dataprovider.go
index d0f29fd1..8252b0de 100644
--- a/internal/dataprovider/dataprovider.go
+++ b/internal/dataprovider/dataprovider.go
@@ -319,32 +319,6 @@ type PasswordValidation struct {
Users PasswordValidationRules `json:"users" mapstructure:"users"`
}
-// FilesystemProvider defines the supported storage filesystems
-type FilesystemProvider struct {
- sdk.FilesystemProvider
-}
-
-// I18nString returns the translation key
-func (p FilesystemProvider) I18nString() string {
- switch p.FilesystemProvider {
- case sdk.LocalFilesystemProvider:
- return util.I18nStorageLocal
- case sdk.S3FilesystemProvider:
- return util.I18nStorageS3
- case sdk.GCSFilesystemProvider:
- return util.I18nStorageGCS
- case sdk.AzureBlobFilesystemProvider:
- return util.I18nStorageAzureBlob
- case sdk.CryptedFilesystemProvider:
- return util.I18nStorageLocalEncrypted
- case sdk.SFTPFilesystemProvider:
- return util.I18nStorageSFTP
- case sdk.HTTPFilesystemProvider:
- return util.I18nStorageHTTP
- }
- return ""
-}
-
type wrappedFolder struct {
Folder vfs.BaseVirtualFolder
}
@@ -1014,6 +988,20 @@ func GetBackupsPath() string {
return config.BackupsPath
}
+// GetProviderFromValue returns the FilesystemProvider matching the specified value.
+// If no match is found LocalFilesystemProvider is returned.
+func GetProviderFromValue(value string) sdk.FilesystemProvider {
+ val, err := strconv.Atoi(value)
+ if err != nil {
+ return sdk.LocalFilesystemProvider
+ }
+ result := sdk.FilesystemProvider(val)
+ if sdk.IsProviderSupported(result) {
+ return result
+ }
+ return sdk.LocalFilesystemProvider
+}
+
func initializeHashingAlgo(cnf *Config) error {
parallelism := cnf.PasswordHashing.Argon2Options.Parallelism
if parallelism == 0 {
diff --git a/internal/httpd/webadmin.go b/internal/httpd/webadmin.go
index 76a0e6f8..98f6851d 100644
--- a/internal/httpd/webadmin.go
+++ b/internal/httpd/webadmin.go
@@ -509,17 +509,6 @@ func loadAdminTemplates(templatesPath string) {
}
fsBaseTpl := template.New("fsBaseTemplate").Funcs(template.FuncMap{
- "ListFSProviders": func() []dataprovider.FilesystemProvider {
- return []dataprovider.FilesystemProvider{
- {FilesystemProvider: sdk.LocalFilesystemProvider},
- {FilesystemProvider: sdk.CryptedFilesystemProvider},
- {FilesystemProvider: sdk.S3FilesystemProvider},
- {FilesystemProvider: sdk.GCSFilesystemProvider},
- {FilesystemProvider: sdk.AzureBlobFilesystemProvider},
- {FilesystemProvider: sdk.SFTPFilesystemProvider},
- {FilesystemProvider: sdk.HTTPFilesystemProvider},
- }
- },
"HumanizeBytes": util.ByteCountSI,
})
usersTmpl := util.LoadTemplate(nil, usersPaths...)
@@ -1694,7 +1683,7 @@ func getOsConfigFromPostFields(r *http.Request, readBufferField, writeBufferFiel
func getFsConfigFromPostFields(r *http.Request) (vfs.Filesystem, error) {
var fs vfs.Filesystem
- fs.Provider = sdk.GetProviderByName(r.Form.Get("fs_provider"))
+ fs.Provider = dataprovider.GetProviderFromValue(r.Form.Get("fs_provider"))
switch fs.Provider {
case sdk.LocalFilesystemProvider:
fs.OSConfig = getOsConfigFromPostFields(r, "osfs_read_buffer_size", "osfs_write_buffer_size")
diff --git a/internal/util/i18n.go b/internal/util/i18n.go
index c15f6b84..0c578794 100644
--- a/internal/util/i18n.go
+++ b/internal/util/i18n.go
@@ -183,13 +183,6 @@ const (
I18nOIDCTokenInvalidRoleAdmin = "oidc.role_admin_err"
I18nOIDCTokenInvalidRoleUser = "oidc.role_user_err"
I18nOIDCErrGetUser = "oidc.get_user_err"
- I18nStorageLocal = "storage.local"
- I18nStorageLocalEncrypted = "storage.encrypted"
- I18nStorageS3 = "storage.s3"
- I18nStorageGCS = "storage.gcs"
- I18nStorageAzureBlob = "storage.azblob"
- I18nStorageSFTP = "storage.sftp"
- I18nStorageHTTP = "storage.http"
I18nErrorInvalidQuotaSize = "user.invalid_quota_size"
I18nErrorTimeOfDayInvalid = "user.time_of_day_invalid"
I18nErrorTimeOfDayConflict = "user.time_of_day_conflict"
diff --git a/internal/util/resources.go b/internal/util/resources.go
index 876fa8c1..9d1a360c 100644
--- a/internal/util/resources.go
+++ b/internal/util/resources.go
@@ -58,25 +58,29 @@ func FindSharedDataPath(name, searchDir string) string {
// LoadTemplate parses the given template paths.
// It behaves like template.Must but it writes a log before exiting.
-// You can optionally provide a base template (e.g. to define some custom functions)
func LoadTemplate(base *template.Template, paths ...string) *template.Template {
- var t *template.Template
- var err error
-
if base != nil {
- base, err = base.Clone()
- if err == nil {
- t, err = base.ParseFiles(paths...)
+ baseTmpl, err := base.Clone()
+ if err != nil {
+ showTemplateLoadingError(err)
}
- } else {
- t, err = template.ParseFiles(paths...)
+ t, err := baseTmpl.ParseFiles(paths...)
+ if err != nil {
+ showTemplateLoadingError(err)
+ }
+ return t
}
+ t, err := template.ParseFiles(paths...)
if err != nil {
- logger.ErrorToConsole("error loading required template: %v", err)
- logger.ErrorToConsole(templateLoadErrorHints)
- logger.Error(logSender, "", "error loading required template: %v", err)
- os.Exit(1)
+ showTemplateLoadingError(err)
}
return t
}
+
+func showTemplateLoadingError(err error) {
+ logger.ErrorToConsole("error loading required template: %v", err)
+ logger.ErrorToConsole(templateLoadErrorHints)
+ logger.Error(logSender, "", "error loading required template: %v", err)
+ os.Exit(1)
+}
diff --git a/templates/common/base.html b/templates/common/base.html
index 0016eec4..75e88fb0 100644
--- a/templates/common/base.html
+++ b/templates/common/base.html
@@ -278,6 +278,38 @@ explicit grant from the SFTPGo Team (support@sftpgo.com).
return window.location.protocol+"//"+window.location.hostname;
}
+ function onFilesystemChanged(val){
+ const supportedFs = ["local", "s3", "gcs", "azblob", "crypt", "sftp", "http"];
+ let fsName = "local";
+ switch (val){
+ case '1':
+ fsName = "s3";
+ break;
+ case '2':
+ fsName = "gcs";
+ break;
+ case '3':
+ fsName = "azblob";
+ break;
+ case '4':
+ fsName = "crypt";
+ break;
+ case '5':
+ fsName = "sftp";
+ break;
+ case '6':
+ fsName = "http";
+ break;
+ }
+ for (let i = 0; i < supportedFs.length; i++){
+ if (supportedFs[i] == fsName){
+ $('.form-group.fsconfig-'+fsName).show();
+ } else {
+ $('.form-group.fsconfig-'+supportedFs[i]).hide();
+ }
+ }
+ }
+
KTUtil.onDOMContentLoaded(function () {
var dismissErrorBtn = $('#id_dismiss_error_msg');
if (dismissErrorBtn){
diff --git a/templates/webadmin/folder.html b/templates/webadmin/folder.html
index 8991baed..f8b69dd2 100644
--- a/templates/webadmin/folder.html
+++ b/templates/webadmin/folder.html
@@ -137,13 +137,9 @@ explicit grant from the SFTPGo Team (support@sftpgo.com).
{{- define "extra_js"}}