mirror of
https://github.com/drakkan/sftpgo.git
synced 2024-11-21 23:20:24 +00:00
add more linters
test cases migration to testify is now complete. Linters are enabled for test cases too
This commit is contained in:
parent
e9534be1e6
commit
f02e24437a
43 changed files with 2288 additions and 3762 deletions
6
.github/workflows/quality.yml
vendored
6
.github/workflows/quality.yml
vendored
|
@ -15,14 +15,14 @@ jobs:
|
||||||
- name: Set up Go 1.14
|
- name: Set up Go 1.14
|
||||||
uses: actions/setup-go@v2
|
uses: actions/setup-go@v2
|
||||||
with:
|
with:
|
||||||
go-version: '1.14'
|
go-version: 1.14
|
||||||
id: go
|
id: go
|
||||||
|
|
||||||
- name: Check out code into the Go module directory
|
- name: Check out code into the Go module directory
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v2
|
||||||
|
|
||||||
- name: Install golangci-lint
|
- name: Install golangci-lint
|
||||||
run: curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(go env GOPATH)/bin v1.25.1
|
run: curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(go env GOPATH)/bin v1.26.0
|
||||||
|
|
||||||
- name: Run golangci-lint
|
- name: Run golangci-lint
|
||||||
run: golangci-lint run --timeout=3m --tests=false --enable=goconst,gofmt,goimports,golint,unconvert,unparam,bodyclose,gocyclo,misspell,maligned,whitespace,dupl,scopelint
|
run: golangci-lint run
|
||||||
|
|
42
.golangci.yml
Normal file
42
.golangci.yml
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
run:
|
||||||
|
timeout: 5m
|
||||||
|
issues-exit-code: 1
|
||||||
|
tests: true
|
||||||
|
|
||||||
|
|
||||||
|
linters-settings:
|
||||||
|
dupl:
|
||||||
|
threshold: 150
|
||||||
|
errcheck:
|
||||||
|
check-type-assertions: false
|
||||||
|
check-blank: false
|
||||||
|
goconst:
|
||||||
|
min-len: 3
|
||||||
|
min-occurrences: 3
|
||||||
|
gocyclo:
|
||||||
|
min-complexity: 15
|
||||||
|
gofmt:
|
||||||
|
simplify: true
|
||||||
|
goimports:
|
||||||
|
local-prefixes: github.com/drakkan/sftpgo
|
||||||
|
maligned:
|
||||||
|
suggest-new: true
|
||||||
|
|
||||||
|
linters:
|
||||||
|
enable:
|
||||||
|
- goconst
|
||||||
|
- errcheck
|
||||||
|
- gofmt
|
||||||
|
- goimports
|
||||||
|
- golint
|
||||||
|
- unconvert
|
||||||
|
- unparam
|
||||||
|
- bodyclose
|
||||||
|
- gocyclo
|
||||||
|
- misspell
|
||||||
|
- maligned
|
||||||
|
- whitespace
|
||||||
|
- dupl
|
||||||
|
- scopelint
|
||||||
|
- rowserrcheck
|
||||||
|
- dogsled
|
|
@ -1,13 +1,14 @@
|
||||||
package cmd
|
package cmd
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"github.com/rs/zerolog"
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
"github.com/spf13/viper"
|
||||||
|
|
||||||
"github.com/drakkan/sftpgo/config"
|
"github.com/drakkan/sftpgo/config"
|
||||||
"github.com/drakkan/sftpgo/dataprovider"
|
"github.com/drakkan/sftpgo/dataprovider"
|
||||||
"github.com/drakkan/sftpgo/logger"
|
"github.com/drakkan/sftpgo/logger"
|
||||||
"github.com/drakkan/sftpgo/utils"
|
"github.com/drakkan/sftpgo/utils"
|
||||||
"github.com/rs/zerolog"
|
|
||||||
"github.com/spf13/cobra"
|
|
||||||
"github.com/spf13/viper"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
|
|
@ -4,9 +4,10 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
|
||||||
"github.com/drakkan/sftpgo/service"
|
"github.com/drakkan/sftpgo/service"
|
||||||
"github.com/drakkan/sftpgo/utils"
|
"github.com/drakkan/sftpgo/utils"
|
||||||
"github.com/spf13/cobra"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
|
|
@ -9,11 +9,12 @@ import (
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
|
||||||
"github.com/drakkan/sftpgo/dataprovider"
|
"github.com/drakkan/sftpgo/dataprovider"
|
||||||
"github.com/drakkan/sftpgo/service"
|
"github.com/drakkan/sftpgo/service"
|
||||||
"github.com/drakkan/sftpgo/sftpd"
|
"github.com/drakkan/sftpgo/sftpd"
|
||||||
"github.com/drakkan/sftpgo/vfs"
|
"github.com/drakkan/sftpgo/vfs"
|
||||||
"github.com/spf13/cobra"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
|
|
@ -3,8 +3,9 @@ package cmd
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/drakkan/sftpgo/service"
|
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
|
|
||||||
|
"github.com/drakkan/sftpgo/service"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
|
41
cmd/root.go
41
cmd/root.go
|
@ -5,10 +5,11 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
"github.com/drakkan/sftpgo/config"
|
|
||||||
"github.com/drakkan/sftpgo/utils"
|
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
"github.com/spf13/viper"
|
"github.com/spf13/viper"
|
||||||
|
|
||||||
|
"github.com/drakkan/sftpgo/config"
|
||||||
|
"github.com/drakkan/sftpgo/utils"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -77,71 +78,71 @@ func Execute() {
|
||||||
|
|
||||||
func addConfigFlags(cmd *cobra.Command) {
|
func addConfigFlags(cmd *cobra.Command) {
|
||||||
viper.SetDefault(configDirKey, defaultConfigDir)
|
viper.SetDefault(configDirKey, defaultConfigDir)
|
||||||
viper.BindEnv(configDirKey, "SFTPGO_CONFIG_DIR") //nolint: errcheck // err is not nil only if the key to bind is missing
|
viper.BindEnv(configDirKey, "SFTPGO_CONFIG_DIR") //nolint:errcheck // err is not nil only if the key to bind is missing
|
||||||
cmd.Flags().StringVarP(&configDir, configDirFlag, "c", viper.GetString(configDirKey),
|
cmd.Flags().StringVarP(&configDir, configDirFlag, "c", viper.GetString(configDirKey),
|
||||||
"Location for SFTPGo config dir. This directory should contain the \"sftpgo\" configuration file or the configured "+
|
"Location for SFTPGo config dir. This directory should contain the \"sftpgo\" configuration file or the configured "+
|
||||||
"config-file and it is used as the base for files with a relative path (eg. the private keys for the SFTP server, "+
|
"config-file and it is used as the base for files with a relative path (eg. the private keys for the SFTP server, "+
|
||||||
"the SQLite database if you use SQLite as data provider). This flag can be set using SFTPGO_CONFIG_DIR env var too.")
|
"the SQLite database if you use SQLite as data provider). This flag can be set using SFTPGO_CONFIG_DIR env var too.")
|
||||||
viper.BindPFlag(configDirKey, cmd.Flags().Lookup(configDirFlag)) //nolint: errcheck
|
viper.BindPFlag(configDirKey, cmd.Flags().Lookup(configDirFlag)) //nolint:errcheck
|
||||||
|
|
||||||
viper.SetDefault(configFileKey, defaultConfigName)
|
viper.SetDefault(configFileKey, defaultConfigName)
|
||||||
viper.BindEnv(configFileKey, "SFTPGO_CONFIG_FILE") //nolint: errcheck
|
viper.BindEnv(configFileKey, "SFTPGO_CONFIG_FILE") //nolint:errcheck
|
||||||
cmd.Flags().StringVarP(&configFile, configFileFlag, "f", viper.GetString(configFileKey),
|
cmd.Flags().StringVarP(&configFile, configFileFlag, "f", viper.GetString(configFileKey),
|
||||||
"Name for SFTPGo configuration file. It must be the name of a file stored in config-dir not the absolute path to the "+
|
"Name for SFTPGo configuration file. It must be the name of a file stored in config-dir not the absolute path to the "+
|
||||||
"configuration file. The specified file name must have no extension we automatically load JSON, YAML, TOML, HCL and "+
|
"configuration file. The specified file name must have no extension we automatically load JSON, YAML, TOML, HCL and "+
|
||||||
"Java properties. Therefore if you set \"sftpgo\" then \"sftpgo.json\", \"sftpgo.yaml\" and so on are searched. "+
|
"Java properties. Therefore if you set \"sftpgo\" then \"sftpgo.json\", \"sftpgo.yaml\" and so on are searched. "+
|
||||||
"This flag can be set using SFTPGO_CONFIG_FILE env var too.")
|
"This flag can be set using SFTPGO_CONFIG_FILE env var too.")
|
||||||
viper.BindPFlag(configFileKey, cmd.Flags().Lookup(configFileFlag)) //nolint: errcheck
|
viper.BindPFlag(configFileKey, cmd.Flags().Lookup(configFileFlag)) //nolint:errcheck
|
||||||
}
|
}
|
||||||
|
|
||||||
func addServeFlags(cmd *cobra.Command) {
|
func addServeFlags(cmd *cobra.Command) {
|
||||||
addConfigFlags(cmd)
|
addConfigFlags(cmd)
|
||||||
|
|
||||||
viper.SetDefault(logFilePathKey, defaultLogFile)
|
viper.SetDefault(logFilePathKey, defaultLogFile)
|
||||||
viper.BindEnv(logFilePathKey, "SFTPGO_LOG_FILE_PATH") //nolint: errcheck
|
viper.BindEnv(logFilePathKey, "SFTPGO_LOG_FILE_PATH") //nolint:errcheck
|
||||||
cmd.Flags().StringVarP(&logFilePath, logFilePathFlag, "l", viper.GetString(logFilePathKey),
|
cmd.Flags().StringVarP(&logFilePath, logFilePathFlag, "l", viper.GetString(logFilePathKey),
|
||||||
"Location for the log file. Leave empty to write logs to the standard output. This flag can be set using SFTPGO_LOG_FILE_PATH "+
|
"Location for the log file. Leave empty to write logs to the standard output. This flag can be set using SFTPGO_LOG_FILE_PATH "+
|
||||||
"env var too.")
|
"env var too.")
|
||||||
viper.BindPFlag(logFilePathKey, cmd.Flags().Lookup(logFilePathFlag)) //nolint: errcheck
|
viper.BindPFlag(logFilePathKey, cmd.Flags().Lookup(logFilePathFlag)) //nolint:errcheck
|
||||||
|
|
||||||
viper.SetDefault(logMaxSizeKey, defaultLogMaxSize)
|
viper.SetDefault(logMaxSizeKey, defaultLogMaxSize)
|
||||||
viper.BindEnv(logMaxSizeKey, "SFTPGO_LOG_MAX_SIZE") //nolint: errcheck
|
viper.BindEnv(logMaxSizeKey, "SFTPGO_LOG_MAX_SIZE") //nolint:errcheck
|
||||||
cmd.Flags().IntVarP(&logMaxSize, logMaxSizeFlag, "s", viper.GetInt(logMaxSizeKey),
|
cmd.Flags().IntVarP(&logMaxSize, logMaxSizeFlag, "s", viper.GetInt(logMaxSizeKey),
|
||||||
"Maximum size in megabytes of the log file before it gets rotated. This flag can be set using SFTPGO_LOG_MAX_SIZE "+
|
"Maximum size in megabytes of the log file before it gets rotated. This flag can be set using SFTPGO_LOG_MAX_SIZE "+
|
||||||
"env var too. It is unused if log-file-path is empty.")
|
"env var too. It is unused if log-file-path is empty.")
|
||||||
viper.BindPFlag(logMaxSizeKey, cmd.Flags().Lookup(logMaxSizeFlag)) //nolint: errcheck
|
viper.BindPFlag(logMaxSizeKey, cmd.Flags().Lookup(logMaxSizeFlag)) //nolint:errcheck
|
||||||
|
|
||||||
viper.SetDefault(logMaxBackupKey, defaultLogMaxBackup)
|
viper.SetDefault(logMaxBackupKey, defaultLogMaxBackup)
|
||||||
viper.BindEnv(logMaxBackupKey, "SFTPGO_LOG_MAX_BACKUPS") //nolint: errcheck
|
viper.BindEnv(logMaxBackupKey, "SFTPGO_LOG_MAX_BACKUPS") //nolint:errcheck
|
||||||
cmd.Flags().IntVarP(&logMaxBackups, "log-max-backups", "b", viper.GetInt(logMaxBackupKey),
|
cmd.Flags().IntVarP(&logMaxBackups, "log-max-backups", "b", viper.GetInt(logMaxBackupKey),
|
||||||
"Maximum number of old log files to retain. This flag can be set using SFTPGO_LOG_MAX_BACKUPS env var too. "+
|
"Maximum number of old log files to retain. This flag can be set using SFTPGO_LOG_MAX_BACKUPS env var too. "+
|
||||||
"It is unused if log-file-path is empty.")
|
"It is unused if log-file-path is empty.")
|
||||||
viper.BindPFlag(logMaxBackupKey, cmd.Flags().Lookup(logMaxBackupFlag)) //nolint: errcheck
|
viper.BindPFlag(logMaxBackupKey, cmd.Flags().Lookup(logMaxBackupFlag)) //nolint:errcheck
|
||||||
|
|
||||||
viper.SetDefault(logMaxAgeKey, defaultLogMaxAge)
|
viper.SetDefault(logMaxAgeKey, defaultLogMaxAge)
|
||||||
viper.BindEnv(logMaxAgeKey, "SFTPGO_LOG_MAX_AGE") //nolint: errcheck
|
viper.BindEnv(logMaxAgeKey, "SFTPGO_LOG_MAX_AGE") //nolint:errcheck
|
||||||
cmd.Flags().IntVarP(&logMaxAge, "log-max-age", "a", viper.GetInt(logMaxAgeKey),
|
cmd.Flags().IntVarP(&logMaxAge, "log-max-age", "a", viper.GetInt(logMaxAgeKey),
|
||||||
"Maximum number of days to retain old log files. This flag can be set using SFTPGO_LOG_MAX_AGE env var too. "+
|
"Maximum number of days to retain old log files. This flag can be set using SFTPGO_LOG_MAX_AGE env var too. "+
|
||||||
"It is unused if log-file-path is empty.")
|
"It is unused if log-file-path is empty.")
|
||||||
viper.BindPFlag(logMaxAgeKey, cmd.Flags().Lookup(logMaxAgeFlag)) //nolint: errcheck
|
viper.BindPFlag(logMaxAgeKey, cmd.Flags().Lookup(logMaxAgeFlag)) //nolint:errcheck
|
||||||
|
|
||||||
viper.SetDefault(logCompressKey, defaultLogCompress)
|
viper.SetDefault(logCompressKey, defaultLogCompress)
|
||||||
viper.BindEnv(logCompressKey, "SFTPGO_LOG_COMPRESS") //nolint: errcheck
|
viper.BindEnv(logCompressKey, "SFTPGO_LOG_COMPRESS") //nolint:errcheck
|
||||||
cmd.Flags().BoolVarP(&logCompress, logCompressFlag, "z", viper.GetBool(logCompressKey), "Determine if the rotated "+
|
cmd.Flags().BoolVarP(&logCompress, logCompressFlag, "z", viper.GetBool(logCompressKey), "Determine if the rotated "+
|
||||||
"log files should be compressed using gzip. This flag can be set using SFTPGO_LOG_COMPRESS env var too. "+
|
"log files should be compressed using gzip. This flag can be set using SFTPGO_LOG_COMPRESS env var too. "+
|
||||||
"It is unused if log-file-path is empty.")
|
"It is unused if log-file-path is empty.")
|
||||||
viper.BindPFlag(logCompressKey, cmd.Flags().Lookup(logCompressFlag)) //nolint: errcheck
|
viper.BindPFlag(logCompressKey, cmd.Flags().Lookup(logCompressFlag)) //nolint:errcheck
|
||||||
|
|
||||||
viper.SetDefault(logVerboseKey, defaultLogVerbose)
|
viper.SetDefault(logVerboseKey, defaultLogVerbose)
|
||||||
viper.BindEnv(logVerboseKey, "SFTPGO_LOG_VERBOSE") //nolint: errcheck
|
viper.BindEnv(logVerboseKey, "SFTPGO_LOG_VERBOSE") //nolint:errcheck
|
||||||
cmd.Flags().BoolVarP(&logVerbose, logVerboseFlag, "v", viper.GetBool(logVerboseKey), "Enable verbose logs. "+
|
cmd.Flags().BoolVarP(&logVerbose, logVerboseFlag, "v", viper.GetBool(logVerboseKey), "Enable verbose logs. "+
|
||||||
"This flag can be set using SFTPGO_LOG_VERBOSE env var too.")
|
"This flag can be set using SFTPGO_LOG_VERBOSE env var too.")
|
||||||
viper.BindPFlag(logVerboseKey, cmd.Flags().Lookup(logVerboseFlag)) //nolint: errcheck
|
viper.BindPFlag(logVerboseKey, cmd.Flags().Lookup(logVerboseFlag)) //nolint:errcheck
|
||||||
|
|
||||||
viper.SetDefault(profilerKey, defaultProfiler)
|
viper.SetDefault(profilerKey, defaultProfiler)
|
||||||
viper.BindEnv(profilerKey, "SFTPGO_PROFILER") //nolint: errcheck
|
viper.BindEnv(profilerKey, "SFTPGO_PROFILER") //nolint:errcheck
|
||||||
cmd.Flags().BoolVarP(&profiler, profilerFlag, "p", viper.GetBool(profilerKey), "Enable the built-in profiler. "+
|
cmd.Flags().BoolVarP(&profiler, profilerFlag, "p", viper.GetBool(profilerKey), "Enable the built-in profiler. "+
|
||||||
"The profiler will be accessible via HTTP/HTTPS using the base URL \"/debug/pprof/\". "+
|
"The profiler will be accessible via HTTP/HTTPS using the base URL \"/debug/pprof/\". "+
|
||||||
"This flag can be set using SFTPGO_PROFILER env var too.")
|
"This flag can be set using SFTPGO_PROFILER env var too.")
|
||||||
viper.BindPFlag(profilerKey, cmd.Flags().Lookup(profilerFlag)) //nolint: errcheck
|
viper.BindPFlag(profilerKey, cmd.Flags().Lookup(profilerFlag)) //nolint:errcheck
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
package cmd
|
package cmd
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
|
||||||
"github.com/drakkan/sftpgo/service"
|
"github.com/drakkan/sftpgo/service"
|
||||||
"github.com/drakkan/sftpgo/utils"
|
"github.com/drakkan/sftpgo/utils"
|
||||||
"github.com/spf13/cobra"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
|
|
@ -4,9 +4,10 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
|
||||||
"github.com/drakkan/sftpgo/service"
|
"github.com/drakkan/sftpgo/service"
|
||||||
"github.com/drakkan/sftpgo/utils"
|
"github.com/drakkan/sftpgo/utils"
|
||||||
"github.com/spf13/cobra"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
|
|
@ -3,8 +3,9 @@ package cmd
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/drakkan/sftpgo/service"
|
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
|
|
||||||
|
"github.com/drakkan/sftpgo/service"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
|
|
@ -3,8 +3,9 @@ package cmd
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/drakkan/sftpgo/service"
|
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
|
|
||||||
|
"github.com/drakkan/sftpgo/service"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
|
|
@ -3,8 +3,9 @@ package cmd
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/drakkan/sftpgo/service"
|
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
|
|
||||||
|
"github.com/drakkan/sftpgo/service"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
|
|
@ -9,13 +9,14 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/spf13/viper"
|
||||||
|
|
||||||
"github.com/drakkan/sftpgo/dataprovider"
|
"github.com/drakkan/sftpgo/dataprovider"
|
||||||
"github.com/drakkan/sftpgo/httpclient"
|
"github.com/drakkan/sftpgo/httpclient"
|
||||||
"github.com/drakkan/sftpgo/httpd"
|
"github.com/drakkan/sftpgo/httpd"
|
||||||
"github.com/drakkan/sftpgo/logger"
|
"github.com/drakkan/sftpgo/logger"
|
||||||
"github.com/drakkan/sftpgo/sftpd"
|
"github.com/drakkan/sftpgo/sftpd"
|
||||||
"github.com/drakkan/sftpgo/utils"
|
"github.com/drakkan/sftpgo/utils"
|
||||||
"github.com/spf13/viper"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -222,19 +223,19 @@ func LoadConfig(configDir, configName string) error {
|
||||||
|
|
||||||
func checkHooksCompatibility() {
|
func checkHooksCompatibility() {
|
||||||
// we copy deprecated fields to new ones to keep backward compatibility so lint is disabled
|
// we copy deprecated fields to new ones to keep backward compatibility so lint is disabled
|
||||||
if len(globalConf.ProviderConf.ExternalAuthProgram) > 0 && len(globalConf.ProviderConf.ExternalAuthHook) == 0 { //nolint: staticcheck
|
if len(globalConf.ProviderConf.ExternalAuthProgram) > 0 && len(globalConf.ProviderConf.ExternalAuthHook) == 0 { //nolint:staticcheck
|
||||||
logger.Warn(logSender, "", "external_auth_program is deprecated, please use external_auth_hook")
|
logger.Warn(logSender, "", "external_auth_program is deprecated, please use external_auth_hook")
|
||||||
logger.WarnToConsole("external_auth_program is deprecated, please use external_auth_hook")
|
logger.WarnToConsole("external_auth_program is deprecated, please use external_auth_hook")
|
||||||
globalConf.ProviderConf.ExternalAuthHook = globalConf.ProviderConf.ExternalAuthProgram //nolint: staticcheck
|
globalConf.ProviderConf.ExternalAuthHook = globalConf.ProviderConf.ExternalAuthProgram //nolint:staticcheck
|
||||||
}
|
}
|
||||||
if len(globalConf.ProviderConf.PreLoginProgram) > 0 && len(globalConf.ProviderConf.PreLoginHook) == 0 { //nolint: staticcheck
|
if len(globalConf.ProviderConf.PreLoginProgram) > 0 && len(globalConf.ProviderConf.PreLoginHook) == 0 { //nolint:staticcheck
|
||||||
logger.Warn(logSender, "", "pre_login_program is deprecated, please use pre_login_hook")
|
logger.Warn(logSender, "", "pre_login_program is deprecated, please use pre_login_hook")
|
||||||
logger.WarnToConsole("pre_login_program is deprecated, please use pre_login_hook")
|
logger.WarnToConsole("pre_login_program is deprecated, please use pre_login_hook")
|
||||||
globalConf.ProviderConf.PreLoginHook = globalConf.ProviderConf.PreLoginProgram //nolint: staticcheck
|
globalConf.ProviderConf.PreLoginHook = globalConf.ProviderConf.PreLoginProgram //nolint:staticcheck
|
||||||
}
|
}
|
||||||
if len(globalConf.SFTPD.KeyboardInteractiveProgram) > 0 && len(globalConf.SFTPD.KeyboardInteractiveHook) == 0 { //nolint: staticcheck
|
if len(globalConf.SFTPD.KeyboardInteractiveProgram) > 0 && len(globalConf.SFTPD.KeyboardInteractiveHook) == 0 { //nolint:staticcheck
|
||||||
logger.Warn(logSender, "", "keyboard_interactive_auth_program is deprecated, please use keyboard_interactive_auth_hook")
|
logger.Warn(logSender, "", "keyboard_interactive_auth_program is deprecated, please use keyboard_interactive_auth_hook")
|
||||||
logger.WarnToConsole("keyboard_interactive_auth_program is deprecated, please use keyboard_interactive_auth_hook")
|
logger.WarnToConsole("keyboard_interactive_auth_program is deprecated, please use keyboard_interactive_auth_hook")
|
||||||
globalConf.SFTPD.KeyboardInteractiveHook = globalConf.SFTPD.KeyboardInteractiveProgram //nolint: staticcheck
|
globalConf.SFTPD.KeyboardInteractiveHook = globalConf.SFTPD.KeyboardInteractiveProgram //nolint:staticcheck
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,12 +8,13 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
|
||||||
"github.com/drakkan/sftpgo/config"
|
"github.com/drakkan/sftpgo/config"
|
||||||
"github.com/drakkan/sftpgo/dataprovider"
|
"github.com/drakkan/sftpgo/dataprovider"
|
||||||
"github.com/drakkan/sftpgo/httpclient"
|
"github.com/drakkan/sftpgo/httpclient"
|
||||||
"github.com/drakkan/sftpgo/httpd"
|
"github.com/drakkan/sftpgo/httpd"
|
||||||
"github.com/drakkan/sftpgo/sftpd"
|
"github.com/drakkan/sftpgo/sftpd"
|
||||||
"github.com/stretchr/testify/assert"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -173,8 +174,8 @@ func TestHookCompatibity(t *testing.T) {
|
||||||
err := config.LoadConfig(configDir, configName)
|
err := config.LoadConfig(configDir, configName)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
providerConf := config.GetProviderConf()
|
providerConf := config.GetProviderConf()
|
||||||
providerConf.ExternalAuthProgram = "ext_auth_program"
|
providerConf.ExternalAuthProgram = "ext_auth_program" //nolint:staticcheck
|
||||||
providerConf.PreLoginProgram = "pre_login_program"
|
providerConf.PreLoginProgram = "pre_login_program" //nolint:staticcheck
|
||||||
c := make(map[string]dataprovider.Config)
|
c := make(map[string]dataprovider.Config)
|
||||||
c["data_provider"] = providerConf
|
c["data_provider"] = providerConf
|
||||||
jsonConf, err := json.Marshal(c)
|
jsonConf, err := json.Marshal(c)
|
||||||
|
@ -189,7 +190,7 @@ func TestHookCompatibity(t *testing.T) {
|
||||||
err = os.Remove(configFilePath)
|
err = os.Remove(configFilePath)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
sftpdConf := config.GetSFTPDConfig()
|
sftpdConf := config.GetSFTPDConfig()
|
||||||
sftpdConf.KeyboardInteractiveProgram = "key_int_program"
|
sftpdConf.KeyboardInteractiveProgram = "key_int_program" //nolint:staticcheck
|
||||||
cnf := make(map[string]sftpd.Configuration)
|
cnf := make(map[string]sftpd.Configuration)
|
||||||
cnf["sftpd"] = sftpdConf
|
cnf["sftpd"] = sftpdConf
|
||||||
jsonConf, err = json.Marshal(cnf)
|
jsonConf, err = json.Marshal(cnf)
|
||||||
|
|
|
@ -8,9 +8,10 @@ import (
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
bolt "go.etcd.io/bbolt"
|
||||||
|
|
||||||
"github.com/drakkan/sftpgo/logger"
|
"github.com/drakkan/sftpgo/logger"
|
||||||
"github.com/drakkan/sftpgo/utils"
|
"github.com/drakkan/sftpgo/utils"
|
||||||
bolt "go.etcd.io/bbolt"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
|
|
@ -33,6 +33,7 @@ import (
|
||||||
|
|
||||||
"github.com/alexedwards/argon2id"
|
"github.com/alexedwards/argon2id"
|
||||||
"github.com/go-chi/render"
|
"github.com/go-chi/render"
|
||||||
|
unixcrypt "github.com/nathanaelle/password/v2"
|
||||||
"github.com/rs/xid"
|
"github.com/rs/xid"
|
||||||
"golang.org/x/crypto/bcrypt"
|
"golang.org/x/crypto/bcrypt"
|
||||||
"golang.org/x/crypto/pbkdf2"
|
"golang.org/x/crypto/pbkdf2"
|
||||||
|
@ -43,7 +44,6 @@ import (
|
||||||
"github.com/drakkan/sftpgo/metrics"
|
"github.com/drakkan/sftpgo/metrics"
|
||||||
"github.com/drakkan/sftpgo/utils"
|
"github.com/drakkan/sftpgo/utils"
|
||||||
"github.com/drakkan/sftpgo/vfs"
|
"github.com/drakkan/sftpgo/vfs"
|
||||||
unixcrypt "github.com/nathanaelle/password/v2"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
|
|
@ -271,9 +271,9 @@ func sqlCommonGetUsers(limit int, offset int, order string, username string, dbH
|
||||||
defer stmt.Close()
|
defer stmt.Close()
|
||||||
var rows *sql.Rows
|
var rows *sql.Rows
|
||||||
if len(username) > 0 {
|
if len(username) > 0 {
|
||||||
rows, err = stmt.Query(username, limit, offset)
|
rows, err = stmt.Query(username, limit, offset) //nolint:rowserrcheck // err is checked
|
||||||
} else {
|
} else {
|
||||||
rows, err = stmt.Query(limit, offset)
|
rows, err = stmt.Query(limit, offset) //nolint:rowserrcheck // err is checked
|
||||||
}
|
}
|
||||||
if err == nil {
|
if err == nil {
|
||||||
defer rows.Close()
|
defer rows.Close()
|
||||||
|
|
|
@ -3,10 +3,11 @@ package httpd
|
||||||
import (
|
import (
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/go-chi/render"
|
||||||
|
|
||||||
"github.com/drakkan/sftpgo/dataprovider"
|
"github.com/drakkan/sftpgo/dataprovider"
|
||||||
"github.com/drakkan/sftpgo/logger"
|
"github.com/drakkan/sftpgo/logger"
|
||||||
"github.com/drakkan/sftpgo/sftpd"
|
"github.com/drakkan/sftpgo/sftpd"
|
||||||
"github.com/go-chi/render"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func getQuotaScans(w http.ResponseWriter, r *http.Request) {
|
func getQuotaScans(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|
|
@ -5,10 +5,11 @@ import (
|
||||||
"net/http"
|
"net/http"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
"github.com/drakkan/sftpgo/dataprovider"
|
|
||||||
"github.com/drakkan/sftpgo/utils"
|
|
||||||
"github.com/go-chi/chi"
|
"github.com/go-chi/chi"
|
||||||
"github.com/go-chi/render"
|
"github.com/go-chi/render"
|
||||||
|
|
||||||
|
"github.com/drakkan/sftpgo/dataprovider"
|
||||||
|
"github.com/drakkan/sftpgo/utils"
|
||||||
)
|
)
|
||||||
|
|
||||||
func getUsers(w http.ResponseWriter, r *http.Request) {
|
func getUsers(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|
|
@ -16,11 +16,12 @@ import (
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/go-chi/render"
|
||||||
|
|
||||||
"github.com/drakkan/sftpgo/dataprovider"
|
"github.com/drakkan/sftpgo/dataprovider"
|
||||||
"github.com/drakkan/sftpgo/httpclient"
|
"github.com/drakkan/sftpgo/httpclient"
|
||||||
"github.com/drakkan/sftpgo/sftpd"
|
"github.com/drakkan/sftpgo/sftpd"
|
||||||
"github.com/drakkan/sftpgo/utils"
|
"github.com/drakkan/sftpgo/utils"
|
||||||
"github.com/go-chi/render"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
|
|
@ -9,10 +9,11 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"github.com/drakkan/sftpgo/logger"
|
|
||||||
"github.com/drakkan/sftpgo/utils"
|
|
||||||
unixcrypt "github.com/nathanaelle/password/v2"
|
unixcrypt "github.com/nathanaelle/password/v2"
|
||||||
"golang.org/x/crypto/bcrypt"
|
"golang.org/x/crypto/bcrypt"
|
||||||
|
|
||||||
|
"github.com/drakkan/sftpgo/logger"
|
||||||
|
"github.com/drakkan/sftpgo/utils"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
|
|
@ -13,10 +13,11 @@ import (
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/go-chi/chi"
|
||||||
|
|
||||||
"github.com/drakkan/sftpgo/dataprovider"
|
"github.com/drakkan/sftpgo/dataprovider"
|
||||||
"github.com/drakkan/sftpgo/logger"
|
"github.com/drakkan/sftpgo/logger"
|
||||||
"github.com/drakkan/sftpgo/utils"
|
"github.com/drakkan/sftpgo/utils"
|
||||||
"github.com/go-chi/chi"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
|
|
@ -46,9 +46,6 @@ const (
|
||||||
activeConnectionsPath = "/api/v1/connection"
|
activeConnectionsPath = "/api/v1/connection"
|
||||||
quotaScanPath = "/api/v1/quota_scan"
|
quotaScanPath = "/api/v1/quota_scan"
|
||||||
versionPath = "/api/v1/version"
|
versionPath = "/api/v1/version"
|
||||||
providerStatusPath = "/api/v1/providerstatus"
|
|
||||||
dumpDataPath = "/api/v1/dumpdata"
|
|
||||||
loadDataPath = "/api/v1/loaddata"
|
|
||||||
metricsPath = "/metrics"
|
metricsPath = "/metrics"
|
||||||
pprofPath = "/debug/pprof/"
|
pprofPath = "/debug/pprof/"
|
||||||
webBasePath = "/web"
|
webBasePath = "/web"
|
||||||
|
@ -94,16 +91,20 @@ func TestMain(m *testing.M) {
|
||||||
homeBasePath = os.TempDir()
|
homeBasePath = os.TempDir()
|
||||||
logfilePath := filepath.Join(configDir, "sftpgo_api_test.log")
|
logfilePath := filepath.Join(configDir, "sftpgo_api_test.log")
|
||||||
logger.InitLogger(logfilePath, 5, 1, 28, false, zerolog.DebugLevel)
|
logger.InitLogger(logfilePath, 5, 1, 28, false, zerolog.DebugLevel)
|
||||||
config.LoadConfig(configDir, "")
|
err := config.LoadConfig(configDir, "")
|
||||||
|
if err != nil {
|
||||||
|
logger.WarnToConsole("error loading configuration: %v", err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
providerConf := config.GetProviderConf()
|
providerConf := config.GetProviderConf()
|
||||||
credentialsPath = filepath.Join(os.TempDir(), "test_credentials")
|
credentialsPath = filepath.Join(os.TempDir(), "test_credentials")
|
||||||
providerConf.CredentialsPath = credentialsPath
|
providerConf.CredentialsPath = credentialsPath
|
||||||
providerDriverName = providerConf.Driver
|
providerDriverName = providerConf.Driver
|
||||||
os.RemoveAll(credentialsPath)
|
os.RemoveAll(credentialsPath) //nolint:errcheck
|
||||||
|
|
||||||
err := dataprovider.Initialize(providerConf, configDir)
|
err = dataprovider.Initialize(providerConf, configDir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Warn(logSender, "", "error initializing data provider: %v", err)
|
logger.WarnToConsole("error initializing data provider: %v", err)
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -117,14 +118,18 @@ func TestMain(m *testing.M) {
|
||||||
httpd.SetBaseURLAndCredentials("http://127.0.0.1:8081", "", "")
|
httpd.SetBaseURLAndCredentials("http://127.0.0.1:8081", "", "")
|
||||||
backupsPath = filepath.Join(os.TempDir(), "test_backups")
|
backupsPath = filepath.Join(os.TempDir(), "test_backups")
|
||||||
httpdConf.BackupsPath = backupsPath
|
httpdConf.BackupsPath = backupsPath
|
||||||
os.MkdirAll(backupsPath, 0777)
|
err = os.MkdirAll(backupsPath, 0777)
|
||||||
|
if err != nil {
|
||||||
|
logger.WarnToConsole("error creating backups path: %v", err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
sftpd.SetDataProvider(dataProvider)
|
sftpd.SetDataProvider(dataProvider)
|
||||||
httpd.SetDataProvider(dataProvider)
|
httpd.SetDataProvider(dataProvider)
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
if err := httpdConf.Initialize(configDir, true); err != nil {
|
if err := httpdConf.Initialize(configDir, true); err != nil {
|
||||||
logger.Error(logSender, "", "could not start HTTP server: %v", err)
|
logger.ErrorToConsole("could not start HTTP server: %v", err)
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
|
@ -132,8 +137,16 @@ func TestMain(m *testing.M) {
|
||||||
// now start an https server
|
// now start an https server
|
||||||
certPath := filepath.Join(os.TempDir(), "test.crt")
|
certPath := filepath.Join(os.TempDir(), "test.crt")
|
||||||
keyPath := filepath.Join(os.TempDir(), "test.key")
|
keyPath := filepath.Join(os.TempDir(), "test.key")
|
||||||
ioutil.WriteFile(certPath, []byte(httpsCert), 0666)
|
err = ioutil.WriteFile(certPath, []byte(httpsCert), 0666)
|
||||||
ioutil.WriteFile(keyPath, []byte(httpsKey), 0666)
|
if err != nil {
|
||||||
|
logger.WarnToConsole("error writing HTTPS certificate: %v", err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
err = ioutil.WriteFile(keyPath, []byte(httpsKey), 0666)
|
||||||
|
if err != nil {
|
||||||
|
logger.WarnToConsole("error writing HTTPS private key: %v", err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
httpdConf.BindPort = 8443
|
httpdConf.BindPort = 8443
|
||||||
httpdConf.CertificateFile = certPath
|
httpdConf.CertificateFile = certPath
|
||||||
httpdConf.CertificateKeyFile = keyPath
|
httpdConf.CertificateKeyFile = keyPath
|
||||||
|
@ -144,18 +157,18 @@ func TestMain(m *testing.M) {
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
waitTCPListening(fmt.Sprintf("%s:%d", httpdConf.BindAddress, httpdConf.BindPort))
|
waitTCPListening(fmt.Sprintf("%s:%d", httpdConf.BindAddress, httpdConf.BindPort))
|
||||||
httpd.ReloadTLSCertificate()
|
httpd.ReloadTLSCertificate() //nolint:errcheck
|
||||||
|
|
||||||
testServer = httptest.NewServer(httpd.GetHTTPRouter())
|
testServer = httptest.NewServer(httpd.GetHTTPRouter())
|
||||||
defer testServer.Close()
|
defer testServer.Close() //nolint:errcheck
|
||||||
|
|
||||||
exitCode := m.Run()
|
exitCode := m.Run()
|
||||||
os.Remove(logfilePath)
|
os.Remove(logfilePath) //nolint:errcheck
|
||||||
os.RemoveAll(backupsPath)
|
os.RemoveAll(backupsPath) //nolint:errcheck
|
||||||
os.RemoveAll(credentialsPath)
|
os.RemoveAll(credentialsPath) //nolint:errcheck
|
||||||
os.Remove(certPath)
|
os.Remove(certPath) //nolint:errcheck
|
||||||
os.Remove(keyPath)
|
os.Remove(keyPath) //nolint:errcheck
|
||||||
os.Exit(exitCode)
|
os.Exit(exitCode) //nolint:errcheck
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestInitialization(t *testing.T) {
|
func TestInitialization(t *testing.T) {
|
||||||
|
@ -163,7 +176,7 @@ func TestInitialization(t *testing.T) {
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
httpdConf := config.GetHTTPDConfig()
|
httpdConf := config.GetHTTPDConfig()
|
||||||
httpdConf.BackupsPath = "test_backups"
|
httpdConf.BackupsPath = "test_backups"
|
||||||
httpdConf.AuthUserFile = "invalid file"
|
httpdConf.AuthUserFile = "invalid_file"
|
||||||
err = httpdConf.Initialize(configDir, true)
|
err = httpdConf.Initialize(configDir, true)
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
httpdConf.BackupsPath = backupsPath
|
httpdConf.BackupsPath = backupsPath
|
||||||
|
@ -241,7 +254,7 @@ func TestAddUserNoHomeDir(t *testing.T) {
|
||||||
|
|
||||||
func TestAddUserInvalidHomeDir(t *testing.T) {
|
func TestAddUserInvalidHomeDir(t *testing.T) {
|
||||||
u := getTestUser()
|
u := getTestUser()
|
||||||
u.HomeDir = "relative_path"
|
u.HomeDir = "relative_path" //nolint:goconst
|
||||||
_, _, err := httpd.AddUser(u, http.StatusBadRequest)
|
_, _, err := httpd.AddUser(u, http.StatusBadRequest)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
}
|
}
|
||||||
|
@ -333,13 +346,13 @@ func TestAddUserInvalidFsConfig(t *testing.T) {
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
err = os.MkdirAll(credentialsPath, 0700)
|
err = os.MkdirAll(credentialsPath, 0700)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
u.FsConfig.S3Config.Bucket = "test"
|
u.FsConfig.S3Config.Bucket = "testbucket"
|
||||||
u.FsConfig.S3Config.Region = "eu-west-1"
|
u.FsConfig.S3Config.Region = "eu-west-1"
|
||||||
u.FsConfig.S3Config.AccessKey = "access-key"
|
u.FsConfig.S3Config.AccessKey = "access-key"
|
||||||
u.FsConfig.S3Config.AccessSecret = "access-secret"
|
u.FsConfig.S3Config.AccessSecret = "access-secret"
|
||||||
u.FsConfig.S3Config.Endpoint = "http://127.0.0.1:9000/path?a=b"
|
u.FsConfig.S3Config.Endpoint = "http://127.0.0.1:9000/path?a=b"
|
||||||
u.FsConfig.S3Config.StorageClass = "Standard"
|
u.FsConfig.S3Config.StorageClass = "Standard" //nolint:goconst
|
||||||
u.FsConfig.S3Config.KeyPrefix = "/somedir/subdir/"
|
u.FsConfig.S3Config.KeyPrefix = "/adir/subdir/"
|
||||||
_, _, err = httpd.AddUser(u, http.StatusBadRequest)
|
_, _, err = httpd.AddUser(u, http.StatusBadRequest)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
u.FsConfig.S3Config.KeyPrefix = ""
|
u.FsConfig.S3Config.KeyPrefix = ""
|
||||||
|
@ -355,13 +368,13 @@ func TestAddUserInvalidFsConfig(t *testing.T) {
|
||||||
u.FsConfig.GCSConfig.Bucket = ""
|
u.FsConfig.GCSConfig.Bucket = ""
|
||||||
_, _, err = httpd.AddUser(u, http.StatusBadRequest)
|
_, _, err = httpd.AddUser(u, http.StatusBadRequest)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
u.FsConfig.GCSConfig.Bucket = "test"
|
u.FsConfig.GCSConfig.Bucket = "abucket"
|
||||||
u.FsConfig.GCSConfig.StorageClass = "Standard"
|
u.FsConfig.GCSConfig.StorageClass = "Standard"
|
||||||
u.FsConfig.GCSConfig.KeyPrefix = "/somedir/subdir/"
|
u.FsConfig.GCSConfig.KeyPrefix = "/somedir/subdir/"
|
||||||
u.FsConfig.GCSConfig.Credentials = base64.StdEncoding.EncodeToString([]byte("test"))
|
u.FsConfig.GCSConfig.Credentials = base64.StdEncoding.EncodeToString([]byte("test"))
|
||||||
_, _, err = httpd.AddUser(u, http.StatusBadRequest)
|
_, _, err = httpd.AddUser(u, http.StatusBadRequest)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
u.FsConfig.GCSConfig.KeyPrefix = "somedir/subdir/"
|
u.FsConfig.GCSConfig.KeyPrefix = "somedir/subdir/" //nolint:goconst
|
||||||
u.FsConfig.GCSConfig.Credentials = ""
|
u.FsConfig.GCSConfig.Credentials = ""
|
||||||
u.FsConfig.GCSConfig.AutomaticCredentials = 0
|
u.FsConfig.GCSConfig.AutomaticCredentials = 0
|
||||||
_, _, err = httpd.AddUser(u, http.StatusBadRequest)
|
_, _, err = httpd.AddUser(u, http.StatusBadRequest)
|
||||||
|
@ -542,8 +555,8 @@ func TestUserS3Config(t *testing.T) {
|
||||||
user, _, err := httpd.AddUser(getTestUser(), http.StatusOK)
|
user, _, err := httpd.AddUser(getTestUser(), http.StatusOK)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
user.FsConfig.Provider = 1
|
user.FsConfig.Provider = 1
|
||||||
user.FsConfig.S3Config.Bucket = "test"
|
user.FsConfig.S3Config.Bucket = "test" //nolint:goconst
|
||||||
user.FsConfig.S3Config.Region = "us-east-1"
|
user.FsConfig.S3Config.Region = "us-east-1" //nolint:goconst
|
||||||
user.FsConfig.S3Config.AccessKey = "Server-Access-Key"
|
user.FsConfig.S3Config.AccessKey = "Server-Access-Key"
|
||||||
user.FsConfig.S3Config.AccessSecret = "Server-Access-Secret"
|
user.FsConfig.S3Config.AccessSecret = "Server-Access-Secret"
|
||||||
user.FsConfig.S3Config.Endpoint = "http://127.0.0.1:9000"
|
user.FsConfig.S3Config.Endpoint = "http://127.0.0.1:9000"
|
||||||
|
@ -559,11 +572,11 @@ func TestUserS3Config(t *testing.T) {
|
||||||
user, _, err = httpd.AddUser(user, http.StatusOK)
|
user, _, err = httpd.AddUser(user, http.StatusOK)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
user.FsConfig.Provider = 1
|
user.FsConfig.Provider = 1
|
||||||
user.FsConfig.S3Config.Bucket = "test1"
|
user.FsConfig.S3Config.Bucket = "test-bucket"
|
||||||
user.FsConfig.S3Config.Region = "us-east-1"
|
user.FsConfig.S3Config.Region = "us-east-1" //nolint:goconst
|
||||||
user.FsConfig.S3Config.AccessKey = "Server-Access-Key1"
|
user.FsConfig.S3Config.AccessKey = "Server-Access-Key1"
|
||||||
user.FsConfig.S3Config.Endpoint = "http://localhost:9000"
|
user.FsConfig.S3Config.Endpoint = "http://localhost:9000"
|
||||||
user.FsConfig.S3Config.KeyPrefix = "somedir/subdir"
|
user.FsConfig.S3Config.KeyPrefix = "somedir/subdir" //nolint:goconst
|
||||||
user.FsConfig.S3Config.UploadConcurrency = 5
|
user.FsConfig.S3Config.UploadConcurrency = 5
|
||||||
user, _, err = httpd.UpdateUser(user, http.StatusOK)
|
user, _, err = httpd.UpdateUser(user, http.StatusOK)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
@ -580,7 +593,7 @@ func TestUserS3Config(t *testing.T) {
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
// test user without access key and access secret (shared config state)
|
// test user without access key and access secret (shared config state)
|
||||||
user.FsConfig.Provider = 1
|
user.FsConfig.Provider = 1
|
||||||
user.FsConfig.S3Config.Bucket = "test1"
|
user.FsConfig.S3Config.Bucket = "testbucket"
|
||||||
user.FsConfig.S3Config.Region = "us-east-1"
|
user.FsConfig.S3Config.Region = "us-east-1"
|
||||||
user.FsConfig.S3Config.AccessKey = ""
|
user.FsConfig.S3Config.AccessKey = ""
|
||||||
user.FsConfig.S3Config.AccessSecret = ""
|
user.FsConfig.S3Config.AccessSecret = ""
|
||||||
|
@ -820,7 +833,8 @@ func TestProviderErrors(t *testing.T) {
|
||||||
backupData.Users = append(backupData.Users, user)
|
backupData.Users = append(backupData.Users, user)
|
||||||
backupContent, _ := json.Marshal(backupData)
|
backupContent, _ := json.Marshal(backupData)
|
||||||
backupFilePath := filepath.Join(backupsPath, "backup.json")
|
backupFilePath := filepath.Join(backupsPath, "backup.json")
|
||||||
ioutil.WriteFile(backupFilePath, backupContent, 0666)
|
err = ioutil.WriteFile(backupFilePath, backupContent, 0666)
|
||||||
|
assert.NoError(t, err)
|
||||||
_, _, err = httpd.Loaddata(backupFilePath, "", "", http.StatusInternalServerError)
|
_, _, err = httpd.Loaddata(backupFilePath, "", "", http.StatusInternalServerError)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
err = os.Remove(backupFilePath)
|
err = os.Remove(backupFilePath)
|
||||||
|
@ -978,11 +992,14 @@ func TestHTTPSConnection(t *testing.T) {
|
||||||
client := &http.Client{
|
client := &http.Client{
|
||||||
Timeout: 5 * time.Second,
|
Timeout: 5 * time.Second,
|
||||||
}
|
}
|
||||||
_, err := client.Get("https://localhost:8443" + metricsPath)
|
resp, err := client.Get("https://localhost:8443" + metricsPath)
|
||||||
assert.Error(t, err)
|
if assert.Error(t, err) {
|
||||||
if !strings.Contains(err.Error(), "certificate is not valid") &&
|
if !strings.Contains(err.Error(), "certificate is not valid") &&
|
||||||
!strings.Contains(err.Error(), "certificate signed by unknown authority") {
|
!strings.Contains(err.Error(), "certificate signed by unknown authority") {
|
||||||
assert.Fail(t, err.Error())
|
assert.Fail(t, err.Error())
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
resp.Body.Close()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1276,7 +1293,8 @@ func TestStartQuotaScanMock(t *testing.T) {
|
||||||
req, _ = http.NewRequest(http.MethodPost, quotaScanPath, bytes.NewBuffer(userAsJSON))
|
req, _ = http.NewRequest(http.MethodPost, quotaScanPath, bytes.NewBuffer(userAsJSON))
|
||||||
rr = executeRequest(req)
|
rr = executeRequest(req)
|
||||||
checkResponseCode(t, http.StatusConflict, rr.Code)
|
checkResponseCode(t, http.StatusConflict, rr.Code)
|
||||||
sftpd.RemoveQuotaScan(user.Username)
|
err = sftpd.RemoveQuotaScan(user.Username)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
userAsJSON = getUserAsJSON(t, user)
|
userAsJSON = getUserAsJSON(t, user)
|
||||||
req, _ = http.NewRequest(http.MethodPost, quotaScanPath, bytes.NewBuffer(userAsJSON))
|
req, _ = http.NewRequest(http.MethodPost, quotaScanPath, bytes.NewBuffer(userAsJSON))
|
||||||
|
@ -1584,7 +1602,8 @@ func TestWebUserAddMock(t *testing.T) {
|
||||||
rr = executeRequest(req)
|
rr = executeRequest(req)
|
||||||
checkResponseCode(t, http.StatusOK, rr.Code)
|
checkResponseCode(t, http.StatusOK, rr.Code)
|
||||||
var users []dataprovider.User
|
var users []dataprovider.User
|
||||||
render.DecodeJSON(rr.Body, &users)
|
err := render.DecodeJSON(rr.Body, &users)
|
||||||
|
assert.NoError(t, err)
|
||||||
assert.Equal(t, 1, len(users))
|
assert.Equal(t, 1, len(users))
|
||||||
newUser := users[0]
|
newUser := users[0]
|
||||||
assert.Equal(t, user.UID, newUser.UID)
|
assert.Equal(t, user.UID, newUser.UID)
|
||||||
|
@ -1650,7 +1669,8 @@ func TestWebUserUpdateMock(t *testing.T) {
|
||||||
rr = executeRequest(req)
|
rr = executeRequest(req)
|
||||||
checkResponseCode(t, http.StatusOK, rr.Code)
|
checkResponseCode(t, http.StatusOK, rr.Code)
|
||||||
var users []dataprovider.User
|
var users []dataprovider.User
|
||||||
render.DecodeJSON(rr.Body, &users)
|
err = render.DecodeJSON(rr.Body, &users)
|
||||||
|
assert.NoError(t, err)
|
||||||
assert.Equal(t, 1, len(users))
|
assert.Equal(t, 1, len(users))
|
||||||
updateUser := users[0]
|
updateUser := users[0]
|
||||||
assert.Equal(t, user.HomeDir, updateUser.HomeDir)
|
assert.Equal(t, user.HomeDir, updateUser.HomeDir)
|
||||||
|
@ -1661,9 +1681,8 @@ func TestWebUserUpdateMock(t *testing.T) {
|
||||||
assert.Equal(t, user.GID, updateUser.GID)
|
assert.Equal(t, user.GID, updateUser.GID)
|
||||||
|
|
||||||
if val, ok := updateUser.Permissions["/otherdir"]; ok {
|
if val, ok := updateUser.Permissions["/otherdir"]; ok {
|
||||||
if !utils.IsStringInSlice(dataprovider.PermListItems, val) || !utils.IsStringInSlice(dataprovider.PermUpload, val) {
|
assert.True(t, utils.IsStringInSlice(dataprovider.PermListItems, val))
|
||||||
t.Error("permssions for /otherdir does not match")
|
assert.True(t, utils.IsStringInSlice(dataprovider.PermUpload, val))
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
assert.Fail(t, "user permissions must contains /otherdir", "actual: %v", updateUser.Permissions)
|
assert.Fail(t, "user permissions must contains /otherdir", "actual: %v", updateUser.Permissions)
|
||||||
}
|
}
|
||||||
|
@ -1672,7 +1691,8 @@ func TestWebUserUpdateMock(t *testing.T) {
|
||||||
assert.True(t, utils.IsStringInSlice(dataprovider.SSHLoginMethodKeyboardInteractive, updateUser.Filters.DeniedLoginMethods))
|
assert.True(t, utils.IsStringInSlice(dataprovider.SSHLoginMethodKeyboardInteractive, updateUser.Filters.DeniedLoginMethods))
|
||||||
assert.True(t, utils.IsStringInSlice(dataprovider.SSHLoginMethodKeyboardInteractive, updateUser.Filters.DeniedLoginMethods))
|
assert.True(t, utils.IsStringInSlice(dataprovider.SSHLoginMethodKeyboardInteractive, updateUser.Filters.DeniedLoginMethods))
|
||||||
assert.True(t, utils.IsStringInSlice(".zip", updateUser.Filters.FileExtensions[0].DeniedExtensions))
|
assert.True(t, utils.IsStringInSlice(".zip", updateUser.Filters.FileExtensions[0].DeniedExtensions))
|
||||||
req, _ = http.NewRequest(http.MethodDelete, userPath+"/"+strconv.FormatInt(user.ID, 10), nil)
|
req, err = http.NewRequest(http.MethodDelete, userPath+"/"+strconv.FormatInt(user.ID, 10), nil)
|
||||||
|
assert.NoError(t, err)
|
||||||
rr = executeRequest(req)
|
rr = executeRequest(req)
|
||||||
checkResponseCode(t, http.StatusOK, rr.Code)
|
checkResponseCode(t, http.StatusOK, rr.Code)
|
||||||
}
|
}
|
||||||
|
@ -1827,7 +1847,8 @@ func TestWebUserGCSMock(t *testing.T) {
|
||||||
rr = executeRequest(req)
|
rr = executeRequest(req)
|
||||||
checkResponseCode(t, http.StatusOK, rr.Code)
|
checkResponseCode(t, http.StatusOK, rr.Code)
|
||||||
var users []dataprovider.User
|
var users []dataprovider.User
|
||||||
render.DecodeJSON(rr.Body, &users)
|
err = render.DecodeJSON(rr.Body, &users)
|
||||||
|
assert.NoError(t, err)
|
||||||
assert.Equal(t, 1, len(users))
|
assert.Equal(t, 1, len(users))
|
||||||
updateUser := users[0]
|
updateUser := users[0]
|
||||||
assert.Equal(t, int64(1577836800000), updateUser.ExpirationDate)
|
assert.Equal(t, int64(1577836800000), updateUser.ExpirationDate)
|
||||||
|
@ -1871,11 +1892,13 @@ func TestProviderClosedMock(t *testing.T) {
|
||||||
req, _ = http.NewRequest(http.MethodPost, webUserPath+"/0", strings.NewReader(form.Encode()))
|
req, _ = http.NewRequest(http.MethodPost, webUserPath+"/0", strings.NewReader(form.Encode()))
|
||||||
rr = executeRequest(req)
|
rr = executeRequest(req)
|
||||||
checkResponseCode(t, http.StatusInternalServerError, rr.Code)
|
checkResponseCode(t, http.StatusInternalServerError, rr.Code)
|
||||||
config.LoadConfig(configDir, "")
|
err := config.LoadConfig(configDir, "")
|
||||||
|
assert.NoError(t, err)
|
||||||
providerConf := config.GetProviderConf()
|
providerConf := config.GetProviderConf()
|
||||||
providerConf.CredentialsPath = credentialsPath
|
providerConf.CredentialsPath = credentialsPath
|
||||||
os.RemoveAll(credentialsPath)
|
err = os.RemoveAll(credentialsPath)
|
||||||
err := dataprovider.Initialize(providerConf, configDir)
|
assert.NoError(t, err)
|
||||||
|
err = dataprovider.Initialize(providerConf, configDir)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
httpd.SetDataProvider(dataprovider.GetProvider())
|
httpd.SetDataProvider(dataprovider.GetProvider())
|
||||||
sftpd.SetDataProvider(dataprovider.GetProvider())
|
sftpd.SetDataProvider(dataprovider.GetProvider())
|
||||||
|
@ -1938,7 +1961,10 @@ func checkResponseCode(t *testing.T, expected, actual int) {
|
||||||
func createTestFile(path string, size int64) error {
|
func createTestFile(path string, size int64) error {
|
||||||
baseDir := filepath.Dir(path)
|
baseDir := filepath.Dir(path)
|
||||||
if _, err := os.Stat(baseDir); os.IsNotExist(err) {
|
if _, err := os.Stat(baseDir); os.IsNotExist(err) {
|
||||||
os.MkdirAll(baseDir, 0777)
|
err = os.MkdirAll(baseDir, 0777)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
content := make([]byte, size)
|
content := make([]byte, size)
|
||||||
if size > 0 {
|
if size > 0 {
|
||||||
|
|
|
@ -14,12 +14,13 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/go-chi/chi"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
|
||||||
"github.com/drakkan/sftpgo/dataprovider"
|
"github.com/drakkan/sftpgo/dataprovider"
|
||||||
"github.com/drakkan/sftpgo/sftpd"
|
"github.com/drakkan/sftpgo/sftpd"
|
||||||
"github.com/drakkan/sftpgo/utils"
|
"github.com/drakkan/sftpgo/utils"
|
||||||
"github.com/drakkan/sftpgo/vfs"
|
"github.com/drakkan/sftpgo/vfs"
|
||||||
"github.com/go-chi/chi"
|
|
||||||
"github.com/stretchr/testify/assert"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -304,8 +305,9 @@ func TestGCSWebInvalidFormFile(t *testing.T) {
|
||||||
form.Set("fs_provider", "2")
|
form.Set("fs_provider", "2")
|
||||||
req, _ := http.NewRequest(http.MethodPost, webUserPath, strings.NewReader(form.Encode()))
|
req, _ := http.NewRequest(http.MethodPost, webUserPath, strings.NewReader(form.Encode()))
|
||||||
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
|
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
|
||||||
req.ParseForm()
|
err := req.ParseForm()
|
||||||
_, err := getFsConfigFromUserPostFields(req)
|
assert.NoError(t, err)
|
||||||
|
_, err = getFsConfigFromUserPostFields(req)
|
||||||
assert.EqualError(t, err, http.ErrNotMultipart.Error())
|
assert.EqualError(t, err, http.ErrNotMultipart.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -370,9 +372,10 @@ func TestBasicAuth(t *testing.T) {
|
||||||
oldAuthPassword := authPassword
|
oldAuthPassword := authPassword
|
||||||
authUserFile := filepath.Join(os.TempDir(), "http_users.txt")
|
authUserFile := filepath.Join(os.TempDir(), "http_users.txt")
|
||||||
authUserData := []byte("test1:$2y$05$bcHSED7aO1cfLto6ZdDBOOKzlwftslVhtpIkRhAtSa4GuLmk5mola\n")
|
authUserData := []byte("test1:$2y$05$bcHSED7aO1cfLto6ZdDBOOKzlwftslVhtpIkRhAtSa4GuLmk5mola\n")
|
||||||
ioutil.WriteFile(authUserFile, authUserData, 0666)
|
err := ioutil.WriteFile(authUserFile, authUserData, 0666)
|
||||||
|
assert.NoError(t, err)
|
||||||
httpAuth, _ = newBasicAuthProvider(authUserFile)
|
httpAuth, _ = newBasicAuthProvider(authUserFile)
|
||||||
_, _, err := GetVersion(http.StatusUnauthorized)
|
_, _, err = GetVersion(http.StatusUnauthorized)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
SetBaseURLAndCredentials(httpBaseURL, "test1", "password1")
|
SetBaseURLAndCredentials(httpBaseURL, "test1", "password1")
|
||||||
_, _, err = GetVersion(http.StatusOK)
|
_, _, err = GetVersion(http.StatusOK)
|
||||||
|
@ -391,12 +394,14 @@ func TestBasicAuth(t *testing.T) {
|
||||||
_, _, err = GetVersion(http.StatusOK)
|
_, _, err = GetVersion(http.StatusOK)
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
authUserData = append(authUserData, []byte("test3:$apr1$gLnIkRIf$Xr/6$aJfmIr$ihP4b2N2tcs/\n")...)
|
authUserData = append(authUserData, []byte("test3:$apr1$gLnIkRIf$Xr/6$aJfmIr$ihP4b2N2tcs/\n")...)
|
||||||
ioutil.WriteFile(authUserFile, authUserData, 0666)
|
err = ioutil.WriteFile(authUserFile, authUserData, 0666)
|
||||||
|
assert.NoError(t, err)
|
||||||
SetBaseURLAndCredentials(httpBaseURL, "test3", "wrong_password")
|
SetBaseURLAndCredentials(httpBaseURL, "test3", "wrong_password")
|
||||||
_, _, err = GetVersion(http.StatusUnauthorized)
|
_, _, err = GetVersion(http.StatusUnauthorized)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
authUserData = append(authUserData, []byte("test4:$invalid$gLnIkRIf$Xr/6$aJfmIr$ihP4b2N2tcs/\n")...)
|
authUserData = append(authUserData, []byte("test4:$invalid$gLnIkRIf$Xr/6$aJfmIr$ihP4b2N2tcs/\n")...)
|
||||||
ioutil.WriteFile(authUserFile, authUserData, 0666)
|
err = ioutil.WriteFile(authUserFile, authUserData, 0666)
|
||||||
|
assert.NoError(t, err)
|
||||||
SetBaseURLAndCredentials(httpBaseURL, "test3", "password2")
|
SetBaseURLAndCredentials(httpBaseURL, "test3", "password2")
|
||||||
_, _, err = GetVersion(http.StatusUnauthorized)
|
_, _, err = GetVersion(http.StatusUnauthorized)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
|
@ -4,14 +4,15 @@ import (
|
||||||
"net/http"
|
"net/http"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/drakkan/sftpgo/dataprovider"
|
|
||||||
"github.com/drakkan/sftpgo/logger"
|
|
||||||
"github.com/drakkan/sftpgo/sftpd"
|
|
||||||
"github.com/drakkan/sftpgo/utils"
|
|
||||||
"github.com/go-chi/chi"
|
"github.com/go-chi/chi"
|
||||||
"github.com/go-chi/chi/middleware"
|
"github.com/go-chi/chi/middleware"
|
||||||
"github.com/go-chi/render"
|
"github.com/go-chi/render"
|
||||||
"github.com/prometheus/client_golang/prometheus/promhttp"
|
"github.com/prometheus/client_golang/prometheus/promhttp"
|
||||||
|
|
||||||
|
"github.com/drakkan/sftpgo/dataprovider"
|
||||||
|
"github.com/drakkan/sftpgo/logger"
|
||||||
|
"github.com/drakkan/sftpgo/sftpd"
|
||||||
|
"github.com/drakkan/sftpgo/utils"
|
||||||
)
|
)
|
||||||
|
|
||||||
// GetHTTPRouter returns the configured HTTP handler
|
// GetHTTPRouter returns the configured HTTP handler
|
||||||
|
|
|
@ -13,11 +13,12 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/go-chi/chi"
|
||||||
|
|
||||||
"github.com/drakkan/sftpgo/dataprovider"
|
"github.com/drakkan/sftpgo/dataprovider"
|
||||||
"github.com/drakkan/sftpgo/sftpd"
|
"github.com/drakkan/sftpgo/sftpd"
|
||||||
"github.com/drakkan/sftpgo/utils"
|
"github.com/drakkan/sftpgo/utils"
|
||||||
"github.com/drakkan/sftpgo/vfs"
|
"github.com/drakkan/sftpgo/vfs"
|
||||||
"github.com/go-chi/chi"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
|
|
@ -5,9 +5,10 @@ import (
|
||||||
"net/http"
|
"net/http"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/drakkan/sftpgo/metrics"
|
|
||||||
"github.com/go-chi/chi/middleware"
|
"github.com/go-chi/chi/middleware"
|
||||||
"github.com/rs/zerolog"
|
"github.com/rs/zerolog"
|
||||||
|
|
||||||
|
"github.com/drakkan/sftpgo/metrics"
|
||||||
)
|
)
|
||||||
|
|
||||||
// StructuredLogger defines a simple wrapper around zerolog logger.
|
// StructuredLogger defines a simple wrapper around zerolog logger.
|
||||||
|
|
3
main.go
3
main.go
|
@ -4,10 +4,11 @@
|
||||||
package main // import "github.com/drakkan/sftpgo"
|
package main // import "github.com/drakkan/sftpgo"
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/drakkan/sftpgo/cmd"
|
|
||||||
_ "github.com/go-sql-driver/mysql"
|
_ "github.com/go-sql-driver/mysql"
|
||||||
_ "github.com/lib/pq"
|
_ "github.com/lib/pq"
|
||||||
_ "github.com/mattn/go-sqlite3"
|
_ "github.com/mattn/go-sqlite3"
|
||||||
|
|
||||||
|
"github.com/drakkan/sftpgo/cmd"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
|
|
@ -11,14 +11,15 @@ import (
|
||||||
"syscall"
|
"syscall"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/grandcat/zeroconf"
|
||||||
|
"github.com/rs/zerolog"
|
||||||
|
|
||||||
"github.com/drakkan/sftpgo/config"
|
"github.com/drakkan/sftpgo/config"
|
||||||
"github.com/drakkan/sftpgo/dataprovider"
|
"github.com/drakkan/sftpgo/dataprovider"
|
||||||
"github.com/drakkan/sftpgo/httpd"
|
"github.com/drakkan/sftpgo/httpd"
|
||||||
"github.com/drakkan/sftpgo/logger"
|
"github.com/drakkan/sftpgo/logger"
|
||||||
"github.com/drakkan/sftpgo/sftpd"
|
"github.com/drakkan/sftpgo/sftpd"
|
||||||
"github.com/drakkan/sftpgo/utils"
|
"github.com/drakkan/sftpgo/utils"
|
||||||
"github.com/grandcat/zeroconf"
|
|
||||||
"github.com/rs/zerolog"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
|
|
@ -7,13 +7,13 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/drakkan/sftpgo/dataprovider"
|
|
||||||
"github.com/drakkan/sftpgo/httpd"
|
|
||||||
"github.com/drakkan/sftpgo/logger"
|
|
||||||
|
|
||||||
"golang.org/x/sys/windows/svc"
|
"golang.org/x/sys/windows/svc"
|
||||||
"golang.org/x/sys/windows/svc/eventlog"
|
"golang.org/x/sys/windows/svc/eventlog"
|
||||||
"golang.org/x/sys/windows/svc/mgr"
|
"golang.org/x/sys/windows/svc/mgr"
|
||||||
|
|
||||||
|
"github.com/drakkan/sftpgo/dataprovider"
|
||||||
|
"github.com/drakkan/sftpgo/httpd"
|
||||||
|
"github.com/drakkan/sftpgo/logger"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
|
|
@ -8,13 +8,12 @@ import (
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/drakkan/sftpgo/vfs"
|
"github.com/pkg/sftp"
|
||||||
"golang.org/x/crypto/ssh"
|
"golang.org/x/crypto/ssh"
|
||||||
|
|
||||||
"github.com/drakkan/sftpgo/dataprovider"
|
"github.com/drakkan/sftpgo/dataprovider"
|
||||||
"github.com/drakkan/sftpgo/logger"
|
"github.com/drakkan/sftpgo/logger"
|
||||||
|
"github.com/drakkan/sftpgo/vfs"
|
||||||
"github.com/pkg/sftp"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Connection details for an authenticated user
|
// Connection details for an authenticated user
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -5,15 +5,13 @@ package sftpd
|
||||||
import (
|
import (
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestWrapCmd(t *testing.T) {
|
func TestWrapCmd(t *testing.T) {
|
||||||
cmd := exec.Command("ls")
|
cmd := exec.Command("ls")
|
||||||
cmd = wrapCmd(cmd, 1000, 1001)
|
cmd = wrapCmd(cmd, 1000, 1001)
|
||||||
if cmd.SysProcAttr.Credential.Uid != 1000 {
|
assert.Equal(t, uint32(1000), cmd.SysProcAttr.Credential.Uid)
|
||||||
t.Errorf("unexpected uid")
|
assert.Equal(t, uint32(1001), cmd.SysProcAttr.Credential.Gid)
|
||||||
}
|
|
||||||
if cmd.SysProcAttr.Credential.Gid != 1001 {
|
|
||||||
t.Errorf("unexpected gid")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,13 +13,14 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/pires/go-proxyproto"
|
||||||
|
"github.com/pkg/sftp"
|
||||||
|
"golang.org/x/crypto/ssh"
|
||||||
|
|
||||||
"github.com/drakkan/sftpgo/dataprovider"
|
"github.com/drakkan/sftpgo/dataprovider"
|
||||||
"github.com/drakkan/sftpgo/logger"
|
"github.com/drakkan/sftpgo/logger"
|
||||||
"github.com/drakkan/sftpgo/metrics"
|
"github.com/drakkan/sftpgo/metrics"
|
||||||
"github.com/drakkan/sftpgo/utils"
|
"github.com/drakkan/sftpgo/utils"
|
||||||
"github.com/pires/go-proxyproto"
|
|
||||||
"github.com/pkg/sftp"
|
|
||||||
"golang.org/x/crypto/ssh"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
|
|
@ -49,7 +49,7 @@ const (
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
uploadModeStandard = iota //nolint:varcheck,deadcode
|
uploadModeStandard = iota
|
||||||
uploadModeAtomic
|
uploadModeAtomic
|
||||||
uploadModeAtomicWithResume
|
uploadModeAtomicWithResume
|
||||||
)
|
)
|
||||||
|
|
4640
sftpd/sftpd_test.go
4640
sftpd/sftpd_test.go
File diff suppressed because it is too large
Load diff
|
@ -15,13 +15,14 @@ import (
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/google/shlex"
|
||||||
|
"golang.org/x/crypto/ssh"
|
||||||
|
|
||||||
"github.com/drakkan/sftpgo/dataprovider"
|
"github.com/drakkan/sftpgo/dataprovider"
|
||||||
"github.com/drakkan/sftpgo/logger"
|
"github.com/drakkan/sftpgo/logger"
|
||||||
"github.com/drakkan/sftpgo/metrics"
|
"github.com/drakkan/sftpgo/metrics"
|
||||||
"github.com/drakkan/sftpgo/utils"
|
"github.com/drakkan/sftpgo/utils"
|
||||||
"github.com/drakkan/sftpgo/vfs"
|
"github.com/drakkan/sftpgo/vfs"
|
||||||
"github.com/google/shlex"
|
|
||||||
"golang.org/x/crypto/ssh"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const scpCmdName = "scp"
|
const scpCmdName = "scp"
|
||||||
|
|
|
@ -8,10 +8,11 @@ import (
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/eikenb/pipeat"
|
||||||
|
|
||||||
"github.com/drakkan/sftpgo/dataprovider"
|
"github.com/drakkan/sftpgo/dataprovider"
|
||||||
"github.com/drakkan/sftpgo/logger"
|
"github.com/drakkan/sftpgo/logger"
|
||||||
"github.com/drakkan/sftpgo/metrics"
|
"github.com/drakkan/sftpgo/metrics"
|
||||||
"github.com/eikenb/pipeat"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
|
|
@ -24,8 +24,9 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/drakkan/sftpgo/logger"
|
|
||||||
"golang.org/x/crypto/ssh"
|
"golang.org/x/crypto/ssh"
|
||||||
|
|
||||||
|
"github.com/drakkan/sftpgo/logger"
|
||||||
)
|
)
|
||||||
|
|
||||||
const logSender = "utils"
|
const logSender = "utils"
|
||||||
|
|
|
@ -12,12 +12,13 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"cloud.google.com/go/storage"
|
"cloud.google.com/go/storage"
|
||||||
"github.com/drakkan/sftpgo/logger"
|
|
||||||
"github.com/drakkan/sftpgo/metrics"
|
|
||||||
"github.com/eikenb/pipeat"
|
"github.com/eikenb/pipeat"
|
||||||
"google.golang.org/api/googleapi"
|
"google.golang.org/api/googleapi"
|
||||||
"google.golang.org/api/iterator"
|
"google.golang.org/api/iterator"
|
||||||
"google.golang.org/api/option"
|
"google.golang.org/api/option"
|
||||||
|
|
||||||
|
"github.com/drakkan/sftpgo/logger"
|
||||||
|
"github.com/drakkan/sftpgo/metrics"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
|
|
@ -8,10 +8,11 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/drakkan/sftpgo/logger"
|
|
||||||
"github.com/drakkan/sftpgo/utils"
|
|
||||||
"github.com/eikenb/pipeat"
|
"github.com/eikenb/pipeat"
|
||||||
"github.com/rs/xid"
|
"github.com/rs/xid"
|
||||||
|
|
||||||
|
"github.com/drakkan/sftpgo/logger"
|
||||||
|
"github.com/drakkan/sftpgo/utils"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
|
|
@ -15,10 +15,11 @@ import (
|
||||||
"github.com/aws/aws-sdk-go/aws/session"
|
"github.com/aws/aws-sdk-go/aws/session"
|
||||||
"github.com/aws/aws-sdk-go/service/s3"
|
"github.com/aws/aws-sdk-go/service/s3"
|
||||||
"github.com/aws/aws-sdk-go/service/s3/s3manager"
|
"github.com/aws/aws-sdk-go/service/s3/s3manager"
|
||||||
|
"github.com/eikenb/pipeat"
|
||||||
|
|
||||||
"github.com/drakkan/sftpgo/logger"
|
"github.com/drakkan/sftpgo/logger"
|
||||||
"github.com/drakkan/sftpgo/metrics"
|
"github.com/drakkan/sftpgo/metrics"
|
||||||
"github.com/drakkan/sftpgo/utils"
|
"github.com/drakkan/sftpgo/utils"
|
||||||
"github.com/eikenb/pipeat"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// S3FsConfig defines the configuration for S3 based filesystem
|
// S3FsConfig defines the configuration for S3 based filesystem
|
||||||
|
|
|
@ -10,9 +10,10 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/drakkan/sftpgo/logger"
|
|
||||||
"github.com/eikenb/pipeat"
|
"github.com/eikenb/pipeat"
|
||||||
"github.com/pkg/sftp"
|
"github.com/pkg/sftp"
|
||||||
|
|
||||||
|
"github.com/drakkan/sftpgo/logger"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Fs defines the interface for filesystem backends
|
// Fs defines the interface for filesystem backends
|
||||||
|
|
Loading…
Reference in a new issue