From 69da5c10c62e8597a72aefbab9e68eec32203a91 Mon Sep 17 00:00:00 2001 From: Nicola Murino Date: Sat, 27 Jan 2024 12:48:15 +0100 Subject: [PATCH] WIP new WebAdmin: configs page Signed-off-by: Nicola Murino --- go.mod | 4 +- go.sum | 8 +- internal/acme/acme.go | 5 +- internal/dataprovider/configs.go | 38 +- internal/httpd/api_configs.go | 2 + internal/httpd/httpd_test.go | 17 +- internal/httpd/webadmin.go | 19 +- internal/sftpd/internal_test.go | 2 - internal/sftpd/server.go | 1 - internal/util/i18n.go | 5 + static/locales/en/translation.json | 47 +- static/locales/it/translation.json | 49 +- templates/webadmin/admin.html | 2 +- templates/webadmin/configs.html | 905 ++++++++++++++--------------- templates/webadmin/profile.html | 2 +- templates/webadmin/user.html | 2 +- templates/webclient/profile.html | 2 +- 17 files changed, 600 insertions(+), 510 deletions(-) diff --git a/go.mod b/go.mod index c02a0fd8..eec31b29 100644 --- a/go.mod +++ b/go.mod @@ -38,7 +38,7 @@ require ( github.com/hashicorp/go-retryablehttp v0.7.5 github.com/jackc/pgx/v5 v5.5.2 github.com/jlaffaye/ftp v0.0.0-20201112195030-9aae4d151126 - github.com/klauspost/compress v1.17.4 + github.com/klauspost/compress v1.17.5 github.com/lestrrat-go/jwx/v2 v2.0.19 github.com/lithammer/shortuuid/v3 v3.0.7 github.com/mattn/go-sqlite3 v1.14.20 @@ -74,7 +74,7 @@ require ( golang.org/x/sys v0.16.0 golang.org/x/term v0.16.0 golang.org/x/time v0.5.0 - google.golang.org/api v0.158.0 + google.golang.org/api v0.159.0 gopkg.in/natefinch/lumberjack.v2 v2.2.1 ) diff --git a/go.sum b/go.sum index 39e1e735..fe5ff2e5 100644 --- a/go.sum +++ b/go.sum @@ -245,8 +245,8 @@ github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9Y github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8= github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U= -github.com/klauspost/compress v1.17.4 h1:Ej5ixsIri7BrIjBkRZLTo6ghwrEtHFk7ijlczPW4fZ4= -github.com/klauspost/compress v1.17.4/go.mod h1:/dCuZOvVtNoHsyb+cuJD3itjs3NbnF6KH9zAO4BDxPM= +github.com/klauspost/compress v1.17.5 h1:d4vBd+7CHydUqpFBgUEKkSdtSugf9YFmSkvUYPquI5E= +github.com/klauspost/compress v1.17.5/go.mod h1:/dCuZOvVtNoHsyb+cuJD3itjs3NbnF6KH9zAO4BDxPM= github.com/kr/fs v0.1.0 h1:Jskdu9ieNAYnjxsi0LbQp1ulIKZV1LAFgK1tWhpZgl8= github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= @@ -522,8 +522,8 @@ golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 h1:+cNy6SZtPcJQH3LJVLOSmiC7MMxXNOb3PU/VUEz+EhU= golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028/go.mod h1:NDW/Ps6MPRej6fsCIbMTohpP40sJ/P/vI1MoTEGwX90= -google.golang.org/api v0.158.0 h1:7SKwlRqzrXT2ULl6a3iESb+1pOak5IOd5F+ay5ULiV4= -google.golang.org/api v0.158.0/go.mod h1:0mu0TpK33qnydLvWqbImq2b1eQ5FHRSDCBzAxX9ZHyw= +google.golang.org/api v0.159.0 h1:fVTj+7HHiUYz4JEZCHHoRIeQX7h5FMzrA2RF/DzDdbs= +google.golang.org/api v0.159.0/go.mod h1:0mu0TpK33qnydLvWqbImq2b1eQ5FHRSDCBzAxX9ZHyw= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.6.8 h1:IhEN5q69dyKagZPYMSdIjS2HqprW324FRQZJcGqPAsM= diff --git a/internal/acme/acme.go b/internal/acme/acme.go index 71f45717..315e2b43 100644 --- a/internal/acme/acme.go +++ b/internal/acme/acme.go @@ -241,7 +241,10 @@ func (c *Configuration) Initialize(configDir string) error { return nil } if c.Email == "" || !util.IsEmailValid(c.Email) { - return fmt.Errorf("invalid email address %q", c.Email) + return util.NewI18nError( + fmt.Errorf("invalid email address %q", c.Email), + util.I18nErrorInvalidEmail, + ) } if c.RenewDays < 1 { return fmt.Errorf("invalid number of days remaining before renewal: %d", c.RenewDays) diff --git a/internal/dataprovider/configs.go b/internal/dataprovider/configs.go index 949ba83f..85f57083 100644 --- a/internal/dataprovider/configs.go +++ b/internal/dataprovider/configs.go @@ -17,7 +17,6 @@ package dataprovider import ( "encoding/json" "fmt" - "strings" "golang.org/x/crypto/ssh" @@ -48,7 +47,6 @@ var ( type SFTPDConfigs struct { HostKeyAlgos []string `json:"host_key_algos,omitempty"` PublicKeyAlgos []string `json:"public_key_algos,omitempty"` - Moduli []string `json:"moduli,omitempty"` KexAlgorithms []string `json:"kex_algorithms,omitempty"` Ciphers []string `json:"ciphers,omitempty"` MACs []string `json:"macs,omitempty"` @@ -61,9 +59,6 @@ func (c *SFTPDConfigs) isEmpty() bool { if len(c.PublicKeyAlgos) > 0 { return false } - if len(c.Moduli) > 0 { - return false - } if len(c.KexAlgorithms) > 0 { return false } @@ -101,11 +96,6 @@ func (*SFTPDConfigs) GetSupportedMACs() []string { return supportedMACs } -// GetModuliAsString returns moduli files as comma separated string -func (c *SFTPDConfigs) GetModuliAsString() string { - return strings.Join(c.Moduli, ",") -} - func (c *SFTPDConfigs) validate() error { var hostKeyAlgos []string for _, algo := range c.HostKeyAlgos { @@ -152,8 +142,6 @@ func (c *SFTPDConfigs) getACopy() *SFTPDConfigs { copy(hostKeys, c.HostKeyAlgos) publicKeys := make([]string, len(c.PublicKeyAlgos)) copy(publicKeys, c.PublicKeyAlgos) - moduli := make([]string, len(c.Moduli)) - copy(moduli, c.Moduli) kexs := make([]string, len(c.KexAlgorithms)) copy(kexs, c.KexAlgorithms) ciphers := make([]string, len(c.Ciphers)) @@ -164,7 +152,6 @@ func (c *SFTPDConfigs) getACopy() *SFTPDConfigs { return &SFTPDConfigs{ HostKeyAlgos: hostKeys, PublicKeyAlgos: publicKeys, - Moduli: moduli, KexAlgorithms: kexs, Ciphers: ciphers, MACs: macs, @@ -204,13 +191,22 @@ func (c *SMTPOAuth2) validate() error { return util.NewValidationError("smtp oauth2: unsupported provider") } if c.ClientID == "" { - return util.NewValidationError("smtp oauth2: client id is required") + return util.NewI18nError( + util.NewValidationError("smtp oauth2: client id is required"), + util.I18nErrorSMTPClientIDRequired, + ) } if c.ClientSecret == nil { - return util.NewValidationError("smtp oauth2: client secret is required") + return util.NewI18nError( + util.NewValidationError("smtp oauth2: client secret is required"), + util.I18nErrorSMTPClientSecretRequired, + ) } if c.RefreshToken == nil { - return util.NewValidationError("smtp oauth2: refresh token is required") + return util.NewI18nError( + util.NewValidationError("smtp oauth2: refresh token is required"), + util.I18nErrorSMTPRefreshTokenRequired, + ) } if err := validateSMTPSecret(c.ClientSecret, "oauth2 client secret"); err != nil { return err @@ -267,7 +263,10 @@ func (c *SMTPConfigs) validate() error { } } if c.User == "" && c.From == "" { - return util.NewValidationError("smtp: from address and user cannot both be empty") + return util.NewI18nError( + util.NewValidationError("smtp: from address and user cannot both be empty"), + util.I18nErrorSMTPRequiredFields, + ) } if c.AuthType < 0 || c.AuthType > 3 { return util.NewValidationError(fmt.Sprintf("smtp: invalid auth type %d", c.AuthType)) @@ -354,7 +353,10 @@ func (c *ACMEConfigs) validate() error { return nil } if c.Email == "" && !util.IsEmailValid(c.Email) { - return util.NewValidationError(fmt.Sprintf("acme: invalid email %q", c.Email)) + return util.NewI18nError( + util.NewValidationError(fmt.Sprintf("acme: invalid email %q", c.Email)), + util.I18nErrorInvalidEmail, + ) } if c.HTTP01Challenge.Port <= 0 || c.HTTP01Challenge.Port > 65535 { return util.NewValidationError(fmt.Sprintf("acme: invalid HTTP-01 challenge port %d", c.HTTP01Challenge.Port)) diff --git a/internal/httpd/api_configs.go b/internal/httpd/api_configs.go index 70bdb3f2..399c7ad2 100644 --- a/internal/httpd/api_configs.go +++ b/internal/httpd/api_configs.go @@ -23,6 +23,7 @@ import ( "github.com/drakkan/sftpgo/v2/internal/dataprovider" "github.com/drakkan/sftpgo/v2/internal/kms" + "github.com/drakkan/sftpgo/v2/internal/logger" "github.com/drakkan/sftpgo/v2/internal/smtp" "github.com/drakkan/sftpgo/v2/internal/util" ) @@ -72,6 +73,7 @@ func testSMTPConfig(w http.ResponseWriter, r *http.Request) { } if err := req.SendEmail([]string{req.Recipient}, nil, "SFTPGo - Testing Email Settings", "It appears your SFTPGo email is setup correctly!", smtp.EmailContentTypeTextPlain); err != nil { + logger.Info(logSender, "", "unable to send test email: %v", err) sendAPIResponse(w, r, err, "", http.StatusInternalServerError) return } diff --git a/internal/httpd/httpd_test.go b/internal/httpd/httpd_test.go index ae14cd7a..633f0d3a 100644 --- a/internal/httpd/httpd_test.go +++ b/internal/httpd/httpd_test.go @@ -7925,7 +7925,6 @@ func TestLoaddata(t *testing.T) { assert.Equal(t, configs.SMTP, configsGet.SMTP) assert.Equal(t, []string{ssh.KeyAlgoRSA}, configsGet.SFTPD.HostKeyAlgos) assert.Equal(t, []string{ssh.KeyAlgoDSA}, configsGet.SFTPD.PublicKeyAlgos) - assert.Len(t, configsGet.SFTPD.Moduli, 0) assert.Len(t, configsGet.SFTPD.KexAlgorithms, 0) assert.Len(t, configsGet.SFTPD.Ciphers, 0) assert.Len(t, configsGet.SFTPD.MACs, 0) @@ -8087,7 +8086,7 @@ func TestLoaddataMode(t *testing.T) { folderName := filepath.Base(mappedPath) configs := dataprovider.Configs{ SFTPD: &dataprovider.SFTPDConfigs{ - Moduli: []string{"/moduli"}, + PublicKeyAlgos: []string{ssh.KeyAlgoRSA}, }, } role := getTestRole() @@ -8200,7 +8199,7 @@ func TestLoaddataMode(t *testing.T) { assert.NoError(t, err) configs, err = dataprovider.GetConfigs() assert.NoError(t, err) - assert.Len(t, configs.SFTPD.Moduli, 1) + assert.Len(t, configs.SFTPD.PublicKeyAlgos, 1) folder, _, err := httpdtest.GetFolderByName(folderName, http.StatusOK) assert.NoError(t, err) assert.Equal(t, mappedPath+"1", folder.MappedPath) @@ -8272,7 +8271,7 @@ func TestLoaddataMode(t *testing.T) { entry, _, err = httpdtest.UpdateIPListEntry(entry, http.StatusOK) assert.NoError(t, err) - configs.SFTPD.Moduli = append(configs.SFTPD.Moduli, "/moduli_new") + configs.SFTPD.PublicKeyAlgos = append(configs.SFTPD.PublicKeyAlgos, ssh.KeyAlgoDSA) err = dataprovider.UpdateConfigs(&configs, "", "", "") assert.NoError(t, err) backupData.Configs = &configs @@ -8286,7 +8285,7 @@ func TestLoaddataMode(t *testing.T) { assert.NoError(t, err) configs, err = dataprovider.GetConfigs() assert.NoError(t, err) - assert.Len(t, configs.SFTPD.Moduli, 2) + assert.Len(t, configs.SFTPD.PublicKeyAlgos, 2) group, _, err = httpdtest.GetGroupByName(group.Name, http.StatusOK) assert.NoError(t, err) assert.NotEqual(t, oldGroupDesc, group.Description) @@ -8346,7 +8345,7 @@ func TestLoaddataMode(t *testing.T) { assert.Equal(t, oldUploadBandwidth, user.UploadBandwidth) configs, err = dataprovider.GetConfigs() assert.NoError(t, err) - assert.Len(t, configs.SFTPD.Moduli, 1) + assert.Len(t, configs.SFTPD.PublicKeyAlgos, 1) // the group is referenced _, err = httpdtest.RemoveGroup(group, http.StatusBadRequest) assert.NoError(t, err) @@ -12772,7 +12771,6 @@ func TestWebConfigsMock(t *testing.T) { form.Set("sftp_host_key_algos", ssh.KeyAlgoRSA) form.Add("sftp_host_key_algos", ssh.CertAlgoDSAv01) form.Set("sftp_pub_key_algos", ssh.KeyAlgoDSA) - form.Set("sftp_moduli", "path 1 , path 2") form.Set("form_action", "sftp_submit") req, err = http.NewRequest(http.MethodPost, webConfigsPath, bytes.NewBuffer([]byte(form.Encode()))) assert.NoError(t, err) @@ -12800,9 +12798,6 @@ func TestWebConfigsMock(t *testing.T) { assert.Contains(t, configs.SFTPD.HostKeyAlgos, ssh.KeyAlgoRSA) assert.Len(t, configs.SFTPD.PublicKeyAlgos, 1) assert.Contains(t, configs.SFTPD.PublicKeyAlgos, ssh.KeyAlgoDSA) - assert.Len(t, configs.SFTPD.Moduli, 2) - assert.Contains(t, configs.SFTPD.Moduli, "path 1") - assert.Contains(t, configs.SFTPD.Moduli, "path 2") assert.Len(t, configs.SFTPD.KexAlgorithms, 1) assert.Contains(t, configs.SFTPD.KexAlgorithms, "diffie-hellman-group16-sha512") // invalid form action @@ -12850,7 +12845,6 @@ func TestWebConfigsMock(t *testing.T) { assert.Contains(t, configs.SFTPD.HostKeyAlgos, ssh.KeyAlgoRSA) assert.Len(t, configs.SFTPD.PublicKeyAlgos, 1) assert.Contains(t, configs.SFTPD.PublicKeyAlgos, ssh.KeyAlgoDSA) - assert.Len(t, configs.SFTPD.Moduli, 2) assert.Equal(t, "mail.example.net", configs.SMTP.Host) assert.Equal(t, 587, configs.SMTP.Port) assert.Equal(t, "Example ", configs.SMTP.From) @@ -12922,7 +12916,6 @@ func TestWebConfigsMock(t *testing.T) { assert.Contains(t, configs.SFTPD.HostKeyAlgos, ssh.KeyAlgoRSA) assert.Len(t, configs.SFTPD.PublicKeyAlgos, 1) assert.Contains(t, configs.SFTPD.PublicKeyAlgos, ssh.KeyAlgoDSA) - assert.Len(t, configs.SFTPD.Moduli, 2) assert.Equal(t, 80, configs.ACME.HTTP01Challenge.Port) assert.Equal(t, 7, configs.ACME.Protocols) assert.Empty(t, configs.ACME.Domain) diff --git a/internal/httpd/webadmin.go b/internal/httpd/webadmin.go index ec7176a5..96898060 100644 --- a/internal/httpd/webadmin.go +++ b/internal/httpd/webadmin.go @@ -101,7 +101,6 @@ const ( pageEventRulesTitle = "Event rules" pageEventActionsTitle = "Event actions" pageEventsTitle = "Logs" - pageConfigsTitle = "Configurations" defaultQueryLimit = 1000 inversePatternType = "inverse" ) @@ -339,7 +338,7 @@ type configsPage struct { RedactedSecret string OAuth2TokenURL string OAuth2RedirectURL string - Error string + Error *util.I18nError } type messagePage struct { @@ -515,7 +514,7 @@ func loadAdminTemplates(templatesPath string) { filepath.Join(templatesPath, templateAdminDir, templateEvents), } configsPaths := []string{ - filepath.Join(templatesPath, templateCommonDir, templateCommonCSS), + filepath.Join(templatesPath, templateCommonDir, templateCommonBase), filepath.Join(templatesPath, templateAdminDir, templateBase), filepath.Join(templatesPath, templateAdminDir, templateConfigs), } @@ -840,7 +839,7 @@ func (s *httpdServer) renderMaintenancePage(w http.ResponseWriter, r *http.Reque } func (s *httpdServer) renderConfigsPage(w http.ResponseWriter, r *http.Request, configs dataprovider.Configs, - error string, section int, + err error, section int, ) { configs.SetNilsToEmpty() if configs.SMTP.Port == 0 { @@ -852,13 +851,13 @@ func (s *httpdServer) renderConfigsPage(w http.ResponseWriter, r *http.Request, configs.ACME.HTTP01Challenge.Port = 80 } data := configsPage{ - basePage: s.getBasePageData(pageConfigsTitle, webConfigsPath, r), + basePage: s.getBasePageData(util.I18nConfigsTitle, webConfigsPath, r), Configs: configs, ConfigSection: section, RedactedSecret: redactedSecret, OAuth2TokenURL: webOAuth2TokenPath, OAuth2RedirectURL: webOAuth2RedirectPath, - Error: error, + Error: getI18nError(err), } renderAdminTemplate(w, templateConfigs, data) @@ -2564,7 +2563,6 @@ func getSFTPConfigsFromPostFields(r *http.Request) *dataprovider.SFTPDConfigs { return &dataprovider.SFTPDConfigs{ HostKeyAlgos: r.Form["sftp_host_key_algos"], PublicKeyAlgos: r.Form["sftp_pub_key_algos"], - Moduli: getSliceFromDelimitedValues(r.Form.Get("sftp_moduli"), ","), KexAlgorithms: r.Form["sftp_kex_algos"], Ciphers: r.Form["sftp_ciphers"], MACs: r.Form["sftp_macs"], @@ -4095,7 +4093,7 @@ func (s *httpdServer) handleWebConfigs(w http.ResponseWriter, r *http.Request) { s.renderInternalServerErrorPage(w, r, err) return } - s.renderConfigsPage(w, r, configs, "", 0) + s.renderConfigsPage(w, r, configs, nil, 0) } func (s *httpdServer) handleWebConfigsPost(w http.ResponseWriter, r *http.Request) { @@ -4131,7 +4129,8 @@ func (s *httpdServer) handleWebConfigsPost(w http.ResponseWriter, r *http.Reques acmeConfigs := getACMEConfigsFromPostFields(r) configs.ACME = acmeConfigs if err := acme.GetCertificatesForConfig(acmeConfigs, configurationDir); err != nil { - s.renderConfigsPage(w, r, configs, err.Error(), configSection) + logger.Info(logSender, "", "unable to get ACME certificates: %v", err) + s.renderConfigsPage(w, r, configs, util.NewI18nError(err, util.I18nErrorACMEGeneric), configSection) return } case "smtp_submit": @@ -4146,7 +4145,7 @@ func (s *httpdServer) handleWebConfigsPost(w http.ResponseWriter, r *http.Reques err = dataprovider.UpdateConfigs(&configs, claims.Username, ipAddr, claims.Role) if err != nil { - s.renderConfigsPage(w, r, configs, err.Error(), configSection) + s.renderConfigsPage(w, r, configs, err, configSection) return } if configSection == 3 { diff --git a/internal/sftpd/internal_test.go b/internal/sftpd/internal_test.go index fa93743f..71394be9 100644 --- a/internal/sftpd/internal_test.go +++ b/internal/sftpd/internal_test.go @@ -1834,7 +1834,6 @@ func TestConfigsFromProvider(t *testing.T) { configs := dataprovider.Configs{ SFTPD: &dataprovider.SFTPDConfigs{ HostKeyAlgos: []string{ssh.KeyAlgoRSA}, - Moduli: []string{"/etc/ssh/moduli"}, KexAlgorithms: []string{kexDHGroupExchangeSHA256}, Ciphers: []string{"aes128-cbc", "aes192-cbc", "aes256-cbc"}, MACs: []string{"hmac-sha2-512-etm@openssh.com"}, @@ -1854,7 +1853,6 @@ func TestConfigsFromProvider(t *testing.T) { assert.Equal(t, expectedKEXs, c.KexAlgorithms) assert.Equal(t, expectedCiphers, c.Ciphers) assert.Equal(t, expectedMACs, c.MACs) - assert.Equal(t, configs.SFTPD.Moduli, c.Moduli) assert.Equal(t, expectedPublicKeyAlgos, c.PublicKeyAlgorithms) err = dataprovider.UpdateConfigs(nil, "", "", "") diff --git a/internal/sftpd/server.go b/internal/sftpd/server.go index 007a496f..ca3bbf5b 100644 --- a/internal/sftpd/server.go +++ b/internal/sftpd/server.go @@ -340,7 +340,6 @@ func (c *Configuration) loadFromProvider() error { } c.PublicKeyAlgorithms = append(c.PublicKeyAlgorithms, configs.SFTPD.PublicKeyAlgos...) } - c.Moduli = append(c.Moduli, configs.SFTPD.Moduli...) if len(configs.SFTPD.KexAlgorithms) > 0 { if len(c.KexAlgorithms) == 0 { c.KexAlgorithms = preferredKexAlgos diff --git a/internal/util/i18n.go b/internal/util/i18n.go index cbe72a88..340973fd 100644 --- a/internal/util/i18n.go +++ b/internal/util/i18n.go @@ -232,6 +232,11 @@ const ( I18nFTPTLSMixed = "status.tls_mixed" I18nErrorBackupFile = "maintenance.backup_invalid_file" I18nErrorRestore = "maintenance.restore_error" + I18nErrorACMEGeneric = "acme.generic_error" + I18nErrorSMTPRequiredFields = "smtp.err_required_fields" + I18nErrorSMTPClientIDRequired = "smtp.client_id_required" + I18nErrorSMTPClientSecretRequired = "smtp.client_secret_required" + I18nErrorSMTPRefreshTokenRequired = "smtp.refresh_token_required" ) // NewI18nError returns a I18nError wrappring the provided error diff --git a/static/locales/en/translation.json b/static/locales/en/translation.json index 9a81a58c..5b4c273e 100644 --- a/static/locales/en/translation.json +++ b/static/locales/en/translation.json @@ -237,7 +237,11 @@ "issuer": "Issuer", "data_provider": "Database", "driver": "Driver", - "mode": "Mode" + "mode": "Mode", + "port": "Port", + "domain": "Domain", + "test": "Test", + "get": "Get" }, "fs": { "view_file": "View file \"{{- path}}\"", @@ -789,5 +793,46 @@ "quota_mode0": "No quota update", "quota_mode1": "Update quota", "quota_mode2": "Update quota for users with quota limits" + }, + "acme": { + "title": "ACME", + "generic_error": "Unable to obtain TLS certificates, check the server logs for more details", + "help": "From this section you can request free TLS certificates for your SFTPGo services using the ACME protocol and the HTTP-01 challenge type. You must create a DNS entry under a custom domain that you own which resolves to your SFTPGo public IP address and the port 80 must be publicly reachable. You can set the configuration options for the most common use cases and single node setups here, for advanced configurations refer to the SFTPGo docs. A service restart is required to apply changes", + "domain_help": "Multiple domains can be specified comma or space separated. They will be included in the same certificate", + "email_help": "Email used for registration and recovery contact", + "port_help": "If different from 80 you have to configure a reverse proxy", + "protocols_help": "Use the obtained certificates for the specified protocols" + }, + "smtp": { + "title": "SMTP", + "err_required_fields": "From address and Username cannot be both empty", + "client_id_required": "Client ID is required", + "client_secret_required": "Client Secret is required", + "refresh_token_required": "Refresh Token is required", + "help": "Set the SMTP configuration replacing the one defined using env vars or config file if any", + "host": "Server name", + "host_help": "If blank the configuration is disabled", + "auth": "Authentication", + "encryption": "Encryption", + "sender": "Sender", + "debug": "Debug logs", + "domain_help": "HELO domain. Leave blank to use the server hostname", + "test_recipient": "Address to send test emails to", + "oauth2_provider": "OAuth2 provider", + "oauth2_provider_help": "URI to redirect to after user authentication", + "oauth2_tenant": "OAuth2 Tenant", + "oauth2_tenant_help": "Azure tenant. Typical values are \"common\", \"organizations\", \"consumers\" or the tenant identifier", + "oauth2_client_id": "OAuth2 Client ID", + "oauth2_client_secret": "OAuth2 Client Secret", + "oauth2_token": "OAuth2 Token", + "recipient_required": "Specify a recipient to send a test email", + "test_error": "Unable to send test email, check server logs for more details", + "test_ok": "No errors were reported while sending the test email. Please check your inbox to make sure", + "oauth2_flow_error": "Unable to get the URI to start OAuth2 flow", + "oauth2_question": "Do you want to start the OAuth2 flow to get a token?" + }, + "sftp": { + "help": "From this section you can enable algorithms disabled by default. You don't need to set values already defined using env vars or config file. A service restart is required to apply changes", + "host_key_algos": "Host Key Algorithms" } } \ No newline at end of file diff --git a/static/locales/it/translation.json b/static/locales/it/translation.json index cd1a7062..f421cb77 100644 --- a/static/locales/it/translation.json +++ b/static/locales/it/translation.json @@ -54,7 +54,7 @@ "update_folder": "Aggiorna cartella virtuale", "template_folder": "Modello cartella virtuale", "oauth2_error": "Impossibile completare il flusso OAuth2", - "oauth2_success": "OAuth2 completato", + "oauth2_success": "Flusso OAuth2 completato", "add_role": "Aggiungi ruolo", "update_role": "Aggiorna ruolo", "add_admin": "Aggiungi amministratore", @@ -237,7 +237,11 @@ "issuer": "Emittente", "data_provider": "Database", "driver": "Driver", - "mode": "Modalità" + "mode": "Modalità", + "port": "Porta", + "domain": "Dominio", + "test": "Test", + "get": "Ottieni" }, "fs": { "view_file": "Visualizza file \"{{- path}}\"", @@ -789,5 +793,46 @@ "quota_mode0": "Non aggiornare quota", "quota_mode1": "Aggiorna quota", "quota_mode2": "Aggiorna quota per gli utenti con limiti di quota" + }, + "acme": { + "title": "ACME", + "generic_error": "Impossibile ottenere certificati TLS, controlla i log del server per maggiori dettagli", + "help": "Da questa sezione puoi richiedere certificati TLS gratuiti per i tuoi servizi SFTPGo utilizzando il protocollo ACME e la tipologia di challenge HTTP-01. Devi creare una voce DNS sotto un dominio personalizzato di tua proprietà che si risolve nel tuo indirizzo IP pubblico SFTPGo e la porta 80 deve essere raggiungibile pubblicamente. Qui è possibile impostare le opzioni di configurazione per i casi d'uso più comuni e le configurazioni a nodo singolo, per le configurazioni avanzate fare riferimento alla documentazione SFTPGo. Per applicare le modifiche è necessario il riavvio del servizio", + "domain_help": "È possibile specificare più domini separati da virgole o spazi. Saranno inclusi nello stesso certificato", + "email_help": "Email utilizzata per la registrazione e il contatto di recupero", + "port_help": "Se diverso da 80 è necessario configurare un proxy inverso", + "protocols_help": "Utilizzare i certificati ottenuti per i protocolli specificati" + }, + "smtp": { + "title": "SMTP", + "err_required_fields": "L'indirizzo del mittente e lo username non possono essere entrambi vuoti", + "client_id_required": "Il Client ID è obbligatorio", + "client_secret_required": "Il Client Secret è obbligatorio", + "refresh_token_required": "Il Refresh Token è obbligatorio", + "help": "Imposta la configurazione SMTP sostituendo quella definita utilizzando env vars o il file di configurazione, se presente", + "host": "Nome server", + "host_help": "Se vuoto la configurazione è disabilitata", + "auth": "Autenticazione", + "encryption": "Crittografia", + "sender": "Mittente", + "debug": "Log a livello debug", + "domain_help": "Dominio HELO. Lascia vuoto per utilizzare il nome host del server", + "test_recipient": "Indirizzo a cui inviare e-mail di test", + "oauth2_provider": "OAuth2 provider", + "oauth2_provider_help": "URI a cui reindirizzare dopo l'autenticazione dell'utente", + "oauth2_tenant": "OAuth2 Tenant", + "oauth2_tenant_help": "Azure tenant. Valori tipici sono \"common\", \"organizations\", \"consumers\" or l'ID del tenant", + "oauth2_client_id": "OAuth2 Client ID", + "oauth2_client_secret": "OAuth2 Client Secret", + "oauth2_token": "OAuth2 Token", + "recipient_required": "Specifica un destinatario per inviare un'e-mail di prova", + "test_error": "Impossibile inviare e-mail di prova, controlla i log del server per maggiori dettagli", + "test_ok": "Non si sono verificati errori durante l'invio dell'e-mail di prova. Controlla la tua casella di posta per essere sicuro", + "oauth2_flow_error": "Impossibile ottenere l'URI per avviare il flusso OAuth2", + "oauth2_question": "Vuoi avviare il flusso OAuth2 per ottenere un token?" + }, + "sftp": { + "help": "Da questa sezione è possibile abilitare gli algoritmi disabilitati di default. Non è necessario impostare valori già definiti utilizzando env vars o il file di configurazione. Per applicare le modifiche è necessario il riavvio del servizio", + "host_key_algos": "Algoritmi per chiavi host" } } \ No newline at end of file diff --git a/templates/webadmin/admin.html b/templates/webadmin/admin.html index 9b929fe1..0d8bd22e 100644 --- a/templates/webadmin/admin.html +++ b/templates/webadmin/admin.html @@ -212,7 +212,7 @@ explicit grant from the SFTPGo Team (support@sftpgo.com).
-
diff --git a/templates/webadmin/configs.html b/templates/webadmin/configs.html index 86b1ddf0..8ed32d8d 100644 --- a/templates/webadmin/configs.html +++ b/templates/webadmin/configs.html @@ -1,107 +1,97 @@ {{template "base" .}} -{{define "title"}}{{.Title}}{{end}} - -{{define "extra_css"}} - -{{end}} - -{{define "page_body"}} -
-
-
{{.Title}}
+{{- define "page_body"}} +
+
+

- {{if .Error}} - - {{end}} -
- -
-
-
-

- -

-
+ {{- template "errmsg" .Error}} +
+
+

+ +

+
+
+

-
-
-
-
Here you can enable algorithms disabled by default. You don't need to set values already defined using env vars or config file. A service restart is required to apply changes.
-
- -
- -
- + {{- range $val := .Configs.SFTPD.GetSupportedHostKeyAlgos}} - {{end}} + {{- end}}
-
- -
- + {{- range $val := .Configs.SFTPD.GetSupportedPublicKeyAlgos}} - {{end}} + {{- end}}
-
- -
- - - Comma separated moduli file paths. Invalid/missing paths are silently ignored. Moduli are required to enable Diffie-Helmann Group Exchange KEX algos - -
-
- -
- -
- + {{- range $val := .Configs.SFTPD.GetSupportedKEXAlgos}} - {{end}} + {{- end}}
-
- -
- + {{- range $val := .Configs.SFTPD.GetSupportedMACs}} + + {{- end}} + +
+
+ +
+ +
+ - {{range $val := .Configs.SFTPD.GetSupportedMACs}} - - {{end}} - -
+
+ + +
+ -
- -
- -
-
-
-

- -

-
+
-
-
-
-
From this section you can request free TLS certificates for your SFTPGo services using the ACME protocol and the HTTP-01 challenge type. You must create a DNS entry under a custom domain that you own which resolves to your SFTPGo public IP address and the port 80 must be publicly reachable. You can set the configuration options for the most common use cases and single node setups here, for advanced configurations refer to the SFTPGo docs. A service restart is required to apply changes
-
+
+

+ +

+
+
+

-
- -
- - - Multiple domains can be specified comma or space separated. They will be included in the same certificate - +
+ +
+ +
+ +
-
- -
- - - Email used for registration and recovery contact - +
+ +
+ +
-
- -
- - - If different from 80 you have to configure a reverse proxy - +
+ +
+ +
-
- -
- - - Use the obtained certificates for the specified protocols - +
-
- +
+ + +
- -
+
-
-
-
-

- -

-
+
-
-
-
-
Set the SMTP configuration replacing the one defined using env vars or config file if any.
-
+
+

+ +

+
+
+

-
- -
- - - If empty the configuration is disabled - +
+ +
+ +
+ +
-
- -
- +
+ +
+
-
- -
- +
+ +
+
-
- -
- +
+ +
+
-
- -
-
-
- -
- +
-
- -
- - - +
-
- -
- - - Azure Active Directory tenant. Typical values are "common", "organizations", "consumers" or tenant identifier. - +
+ +
+ +
-
- -
- +
+ +
+
-
- -
- +
+ +
+
-
- -
+
+ +
- -
- -
+ +
-
- -
- +
+ +
+
-
- -
- - - HELO domain. Leave blank to use the server hostname - +
+ +
+ +
-
-
- - -
-
- -
-
-
- -
- -
+
+ +
+
+
-
- +
+
+
+ + +
+
-
+
+ + + +
+
- -
-
-{{end}} -{{define "dialog"}} - - +{{- end}} - -{{end}} -{{define "extra_js"}} - - -{{end}} +{{- end}} \ No newline at end of file diff --git a/templates/webadmin/profile.html b/templates/webadmin/profile.html index b8d57111..8e46e68a 100644 --- a/templates/webadmin/profile.html +++ b/templates/webadmin/profile.html @@ -26,7 +26,7 @@ explicit grant from the SFTPGo Team (support@sftpgo.com).
-
diff --git a/templates/webadmin/user.html b/templates/webadmin/user.html index ff397681..2dc21319 100644 --- a/templates/webadmin/user.html +++ b/templates/webadmin/user.html @@ -392,7 +392,7 @@ explicit grant from the SFTPGo Team (support@sftpgo.com).
-
diff --git a/templates/webclient/profile.html b/templates/webclient/profile.html index e572f43d..4155ab82 100644 --- a/templates/webclient/profile.html +++ b/templates/webclient/profile.html @@ -26,7 +26,7 @@ explicit grant from the SFTPGo Team (support@sftpgo.com).
-