don't execute fs check if the user has recent activity
The check could be expensive with some backends and is generally only required the first time that a user logs in Signed-off-by: Nicola Murino <nicola.murino@gmail.com>
This commit is contained in:
parent
670018f05e
commit
f5a0559be6
16 changed files with 355 additions and 156 deletions
|
@ -881,6 +881,39 @@ func TestGetTLSVersion(t *testing.T) {
|
|||
assert.Equal(t, uint16(tls.VersionTLS13), tlsVer)
|
||||
}
|
||||
|
||||
func TestCleanPath(t *testing.T) {
|
||||
assert.Equal(t, "/", util.CleanPath("/"))
|
||||
assert.Equal(t, "/", util.CleanPath("."))
|
||||
assert.Equal(t, "/", util.CleanPath("/."))
|
||||
assert.Equal(t, "/", util.CleanPath("/a/.."))
|
||||
assert.Equal(t, "/a", util.CleanPath("/a/"))
|
||||
assert.Equal(t, "/a", util.CleanPath("a/"))
|
||||
// filepath.ToSlash does not touch \ as char on unix systems
|
||||
// so os.PathSeparator is used for windows compatible tests
|
||||
bslash := string(os.PathSeparator)
|
||||
assert.Equal(t, "/", util.CleanPath(bslash))
|
||||
assert.Equal(t, "/", util.CleanPath(bslash+bslash))
|
||||
assert.Equal(t, "/a", util.CleanPath(bslash+"a"+bslash))
|
||||
assert.Equal(t, "/a", util.CleanPath("a"+bslash))
|
||||
assert.Equal(t, "/a/b/c", util.CleanPath(bslash+"a"+bslash+bslash+"b"+bslash+bslash+"c"+bslash))
|
||||
assert.Equal(t, "/C:/a", util.CleanPath("C:"+bslash+"a"))
|
||||
}
|
||||
|
||||
func TestUserRecentActivity(t *testing.T) {
|
||||
u := dataprovider.User{}
|
||||
res := u.HasRecentActivity()
|
||||
assert.False(t, res)
|
||||
u.LastLogin = util.GetTimeAsMsSinceEpoch(time.Now())
|
||||
res = u.HasRecentActivity()
|
||||
assert.True(t, res)
|
||||
u.LastLogin = util.GetTimeAsMsSinceEpoch(time.Now().Add(1 * time.Minute))
|
||||
res = u.HasRecentActivity()
|
||||
assert.False(t, res)
|
||||
u.LastLogin = util.GetTimeAsMsSinceEpoch(time.Now().Add(1 * time.Second))
|
||||
res = u.HasRecentActivity()
|
||||
assert.True(t, res)
|
||||
}
|
||||
|
||||
func BenchmarkBcryptHashing(b *testing.B) {
|
||||
bcryptPassword := "bcryptpassword"
|
||||
for i := 0; i < b.N; i++ {
|
||||
|
|
|
@ -837,13 +837,16 @@ func TestTruncateQuotaLimits(t *testing.T) {
|
|||
// cleanup
|
||||
err = os.RemoveAll(user.GetHomeDir())
|
||||
assert.NoError(t, err)
|
||||
user.UsedQuotaFiles = 0
|
||||
user.UsedQuotaSize = 0
|
||||
_, err = httpdtest.UpdateQuotaUsage(user, "reset", http.StatusOK)
|
||||
assert.NoError(t, err)
|
||||
user.QuotaSize = 0
|
||||
_, _, err = httpdtest.UpdateUser(user, http.StatusOK, "")
|
||||
assert.NoError(t, err)
|
||||
if user.Username == defaultUsername {
|
||||
_, err = httpdtest.RemoveUser(user, http.StatusOK)
|
||||
assert.NoError(t, err)
|
||||
user.Password = defaultPassword
|
||||
user.QuotaSize = 0
|
||||
user.ID = 0
|
||||
user.CreatedAt = 0
|
||||
_, resp, err := httpdtest.AddUser(user, http.StatusCreated)
|
||||
assert.NoError(t, err, string(resp))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1122,9 +1122,7 @@ func UpdateAPIKeyLastUse(apiKey *APIKey) error {
|
|||
|
||||
// UpdateLastLogin updates the last login field for the given SFTPGo user
|
||||
func UpdateLastLogin(user *User) {
|
||||
lastLogin := util.GetTimeFromMsecSinceEpoch(user.LastLogin)
|
||||
diff := -time.Until(lastLogin)
|
||||
if diff < 0 || diff > lastLoginMinDelay {
|
||||
if !isLastActivityRecent(user.LastLogin) {
|
||||
err := provider.updateLastLogin(user.Username)
|
||||
if err == nil {
|
||||
webDAVUsersCache.updateLastLogin(user.Username)
|
||||
|
@ -1134,9 +1132,7 @@ func UpdateLastLogin(user *User) {
|
|||
|
||||
// UpdateAdminLastLogin updates the last login field for the given SFTPGo admin
|
||||
func UpdateAdminLastLogin(admin *Admin) {
|
||||
lastLogin := util.GetTimeFromMsecSinceEpoch(admin.LastLogin)
|
||||
diff := -time.Until(lastLogin)
|
||||
if diff < 0 || diff > lastLoginMinDelay {
|
||||
if !isLastActivityRecent(admin.LastLogin) {
|
||||
provider.updateAdminLastLogin(admin.Username) //nolint:errcheck
|
||||
}
|
||||
}
|
||||
|
@ -3375,3 +3371,12 @@ func getUserAndJSONForHook(username string) (User, []byte, error) {
|
|||
func providerLog(level logger.LogLevel, format string, v ...interface{}) {
|
||||
logger.Log(level, logSender, "", format, v...)
|
||||
}
|
||||
|
||||
func isLastActivityRecent(lastActivity int64) bool {
|
||||
lastActivityTime := util.GetTimeFromMsecSinceEpoch(lastActivity)
|
||||
diff := -time.Until(lastActivityTime)
|
||||
if diff < -10*time.Second {
|
||||
return false
|
||||
}
|
||||
return diff < lastLoginMinDelay
|
||||
}
|
||||
|
|
|
@ -161,12 +161,51 @@ func (u *User) getRootFs(connectionID string) (fs vfs.Fs, err error) {
|
|||
}
|
||||
}
|
||||
|
||||
func (u *User) checkDirWithParents(virtualDirPath, connectionID string) error {
|
||||
dirs := util.GetDirsForVirtualPath(virtualDirPath)
|
||||
for idx := len(dirs) - 1; idx >= 0; idx-- {
|
||||
vPath := dirs[idx]
|
||||
if vPath == "/" {
|
||||
continue
|
||||
}
|
||||
fs, err := u.GetFilesystemForPath(vPath, connectionID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to get fs for path %#v: %w", vPath, err)
|
||||
}
|
||||
if fs.HasVirtualFolders() {
|
||||
continue
|
||||
}
|
||||
fsPath, err := fs.ResolvePath(vPath)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to resolve path %#v: %w", vPath, err)
|
||||
}
|
||||
_, err = fs.Stat(fsPath)
|
||||
if err == nil {
|
||||
continue
|
||||
}
|
||||
if fs.IsNotExist(err) {
|
||||
err = fs.Mkdir(fsPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
vfs.SetPathPermissions(fs, fsPath, u.GetUID(), u.GetGID())
|
||||
} else {
|
||||
return fmt.Errorf("unable to stat path %#v: %w", vPath, err)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// CheckFsRoot check the root directory for the main fs and the virtual folders.
|
||||
// It returns an error if the main filesystem cannot be created
|
||||
func (u *User) CheckFsRoot(connectionID string) error {
|
||||
if u.Filters.DisableFsChecks {
|
||||
return nil
|
||||
}
|
||||
if isLastActivityRecent(u.LastLogin) {
|
||||
return nil
|
||||
}
|
||||
fs, err := u.GetFilesystemForPath("/", connectionID)
|
||||
if err != nil {
|
||||
logger.Warn(logSender, connectionID, "could not create main filesystem for user %#v err: %v", u.Username, err)
|
||||
|
@ -180,15 +219,9 @@ func (u *User) CheckFsRoot(connectionID string) error {
|
|||
fs.CheckRootPath(u.Username, u.GetUID(), u.GetGID())
|
||||
}
|
||||
// now check intermediary folders
|
||||
fs, err = u.GetFilesystemForPath(path.Dir(v.VirtualPath), connectionID)
|
||||
if err == nil && !fs.HasVirtualFolders() {
|
||||
fsPath, err := fs.ResolvePath(v.VirtualPath)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
err = fs.MkdirAll(fsPath, u.GetUID(), u.GetGID())
|
||||
logger.Debug(logSender, connectionID, "create intermediary dir to %#v, path %#v, err: %v",
|
||||
v.VirtualPath, fsPath, err)
|
||||
err = u.checkDirWithParents(path.Dir(v.VirtualPath), connectionID)
|
||||
if err != nil {
|
||||
logger.Warn(logSender, connectionID, "could not create intermediary dir to %#v, err: %v", v.VirtualPath, err)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
|
@ -1071,6 +1104,11 @@ func (u *User) GetHomeDir() string {
|
|||
return filepath.Clean(u.HomeDir)
|
||||
}
|
||||
|
||||
// HasRecentActivity returns true if the last user login is recent and so we can skip some expensive checks
|
||||
func (u *User) HasRecentActivity() bool {
|
||||
return isLastActivityRecent(u.LastLogin)
|
||||
}
|
||||
|
||||
// HasQuotaRestrictions returns true if there are any disk quota restrictions
|
||||
func (u *User) HasQuotaRestrictions() bool {
|
||||
return u.QuotaFiles > 0 || u.QuotaSize > 0
|
||||
|
|
|
@ -1433,6 +1433,13 @@ func TestResume(t *testing.T) {
|
|||
if user.Username == defaultUsername {
|
||||
err = os.RemoveAll(user.GetHomeDir())
|
||||
assert.NoError(t, err)
|
||||
_, err = httpdtest.RemoveUser(user, http.StatusOK)
|
||||
assert.NoError(t, err)
|
||||
user.Password = defaultPassword
|
||||
user.ID = 0
|
||||
user.CreatedAt = 0
|
||||
_, resp, err := httpdtest.AddUser(user, http.StatusCreated)
|
||||
assert.NoError(t, err, string(resp))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1579,8 +1586,14 @@ func TestQuotaLimits(t *testing.T) {
|
|||
assert.NoError(t, err)
|
||||
user.QuotaFiles = 0
|
||||
user.QuotaSize = 0
|
||||
_, _, err = httpdtest.UpdateUser(user, http.StatusOK, "")
|
||||
_, err = httpdtest.RemoveUser(user, http.StatusOK)
|
||||
assert.NoError(t, err)
|
||||
user.Password = defaultPassword
|
||||
user.QuotaSize = 0
|
||||
user.ID = 0
|
||||
user.CreatedAt = 0
|
||||
_, resp, err := httpdtest.AddUser(user, http.StatusCreated)
|
||||
assert.NoError(t, err, string(resp))
|
||||
}
|
||||
}
|
||||
_, err = httpdtest.RemoveUser(sftpUser, http.StatusOK)
|
||||
|
@ -1631,9 +1644,14 @@ func TestUploadMaxSize(t *testing.T) {
|
|||
if user.Username == defaultUsername {
|
||||
err = os.RemoveAll(user.GetHomeDir())
|
||||
assert.NoError(t, err)
|
||||
user.Filters.MaxUploadFileSize = 65536000
|
||||
_, _, err = httpdtest.UpdateUser(user, http.StatusOK, "")
|
||||
_, err = httpdtest.RemoveUser(user, http.StatusOK)
|
||||
assert.NoError(t, err)
|
||||
user.Password = defaultPassword
|
||||
user.Filters.MaxUploadFileSize = 65536000
|
||||
user.ID = 0
|
||||
user.CreatedAt = 0
|
||||
_, resp, err := httpdtest.AddUser(user, http.StatusCreated)
|
||||
assert.NoError(t, err, string(resp))
|
||||
}
|
||||
}
|
||||
_, err = httpdtest.RemoveUser(sftpUser, http.StatusOK)
|
||||
|
@ -1823,12 +1841,17 @@ func TestRename(t *testing.T) {
|
|||
err = os.Remove(testFilePath)
|
||||
assert.NoError(t, err)
|
||||
if user.Username == defaultUsername {
|
||||
user.Permissions = make(map[string][]string)
|
||||
user.Permissions["/"] = allPerms
|
||||
user, _, err = httpdtest.UpdateUser(user, http.StatusOK, "")
|
||||
assert.NoError(t, err)
|
||||
err = os.RemoveAll(user.GetHomeDir())
|
||||
assert.NoError(t, err)
|
||||
_, err = httpdtest.RemoveUser(user, http.StatusOK)
|
||||
assert.NoError(t, err)
|
||||
user.Permissions = make(map[string][]string)
|
||||
user.Permissions["/"] = allPerms
|
||||
user.Password = defaultPassword
|
||||
user.ID = 0
|
||||
user.CreatedAt = 0
|
||||
_, resp, err := httpdtest.AddUser(user, http.StatusCreated)
|
||||
assert.NoError(t, err, string(resp))
|
||||
}
|
||||
}
|
||||
_, err = httpdtest.RemoveUser(sftpUser, http.StatusOK)
|
||||
|
@ -1885,6 +1908,13 @@ func TestSymlink(t *testing.T) {
|
|||
if user.Username == defaultUsername {
|
||||
err = os.RemoveAll(user.GetHomeDir())
|
||||
assert.NoError(t, err)
|
||||
_, err = httpdtest.RemoveUser(user, http.StatusOK)
|
||||
assert.NoError(t, err)
|
||||
user.Password = defaultPassword
|
||||
user.ID = 0
|
||||
user.CreatedAt = 0
|
||||
_, resp, err := httpdtest.AddUser(user, http.StatusCreated)
|
||||
assert.NoError(t, err, string(resp))
|
||||
}
|
||||
}
|
||||
err = os.Remove(testFilePath)
|
||||
|
@ -1935,6 +1965,13 @@ func TestStat(t *testing.T) {
|
|||
if user.Username == defaultUsername {
|
||||
err = os.RemoveAll(user.GetHomeDir())
|
||||
assert.NoError(t, err)
|
||||
_, err = httpdtest.RemoveUser(user, http.StatusOK)
|
||||
assert.NoError(t, err)
|
||||
user.Password = defaultPassword
|
||||
user.ID = 0
|
||||
user.CreatedAt = 0
|
||||
_, resp, err := httpdtest.AddUser(user, http.StatusCreated)
|
||||
assert.NoError(t, err, string(resp))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2284,6 +2321,13 @@ func TestChtimes(t *testing.T) {
|
|||
if user.Username == defaultUsername {
|
||||
err = os.RemoveAll(user.GetHomeDir())
|
||||
assert.NoError(t, err)
|
||||
_, err = httpdtest.RemoveUser(user, http.StatusOK)
|
||||
assert.NoError(t, err)
|
||||
user.Password = defaultPassword
|
||||
user.ID = 0
|
||||
user.CreatedAt = 0
|
||||
_, resp, err := httpdtest.AddUser(user, http.StatusCreated)
|
||||
assert.NoError(t, err, string(resp))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2366,6 +2410,13 @@ func TestChmod(t *testing.T) {
|
|||
if user.Username == defaultUsername {
|
||||
err = os.RemoveAll(user.GetHomeDir())
|
||||
assert.NoError(t, err)
|
||||
_, err = httpdtest.RemoveUser(user, http.StatusOK)
|
||||
assert.NoError(t, err)
|
||||
user.Password = defaultPassword
|
||||
user.ID = 0
|
||||
user.CreatedAt = 0
|
||||
_, resp, err := httpdtest.AddUser(user, http.StatusCreated)
|
||||
assert.NoError(t, err, string(resp))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2523,6 +2574,13 @@ func TestHASH(t *testing.T) {
|
|||
if user.Username == defaultUsername {
|
||||
err = os.RemoveAll(user.GetHomeDir())
|
||||
assert.NoError(t, err)
|
||||
_, err = httpdtest.RemoveUser(user, http.StatusOK)
|
||||
assert.NoError(t, err)
|
||||
user.Password = defaultPassword
|
||||
user.ID = 0
|
||||
user.CreatedAt = 0
|
||||
_, resp, err := httpdtest.AddUser(user, http.StatusCreated)
|
||||
assert.NoError(t, err, string(resp))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2577,6 +2635,13 @@ func TestCombine(t *testing.T) {
|
|||
if user.Username == defaultUsername {
|
||||
err = os.RemoveAll(user.GetHomeDir())
|
||||
assert.NoError(t, err)
|
||||
_, err = httpdtest.RemoveUser(user, http.StatusOK)
|
||||
assert.NoError(t, err)
|
||||
user.Password = defaultPassword
|
||||
user.ID = 0
|
||||
user.CreatedAt = 0
|
||||
_, resp, err := httpdtest.AddUser(user, http.StatusCreated)
|
||||
assert.NoError(t, err, string(resp))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
18
go.mod
18
go.mod
|
@ -8,7 +8,7 @@ require (
|
|||
github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v0.3.0
|
||||
github.com/GehirnInc/crypt v0.0.0-20200316065508-bb7000b8a962
|
||||
github.com/alexedwards/argon2id v0.0.0-20211130144151-3585854a6387
|
||||
github.com/aws/aws-sdk-go v1.43.2
|
||||
github.com/aws/aws-sdk-go v1.43.5
|
||||
github.com/cockroachdb/cockroach-go/v2 v2.2.8
|
||||
github.com/coreos/go-oidc/v3 v3.1.0
|
||||
github.com/eikenb/pipeat v0.0.0-20210730190139-06b3e6902001
|
||||
|
@ -26,8 +26,8 @@ require (
|
|||
github.com/hashicorp/go-plugin v1.4.3
|
||||
github.com/hashicorp/go-retryablehttp v0.7.0
|
||||
github.com/jlaffaye/ftp v0.0.0-20201112195030-9aae4d151126
|
||||
github.com/klauspost/compress v1.14.3
|
||||
github.com/lestrrat-go/jwx v1.2.18
|
||||
github.com/klauspost/compress v1.14.4
|
||||
github.com/lestrrat-go/jwx v1.2.19
|
||||
github.com/lib/pq v1.10.4
|
||||
github.com/lithammer/shortuuid/v3 v3.0.7
|
||||
github.com/mattn/go-sqlite3 v1.14.11
|
||||
|
@ -57,16 +57,16 @@ require (
|
|||
gocloud.dev v0.24.0
|
||||
golang.org/x/crypto v0.0.0-20220214200702-86341886e292
|
||||
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd
|
||||
golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8
|
||||
golang.org/x/sys v0.0.0-20220209214540-3681064d5158
|
||||
golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b
|
||||
golang.org/x/sys v0.0.0-20220224120231-95c6836cb0e7
|
||||
golang.org/x/time v0.0.0-20220210224613-90d013bbcef8
|
||||
google.golang.org/api v0.69.0
|
||||
google.golang.org/api v0.70.0
|
||||
gopkg.in/natefinch/lumberjack.v2 v2.0.0
|
||||
)
|
||||
|
||||
require (
|
||||
cloud.google.com/go v0.100.2 // indirect
|
||||
cloud.google.com/go/compute v1.3.0 // indirect
|
||||
cloud.google.com/go/compute v1.5.0 // indirect
|
||||
cloud.google.com/go/iam v0.2.0 // indirect
|
||||
github.com/Azure/azure-sdk-for-go/sdk/internal v0.9.1 // indirect
|
||||
github.com/beorn7/perks v1.0.1 // indirect
|
||||
|
@ -98,7 +98,7 @@ require (
|
|||
github.com/lestrrat-go/iter v1.0.1 // indirect
|
||||
github.com/lestrrat-go/option v1.0.0 // indirect
|
||||
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect
|
||||
github.com/magiconair/properties v1.8.5 // indirect
|
||||
github.com/magiconair/properties v1.8.6 // indirect
|
||||
github.com/mattn/go-colorable v0.1.12 // indirect
|
||||
github.com/mattn/go-isatty v0.0.14 // indirect
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect
|
||||
|
@ -128,7 +128,7 @@ require (
|
|||
golang.org/x/tools v0.1.9 // indirect
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect
|
||||
google.golang.org/appengine v1.6.7 // indirect
|
||||
google.golang.org/genproto v0.0.0-20220218161850-94dd64e39d7c // indirect
|
||||
google.golang.org/genproto v0.0.0-20220222213610-43724f9ea8cf // indirect
|
||||
google.golang.org/grpc v1.44.0 // indirect
|
||||
google.golang.org/protobuf v1.27.1 // indirect
|
||||
gopkg.in/ini.v1 v1.66.4 // indirect
|
||||
|
|
30
go.sum
30
go.sum
|
@ -47,8 +47,9 @@ cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4g
|
|||
cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ=
|
||||
cloud.google.com/go/compute v0.1.0/go.mod h1:GAesmwr110a34z04OlxYkATPBEfVhkymfTBXtfbBFow=
|
||||
cloud.google.com/go/compute v1.2.0/go.mod h1:xlogom/6gr8RJGBe7nT2eGsQYAFUbbv8dbC29qE3Xmw=
|
||||
cloud.google.com/go/compute v1.3.0 h1:mPL/MzDDYHsh5tHRS9mhmhWlcgClCrCa6ApQCU6wnHI=
|
||||
cloud.google.com/go/compute v1.3.0/go.mod h1:cCZiE1NHEtai4wiufUhW8I8S1JKkAnhnQJWM7YD99wM=
|
||||
cloud.google.com/go/compute v1.5.0 h1:b1zWmYuuHz7gO9kDcM/EpHGr06UgsYNRpNJzI2kFiLM=
|
||||
cloud.google.com/go/compute v1.5.0/go.mod h1:9SMHyhJlzhlkJqrPAc839t2BZFTSk6Jdj6mkzQJeu0M=
|
||||
cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE=
|
||||
cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk=
|
||||
cloud.google.com/go/firestore v1.5.0/go.mod h1:c4nNYR1qdq7eaZ+jSc5fonrQN2k3M7sWATcYTiakjEo=
|
||||
|
@ -143,8 +144,8 @@ github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgI
|
|||
github.com/aws/aws-sdk-go v1.15.27/go.mod h1:mFuSZ37Z9YOHbQEwBWztmVzqXrEkub65tZoCYDt7FT0=
|
||||
github.com/aws/aws-sdk-go v1.37.0/go.mod h1:hcU610XS61/+aQV88ixoOzUoG7v3b31pl2zKMmprdro=
|
||||
github.com/aws/aws-sdk-go v1.40.34/go.mod h1:585smgzpB/KqRA+K3y/NL/oYRqQvpNJYvLm+LY1U59Q=
|
||||
github.com/aws/aws-sdk-go v1.43.2 h1:T6LuKCNu8CYXXDn3xJoldh8FbdvuVH7C9aSuLNrlht0=
|
||||
github.com/aws/aws-sdk-go v1.43.2/go.mod h1:OGr6lGMAKGlG9CVrYnWYDKIyb829c6EVBRjxqjmPepc=
|
||||
github.com/aws/aws-sdk-go v1.43.5 h1:N7arnx54E4QyW69c45UW5o8j2DCSjzpoxzJW3yU6OSo=
|
||||
github.com/aws/aws-sdk-go v1.43.5/go.mod h1:y4AeaBuwd2Lk+GepC1E9v0qOiTws0MIWAX4oIKwKHZo=
|
||||
github.com/aws/aws-sdk-go-v2 v1.9.0/go.mod h1:cK/D0BBs0b/oWPIcX/Z/obahJK1TT7IPVjy53i/mX/4=
|
||||
github.com/aws/aws-sdk-go-v2/config v1.7.0/go.mod h1:w9+nMZ7soXCe5nT46Ri354SNhXDQ6v+V5wqDjnZE+GY=
|
||||
github.com/aws/aws-sdk-go-v2/credentials v1.4.0/go.mod h1:dgGR+Qq7Wjcd4AOAW5Rf5Tnv3+x7ed6kETXyS9WCuAY=
|
||||
|
@ -513,8 +514,8 @@ github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI
|
|||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||
github.com/klauspost/compress v1.10.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
|
||||
github.com/klauspost/compress v1.13.5/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
|
||||
github.com/klauspost/compress v1.14.3 h1:DQv1WP+iS4srNjibdnHtqu8JNWCDMluj5NzPnFJsnvk=
|
||||
github.com/klauspost/compress v1.14.3/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
|
||||
github.com/klauspost/compress v1.14.4 h1:eijASRJcobkVtSt81Olfh7JX43osYLwy5krOJo6YEu4=
|
||||
github.com/klauspost/compress v1.14.4/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
|
||||
github.com/klauspost/cpuid/v2 v2.0.4/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
|
||||
github.com/klauspost/cpuid/v2 v2.0.11 h1:i2lw1Pm7Yi/4O6XCSyJWqEHI2MDw2FzUK6o/D21xn2A=
|
||||
github.com/klauspost/cpuid/v2 v2.0.11/go.mod h1:g2LTdtYhdyuGPqyWyv7qRAmj1WBqxuObKfj5c0PQa7c=
|
||||
|
@ -543,8 +544,8 @@ github.com/lestrrat-go/httpcc v1.0.0/go.mod h1:tGS/u00Vh5N6FHNkExqGGNId8e0Big+++
|
|||
github.com/lestrrat-go/iter v1.0.1 h1:q8faalr2dY6o8bV45uwrxq12bRa1ezKrB6oM9FUgN4A=
|
||||
github.com/lestrrat-go/iter v1.0.1/go.mod h1:zIdgO1mRKhn8l9vrZJZz9TUMMFbQbLeTsbqPDrJ/OJc=
|
||||
github.com/lestrrat-go/jwx v1.2.6/go.mod h1:tJuGuAI3LC71IicTx82Mz1n3w9woAs2bYJZpkjJQ5aU=
|
||||
github.com/lestrrat-go/jwx v1.2.18 h1:RV4hcTRUlPVYUnGqATKXEojoOsLexoU8Na4KheVzxQ8=
|
||||
github.com/lestrrat-go/jwx v1.2.18/go.mod h1:bWTBO7IHHVMtNunM8so9MT8wD+euEY1PzGEyCnuI2qM=
|
||||
github.com/lestrrat-go/jwx v1.2.19 h1:qxxLmAXNwZpTTvjc4PH21nT7I4wPK6lVv3lVNcZPnUk=
|
||||
github.com/lestrrat-go/jwx v1.2.19/go.mod h1:bWTBO7IHHVMtNunM8so9MT8wD+euEY1PzGEyCnuI2qM=
|
||||
github.com/lestrrat-go/option v1.0.0 h1:WqAWL8kh8VcSoD6xjSH34/1m8yxluXQbDeKNfvFeEO4=
|
||||
github.com/lestrrat-go/option v1.0.0/go.mod h1:5ZHFbivi4xwXxhxY9XHDe2FHo6/Z7WWmtT7T5nBBp3I=
|
||||
github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
||||
|
@ -560,8 +561,9 @@ github.com/lithammer/shortuuid/v3 v3.0.7/go.mod h1:vMk8ke37EmiewwolSO1NLW8vP4ZaK
|
|||
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4=
|
||||
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I=
|
||||
github.com/lyft/protoc-gen-star v0.5.3/go.mod h1:V0xaHgaf5oCCqmcxYcWiDfTiKsZsRc87/1qhoTACD8w=
|
||||
github.com/magiconair/properties v1.8.5 h1:b6kJs+EmPFMYGkow9GiUyCyOvIwYetYJ3fSaWak/Gls=
|
||||
github.com/magiconair/properties v1.8.5/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60=
|
||||
github.com/magiconair/properties v1.8.6 h1:5ibWZ6iY0NctNGWo87LalDlEZ6R41TqbbDamhfG/Qzo=
|
||||
github.com/magiconair/properties v1.8.6/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60=
|
||||
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
|
||||
github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ=
|
||||
github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
|
||||
|
@ -854,8 +856,9 @@ golang.org/x/oauth2 v0.0.0-20210628180205-a41e5a781914/go.mod h1:KelEdhl1UZF7XfJ
|
|||
golang.org/x/oauth2 v0.0.0-20210805134026-6f1e6394065a/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||
golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||
golang.org/x/oauth2 v0.0.0-20211005180243-6b3c2da341f1/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||
golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8 h1:RerP+noqYHUQ8CMRcPlC2nvTa4dcBIjegkuWdcUDuqg=
|
||||
golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||
golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b h1:clP8eMhB30EHdc0bd2Twtq6kgU7yl5ub2cQLSdrv1Dg=
|
||||
golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
|
@ -953,8 +956,9 @@ golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBc
|
|||
golang.org/x/sys v0.0.0-20220111092808-5a964db01320/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220209214540-3681064d5158 h1:rm+CHSpPEEW2IsXUib1ThaHIjuBVZjxNgSKmBLFfD4c=
|
||||
golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220224120231-95c6836cb0e7 h1:BXxu8t6QN0G1uff4bzZzSkpsax8+ALqTGUtz08QrV00=
|
||||
golang.org/x/sys v0.0.0-20220224120231-95c6836cb0e7/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 h1:JGgROgKl9N8DuW20oFS5gxc+lE67/N3FcwmBPMe7ArY=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
|
@ -1087,8 +1091,9 @@ google.golang.org/api v0.63.0/go.mod h1:gs4ij2ffTRXwuzzgJl/56BdwJaA194ijkfn++9tD
|
|||
google.golang.org/api v0.64.0/go.mod h1:931CdxA8Rm4t6zqTFGSsgwbAEZ2+GMYurbndwSimebM=
|
||||
google.golang.org/api v0.66.0/go.mod h1:I1dmXYpX7HGwz/ejRxwQp2qj5bFAz93HiCU1C1oYd9M=
|
||||
google.golang.org/api v0.67.0/go.mod h1:ShHKP8E60yPsKNw/w8w+VYaj9H6buA5UqDp8dhbQZ6g=
|
||||
google.golang.org/api v0.69.0 h1:yHW5s2SFyDapr/43kYtIQmoaaFVW4baLMLwqV4auj2A=
|
||||
google.golang.org/api v0.69.0/go.mod h1:boanBiw+h5c3s+tBPgEzLDRHfFLWV0qXxRHz3ws7C80=
|
||||
google.golang.org/api v0.70.0 h1:67zQnAE0T2rB0A3CwLSas0K+SbVzSxP+zTLkQLexeiw=
|
||||
google.golang.org/api v0.70.0/go.mod h1:Bs4ZM2HGifEvXwd50TtW70ovgJffJYw2oRCOFU/SkfA=
|
||||
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.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||
|
@ -1178,8 +1183,9 @@ google.golang.org/genproto v0.0.0-20220201184016-50beb8ab5c44/go.mod h1:5CzLGKJ6
|
|||
google.golang.org/genproto v0.0.0-20220207164111-0872dc986b00/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
|
||||
google.golang.org/genproto v0.0.0-20220211171837-173942840c17/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI=
|
||||
google.golang.org/genproto v0.0.0-20220216160803-4663080d8bc8/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI=
|
||||
google.golang.org/genproto v0.0.0-20220218161850-94dd64e39d7c h1:TU4rFa5APdKTq0s6B7WTsH6Xmx0Knj86s6Biz56mErE=
|
||||
google.golang.org/genproto v0.0.0-20220218161850-94dd64e39d7c/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI=
|
||||
google.golang.org/genproto v0.0.0-20220222213610-43724f9ea8cf h1:SVYXkUz2yZS9FWb2Gm8ivSlbNQzL2Z/NpPKE3RG2jWk=
|
||||
google.golang.org/genproto v0.0.0-20220222213610-43724f9ea8cf/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI=
|
||||
google.golang.org/grpc v1.8.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
|
||||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
|
||||
|
|
|
@ -5,7 +5,6 @@ import (
|
|||
"fmt"
|
||||
"net/http"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/go-chi/jwtauth/v5"
|
||||
"github.com/lestrrat-go/jwx/jwt"
|
||||
|
@ -406,15 +405,11 @@ func authenticateUserWithAPIKey(username, keyID string, tokenAuth *jwtauth.JWTAu
|
|||
updateLoginMetrics(&user, dataprovider.LoginMethodPassword, ipAddr, err)
|
||||
return err
|
||||
}
|
||||
lastLogin := util.GetTimeFromMsecSinceEpoch(user.LastLogin)
|
||||
diff := -time.Until(lastLogin)
|
||||
if diff < 0 || diff > 10*time.Minute {
|
||||
defer user.CloseFs() //nolint:errcheck
|
||||
err = user.CheckFsRoot(connectionID)
|
||||
if err != nil {
|
||||
updateLoginMetrics(&user, dataprovider.LoginMethodPassword, ipAddr, common.ErrInternalFailure)
|
||||
return common.ErrInternalFailure
|
||||
}
|
||||
defer user.CloseFs() //nolint:errcheck
|
||||
err = user.CheckFsRoot(connectionID)
|
||||
if err != nil {
|
||||
updateLoginMetrics(&user, dataprovider.LoginMethodPassword, ipAddr, common.ErrInternalFailure)
|
||||
return common.ErrInternalFailure
|
||||
}
|
||||
c := jwtTokenClaims{
|
||||
Username: user.Username,
|
||||
|
|
|
@ -762,6 +762,13 @@ func TestOpenReadWritePerm(t *testing.T) {
|
|||
if user.Username == defaultUsername {
|
||||
err = os.RemoveAll(user.GetHomeDir())
|
||||
assert.NoError(t, err)
|
||||
_, err = httpdtest.RemoveUser(user, http.StatusOK)
|
||||
assert.NoError(t, err)
|
||||
user.Password = defaultPassword
|
||||
user.ID = 0
|
||||
user.CreatedAt = 0
|
||||
_, resp, err := httpdtest.AddUser(user, http.StatusCreated)
|
||||
assert.NoError(t, err, string(resp))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1063,6 +1070,13 @@ func TestUploadResume(t *testing.T) {
|
|||
if user.Username == defaultUsername {
|
||||
err = os.RemoveAll(user.GetHomeDir())
|
||||
assert.NoError(t, err)
|
||||
_, err = httpdtest.RemoveUser(user, http.StatusOK)
|
||||
assert.NoError(t, err)
|
||||
user.Password = defaultPassword
|
||||
user.ID = 0
|
||||
user.CreatedAt = 0
|
||||
_, resp, err := httpdtest.AddUser(user, http.StatusCreated)
|
||||
assert.NoError(t, err, string(resp))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1290,6 +1304,13 @@ func TestStat(t *testing.T) {
|
|||
if user.Username == defaultUsername {
|
||||
err = os.RemoveAll(user.GetHomeDir())
|
||||
assert.NoError(t, err)
|
||||
_, err = httpdtest.RemoveUser(user, http.StatusOK)
|
||||
assert.NoError(t, err)
|
||||
user.Password = defaultPassword
|
||||
user.ID = 0
|
||||
user.CreatedAt = 0
|
||||
_, resp, err := httpdtest.AddUser(user, http.StatusCreated)
|
||||
assert.NoError(t, err, string(resp))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1340,6 +1361,13 @@ func TestStatChownChmod(t *testing.T) {
|
|||
if user.Username == defaultUsername {
|
||||
err = os.RemoveAll(user.GetHomeDir())
|
||||
assert.NoError(t, err)
|
||||
_, err = httpdtest.RemoveUser(user, http.StatusOK)
|
||||
assert.NoError(t, err)
|
||||
user.Password = defaultPassword
|
||||
user.ID = 0
|
||||
user.CreatedAt = 0
|
||||
_, resp, err := httpdtest.AddUser(user, http.StatusCreated)
|
||||
assert.NoError(t, err, string(resp))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1384,11 +1412,13 @@ func TestSFTPFsLoginWrongFingerprint(t *testing.T) {
|
|||
sftpUser.FsConfig.SFTPConfig.Fingerprints = []string{"wrong"}
|
||||
_, _, err = httpdtest.UpdateUser(sftpUser, http.StatusOK, "")
|
||||
assert.NoError(t, err)
|
||||
_, _, err = getSftpClient(sftpUser, usePubKey)
|
||||
assert.Error(t, err)
|
||||
|
||||
_, err = runSSHCommand("md5sum", sftpUser, usePubKey)
|
||||
assert.Error(t, err)
|
||||
conn, client, err = getSftpClient(sftpUser, usePubKey)
|
||||
if assert.NoError(t, err) {
|
||||
defer conn.Close()
|
||||
defer client.Close()
|
||||
err = checkBasicSFTP(client)
|
||||
assert.Error(t, err)
|
||||
}
|
||||
|
||||
_, err = httpdtest.RemoveUser(sftpUser, http.StatusOK)
|
||||
assert.NoError(t, err)
|
||||
|
@ -1438,6 +1468,13 @@ func TestChtimes(t *testing.T) {
|
|||
if user.Username == defaultUsername {
|
||||
err = os.RemoveAll(user.GetHomeDir())
|
||||
assert.NoError(t, err)
|
||||
_, err = httpdtest.RemoveUser(user, http.StatusOK)
|
||||
assert.NoError(t, err)
|
||||
user.Password = defaultPassword
|
||||
user.ID = 0
|
||||
user.CreatedAt = 0
|
||||
_, resp, err := httpdtest.AddUser(user, http.StatusCreated)
|
||||
assert.NoError(t, err, string(resp))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3816,13 +3853,14 @@ func TestQuotaFileReplace(t *testing.T) {
|
|||
if user.Username == defaultUsername {
|
||||
err = os.RemoveAll(user.GetHomeDir())
|
||||
assert.NoError(t, err)
|
||||
user.UsedQuotaFiles = 0
|
||||
user.UsedQuotaSize = 0
|
||||
_, err = httpdtest.UpdateQuotaUsage(user, "reset", http.StatusOK)
|
||||
_, err = httpdtest.RemoveUser(user, http.StatusOK)
|
||||
assert.NoError(t, err)
|
||||
user.Password = defaultPassword
|
||||
user.ID = 0
|
||||
user.CreatedAt = 0
|
||||
user.QuotaSize = 0
|
||||
_, _, err = httpdtest.UpdateUser(user, http.StatusOK, "")
|
||||
assert.NoError(t, err)
|
||||
_, resp, err := httpdtest.AddUser(user, http.StatusCreated)
|
||||
assert.NoError(t, err, string(resp))
|
||||
}
|
||||
}
|
||||
_, err = httpdtest.RemoveUser(sftpUser, http.StatusOK)
|
||||
|
@ -3914,10 +3952,13 @@ func TestQuotaRename(t *testing.T) {
|
|||
if user.Username == defaultUsername {
|
||||
err = os.RemoveAll(user.GetHomeDir())
|
||||
assert.NoError(t, err)
|
||||
user.UsedQuotaFiles = 0
|
||||
user.UsedQuotaSize = 0
|
||||
_, err = httpdtest.UpdateQuotaUsage(user, "reset", http.StatusOK)
|
||||
_, err = httpdtest.RemoveUser(user, http.StatusOK)
|
||||
assert.NoError(t, err)
|
||||
user.Password = defaultPassword
|
||||
user.ID = 0
|
||||
user.CreatedAt = 0
|
||||
_, resp, err := httpdtest.AddUser(user, http.StatusCreated)
|
||||
assert.NoError(t, err, string(resp))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -4078,10 +4119,13 @@ func TestQuotaLimits(t *testing.T) {
|
|||
if user.Username == defaultUsername {
|
||||
err = os.RemoveAll(user.GetHomeDir())
|
||||
assert.NoError(t, err)
|
||||
user.UsedQuotaFiles = 0
|
||||
user.UsedQuotaSize = 0
|
||||
_, err = httpdtest.UpdateQuotaUsage(user, "reset", http.StatusOK)
|
||||
_, err = httpdtest.RemoveUser(user, http.StatusOK)
|
||||
assert.NoError(t, err)
|
||||
user.Password = defaultPassword
|
||||
user.ID = 0
|
||||
user.CreatedAt = 0
|
||||
_, resp, err := httpdtest.AddUser(user, http.StatusCreated)
|
||||
assert.NoError(t, err, string(resp))
|
||||
}
|
||||
}
|
||||
err = os.Remove(testFilePath)
|
||||
|
@ -5078,13 +5122,14 @@ func TestTruncateQuotaLimits(t *testing.T) {
|
|||
// cleanup
|
||||
err = os.RemoveAll(user.GetHomeDir())
|
||||
assert.NoError(t, err)
|
||||
user.UsedQuotaFiles = 0
|
||||
user.UsedQuotaSize = 0
|
||||
_, err = httpdtest.UpdateQuotaUsage(user, "reset", http.StatusOK)
|
||||
_, err = httpdtest.RemoveUser(user, http.StatusOK)
|
||||
assert.NoError(t, err)
|
||||
user.Password = defaultPassword
|
||||
user.ID = 0
|
||||
user.CreatedAt = 0
|
||||
user.QuotaSize = 0
|
||||
_, _, err = httpdtest.UpdateUser(user, http.StatusOK, "")
|
||||
assert.NoError(t, err)
|
||||
_, resp, err := httpdtest.AddUser(user, http.StatusCreated)
|
||||
assert.NoError(t, err, string(resp))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -7323,10 +7368,15 @@ func TestRootDirCommands(t *testing.T) {
|
|||
if user.Username == defaultUsername {
|
||||
err = os.RemoveAll(user.GetHomeDir())
|
||||
assert.NoError(t, err)
|
||||
_, err = httpdtest.RemoveUser(user, http.StatusOK)
|
||||
assert.NoError(t, err)
|
||||
user.Password = defaultPassword
|
||||
user.ID = 0
|
||||
user.CreatedAt = 0
|
||||
user.Permissions = make(map[string][]string)
|
||||
user.Permissions["/"] = []string{dataprovider.PermAny}
|
||||
_, _, err = httpdtest.UpdateUser(user, http.StatusOK, "")
|
||||
assert.NoError(t, err)
|
||||
_, resp, err := httpdtest.AddUser(user, http.StatusCreated)
|
||||
assert.NoError(t, err, string(resp))
|
||||
}
|
||||
}
|
||||
_, err = httpdtest.RemoveUser(sftpUser, http.StatusOK)
|
||||
|
@ -8900,6 +8950,13 @@ func TestSCPBasicHandling(t *testing.T) {
|
|||
if user.Username == defaultUsername {
|
||||
err = os.RemoveAll(user.GetHomeDir())
|
||||
assert.NoError(t, err)
|
||||
_, err = httpdtest.RemoveUser(user, http.StatusOK)
|
||||
assert.NoError(t, err)
|
||||
user.Password = defaultPassword
|
||||
user.ID = 0
|
||||
user.CreatedAt = 0
|
||||
_, resp, err := httpdtest.AddUser(user, http.StatusCreated)
|
||||
assert.NoError(t, err, string(resp))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -8975,6 +9032,13 @@ func TestSCPUploadFileOverwrite(t *testing.T) {
|
|||
if user.Username == defaultUsername {
|
||||
err = os.RemoveAll(user.GetHomeDir())
|
||||
assert.NoError(t, err)
|
||||
_, err = httpdtest.RemoveUser(user, http.StatusOK)
|
||||
assert.NoError(t, err)
|
||||
user.Password = defaultPassword
|
||||
user.ID = 0
|
||||
user.CreatedAt = 0
|
||||
_, resp, err := httpdtest.AddUser(user, http.StatusCreated)
|
||||
assert.NoError(t, err, string(resp))
|
||||
}
|
||||
}
|
||||
err = os.Remove(testFilePath)
|
||||
|
@ -9043,6 +9107,13 @@ func TestSCPRecursive(t *testing.T) {
|
|||
if user.Username == defaultUsername {
|
||||
err = os.RemoveAll(user.GetHomeDir())
|
||||
assert.NoError(t, err)
|
||||
_, err = httpdtest.RemoveUser(user, http.StatusOK)
|
||||
assert.NoError(t, err)
|
||||
user.Password = defaultPassword
|
||||
user.ID = 0
|
||||
user.CreatedAt = 0
|
||||
_, resp, err := httpdtest.AddUser(user, http.StatusCreated)
|
||||
assert.NoError(t, err, string(resp))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -353,11 +353,6 @@ func (fs *AzureBlobFs) Mkdir(name string) error {
|
|||
return w.Close()
|
||||
}
|
||||
|
||||
// MkdirAll does nothing, we don't have folder
|
||||
func (*AzureBlobFs) MkdirAll(name string, uid int, gid int) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Symlink creates source as a symbolic link to target.
|
||||
func (*AzureBlobFs) Symlink(source, target string) error {
|
||||
return ErrVfsUnsupported
|
||||
|
|
|
@ -317,11 +317,6 @@ func (fs *GCSFs) Mkdir(name string) error {
|
|||
return w.Close()
|
||||
}
|
||||
|
||||
// MkdirAll does nothing, we don't have folder
|
||||
func (*GCSFs) MkdirAll(name string, uid int, gid int) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Symlink creates source as a symbolic link to target.
|
||||
func (*GCSFs) Symlink(source, target string) error {
|
||||
return ErrVfsUnsupported
|
||||
|
|
24
vfs/osfs.go
24
vfs/osfs.go
|
@ -128,13 +128,6 @@ func (*OsFs) Mkdir(name string) error {
|
|||
return os.Mkdir(name, os.ModePerm)
|
||||
}
|
||||
|
||||
// MkdirAll creates a directory named path, along with any necessary parents,
|
||||
// and returns nil, or else returns an error.
|
||||
// If path is already a directory, MkdirAll does nothing and returns nil.
|
||||
func (fs *OsFs) MkdirAll(name string, uid int, gid int) error {
|
||||
return fs.createMissingDirs(name, uid, gid)
|
||||
}
|
||||
|
||||
// Symlink creates source as a symbolic link to target.
|
||||
func (*OsFs) Symlink(source, target string) error {
|
||||
return os.Symlink(source, target)
|
||||
|
@ -418,23 +411,6 @@ func (fs *OsFs) isSubDir(sub string) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (fs *OsFs) createMissingDirs(filePath string, uid, gid int) error {
|
||||
dirsToCreate, err := fs.findNonexistentDirs(filePath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
last := len(dirsToCreate) - 1
|
||||
for i := range dirsToCreate {
|
||||
d := dirsToCreate[last-i]
|
||||
if err := os.Mkdir(d, os.ModePerm); err != nil {
|
||||
fsLog(fs, logger.LevelError, "error creating missing dir: %#v", d)
|
||||
return err
|
||||
}
|
||||
SetPathPermissions(fs, d, uid, gid)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetMimeType returns the content type
|
||||
func (fs *OsFs) GetMimeType(name string) (string, error) {
|
||||
f, err := os.OpenFile(name, os.O_RDONLY, 0)
|
||||
|
|
45
vfs/s3fs.go
45
vfs/s3fs.go
|
@ -90,22 +90,7 @@ func NewS3Fs(connectionID, localTempDir, mountPath string, config S3FsConfig) (F
|
|||
if fs.config.ForcePathStyle {
|
||||
awsConfig.S3ForcePathStyle = aws.Bool(true)
|
||||
}
|
||||
if fs.config.UploadPartSize == 0 {
|
||||
fs.config.UploadPartSize = s3manager.DefaultUploadPartSize
|
||||
} else {
|
||||
fs.config.UploadPartSize *= 1024 * 1024
|
||||
}
|
||||
if fs.config.UploadConcurrency == 0 {
|
||||
fs.config.UploadConcurrency = s3manager.DefaultUploadConcurrency
|
||||
}
|
||||
if fs.config.DownloadPartSize == 0 {
|
||||
fs.config.DownloadPartSize = s3manager.DefaultDownloadPartSize
|
||||
} else {
|
||||
fs.config.DownloadPartSize *= 1024 * 1024
|
||||
}
|
||||
if fs.config.DownloadConcurrency == 0 {
|
||||
fs.config.DownloadConcurrency = s3manager.DefaultDownloadConcurrency
|
||||
}
|
||||
fs.setConfigDefaults()
|
||||
|
||||
sessOpts := session.Options{
|
||||
Config: *awsConfig,
|
||||
|
@ -392,11 +377,6 @@ func (fs *S3Fs) Mkdir(name string) error {
|
|||
return w.Close()
|
||||
}
|
||||
|
||||
// MkdirAll does nothing, we don't have folder
|
||||
func (*S3Fs) MkdirAll(name string, uid int, gid int) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Symlink creates source as a symbolic link to target.
|
||||
func (*S3Fs) Symlink(source, target string) error {
|
||||
return ErrVfsUnsupported
|
||||
|
@ -742,6 +722,29 @@ func (fs *S3Fs) checkIfBucketExists() error {
|
|||
return err
|
||||
}
|
||||
|
||||
func (fs *S3Fs) setConfigDefaults() {
|
||||
if fs.config.UploadPartSize == 0 {
|
||||
fs.config.UploadPartSize = s3manager.DefaultUploadPartSize
|
||||
} else {
|
||||
if fs.config.UploadPartSize < 1024*1024 {
|
||||
fs.config.UploadPartSize *= 1024 * 1024
|
||||
}
|
||||
}
|
||||
if fs.config.UploadConcurrency == 0 {
|
||||
fs.config.UploadConcurrency = s3manager.DefaultUploadConcurrency
|
||||
}
|
||||
if fs.config.DownloadPartSize == 0 {
|
||||
fs.config.DownloadPartSize = s3manager.DefaultDownloadPartSize
|
||||
} else {
|
||||
if fs.config.DownloadPartSize < 1024*1024 {
|
||||
fs.config.DownloadPartSize *= 1024 * 1024
|
||||
}
|
||||
}
|
||||
if fs.config.DownloadConcurrency == 0 {
|
||||
fs.config.DownloadConcurrency = s3manager.DefaultDownloadConcurrency
|
||||
}
|
||||
}
|
||||
|
||||
func (fs *S3Fs) hasContents(name string) (bool, error) {
|
||||
prefix := ""
|
||||
if name != "/" && name != "." {
|
||||
|
|
|
@ -349,16 +349,6 @@ func (fs *SFTPFs) Mkdir(name string) error {
|
|||
return fs.sftpClient.Mkdir(name)
|
||||
}
|
||||
|
||||
// MkdirAll creates a directory named path, along with any necessary parents,
|
||||
// and returns nil, or else returns an error.
|
||||
// If path is already a directory, MkdirAll does nothing and returns nil.
|
||||
func (fs *SFTPFs) MkdirAll(name string, uid int, gid int) error {
|
||||
if err := fs.checkConnection(); err != nil {
|
||||
return err
|
||||
}
|
||||
return fs.sftpClient.MkdirAll(name)
|
||||
}
|
||||
|
||||
// Symlink creates source as a symbolic link to target.
|
||||
func (fs *SFTPFs) Symlink(source, target string) error {
|
||||
if err := fs.checkConnection(); err != nil {
|
||||
|
@ -459,7 +449,10 @@ func (fs *SFTPFs) CheckRootPath(username string, uid int, gid int) bool {
|
|||
if fs.config.Prefix == "/" {
|
||||
return true
|
||||
}
|
||||
if err := fs.MkdirAll(fs.config.Prefix, uid, gid); err != nil {
|
||||
if err := fs.checkConnection(); err != nil {
|
||||
return false
|
||||
}
|
||||
if err := fs.sftpClient.MkdirAll(fs.config.Prefix); err != nil {
|
||||
fsLog(fs, logger.LevelDebug, "error creating root directory %#v for user %#v: %v", fs.config.Prefix, username, err)
|
||||
return false
|
||||
}
|
||||
|
|
|
@ -73,7 +73,6 @@ type Fs interface {
|
|||
Rename(source, target string) error
|
||||
Remove(name string, isDir bool) error
|
||||
Mkdir(name string) error
|
||||
MkdirAll(name string, uid int, gid int) error
|
||||
Symlink(source, target string) error
|
||||
Chown(name string, uid int, gid int) error
|
||||
Chmod(name string, mode os.FileMode) error
|
||||
|
|
|
@ -576,6 +576,13 @@ func TestBasicHandling(t *testing.T) {
|
|||
if user.Username == defaultUsername {
|
||||
err = os.RemoveAll(user.GetHomeDir())
|
||||
assert.NoError(t, err)
|
||||
_, err = httpdtest.RemoveUser(user, http.StatusOK)
|
||||
assert.NoError(t, err)
|
||||
user.Password = defaultPassword
|
||||
user.ID = 0
|
||||
user.CreatedAt = 0
|
||||
_, resp, err := httpdtest.AddUser(user, http.StatusCreated)
|
||||
assert.NoError(t, err, string(resp))
|
||||
}
|
||||
}
|
||||
_, err = httpdtest.RemoveUser(sftpUser, http.StatusOK)
|
||||
|
@ -1484,10 +1491,15 @@ func TestQuotaLimits(t *testing.T) {
|
|||
if user.Username == defaultUsername {
|
||||
err = os.RemoveAll(user.GetHomeDir())
|
||||
assert.NoError(t, err)
|
||||
_, err = httpdtest.RemoveUser(user, http.StatusOK)
|
||||
assert.NoError(t, err)
|
||||
user.Password = defaultPassword
|
||||
user.ID = 0
|
||||
user.CreatedAt = 0
|
||||
user.QuotaFiles = 0
|
||||
user.QuotaSize = 0
|
||||
_, _, err = httpdtest.UpdateUser(user, http.StatusOK, "")
|
||||
assert.NoError(t, err)
|
||||
_, resp, err := httpdtest.AddUser(user, http.StatusCreated)
|
||||
assert.NoError(t, err, string(resp))
|
||||
}
|
||||
}
|
||||
_, err = httpdtest.RemoveUser(sftpUser, http.StatusOK)
|
||||
|
@ -1581,9 +1593,14 @@ func TestUploadMaxSize(t *testing.T) {
|
|||
if user.Username == defaultUsername {
|
||||
err = os.RemoveAll(user.GetHomeDir())
|
||||
assert.NoError(t, err)
|
||||
user.Filters.MaxUploadFileSize = 65536000
|
||||
_, _, err = httpdtest.UpdateUser(user, http.StatusOK, "")
|
||||
_, err = httpdtest.RemoveUser(user, http.StatusOK)
|
||||
assert.NoError(t, err)
|
||||
user.Filters.MaxUploadFileSize = 65536000
|
||||
user.Password = defaultPassword
|
||||
user.ID = 0
|
||||
user.CreatedAt = 0
|
||||
_, resp, err := httpdtest.AddUser(user, http.StatusCreated)
|
||||
assert.NoError(t, err, string(resp))
|
||||
}
|
||||
}
|
||||
_, err = httpdtest.RemoveUser(sftpUser, http.StatusOK)
|
||||
|
@ -2195,9 +2212,14 @@ func TestMiscCommands(t *testing.T) {
|
|||
if user.Username == defaultUsername {
|
||||
err = os.RemoveAll(user.GetHomeDir())
|
||||
assert.NoError(t, err)
|
||||
user.QuotaFiles = 0
|
||||
_, _, err = httpdtest.UpdateUser(user, http.StatusOK, "")
|
||||
_, err = httpdtest.RemoveUser(user, http.StatusOK)
|
||||
assert.NoError(t, err)
|
||||
user.Password = defaultPassword
|
||||
user.ID = 0
|
||||
user.CreatedAt = 0
|
||||
user.QuotaFiles = 0
|
||||
_, resp, err := httpdtest.AddUser(user, http.StatusCreated)
|
||||
assert.NoError(t, err, string(resp))
|
||||
}
|
||||
}
|
||||
_, err = httpdtest.RemoveUser(sftpUser, http.StatusOK)
|
||||
|
|
Loading…
Reference in a new issue