Browse Source

EventManager: add uid and extension placeholders

Signed-off-by: Nicola Murino <nicola.murino@gmail.com>
Nicola Murino 1 year ago
parent
commit
00ce4e4685

+ 2 - 0
docs/eventmanager.md

@@ -36,6 +36,7 @@ The following placeholders are supported:
 - `{{FsPath}}`. Full filesystem path, for example `/user/homedir/adir/afile.txt` or `C:/data/user/homedir/adir/afile.txt` on Windows.
 - `{{FsPath}}`. Full filesystem path, for example `/user/homedir/adir/afile.txt` or `C:/data/user/homedir/adir/afile.txt` on Windows.
 - `{{ObjectName}}`. File/directory name, for example `afile.txt` or provider object name.
 - `{{ObjectName}}`. File/directory name, for example `afile.txt` or provider object name.
 - `{{ObjectType}}`. Object type for provider events: `user`, `group`, `admin`, etc.
 - `{{ObjectType}}`. Object type for provider events: `user`, `group`, `admin`, etc.
+- `{{Ext}}`. File extension, for example `.txt` if the filename is `afile.txt`.
 - `{{VirtualTargetPath}}`. Virtual target path for renames.
 - `{{VirtualTargetPath}}`. Virtual target path for renames.
 - `{{VirtualTargetDirPath}}`. Parent directory for VirtualTargetPath.
 - `{{VirtualTargetDirPath}}`. Parent directory for VirtualTargetPath.
 - `{{TargetName}}`. Target object name for renames.
 - `{{TargetName}}`. Target object name for renames.
@@ -53,6 +54,7 @@ The following placeholders are supported:
 - `{{IDPField<fieldname>}}`. Identity Provider custom fields containing a string.
 - `{{IDPField<fieldname>}}`. Identity Provider custom fields containing a string.
 - `{{Metadata}}`. Cloud storage metadata for the downloaded file serialized as JSON.
 - `{{Metadata}}`. Cloud storage metadata for the downloaded file serialized as JSON.
 - `{{MetadataString}}`. Cloud storage metadata for the downloaded file as JSON escaped string.
 - `{{MetadataString}}`. Cloud storage metadata for the downloaded file as JSON escaped string.
+- `{{UID}}`. Unique ID.
 
 
 Event rules are based on the premise that an event occours. To each rule you can associate one or more actions.
 Event rules are based on the premise that an event occours. To each rule you can associate one or more actions.
 The following trigger events are supported:
 The following trigger events are supported:

+ 3 - 3
go.mod

@@ -5,7 +5,7 @@ go 1.21
 require (
 require (
 	cloud.google.com/go/storage v1.36.0
 	cloud.google.com/go/storage v1.36.0
 	github.com/Azure/azure-sdk-for-go/sdk/azcore v1.9.1
 	github.com/Azure/azure-sdk-for-go/sdk/azcore v1.9.1
-	github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.2.0
+	github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.2.1
 	github.com/GehirnInc/crypt v0.0.0-20230320061759-8cc1b52080c5
 	github.com/GehirnInc/crypt v0.0.0-20230320061759-8cc1b52080c5
 	github.com/alexedwards/argon2id v1.0.0
 	github.com/alexedwards/argon2id v1.0.0
 	github.com/amoghe/go-crypt v0.0.0-20220222110647-20eada5f5964
 	github.com/amoghe/go-crypt v0.0.0-20220222110647-20eada5f5964
@@ -41,7 +41,7 @@ require (
 	github.com/klauspost/compress v1.17.4
 	github.com/klauspost/compress v1.17.4
 	github.com/lestrrat-go/jwx/v2 v2.0.18
 	github.com/lestrrat-go/jwx/v2 v2.0.18
 	github.com/lithammer/shortuuid/v3 v3.0.7
 	github.com/lithammer/shortuuid/v3 v3.0.7
-	github.com/mattn/go-sqlite3 v1.14.18
+	github.com/mattn/go-sqlite3 v1.14.19
 	github.com/mhale/smtpd v0.8.1
 	github.com/mhale/smtpd v0.8.1
 	github.com/minio/sio v0.3.1
 	github.com/minio/sio v0.3.1
 	github.com/otiai10/copy v1.14.0
 	github.com/otiai10/copy v1.14.0
@@ -165,7 +165,7 @@ require (
 	go.opentelemetry.io/otel/metric v1.21.0 // indirect
 	go.opentelemetry.io/otel/metric v1.21.0 // indirect
 	go.opentelemetry.io/otel/trace v1.21.0 // indirect
 	go.opentelemetry.io/otel/trace v1.21.0 // indirect
 	go.uber.org/multierr v1.11.0 // indirect
 	go.uber.org/multierr v1.11.0 // indirect
-	golang.org/x/exp v0.0.0-20231206192017-f3f8817b8deb // indirect
+	golang.org/x/exp v0.0.0-20231214170342-aacd6d4b4611 // indirect
 	golang.org/x/mod v0.14.0 // indirect
 	golang.org/x/mod v0.14.0 // indirect
 	golang.org/x/sync v0.5.0 // indirect
 	golang.org/x/sync v0.5.0 // indirect
 	golang.org/x/text v0.14.0 // indirect
 	golang.org/x/text v0.14.0 // indirect

+ 8 - 8
go.sum

@@ -18,10 +18,10 @@ github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.4.0 h1:BMAjVKJM0U/CYF27gA0ZM
 github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.4.0/go.mod h1:1fXstnBMas5kzG+S3q8UoJcmyU6nUeunJcMDHcRYHhs=
 github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.4.0/go.mod h1:1fXstnBMas5kzG+S3q8UoJcmyU6nUeunJcMDHcRYHhs=
 github.com/Azure/azure-sdk-for-go/sdk/internal v1.5.1 h1:6oNBlSdi1QqM1PNW7FPA6xOGA5UNsXnkaYZz9vdPGhA=
 github.com/Azure/azure-sdk-for-go/sdk/internal v1.5.1 h1:6oNBlSdi1QqM1PNW7FPA6xOGA5UNsXnkaYZz9vdPGhA=
 github.com/Azure/azure-sdk-for-go/sdk/internal v1.5.1/go.mod h1:s4kgfzA0covAXNicZHDMN58jExvcng2mC/DepXiF1EI=
 github.com/Azure/azure-sdk-for-go/sdk/internal v1.5.1/go.mod h1:s4kgfzA0covAXNicZHDMN58jExvcng2mC/DepXiF1EI=
-github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/storage/armstorage v1.2.0 h1:Ma67P/GGprNwsslzEH6+Kb8nybI8jpDTm4Wmzu2ReK8=
-github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/storage/armstorage v1.2.0/go.mod h1:c+Lifp3EDEamAkPVzMooRNOK6CZjNSdEnf1A7jsI9u4=
-github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.2.0 h1:gggzg0SUMs6SQbEw+3LoSsYf9YMjkupeAnHMX8O9mmY=
-github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.2.0/go.mod h1:+6KLcKIVgxoBDMqMO/Nvy7bZ9a0nbU3I1DtFQK3YvB4=
+github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/storage/armstorage v1.5.0 h1:AifHbc4mg0x9zW52WOpKbsHaDKuRhlI7TVl47thgQ70=
+github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/storage/armstorage v1.5.0/go.mod h1:T5RfihdXtBDxt1Ch2wobif3TvzTdumDy29kahv6AV9A=
+github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.2.1 h1:AMf7YbZOZIW5b66cXNHMWWT/zkjhz5+a+k/3x40EO7E=
+github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.2.1/go.mod h1:uwfk06ZBcvL/g4VHNjurPfVln9NMbsk2XIZxJ+hu81k=
 github.com/AzureAD/microsoft-authentication-library-for-go v1.2.0 h1:hVeq+yCyUi+MsoO/CU95yqCIcdzra5ovzk8Q2BBpV2M=
 github.com/AzureAD/microsoft-authentication-library-for-go v1.2.0 h1:hVeq+yCyUi+MsoO/CU95yqCIcdzra5ovzk8Q2BBpV2M=
 github.com/AzureAD/microsoft-authentication-library-for-go v1.2.0/go.mod h1:wP83P5OoQ5p6ip3ScPr0BAq0BvuPAvacpEuSzyouqAI=
 github.com/AzureAD/microsoft-authentication-library-for-go v1.2.0/go.mod h1:wP83P5OoQ5p6ip3ScPr0BAq0BvuPAvacpEuSzyouqAI=
 github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
 github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
@@ -288,8 +288,8 @@ github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/
 github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
 github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
 github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
 github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
 github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
 github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
-github.com/mattn/go-sqlite3 v1.14.18 h1:JL0eqdCOq6DJVNPSvArO/bIV9/P7fbGrV00LZHc+5aI=
-github.com/mattn/go-sqlite3 v1.14.18/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg=
+github.com/mattn/go-sqlite3 v1.14.19 h1:fhGleo2h1p8tVChob4I9HpmVFIAkKGpiukdrgQbWfGI=
+github.com/mattn/go-sqlite3 v1.14.19/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg=
 github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 h1:jWpvCLoY8Z/e3VKvlsiIGKtc+UG6U5vzxaoagmhXfyg=
 github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 h1:jWpvCLoY8Z/e3VKvlsiIGKtc+UG6U5vzxaoagmhXfyg=
 github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0/go.mod h1:QUyp042oQthUoa9bqDv0ER0wrtXnBruoNd7aNjkbP+k=
 github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0/go.mod h1:QUyp042oQthUoa9bqDv0ER0wrtXnBruoNd7aNjkbP+k=
 github.com/mhale/smtpd v0.8.1 h1:O02u8O3eYAGxZCGf4E98WjyB+rA3DVFZtchEialjX4s=
 github.com/mhale/smtpd v0.8.1 h1:O02u8O3eYAGxZCGf4E98WjyB+rA3DVFZtchEialjX4s=
@@ -432,8 +432,8 @@ go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN8
 gocloud.dev v0.35.0 h1:x/Gtt5OJdT4j+ir1AXAIXb7bBnFawXAAaJptCUGk3HU=
 gocloud.dev v0.35.0 h1:x/Gtt5OJdT4j+ir1AXAIXb7bBnFawXAAaJptCUGk3HU=
 gocloud.dev v0.35.0/go.mod h1:wbyF+BhfdtLWyUtVEWRW13hFLb1vXnV2ovEhYGQe3ck=
 gocloud.dev v0.35.0/go.mod h1:wbyF+BhfdtLWyUtVEWRW13hFLb1vXnV2ovEhYGQe3ck=
 golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
 golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
-golang.org/x/exp v0.0.0-20231206192017-f3f8817b8deb h1:c0vyKkb6yr3KR7jEfJaOSv4lG7xPkbN6r52aJz1d8a8=
-golang.org/x/exp v0.0.0-20231206192017-f3f8817b8deb/go.mod h1:iRJReGqOEeBhDZGkGbynYwcHlctCvnjTYIamk7uXpHI=
+golang.org/x/exp v0.0.0-20231214170342-aacd6d4b4611 h1:qCEDpW1G+vcj3Y7Fy52pEM1AWm3abj8WimGYejI3SC4=
+golang.org/x/exp v0.0.0-20231214170342-aacd6d4b4611/go.mod h1:iRJReGqOEeBhDZGkGbynYwcHlctCvnjTYIamk7uXpHI=
 golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
 golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
 golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
 golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
 golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
 golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=

+ 2 - 0
internal/common/actions.go

@@ -107,6 +107,7 @@ func ExecutePreAction(conn *BaseConnection, operation, filePath, virtualPath str
 			VirtualTargetPath: event.VirtualTargetPath,
 			VirtualTargetPath: event.VirtualTargetPath,
 			FsTargetPath:      event.TargetPath,
 			FsTargetPath:      event.TargetPath,
 			ObjectName:        path.Base(event.VirtualPath),
 			ObjectName:        path.Base(event.VirtualPath),
+			Extension:         path.Ext(event.VirtualPath),
 			FileSize:          event.FileSize,
 			FileSize:          event.FileSize,
 			Protocol:          event.Protocol,
 			Protocol:          event.Protocol,
 			IP:                event.IP,
 			IP:                event.IP,
@@ -152,6 +153,7 @@ func ExecuteActionNotification(conn *BaseConnection, operation, filePath, virtua
 			VirtualTargetPath: notification.VirtualTargetPath,
 			VirtualTargetPath: notification.VirtualTargetPath,
 			FsTargetPath:      notification.TargetPath,
 			FsTargetPath:      notification.TargetPath,
 			ObjectName:        path.Base(notification.VirtualPath),
 			ObjectName:        path.Base(notification.VirtualPath),
+			Extension:         path.Ext(notification.VirtualPath),
 			FileSize:          notification.FileSize,
 			FileSize:          notification.FileSize,
 			Elapsed:           notification.Elapsed,
 			Elapsed:           notification.Elapsed,
 			Protocol:          notification.Protocol,
 			Protocol:          notification.Protocol,

+ 13 - 0
internal/common/eventmanager.go

@@ -398,6 +398,7 @@ func (r *eventRulesContainer) handleFsEvent(params EventParams) (bool, error) {
 	r.RUnlock()
 	r.RUnlock()
 
 
 	params.sender = params.Name
 	params.sender = params.Name
+	params.addUID()
 	if len(rulesAsync) > 0 {
 	if len(rulesAsync) > 0 {
 		go executeAsyncRulesActions(rulesAsync, params)
 		go executeAsyncRulesActions(rulesAsync, params)
 	}
 	}
@@ -451,6 +452,7 @@ func (r *eventRulesContainer) handleIDPLoginEvent(params EventParams, customFiel
 		return nil, nil, fmt.Errorf("more than one account check action rules matches: %q", strings.Join(ruleNames, ","))
 		return nil, nil, fmt.Errorf("more than one account check action rules matches: %q", strings.Join(ruleNames, ","))
 	}
 	}
 
 
+	params.addUID()
 	if len(rulesAsync) > 0 {
 	if len(rulesAsync) > 0 {
 		go executeAsyncRulesActions(rulesAsync, params)
 		go executeAsyncRulesActions(rulesAsync, params)
 	}
 	}
@@ -545,6 +547,7 @@ type EventParams struct {
 	VirtualTargetPath     string
 	VirtualTargetPath     string
 	FsTargetPath          string
 	FsTargetPath          string
 	ObjectName            string
 	ObjectName            string
+	Extension             string
 	ObjectType            string
 	ObjectType            string
 	FileSize              int64
 	FileSize              int64
 	Elapsed               int64
 	Elapsed               int64
@@ -553,6 +556,7 @@ type EventParams struct {
 	Role                  string
 	Role                  string
 	Email                 string
 	Email                 string
 	Timestamp             int64
 	Timestamp             int64
+	UID                   string
 	IDPCustomFields       *map[string]string
 	IDPCustomFields       *map[string]string
 	Object                plugin.Renderer
 	Object                plugin.Renderer
 	Metadata              map[string]string
 	Metadata              map[string]string
@@ -621,6 +625,12 @@ func (p *EventParams) AddError(err error) {
 	p.errors = append(p.errors, err.Error())
 	p.errors = append(p.errors, err.Error())
 }
 }
 
 
+func (p *EventParams) addUID() {
+	if p.UID == "" {
+		p.UID = util.GenerateUniqueID()
+	}
+}
+
 func (p *EventParams) setBackupParams(backupPath string) {
 func (p *EventParams) setBackupParams(backupPath string) {
 	if p.sender != "" {
 	if p.sender != "" {
 		return
 		return
@@ -781,6 +791,8 @@ func (p *EventParams) getStringReplacements(addObjectData, jsonEscaped bool) []s
 		"{{Email}}", p.getStringReplacement(p.Email, jsonEscaped),
 		"{{Email}}", p.getStringReplacement(p.Email, jsonEscaped),
 		"{{Timestamp}}", fmt.Sprintf("%d", p.Timestamp),
 		"{{Timestamp}}", fmt.Sprintf("%d", p.Timestamp),
 		"{{StatusString}}", p.getStatusString(),
 		"{{StatusString}}", p.getStatusString(),
+		"{{UID}}", p.getStringReplacement(p.UID, jsonEscaped),
+		"{{Ext}}", p.getStringReplacement(p.Extension, jsonEscaped),
 	}
 	}
 	if p.VirtualPath != "" {
 	if p.VirtualPath != "" {
 		replacements = append(replacements, "{{VirtualDirPath}}", p.getStringReplacement(path.Dir(p.VirtualPath), jsonEscaped))
 		replacements = append(replacements, "{{VirtualDirPath}}", p.getStringReplacement(path.Dir(p.VirtualPath), jsonEscaped))
@@ -2615,6 +2627,7 @@ func executeAsyncRulesActions(rules []dataprovider.EventRule, params EventParams
 	eventManager.addAsyncTask()
 	eventManager.addAsyncTask()
 	defer eventManager.removeAsyncTask()
 	defer eventManager.removeAsyncTask()
 
 
+	params.addUID()
 	for _, rule := range rules {
 	for _, rule := range rules {
 		executeRuleAsyncActions(rule, params.getACopy(), nil)
 		executeRuleAsyncActions(rule, params.getACopy(), nil)
 	}
 	}

+ 1 - 0
internal/common/eventmanager_test.go

@@ -2004,6 +2004,7 @@ func TestEventParamsCopy(t *testing.T) {
 	params := EventParams{
 	params := EventParams{
 		Name:            "name",
 		Name:            "name",
 		Event:           "event",
 		Event:           "event",
+		Extension:       "ext",
 		Status:          1,
 		Status:          1,
 		errors:          []string{"error1"},
 		errors:          []string{"error1"},
 		retentionChecks: []executedRetentionCheck{},
 		retentionChecks: []executedRetentionCheck{},

+ 6 - 0
templates/webadmin/eventaction.html

@@ -792,6 +792,9 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
                 <p>
                 <p>
                     <span class="shortcut"><b>{{`{{FsPath}}`}}</b></span> => Full filesystem path, for example "/user/homedir/adir/afile.txt" or "C:/data/user/homedir/adir/afile.txt" on Windows.
                     <span class="shortcut"><b>{{`{{FsPath}}`}}</b></span> => Full filesystem path, for example "/user/homedir/adir/afile.txt" or "C:/data/user/homedir/adir/afile.txt" on Windows.
                 </p>
                 </p>
+                <p>
+                    <span class="shortcut"><b>{{`{{Ext}}`}}</b></span> => File extension, for example ".txt" if the filename is "afile.txt".
+                </p>
                 <p>
                 <p>
                     <span class="shortcut"><b>{{`{{ObjectName}}`}}</b></span> => File/directory name, for example "afile.txt" or provider object name.
                     <span class="shortcut"><b>{{`{{ObjectName}}`}}</b></span> => File/directory name, for example "afile.txt" or provider object name.
                 </p>
                 </p>
@@ -849,6 +852,9 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
                 <p>
                 <p>
                     <span class="shortcut"><b>{{`{{MetadataString}}`}}</b></span> => Cloud storage metadata for the downloaded file as JSON escaped string.
                     <span class="shortcut"><b>{{`{{MetadataString}}`}}</b></span> => Cloud storage metadata for the downloaded file as JSON escaped string.
                 </p>
                 </p>
+                <p>
+                    <span class="shortcut"><b>{{`{{UID}}`}}</b></span> => Unique ID.
+                </p>
             </div>
             </div>
             <div class="modal-footer">
             <div class="modal-footer">
                 <button class="btn btn-primary" type="button" data-dismiss="modal">OK</button>
                 <button class="btn btn-primary" type="button" data-dismiss="modal">OK</button>