WebDAV: Skip download sync if storage is full or quota is exceeded #4266

Signed-off-by: Michael Mayer <michael@photoprism.app>
This commit is contained in:
Michael Mayer
2025-03-11 23:45:41 +01:00
parent c3d22c157c
commit eb9371d089
7 changed files with 19 additions and 14 deletions

View File

@@ -56,7 +56,7 @@ func StartImport(router *gin.RouterGroup) {
}
// Abort if there is not enough free storage to import new files.
if conf.FilesQuotaReached() {
if conf.FilesQuotaExceeded() {
event.AuditErr([]string{ClientIP(c), "session %s", "import files", "insufficient storage"}, s.RefID)
Abort(c, http.StatusInsufficientStorage, i18n.ErrInsufficientStorage)
return

View File

@@ -53,7 +53,7 @@ func UploadUserFiles(router *gin.RouterGroup) {
}
// Abort if there is not enough free storage to upload new files.
if conf.FilesQuotaReached() {
if conf.FilesQuotaExceeded() {
event.AuditErr([]string{ClientIP(c), "session %s", "upload files", "insufficient storage"}, s.RefID)
Abort(c, http.StatusInsufficientStorage, i18n.ErrInsufficientStorage)
return

View File

@@ -118,8 +118,8 @@ func (c *Config) FilesQuotaBytes() uint64 {
return c.options.FilesQuota * fs.GB
}
// FilesQuotaReached checks if the filesystem usage has been reached or exceeded.
func (c *Config) FilesQuotaReached() bool {
// FilesQuotaExceeded checks if the filesystem usage has been reached or exceeded.
func (c *Config) FilesQuotaExceeded() bool {
return c.Usage().FilesUsedPct >= 100
}

View File

@@ -56,19 +56,19 @@ func TestConfig_Quota(t *testing.T) {
c.options.UsersQuota = 0
}
func TestConfig_FilesQuotaReached(t *testing.T) {
func TestConfig_FilesQuotaExceeded(t *testing.T) {
c := TestConfig()
FlushUsageCache()
assert.False(t, c.FilesQuotaReached())
assert.False(t, c.FilesQuotaExceeded())
c.options.FilesQuota = uint64(1)
FlushUsageCache()
assert.True(t, c.FilesQuotaReached())
assert.True(t, c.FilesQuotaExceeded())
c.options.FilesQuota = uint64(5)
FlushUsageCache()
assert.False(t, c.FilesQuotaReached())
assert.False(t, c.FilesQuotaExceeded())
c.options.FilesQuota = uint64(0)
}

View File

@@ -95,7 +95,7 @@ func WebDAV(dir string, router *gin.RouterGroup, conf *config.Config) {
// is not enough free storage to upload new files.
switch c.Request.Method {
case MethodPut, MethodPost, MethodPatch, MethodCopy:
if conf.FilesQuotaReached() {
if conf.FilesQuotaExceeded() {
c.AbortWithStatus(http.StatusInsufficientStorage)
return
}

View File

@@ -106,9 +106,9 @@ func (w *Sync) Start() (err error) {
}
}
case entity.SyncStatusDownload:
if complete, err := w.download(a); err != nil {
if complete, downloadErr := w.download(a); downloadErr != nil {
accErrors++
accError = err.Error()
accError = downloadErr.Error()
syncStatus = entity.SyncStatusRefresh
} else if complete {
if a.SyncUpload {

View File

@@ -105,6 +105,11 @@ func (w *Sync) download(a entity.Service) (complete bool, err error) {
done := make(map[string]bool)
for _, files := range relatedFiles {
if w.conf.FilesQuotaExceeded() {
log.Warnf("sync: skipped downloading files from %s due to insufficient storage", clean.Log(a.AccName))
return false, nil
}
for i, file := range files {
if mutex.SyncWorker.Canceled() {
return false, nil
@@ -112,14 +117,14 @@ func (w *Sync) download(a entity.Service) (complete bool, err error) {
// Failed too often?
if a.RetryLimit > 0 && file.Errors > a.RetryLimit {
log.Debugf("sync: downloading %s failed more than %d times", file.RemoteName, a.RetryLimit)
log.Debugf("sync: downloading %s from %s failed more than %d times", file.RemoteName, clean.Log(a.AccName), a.RetryLimit)
continue
}
localName := baseDir + file.RemoteName
if _, err = os.Stat(localName); err == nil {
log.Warnf("sync: download skipped, %s already exists", localName)
log.Warnf("sync: skipped download of %s from %s because local file %s already exists", file.RemoteName, clean.Log(a.AccName), localName)
file.Status = entity.FileSyncExists
file.Error = ""
file.Errors = 0
@@ -128,7 +133,7 @@ func (w *Sync) download(a entity.Service) (complete bool, err error) {
file.Errors++
file.Error = err.Error()
} else {
log.Infof("sync: downloaded %s from %s", file.RemoteName, a.AccName)
log.Infof("sync: downloaded %s from %s", file.RemoteName, clean.Log(a.AccName))
file.Status = entity.FileSyncDownloaded
file.Error = ""
file.Errors = 0