| 
					
				 | 
			
			
				@@ -34,8 +34,29 @@ type ProtocolActions struct { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	Hook string `json:"hook" mapstructure:"hook"` 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-// actionNotification defines a notification for a Protocol Action 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-type actionNotification struct { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+var actionHandler ActionHandler = defaultActionHandler{} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+// InitializeActionHandler lets the user choose an action handler implementation. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+// 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+// Do NOT call this function after application initialization. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+func InitializeActionHandler(handler ActionHandler) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	actionHandler = handler 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+// SSHCommandActionNotification executes the defined action for the specified SSH command. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+func SSHCommandActionNotification(user *dataprovider.User, filePath, target, sshCmd string, err error) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	notification := newActionNotification(user, operationSSHCmd, filePath, target, sshCmd, ProtocolSSH, 0, err) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	go actionHandler.Handle(notification) // nolint:errcheck 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+// ActionHandler handles a notification for a Protocol Action. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+type ActionHandler interface { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	Handle(notification ActionNotification) error 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+// ActionNotification defines a notification for a Protocol Action. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+type ActionNotification struct { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	Action     string `json:"action"` 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	Username   string `json:"username"` 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	Path       string `json:"path"` 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -49,29 +70,29 @@ type actionNotification struct { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	Protocol   string `json:"protocol"` 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-// SSHCommandActionNotification executes the defined action for the specified SSH command 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-func SSHCommandActionNotification(user *dataprovider.User, filePath, target, sshCmd string, err error) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	action := newActionNotification(user, operationSSHCmd, filePath, target, sshCmd, ProtocolSSH, 0, err) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	go action.execute() //nolint:errcheck 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-func newActionNotification(user *dataprovider.User, operation, filePath, target, sshCmd, protocol string, fileSize int64, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	err error) actionNotification { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	bucket := "" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	endpoint := "" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+func newActionNotification( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	user *dataprovider.User, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	operation, filePath, target, sshCmd, protocol string, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	fileSize int64, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	err error, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+) ActionNotification { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	var bucket, endpoint string 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	status := 1 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	if user.FsConfig.Provider == dataprovider.S3FilesystemProvider { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		bucket = user.FsConfig.S3Config.Bucket 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		endpoint = user.FsConfig.S3Config.Endpoint 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	} else if user.FsConfig.Provider == dataprovider.GCSFilesystemProvider { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		bucket = user.FsConfig.GCSConfig.Bucket 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	if err == ErrQuotaExceeded { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		status = 2 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	} else if err != nil { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		status = 0 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	return actionNotification{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	return ActionNotification{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		Action:     operation, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		Username:   user.Username, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		Path:       filePath, 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -86,72 +107,92 @@ func newActionNotification(user *dataprovider.User, operation, filePath, target, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-func (a *actionNotification) asJSON() []byte { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	res, _ := json.Marshal(a) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	return res 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+type defaultActionHandler struct{} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+func (h defaultActionHandler) Handle(notification ActionNotification) error { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	if !utils.IsStringInSlice(notification.Action, Config.Actions.ExecuteOn) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		return errUnconfiguredAction 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	if Config.Actions.Hook == "" { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		logger.Warn(notification.Protocol, "", "Unable to send notification, no hook is defined") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		return errNoHook 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	if strings.HasPrefix(Config.Actions.Hook, "http") { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		return h.handleHTTP(notification) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	return h.handleCommand(notification) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-func (a *actionNotification) asEnvVars() []string { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	return []string{fmt.Sprintf("SFTPGO_ACTION=%v", a.Action), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		fmt.Sprintf("SFTPGO_ACTION_USERNAME=%v", a.Username), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		fmt.Sprintf("SFTPGO_ACTION_PATH=%v", a.Path), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		fmt.Sprintf("SFTPGO_ACTION_TARGET=%v", a.TargetPath), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		fmt.Sprintf("SFTPGO_ACTION_SSH_CMD=%v", a.SSHCmd), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		fmt.Sprintf("SFTPGO_ACTION_FILE_SIZE=%v", a.FileSize), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		fmt.Sprintf("SFTPGO_ACTION_FS_PROVIDER=%v", a.FsProvider), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		fmt.Sprintf("SFTPGO_ACTION_BUCKET=%v", a.Bucket), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		fmt.Sprintf("SFTPGO_ACTION_ENDPOINT=%v", a.Endpoint), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		fmt.Sprintf("SFTPGO_ACTION_STATUS=%v", a.Status), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		fmt.Sprintf("SFTPGO_ACTION_PROTOCOL=%v", a.Protocol), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+func (h defaultActionHandler) handleHTTP(notification ActionNotification) error { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	u, err := url.Parse(Config.Actions.Hook) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	if err != nil { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		logger.Warn(notification.Protocol, "", "Invalid hook %#v for operation %#v: %v", Config.Actions.Hook, notification.Action, err) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		return err 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	startTime := time.Now() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	respCode := 0 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	httpClient := httpclient.GetHTTPClient() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	var b bytes.Buffer 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	_ = json.NewEncoder(&b).Encode(notification) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	resp, err := httpClient.Post(u.String(), "application/json", &b) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	if err == nil { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		respCode = resp.StatusCode 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		resp.Body.Close() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		if respCode != http.StatusOK { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			err = errUnexpectedHTTResponse 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	logger.Debug(notification.Protocol, "", "notified operation %#v to URL: %v status code: %v, elapsed: %v err: %v", notification.Action, u.String(), respCode, time.Since(startTime), err) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	return err 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-func (a *actionNotification) executeNotificationCommand() error { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+func (h defaultActionHandler) handleCommand(notification ActionNotification) error { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	if !filepath.IsAbs(Config.Actions.Hook) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		err := fmt.Errorf("invalid notification command %#v", Config.Actions.Hook) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		logger.Warn(a.Protocol, "", "unable to execute notification command: %v", err) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		logger.Warn(notification.Protocol, "", "unable to execute notification command: %v", err) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		return err 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	defer cancel() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	cmd := exec.CommandContext(ctx, Config.Actions.Hook, a.Action, a.Username, a.Path, a.TargetPath, a.SSHCmd) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	cmd.Env = append(os.Environ(), a.asEnvVars()...) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	cmd := exec.CommandContext(ctx, Config.Actions.Hook, notification.Action, notification.Username, notification.Path, notification.TargetPath, notification.SSHCmd) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	cmd.Env = append(os.Environ(), notificationAsEnvVars(notification)...) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	startTime := time.Now() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	err := cmd.Run() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	logger.Debug(a.Protocol, "", "executed command %#v with arguments: %#v, %#v, %#v, %#v, %#v, elapsed: %v, error: %v", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		Config.Actions.Hook, a.Action, a.Username, a.Path, a.TargetPath, a.SSHCmd, time.Since(startTime), err) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	logger.Debug(notification.Protocol, "", "executed command %#v with arguments: %#v, %#v, %#v, %#v, %#v, elapsed: %v, error: %v", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		Config.Actions.Hook, notification.Action, notification.Username, notification.Path, notification.TargetPath, notification.SSHCmd, time.Since(startTime), err) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	return err 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-func (a *actionNotification) execute() error { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	if !utils.IsStringInSlice(a.Action, Config.Actions.ExecuteOn) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		return errUnconfiguredAction 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	if len(Config.Actions.Hook) == 0 { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		logger.Warn(a.Protocol, "", "Unable to send notification, no hook is defined") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		return errNoHook 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	if strings.HasPrefix(Config.Actions.Hook, "http") { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		var url *url.URL 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		url, err := url.Parse(Config.Actions.Hook) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		if err != nil { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-			logger.Warn(a.Protocol, "", "Invalid hook %#v for operation %#v: %v", Config.Actions.Hook, a.Action, err) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-			return err 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		startTime := time.Now() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		httpClient := httpclient.GetHTTPClient() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		resp, err := httpClient.Post(url.String(), "application/json", bytes.NewBuffer(a.asJSON())) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		respCode := 0 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		if err == nil { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-			respCode = resp.StatusCode 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-			resp.Body.Close() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-			if respCode != http.StatusOK { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-				err = errUnexpectedHTTResponse 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-			} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		logger.Debug(a.Protocol, "", "notified operation %#v to URL: %v status code: %v, elapsed: %v err: %v", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-			a.Action, url.String(), respCode, time.Since(startTime), err) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		return err 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+func notificationAsEnvVars(notification ActionNotification) []string { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	return []string{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		fmt.Sprintf("SFTPGO_ACTION=%v", notification.Action), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		fmt.Sprintf("SFTPGO_ACTION_USERNAME=%v", notification.Username), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		fmt.Sprintf("SFTPGO_ACTION_PATH=%v", notification.Path), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		fmt.Sprintf("SFTPGO_ACTION_TARGET=%v", notification.TargetPath), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		fmt.Sprintf("SFTPGO_ACTION_SSH_CMD=%v", notification.SSHCmd), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		fmt.Sprintf("SFTPGO_ACTION_FILE_SIZE=%v", notification.FileSize), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		fmt.Sprintf("SFTPGO_ACTION_FS_PROVIDER=%v", notification.FsProvider), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		fmt.Sprintf("SFTPGO_ACTION_BUCKET=%v", notification.Bucket), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		fmt.Sprintf("SFTPGO_ACTION_ENDPOINT=%v", notification.Endpoint), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		fmt.Sprintf("SFTPGO_ACTION_STATUS=%v", notification.Status), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		fmt.Sprintf("SFTPGO_ACTION_PROTOCOL=%v", notification.Protocol), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	return a.executeNotificationCommand() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 |