瀏覽代碼

EventManager: add placeholder for filename without extension

Fixes #1828
Fixes #1833

Co-authored-by: Per Osbeck <per.osbeck@consid.se>
Signed-off-by: Nicola Murino <nicola.murino@gmail.com>
Nicola Murino 7 月之前
父節點
當前提交
dee3f3f87a

+ 1 - 0
internal/common/eventmanager.go

@@ -799,6 +799,7 @@ func (p *EventParams) getStringReplacements(addObjectData, jsonEscaped bool) []s
 		"{{VirtualTargetPath}}", p.getStringReplacement(p.VirtualTargetPath, jsonEscaped),
 		"{{FsTargetPath}}", p.getStringReplacement(p.FsTargetPath, jsonEscaped),
 		"{{ObjectName}}", p.getStringReplacement(p.ObjectName, jsonEscaped),
+		"{{ObjectBaseName}}", p.getStringReplacement(strings.TrimSuffix(p.ObjectName, p.Extension), jsonEscaped),
 		"{{ObjectType}}", p.ObjectType,
 		"{{FileSize}}", strconv.FormatInt(p.FileSize, 10),
 		"{{Elapsed}}", strconv.FormatInt(p.Elapsed, 10),

+ 74 - 0
internal/common/protocol_test.go

@@ -4821,6 +4821,80 @@ func TestEventRuleFsActions(t *testing.T) {
 	assert.NoError(t, err)
 }
 
+func TestEventActionObjectBaseName(t *testing.T) {
+	a1 := dataprovider.BaseEventAction{
+		Name: "a1",
+		Type: dataprovider.ActionTypeFilesystem,
+		Options: dataprovider.BaseEventActionOptions{
+			FsConfig: dataprovider.EventActionFilesystemConfig{
+				Type: dataprovider.FilesystemActionRename,
+				Renames: []dataprovider.RenameConfig{
+					{
+						KeyValue: dataprovider.KeyValue{
+							Key:   "/{{VirtualDirPath}}/{{ObjectName}}",
+							Value: "/{{ObjectBaseName}}",
+						},
+					},
+				},
+			},
+		},
+	}
+	action1, resp, err := httpdtest.AddEventAction(a1, http.StatusCreated)
+	assert.NoError(t, err, string(resp))
+
+	r1 := dataprovider.EventRule{
+		Name:    "r2",
+		Status:  1,
+		Trigger: dataprovider.EventTriggerFsEvent,
+		Conditions: dataprovider.EventConditions{
+			FsEvents: []string{"upload"},
+		},
+		Actions: []dataprovider.EventAction{
+			{
+				BaseEventAction: dataprovider.BaseEventAction{
+					Name: action1.Name,
+				},
+				Order: 1,
+				Options: dataprovider.EventActionOptions{
+					ExecuteSync: true,
+				},
+			},
+		},
+	}
+	rule1, _, err := httpdtest.AddEventRule(r1, http.StatusCreated)
+	assert.NoError(t, err)
+
+	user, _, err := httpdtest.AddUser(getTestUser(), http.StatusCreated)
+	assert.NoError(t, err)
+	conn, client, err := getSftpClient(user)
+	if assert.NoError(t, err) {
+		defer conn.Close()
+		defer client.Close()
+
+		testDir := "test dir name"
+		err = client.Mkdir(testDir)
+		fileSize := int64(32768)
+		assert.NoError(t, err)
+		err = writeSFTPFileNoCheck(path.Join(testDir, testFileName), fileSize, client)
+		assert.NoError(t, err)
+
+		_, err = client.Stat(path.Join(testDir, testFileName))
+		assert.ErrorIs(t, err, os.ErrNotExist)
+
+		_, err = client.Stat(strings.TrimSuffix(testFileName, path.Ext(testFileName)))
+		assert.NoError(t, err)
+	}
+
+	_, err = httpdtest.RemoveUser(user, http.StatusOK)
+	assert.NoError(t, err)
+	err = os.RemoveAll(user.GetHomeDir())
+	assert.NoError(t, err)
+	_, err = httpdtest.RemoveEventRule(rule1, http.StatusOK)
+	assert.NoError(t, err)
+	_, err = httpdtest.RemoveEventAction(action1, http.StatusOK)
+	assert.NoError(t, err)
+}
+
 func TestUploadEventRule(t *testing.T) {
 	smtpCfg := smtp.Config{
 		Host:          "127.0.0.1",

+ 1 - 0
static/locales/en/translation.json

@@ -1065,6 +1065,7 @@
             "fs_path": "Full filesystem path, for example \"/user/homedir/adir/afile.txt\" or \"C:/data/user/homedir/adir/afile.txt\" on Windows",
             "ext": "File extension, for example \".txt\" if the filename is \"afile.txt\"",
             "object_name": "File/directory name, for example \"afile.txt\" or provider object name",
+            "object_basename": "Filename without extension, for example \"afile\" if the filename is \"afile.txt\"",
             "object_type": "Object type for provider events: \"user\", \"group\", \"admin\", etc",
             "virtual_target_path": "Virtual target path for rename and copy operations",
             "virtual_target_dir_path": "Parent directory for \"VirtualTargetPath\"",

+ 1 - 0
static/locales/it/translation.json

@@ -1065,6 +1065,7 @@
             "fs_path": "Percorso completo del filesystem, ad esempio \"/user/homedir/adir/afile.txt\" o \"C:/data/user/homedir/adir/afile.txt\" su Windows",
             "ext": "Estensione del file, ad esempio \".txt\" se il nome del file è \"afile.txt\"",
             "object_name": "Nome del file/directory, ad esempio \"afile.txt\" o nome dell'oggetto del provider",
+            "object_basename": "Nome del file senza estensione, ad esempio \"afile\" se il nome del file è \"afile.txt\"",
             "object_type": "Tipo di oggetto per gli eventi provider: \"user\", \"group\", \"admin\", ecc",
             "virtual_target_path": "Percorso di destinazione virtuale per le operazioni di ridenominazione e copia",
             "virtual_target_dir_path": "Cartella superiore per \"VirtualTargetPath\"",

+ 3 - 0
templates/webadmin/eventaction.html

@@ -921,6 +921,9 @@ explicit grant from the SFTPGo Team (support@sftpgo.com).
                 <p>
                     <span class="shortcut">{{`{{ObjectName}}`}}</span> => <span data-i18n="actions.placeholders_modal.object_name">File/directory name, for example "afile.txt" or provider object name.</span>
                 </p>
+                <p>
+                    <span class="shortcut">{{`{{ObjectBaseName}}`}}</span> => <span data-i18n="actions.placeholders_modal.object_basename">Filename without extension, for example "afile" if the filename is "afile.txt".</span>
+                </p>
                 <p>
                     <span class="shortcut">{{`{{ObjectType}}`}}</span> => <span data-i18n="actions.placeholders_modal.object_type">Object type for provider events: "user", "group", "admin", etc.</span>
                 </p>