actions: add pre-download and pre-upload

Downloads and uploads can be denied based on hook response
This commit is contained in:
Nicola Murino
2021-05-26 07:48:37 +02:00
parent 600268ebb8
commit 25a44030f9
24 changed files with 710 additions and 176 deletions

View File

@@ -49,9 +49,24 @@ func InitializeActionHandler(handler ActionHandler) {
actionHandler = handler
}
// ExecutePreAction executes a pre-* action and returns the result
func ExecutePreAction(user *dataprovider.User, operation, filePath, virtualPath, protocol string, fileSize int64) error {
if !utils.IsStringInSlice(operation, Config.Actions.ExecuteOn) {
// for pre-delete we execute the internal handling on error, so we must return errUnconfiguredAction.
// Other pre action will deny the operation on error so if we have no configuration we must return
// a nil error
if operation == operationPreDelete {
return errUnconfiguredAction
}
return nil
}
notification := newActionNotification(user, operation, filePath, virtualPath, "", "", protocol, fileSize, nil)
return actionHandler.Handle(notification)
}
// ExecuteActionNotification executes the defined hook, if any, for the specified action
func ExecuteActionNotification(user *dataprovider.User, operation, filePath, target, sshCmd, protocol string, fileSize int64, err error) {
notification := newActionNotification(user, operation, filePath, target, sshCmd, protocol, fileSize, err)
func ExecuteActionNotification(user *dataprovider.User, operation, filePath, virtualPath, target, sshCmd, protocol string, fileSize int64, err error) {
notification := newActionNotification(user, operation, filePath, virtualPath, target, sshCmd, protocol, fileSize, err)
if utils.IsStringInSlice(operation, Config.Actions.ExecuteSync) {
actionHandler.Handle(notification) //nolint:errcheck
@@ -83,25 +98,30 @@ type ActionNotification struct {
func newActionNotification(
user *dataprovider.User,
operation, filePath, target, sshCmd, protocol string,
operation, filePath, virtualPath, target, sshCmd, protocol string,
fileSize int64,
err error,
) *ActionNotification {
var bucket, endpoint string
status := 1
if user.FsConfig.Provider == vfs.S3FilesystemProvider {
bucket = user.FsConfig.S3Config.Bucket
endpoint = user.FsConfig.S3Config.Endpoint
} else if user.FsConfig.Provider == vfs.GCSFilesystemProvider {
bucket = user.FsConfig.GCSConfig.Bucket
} else if user.FsConfig.Provider == vfs.AzureBlobFilesystemProvider {
bucket = user.FsConfig.AzBlobConfig.Container
if user.FsConfig.AzBlobConfig.SASURL != "" {
endpoint = user.FsConfig.AzBlobConfig.SASURL
fsConfig := user.GetFsConfigForPath(virtualPath)
switch fsConfig.Provider {
case vfs.S3FilesystemProvider:
bucket = fsConfig.S3Config.Bucket
endpoint = fsConfig.S3Config.Endpoint
case vfs.GCSFilesystemProvider:
bucket = fsConfig.GCSConfig.Bucket
case vfs.AzureBlobFilesystemProvider:
bucket = fsConfig.AzBlobConfig.Container
if fsConfig.AzBlobConfig.SASURL != "" {
endpoint = fsConfig.AzBlobConfig.SASURL
} else {
endpoint = user.FsConfig.AzBlobConfig.Endpoint
endpoint = fsConfig.AzBlobConfig.Endpoint
}
case vfs.SFTPFilesystemProvider:
endpoint = fsConfig.SFTPConfig.Endpoint
}
if err == ErrQuotaExceeded {
@@ -117,7 +137,7 @@ func newActionNotification(
TargetPath: target,
SSHCmd: sshCmd,
FileSize: fileSize,
FsProvider: int(user.FsConfig.Provider),
FsProvider: int(fsConfig.Provider),
Bucket: bucket,
Endpoint: endpoint,
Status: status,
@@ -168,8 +188,8 @@ func (h *defaultActionHandler) handleHTTP(notification *ActionNotification) erro
}
}
logger.Debug(notification.Protocol, "", "notified operation %#v to URL: %v status code: %v, elapsed: %v err: %v", notification.Action,
u.Redacted(), respCode, time.Since(startTime), err)
logger.Debug(notification.Protocol, "", "notified operation %#v to URL: %v status code: %v, elapsed: %v err: %v",
notification.Action, u.Redacted(), respCode, time.Since(startTime), err)
return err
}