mirror of
https://github.com/drakkan/sftpgo.git
synced 2024-11-24 16:40:26 +00:00
allow quota tracking only for users with quota restrictions
Setting "track_quota" to 2 in sftpgo.conf will avoid a database update after each file upload/deletion if the user has no quota restrictions
This commit is contained in:
parent
9987821003
commit
0bed768909
6 changed files with 24 additions and 16 deletions
|
@ -87,7 +87,10 @@ The `sftpgo.conf` configuration file contains the following sections:
|
|||
- `connectionstring`, string. Provide a custom database connection string. If not empty this connection string will be used instead of build one using the previous parameters
|
||||
- `users_table`, string. Database table for SFTP users
|
||||
- `manage_users`, integer. Set to 0 to disable users management, 1 to enable
|
||||
- `track_quota`, integer. Set to 0 to disable quota tracking, 1 to update the used quota each time a user upload or delete a file
|
||||
- `track_quota`, integer. Set the preferred way to track users quota between the following choices:
|
||||
- 0, disable quota tracking. REST API to scan user dir and update quota will do nothing
|
||||
- 1, quota is updated each time a user upload or delete a file even if the user has no quota restrictions
|
||||
- 2, quota is updated each time a user upload or delete a file but only for users with quota restrictions. With this configuration you can still use the "quota scan" REST API to periodically update space usage for users without quota restrictions
|
||||
- **"httpd"**, the configuration for the HTTP server used to serve REST API
|
||||
- `bind_port`, integer. The port used for serving HTTP requests. Set to 0 to disable HTTP server. Default: 8080
|
||||
- `bind_address`, string. Leave blank to listen on all available network interfaces. Default: "127.0.0.1"
|
||||
|
@ -157,7 +160,7 @@ These properties are stored inside the data provider. If you want to use your ex
|
|||
|
||||
SFTPGo exposes REST API to manage users and quota and to get real time reports for the active connections with possibility of forcibly closing a connection.
|
||||
|
||||
If quota tracking is enabled in `sftpgo.conf` configuration file, then the used size and number of files are updated each time a file is added/removed. If files are added/removed not using SFTP, you can rescan the user home dir and update the used quota using the REST API.
|
||||
If quota tracking is enabled in `sftpgo.conf` configuration file, then the used size and number of files are updated each time a file is added/removed. If files are added/removed not using SFTP or if you change `track_quota` from `2` to `1`, you can rescan the user home dir and update the used quota using the REST API.
|
||||
|
||||
REST API is designed to run on localhost or on a trusted network, if you need https or authentication you can setup a reverse proxy using an HTTP Server such as Apache or NGNIX.
|
||||
|
||||
|
|
|
@ -33,11 +33,8 @@ func startQuotaScan(w http.ResponseWriter, r *http.Request) {
|
|||
if err != nil {
|
||||
logger.Warn(logSender, "error scanning user home dir %v: %v", user.HomeDir, err)
|
||||
} else {
|
||||
err := dataprovider.UpdateUserQuota(dataProvider, user.Username, numFiles, size, true)
|
||||
if err != nil {
|
||||
logger.Debug(logSender, "error updating user quota for %v: %v", user.Username, err)
|
||||
}
|
||||
logger.Debug(logSender, "user dir scanned, user: %v, dir: %v", user.Username, user.HomeDir)
|
||||
err := dataprovider.UpdateUserQuota(dataProvider, user, numFiles, size, true)
|
||||
logger.Debug(logSender, "user dir scanned, user: %v, dir: %v, error: %v", user.Username, user.HomeDir, err)
|
||||
}
|
||||
sftpd.RemoveQuotaScan(user.Username)
|
||||
}()
|
||||
|
|
|
@ -23,7 +23,7 @@ const (
|
|||
logSender = "dataProvider"
|
||||
argonPwdPrefix = "$argon2id$"
|
||||
manageUsersDisabledError = "please set manage_users to 1 in sftpgo.conf to enable this method"
|
||||
trackQuotaDisabledError = "please set track_quota to 1 in sftpgo.conf to enable this method"
|
||||
trackQuotaDisabledError = "please enable track_quota in sftpgo.conf to use this method"
|
||||
)
|
||||
|
||||
var (
|
||||
|
@ -117,11 +117,13 @@ func CheckUserAndPubKey(p Provider, username string, pubKey string) (User, error
|
|||
}
|
||||
|
||||
// UpdateUserQuota update the quota for the given user
|
||||
func UpdateUserQuota(p Provider, username string, filesAdd int, sizeAdd int64, reset bool) error {
|
||||
func UpdateUserQuota(p Provider, user User, filesAdd int, sizeAdd int64, reset bool) error {
|
||||
if config.TrackQuota == 0 {
|
||||
return &MethodDisabledError{err: trackQuotaDisabledError}
|
||||
} else if config.TrackQuota == 2 && !reset && !user.HasQuotaRestrictions() {
|
||||
return nil
|
||||
}
|
||||
return p.updateQuota(username, filesAdd, sizeAdd, reset)
|
||||
return p.updateQuota(user.Username, filesAdd, sizeAdd, reset)
|
||||
}
|
||||
|
||||
// GetUsedQuota returns the used quota for the given user
|
||||
|
|
|
@ -82,3 +82,9 @@ func (u *User) GetGID() int {
|
|||
func (u *User) GetHomeDir() string {
|
||||
return filepath.Clean(u.HomeDir)
|
||||
}
|
||||
|
||||
// HasQuotaRestrictions returns true if there is a quota restriction on number of files
|
||||
// or size or both
|
||||
func (u *User) HasQuotaRestrictions() bool {
|
||||
return u.QuotaFiles > 0 || u.QuotaSize > 0
|
||||
}
|
||||
|
|
|
@ -167,8 +167,7 @@ func (c Connection) Filewrite(request *sftp.Request) (io.WriterAt, error) {
|
|||
|
||||
if trunc {
|
||||
// the file is truncated so we need to decrease quota size but not quota files
|
||||
logger.Debug(logSender, "file truncation requested update quota for user %v", c.User.Username)
|
||||
dataprovider.UpdateUserQuota(dataProvider, c.User.Username, 0, -stat.Size(), false)
|
||||
dataprovider.UpdateUserQuota(dataProvider, c.User, 0, -stat.Size(), false)
|
||||
}
|
||||
|
||||
utils.SetPathPermissions(p, c.User.GetUID(), c.User.GetGID())
|
||||
|
@ -339,7 +338,7 @@ func (c Connection) handleSFTPRmdir(path string) error {
|
|||
}
|
||||
|
||||
logger.CommandLog(sftpdRmdirLogSender, path, "", c.User.Username, c.ID)
|
||||
dataprovider.UpdateUserQuota(dataProvider, c.User.Username, -numFiles, -size, false)
|
||||
dataprovider.UpdateUserQuota(dataProvider, c.User, -numFiles, -size, false)
|
||||
for _, p := range fileList {
|
||||
executeAction(operationDelete, c.User.Username, p, "")
|
||||
}
|
||||
|
@ -392,7 +391,7 @@ func (c Connection) handleSFTPRemove(path string) error {
|
|||
|
||||
logger.CommandLog(sftpdRemoveLogSender, path, "", c.User.Username, c.ID)
|
||||
if fi.Mode()&os.ModeSymlink != os.ModeSymlink {
|
||||
dataprovider.UpdateUserQuota(dataProvider, c.User.Username, -1, -size, false)
|
||||
dataprovider.UpdateUserQuota(dataProvider, c.User, -1, -size, false)
|
||||
}
|
||||
executeAction(operationDelete, c.User.Username, path, "")
|
||||
|
||||
|
@ -410,7 +409,8 @@ func (c Connection) hasSpace(checkFiles bool) bool {
|
|||
logger.Warn(logSender, "error getting used quota for %v: %v", c.User.Username, err)
|
||||
return false
|
||||
}
|
||||
if (checkFiles && numFile >= c.User.QuotaFiles) || size >= c.User.QuotaSize {
|
||||
if (checkFiles && c.User.QuotaFiles > 0 && numFile >= c.User.QuotaFiles) ||
|
||||
(c.User.QuotaSize > 0 && size >= c.User.QuotaSize) {
|
||||
logger.Debug(logSender, "quota exceed for user %v, num files: %v/%v, size: %v/%v check files: %v",
|
||||
c.User.Username, numFile, c.User.QuotaFiles, size, c.User.QuotaSize, checkFiles)
|
||||
return false
|
||||
|
|
|
@ -62,7 +62,7 @@ func (t *Transfer) Close() error {
|
|||
if t.isNewFile {
|
||||
numFiles = 1
|
||||
}
|
||||
dataprovider.UpdateUserQuota(dataProvider, t.user.Username, numFiles, t.bytesReceived, false)
|
||||
dataprovider.UpdateUserQuota(dataProvider, t.user, numFiles, t.bytesReceived, false)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue