Storage: move file quota check to service (#53058)

* Storage: move file quota check to service

* Fix tests
This commit is contained in:
Artur Wierzbicki 2022-08-01 22:53:44 +04:00 committed by GitHub
parent 8fc8d00167
commit 0d817987ec
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 30 additions and 10 deletions

View File

@ -28,6 +28,9 @@ func UploadErrorToStatusCode(err error) int {
case errors.Is(err, ErrValidationFailed): case errors.Is(err, ErrValidationFailed):
return 400 return 400
case errors.Is(err, ErrQuotaReached):
return 400
case errors.Is(err, ErrFileAlreadyExists): case errors.Is(err, ErrFileAlreadyExists):
return 400 return 400
@ -70,16 +73,6 @@ func (s *standardStorageService) doWrite(c *models.ReqContext) response.Response
} }
func (s *standardStorageService) doUpload(c *models.ReqContext) response.Response { func (s *standardStorageService) doUpload(c *models.ReqContext) response.Response {
// assumes we are only uploading to the SQL database - TODO: refactor once we introduce object stores
quotaReached, err := s.quotaService.CheckQuotaReached(c.Req.Context(), "file", nil)
if err != nil {
return response.Error(500, "Internal server error", err)
}
if quotaReached {
return response.Error(400, "File quota reached", errors.New("file quota reached"))
}
type rspInfo struct { type rspInfo struct {
Message string `json:"message,omitempty"` Message string `json:"message,omitempty"`
Path string `json:"path,omitempty"` Path string `json:"path,omitempty"`

View File

@ -25,6 +25,7 @@ var grafanaStorageLogger = log.New("grafanaStorageLogger")
var ErrUnsupportedStorage = errors.New("storage does not support this operation") var ErrUnsupportedStorage = errors.New("storage does not support this operation")
var ErrUploadInternalError = errors.New("upload internal error") var ErrUploadInternalError = errors.New("upload internal error")
var ErrQuotaReached = errors.New("file quota reached")
var ErrValidationFailed = errors.New("request validation failed") var ErrValidationFailed = errors.New("request validation failed")
var ErrFileAlreadyExists = errors.New("file exists") var ErrFileAlreadyExists = errors.New("file exists")
var ErrStorageNotFound = errors.New("storage not found") var ErrStorageNotFound = errors.New("storage not found")
@ -300,6 +301,10 @@ type UploadRequest struct {
} }
func (s *standardStorageService) Upload(ctx context.Context, user *models.SignedInUser, req *UploadRequest) error { func (s *standardStorageService) Upload(ctx context.Context, user *models.SignedInUser, req *UploadRequest) error {
if err := s.checkFileQuota(ctx, req.Path); err != nil {
return err
}
guardian := s.authService.newGuardian(ctx, user, getFirstSegment(req.Path)) guardian := s.authService.newGuardian(ctx, user, getFirstSegment(req.Path))
if !guardian.canWrite(req.Path) { if !guardian.canWrite(req.Path) {
return ErrAccessDenied return ErrAccessDenied
@ -348,6 +353,22 @@ func (s *standardStorageService) Upload(ctx context.Context, user *models.Signed
return nil return nil
} }
func (s *standardStorageService) checkFileQuota(ctx context.Context, path string) error {
// assumes we are only uploading to the SQL database - TODO: refactor once we introduce object stores
quotaReached, err := s.quotaService.CheckQuotaReached(ctx, "file", nil)
if err != nil {
grafanaStorageLogger.Error("failed while checking upload quota", "path", path, "error", err)
return ErrUploadInternalError
}
if quotaReached {
grafanaStorageLogger.Info("reached file quota", "path", path)
return ErrQuotaReached
}
return nil
}
func (s *standardStorageService) DeleteFolder(ctx context.Context, user *models.SignedInUser, cmd *DeleteFolderCmd) error { func (s *standardStorageService) DeleteFolder(ctx context.Context, user *models.SignedInUser, cmd *DeleteFolderCmd) error {
guardian := s.authService.newGuardian(ctx, user, getFirstSegment(cmd.Path)) guardian := s.authService.newGuardian(ctx, user, getFirstSegment(cmd.Path))
if !guardian.canDelete(cmd.Path) { if !guardian.canDelete(cmd.Path) {
@ -370,6 +391,10 @@ func (s *standardStorageService) DeleteFolder(ctx context.Context, user *models.
} }
func (s *standardStorageService) CreateFolder(ctx context.Context, user *models.SignedInUser, cmd *CreateFolderCmd) error { func (s *standardStorageService) CreateFolder(ctx context.Context, user *models.SignedInUser, cmd *CreateFolderCmd) error {
if err := s.checkFileQuota(ctx, cmd.Path); err != nil {
return err
}
guardian := s.authService.newGuardian(ctx, user, getFirstSegment(cmd.Path)) guardian := s.authService.newGuardian(ctx, user, getFirstSegment(cmd.Path))
if !guardian.canWrite(cmd.Path) { if !guardian.canWrite(cmd.Path) {
return ErrAccessDenied return ErrAccessDenied

View File

@ -10,6 +10,7 @@ import (
"github.com/grafana/grafana-plugin-sdk-go/experimental" "github.com/grafana/grafana-plugin-sdk-go/experimental"
"github.com/grafana/grafana/pkg/infra/filestorage" "github.com/grafana/grafana/pkg/infra/filestorage"
"github.com/grafana/grafana/pkg/models" "github.com/grafana/grafana/pkg/models"
"github.com/grafana/grafana/pkg/services/quota/quotatest"
"github.com/grafana/grafana/pkg/services/sqlstore" "github.com/grafana/grafana/pkg/services/sqlstore"
"github.com/grafana/grafana/pkg/setting" "github.com/grafana/grafana/pkg/setting"
"github.com/grafana/grafana/pkg/tsdb/testdatasource" "github.com/grafana/grafana/pkg/tsdb/testdatasource"
@ -117,6 +118,7 @@ func setupUploadStore(t *testing.T, authService storageAuthService) (StorageServ
store.cfg = &GlobalStorageConfig{ store.cfg = &GlobalStorageConfig{
AllowUnsanitizedSvgUpload: true, AllowUnsanitizedSvgUpload: true,
} }
store.quotaService = quotatest.NewQuotaServiceFake()
return store, mockStorage, storageName return store, mockStorage, storageName
} }