add role to events

Signed-off-by: Nicola Murino <nicola.murino@gmail.com>
This commit is contained in:
Nicola Murino 2022-12-03 11:45:27 +01:00
parent e87118d2a8
commit 1f9cf194fe
No known key found for this signature in database
GPG key ID: 935D2952DEC4EECF
50 changed files with 536 additions and 444 deletions

View file

@ -49,6 +49,7 @@ If the `hook` defines a path to an external program, then this program can read
- `SFTPGO_ACTION_IP`, the action was executed from this IP address - `SFTPGO_ACTION_IP`, the action was executed from this IP address
- `SFTPGO_ACTION_SESSION_ID`, string. Unique protocol session identifier. For stateless protocols such as HTTP the session id will change for each request - `SFTPGO_ACTION_SESSION_ID`, string. Unique protocol session identifier. For stateless protocols such as HTTP the session id will change for each request
- `SFTPGO_ACTION_OPEN_FLAGS`, integer. File open flags, can be non-zero for `pre-upload` action. If `SFTPGO_ACTION_FILE_SIZE` is greater than zero and `SFTPGO_ACTION_OPEN_FLAGS&512 == 0` the target file will not be truncated - `SFTPGO_ACTION_OPEN_FLAGS`, integer. File open flags, can be non-zero for `pre-upload` action. If `SFTPGO_ACTION_FILE_SIZE` is greater than zero and `SFTPGO_ACTION_OPEN_FLAGS&512 == 0` the target file will not be truncated
- `SFTPGO_ACTION_ROLE`, string. Role of the user who executed the action
- `SFTPGO_ACTION_TIMESTAMP`, int64. Event timestamp as nanoseconds since epoch - `SFTPGO_ACTION_TIMESTAMP`, int64. Event timestamp as nanoseconds since epoch
Global environment variables are cleared, for security reasons, when the script is called. You can set additional environment variables in the "command" configuration section. Global environment variables are cleared, for security reasons, when the script is called. You can set additional environment variables in the "command" configuration section.
@ -72,6 +73,7 @@ If the `hook` defines an HTTP URL then this URL will be invoked as HTTP POST. Th
- `ip`, string. The action was executed from this IP address - `ip`, string. The action was executed from this IP address
- `session_id`, string. Unique protocol session identifier. For stateless protocols such as HTTP the session id will change for each request - `session_id`, string. Unique protocol session identifier. For stateless protocols such as HTTP the session id will change for each request
- `open_flags`, integer. File open flags, can be non-zero for `pre-upload` action. If `file_size` is greater than zero and `file_size&512 == 0` the target file will not be truncated - `open_flags`, integer. File open flags, can be non-zero for `pre-upload` action. If `file_size` is greater than zero and `file_size&512 == 0` the target file will not be truncated
- `role`, string. Included if the user who executed the action has a role
- `timestamp`, int64. Event timestamp as nanoseconds since epoch - `timestamp`, int64. Event timestamp as nanoseconds since epoch
The HTTP hook will use the global configuration for HTTP clients and will respect the retry configurations. The HTTP hook will use the global configuration for HTTP clients and will respect the retry configurations.
@ -102,15 +104,16 @@ If the `hook` defines a path to an external program, then this program can read
- `SFTPGO_PROVIDER_ACTION`, supported values are `add`, `update`, `delete` - `SFTPGO_PROVIDER_ACTION`, supported values are `add`, `update`, `delete`
- `SFTPGO_PROVIDER_OBJECT_TYPE`, affected object type - `SFTPGO_PROVIDER_OBJECT_TYPE`, affected object type
- `SFTPGO_PROVIDER_OBJECT_NAME`, unique identifier for the affected object, for example username or key id - `SFTPGO_PROVIDER_OBJECT_NAME`, unique identifier for the affected object, for example username or key id
- `SFTPGO_PROVIDER_USERNAME`, the username that executed the action. There are two special usernames: `__self__` identifies a user/admin that updates itself and `__system__` identifies an action that does not have an explicit executor associated with it, for example users/admins can be added/updated by loading them from initial data - `SFTPGO_PROVIDER_USERNAME`, the admin username that executed the action. There are two special usernames: `__self__` identifies a user/admin that updates itself and `__system__` identifies an action that does not have an explicit executor associated with it, for example users/admins can be added/updated by loading them from initial data
- `SFTPGO_PROVIDER_IP`, the action was executed from this IP address - `SFTPGO_PROVIDER_IP`, the action was executed from this IP address
- `SFTPGO_PROVIDER_ROLE`, the action was executed by an admin with this role
- `SFTPGO_PROVIDER_TIMESTAMP`, event timestamp as nanoseconds since epoch - `SFTPGO_PROVIDER_TIMESTAMP`, event timestamp as nanoseconds since epoch
- `SFTPGO_PROVIDER_OBJECT`, object serialized as JSON with sensitive fields removed - `SFTPGO_PROVIDER_OBJECT`, object serialized as JSON with sensitive fields removed
Global environment variables are cleared, for security reasons, when the script is called. You can set additional environment variables in the "command" configuration section. Global environment variables are cleared, for security reasons, when the script is called. You can set additional environment variables in the "command" configuration section.
The program must finish within 15 seconds. The program must finish within 15 seconds.
If the `hook` defines an HTTP URL then this URL will be invoked as HTTP POST. The action, username, ip, object_type and object_name and timestamp are added to the query string, for example `<hook>?action=update&username=admin&ip=127.0.0.1&object_type=user&object_name=user1&timestamp=1633860803249`, and the full object is sent serialized as JSON inside the POST body with sensitive fields removed. If the `hook` defines an HTTP URL then this URL will be invoked as HTTP POST. The action, username, ip, object_type and object_name and timestamp and role are added to the query string, for example `<hook>?action=update&username=admin&ip=127.0.0.1&object_type=user&object_name=user1&timestamp=1633860803249`, and the full object is sent serialized as JSON inside the POST body with sensitive fields removed. The role is added only if not empty.
The HTTP hook will use the global configuration for HTTP clients and will respect the retry configurations. The HTTP hook will use the global configuration for HTTP clients and will respect the retry configurations.

View file

@ -39,6 +39,7 @@ The following placeholders are supported:
- `{{FileSize}}`. File size. - `{{FileSize}}`. File size.
- `{{Protocol}}`. Used protocol, for example `SFTP`, `FTP`. - `{{Protocol}}`. Used protocol, for example `SFTP`, `FTP`.
- `{{IP}}`. Client IP address. - `{{IP}}`. Client IP address.
- `{{Role}}`. User or admin role.
- `{{Timestamp}}`. Event timestamp as nanoseconds since epoch. - `{{Timestamp}}`. Event timestamp as nanoseconds since epoch.
- `{{ObjectData}}`. Provider object data serialized as JSON with sensitive fields removed. - `{{ObjectData}}`. Provider object data serialized as JSON with sensitive fields removed.
- `{{RetentionReports}}`. Data retention reports as zip compressed CSV files. Supported as email attachment, file path for multipart HTTP request and as single parameter for HTTP requests body. Data retention reports contain details on the number of files deleted and the total size deleted for each folder. - `{{RetentionReports}}`. Data retention reports as zip compressed CSV files. Supported as email attachment, file path for multipart HTTP request and as single parameter for HTTP requests body. Data retention reports contain details on the number of files deleted and the total size deleted for each folder.

58
go.mod
View file

@ -3,20 +3,20 @@ module github.com/drakkan/sftpgo/v2
go 1.19 go 1.19
require ( require (
cloud.google.com/go/storage v1.28.0 cloud.google.com/go/storage v1.28.1
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.2.0 github.com/Azure/azure-sdk-for-go/sdk/azcore v1.2.0
github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v0.5.1 github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v0.5.1
github.com/GehirnInc/crypt v0.0.0-20200316065508-bb7000b8a962 github.com/GehirnInc/crypt v0.0.0-20200316065508-bb7000b8a962
github.com/alexedwards/argon2id v0.0.0-20211130144151-3585854a6387 github.com/alexedwards/argon2id v0.0.0-20211130144151-3585854a6387
github.com/aws/aws-sdk-go-v2 v1.17.1 github.com/aws/aws-sdk-go-v2 v1.17.2
github.com/aws/aws-sdk-go-v2/config v1.18.3 github.com/aws/aws-sdk-go-v2/config v1.18.4
github.com/aws/aws-sdk-go-v2/credentials v1.13.3 github.com/aws/aws-sdk-go-v2/credentials v1.13.4
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.12.19 github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.12.20
github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.11.42 github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.11.43
github.com/aws/aws-sdk-go-v2/service/marketplacemetering v1.13.24 github.com/aws/aws-sdk-go-v2/service/marketplacemetering v1.13.25
github.com/aws/aws-sdk-go-v2/service/s3 v1.29.4 github.com/aws/aws-sdk-go-v2/service/s3 v1.29.5
github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.16.8 github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.16.9
github.com/aws/aws-sdk-go-v2/service/sts v1.17.5 github.com/aws/aws-sdk-go-v2/service/sts v1.17.6
github.com/cockroachdb/cockroach-go/v2 v2.2.19 github.com/cockroachdb/cockroach-go/v2 v2.2.19
github.com/coreos/go-oidc/v3 v3.4.0 github.com/coreos/go-oidc/v3 v3.4.0
github.com/drakkan/webdav v0.0.0-20221101181759-17ed21f9337b github.com/drakkan/webdav v0.0.0-20221101181759-17ed21f9337b
@ -27,7 +27,7 @@ require (
github.com/go-chi/chi/v5 v5.0.8-0.20221018120124-e5529d9db4d3 github.com/go-chi/chi/v5 v5.0.8-0.20221018120124-e5529d9db4d3
github.com/go-chi/jwtauth/v5 v5.1.0 github.com/go-chi/jwtauth/v5 v5.1.0
github.com/go-chi/render v1.0.2 github.com/go-chi/render v1.0.2
github.com/go-sql-driver/mysql v1.6.0 github.com/go-sql-driver/mysql v1.7.0
github.com/golang/mock v1.6.0 github.com/golang/mock v1.6.0
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510
github.com/google/uuid v1.3.0 github.com/google/uuid v1.3.0
@ -51,8 +51,8 @@ require (
github.com/rs/cors v1.8.3-0.20220619195839-da52b0701de5 github.com/rs/cors v1.8.3-0.20220619195839-da52b0701de5
github.com/rs/xid v1.4.0 github.com/rs/xid v1.4.0
github.com/rs/zerolog v1.28.0 github.com/rs/zerolog v1.28.0
github.com/sftpgo/sdk v0.1.3-0.20221116180328-3fc64e926700 github.com/sftpgo/sdk v0.1.3-0.20221203095324-2feef3600930
github.com/shirou/gopsutil/v3 v3.22.10 github.com/shirou/gopsutil/v3 v3.22.11
github.com/spf13/afero v1.9.3 github.com/spf13/afero v1.9.3
github.com/spf13/cobra v1.6.1 github.com/spf13/cobra v1.6.1
github.com/spf13/viper v1.14.0 github.com/spf13/viper v1.14.0
@ -77,23 +77,23 @@ require (
require ( require (
cloud.google.com/go v0.107.0 // indirect cloud.google.com/go v0.107.0 // indirect
cloud.google.com/go/compute v1.12.1 // indirect cloud.google.com/go/compute v1.13.0 // indirect
cloud.google.com/go/compute/metadata v0.2.1 // indirect cloud.google.com/go/compute/metadata v0.2.2 // indirect
cloud.google.com/go/iam v0.7.0 // indirect cloud.google.com/go/iam v0.7.0 // indirect
github.com/Azure/azure-sdk-for-go/sdk/internal v1.1.1 // indirect github.com/Azure/azure-sdk-for-go/sdk/internal v1.1.1 // indirect
github.com/ajg/form v1.5.1 // indirect github.com/ajg/form v1.5.1 // indirect
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.4.9 // indirect github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.4.10 // indirect
github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.25 // indirect github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.26 // indirect
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.19 // indirect github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.20 // indirect
github.com/aws/aws-sdk-go-v2/internal/ini v1.3.26 // indirect github.com/aws/aws-sdk-go-v2/internal/ini v1.3.27 // indirect
github.com/aws/aws-sdk-go-v2/internal/v4a v1.0.16 // indirect github.com/aws/aws-sdk-go-v2/internal/v4a v1.0.17 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.9.10 // indirect github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.9.11 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.1.20 // indirect github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.1.21 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.19 // indirect github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.20 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.13.19 // indirect github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.13.20 // indirect
github.com/aws/aws-sdk-go-v2/service/sso v1.11.25 // indirect github.com/aws/aws-sdk-go-v2/service/sso v1.11.26 // indirect
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.13.8 // indirect github.com/aws/aws-sdk-go-v2/service/ssooidc v1.13.9 // indirect
github.com/aws/smithy-go v1.13.4 // indirect github.com/aws/smithy-go v1.13.5 // indirect
github.com/beorn7/perks v1.0.1 // indirect github.com/beorn7/perks v1.0.1 // indirect
github.com/boombuler/barcode v1.0.1 // indirect github.com/boombuler/barcode v1.0.1 // indirect
github.com/cenkalti/backoff/v4 v4.2.0 // indirect github.com/cenkalti/backoff/v4 v4.2.0 // indirect
@ -115,7 +115,7 @@ require (
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
github.com/hashicorp/hcl v1.0.0 // indirect github.com/hashicorp/hcl v1.0.0 // indirect
github.com/hashicorp/yamux v0.1.1 // indirect github.com/hashicorp/yamux v0.1.1 // indirect
github.com/inconshreveable/mousetrap v1.0.1 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/jackc/pgpassfile v1.0.0 // indirect github.com/jackc/pgpassfile v1.0.0 // indirect
github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b // indirect github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b // indirect
github.com/jmespath/go-jmespath v0.4.0 // indirect github.com/jmespath/go-jmespath v0.4.0 // indirect
@ -158,7 +158,7 @@ require (
golang.org/x/tools v0.3.0 // indirect golang.org/x/tools v0.3.0 // indirect
golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect
google.golang.org/appengine v1.6.7 // indirect google.golang.org/appengine v1.6.7 // indirect
google.golang.org/genproto v0.0.0-20221118155620-16455021b5e6 // indirect google.golang.org/genproto v0.0.0-20221202195650-67e5cbc046fd // indirect
google.golang.org/grpc v1.51.0 // indirect google.golang.org/grpc v1.51.0 // indirect
google.golang.org/protobuf v1.28.1 // indirect google.golang.org/protobuf v1.28.1 // indirect
gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/ini.v1 v1.67.0 // indirect

116
go.sum
View file

@ -50,10 +50,10 @@ cloud.google.com/go/compute v1.5.0/go.mod h1:9SMHyhJlzhlkJqrPAc839t2BZFTSk6Jdj6m
cloud.google.com/go/compute v1.6.0/go.mod h1:T29tfhtVbq1wvAPo0E3+7vhgmkOYeXjhFvz/FMzPu0s= cloud.google.com/go/compute v1.6.0/go.mod h1:T29tfhtVbq1wvAPo0E3+7vhgmkOYeXjhFvz/FMzPu0s=
cloud.google.com/go/compute v1.6.1/go.mod h1:g85FgpzFvNULZ+S8AYq87axRKuf2Kh7deLqV/jJ3thU= cloud.google.com/go/compute v1.6.1/go.mod h1:g85FgpzFvNULZ+S8AYq87axRKuf2Kh7deLqV/jJ3thU=
cloud.google.com/go/compute v1.7.0/go.mod h1:435lt8av5oL9P3fv1OEzSbSUe+ybHXGMPQHHZWZxy9U= cloud.google.com/go/compute v1.7.0/go.mod h1:435lt8av5oL9P3fv1OEzSbSUe+ybHXGMPQHHZWZxy9U=
cloud.google.com/go/compute v1.12.1 h1:gKVJMEyqV5c/UnpzjjQbo3Rjvvqpr9B1DFSbJC4OXr0= cloud.google.com/go/compute v1.13.0 h1:AYrLkB8NPdDRslNp4Jxmzrhdr03fUAIDbiGFjLWowoU=
cloud.google.com/go/compute v1.12.1/go.mod h1:e8yNOBcBONZU1vJKCvCoDw/4JQsA0dpM4x/6PIIOocU= cloud.google.com/go/compute v1.13.0/go.mod h1:5aPTS0cUNMIc1CE546K+Th6weJUNQErARyZtRXDJ8GE=
cloud.google.com/go/compute/metadata v0.2.1 h1:efOwf5ymceDhK6PKMnnrTHP4pppY5L22mle96M1yP48= cloud.google.com/go/compute/metadata v0.2.2 h1:aWKAjYaBaOSrpKl57+jnS/3fJRQnxL7TvR/u1VVbt6k=
cloud.google.com/go/compute/metadata v0.2.1/go.mod h1:jgHgmJd2RKBGzXqF5LR2EZMGxBkeanZ9wwa75XHJgOM= cloud.google.com/go/compute/metadata v0.2.2/go.mod h1:jgHgmJd2RKBGzXqF5LR2EZMGxBkeanZ9wwa75XHJgOM=
cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE=
cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk=
cloud.google.com/go/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk= cloud.google.com/go/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk=
@ -82,8 +82,8 @@ cloud.google.com/go/storage v1.14.0/go.mod h1:GrKmX003DSIwi9o29oFT7YDnHYwZoctc3f
cloud.google.com/go/storage v1.22.1/go.mod h1:S8N1cAStu7BOeFfE8KAQzmyyLkK8p/vmRq6kuBTW58Y= cloud.google.com/go/storage v1.22.1/go.mod h1:S8N1cAStu7BOeFfE8KAQzmyyLkK8p/vmRq6kuBTW58Y=
cloud.google.com/go/storage v1.23.0/go.mod h1:vOEEDNFnciUMhBeT6hsJIn3ieU5cFRmzeLgDvXzfIXc= cloud.google.com/go/storage v1.23.0/go.mod h1:vOEEDNFnciUMhBeT6hsJIn3ieU5cFRmzeLgDvXzfIXc=
cloud.google.com/go/storage v1.24.0/go.mod h1:3xrJEFMXBsQLgxwThyjuD3aYlroL0TMRec1ypGUQ0KE= cloud.google.com/go/storage v1.24.0/go.mod h1:3xrJEFMXBsQLgxwThyjuD3aYlroL0TMRec1ypGUQ0KE=
cloud.google.com/go/storage v1.28.0 h1:DLrIZ6xkeZX6K70fU/boWx5INJumt6f+nwwWSHXzzGY= cloud.google.com/go/storage v1.28.1 h1:F5QDG5ChchaAVQhINh24U99OWHURqrW8OmQcGKXcbgI=
cloud.google.com/go/storage v1.28.0/go.mod h1:qlgZML35PXA3zoEnIkiPLY4/TOkUleufRlu6qmcf7sI= cloud.google.com/go/storage v1.28.1/go.mod h1:Qnisd4CqDdo6BGs2AD5LLnEsmSQ80wQ5ogcBBKhU86Y=
cloud.google.com/go/trace v1.0.0/go.mod h1:4iErSByzxkyHWzzlAj63/Gmjz0NH1ASqhJguHpGcr6A= cloud.google.com/go/trace v1.0.0/go.mod h1:4iErSByzxkyHWzzlAj63/Gmjz0NH1ASqhJguHpGcr6A=
cloud.google.com/go/trace v1.2.0/go.mod h1:Wc8y/uYyOhPy12KEnXG9XGrvfMz5F5SrYecQlbW1rwM= cloud.google.com/go/trace v1.2.0/go.mod h1:Wc8y/uYyOhPy12KEnXG9XGrvfMz5F5SrYecQlbW1rwM=
code.cloudfoundry.org/clock v0.0.0-20180518195852-02e53af36e6c/go.mod h1:QD9Lzhd/ux6eNQVUDVRJX/RKTigpewimNYBi7ivZKY8= code.cloudfoundry.org/clock v0.0.0-20180518195852-02e53af36e6c/go.mod h1:QD9Lzhd/ux6eNQVUDVRJX/RKTigpewimNYBi7ivZKY8=
@ -227,70 +227,70 @@ github.com/aws/aws-sdk-go v1.44.45/go.mod h1:y4AeaBuwd2Lk+GepC1E9v0qOiTws0MIWAX4
github.com/aws/aws-sdk-go v1.44.68/go.mod h1:y4AeaBuwd2Lk+GepC1E9v0qOiTws0MIWAX4oIKwKHZo= github.com/aws/aws-sdk-go v1.44.68/go.mod h1:y4AeaBuwd2Lk+GepC1E9v0qOiTws0MIWAX4oIKwKHZo=
github.com/aws/aws-sdk-go-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g= github.com/aws/aws-sdk-go-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g=
github.com/aws/aws-sdk-go-v2 v1.16.8/go.mod h1:6CpKuLXg2w7If3ABZCl/qZ6rEgwtjZTn4eAf4RcEyuw= github.com/aws/aws-sdk-go-v2 v1.16.8/go.mod h1:6CpKuLXg2w7If3ABZCl/qZ6rEgwtjZTn4eAf4RcEyuw=
github.com/aws/aws-sdk-go-v2 v1.17.1 h1:02c72fDJr87N8RAC2s3Qu0YuvMRZKNZJ9F+lAehCazk= github.com/aws/aws-sdk-go-v2 v1.17.2 h1:r0yRZInwiPBNpQ4aDy/Ssh3ROWsGtKDwar2JS8Lm+N8=
github.com/aws/aws-sdk-go-v2 v1.17.1/go.mod h1:JLnGeGONAyi2lWXI1p0PCIOIy333JMVK1U7Hf0aRFLw= github.com/aws/aws-sdk-go-v2 v1.17.2/go.mod h1:uzbQtefpm44goOPmdKyAlXSNcwlRgF3ePWVW6EtJvvw=
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.4.3/go.mod h1:gNsR5CaXKmQSSzrmGxmwmct/r+ZBfbxorAuXYsj/M5Y= github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.4.3/go.mod h1:gNsR5CaXKmQSSzrmGxmwmct/r+ZBfbxorAuXYsj/M5Y=
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.4.9 h1:RKci2D7tMwpvGpDNZnGQw9wk6v7o/xSwFcUAuNPoB8k= github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.4.10 h1:dK82zF6kkPeCo8J1e+tGx4JdvDIQzj7ygIoLg8WMuGs=
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.4.9/go.mod h1:vCmV1q1VK8eoQJ5+aYE7PkK1K6v41qJ5pJdK3ggCDvg= github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.4.10/go.mod h1:VeTZetY5KRJLuD/7fkQXMU6Mw7H5m/KP2J5Iy9osMno=
github.com/aws/aws-sdk-go-v2/config v1.15.15/go.mod h1:A1Lzyy/o21I5/s2FbyX5AevQfSVXpvvIDCoVFD0BC4E= github.com/aws/aws-sdk-go-v2/config v1.15.15/go.mod h1:A1Lzyy/o21I5/s2FbyX5AevQfSVXpvvIDCoVFD0BC4E=
github.com/aws/aws-sdk-go-v2/config v1.18.3 h1:3kfBKcX3votFX84dm00U8RGA1sCCh3eRMOGzg5dCWfU= github.com/aws/aws-sdk-go-v2/config v1.18.4 h1:VZKhr3uAADXHStS/Gf9xSYVmmaluTUfkc0dcbPiDsKE=
github.com/aws/aws-sdk-go-v2/config v1.18.3/go.mod h1:BYdrbeCse3ZnOD5+2/VE/nATOK8fEUpBtmPMdKSyhMU= github.com/aws/aws-sdk-go-v2/config v1.18.4/go.mod h1:EZxMPLSdGAZ3eAmkqXfYbRppZJTzFTkv8VyEzJhKko4=
github.com/aws/aws-sdk-go-v2/credentials v1.12.10/go.mod h1:g5eIM5XRs/OzIIK81QMBl+dAuDyoLN0VYaLP+tBqEOk= github.com/aws/aws-sdk-go-v2/credentials v1.12.10/go.mod h1:g5eIM5XRs/OzIIK81QMBl+dAuDyoLN0VYaLP+tBqEOk=
github.com/aws/aws-sdk-go-v2/credentials v1.13.3 h1:ur+FHdp4NbVIv/49bUjBW+FE7e57HOo03ELodttmagk= github.com/aws/aws-sdk-go-v2/credentials v1.13.4 h1:nEbHIyJy7mCvQ/kzGG7VWHSBpRB4H6sJy3bWierWUtg=
github.com/aws/aws-sdk-go-v2/credentials v1.13.3/go.mod h1:/rOMmqYBcFfNbRPU0iN9IgGqD5+V2yp3iWNmIlz0wI4= github.com/aws/aws-sdk-go-v2/credentials v1.13.4/go.mod h1:/Cj5w9LRsNTLSwexsohwDME32OzJ6U81Zs33zr2ZWOM=
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.12.9/go.mod h1:KDCCm4ONIdHtUloDcFvK2+vshZvx4Zmj7UMDfusuz5s= github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.12.9/go.mod h1:KDCCm4ONIdHtUloDcFvK2+vshZvx4Zmj7UMDfusuz5s=
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.12.19 h1:E3PXZSI3F2bzyj6XxUXdTIfvp425HHhwKsFvmzBwHgs= github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.12.20 h1:tpNOglTZ8kg9T38NpcGBxudqfUAwUzyUnLQ4XSd0CHE=
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.12.19/go.mod h1:VihW95zQpeKQWVPGkwT+2+WJNQV8UXFfMTWdU6VErL8= github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.12.20/go.mod h1:d9xFpWd3qYwdIXM0fvu7deD08vvdRXyc/ueV+0SqaWE=
github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.11.21/go.mod h1:iIYPrQ2rYfZiB/iADYlhj9HHZ9TTi6PqKQPAqygohbE= github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.11.21/go.mod h1:iIYPrQ2rYfZiB/iADYlhj9HHZ9TTi6PqKQPAqygohbE=
github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.11.42 h1:bxgBYvvBh+W1RnNYP4ROXEB8N+HSSucDszfE7Rb+kfU= github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.11.43 h1:+bkAMTd5OGyHu2nwNOangjEsP65fR0uhMbZJA52sZ64=
github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.11.42/go.mod h1:LHOsygMiW/14CkFxdXxvzKyMh3jbk/QfZVaDtCbLkl8= github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.11.43/go.mod h1:sS2tu0VEspKuY5eM1vQgy7P/hpZX8F62o6qsghZExWc=
github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.15/go.mod h1:pWrr2OoHlT7M/Pd2y4HV3gJyPb3qj5qMmnPkKSNPYK4= github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.15/go.mod h1:pWrr2OoHlT7M/Pd2y4HV3gJyPb3qj5qMmnPkKSNPYK4=
github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.25 h1:nBO/RFxeq/IS5G9Of+ZrgucRciie2qpLy++3UGZ+q2E= github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.26 h1:5WU31cY7m0tG+AiaXuXGoMzo2GBQ1IixtWa8Yywsgco=
github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.25/go.mod h1:Zb29PYkf42vVYQY6pvSyJCJcFHlPIiY+YKdPtwnvMkY= github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.26/go.mod h1:2E0LdbJW6lbeU4uxjum99GZzI0ZjDpAb0CoSCM0oeEY=
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.9/go.mod h1:08tUpeSGN33QKSO7fwxXczNfiwCpbj+GxK6XKwqWVv0= github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.9/go.mod h1:08tUpeSGN33QKSO7fwxXczNfiwCpbj+GxK6XKwqWVv0=
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.19 h1:oRHDrwCTVT8ZXi4sr9Ld+EXk7N/KGssOr2ygNeojEhw= github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.20 h1:WW0qSzDWoiWU2FS5DbKpxGilFVlCEJPwx4YtjdfI0Jw=
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.19/go.mod h1:6Q0546uHDp421okhmmGfbxzq2hBqbXFNpi4k+Q1JnQA= github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.20/go.mod h1:/+6lSiby8TBFpTVXZgKiN/rCfkYXEGvhlM4zCgPpt7w=
github.com/aws/aws-sdk-go-v2/internal/ini v1.3.16/go.mod h1:CYmI+7x03jjJih8kBEEFKRQc40UjUokT0k7GbvrhhTc= github.com/aws/aws-sdk-go-v2/internal/ini v1.3.16/go.mod h1:CYmI+7x03jjJih8kBEEFKRQc40UjUokT0k7GbvrhhTc=
github.com/aws/aws-sdk-go-v2/internal/ini v1.3.26 h1:Mza+vlnZr+fPKFKRq/lKGVvM6B/8ZZmNdEopOwSQLms= github.com/aws/aws-sdk-go-v2/internal/ini v1.3.27 h1:N2eKFw2S+JWRCtTt0IhIX7uoGGQciD4p6ba+SJv4WEU=
github.com/aws/aws-sdk-go-v2/internal/ini v1.3.26/go.mod h1:Y2OJ+P+MC1u1VKnavT+PshiEuGPyh/7DqxoDNij4/bg= github.com/aws/aws-sdk-go-v2/internal/ini v1.3.27/go.mod h1:RdwFVc7PBYWY33fa2+8T1mSqQ7ZEK4ILpM0wfioDC3w=
github.com/aws/aws-sdk-go-v2/internal/v4a v1.0.6/go.mod h1:O7Oc4peGZDEKlddivslfYFvAbgzvl/GH3J8j3JIGBXc= github.com/aws/aws-sdk-go-v2/internal/v4a v1.0.6/go.mod h1:O7Oc4peGZDEKlddivslfYFvAbgzvl/GH3J8j3JIGBXc=
github.com/aws/aws-sdk-go-v2/internal/v4a v1.0.16 h1:2EXB7dtGwRYIN3XQ9qwIW504DVbKIw3r89xQnonGdsQ= github.com/aws/aws-sdk-go-v2/internal/v4a v1.0.17 h1:5tXbMJ7Jq0iG65oiMg6tCLsHkSaO2xLXa2EmZ29vaTA=
github.com/aws/aws-sdk-go-v2/internal/v4a v1.0.16/go.mod h1:XH+3h395e3WVdd6T2Z3mPxuI+x/HVtdqVOREkTiyubs= github.com/aws/aws-sdk-go-v2/internal/v4a v1.0.17/go.mod h1:twV0fKMQuqLY4klyFH56aXNq3AFiA5LO0/frTczEOFE=
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.9.3/go.mod h1:gkb2qADY+OHaGLKNTYxMaQNacfeyQpZ4csDTQMeFmcw= github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.9.3/go.mod h1:gkb2qADY+OHaGLKNTYxMaQNacfeyQpZ4csDTQMeFmcw=
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.9.10 h1:dpiPHgmFstgkLG07KaYAewvuptq5kvo52xn7tVSrtrQ= github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.9.11 h1:y2+VQzC6Zh2ojtV2LoC0MNwHWc6qXv/j2vrQtlftkdA=
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.9.10/go.mod h1:9cBNUHI2aW4ho0A5T87O294iPDuuUOSIEDjnd1Lq/z0= github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.9.11/go.mod h1:iV4q2hsqtNECrfmlXyord9u4zyuFEJX9eLgLpSPzWA8=
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.1.10/go.mod h1:Qks+dxK3O+Z2deAhNo6cJ8ls1bam3tUGUAcgxQP1c70= github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.1.10/go.mod h1:Qks+dxK3O+Z2deAhNo6cJ8ls1bam3tUGUAcgxQP1c70=
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.1.20 h1:KSvtm1+fPXE0swe9GPjc6msyrdTT0LB/BP8eLugL1FI= github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.1.21 h1:77b1GfaSuIok5yB/3HYbG+ypWvOJDQ2rVdq943D17R4=
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.1.20/go.mod h1:Mp4XI/CkWGD79AQxZ5lIFlgvC0A+gl+4BmyG1F+SfNc= github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.1.21/go.mod h1:sPOz31BVdqeeurKEuUpLNSve4tdCNPluE+070HNcEHI=
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.9/go.mod h1:yQowTpvdZkFVuHrLBXmczat4W+WJKg/PafBZnGBLga0= github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.9/go.mod h1:yQowTpvdZkFVuHrLBXmczat4W+WJKg/PafBZnGBLga0=
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.19 h1:GE25AWCdNUPh9AOJzI9KIJnja7IwUc1WyUqz/JTyJ/I= github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.20 h1:jlgyHbkZQAgAc7VIxJDmtouH8eNjOk2REVAQfVhdaiQ=
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.19/go.mod h1:02CP6iuYP+IVnBX5HULVdSAku/85eHB2Y9EsFhrkEwU= github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.20/go.mod h1:Xs52xaLBqDEKRcAfX/hgjmD3YQ7c/W+BEyfamlO/W2E=
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.13.9/go.mod h1:Rc5+wn2k8gFSi3V1Ch4mhxOzjMh+bYSXVFfVaqowQOY= github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.13.9/go.mod h1:Rc5+wn2k8gFSi3V1Ch4mhxOzjMh+bYSXVFfVaqowQOY=
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.13.19 h1:piDBAaWkaxkkVV3xJJbTehXCZRXYs49kvpi/LG6LR2o= github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.13.20 h1:4K6dbmR0mlp3o4Bo78PnpvzHtYAqEeVMguvEenpMGsI=
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.13.19/go.mod h1:BmQWRVkLTmyNzYPFAZgon53qKLWBNSvonugD1MrSWUs= github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.13.20/go.mod h1:1XpDcReIEOHsjwNToDKhIAO3qwLo1BnfbtSqWJa8j7g=
github.com/aws/aws-sdk-go-v2/service/kms v1.18.1/go.mod h1:4PZMUkc9rXHWGVB5J9vKaZy3D7Nai79ORworQ3ASMiM= github.com/aws/aws-sdk-go-v2/service/kms v1.18.1/go.mod h1:4PZMUkc9rXHWGVB5J9vKaZy3D7Nai79ORworQ3ASMiM=
github.com/aws/aws-sdk-go-v2/service/marketplacemetering v1.13.24 h1:DYr+X4xrRzcthq2OLJzsiS/uSJhZ/HHxXG0yUgGZceU= github.com/aws/aws-sdk-go-v2/service/marketplacemetering v1.13.25 h1:rCfUDMT9KO++W4TkIJr3BO0h749xkRX4RpHdydSFfHw=
github.com/aws/aws-sdk-go-v2/service/marketplacemetering v1.13.24/go.mod h1:mRGY+k3s1yt7yQA3AfzJhnr68OCs1xDfQfIABFUk+ek= github.com/aws/aws-sdk-go-v2/service/marketplacemetering v1.13.25/go.mod h1:xCXhZdPR0p6uaNhggLVGREnJaUIc2CNOJydWnZ2R7OQ=
github.com/aws/aws-sdk-go-v2/service/s3 v1.27.2/go.mod h1:u+566cosFI+d+motIz3USXEh6sN8Nq4GrNXSg2RXVMo= github.com/aws/aws-sdk-go-v2/service/s3 v1.27.2/go.mod h1:u+566cosFI+d+motIz3USXEh6sN8Nq4GrNXSg2RXVMo=
github.com/aws/aws-sdk-go-v2/service/s3 v1.29.4 h1:QgmmWifaYZZcpaw3y1+ccRlgH6jAvLm4K/MBGUc7cNM= github.com/aws/aws-sdk-go-v2/service/s3 v1.29.5 h1:nRSEQj1JergKTVc8RGkhZvOEGgcvo4fWpDPwGDeg2ok=
github.com/aws/aws-sdk-go-v2/service/s3 v1.29.4/go.mod h1:/NHbqPRiwxSPVOB2Xr+StDEH+GWV/64WwnUjv4KYzV0= github.com/aws/aws-sdk-go-v2/service/s3 v1.29.5/go.mod h1:wcaJTmjKFDW0s+Se55HBNIds6ghdAGoDDw+SGUdrfAk=
github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.15.14/go.mod h1:xakbH8KMsQQKqzX87uyyzTHshc/0/Df8bsTneTS5pFU= github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.15.14/go.mod h1:xakbH8KMsQQKqzX87uyyzTHshc/0/Df8bsTneTS5pFU=
github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.16.8 h1:Zw48FHykP40fKMxPmagkuzklpEuDPLhvUjKP8Ygrds0= github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.16.9 h1:ogcakjF/mrZOo9oJVWmRbG838C04oWGXI8T8IY4xcfM=
github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.16.8/go.mod h1:k6CPuxyzO247nYEM1baEwHH1kRtosRCvgahAepaaShw= github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.16.9/go.mod h1:S7AsUoaHONHV2iGM5QXQOonnaV05cK9fty2dXRdouws=
github.com/aws/aws-sdk-go-v2/service/sns v1.17.10/go.mod h1:uITsRNVMeCB3MkWpXxXw0eDz8pW4TYLzj+eyQtbhSxM= github.com/aws/aws-sdk-go-v2/service/sns v1.17.10/go.mod h1:uITsRNVMeCB3MkWpXxXw0eDz8pW4TYLzj+eyQtbhSxM=
github.com/aws/aws-sdk-go-v2/service/sqs v1.19.1/go.mod h1:A94o564Gj+Yn+7QO1eLFeI7UVv3riy/YBFOfICVqFvU= github.com/aws/aws-sdk-go-v2/service/sqs v1.19.1/go.mod h1:A94o564Gj+Yn+7QO1eLFeI7UVv3riy/YBFOfICVqFvU=
github.com/aws/aws-sdk-go-v2/service/ssm v1.27.6/go.mod h1:fiFzQgj4xNOg4/wqmAiPvzgDMXPD+cUEplX/CYn+0j0= github.com/aws/aws-sdk-go-v2/service/ssm v1.27.6/go.mod h1:fiFzQgj4xNOg4/wqmAiPvzgDMXPD+cUEplX/CYn+0j0=
github.com/aws/aws-sdk-go-v2/service/sso v1.11.13/go.mod h1:d7ptRksDDgvXaUvxyHZ9SYh+iMDymm94JbVcgvSYSzU= github.com/aws/aws-sdk-go-v2/service/sso v1.11.13/go.mod h1:d7ptRksDDgvXaUvxyHZ9SYh+iMDymm94JbVcgvSYSzU=
github.com/aws/aws-sdk-go-v2/service/sso v1.11.25 h1:GFZitO48N/7EsFDt8fMa5iYdmWqkUDDB3Eje6z3kbG0= github.com/aws/aws-sdk-go-v2/service/sso v1.11.26 h1:ActQgdTNQej/RuUJjB9uxYVLDOvRGtUreXF8L3c8wyg=
github.com/aws/aws-sdk-go-v2/service/sso v1.11.25/go.mod h1:IARHuzTXmj1C0KS35vboR0FeJ89OkEy1M9mWbK2ifCI= github.com/aws/aws-sdk-go-v2/service/sso v1.11.26/go.mod h1:uB9tV79ULEZUXc6Ob18A46KSQ0JDlrplPni9XW6Ot60=
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.13.8 h1:jcw6kKZrtNfBPJkaHrscDOZoe5gvi9wjudnxvozYFJo= github.com/aws/aws-sdk-go-v2/service/ssooidc v1.13.9 h1:wihKuqYUlA2T/Rx+yu2s6NDAns8B9DgnRooB1PVhY+Q=
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.13.8/go.mod h1:er2JHN+kBY6FcMfcBBKNGCT3CarImmdFzishsqBmSRI= github.com/aws/aws-sdk-go-v2/service/ssooidc v1.13.9/go.mod h1:2E/3D/mB8/r2J7nK42daoKP/ooCwbf0q1PznNc+DZTU=
github.com/aws/aws-sdk-go-v2/service/sts v1.16.10/go.mod h1:cftkHYN6tCDNfkSasAmclSfl4l7cySoay8vz7p/ce0E= github.com/aws/aws-sdk-go-v2/service/sts v1.16.10/go.mod h1:cftkHYN6tCDNfkSasAmclSfl4l7cySoay8vz7p/ce0E=
github.com/aws/aws-sdk-go-v2/service/sts v1.17.5 h1:60SJ4lhvn///8ygCzYy2l53bFW/Q15bVfyjyAWo6zuw= github.com/aws/aws-sdk-go-v2/service/sts v1.17.6 h1:VQFOLQVL3BrKM/NLO/7FiS4vcp5bqK0mGMyk09xLoAY=
github.com/aws/aws-sdk-go-v2/service/sts v1.17.5/go.mod h1:bXcN3koeVYiJcdDU89n3kCYILob7Y34AeLopUbZgLT4= github.com/aws/aws-sdk-go-v2/service/sts v1.17.6/go.mod h1:Az3OXXYGyfNwQNsK/31L4R75qFYnO641RZGAoV3uH1c=
github.com/aws/smithy-go v1.12.0/go.mod h1:Tg+OJXh4MB2R/uN61Ko2f6hTZwB/ZYGOtib8J3gBHzA= github.com/aws/smithy-go v1.12.0/go.mod h1:Tg+OJXh4MB2R/uN61Ko2f6hTZwB/ZYGOtib8J3gBHzA=
github.com/aws/smithy-go v1.13.4 h1:/RN2z1txIJWeXeOkzX+Hk/4Uuvv7dWtCjbmVJcrskyk= github.com/aws/smithy-go v1.13.5 h1:hgz0X/DX0dGqTYpGALqXJoRKRj5oQ7150i5FdTePzO8=
github.com/aws/smithy-go v1.13.4/go.mod h1:Tg+OJXh4MB2R/uN61Ko2f6hTZwB/ZYGOtib8J3gBHzA= github.com/aws/smithy-go v1.13.5/go.mod h1:Tg+OJXh4MB2R/uN61Ko2f6hTZwB/ZYGOtib8J3gBHzA=
github.com/benbjohnson/clock v1.0.3/go.mod h1:bGMdMPoPVvcYyt1gHDf4J2KE153Yf9BuiUKYMaxlTDM= github.com/benbjohnson/clock v1.0.3/go.mod h1:bGMdMPoPVvcYyt1gHDf4J2KE153Yf9BuiUKYMaxlTDM=
github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA=
github.com/beorn7/perks v0.0.0-20160804104726-4c0e84591b9a/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v0.0.0-20160804104726-4c0e84591b9a/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
@ -676,8 +676,9 @@ github.com/go-playground/validator/v10 v10.2.0/go.mod h1:uOYAAleCW8F/7oMFd6aG0GO
github.com/go-playground/validator/v10 v10.4.1/go.mod h1:nlOn6nFhuKACm19sB/8EGNn9GlaMV7XkbRSipzJ0Ii4= github.com/go-playground/validator/v10 v10.4.1/go.mod h1:nlOn6nFhuKACm19sB/8EGNn9GlaMV7XkbRSipzJ0Ii4=
github.com/go-resty/resty/v2 v2.1.1-0.20191201195748-d7b97669fe48/go.mod h1:dZGr0i9PLlaaTD4H/hoZIDjQ+r6xq8mgbRzHZf7f2J8= github.com/go-resty/resty/v2 v2.1.1-0.20191201195748-d7b97669fe48/go.mod h1:dZGr0i9PLlaaTD4H/hoZIDjQ+r6xq8mgbRzHZf7f2J8=
github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE=
github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
github.com/go-sql-driver/mysql v1.7.0 h1:ueSltNNllEqE3qcWBTD0iQd3IpL/6U+mJxLkazJ7YPc=
github.com/go-sql-driver/mysql v1.7.0/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI=
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
github.com/go-stack/stack v1.8.1/go.mod h1:dcoOX6HbPZSZptuspn9bctJ+N/CnF5gGygcUP3XYfe4= github.com/go-stack/stack v1.8.1/go.mod h1:dcoOX6HbPZSZptuspn9bctJ+N/CnF5gGygcUP3XYfe4=
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
@ -966,8 +967,9 @@ github.com/imdario/mergo v0.3.10/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH
github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
github.com/inconshreveable/mousetrap v1.0.1 h1:U3uMjPSQEBMNp1lFxmllqCPM6P5u/Xq7Pgzkat/bFNc=
github.com/inconshreveable/mousetrap v1.0.1/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/inconshreveable/mousetrap v1.0.1/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo= github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo=
github.com/intel/goresctrl v0.2.0/go.mod h1:+CZdzouYFn5EsxgqAQTEzMfwKwuc0fVdMrT9FCCAVRQ= github.com/intel/goresctrl v0.2.0/go.mod h1:+CZdzouYFn5EsxgqAQTEzMfwKwuc0fVdMrT9FCCAVRQ=
github.com/ionos-cloud/sdk-go/v6 v6.1.0/go.mod h1:Ox3W0iiEz0GHnfY9e5LmAxwklsxguuNFEUSu0gVRTME= github.com/ionos-cloud/sdk-go/v6 v6.1.0/go.mod h1:Ox3W0iiEz0GHnfY9e5LmAxwklsxguuNFEUSu0gVRTME=
@ -1446,10 +1448,10 @@ github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg
github.com/seccomp/libseccomp-golang v0.9.1/go.mod h1:GbW5+tmTXfcxTToHLXlScSlAvWlF4P2Ca7zGrPiEpWo= github.com/seccomp/libseccomp-golang v0.9.1/go.mod h1:GbW5+tmTXfcxTToHLXlScSlAvWlF4P2Ca7zGrPiEpWo=
github.com/seccomp/libseccomp-golang v0.9.2-0.20210429002308-3879420cc921/go.mod h1:JA8cRccbGaA1s33RQf7Y1+q9gHmZX1yB/z9WDN1C6fg= github.com/seccomp/libseccomp-golang v0.9.2-0.20210429002308-3879420cc921/go.mod h1:JA8cRccbGaA1s33RQf7Y1+q9gHmZX1yB/z9WDN1C6fg=
github.com/secsy/goftp v0.0.0-20200609142545-aa2de14babf4 h1:PT+ElG/UUFMfqy5HrxJxNzj3QBOf7dZwupeVC+mG1Lo= github.com/secsy/goftp v0.0.0-20200609142545-aa2de14babf4 h1:PT+ElG/UUFMfqy5HrxJxNzj3QBOf7dZwupeVC+mG1Lo=
github.com/sftpgo/sdk v0.1.3-0.20221116180328-3fc64e926700 h1:hfUjwmNPMqE9o5oIBxDQZE0FJ8IqlJwVVhATQYwe2Ao= github.com/sftpgo/sdk v0.1.3-0.20221203095324-2feef3600930 h1:znJ52fQBSAQhacaQvZAfkpTioqpcutDREM/H8NttKzU=
github.com/sftpgo/sdk v0.1.3-0.20221116180328-3fc64e926700/go.mod h1:Giy5vj7Gmju0nGlmBNd28DwPo0G0o1nr9XkE+vu3i+o= github.com/sftpgo/sdk v0.1.3-0.20221203095324-2feef3600930/go.mod h1:S2S/Q9fgUpXmL11YoCCt0hyCkEwH1LzQM/6QVsbUCFg=
github.com/shirou/gopsutil/v3 v3.22.10 h1:4KMHdfBRYXGF9skjDWiL4RA2N+E8dRdodU/bOZpPoVg= github.com/shirou/gopsutil/v3 v3.22.11 h1:kxsPKS+Eeo+VnEQ2XCaGJepeP6KY53QoRTETx3+1ndM=
github.com/shirou/gopsutil/v3 v3.22.10/go.mod h1:QNza6r4YQoydyCfo6rH0blGfKahgibh4dQmV5xdFkQk= github.com/shirou/gopsutil/v3 v3.22.11/go.mod h1:xl0EeL4vXJ+hQMAGN8B9VFpxukEMA0XdevQOe5MZ1oY=
github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24/go.mod h1:M+9NzErvs504Cn4c5DxATwIqPbtswREoFCre64PpcG4= github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24/go.mod h1:M+9NzErvs504Cn4c5DxATwIqPbtswREoFCre64PpcG4=
github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o=
github.com/shopspring/decimal v1.3.1/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= github.com/shopspring/decimal v1.3.1/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o=
@ -1536,10 +1538,8 @@ github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635/go.mod h1:hkRG
github.com/tchap/go-patricia v2.2.6+incompatible/go.mod h1:bmLyhP68RS6kStMGxByiQ23RP/odRBOTVjwp2cDyi6I= github.com/tchap/go-patricia v2.2.6+incompatible/go.mod h1:bmLyhP68RS6kStMGxByiQ23RP/odRBOTVjwp2cDyi6I=
github.com/tedsuo/ifrit v0.0.0-20180802180643-bea94bb476cc/go.mod h1:eyZnKCc955uh98WQvzOm0dgAeLnf2O0Rz0LPoC5ze+0= github.com/tedsuo/ifrit v0.0.0-20180802180643-bea94bb476cc/go.mod h1:eyZnKCc955uh98WQvzOm0dgAeLnf2O0Rz0LPoC5ze+0=
github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
github.com/tklauser/go-sysconf v0.3.10/go.mod h1:C8XykCvCb+Gn0oNCWPIlcb0RuglQTYaQ2hGm7jmxEFk=
github.com/tklauser/go-sysconf v0.3.11 h1:89WgdJhk5SNwJfu+GKyYveZ4IaJ7xAkecBo+KdJV0CM= github.com/tklauser/go-sysconf v0.3.11 h1:89WgdJhk5SNwJfu+GKyYveZ4IaJ7xAkecBo+KdJV0CM=
github.com/tklauser/go-sysconf v0.3.11/go.mod h1:GqXfhXY3kiPa0nAXPDIQIWzJbMCB7AmcWpGR8lSZfqI= github.com/tklauser/go-sysconf v0.3.11/go.mod h1:GqXfhXY3kiPa0nAXPDIQIWzJbMCB7AmcWpGR8lSZfqI=
github.com/tklauser/numcpus v0.4.0/go.mod h1:1+UI3pD8NW14VMwdgJNJ1ESk2UnwhAnz5hMwiKKqXCQ=
github.com/tklauser/numcpus v0.6.0 h1:kebhY2Qt+3U6RNK7UqpYNA+tJ23IBEGKkB7JQBfDYms= github.com/tklauser/numcpus v0.6.0 h1:kebhY2Qt+3U6RNK7UqpYNA+tJ23IBEGKkB7JQBfDYms=
github.com/tklauser/numcpus v0.6.0/go.mod h1:FEZLMke0lhOUG6w2JadTzp0a+Nl8PF/GFkQ5UVIcaL4= github.com/tklauser/numcpus v0.6.0/go.mod h1:FEZLMke0lhOUG6w2JadTzp0a+Nl8PF/GFkQ5UVIcaL4=
github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
@ -2294,8 +2294,8 @@ google.golang.org/genproto v0.0.0-20220617124728-180714bec0ad/go.mod h1:KEWEmljW
google.golang.org/genproto v0.0.0-20220624142145-8cd45d7dbd1f/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA= google.golang.org/genproto v0.0.0-20220624142145-8cd45d7dbd1f/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA=
google.golang.org/genproto v0.0.0-20220628213854-d9e0b6570c03/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA= google.golang.org/genproto v0.0.0-20220628213854-d9e0b6570c03/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA=
google.golang.org/genproto v0.0.0-20220802133213-ce4fa296bf78/go.mod h1:iHe1svFLAZg9VWz891+QbRMwUv9O/1Ww+/mngYeThbc= google.golang.org/genproto v0.0.0-20220802133213-ce4fa296bf78/go.mod h1:iHe1svFLAZg9VWz891+QbRMwUv9O/1Ww+/mngYeThbc=
google.golang.org/genproto v0.0.0-20221118155620-16455021b5e6 h1:a2S6M0+660BgMNl++4JPlcAO/CjkqYItDEZwkoDQK7c= google.golang.org/genproto v0.0.0-20221202195650-67e5cbc046fd h1:OjndDrsik+Gt+e6fs45z9AxiewiKyLKYpA45W5Kpkks=
google.golang.org/genproto v0.0.0-20221118155620-16455021b5e6/go.mod h1:rZS5c/ZVYMaOGBfO68GWtjOw/eLaZM1X6iVtgjZ+EWg= google.golang.org/genproto v0.0.0-20221202195650-67e5cbc046fd/go.mod h1:cTsE614GARnxrLsqKREzmNYJACSWWpAWdNMwnD7c2BE=
google.golang.org/grpc v0.0.0-20160317175043-d3ddb4469d5a/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= google.golang.org/grpc v0.0.0-20160317175043-d3ddb4469d5a/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=

View file

@ -142,7 +142,7 @@ Command-line flags should be specified in the Subsystem declaration.
if user.HomeDir != filepath.Clean(homedir) && !preserveHomeDir { if user.HomeDir != filepath.Clean(homedir) && !preserveHomeDir {
// update the user // update the user
user.HomeDir = filepath.Clean(homedir) user.HomeDir = filepath.Clean(homedir)
err = dataprovider.UpdateUser(&user, dataprovider.ActionExecutorSystem, "") err = dataprovider.UpdateUser(&user, dataprovider.ActionExecutorSystem, "", "")
if err != nil { if err != nil {
logger.Error(logSender, connectionID, "unable to update user %#v: %v", username, err) logger.Error(logSender, connectionID, "unable to update user %#v: %v", username, err)
os.Exit(1) os.Exit(1)
@ -159,7 +159,7 @@ Command-line flags should be specified in the Subsystem declaration.
user.Password = connectionID user.Password = connectionID
user.Permissions = make(map[string][]string) user.Permissions = make(map[string][]string)
user.Permissions["/"] = []string{dataprovider.PermAny} user.Permissions["/"] = []string{dataprovider.PermAny}
err = dataprovider.AddUser(&user, dataprovider.ActionExecutorSystem, "") err = dataprovider.AddUser(&user, dataprovider.ActionExecutorSystem, "", "")
if err != nil { if err != nil {
logger.Error(logSender, connectionID, "unable to add user %#v: %v", username, err) logger.Error(logSender, connectionID, "unable to add user %#v: %v", username, err)
os.Exit(1) os.Exit(1)

View file

@ -139,6 +139,7 @@ func ExecuteActionNotification(conn *BaseConnection, operation, filePath, virtua
FileSize: notification.FileSize, FileSize: notification.FileSize,
Protocol: notification.Protocol, Protocol: notification.Protocol,
IP: notification.IP, IP: notification.IP,
Role: notification.Role,
Timestamp: notification.Timestamp, Timestamp: notification.Timestamp,
Object: nil, Object: nil,
} }
@ -214,6 +215,7 @@ func newActionNotification(
IP: ip, IP: ip,
SessionID: sessionID, SessionID: sessionID,
OpenFlags: openFlags, OpenFlags: openFlags,
Role: user.Role,
Timestamp: time.Now().UnixNano(), Timestamp: time.Now().UnixNano(),
} }
} }
@ -311,6 +313,7 @@ func notificationAsEnvVars(event *notifier.FsEvent) []string {
fmt.Sprintf("SFTPGO_ACTION_SESSION_ID=%s", event.SessionID), fmt.Sprintf("SFTPGO_ACTION_SESSION_ID=%s", event.SessionID),
fmt.Sprintf("SFTPGO_ACTION_OPEN_FLAGS=%d", event.OpenFlags), fmt.Sprintf("SFTPGO_ACTION_OPEN_FLAGS=%d", event.OpenFlags),
fmt.Sprintf("SFTPGO_ACTION_TIMESTAMP=%d", event.Timestamp), fmt.Sprintf("SFTPGO_ACTION_TIMESTAMP=%d", event.Timestamp),
fmt.Sprintf("SFTPGO_ACTION_ROLE=%s", event.Role),
} }
} }

View file

@ -1380,7 +1380,7 @@ func TestUpdateTransferTimestamps(t *testing.T) {
}, },
}, },
} }
err := dataprovider.AddUser(user, "", "") err := dataprovider.AddUser(user, "", "", "")
assert.NoError(t, err) assert.NoError(t, err)
assert.Equal(t, int64(0), user.FirstUpload) assert.Equal(t, int64(0), user.FirstUpload)
assert.Equal(t, int64(0), user.FirstDownload) assert.Equal(t, int64(0), user.FirstDownload)

View file

@ -69,7 +69,7 @@ func init() {
concurrencyGuard: make(chan struct{}, 200), concurrencyGuard: make(chan struct{}, 200),
} }
dataprovider.SetEventRulesCallbacks(eventManager.loadRules, eventManager.RemoveRule, dataprovider.SetEventRulesCallbacks(eventManager.loadRules, eventManager.RemoveRule,
func(operation, executor, ip, objectType, objectName string, object plugin.Renderer) { func(operation, executor, ip, objectType, objectName, role string, object plugin.Renderer) {
eventManager.handleProviderEvent(EventParams{ eventManager.handleProviderEvent(EventParams{
Name: executor, Name: executor,
ObjectName: objectName, ObjectName: objectName,
@ -77,6 +77,7 @@ func init() {
Status: 1, Status: 1,
ObjectType: objectType, ObjectType: objectType,
IP: ip, IP: ip,
Role: role,
Timestamp: time.Now().UnixNano(), Timestamp: time.Now().UnixNano(),
Object: object, Object: object,
}) })
@ -439,6 +440,7 @@ type EventParams struct {
FileSize int64 FileSize int64
Protocol string Protocol string
IP string IP string
Role string
Timestamp int64 Timestamp int64
Object plugin.Renderer Object plugin.Renderer
sender string sender string
@ -610,6 +612,7 @@ func (p *EventParams) getStringReplacements(addObjectData bool) []string {
"{{FileSize}}", fmt.Sprintf("%d", p.FileSize), "{{FileSize}}", fmt.Sprintf("%d", p.FileSize),
"{{Protocol}}", p.Protocol, "{{Protocol}}", p.Protocol,
"{{IP}}", p.IP, "{{IP}}", p.IP,
"{{Role}}", p.Role,
"{{Timestamp}}", fmt.Sprintf("%d", p.Timestamp), "{{Timestamp}}", fmt.Sprintf("%d", p.Timestamp),
"{{StatusString}}", p.getStatusString(), "{{StatusString}}", p.getStatusString(),
} }

View file

@ -210,7 +210,7 @@ func TestEventManager(t *testing.T) {
}, },
}, },
} }
err := dataprovider.AddEventAction(action, "", "") err := dataprovider.AddEventAction(action, "", "", "")
assert.NoError(t, err) assert.NoError(t, err)
rule := &dataprovider.EventRule{ rule := &dataprovider.EventRule{
Name: "rule", Name: "rule",
@ -228,7 +228,7 @@ func TestEventManager(t *testing.T) {
}, },
} }
err = dataprovider.AddEventRule(rule, "", "") err = dataprovider.AddEventRule(rule, "", "", "")
assert.NoError(t, err) assert.NoError(t, err)
eventManager.RLock() eventManager.RLock()
@ -242,7 +242,7 @@ func TestEventManager(t *testing.T) {
rule.Conditions = dataprovider.EventConditions{ rule.Conditions = dataprovider.EventConditions{
ProviderEvents: []string{"add"}, ProviderEvents: []string{"add"},
} }
err = dataprovider.UpdateEventRule(rule, "", "") err = dataprovider.UpdateEventRule(rule, "", "", "")
assert.NoError(t, err) assert.NoError(t, err)
eventManager.RLock() eventManager.RLock()
@ -280,7 +280,7 @@ func TestEventManager(t *testing.T) {
}, 2*time.Second, 100*time.Millisecond) }, 2*time.Second, 100*time.Millisecond)
rule.DeletedAt = 0 rule.DeletedAt = 0
err = dataprovider.AddEventRule(rule, "", "") err = dataprovider.AddEventRule(rule, "", "", "")
assert.NoError(t, err) assert.NoError(t, err)
eventManager.RLock() eventManager.RLock()
@ -290,7 +290,7 @@ func TestEventManager(t *testing.T) {
assert.Len(t, eventManager.schedulesMapping, 1) assert.Len(t, eventManager.schedulesMapping, 1)
eventManager.RUnlock() eventManager.RUnlock()
err = dataprovider.DeleteEventRule(rule.Name, "", "") err = dataprovider.DeleteEventRule(rule.Name, "", "", "")
assert.NoError(t, err) assert.NoError(t, err)
eventManager.RLock() eventManager.RLock()
@ -300,7 +300,7 @@ func TestEventManager(t *testing.T) {
assert.Len(t, eventManager.schedulesMapping, 0) assert.Len(t, eventManager.schedulesMapping, 0)
eventManager.RUnlock() eventManager.RUnlock()
err = dataprovider.DeleteEventAction(action.Name, "", "") err = dataprovider.DeleteEventAction(action.Name, "", "", "")
assert.NoError(t, err) assert.NoError(t, err)
stopEventScheduler() stopEventScheduler()
} }
@ -616,9 +616,9 @@ func TestEventRuleActions(t *testing.T) {
}, },
}, },
} }
err = dataprovider.AddUser(&user1, "", "") err = dataprovider.AddUser(&user1, "", "", "")
assert.NoError(t, err) assert.NoError(t, err)
err = dataprovider.AddUser(&user2, "", "") err = dataprovider.AddUser(&user2, "", "", "")
assert.NoError(t, err) assert.NoError(t, err)
action = dataprovider.BaseEventAction{ action = dataprovider.BaseEventAction{
@ -963,9 +963,9 @@ func TestEventRuleActions(t *testing.T) {
Name: foldername2, Name: foldername2,
MappedPath: filepath.Join(os.TempDir(), foldername2), MappedPath: filepath.Join(os.TempDir(), foldername2),
} }
err = dataprovider.AddFolder(&folder1, "", "") err = dataprovider.AddFolder(&folder1, "", "", "")
assert.NoError(t, err) assert.NoError(t, err)
err = dataprovider.AddFolder(&folder2, "", "") err = dataprovider.AddFolder(&folder2, "", "", "")
assert.NoError(t, err) assert.NoError(t, err)
action = dataprovider.BaseEventAction{ action = dataprovider.BaseEventAction{
Type: dataprovider.ActionTypeFolderQuotaReset, Type: dataprovider.ActionTypeFolderQuotaReset,
@ -1025,9 +1025,9 @@ func TestEventRuleActions(t *testing.T) {
err = os.RemoveAll(folder1.MappedPath) err = os.RemoveAll(folder1.MappedPath)
assert.NoError(t, err) assert.NoError(t, err)
err = dataprovider.DeleteFolder(foldername1, "", "") err = dataprovider.DeleteFolder(foldername1, "", "", "")
assert.NoError(t, err) assert.NoError(t, err)
err = dataprovider.DeleteFolder(foldername2, "", "") err = dataprovider.DeleteFolder(foldername2, "", "", "")
assert.NoError(t, err) assert.NoError(t, err)
} }
@ -1042,7 +1042,7 @@ func TestEventRuleActionsNoGroupMatching(t *testing.T) {
HomeDir: filepath.Join(os.TempDir(), username), HomeDir: filepath.Join(os.TempDir(), username),
}, },
} }
err := dataprovider.AddUser(&user, "", "") err := dataprovider.AddUser(&user, "", "", "")
assert.NoError(t, err) assert.NoError(t, err)
conditions := dataprovider.ConditionOptions{ conditions := dataprovider.ConditionOptions{
@ -1102,7 +1102,7 @@ func TestGetFileContent(t *testing.T) {
HomeDir: filepath.Join(os.TempDir(), username), HomeDir: filepath.Join(os.TempDir(), username),
}, },
} }
err := dataprovider.AddUser(&user, "", "") err := dataprovider.AddUser(&user, "", "", "")
assert.NoError(t, err) assert.NoError(t, err)
err = os.MkdirAll(user.GetHomeDir(), os.ModePerm) err = os.MkdirAll(user.GetHomeDir(), os.ModePerm)
assert.NoError(t, err) assert.NoError(t, err)
@ -1141,7 +1141,7 @@ func TestGetFileContent(t *testing.T) {
// change the filesystem provider // change the filesystem provider
user.FsConfig.Provider = sdk.CryptedFilesystemProvider user.FsConfig.Provider = sdk.CryptedFilesystemProvider
user.FsConfig.CryptConfig.Passphrase = kms.NewPlainSecret("pwd") user.FsConfig.CryptConfig.Passphrase = kms.NewPlainSecret("pwd")
err = dataprovider.UpdateUser(&user, "", "") err = dataprovider.UpdateUser(&user, "", "", "")
assert.NoError(t, err) assert.NoError(t, err)
// the file is not encrypted so reading the encryption header will fail // the file is not encrypted so reading the encryption header will fail
_, err = getMailAttachments(user, []string{"/file.txt"}, replacer) _, err = getMailAttachments(user, []string{"/file.txt"}, replacer)
@ -1191,7 +1191,7 @@ func TestFilesystemActionErrors(t *testing.T) {
conn := NewBaseConnection("", protocolEventAction, "", "", user) conn := NewBaseConnection("", protocolEventAction, "", "", user)
err = executeDeleteFileFsAction(conn, "", nil) err = executeDeleteFileFsAction(conn, "", nil)
assert.Error(t, err) assert.Error(t, err)
err = dataprovider.AddUser(&user, "", "") err = dataprovider.AddUser(&user, "", "", "")
assert.NoError(t, err) assert.NoError(t, err)
// check root fs fails // check root fs fails
err = executeDeleteFsActionForUser(nil, testReplacer, user) err = executeDeleteFsActionForUser(nil, testReplacer, user)
@ -1234,7 +1234,7 @@ func TestFilesystemActionErrors(t *testing.T) {
user.Permissions["/"] = []string{dataprovider.PermUpload} user.Permissions["/"] = []string{dataprovider.PermUpload}
err = dataprovider.DeleteUser(username, "", "", "") err = dataprovider.DeleteUser(username, "", "", "")
assert.NoError(t, err) assert.NoError(t, err)
err = dataprovider.AddUser(&user, "", "") err = dataprovider.AddUser(&user, "", "", "")
assert.NoError(t, err) assert.NoError(t, err)
err = executeRenameFsActionForUser([]dataprovider.KeyValue{ err = executeRenameFsActionForUser([]dataprovider.KeyValue{
{ {
@ -1373,7 +1373,7 @@ func TestQuotaActionsWithQuotaTrackDisabled(t *testing.T) {
Provider: sdk.LocalFilesystemProvider, Provider: sdk.LocalFilesystemProvider,
}, },
} }
err = dataprovider.AddUser(&user, "", "") err = dataprovider.AddUser(&user, "", "", "")
assert.NoError(t, err) assert.NoError(t, err)
err = os.MkdirAll(user.GetHomeDir(), os.ModePerm) err = os.MkdirAll(user.GetHomeDir(), os.ModePerm)
@ -1408,7 +1408,7 @@ func TestQuotaActionsWithQuotaTrackDisabled(t *testing.T) {
Name: foldername, Name: foldername,
MappedPath: filepath.Join(os.TempDir(), foldername), MappedPath: filepath.Join(os.TempDir(), foldername),
} }
err = dataprovider.AddFolder(&folder, "", "") err = dataprovider.AddFolder(&folder, "", "", "")
assert.NoError(t, err) assert.NoError(t, err)
err = os.MkdirAll(folder.MappedPath, os.ModePerm) err = os.MkdirAll(folder.MappedPath, os.ModePerm)
assert.NoError(t, err) assert.NoError(t, err)
@ -1425,7 +1425,7 @@ func TestQuotaActionsWithQuotaTrackDisabled(t *testing.T) {
err = os.RemoveAll(folder.MappedPath) err = os.RemoveAll(folder.MappedPath)
assert.NoError(t, err) assert.NoError(t, err)
err = dataprovider.DeleteFolder(foldername, "", "") err = dataprovider.DeleteFolder(foldername, "", "", "")
assert.NoError(t, err) assert.NoError(t, err)
err = dataprovider.Close() err = dataprovider.Close()
@ -1444,7 +1444,7 @@ func TestScheduledActions(t *testing.T) {
Name: "action", Name: "action",
Type: dataprovider.ActionTypeBackup, Type: dataprovider.ActionTypeBackup,
} }
err = dataprovider.AddEventAction(action, "", "") err = dataprovider.AddEventAction(action, "", "", "")
assert.NoError(t, err) assert.NoError(t, err)
rule := &dataprovider.EventRule{ rule := &dataprovider.EventRule{
Name: "rule", Name: "rule",
@ -1475,7 +1475,7 @@ func TestScheduledActions(t *testing.T) {
job.Run() // rule not found job.Run() // rule not found
assert.NoDirExists(t, backupsPath) assert.NoDirExists(t, backupsPath)
err = dataprovider.AddEventRule(rule, "", "") err = dataprovider.AddEventRule(rule, "", "", "")
assert.NoError(t, err) assert.NoError(t, err)
job.Run() job.Run()
@ -1490,13 +1490,13 @@ func TestScheduledActions(t *testing.T) {
Attachments: []string{"/file1.txt"}, Attachments: []string{"/file1.txt"},
}, },
} }
err = dataprovider.UpdateEventAction(action, "", "") err = dataprovider.UpdateEventAction(action, "", "", "")
assert.NoError(t, err) assert.NoError(t, err)
job.Run() // action is not compatible with a scheduled rule job.Run() // action is not compatible with a scheduled rule
err = dataprovider.DeleteEventRule(rule.Name, "", "") err = dataprovider.DeleteEventRule(rule.Name, "", "", "")
assert.NoError(t, err) assert.NoError(t, err)
err = dataprovider.DeleteEventAction(action.Name, "", "") err = dataprovider.DeleteEventAction(action.Name, "", "", "")
assert.NoError(t, err) assert.NoError(t, err)
err = os.RemoveAll(backupsPath) err = os.RemoveAll(backupsPath)
assert.NoError(t, err) assert.NoError(t, err)

View file

@ -3295,7 +3295,7 @@ func TestDelayedQuotaUpdater(t *testing.T) {
Name: "folder", Name: "folder",
MappedPath: filepath.Join(os.TempDir(), "p"), MappedPath: filepath.Join(os.TempDir(), "p"),
} }
err = dataprovider.AddFolder(&folder, "", "") err = dataprovider.AddFolder(&folder, "", "", "")
assert.NoError(t, err) assert.NoError(t, err)
err = dataprovider.UpdateVirtualFolderQuota(&folder, 10, 6000, false) err = dataprovider.UpdateVirtualFolderQuota(&folder, 10, 6000, false)
@ -3322,7 +3322,7 @@ func TestDelayedQuotaUpdater(t *testing.T) {
assert.Equal(t, 10, folderGet.UsedQuotaFiles) assert.Equal(t, 10, folderGet.UsedQuotaFiles)
assert.Equal(t, int64(6000), folderGet.UsedQuotaSize) assert.Equal(t, int64(6000), folderGet.UsedQuotaSize)
err = dataprovider.DeleteFolder(folder.Name, "", "") err = dataprovider.DeleteFolder(folder.Name, "", "", "")
assert.NoError(t, err) assert.NoError(t, err)
err = dataprovider.Close() err = dataprovider.Close()
@ -5669,13 +5669,13 @@ func TestEventRuleIPBlocked(t *testing.T) {
assert.True(t, util.Contains(email.To, "test4@example.com")) assert.True(t, util.Contains(email.To, "test4@example.com"))
assert.Contains(t, email.Data, `Subject: New "IP Blocked"`) assert.Contains(t, email.Data, `Subject: New "IP Blocked"`)
err = dataprovider.DeleteEventRule(rule1.Name, "", "") err = dataprovider.DeleteEventRule(rule1.Name, "", "", "")
assert.NoError(t, err) assert.NoError(t, err)
err = dataprovider.DeleteEventRule(rule2.Name, "", "") err = dataprovider.DeleteEventRule(rule2.Name, "", "", "")
assert.NoError(t, err) assert.NoError(t, err)
err = dataprovider.DeleteEventAction(action1.Name, "", "") err = dataprovider.DeleteEventAction(action1.Name, "", "", "")
assert.NoError(t, err) assert.NoError(t, err)
err = dataprovider.DeleteEventAction(action2.Name, "", "") err = dataprovider.DeleteEventAction(action2.Name, "", "", "")
assert.NoError(t, err) assert.NoError(t, err)
err = dataprovider.DeleteUser(user.Username, "", "", "") err = dataprovider.DeleteUser(user.Username, "", "", "")
assert.NoError(t, err) assert.NoError(t, err)
@ -6125,7 +6125,7 @@ func TestBuiltinKeyboardInteractiveAuthentication(t *testing.T) {
Secret: kms.NewPlainSecret(secret), Secret: kms.NewPlainSecret(secret),
Protocols: []string{common.ProtocolSSH}, Protocols: []string{common.ProtocolSSH},
} }
err = dataprovider.UpdateUser(&user, "", "") err = dataprovider.UpdateUser(&user, "", "", "")
assert.NoError(t, err) assert.NoError(t, err)
passcode, err := generateTOTPPasscode(secret, otp.AlgorithmSHA1) passcode, err := generateTOTPPasscode(secret, otp.AlgorithmSHA1)
assert.NoError(t, err) assert.NoError(t, err)

View file

@ -76,12 +76,12 @@ func TestTransfersCheckerDiskQuota(t *testing.T) {
}, },
}, },
} }
err := dataprovider.AddGroup(&group, "", "") err := dataprovider.AddGroup(&group, "", "", "")
assert.NoError(t, err) assert.NoError(t, err)
group, err = dataprovider.GroupExists(groupName) group, err = dataprovider.GroupExists(groupName)
assert.NoError(t, err) assert.NoError(t, err)
assert.Equal(t, int64(120), group.UserSettings.QuotaSize) assert.Equal(t, int64(120), group.UserSettings.QuotaSize)
err = dataprovider.AddUser(&user, "", "") err = dataprovider.AddUser(&user, "", "", "")
assert.NoError(t, err) assert.NoError(t, err)
user, err = dataprovider.GetUserWithGroupSettings(username, "") user, err = dataprovider.GetUserWithGroupSettings(username, "")
assert.NoError(t, err) assert.NoError(t, err)
@ -154,7 +154,7 @@ func TestTransfersCheckerDiskQuota(t *testing.T) {
assert.True(t, conn3.IsQuotaExceededError(transfer3.GetAbortError())) assert.True(t, conn3.IsQuotaExceededError(transfer3.GetAbortError()))
// update the user quota size // update the user quota size
group.UserSettings.QuotaSize = 1000 group.UserSettings.QuotaSize = 1000
err = dataprovider.UpdateGroup(&group, []string{username}, "", "") err = dataprovider.UpdateGroup(&group, []string{username}, "", "", "")
assert.NoError(t, err) assert.NoError(t, err)
transfer1.errAbort = nil transfer1.errAbort = nil
transfer2.errAbort = nil transfer2.errAbort = nil
@ -164,7 +164,7 @@ func TestTransfersCheckerDiskQuota(t *testing.T) {
assert.Nil(t, transfer3.errAbort) assert.Nil(t, transfer3.errAbort)
group.UserSettings.QuotaSize = 0 group.UserSettings.QuotaSize = 0
err = dataprovider.UpdateGroup(&group, []string{username}, "", "") err = dataprovider.UpdateGroup(&group, []string{username}, "", "", "")
assert.NoError(t, err) assert.NoError(t, err)
Connections.checkTransfers() Connections.checkTransfers()
assert.Nil(t, transfer1.errAbort) assert.Nil(t, transfer1.errAbort)
@ -251,11 +251,11 @@ func TestTransfersCheckerDiskQuota(t *testing.T) {
err = os.RemoveAll(user.GetHomeDir()) err = os.RemoveAll(user.GetHomeDir())
assert.NoError(t, err) assert.NoError(t, err)
err = dataprovider.DeleteFolder(folderName, "", "") err = dataprovider.DeleteFolder(folderName, "", "", "")
assert.NoError(t, err) assert.NoError(t, err)
err = os.RemoveAll(filepath.Join(os.TempDir(), folderName)) err = os.RemoveAll(filepath.Join(os.TempDir(), folderName))
assert.NoError(t, err) assert.NoError(t, err)
err = dataprovider.DeleteGroup(groupName, "", "") err = dataprovider.DeleteGroup(groupName, "", "", "")
assert.NoError(t, err) assert.NoError(t, err)
} }
@ -273,7 +273,7 @@ func TestTransferCheckerTransferQuota(t *testing.T) {
}, },
}, },
} }
err := dataprovider.AddUser(&user, "", "") err := dataprovider.AddUser(&user, "", "", "")
assert.NoError(t, err) assert.NoError(t, err)
connID1 := xid.New().String() connID1 := xid.New().String()
@ -634,7 +634,7 @@ func TestGetUsersForQuotaCheck(t *testing.T) {
}, },
}, },
} }
err = dataprovider.AddUser(&user, "", "") err = dataprovider.AddUser(&user, "", "", "")
assert.NoError(t, err) assert.NoError(t, err)
err = dataprovider.UpdateVirtualFolderQuota(&vfs.BaseVirtualFolder{Name: fmt.Sprintf("f%v", i)}, 1, 50, false) err = dataprovider.UpdateVirtualFolderQuota(&vfs.BaseVirtualFolder{Name: fmt.Sprintf("f%v", i)}, 1, 50, false)
assert.NoError(t, err) assert.NoError(t, err)
@ -673,7 +673,7 @@ func TestGetUsersForQuotaCheck(t *testing.T) {
for i := 0; i < 40; i++ { for i := 0; i < 40; i++ {
err = dataprovider.DeleteUser(fmt.Sprintf("user%v", i), "", "", "") err = dataprovider.DeleteUser(fmt.Sprintf("user%v", i), "", "", "")
assert.NoError(t, err) assert.NoError(t, err)
err = dataprovider.DeleteFolder(fmt.Sprintf("f%v", i), "", "") err = dataprovider.DeleteFolder(fmt.Sprintf("f%v", i), "", "", "")
assert.NoError(t, err) assert.NoError(t, err)
} }

View file

@ -58,7 +58,7 @@ var (
reservedUsers = []string{ActionExecutorSelf, ActionExecutorSystem} reservedUsers = []string{ActionExecutorSelf, ActionExecutorSystem}
) )
func executeAction(operation, executor, ip, objectType, objectName string, object plugin.Renderer) { func executeAction(operation, executor, ip, objectType, objectName, role string, object plugin.Renderer) {
if plugin.Handler.HasNotifiers() { if plugin.Handler.HasNotifiers() {
plugin.Handler.NotifyProviderEvent(&notifier.ProviderEvent{ plugin.Handler.NotifyProviderEvent(&notifier.ProviderEvent{
Action: operation, Action: operation,
@ -66,11 +66,12 @@ func executeAction(operation, executor, ip, objectType, objectName string, objec
ObjectType: objectType, ObjectType: objectType,
ObjectName: objectName, ObjectName: objectName,
IP: ip, IP: ip,
Role: role,
Timestamp: time.Now().UnixNano(), Timestamp: time.Now().UnixNano(),
}, object) }, object)
} }
if fnHandleRuleForProviderEvent != nil { if fnHandleRuleForProviderEvent != nil {
fnHandleRuleForProviderEvent(operation, executor, ip, objectType, objectName, object) fnHandleRuleForProviderEvent(operation, executor, ip, objectType, objectName, role, object)
} }
if config.Actions.Hook == "" { if config.Actions.Hook == "" {
return return
@ -105,6 +106,9 @@ func executeAction(operation, executor, ip, objectType, objectName string, objec
q.Add("ip", ip) q.Add("ip", ip)
q.Add("object_type", objectType) q.Add("object_type", objectType)
q.Add("object_name", objectName) q.Add("object_name", objectName)
if role != "" {
q.Add("role", role)
}
q.Add("timestamp", fmt.Sprintf("%d", time.Now().UnixNano())) q.Add("timestamp", fmt.Sprintf("%d", time.Now().UnixNano()))
url.RawQuery = q.Encode() url.RawQuery = q.Encode()
startTime := time.Now() startTime := time.Now()
@ -114,15 +118,15 @@ func executeAction(operation, executor, ip, objectType, objectName string, objec
respCode = resp.StatusCode respCode = resp.StatusCode
resp.Body.Close() resp.Body.Close()
} }
providerLog(logger.LevelDebug, "notified operation %#v to URL: %v status code: %v, elapsed: %v err: %v", providerLog(logger.LevelDebug, "notified operation %q to URL: %s status code: %d, elapsed: %s err: %v",
operation, url.Redacted(), respCode, time.Since(startTime), err) operation, url.Redacted(), respCode, time.Since(startTime), err)
} else { return
executeNotificationCommand(operation, executor, ip, objectType, objectName, dataAsJSON) //nolint:errcheck // the error is used in test cases only
} }
executeNotificationCommand(operation, executor, ip, objectType, objectName, role, dataAsJSON) //nolint:errcheck // the error is used in test cases only
}() }()
} }
func executeNotificationCommand(operation, executor, ip, objectType, objectName string, objectAsJSON []byte) error { func executeNotificationCommand(operation, executor, ip, objectType, objectName, role string, objectAsJSON []byte) error {
if !filepath.IsAbs(config.Actions.Hook) { if !filepath.IsAbs(config.Actions.Hook) {
err := fmt.Errorf("invalid notification command %#v", config.Actions.Hook) err := fmt.Errorf("invalid notification command %#v", config.Actions.Hook)
logger.Warn(logSender, "", "unable to execute notification command: %v", err) logger.Warn(logSender, "", "unable to execute notification command: %v", err)
@ -140,6 +144,7 @@ func executeNotificationCommand(operation, executor, ip, objectType, objectName
fmt.Sprintf("SFTPGO_PROVIDER_OBJECT_NAME=%s", objectName), fmt.Sprintf("SFTPGO_PROVIDER_OBJECT_NAME=%s", objectName),
fmt.Sprintf("SFTPGO_PROVIDER_USERNAME=%s", executor), fmt.Sprintf("SFTPGO_PROVIDER_USERNAME=%s", executor),
fmt.Sprintf("SFTPGO_PROVIDER_IP=%s", ip), fmt.Sprintf("SFTPGO_PROVIDER_IP=%s", ip),
fmt.Sprintf("SFTPGO_PROVIDER_ROLE=%s", role),
fmt.Sprintf("SFTPGO_PROVIDER_TIMESTAMP=%d", util.GetTimeAsMsSinceEpoch(time.Now())), fmt.Sprintf("SFTPGO_PROVIDER_TIMESTAMP=%d", util.GetTimeAsMsSinceEpoch(time.Now())),
fmt.Sprintf("SFTPGO_PROVIDER_OBJECT=%s", string(objectAsJSON))) fmt.Sprintf("SFTPGO_PROVIDER_OBJECT=%s", string(objectAsJSON)))

View file

@ -75,7 +75,7 @@ var (
PermAdminManageAPIKeys, PermAdminQuotaScans, PermAdminManageSystem, PermAdminManageDefender, PermAdminManageAPIKeys, PermAdminQuotaScans, PermAdminManageSystem, PermAdminManageDefender,
PermAdminViewDefender, PermAdminRetentionChecks, PermAdminMetadataChecks, PermAdminViewEvents} PermAdminViewDefender, PermAdminRetentionChecks, PermAdminMetadataChecks, PermAdminViewEvents}
forbiddenPermsForRoleAdmins = []string{PermAdminAny, PermAdminManageAdmins, PermAdminManageSystem, forbiddenPermsForRoleAdmins = []string{PermAdminAny, PermAdminManageAdmins, PermAdminManageSystem,
PermAdminManageEventRules, PermAdminManageRoles, PermAdminViewEvents} PermAdminManageEventRules, PermAdminManageRoles}
) )
// AdminTOTPConfig defines the time-based one time password configuration // AdminTOTPConfig defines the time-based one time password configuration

View file

@ -233,7 +233,7 @@ type FnReloadRules func()
type FnRemoveRule func(name string) type FnRemoveRule func(name string)
// FnHandleRuleForProviderEvent define the callback to handle event rules for provider events // FnHandleRuleForProviderEvent define the callback to handle event rules for provider events
type FnHandleRuleForProviderEvent func(operation, executor, ip, objectType, objectName string, object plugin.Renderer) type FnHandleRuleForProviderEvent func(operation, executor, ip, objectType, objectName, role string, object plugin.Renderer)
// SetEventRulesCallbacks sets the event rules callbacks // SetEventRulesCallbacks sets the event rules callbacks
func SetEventRulesCallbacks(reload FnReloadRules, remove FnRemoveRule, handle FnHandleRuleForProviderEvent) { func SetEventRulesCallbacks(reload FnReloadRules, remove FnRemoveRule, handle FnHandleRuleForProviderEvent) {
@ -1504,32 +1504,32 @@ func GetUsedVirtualFolderQuota(name string) (int, int64, error) {
} }
// AddShare adds a new share // AddShare adds a new share
func AddShare(share *Share, executor, ipAddress string) error { func AddShare(share *Share, executor, ipAddress, role string) error {
err := provider.addShare(share) err := provider.addShare(share)
if err == nil { if err == nil {
executeAction(operationAdd, executor, ipAddress, actionObjectShare, share.ShareID, share) executeAction(operationAdd, executor, ipAddress, actionObjectShare, share.ShareID, role, share)
} }
return err return err
} }
// UpdateShare updates an existing share // UpdateShare updates an existing share
func UpdateShare(share *Share, executor, ipAddress string) error { func UpdateShare(share *Share, executor, ipAddress, role string) error {
err := provider.updateShare(share) err := provider.updateShare(share)
if err == nil { if err == nil {
executeAction(operationUpdate, executor, ipAddress, actionObjectShare, share.ShareID, share) executeAction(operationUpdate, executor, ipAddress, actionObjectShare, share.ShareID, role, share)
} }
return err return err
} }
// DeleteShare deletes an existing share // DeleteShare deletes an existing share
func DeleteShare(shareID string, executor, ipAddress string) error { func DeleteShare(shareID string, executor, ipAddress, role string) error {
share, err := provider.shareExists(shareID, executor) share, err := provider.shareExists(shareID, executor)
if err != nil { if err != nil {
return err return err
} }
err = provider.deleteShare(share) err = provider.deleteShare(share)
if err == nil { if err == nil {
executeAction(operationDelete, executor, ipAddress, actionObjectShare, shareID, &share) executeAction(operationDelete, executor, ipAddress, actionObjectShare, shareID, role, &share)
} }
return err return err
} }
@ -1543,26 +1543,26 @@ func ShareExists(shareID, username string) (Share, error) {
} }
// AddRole adds a new role // AddRole adds a new role
func AddRole(role *Role, executor, ipAddress string) error { func AddRole(role *Role, executor, ipAddress, executorRole string) error {
role.Name = config.convertName(role.Name) role.Name = config.convertName(role.Name)
err := provider.addRole(role) err := provider.addRole(role)
if err == nil { if err == nil {
executeAction(operationAdd, executor, ipAddress, actionObjectRole, role.Name, role) executeAction(operationAdd, executor, ipAddress, actionObjectRole, role.Name, executorRole, role)
} }
return err return err
} }
// UpdateRole updates an existing Role // UpdateRole updates an existing Role
func UpdateRole(role *Role, executor, ipAddress string) error { func UpdateRole(role *Role, executor, ipAddress, executorRole string) error {
err := provider.updateRole(role) err := provider.updateRole(role)
if err == nil { if err == nil {
executeAction(operationUpdate, executor, ipAddress, actionObjectRole, role.Name, role) executeAction(operationUpdate, executor, ipAddress, actionObjectRole, role.Name, executorRole, role)
} }
return err return err
} }
// DeleteRole deletes an existing Role // DeleteRole deletes an existing Role
func DeleteRole(name string, executor, ipAddress string) error { func DeleteRole(name string, executor, ipAddress, executorRole string) error {
name = config.convertName(name) name = config.convertName(name)
role, err := provider.roleExists(name) role, err := provider.roleExists(name)
if err != nil { if err != nil {
@ -1574,13 +1574,13 @@ func DeleteRole(name string, executor, ipAddress string) error {
} }
err = provider.deleteRole(role) err = provider.deleteRole(role)
if err == nil { if err == nil {
executeAction(operationDelete, executor, ipAddress, actionObjectRole, role.Name, &role) executeAction(operationDelete, executor, ipAddress, actionObjectRole, role.Name, executorRole, &role)
for _, user := range role.Users { for _, user := range role.Users {
provider.setUpdatedAt(user) provider.setUpdatedAt(user)
u, err := provider.userExists(user, "") u, err := provider.userExists(user, "")
if err == nil { if err == nil {
webDAVUsersCache.swap(&u) webDAVUsersCache.swap(&u)
executeAction(operationUpdate, executor, ipAddress, actionObjectUser, u.Username, &u) executeAction(operationUpdate, executor, ipAddress, actionObjectUser, u.Username, u.Role, &u)
} }
} }
} }
@ -1594,17 +1594,17 @@ func RoleExists(name string) (Role, error) {
} }
// AddGroup adds a new group // AddGroup adds a new group
func AddGroup(group *Group, executor, ipAddress string) error { func AddGroup(group *Group, executor, ipAddress, role string) error {
group.Name = config.convertName(group.Name) group.Name = config.convertName(group.Name)
err := provider.addGroup(group) err := provider.addGroup(group)
if err == nil { if err == nil {
executeAction(operationAdd, executor, ipAddress, actionObjectGroup, group.Name, group) executeAction(operationAdd, executor, ipAddress, actionObjectGroup, group.Name, role, group)
} }
return err return err
} }
// UpdateGroup updates an existing Group // UpdateGroup updates an existing Group
func UpdateGroup(group *Group, users []string, executor, ipAddress string) error { func UpdateGroup(group *Group, users []string, executor, ipAddress, role string) error {
err := provider.updateGroup(group) err := provider.updateGroup(group)
if err == nil { if err == nil {
for _, user := range users { for _, user := range users {
@ -1612,18 +1612,17 @@ func UpdateGroup(group *Group, users []string, executor, ipAddress string) error
u, err := provider.userExists(user, "") u, err := provider.userExists(user, "")
if err == nil { if err == nil {
webDAVUsersCache.swap(&u) webDAVUsersCache.swap(&u)
executeAction(operationUpdate, executor, ipAddress, actionObjectUser, u.Username, &u)
} else { } else {
RemoveCachedWebDAVUser(user) RemoveCachedWebDAVUser(user)
} }
} }
executeAction(operationUpdate, executor, ipAddress, actionObjectGroup, group.Name, group) executeAction(operationUpdate, executor, ipAddress, actionObjectGroup, group.Name, role, group)
} }
return err return err
} }
// DeleteGroup deletes an existing Group // DeleteGroup deletes an existing Group
func DeleteGroup(name string, executor, ipAddress string) error { func DeleteGroup(name string, executor, ipAddress, role string) error {
name = config.convertName(name) name = config.convertName(name)
group, err := provider.groupExists(name) group, err := provider.groupExists(name)
if err != nil { if err != nil {
@ -1639,11 +1638,11 @@ func DeleteGroup(name string, executor, ipAddress string) error {
provider.setUpdatedAt(user) provider.setUpdatedAt(user)
u, err := provider.userExists(user, "") u, err := provider.userExists(user, "")
if err == nil { if err == nil {
executeAction(operationUpdate, executor, ipAddress, actionObjectUser, u.Username, &u) executeAction(operationUpdate, executor, ipAddress, actionObjectUser, u.Username, u.Role, &u)
} }
RemoveCachedWebDAVUser(user) RemoveCachedWebDAVUser(user)
} }
executeAction(operationDelete, executor, ipAddress, actionObjectGroup, group.Name, &group) executeAction(operationDelete, executor, ipAddress, actionObjectGroup, group.Name, role, &group)
} }
return err return err
} }
@ -1655,32 +1654,32 @@ func GroupExists(name string) (Group, error) {
} }
// AddAPIKey adds a new API key // AddAPIKey adds a new API key
func AddAPIKey(apiKey *APIKey, executor, ipAddress string) error { func AddAPIKey(apiKey *APIKey, executor, ipAddress, role string) error {
err := provider.addAPIKey(apiKey) err := provider.addAPIKey(apiKey)
if err == nil { if err == nil {
executeAction(operationAdd, executor, ipAddress, actionObjectAPIKey, apiKey.KeyID, apiKey) executeAction(operationAdd, executor, ipAddress, actionObjectAPIKey, apiKey.KeyID, role, apiKey)
} }
return err return err
} }
// UpdateAPIKey updates an existing API key // UpdateAPIKey updates an existing API key
func UpdateAPIKey(apiKey *APIKey, executor, ipAddress string) error { func UpdateAPIKey(apiKey *APIKey, executor, ipAddress, role string) error {
err := provider.updateAPIKey(apiKey) err := provider.updateAPIKey(apiKey)
if err == nil { if err == nil {
executeAction(operationUpdate, executor, ipAddress, actionObjectAPIKey, apiKey.KeyID, apiKey) executeAction(operationUpdate, executor, ipAddress, actionObjectAPIKey, apiKey.KeyID, role, apiKey)
} }
return err return err
} }
// DeleteAPIKey deletes an existing API key // DeleteAPIKey deletes an existing API key
func DeleteAPIKey(keyID string, executor, ipAddress string) error { func DeleteAPIKey(keyID string, executor, ipAddress, role string) error {
apiKey, err := provider.apiKeyExists(keyID) apiKey, err := provider.apiKeyExists(keyID)
if err != nil { if err != nil {
return err return err
} }
err = provider.deleteAPIKey(apiKey) err = provider.deleteAPIKey(apiKey)
if err == nil { if err == nil {
executeAction(operationDelete, executor, ipAddress, actionObjectAPIKey, apiKey.KeyID, &apiKey) executeAction(operationDelete, executor, ipAddress, actionObjectAPIKey, apiKey.KeyID, role, &apiKey)
} }
return err return err
} }
@ -1705,29 +1704,29 @@ func EventActionExists(name string) (BaseEventAction, error) {
} }
// AddEventAction adds a new event action // AddEventAction adds a new event action
func AddEventAction(action *BaseEventAction, executor, ipAddress string) error { func AddEventAction(action *BaseEventAction, executor, ipAddress, role string) error {
action.Name = config.convertName(action.Name) action.Name = config.convertName(action.Name)
err := provider.addEventAction(action) err := provider.addEventAction(action)
if err == nil { if err == nil {
executeAction(operationAdd, executor, ipAddress, actionObjectEventAction, action.Name, action) executeAction(operationAdd, executor, ipAddress, actionObjectEventAction, action.Name, role, action)
} }
return err return err
} }
// UpdateEventAction updates an existing event action // UpdateEventAction updates an existing event action
func UpdateEventAction(action *BaseEventAction, executor, ipAddress string) error { func UpdateEventAction(action *BaseEventAction, executor, ipAddress, role string) error {
err := provider.updateEventAction(action) err := provider.updateEventAction(action)
if err == nil { if err == nil {
if fnReloadRules != nil { if fnReloadRules != nil {
fnReloadRules() fnReloadRules()
} }
executeAction(operationUpdate, executor, ipAddress, actionObjectEventAction, action.Name, action) executeAction(operationUpdate, executor, ipAddress, actionObjectEventAction, action.Name, role, action)
} }
return err return err
} }
// DeleteEventAction deletes an existing event action // DeleteEventAction deletes an existing event action
func DeleteEventAction(name string, executor, ipAddress string) error { func DeleteEventAction(name string, executor, ipAddress, role string) error {
name = config.convertName(name) name = config.convertName(name)
action, err := provider.eventActionExists(name) action, err := provider.eventActionExists(name)
if err != nil { if err != nil {
@ -1739,7 +1738,7 @@ func DeleteEventAction(name string, executor, ipAddress string) error {
} }
err = provider.deleteEventAction(action) err = provider.deleteEventAction(action)
if err == nil { if err == nil {
executeAction(operationDelete, executor, ipAddress, actionObjectEventAction, action.Name, &action) executeAction(operationDelete, executor, ipAddress, actionObjectEventAction, action.Name, role, &action)
} }
return err return err
} }
@ -1761,32 +1760,32 @@ func EventRuleExists(name string) (EventRule, error) {
} }
// AddEventRule adds a new event rule // AddEventRule adds a new event rule
func AddEventRule(rule *EventRule, executor, ipAddress string) error { func AddEventRule(rule *EventRule, executor, ipAddress, role string) error {
rule.Name = config.convertName(rule.Name) rule.Name = config.convertName(rule.Name)
err := provider.addEventRule(rule) err := provider.addEventRule(rule)
if err == nil { if err == nil {
if fnReloadRules != nil { if fnReloadRules != nil {
fnReloadRules() fnReloadRules()
} }
executeAction(operationAdd, executor, ipAddress, actionObjectEventRule, rule.Name, rule) executeAction(operationAdd, executor, ipAddress, actionObjectEventRule, rule.Name, role, rule)
} }
return err return err
} }
// UpdateEventRule updates an existing event rule // UpdateEventRule updates an existing event rule
func UpdateEventRule(rule *EventRule, executor, ipAddress string) error { func UpdateEventRule(rule *EventRule, executor, ipAddress, role string) error {
err := provider.updateEventRule(rule) err := provider.updateEventRule(rule)
if err == nil { if err == nil {
if fnReloadRules != nil { if fnReloadRules != nil {
fnReloadRules() fnReloadRules()
} }
executeAction(operationUpdate, executor, ipAddress, actionObjectEventRule, rule.Name, rule) executeAction(operationUpdate, executor, ipAddress, actionObjectEventRule, rule.Name, role, rule)
} }
return err return err
} }
// DeleteEventRule deletes an existing event rule // DeleteEventRule deletes an existing event rule
func DeleteEventRule(name string, executor, ipAddress string) error { func DeleteEventRule(name string, executor, ipAddress, role string) error {
name = config.convertName(name) name = config.convertName(name)
rule, err := provider.eventRuleExists(name) rule, err := provider.eventRuleExists(name)
if err != nil { if err != nil {
@ -1797,7 +1796,7 @@ func DeleteEventRule(name string, executor, ipAddress string) error {
if fnRemoveRule != nil { if fnRemoveRule != nil {
fnRemoveRule(rule.Name) fnRemoveRule(rule.Name)
} }
executeAction(operationDelete, executor, ipAddress, actionObjectEventRule, rule.Name, &rule) executeAction(operationDelete, executor, ipAddress, actionObjectEventRule, rule.Name, role, &rule)
} }
return err return err
} }
@ -1857,7 +1856,7 @@ func HasAdmin() bool {
} }
// AddAdmin adds a new SFTPGo admin // AddAdmin adds a new SFTPGo admin
func AddAdmin(admin *Admin, executor, ipAddress string) error { func AddAdmin(admin *Admin, executor, ipAddress, role string) error {
admin.Filters.RecoveryCodes = nil admin.Filters.RecoveryCodes = nil
admin.Filters.TOTPConfig = AdminTOTPConfig{ admin.Filters.TOTPConfig = AdminTOTPConfig{
Enabled: false, Enabled: false,
@ -1866,22 +1865,22 @@ func AddAdmin(admin *Admin, executor, ipAddress string) error {
err := provider.addAdmin(admin) err := provider.addAdmin(admin)
if err == nil { if err == nil {
isAdminCreated.Store(true) isAdminCreated.Store(true)
executeAction(operationAdd, executor, ipAddress, actionObjectAdmin, admin.Username, admin) executeAction(operationAdd, executor, ipAddress, actionObjectAdmin, admin.Username, role, admin)
} }
return err return err
} }
// UpdateAdmin updates an existing SFTPGo admin // UpdateAdmin updates an existing SFTPGo admin
func UpdateAdmin(admin *Admin, executor, ipAddress string) error { func UpdateAdmin(admin *Admin, executor, ipAddress, role string) error {
err := provider.updateAdmin(admin) err := provider.updateAdmin(admin)
if err == nil { if err == nil {
executeAction(operationUpdate, executor, ipAddress, actionObjectAdmin, admin.Username, admin) executeAction(operationUpdate, executor, ipAddress, actionObjectAdmin, admin.Username, role, admin)
} }
return err return err
} }
// DeleteAdmin deletes an existing SFTPGo admin // DeleteAdmin deletes an existing SFTPGo admin
func DeleteAdmin(username, executor, ipAddress string) error { func DeleteAdmin(username, executor, ipAddress, role string) error {
username = config.convertName(username) username = config.convertName(username)
admin, err := provider.adminExists(username) admin, err := provider.adminExists(username)
if err != nil { if err != nil {
@ -1889,7 +1888,7 @@ func DeleteAdmin(username, executor, ipAddress string) error {
} }
err = provider.deleteAdmin(admin) err = provider.deleteAdmin(admin)
if err == nil { if err == nil {
executeAction(operationDelete, executor, ipAddress, actionObjectAdmin, admin.Username, &admin) executeAction(operationDelete, executor, ipAddress, actionObjectAdmin, admin.Username, role, &admin)
} }
return err return err
} }
@ -1932,17 +1931,17 @@ func GetUserVariants(username, role string) (User, User, error) {
} }
// AddUser adds a new SFTPGo user. // AddUser adds a new SFTPGo user.
func AddUser(user *User, executor, ipAddress string) error { func AddUser(user *User, executor, ipAddress, role string) error {
user.Username = config.convertName(user.Username) user.Username = config.convertName(user.Username)
err := provider.addUser(user) err := provider.addUser(user)
if err == nil { if err == nil {
executeAction(operationAdd, executor, ipAddress, actionObjectUser, user.Username, user) executeAction(operationAdd, executor, ipAddress, actionObjectUser, user.Username, role, user)
} }
return err return err
} }
// UpdateUserPassword updates the user password // UpdateUserPassword updates the user password
func UpdateUserPassword(username, plainPwd, executor, ipAddress string) error { func UpdateUserPassword(username, plainPwd, executor, ipAddress, role string) error {
hashedPwd, err := hashPlainPassword(plainPwd) hashedPwd, err := hashPlainPassword(plainPwd)
if err != nil { if err != nil {
return util.NewGenericError(fmt.Sprintf("unable to set the new password: %v", err)) return util.NewGenericError(fmt.Sprintf("unable to set the new password: %v", err))
@ -1952,12 +1951,12 @@ func UpdateUserPassword(username, plainPwd, executor, ipAddress string) error {
return util.NewGenericError(fmt.Sprintf("unable to set the new password: %v", err)) return util.NewGenericError(fmt.Sprintf("unable to set the new password: %v", err))
} }
cachedPasswords.Remove(username) cachedPasswords.Remove(username)
executeAction(operationUpdate, executor, ipAddress, actionObjectUser, username, &User{}) executeAction(operationUpdate, executor, ipAddress, actionObjectUser, username, role, &User{})
return nil return nil
} }
// UpdateUser updates an existing SFTPGo user. // UpdateUser updates an existing SFTPGo user.
func UpdateUser(user *User, executor, ipAddress string) error { func UpdateUser(user *User, executor, ipAddress, role string) error {
if user.groupSettingsApplied { if user.groupSettingsApplied {
return errors.New("cannot save a user with group settings applied") return errors.New("cannot save a user with group settings applied")
} }
@ -1965,7 +1964,7 @@ func UpdateUser(user *User, executor, ipAddress string) error {
if err == nil { if err == nil {
webDAVUsersCache.swap(user) webDAVUsersCache.swap(user)
cachedPasswords.Remove(user.Username) cachedPasswords.Remove(user.Username)
executeAction(operationUpdate, executor, ipAddress, actionObjectUser, user.Username, user) executeAction(operationUpdate, executor, ipAddress, actionObjectUser, user.Username, role, user)
} }
return err return err
} }
@ -1982,7 +1981,7 @@ func DeleteUser(username, executor, ipAddress, role string) error {
RemoveCachedWebDAVUser(user.Username) RemoveCachedWebDAVUser(user.Username)
delayedQuotaUpdater.resetUserQuota(user.Username) delayedQuotaUpdater.resetUserQuota(user.Username)
cachedPasswords.Remove(username) cachedPasswords.Remove(username)
executeAction(operationDelete, executor, ipAddress, actionObjectUser, user.Username, &user) executeAction(operationDelete, executor, ipAddress, actionObjectUser, user.Username, role, &user)
} }
return err return err
} }
@ -2106,20 +2105,20 @@ func GetUsersForQuotaCheck(toFetch map[string]bool) ([]User, error) {
} }
// AddFolder adds a new virtual folder. // AddFolder adds a new virtual folder.
func AddFolder(folder *vfs.BaseVirtualFolder, executor, ipAddress string) error { func AddFolder(folder *vfs.BaseVirtualFolder, executor, ipAddress, role string) error {
folder.Name = config.convertName(folder.Name) folder.Name = config.convertName(folder.Name)
err := provider.addFolder(folder) err := provider.addFolder(folder)
if err == nil { if err == nil {
executeAction(operationAdd, executor, ipAddress, actionObjectFolder, folder.Name, &wrappedFolder{Folder: *folder}) executeAction(operationAdd, executor, ipAddress, actionObjectFolder, folder.Name, role, &wrappedFolder{Folder: *folder})
} }
return err return err
} }
// UpdateFolder updates the specified virtual folder // UpdateFolder updates the specified virtual folder
func UpdateFolder(folder *vfs.BaseVirtualFolder, users []string, groups []string, executor, ipAddress string) error { func UpdateFolder(folder *vfs.BaseVirtualFolder, users []string, groups []string, executor, ipAddress, role string) error {
err := provider.updateFolder(folder) err := provider.updateFolder(folder)
if err == nil { if err == nil {
executeAction(operationUpdate, executor, ipAddress, actionObjectFolder, folder.Name, &wrappedFolder{Folder: *folder}) executeAction(operationUpdate, executor, ipAddress, actionObjectFolder, folder.Name, role, &wrappedFolder{Folder: *folder})
usersInGroups, errGrp := provider.getUsersInGroups(groups) usersInGroups, errGrp := provider.getUsersInGroups(groups)
if errGrp == nil { if errGrp == nil {
users = append(users, usersInGroups...) users = append(users, usersInGroups...)
@ -2132,7 +2131,7 @@ func UpdateFolder(folder *vfs.BaseVirtualFolder, users []string, groups []string
u, err := provider.userExists(user, "") u, err := provider.userExists(user, "")
if err == nil { if err == nil {
webDAVUsersCache.swap(&u) webDAVUsersCache.swap(&u)
executeAction(operationUpdate, executor, ipAddress, actionObjectUser, u.Username, &u) executeAction(operationUpdate, executor, ipAddress, actionObjectUser, u.Username, u.Role, &u)
} else { } else {
RemoveCachedWebDAVUser(user) RemoveCachedWebDAVUser(user)
} }
@ -2142,7 +2141,7 @@ func UpdateFolder(folder *vfs.BaseVirtualFolder, users []string, groups []string
} }
// DeleteFolder deletes an existing folder. // DeleteFolder deletes an existing folder.
func DeleteFolder(folderName, executor, ipAddress string) error { func DeleteFolder(folderName, executor, ipAddress, role string) error {
folderName = config.convertName(folderName) folderName = config.convertName(folderName)
folder, err := provider.getFolderByName(folderName) folder, err := provider.getFolderByName(folderName)
if err != nil { if err != nil {
@ -2150,7 +2149,7 @@ func DeleteFolder(folderName, executor, ipAddress string) error {
} }
err = provider.deleteFolder(folder) err = provider.deleteFolder(folder)
if err == nil { if err == nil {
executeAction(operationDelete, executor, ipAddress, actionObjectFolder, folder.Name, &wrappedFolder{Folder: folder}) executeAction(operationDelete, executor, ipAddress, actionObjectFolder, folder.Name, role, &wrappedFolder{Folder: folder})
users := folder.Users users := folder.Users
usersInGroups, errGrp := provider.getUsersInGroups(folder.Groups) usersInGroups, errGrp := provider.getUsersInGroups(folder.Groups)
if errGrp == nil { if errGrp == nil {
@ -2163,7 +2162,7 @@ func DeleteFolder(folderName, executor, ipAddress string) error {
provider.setUpdatedAt(user) provider.setUpdatedAt(user)
u, err := provider.userExists(user, "") u, err := provider.userExists(user, "")
if err == nil { if err == nil {
executeAction(operationUpdate, executor, ipAddress, actionObjectUser, u.Username, &u) executeAction(operationUpdate, executor, ipAddress, actionObjectUser, u.Username, u.Role, &u)
} }
RemoveCachedWebDAVUser(user) RemoveCachedWebDAVUser(user)
} }

View file

@ -2805,13 +2805,13 @@ func (p *MemoryProvider) restoreEventActions(dump BackupData) error {
action := action // pin action := action // pin
if err == nil { if err == nil {
action.ID = a.ID action.ID = a.ID
err = UpdateEventAction(&action, ActionExecutorSystem, "") err = UpdateEventAction(&action, ActionExecutorSystem, "", "")
if err != nil { if err != nil {
providerLog(logger.LevelError, "error updating event action %q: %v", action.Name, err) providerLog(logger.LevelError, "error updating event action %q: %v", action.Name, err)
return err return err
} }
} else { } else {
err = AddEventAction(&action, ActionExecutorSystem, "") err = AddEventAction(&action, ActionExecutorSystem, "", "")
if err != nil { if err != nil {
providerLog(logger.LevelError, "error adding event action %q: %v", action.Name, err) providerLog(logger.LevelError, "error adding event action %q: %v", action.Name, err)
return err return err
@ -2827,13 +2827,13 @@ func (p *MemoryProvider) restoreEventRules(dump BackupData) error {
rule := rule // pin rule := rule // pin
if err == nil { if err == nil {
rule.ID = r.ID rule.ID = r.ID
err = UpdateEventRule(&rule, ActionExecutorSystem, "") err = UpdateEventRule(&rule, ActionExecutorSystem, "", "")
if err != nil { if err != nil {
providerLog(logger.LevelError, "error updating event rule %q: %v", rule.Name, err) providerLog(logger.LevelError, "error updating event rule %q: %v", rule.Name, err)
return err return err
} }
} else { } else {
err = AddEventRule(&rule, ActionExecutorSystem, "") err = AddEventRule(&rule, ActionExecutorSystem, "", "")
if err != nil { if err != nil {
providerLog(logger.LevelError, "error adding event rule %q: %v", rule.Name, err) providerLog(logger.LevelError, "error adding event rule %q: %v", rule.Name, err)
return err return err
@ -2850,13 +2850,13 @@ func (p *MemoryProvider) restoreShares(dump BackupData) error {
share.IsRestore = true share.IsRestore = true
if err == nil { if err == nil {
share.ID = s.ID share.ID = s.ID
err = UpdateShare(&share, ActionExecutorSystem, "") err = UpdateShare(&share, ActionExecutorSystem, "", "")
if err != nil { if err != nil {
providerLog(logger.LevelError, "error updating share %#v: %v", share.ShareID, err) providerLog(logger.LevelError, "error updating share %#v: %v", share.ShareID, err)
return err return err
} }
} else { } else {
err = AddShare(&share, ActionExecutorSystem, "") err = AddShare(&share, ActionExecutorSystem, "", "")
if err != nil { if err != nil {
providerLog(logger.LevelError, "error adding share %#v: %v", share.ShareID, err) providerLog(logger.LevelError, "error adding share %#v: %v", share.ShareID, err)
return err return err
@ -2875,13 +2875,13 @@ func (p *MemoryProvider) restoreAPIKeys(dump BackupData) error {
apiKey := apiKey // pin apiKey := apiKey // pin
if err == nil { if err == nil {
apiKey.ID = k.ID apiKey.ID = k.ID
err = UpdateAPIKey(&apiKey, ActionExecutorSystem, "") err = UpdateAPIKey(&apiKey, ActionExecutorSystem, "", "")
if err != nil { if err != nil {
providerLog(logger.LevelError, "error updating API key %#v: %v", apiKey.KeyID, err) providerLog(logger.LevelError, "error updating API key %#v: %v", apiKey.KeyID, err)
return err return err
} }
} else { } else {
err = AddAPIKey(&apiKey, ActionExecutorSystem, "") err = AddAPIKey(&apiKey, ActionExecutorSystem, "", "")
if err != nil { if err != nil {
providerLog(logger.LevelError, "error adding API key %#v: %v", apiKey.KeyID, err) providerLog(logger.LevelError, "error adding API key %#v: %v", apiKey.KeyID, err)
return err return err
@ -2898,13 +2898,13 @@ func (p *MemoryProvider) restoreAdmins(dump BackupData) error {
a, err := p.adminExists(admin.Username) a, err := p.adminExists(admin.Username)
if err == nil { if err == nil {
admin.ID = a.ID admin.ID = a.ID
err = UpdateAdmin(&admin, ActionExecutorSystem, "") err = UpdateAdmin(&admin, ActionExecutorSystem, "", "")
if err != nil { if err != nil {
providerLog(logger.LevelError, "error updating admin %#v: %v", admin.Username, err) providerLog(logger.LevelError, "error updating admin %#v: %v", admin.Username, err)
return err return err
} }
} else { } else {
err = AddAdmin(&admin, ActionExecutorSystem, "") err = AddAdmin(&admin, ActionExecutorSystem, "", "")
if err != nil { if err != nil {
providerLog(logger.LevelError, "error adding admin %#v: %v", admin.Username, err) providerLog(logger.LevelError, "error adding admin %#v: %v", admin.Username, err)
return err return err
@ -2921,7 +2921,7 @@ func (p *MemoryProvider) restoreRoles(dump BackupData) error {
r, err := p.roleExists(role.Name) r, err := p.roleExists(role.Name)
if err == nil { if err == nil {
role.ID = r.ID role.ID = r.ID
err = UpdateRole(&role, ActionExecutorSystem, "") err = UpdateRole(&role, ActionExecutorSystem, "", "")
if err != nil { if err != nil {
providerLog(logger.LevelError, "error updating role %q: %v", role.Name, err) providerLog(logger.LevelError, "error updating role %q: %v", role.Name, err)
return err return err
@ -2929,7 +2929,7 @@ func (p *MemoryProvider) restoreRoles(dump BackupData) error {
} else { } else {
role.Admins = nil role.Admins = nil
role.Users = nil role.Users = nil
err = AddRole(&role, ActionExecutorSystem, "") err = AddRole(&role, ActionExecutorSystem, "", "")
if err != nil { if err != nil {
providerLog(logger.LevelError, "error adding role %q: %v", role.Name, err) providerLog(logger.LevelError, "error adding role %q: %v", role.Name, err)
return err return err
@ -2946,14 +2946,14 @@ func (p *MemoryProvider) restoreGroups(dump BackupData) error {
g, err := p.groupExists(group.Name) g, err := p.groupExists(group.Name)
if err == nil { if err == nil {
group.ID = g.ID group.ID = g.ID
err = UpdateGroup(&group, g.Users, ActionExecutorSystem, "") err = UpdateGroup(&group, g.Users, ActionExecutorSystem, "", "")
if err != nil { if err != nil {
providerLog(logger.LevelError, "error updating group %#v: %v", group.Name, err) providerLog(logger.LevelError, "error updating group %#v: %v", group.Name, err)
return err return err
} }
} else { } else {
group.Users = nil group.Users = nil
err = AddGroup(&group, ActionExecutorSystem, "") err = AddGroup(&group, ActionExecutorSystem, "", "")
if err != nil { if err != nil {
providerLog(logger.LevelError, "error adding group %#v: %v", group.Name, err) providerLog(logger.LevelError, "error adding group %#v: %v", group.Name, err)
return err return err
@ -2970,14 +2970,14 @@ func (p *MemoryProvider) restoreFolders(dump BackupData) error {
f, err := p.getFolderByName(folder.Name) f, err := p.getFolderByName(folder.Name)
if err == nil { if err == nil {
folder.ID = f.ID folder.ID = f.ID
err = UpdateFolder(&folder, f.Users, f.Groups, ActionExecutorSystem, "") err = UpdateFolder(&folder, f.Users, f.Groups, ActionExecutorSystem, "", "")
if err != nil { if err != nil {
providerLog(logger.LevelError, "error updating folder %#v: %v", folder.Name, err) providerLog(logger.LevelError, "error updating folder %#v: %v", folder.Name, err)
return err return err
} }
} else { } else {
folder.Users = nil folder.Users = nil
err = AddFolder(&folder, ActionExecutorSystem, "") err = AddFolder(&folder, ActionExecutorSystem, "", "")
if err != nil { if err != nil {
providerLog(logger.LevelError, "error adding folder %#v: %v", folder.Name, err) providerLog(logger.LevelError, "error adding folder %#v: %v", folder.Name, err)
return err return err
@ -2994,13 +2994,13 @@ func (p *MemoryProvider) restoreUsers(dump BackupData) error {
u, err := p.userExists(user.Username, "") u, err := p.userExists(user.Username, "")
if err == nil { if err == nil {
user.ID = u.ID user.ID = u.ID
err = UpdateUser(&user, ActionExecutorSystem, "") err = UpdateUser(&user, ActionExecutorSystem, "", "")
if err != nil { if err != nil {
providerLog(logger.LevelError, "error updating user %#v: %v", user.Username, err) providerLog(logger.LevelError, "error updating user %#v: %v", user.Username, err)
return err return err
} }
} else { } else {
err = AddUser(&user, ActionExecutorSystem, "") err = AddUser(&user, ActionExecutorSystem, "", "")
if err != nil { if err != nil {
providerLog(logger.LevelError, "error adding user %#v: %v", user.Username, err) providerLog(logger.LevelError, "error adding user %#v: %v", user.Username, err)
return err return err

View file

@ -58,6 +58,9 @@ func (r *Role) validate() error {
if r.Name == "" { if r.Name == "" {
return util.NewValidationError("name is mandatory") return util.NewValidationError("name is mandatory")
} }
if len(r.Name) > 255 {
return util.NewValidationError("name is too long, 255 is the maximum length allowed")
}
if config.NamingRules&1 == 0 && !usernameRegex.MatchString(r.Name) { if config.NamingRules&1 == 0 && !usernameRegex.MatchString(r.Name) {
return util.NewValidationError(fmt.Sprintf("name %q is not valid, the following characters are allowed: a-zA-Z0-9-_.~", r.Name)) return util.NewValidationError(fmt.Sprintf("name %q is not valid, the following characters are allowed: a-zA-Z0-9-_.~", r.Name))
} }

View file

@ -1024,7 +1024,7 @@ func TestMultiFactorAuth(t *testing.T) {
Secret: kms.NewPlainSecret(secret), Secret: kms.NewPlainSecret(secret),
Protocols: []string{common.ProtocolFTP}, Protocols: []string{common.ProtocolFTP},
} }
err = dataprovider.UpdateUser(&user, "", "") err = dataprovider.UpdateUser(&user, "", "", "")
assert.NoError(t, err) assert.NoError(t, err)
user.Password = defaultPassword user.Password = defaultPassword
@ -1073,7 +1073,7 @@ func TestSecondFactorRequirement(t *testing.T) {
Secret: kms.NewPlainSecret(secret), Secret: kms.NewPlainSecret(secret),
Protocols: []string{common.ProtocolFTP}, Protocols: []string{common.ProtocolFTP},
} }
err = dataprovider.UpdateUser(&user, "", "") err = dataprovider.UpdateUser(&user, "", "", "")
assert.NoError(t, err) assert.NoError(t, err)
passcode, err := generateTOTPPasscode(secret, otp.AlgorithmSHA1) passcode, err := generateTOTPPasscode(secret, otp.AlgorithmSHA1)
assert.NoError(t, err) assert.NoError(t, err)
@ -1611,7 +1611,7 @@ func TestMaxConnections(t *testing.T) {
}, 1000*time.Millisecond, 50*time.Millisecond) }, 1000*time.Millisecond, 50*time.Millisecond)
user := getTestUser() user := getTestUser()
err := dataprovider.AddUser(&user, "", "") err := dataprovider.AddUser(&user, "", "", "")
assert.NoError(t, err) assert.NoError(t, err)
user.Password = "" user.Password = ""
client, err := getFTPClient(user, true, nil) client, err := getFTPClient(user, true, nil)
@ -1641,7 +1641,7 @@ func TestMaxPerHostConnections(t *testing.T) {
}, 1000*time.Millisecond, 50*time.Millisecond) }, 1000*time.Millisecond, 50*time.Millisecond)
user := getTestUser() user := getTestUser()
err := dataprovider.AddUser(&user, "", "") err := dataprovider.AddUser(&user, "", "", "")
assert.NoError(t, err) assert.NoError(t, err)
user.Password = "" user.Password = ""
client, err := getFTPClient(user, true, nil) client, err := getFTPClient(user, true, nil)

View file

@ -76,7 +76,7 @@ func addAdmin(w http.ResponseWriter, r *http.Request) {
sendAPIResponse(w, r, err, "", http.StatusBadRequest) sendAPIResponse(w, r, err, "", http.StatusBadRequest)
return return
} }
err = dataprovider.AddAdmin(&admin, claims.Username, util.GetIPFromRemoteAddress(r.RemoteAddr)) err = dataprovider.AddAdmin(&admin, claims.Username, util.GetIPFromRemoteAddress(r.RemoteAddr), claims.Role)
if err != nil { if err != nil {
sendAPIResponse(w, r, err, "", getRespStatus(err)) sendAPIResponse(w, r, err, "", getRespStatus(err))
return return
@ -100,7 +100,7 @@ func disableAdmin2FA(w http.ResponseWriter, r *http.Request) {
admin.Filters.TOTPConfig = dataprovider.AdminTOTPConfig{ admin.Filters.TOTPConfig = dataprovider.AdminTOTPConfig{
Enabled: false, Enabled: false,
} }
if err := dataprovider.UpdateAdmin(&admin, claims.Username, util.GetIPFromRemoteAddress(r.RemoteAddr)); err != nil { if err := dataprovider.UpdateAdmin(&admin, claims.Username, util.GetIPFromRemoteAddress(r.RemoteAddr), claims.Role); err != nil {
sendAPIResponse(w, r, err, "", getRespStatus(err)) sendAPIResponse(w, r, err, "", getRespStatus(err))
return return
} }
@ -156,7 +156,7 @@ func updateAdmin(w http.ResponseWriter, r *http.Request) {
admin.Username = username admin.Username = username
admin.Filters.TOTPConfig = totpConfig admin.Filters.TOTPConfig = totpConfig
admin.Filters.RecoveryCodes = recoveryCodes admin.Filters.RecoveryCodes = recoveryCodes
if err := dataprovider.UpdateAdmin(&admin, claims.Username, util.GetIPFromRemoteAddress(r.RemoteAddr)); err != nil { if err := dataprovider.UpdateAdmin(&admin, claims.Username, util.GetIPFromRemoteAddress(r.RemoteAddr), claims.Role); err != nil {
sendAPIResponse(w, r, err, "", getRespStatus(err)) sendAPIResponse(w, r, err, "", getRespStatus(err))
return return
} }
@ -176,7 +176,7 @@ func deleteAdmin(w http.ResponseWriter, r *http.Request) {
return return
} }
err = dataprovider.DeleteAdmin(username, claims.Username, util.GetIPFromRemoteAddress(r.RemoteAddr)) err = dataprovider.DeleteAdmin(username, claims.Username, util.GetIPFromRemoteAddress(r.RemoteAddr), claims.Role)
if err != nil { if err != nil {
sendAPIResponse(w, r, err, "", getRespStatus(err)) sendAPIResponse(w, r, err, "", getRespStatus(err))
return return
@ -227,7 +227,7 @@ func updateAdminProfile(w http.ResponseWriter, r *http.Request) {
admin.Email = req.Email admin.Email = req.Email
admin.Description = req.Description admin.Description = req.Description
admin.Filters.AllowAPIKeyAuth = req.AllowAPIKeyAuth admin.Filters.AllowAPIKeyAuth = req.AllowAPIKeyAuth
if err := dataprovider.UpdateAdmin(&admin, dataprovider.ActionExecutorSelf, util.GetIPFromRemoteAddress(r.RemoteAddr)); err != nil { if err := dataprovider.UpdateAdmin(&admin, dataprovider.ActionExecutorSelf, util.GetIPFromRemoteAddress(r.RemoteAddr), claims.Role); err != nil {
sendAPIResponse(w, r, err, "", getRespStatus(err)) sendAPIResponse(w, r, err, "", getRespStatus(err))
return return
} }
@ -309,7 +309,7 @@ func doChangeAdminPassword(r *http.Request, currentPassword, newPassword, confir
admin.Password = newPassword admin.Password = newPassword
return dataprovider.UpdateAdmin(&admin, dataprovider.ActionExecutorSelf, util.GetIPFromRemoteAddress(r.RemoteAddr)) return dataprovider.UpdateAdmin(&admin, dataprovider.ActionExecutorSelf, util.GetIPFromRemoteAddress(r.RemoteAddr), claims.Role)
} }
func getTokenClaims(r *http.Request) (jwtTokenClaims, error) { func getTokenClaims(r *http.Request) (jwtTokenClaims, error) {

View file

@ -74,7 +74,7 @@ func addEventAction(w http.ResponseWriter, r *http.Request) {
sendAPIResponse(w, r, err, "", http.StatusBadRequest) sendAPIResponse(w, r, err, "", http.StatusBadRequest)
return return
} }
err = dataprovider.AddEventAction(&action, claims.Username, util.GetIPFromRemoteAddress(r.RemoteAddr)) err = dataprovider.AddEventAction(&action, claims.Username, util.GetIPFromRemoteAddress(r.RemoteAddr), claims.Role)
if err != nil { if err != nil {
sendAPIResponse(w, r, err, "", getRespStatus(err)) sendAPIResponse(w, r, err, "", getRespStatus(err))
return return
@ -116,7 +116,7 @@ func updateEventAction(w http.ResponseWriter, r *http.Request) {
} }
} }
err = dataprovider.UpdateEventAction(&action, claims.Username, util.GetIPFromRemoteAddress(r.RemoteAddr)) err = dataprovider.UpdateEventAction(&action, claims.Username, util.GetIPFromRemoteAddress(r.RemoteAddr), claims.Role)
if err != nil { if err != nil {
sendAPIResponse(w, r, err, "", getRespStatus(err)) sendAPIResponse(w, r, err, "", getRespStatus(err))
return return
@ -132,7 +132,7 @@ func deleteEventAction(w http.ResponseWriter, r *http.Request) {
return return
} }
name := getURLParam(r, "name") name := getURLParam(r, "name")
err = dataprovider.DeleteEventAction(name, claims.Username, util.GetIPFromRemoteAddress(r.RemoteAddr)) err = dataprovider.DeleteEventAction(name, claims.Username, util.GetIPFromRemoteAddress(r.RemoteAddr), claims.Role)
if err != nil { if err != nil {
sendAPIResponse(w, r, err, "", getRespStatus(err)) sendAPIResponse(w, r, err, "", getRespStatus(err))
return return
@ -190,7 +190,7 @@ func addEventRule(w http.ResponseWriter, r *http.Request) {
sendAPIResponse(w, r, err, "", http.StatusBadRequest) sendAPIResponse(w, r, err, "", http.StatusBadRequest)
return return
} }
err = dataprovider.AddEventRule(&rule, claims.Username, util.GetIPFromRemoteAddress(r.RemoteAddr)) err = dataprovider.AddEventRule(&rule, claims.Username, util.GetIPFromRemoteAddress(r.RemoteAddr), claims.Role)
if err != nil { if err != nil {
sendAPIResponse(w, r, err, "", getRespStatus(err)) sendAPIResponse(w, r, err, "", getRespStatus(err))
return return
@ -224,7 +224,7 @@ func updateEventRule(w http.ResponseWriter, r *http.Request) {
rule.ID = ruleID rule.ID = ruleID
rule.Name = name rule.Name = name
err = dataprovider.UpdateEventRule(&rule, claims.Username, util.GetIPFromRemoteAddress(r.RemoteAddr)) err = dataprovider.UpdateEventRule(&rule, claims.Username, util.GetIPFromRemoteAddress(r.RemoteAddr), claims.Role)
if err != nil { if err != nil {
sendAPIResponse(w, r, err, "", getRespStatus(err)) sendAPIResponse(w, r, err, "", getRespStatus(err))
return return
@ -240,7 +240,7 @@ func deleteEventRule(w http.ResponseWriter, r *http.Request) {
return return
} }
name := getURLParam(r, "name") name := getURLParam(r, "name")
err = dataprovider.DeleteEventRule(name, claims.Username, util.GetIPFromRemoteAddress(r.RemoteAddr)) err = dataprovider.DeleteEventRule(name, claims.Username, util.GetIPFromRemoteAddress(r.RemoteAddr), claims.Role)
if err != nil { if err != nil {
sendAPIResponse(w, r, err, "", getRespStatus(err)) sendAPIResponse(w, r, err, "", getRespStatus(err))
return return

View file

@ -119,12 +119,18 @@ func getProviderSearchParamsFromRequest(r *http.Request) (eventsearcher.Provider
func searchFsEvents(w http.ResponseWriter, r *http.Request) { func searchFsEvents(w http.ResponseWriter, r *http.Request) {
r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize) r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
claims, err := getTokenClaims(r)
if err != nil || claims.Username == "" {
sendAPIResponse(w, r, err, "Invalid token claims", http.StatusBadRequest)
return
}
filters, err := getFsSearchParamsFromRequest(r) filters, err := getFsSearchParamsFromRequest(r)
if err != nil { if err != nil {
sendAPIResponse(w, r, err, "", getRespStatus(err)) sendAPIResponse(w, r, err, "", getRespStatus(err))
return return
} }
filters.Role = getRoleFilterForEventSearch(r, claims.Role)
data, _, _, err := plugin.Handler.SearchFsEvents(&filters) data, _, _, err := plugin.Handler.SearchFsEvents(&filters)
if err != nil { if err != nil {
@ -138,12 +144,18 @@ func searchFsEvents(w http.ResponseWriter, r *http.Request) {
func searchProviderEvents(w http.ResponseWriter, r *http.Request) { func searchProviderEvents(w http.ResponseWriter, r *http.Request) {
r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize) r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
claims, err := getTokenClaims(r)
if err != nil || claims.Username == "" {
sendAPIResponse(w, r, err, "Invalid token claims", http.StatusBadRequest)
return
}
filters, err := getProviderSearchParamsFromRequest(r) filters, err := getProviderSearchParamsFromRequest(r)
if err != nil { if err != nil {
sendAPIResponse(w, r, err, "", getRespStatus(err)) sendAPIResponse(w, r, err, "", getRespStatus(err))
return return
} }
filters.Role = getRoleFilterForEventSearch(r, claims.Role)
data, _, _, err := plugin.Handler.SearchProviderEvents(&filters) data, _, _, err := plugin.Handler.SearchProviderEvents(&filters)
if err != nil { if err != nil {
@ -154,3 +166,10 @@ func searchProviderEvents(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json; charset=utf-8") w.Header().Set("Content-Type", "application/json; charset=utf-8")
w.Write(data) //nolint:errcheck w.Write(data) //nolint:errcheck
} }
func getRoleFilterForEventSearch(r *http.Request, defaultValue string) string {
if defaultValue != "" {
return defaultValue
}
return r.URL.Query().Get("role")
}

View file

@ -54,7 +54,7 @@ func addFolder(w http.ResponseWriter, r *http.Request) {
sendAPIResponse(w, r, err, "", http.StatusBadRequest) sendAPIResponse(w, r, err, "", http.StatusBadRequest)
return return
} }
err = dataprovider.AddFolder(&folder, claims.Username, util.GetIPFromRemoteAddress(r.RemoteAddr)) err = dataprovider.AddFolder(&folder, claims.Username, util.GetIPFromRemoteAddress(r.RemoteAddr), claims.Role)
if err != nil { if err != nil {
sendAPIResponse(w, r, err, "", getRespStatus(err)) sendAPIResponse(w, r, err, "", getRespStatus(err))
return return
@ -108,7 +108,7 @@ func updateFolder(w http.ResponseWriter, r *http.Request) {
updateEncryptedSecrets(&folder.FsConfig, currentS3AccessSecret, currentAzAccountKey, currentAzSASUrl, currentGCSCredentials, updateEncryptedSecrets(&folder.FsConfig, currentS3AccessSecret, currentAzAccountKey, currentAzSASUrl, currentGCSCredentials,
currentCryptoPassphrase, currentSFTPPassword, currentSFTPKey, currentSFTPKeyPassphrase, currentHTTPPassword, currentCryptoPassphrase, currentSFTPPassword, currentSFTPKey, currentSFTPKeyPassphrase, currentHTTPPassword,
currentHTTPAPIKey) currentHTTPAPIKey)
err = dataprovider.UpdateFolder(&folder, users, groups, claims.Username, util.GetIPFromRemoteAddress(r.RemoteAddr)) err = dataprovider.UpdateFolder(&folder, users, groups, claims.Username, util.GetIPFromRemoteAddress(r.RemoteAddr), claims.Role)
if err != nil { if err != nil {
sendAPIResponse(w, r, err, "", getRespStatus(err)) sendAPIResponse(w, r, err, "", getRespStatus(err))
return return
@ -145,7 +145,7 @@ func deleteFolder(w http.ResponseWriter, r *http.Request) {
return return
} }
name := getURLParam(r, "name") name := getURLParam(r, "name")
err = dataprovider.DeleteFolder(name, claims.Username, util.GetIPFromRemoteAddress(r.RemoteAddr)) err = dataprovider.DeleteFolder(name, claims.Username, util.GetIPFromRemoteAddress(r.RemoteAddr), claims.Role)
if err != nil { if err != nil {
sendAPIResponse(w, r, err, "", getRespStatus(err)) sendAPIResponse(w, r, err, "", getRespStatus(err))
return return

View file

@ -54,7 +54,7 @@ func addGroup(w http.ResponseWriter, r *http.Request) {
sendAPIResponse(w, r, err, "", http.StatusBadRequest) sendAPIResponse(w, r, err, "", http.StatusBadRequest)
return return
} }
err = dataprovider.AddGroup(&group, claims.Username, util.GetIPFromRemoteAddress(r.RemoteAddr)) err = dataprovider.AddGroup(&group, claims.Username, util.GetIPFromRemoteAddress(r.RemoteAddr), claims.Role)
if err != nil { if err != nil {
sendAPIResponse(w, r, err, "", getRespStatus(err)) sendAPIResponse(w, r, err, "", getRespStatus(err))
return return
@ -107,7 +107,7 @@ func updateGroup(w http.ResponseWriter, r *http.Request) {
updateEncryptedSecrets(&group.UserSettings.FsConfig, currentS3AccessSecret, currentAzAccountKey, currentAzSASUrl, updateEncryptedSecrets(&group.UserSettings.FsConfig, currentS3AccessSecret, currentAzAccountKey, currentAzSASUrl,
currentGCSCredentials, currentCryptoPassphrase, currentSFTPPassword, currentSFTPKey, currentSFTPKeyPassphrase, currentGCSCredentials, currentCryptoPassphrase, currentSFTPPassword, currentSFTPKey, currentSFTPKeyPassphrase,
currentHTTPPassword, currentHTTPAPIKey) currentHTTPPassword, currentHTTPAPIKey)
err = dataprovider.UpdateGroup(&group, users, claims.Username, util.GetIPFromRemoteAddress(r.RemoteAddr)) err = dataprovider.UpdateGroup(&group, users, claims.Username, util.GetIPFromRemoteAddress(r.RemoteAddr), claims.Role)
if err != nil { if err != nil {
sendAPIResponse(w, r, err, "", getRespStatus(err)) sendAPIResponse(w, r, err, "", getRespStatus(err))
return return
@ -144,7 +144,7 @@ func deleteGroup(w http.ResponseWriter, r *http.Request) {
return return
} }
name := getURLParam(r, "name") name := getURLParam(r, "name")
err = dataprovider.DeleteGroup(name, claims.Username, util.GetIPFromRemoteAddress(r.RemoteAddr)) err = dataprovider.DeleteGroup(name, claims.Username, util.GetIPFromRemoteAddress(r.RemoteAddr), claims.Role)
if err != nil { if err != nil {
sendAPIResponse(w, r, err, "", getRespStatus(err)) sendAPIResponse(w, r, err, "", getRespStatus(err))
return return

View file

@ -453,7 +453,7 @@ func updateUserProfile(w http.ResponseWriter, r *http.Request) {
user.Email = req.Email user.Email = req.Email
user.Description = req.Description user.Description = req.Description
} }
if err := dataprovider.UpdateUser(&user, dataprovider.ActionExecutorSelf, util.GetIPFromRemoteAddress(r.RemoteAddr)); err != nil { if err := dataprovider.UpdateUser(&user, dataprovider.ActionExecutorSelf, util.GetIPFromRemoteAddress(r.RemoteAddr), user.Role); err != nil {
sendAPIResponse(w, r, err, "", getRespStatus(err)) sendAPIResponse(w, r, err, "", getRespStatus(err))
return return
} }
@ -498,7 +498,7 @@ func doChangeUserPassword(r *http.Request, currentPassword, newPassword, confirm
} }
return dataprovider.UpdateUserPassword(claims.Username, newPassword, dataprovider.ActionExecutorSelf, return dataprovider.UpdateUserPassword(claims.Username, newPassword, dataprovider.ActionExecutorSelf,
util.GetIPFromRemoteAddress(r.RemoteAddr)) util.GetIPFromRemoteAddress(r.RemoteAddr), claims.Role)
} }
func setModificationTimeFromHeader(r *http.Request, c *Connection, filePath string) { func setModificationTimeFromHeader(r *http.Request, c *Connection, filePath string) {

View file

@ -70,7 +70,7 @@ func addAPIKey(w http.ResponseWriter, r *http.Request) {
apiKey.KeyID = "" apiKey.KeyID = ""
apiKey.Key = "" apiKey.Key = ""
apiKey.LastUseAt = 0 apiKey.LastUseAt = 0
err = dataprovider.AddAPIKey(&apiKey, claims.Username, util.GetIPFromRemoteAddress(r.RemoteAddr)) err = dataprovider.AddAPIKey(&apiKey, claims.Username, util.GetIPFromRemoteAddress(r.RemoteAddr), claims.Role)
if err != nil { if err != nil {
sendAPIResponse(w, r, err, "", getRespStatus(err)) sendAPIResponse(w, r, err, "", getRespStatus(err))
return return
@ -105,7 +105,7 @@ func updateAPIKey(w http.ResponseWriter, r *http.Request) {
} }
apiKey.KeyID = keyID apiKey.KeyID = keyID
if err := dataprovider.UpdateAPIKey(&apiKey, claims.Username, util.GetIPFromRemoteAddress(r.RemoteAddr)); err != nil { if err := dataprovider.UpdateAPIKey(&apiKey, claims.Username, util.GetIPFromRemoteAddress(r.RemoteAddr), claims.Role); err != nil {
sendAPIResponse(w, r, err, "", getRespStatus(err)) sendAPIResponse(w, r, err, "", getRespStatus(err))
return return
} }
@ -121,7 +121,7 @@ func deleteAPIKey(w http.ResponseWriter, r *http.Request) {
return return
} }
err = dataprovider.DeleteAPIKey(keyID, claims.Username, util.GetIPFromRemoteAddress(r.RemoteAddr)) err = dataprovider.DeleteAPIKey(keyID, claims.Username, util.GetIPFromRemoteAddress(r.RemoteAddr), claims.Role)
if err != nil { if err != nil {
sendAPIResponse(w, r, err, "", getRespStatus(err)) sendAPIResponse(w, r, err, "", getRespStatus(err))
return return

View file

@ -130,7 +130,7 @@ func loadDataFromRequest(w http.ResponseWriter, r *http.Request) {
sendAPIResponse(w, r, err, "", getRespStatus(err)) sendAPIResponse(w, r, err, "", getRespStatus(err))
return return
} }
if err := restoreBackup(content, "", scanQuota, mode, claims.Username, util.GetIPFromRemoteAddress(r.RemoteAddr)); err != nil { if err := restoreBackup(content, "", scanQuota, mode, claims.Username, util.GetIPFromRemoteAddress(r.RemoteAddr), claims.Role); err != nil {
sendAPIResponse(w, r, err, "", getRespStatus(err)) sendAPIResponse(w, r, err, "", getRespStatus(err))
} }
sendAPIResponse(w, r, err, "Data restored", http.StatusOK) sendAPIResponse(w, r, err, "Data restored", http.StatusOK)
@ -168,51 +168,51 @@ func loadData(w http.ResponseWriter, r *http.Request) {
sendAPIResponse(w, r, err, "", getRespStatus(err)) sendAPIResponse(w, r, err, "", getRespStatus(err))
return return
} }
if err := restoreBackup(content, inputFile, scanQuota, mode, claims.Username, util.GetIPFromRemoteAddress(r.RemoteAddr)); err != nil { if err := restoreBackup(content, inputFile, scanQuota, mode, claims.Username, util.GetIPFromRemoteAddress(r.RemoteAddr), claims.Role); err != nil {
sendAPIResponse(w, r, err, "", getRespStatus(err)) sendAPIResponse(w, r, err, "", getRespStatus(err))
} }
sendAPIResponse(w, r, err, "Data restored", http.StatusOK) sendAPIResponse(w, r, err, "Data restored", http.StatusOK)
} }
func restoreBackup(content []byte, inputFile string, scanQuota, mode int, executor, ipAddress string) error { func restoreBackup(content []byte, inputFile string, scanQuota, mode int, executor, ipAddress, role string) error {
dump, err := dataprovider.ParseDumpData(content) dump, err := dataprovider.ParseDumpData(content)
if err != nil { if err != nil {
return util.NewValidationError(fmt.Sprintf("unable to parse backup content: %v", err)) return util.NewValidationError(fmt.Sprintf("unable to parse backup content: %v", err))
} }
if err = RestoreRoles(dump.Roles, inputFile, mode, executor, ipAddress); err != nil { if err = RestoreRoles(dump.Roles, inputFile, mode, executor, ipAddress, role); err != nil {
return err return err
} }
if err = RestoreFolders(dump.Folders, inputFile, mode, scanQuota, executor, ipAddress); err != nil { if err = RestoreFolders(dump.Folders, inputFile, mode, scanQuota, executor, ipAddress, role); err != nil {
return err return err
} }
if err = RestoreGroups(dump.Groups, inputFile, mode, executor, ipAddress); err != nil { if err = RestoreGroups(dump.Groups, inputFile, mode, executor, ipAddress, role); err != nil {
return err return err
} }
if err = RestoreUsers(dump.Users, inputFile, mode, scanQuota, executor, ipAddress); err != nil { if err = RestoreUsers(dump.Users, inputFile, mode, scanQuota, executor, ipAddress, role); err != nil {
return err return err
} }
if err = RestoreAdmins(dump.Admins, inputFile, mode, executor, ipAddress); err != nil { if err = RestoreAdmins(dump.Admins, inputFile, mode, executor, ipAddress, role); err != nil {
return err return err
} }
if err = RestoreAPIKeys(dump.APIKeys, inputFile, mode, executor, ipAddress); err != nil { if err = RestoreAPIKeys(dump.APIKeys, inputFile, mode, executor, ipAddress, role); err != nil {
return err return err
} }
if err = RestoreShares(dump.Shares, inputFile, mode, executor, ipAddress); err != nil { if err = RestoreShares(dump.Shares, inputFile, mode, executor, ipAddress, role); err != nil {
return err return err
} }
if err = RestoreEventActions(dump.EventActions, inputFile, mode, executor, ipAddress); err != nil { if err = RestoreEventActions(dump.EventActions, inputFile, mode, executor, ipAddress, role); err != nil {
return err return err
} }
if err = RestoreEventRules(dump.EventRules, inputFile, mode, executor, ipAddress); err != nil { if err = RestoreEventRules(dump.EventRules, inputFile, mode, executor, ipAddress, role); err != nil {
return err return err
} }
@ -248,7 +248,7 @@ func getLoaddataOptions(r *http.Request) (string, int, int, error) {
} }
// RestoreFolders restores the specified folders // RestoreFolders restores the specified folders
func RestoreFolders(folders []vfs.BaseVirtualFolder, inputFile string, mode, scanQuota int, executor, ipAddress string) error { func RestoreFolders(folders []vfs.BaseVirtualFolder, inputFile string, mode, scanQuota int, executor, ipAddress, role string) error {
for _, folder := range folders { for _, folder := range folders {
folder := folder // pin folder := folder // pin
f, err := dataprovider.GetFolderByName(folder.Name) f, err := dataprovider.GetFolderByName(folder.Name)
@ -259,11 +259,11 @@ func RestoreFolders(folders []vfs.BaseVirtualFolder, inputFile string, mode, sca
} }
folder.ID = f.ID folder.ID = f.ID
folder.Name = f.Name folder.Name = f.Name
err = dataprovider.UpdateFolder(&folder, f.Users, f.Groups, executor, ipAddress) err = dataprovider.UpdateFolder(&folder, f.Users, f.Groups, executor, ipAddress, role)
logger.Debug(logSender, "", "restoring existing folder %#v, dump file: %#v, error: %v", folder.Name, inputFile, err) logger.Debug(logSender, "", "restoring existing folder %#v, dump file: %#v, error: %v", folder.Name, inputFile, err)
} else { } else {
folder.Users = nil folder.Users = nil
err = dataprovider.AddFolder(&folder, executor, ipAddress) err = dataprovider.AddFolder(&folder, executor, ipAddress, role)
logger.Debug(logSender, "", "adding new folder %#v, dump file: %#v, error: %v", folder.Name, inputFile, err) logger.Debug(logSender, "", "adding new folder %#v, dump file: %#v, error: %v", folder.Name, inputFile, err)
} }
if err != nil { if err != nil {
@ -281,7 +281,7 @@ func RestoreFolders(folders []vfs.BaseVirtualFolder, inputFile string, mode, sca
// RestoreShares restores the specified shares // RestoreShares restores the specified shares
func RestoreShares(shares []dataprovider.Share, inputFile string, mode int, executor, func RestoreShares(shares []dataprovider.Share, inputFile string, mode int, executor,
ipAddress string, ipAddress, role string,
) error { ) error {
for _, share := range shares { for _, share := range shares {
share := share // pin share := share // pin
@ -293,10 +293,10 @@ func RestoreShares(shares []dataprovider.Share, inputFile string, mode int, exec
continue continue
} }
share.ID = s.ID share.ID = s.ID
err = dataprovider.UpdateShare(&share, executor, ipAddress) err = dataprovider.UpdateShare(&share, executor, ipAddress, role)
logger.Debug(logSender, "", "restoring existing share %#v, dump file: %#v, error: %v", share.ShareID, inputFile, err) logger.Debug(logSender, "", "restoring existing share %#v, dump file: %#v, error: %v", share.ShareID, inputFile, err)
} else { } else {
err = dataprovider.AddShare(&share, executor, ipAddress) err = dataprovider.AddShare(&share, executor, ipAddress, role)
logger.Debug(logSender, "", "adding new share %#v, dump file: %#v, error: %v", share.ShareID, inputFile, err) logger.Debug(logSender, "", "adding new share %#v, dump file: %#v, error: %v", share.ShareID, inputFile, err)
} }
if err != nil { if err != nil {
@ -307,7 +307,7 @@ func RestoreShares(shares []dataprovider.Share, inputFile string, mode int, exec
} }
// RestoreEventActions restores the specified event actions // RestoreEventActions restores the specified event actions
func RestoreEventActions(actions []dataprovider.BaseEventAction, inputFile string, mode int, executor, ipAddress string) error { func RestoreEventActions(actions []dataprovider.BaseEventAction, inputFile string, mode int, executor, ipAddress, role string) error {
for _, action := range actions { for _, action := range actions {
action := action // pin action := action // pin
a, err := dataprovider.EventActionExists(action.Name) a, err := dataprovider.EventActionExists(action.Name)
@ -317,10 +317,10 @@ func RestoreEventActions(actions []dataprovider.BaseEventAction, inputFile strin
continue continue
} }
action.ID = a.ID action.ID = a.ID
err = dataprovider.UpdateEventAction(&action, executor, ipAddress) err = dataprovider.UpdateEventAction(&action, executor, ipAddress, role)
logger.Debug(logSender, "", "restoring event action %q, dump file: %q, error: %v", action.Name, inputFile, err) logger.Debug(logSender, "", "restoring event action %q, dump file: %q, error: %v", action.Name, inputFile, err)
} else { } else {
err = dataprovider.AddEventAction(&action, executor, ipAddress) err = dataprovider.AddEventAction(&action, executor, ipAddress, role)
logger.Debug(logSender, "", "adding new event action %q, dump file: %q, error: %v", action.Name, inputFile, err) logger.Debug(logSender, "", "adding new event action %q, dump file: %q, error: %v", action.Name, inputFile, err)
} }
if err != nil { if err != nil {
@ -331,7 +331,7 @@ func RestoreEventActions(actions []dataprovider.BaseEventAction, inputFile strin
} }
// RestoreEventRules restores the specified event rules // RestoreEventRules restores the specified event rules
func RestoreEventRules(rules []dataprovider.EventRule, inputFile string, mode int, executor, ipAddress string) error { func RestoreEventRules(rules []dataprovider.EventRule, inputFile string, mode int, executor, ipAddress, role string) error {
for _, rule := range rules { for _, rule := range rules {
rule := rule // pin rule := rule // pin
r, err := dataprovider.EventRuleExists(rule.Name) r, err := dataprovider.EventRuleExists(rule.Name)
@ -341,10 +341,10 @@ func RestoreEventRules(rules []dataprovider.EventRule, inputFile string, mode in
continue continue
} }
rule.ID = r.ID rule.ID = r.ID
err = dataprovider.UpdateEventRule(&rule, executor, ipAddress) err = dataprovider.UpdateEventRule(&rule, executor, ipAddress, role)
logger.Debug(logSender, "", "restoring event rule %q, dump file: %q, error: %v", rule.Name, inputFile, err) logger.Debug(logSender, "", "restoring event rule %q, dump file: %q, error: %v", rule.Name, inputFile, err)
} else { } else {
err = dataprovider.AddEventRule(&rule, executor, ipAddress) err = dataprovider.AddEventRule(&rule, executor, ipAddress, role)
logger.Debug(logSender, "", "adding new event rule %q, dump file: %q, error: %v", rule.Name, inputFile, err) logger.Debug(logSender, "", "adding new event rule %q, dump file: %q, error: %v", rule.Name, inputFile, err)
} }
if err != nil { if err != nil {
@ -355,7 +355,7 @@ func RestoreEventRules(rules []dataprovider.EventRule, inputFile string, mode in
} }
// RestoreAPIKeys restores the specified API keys // RestoreAPIKeys restores the specified API keys
func RestoreAPIKeys(apiKeys []dataprovider.APIKey, inputFile string, mode int, executor, ipAddress string) error { func RestoreAPIKeys(apiKeys []dataprovider.APIKey, inputFile string, mode int, executor, ipAddress, role string) error {
for _, apiKey := range apiKeys { for _, apiKey := range apiKeys {
apiKey := apiKey // pin apiKey := apiKey // pin
if apiKey.Key == "" { if apiKey.Key == "" {
@ -369,10 +369,10 @@ func RestoreAPIKeys(apiKeys []dataprovider.APIKey, inputFile string, mode int, e
continue continue
} }
apiKey.ID = k.ID apiKey.ID = k.ID
err = dataprovider.UpdateAPIKey(&apiKey, executor, ipAddress) err = dataprovider.UpdateAPIKey(&apiKey, executor, ipAddress, role)
logger.Debug(logSender, "", "restoring existing API key %#v, dump file: %#v, error: %v", apiKey.KeyID, inputFile, err) logger.Debug(logSender, "", "restoring existing API key %#v, dump file: %#v, error: %v", apiKey.KeyID, inputFile, err)
} else { } else {
err = dataprovider.AddAPIKey(&apiKey, executor, ipAddress) err = dataprovider.AddAPIKey(&apiKey, executor, ipAddress, role)
logger.Debug(logSender, "", "adding new API key %#v, dump file: %#v, error: %v", apiKey.KeyID, inputFile, err) logger.Debug(logSender, "", "adding new API key %#v, dump file: %#v, error: %v", apiKey.KeyID, inputFile, err)
} }
if err != nil { if err != nil {
@ -383,7 +383,7 @@ func RestoreAPIKeys(apiKeys []dataprovider.APIKey, inputFile string, mode int, e
} }
// RestoreAdmins restores the specified admins // RestoreAdmins restores the specified admins
func RestoreAdmins(admins []dataprovider.Admin, inputFile string, mode int, executor, ipAddress string) error { func RestoreAdmins(admins []dataprovider.Admin, inputFile string, mode int, executor, ipAddress, role string) error {
for _, admin := range admins { for _, admin := range admins {
admin := admin // pin admin := admin // pin
a, err := dataprovider.AdminExists(admin.Username) a, err := dataprovider.AdminExists(admin.Username)
@ -394,10 +394,10 @@ func RestoreAdmins(admins []dataprovider.Admin, inputFile string, mode int, exec
} }
admin.ID = a.ID admin.ID = a.ID
admin.Username = a.Username admin.Username = a.Username
err = dataprovider.UpdateAdmin(&admin, executor, ipAddress) err = dataprovider.UpdateAdmin(&admin, executor, ipAddress, role)
logger.Debug(logSender, "", "restoring existing admin %#v, dump file: %#v, error: %v", admin.Username, inputFile, err) logger.Debug(logSender, "", "restoring existing admin %#v, dump file: %#v, error: %v", admin.Username, inputFile, err)
} else { } else {
err = dataprovider.AddAdmin(&admin, executor, ipAddress) err = dataprovider.AddAdmin(&admin, executor, ipAddress, role)
logger.Debug(logSender, "", "adding new admin %#v, dump file: %#v, error: %v", admin.Username, inputFile, err) logger.Debug(logSender, "", "adding new admin %#v, dump file: %#v, error: %v", admin.Username, inputFile, err)
} }
if err != nil { if err != nil {
@ -409,7 +409,7 @@ func RestoreAdmins(admins []dataprovider.Admin, inputFile string, mode int, exec
} }
// RestoreRoles restores the specified roles // RestoreRoles restores the specified roles
func RestoreRoles(roles []dataprovider.Role, inputFile string, mode int, executor, ipAddress string) error { func RestoreRoles(roles []dataprovider.Role, inputFile string, mode int, executor, ipAddress, executorRole string) error {
for _, role := range roles { for _, role := range roles {
role := role // pin role := role // pin
r, err := dataprovider.RoleExists(role.Name) r, err := dataprovider.RoleExists(role.Name)
@ -419,10 +419,10 @@ func RestoreRoles(roles []dataprovider.Role, inputFile string, mode int, executo
continue continue
} }
role.ID = r.ID role.ID = r.ID
err = dataprovider.UpdateRole(&role, executor, ipAddress) err = dataprovider.UpdateRole(&role, executor, ipAddress, executorRole)
logger.Debug(logSender, "", "restoring existing role: %q, dump file: %#v, error: %v", role.Name, inputFile, err) logger.Debug(logSender, "", "restoring existing role: %q, dump file: %#v, error: %v", role.Name, inputFile, err)
} else { } else {
err = dataprovider.AddRole(&role, executor, ipAddress) err = dataprovider.AddRole(&role, executor, ipAddress, executorRole)
logger.Debug(logSender, "", "adding new role: %q, dump file: %q, error: %v", role.Name, inputFile, err) logger.Debug(logSender, "", "adding new role: %q, dump file: %q, error: %v", role.Name, inputFile, err)
} }
if err != nil { if err != nil {
@ -433,7 +433,7 @@ func RestoreRoles(roles []dataprovider.Role, inputFile string, mode int, executo
} }
// RestoreGroups restores the specified groups // RestoreGroups restores the specified groups
func RestoreGroups(groups []dataprovider.Group, inputFile string, mode int, executor, ipAddress string) error { func RestoreGroups(groups []dataprovider.Group, inputFile string, mode int, executor, ipAddress, role string) error {
for _, group := range groups { for _, group := range groups {
group := group // pin group := group // pin
g, err := dataprovider.GroupExists(group.Name) g, err := dataprovider.GroupExists(group.Name)
@ -444,10 +444,10 @@ func RestoreGroups(groups []dataprovider.Group, inputFile string, mode int, exec
} }
group.ID = g.ID group.ID = g.ID
group.Name = g.Name group.Name = g.Name
err = dataprovider.UpdateGroup(&group, g.Users, executor, ipAddress) err = dataprovider.UpdateGroup(&group, g.Users, executor, ipAddress, role)
logger.Debug(logSender, "", "restoring existing group: %#v, dump file: %#v, error: %v", group.Name, inputFile, err) logger.Debug(logSender, "", "restoring existing group: %#v, dump file: %#v, error: %v", group.Name, inputFile, err)
} else { } else {
err = dataprovider.AddGroup(&group, executor, ipAddress) err = dataprovider.AddGroup(&group, executor, ipAddress, role)
logger.Debug(logSender, "", "adding new group: %#v, dump file: %#v, error: %v", group.Name, inputFile, err) logger.Debug(logSender, "", "adding new group: %#v, dump file: %#v, error: %v", group.Name, inputFile, err)
} }
if err != nil { if err != nil {
@ -458,7 +458,7 @@ func RestoreGroups(groups []dataprovider.Group, inputFile string, mode int, exec
} }
// RestoreUsers restores the specified users // RestoreUsers restores the specified users
func RestoreUsers(users []dataprovider.User, inputFile string, mode, scanQuota int, executor, ipAddress string) error { func RestoreUsers(users []dataprovider.User, inputFile string, mode, scanQuota int, executor, ipAddress, role string) error {
for _, user := range users { for _, user := range users {
user := user // pin user := user // pin
u, err := dataprovider.UserExists(user.Username, "") u, err := dataprovider.UserExists(user.Username, "")
@ -469,13 +469,13 @@ func RestoreUsers(users []dataprovider.User, inputFile string, mode, scanQuota i
} }
user.ID = u.ID user.ID = u.ID
user.Username = u.Username user.Username = u.Username
err = dataprovider.UpdateUser(&user, executor, ipAddress) err = dataprovider.UpdateUser(&user, executor, ipAddress, role)
logger.Debug(logSender, "", "restoring existing user: %#v, dump file: %#v, error: %v", user.Username, inputFile, err) logger.Debug(logSender, "", "restoring existing user: %#v, dump file: %#v, error: %v", user.Username, inputFile, err)
if mode == 2 && err == nil { if mode == 2 && err == nil {
disconnectUser(user.Username) disconnectUser(user.Username)
} }
} else { } else {
err = dataprovider.AddUser(&user, executor, ipAddress) err = dataprovider.AddUser(&user, executor, ipAddress, role)
logger.Debug(logSender, "", "adding new user: %#v, dump file: %#v, error: %v", user.Username, inputFile, err) logger.Debug(logSender, "", "adding new user: %#v, dump file: %#v, error: %v", user.Username, inputFile, err)
} }
if err != nil { if err != nil {

View file

@ -213,7 +213,7 @@ func generateRecoveryCodes(w http.ResponseWriter, r *http.Request) {
return return
} }
user.Filters.RecoveryCodes = accountRecoveryCodes user.Filters.RecoveryCodes = accountRecoveryCodes
if err := dataprovider.UpdateUser(&user, dataprovider.ActionExecutorSelf, util.GetIPFromRemoteAddress(r.RemoteAddr)); err != nil { if err := dataprovider.UpdateUser(&user, dataprovider.ActionExecutorSelf, util.GetIPFromRemoteAddress(r.RemoteAddr), user.Role); err != nil {
sendAPIResponse(w, r, err, "", getRespStatus(err)) sendAPIResponse(w, r, err, "", getRespStatus(err))
return return
} }
@ -228,7 +228,7 @@ func generateRecoveryCodes(w http.ResponseWriter, r *http.Request) {
return return
} }
admin.Filters.RecoveryCodes = accountRecoveryCodes admin.Filters.RecoveryCodes = accountRecoveryCodes
if err := dataprovider.UpdateAdmin(&admin, dataprovider.ActionExecutorSelf, util.GetIPFromRemoteAddress(r.RemoteAddr)); err != nil { if err := dataprovider.UpdateAdmin(&admin, dataprovider.ActionExecutorSelf, util.GetIPFromRemoteAddress(r.RemoteAddr), admin.Role); err != nil {
sendAPIResponse(w, r, err, "", getRespStatus(err)) sendAPIResponse(w, r, err, "", getRespStatus(err))
return return
} }
@ -271,7 +271,7 @@ func saveUserTOTPConfig(username string, r *http.Request, recoveryCodes []datapr
} else { } else {
user.Filters.RecoveryCodes = nil user.Filters.RecoveryCodes = nil
} }
return dataprovider.UpdateUser(&user, dataprovider.ActionExecutorSelf, util.GetIPFromRemoteAddress(r.RemoteAddr)) return dataprovider.UpdateUser(&user, dataprovider.ActionExecutorSelf, util.GetIPFromRemoteAddress(r.RemoteAddr), user.Role)
} }
func saveAdminTOTPConfig(username string, r *http.Request, recoveryCodes []dataprovider.RecoveryCode) error { func saveAdminTOTPConfig(username string, r *http.Request, recoveryCodes []dataprovider.RecoveryCode) error {
@ -295,5 +295,5 @@ func saveAdminTOTPConfig(username string, r *http.Request, recoveryCodes []datap
if admin.Filters.TOTPConfig.Secret == nil || !admin.Filters.TOTPConfig.Secret.IsPlain() { if admin.Filters.TOTPConfig.Secret == nil || !admin.Filters.TOTPConfig.Secret.IsPlain() {
admin.Filters.TOTPConfig.Secret = currentTOTPSecret admin.Filters.TOTPConfig.Secret = currentTOTPSecret
} }
return dataprovider.UpdateAdmin(&admin, dataprovider.ActionExecutorSelf, util.GetIPFromRemoteAddress(r.RemoteAddr)) return dataprovider.UpdateAdmin(&admin, dataprovider.ActionExecutorSelf, util.GetIPFromRemoteAddress(r.RemoteAddr), admin.Role)
} }

View file

@ -53,7 +53,7 @@ func addRole(w http.ResponseWriter, r *http.Request) {
sendAPIResponse(w, r, err, "", http.StatusBadRequest) sendAPIResponse(w, r, err, "", http.StatusBadRequest)
return return
} }
err = dataprovider.AddRole(&role, claims.Username, util.GetIPFromRemoteAddress(r.RemoteAddr)) err = dataprovider.AddRole(&role, claims.Username, util.GetIPFromRemoteAddress(r.RemoteAddr), claims.Role)
if err != nil { if err != nil {
sendAPIResponse(w, r, err, "", getRespStatus(err)) sendAPIResponse(w, r, err, "", getRespStatus(err))
return return
@ -84,7 +84,7 @@ func updateRole(w http.ResponseWriter, r *http.Request) {
} }
role.ID = roleID role.ID = roleID
role.Name = name role.Name = name
err = dataprovider.UpdateRole(&role, claims.Username, util.GetIPFromRemoteAddress(r.RemoteAddr)) err = dataprovider.UpdateRole(&role, claims.Username, util.GetIPFromRemoteAddress(r.RemoteAddr), claims.Role)
if err != nil { if err != nil {
sendAPIResponse(w, r, err, "", getRespStatus(err)) sendAPIResponse(w, r, err, "", getRespStatus(err))
return return
@ -120,7 +120,7 @@ func deleteRole(w http.ResponseWriter, r *http.Request) {
return return
} }
name := getURLParam(r, "name") name := getURLParam(r, "name")
err = dataprovider.DeleteRole(name, claims.Username, util.GetIPFromRemoteAddress(r.RemoteAddr)) err = dataprovider.DeleteRole(name, claims.Username, util.GetIPFromRemoteAddress(r.RemoteAddr), claims.Role)
if err != nil { if err != nil {
sendAPIResponse(w, r, err, "", getRespStatus(err)) sendAPIResponse(w, r, err, "", getRespStatus(err))
return return

View file

@ -107,7 +107,7 @@ func addShare(w http.ResponseWriter, r *http.Request) {
return return
} }
} }
err = dataprovider.AddShare(&share, claims.Username, util.GetIPFromRemoteAddress(r.RemoteAddr)) err = dataprovider.AddShare(&share, claims.Username, util.GetIPFromRemoteAddress(r.RemoteAddr), claims.Role)
if err != nil { if err != nil {
sendAPIResponse(w, r, err, "", getRespStatus(err)) sendAPIResponse(w, r, err, "", getRespStatus(err))
return return
@ -150,7 +150,7 @@ func updateShare(w http.ResponseWriter, r *http.Request) {
return return
} }
} }
if err := dataprovider.UpdateShare(&share, claims.Username, util.GetIPFromRemoteAddress(r.RemoteAddr)); err != nil { if err := dataprovider.UpdateShare(&share, claims.Username, util.GetIPFromRemoteAddress(r.RemoteAddr), claims.Role); err != nil {
sendAPIResponse(w, r, err, "", getRespStatus(err)) sendAPIResponse(w, r, err, "", getRespStatus(err))
return return
} }
@ -166,7 +166,7 @@ func deleteShare(w http.ResponseWriter, r *http.Request) {
return return
} }
err = dataprovider.DeleteShare(shareID, claims.Username, util.GetIPFromRemoteAddress(r.RemoteAddr)) err = dataprovider.DeleteShare(shareID, claims.Username, util.GetIPFromRemoteAddress(r.RemoteAddr), claims.Role)
if err != nil { if err != nil {
sendAPIResponse(w, r, err, "", getRespStatus(err)) sendAPIResponse(w, r, err, "", getRespStatus(err))
return return

View file

@ -107,7 +107,7 @@ func addUser(w http.ResponseWriter, r *http.Request) {
user.Filters.TOTPConfig = dataprovider.UserTOTPConfig{ user.Filters.TOTPConfig = dataprovider.UserTOTPConfig{
Enabled: false, Enabled: false,
} }
err = dataprovider.AddUser(&user, claims.Username, util.GetIPFromRemoteAddress(r.RemoteAddr)) err = dataprovider.AddUser(&user, claims.Username, util.GetIPFromRemoteAddress(r.RemoteAddr), claims.Role)
if err != nil { if err != nil {
sendAPIResponse(w, r, err, "", getRespStatus(err)) sendAPIResponse(w, r, err, "", getRespStatus(err))
return return
@ -132,7 +132,7 @@ func disableUser2FA(w http.ResponseWriter, r *http.Request) {
user.Filters.TOTPConfig = dataprovider.UserTOTPConfig{ user.Filters.TOTPConfig = dataprovider.UserTOTPConfig{
Enabled: false, Enabled: false,
} }
if err := dataprovider.UpdateUser(&user, claims.Username, util.GetIPFromRemoteAddress(r.RemoteAddr)); err != nil { if err := dataprovider.UpdateUser(&user, claims.Username, util.GetIPFromRemoteAddress(r.RemoteAddr), claims.Role); err != nil {
sendAPIResponse(w, r, err, "", getRespStatus(err)) sendAPIResponse(w, r, err, "", getRespStatus(err))
return return
} }
@ -208,7 +208,7 @@ func updateUser(w http.ResponseWriter, r *http.Request) {
if claims.Role != "" { if claims.Role != "" {
user.Role = claims.Role user.Role = claims.Role
} }
err = dataprovider.UpdateUser(&user, claims.Username, util.GetIPFromRemoteAddress(r.RemoteAddr)) err = dataprovider.UpdateUser(&user, claims.Username, util.GetIPFromRemoteAddress(r.RemoteAddr), claims.Role)
if err != nil { if err != nil {
sendAPIResponse(w, r, err, "", getRespStatus(err)) sendAPIResponse(w, r, err, "", getRespStatus(err))
return return

View file

@ -712,7 +712,7 @@ func handleResetPassword(r *http.Request, code, newPassword string, isAdmin bool
return &admin, &user, util.NewValidationError("unable to associate the confirmation code with an existing admin") return &admin, &user, util.NewValidationError("unable to associate the confirmation code with an existing admin")
} }
admin.Password = newPassword admin.Password = newPassword
err = dataprovider.UpdateAdmin(&admin, dataprovider.ActionExecutorSelf, util.GetIPFromRemoteAddress(r.RemoteAddr)) err = dataprovider.UpdateAdmin(&admin, dataprovider.ActionExecutorSelf, util.GetIPFromRemoteAddress(r.RemoteAddr), admin.Role)
if err != nil { if err != nil {
return &admin, &user, util.NewGenericError(fmt.Sprintf("unable to set the new password: %v", err)) return &admin, &user, util.NewGenericError(fmt.Sprintf("unable to set the new password: %v", err))
} }
@ -729,7 +729,7 @@ func handleResetPassword(r *http.Request, code, newPassword string, isAdmin bool
} }
} }
err = dataprovider.UpdateUserPassword(user.Username, newPassword, dataprovider.ActionExecutorSelf, err = dataprovider.UpdateUserPassword(user.Username, newPassword, dataprovider.ActionExecutorSelf,
util.GetIPFromRemoteAddress(r.RemoteAddr)) util.GetIPFromRemoteAddress(r.RemoteAddr), user.Role)
if err == nil { if err == nil {
err = resetCodesMgr.Delete(code) err = resetCodesMgr.Delete(code)
} }

View file

@ -348,6 +348,7 @@ func getUserFromToken(r *http.Request) *dataprovider.User {
tokenClaims.Decode(claims) tokenClaims.Decode(claims)
user.Username = tokenClaims.Username user.Username = tokenClaims.Username
user.Filters.WebClient = tokenClaims.Permissions user.Filters.WebClient = tokenClaims.Permissions
user.Role = tokenClaims.Role
return user return user
} }

View file

@ -3065,7 +3065,7 @@ func TestChangeAdminPassword(t *testing.T) {
admin, err := dataprovider.AdminExists(defaultTokenAuthUser) admin, err := dataprovider.AdminExists(defaultTokenAuthUser)
assert.NoError(t, err) assert.NoError(t, err)
admin.Password = defaultTokenAuthPass admin.Password = defaultTokenAuthPass
err = dataprovider.UpdateAdmin(&admin, "", "") err = dataprovider.UpdateAdmin(&admin, "", "", "")
assert.NoError(t, err) assert.NoError(t, err)
} }
@ -3717,7 +3717,7 @@ func TestUserRedactedPassword(t *testing.T) {
_, resp, err := httpdtest.AddUser(u, http.StatusBadRequest) _, resp, err := httpdtest.AddUser(u, http.StatusBadRequest)
assert.NoError(t, err, string(resp)) assert.NoError(t, err, string(resp))
assert.Contains(t, string(resp), "cannot save a user with a redacted secret") assert.Contains(t, string(resp), "cannot save a user with a redacted secret")
err = dataprovider.AddUser(&u, "", "") err = dataprovider.AddUser(&u, "", "", "")
if assert.Error(t, err) { if assert.Error(t, err) {
assert.Contains(t, err.Error(), "cannot save a user with a redacted secret") assert.Contains(t, err.Error(), "cannot save a user with a redacted secret")
} }
@ -3742,7 +3742,7 @@ func TestUserRedactedPassword(t *testing.T) {
user.Password = defaultPassword user.Password = defaultPassword
user.VirtualFolders = append(user.VirtualFolders, vfolder) user.VirtualFolders = append(user.VirtualFolders, vfolder)
err = dataprovider.UpdateUser(&user, "", "") err = dataprovider.UpdateUser(&user, "", "", "")
if assert.Error(t, err) { if assert.Error(t, err) {
assert.Contains(t, err.Error(), "cannot save a user with a redacted secret") assert.Contains(t, err.Error(), "cannot save a user with a redacted secret")
} }
@ -5707,7 +5707,7 @@ func TestAdminGenerateRecoveryCodesSaveError(t *testing.T) {
Secret: kms.NewPlainSecret(secret), Secret: kms.NewPlainSecret(secret),
} }
admin.Password = defaultTokenAuthPass admin.Password = defaultTokenAuthPass
err = dataprovider.UpdateAdmin(&admin, "", "") err = dataprovider.UpdateAdmin(&admin, "", "", "")
assert.NoError(t, err) assert.NoError(t, err)
admin, _, err = httpdtest.GetAdminByUsername(a.Username, http.StatusOK) admin, _, err = httpdtest.GetAdminByUsername(a.Username, http.StatusOK)
assert.NoError(t, err) assert.NoError(t, err)
@ -5773,7 +5773,7 @@ func TestNamingRules(t *testing.T) {
Protocols: []string{common.ProtocolSSH}, Protocols: []string{common.ProtocolSSH},
} }
user.Password = u.Password user.Password = u.Password
err = dataprovider.UpdateUser(&user, "", "") err = dataprovider.UpdateUser(&user, "", "", "")
assert.NoError(t, err) assert.NoError(t, err)
user.Username = u.Username user.Username = u.Username
user.AdditionalInfo = "info" user.AdditionalInfo = "info"
@ -6012,7 +6012,7 @@ func TestSaveErrors(t *testing.T) {
Protocols: []string{common.ProtocolSSH, common.ProtocolHTTP}, Protocols: []string{common.ProtocolSSH, common.ProtocolHTTP},
} }
user.Filters.RecoveryCodes = recoveryCodes user.Filters.RecoveryCodes = recoveryCodes
err = dataprovider.UpdateUser(&user, "", "") err = dataprovider.UpdateUser(&user, "", "", "")
assert.NoError(t, err) assert.NoError(t, err)
user, _, err = httpdtest.GetUserByUsername(user.Username, http.StatusOK) user, _, err = httpdtest.GetUserByUsername(user.Username, http.StatusOK)
assert.NoError(t, err) assert.NoError(t, err)
@ -6033,7 +6033,7 @@ func TestSaveErrors(t *testing.T) {
Secret: kms.NewPlainSecret(secret), Secret: kms.NewPlainSecret(secret),
} }
admin.Filters.RecoveryCodes = recoveryCodes admin.Filters.RecoveryCodes = recoveryCodes
err = dataprovider.UpdateAdmin(&admin, "", "") err = dataprovider.UpdateAdmin(&admin, "", "", "")
assert.NoError(t, err) assert.NoError(t, err)
admin, _, err = httpdtest.GetAdminByUsername(admin.Username, http.StatusOK) admin, _, err = httpdtest.GetAdminByUsername(admin.Username, http.StatusOK)
assert.NoError(t, err) assert.NoError(t, err)
@ -7360,7 +7360,7 @@ func TestLoaddataMode(t *testing.T) {
apiKey, _, err = httpdtest.UpdateAPIKey(apiKey, http.StatusOK) apiKey, _, err = httpdtest.UpdateAPIKey(apiKey, http.StatusOK)
assert.NoError(t, err) assert.NoError(t, err)
share.Description = "test desc" share.Description = "test desc"
err = dataprovider.UpdateShare(&share, "", "") err = dataprovider.UpdateShare(&share, "", "", "")
assert.NoError(t, err) assert.NoError(t, err)
action, _, err = httpdtest.GetEventActionByName(action.Name, http.StatusOK) action, _, err = httpdtest.GetEventActionByName(action.Name, http.StatusOK)
@ -8785,11 +8785,20 @@ func TestSearchEvents(t *testing.T) {
if assert.Len(t, events, 1) { if assert.Len(t, events, 1) {
ev := events[0] ev := events[0]
for _, field := range []string{"id", "timestamp", "action", "username", "fs_path", "status", "protocol", for _, field := range []string{"id", "timestamp", "action", "username", "fs_path", "status", "protocol",
"ip", "session_id", "fs_provider", "bucket", "endpoint", "open_flags", "instance_id"} { "ip", "session_id", "fs_provider", "bucket", "endpoint", "open_flags", "role", "instance_id"} {
_, ok := ev[field] _, ok := ev[field]
assert.True(t, ok, field) assert.True(t, ok, field)
} }
} }
req, err = http.NewRequest(http.MethodGet, fsEventsPath+"?limit=10&order=ASC&role=role1", nil)
assert.NoError(t, err)
setBearerForReq(req, token)
rr = executeRequest(req)
checkResponseCode(t, http.StatusOK, rr)
events = nil
err = json.Unmarshal(rr.Body.Bytes(), &events)
assert.NoError(t, err)
assert.Len(t, events, 1)
// the test eventsearcher plugin returns error if start_timestamp < 0 // the test eventsearcher plugin returns error if start_timestamp < 0
req, err = http.NewRequest(http.MethodGet, fsEventsPath+"?start_timestamp=-1&end_timestamp=123456&statuses=1,2", nil) req, err = http.NewRequest(http.MethodGet, fsEventsPath+"?start_timestamp=-1&end_timestamp=123456&statuses=1,2", nil)
@ -8815,7 +8824,7 @@ func TestSearchEvents(t *testing.T) {
if assert.Len(t, events, 1) { if assert.Len(t, events, 1) {
ev := events[0] ev := events[0]
for _, field := range []string{"id", "timestamp", "action", "username", "object_type", "object_name", for _, field := range []string{"id", "timestamp", "action", "username", "object_type", "object_name",
"object_data", "instance_id"} { "object_data", "role", "instance_id"} {
_, ok := ev[field] _, ok := ev[field]
assert.True(t, ok, field) assert.True(t, ok, field)
} }
@ -9047,7 +9056,7 @@ func TestMFAInvalidSecret(t *testing.T) {
Used: false, Used: false,
Secret: kms.NewSecret(sdkkms.SecretStatusSecretBox, "payload", "key", user.Username), Secret: kms.NewSecret(sdkkms.SecretStatusSecretBox, "payload", "key", user.Username),
}) })
err = dataprovider.UpdateUser(&user, "", "") err = dataprovider.UpdateUser(&user, "", "", "")
assert.NoError(t, err) assert.NoError(t, err)
req, err := http.NewRequest(http.MethodGet, user2FARecoveryCodesPath, nil) req, err := http.NewRequest(http.MethodGet, user2FARecoveryCodesPath, nil)
@ -9122,7 +9131,7 @@ func TestMFAInvalidSecret(t *testing.T) {
Used: false, Used: false,
Secret: kms.NewSecret(sdkkms.SecretStatusSecretBox, "payload", "key", user.Username), Secret: kms.NewSecret(sdkkms.SecretStatusSecretBox, "payload", "key", user.Username),
}) })
err = dataprovider.UpdateAdmin(&admin, "", "") err = dataprovider.UpdateAdmin(&admin, "", "", "")
assert.NoError(t, err) assert.NoError(t, err)
csrfToken, err = getCSRFToken(httpBaseURL + webLoginPath) csrfToken, err = getCSRFToken(httpBaseURL + webLoginPath)
@ -10025,7 +10034,7 @@ func TestAdminHandlingWithAPIKeys(t *testing.T) {
dbAdmin, err := dataprovider.AdminExists(defaultTokenAuthUser) dbAdmin, err := dataprovider.AdminExists(defaultTokenAuthUser)
assert.NoError(t, err) assert.NoError(t, err)
dbAdmin.Filters.AllowAPIKeyAuth = false dbAdmin.Filters.AllowAPIKeyAuth = false
err = dataprovider.UpdateAdmin(&dbAdmin, "", "") err = dataprovider.UpdateAdmin(&dbAdmin, "", "", "")
assert.NoError(t, err) assert.NoError(t, err)
sysAdmin, _, err = httpdtest.GetAdminByUsername(defaultTokenAuthUser, http.StatusOK) sysAdmin, _, err = httpdtest.GetAdminByUsername(defaultTokenAuthUser, http.StatusOK)
assert.NoError(t, err) assert.NoError(t, err)
@ -11943,7 +11952,7 @@ func TestShareUsage(t *testing.T) {
checkResponseCode(t, http.StatusNotFound, rr) checkResponseCode(t, http.StatusNotFound, rr)
share.MaxTokens = 0 share.MaxTokens = 0
err = dataprovider.UpdateShare(&share, user.Username, "") err = dataprovider.UpdateShare(&share, user.Username, "", "")
assert.NoError(t, err) assert.NoError(t, err)
user.Permissions["/"] = []string{dataprovider.PermListItems, dataprovider.PermDownload} user.Permissions["/"] = []string{dataprovider.PermListItems, dataprovider.PermDownload}
@ -11997,7 +12006,7 @@ func TestShareUsage(t *testing.T) {
user, _, err = httpdtest.UpdateUser(user, http.StatusOK, "") user, _, err = httpdtest.UpdateUser(user, http.StatusOK, "")
assert.NoError(t, err) assert.NoError(t, err)
share.Password = "" share.Password = ""
err = dataprovider.UpdateShare(&share, user.Username, "") err = dataprovider.UpdateShare(&share, user.Username, "", "")
assert.NoError(t, err) assert.NoError(t, err)
req, err = http.NewRequest(http.MethodPost, sharesPath+"/"+objectID, reader) req, err = http.NewRequest(http.MethodPost, sharesPath+"/"+objectID, reader)
@ -12014,7 +12023,7 @@ func TestShareUsage(t *testing.T) {
share.Scope = dataprovider.ShareScopeRead share.Scope = dataprovider.ShareScopeRead
share.Paths = []string{"/missing1", "/missing2"} share.Paths = []string{"/missing1", "/missing2"}
err = dataprovider.UpdateShare(&share, user.Username, "") err = dataprovider.UpdateShare(&share, user.Username, "", "")
assert.NoError(t, err) assert.NoError(t, err)
defer func() { defer func() {
@ -15406,7 +15415,7 @@ func TestWebAdminSetupMock(t *testing.T) {
admins, err := dataprovider.GetAdmins(100, 0, dataprovider.OrderASC) admins, err := dataprovider.GetAdmins(100, 0, dataprovider.OrderASC)
assert.NoError(t, err) assert.NoError(t, err)
for _, admin := range admins { for _, admin := range admins {
err = dataprovider.DeleteAdmin(admin.Username, "", "") err = dataprovider.DeleteAdmin(admin.Username, "", "", "")
assert.NoError(t, err) assert.NoError(t, err)
} }
// close the provider and initializes it without creating the default admin // close the provider and initializes it without creating the default admin

View file

@ -746,6 +746,16 @@ func TestInvalidToken(t *testing.T) {
assert.Equal(t, http.StatusBadRequest, rr.Code) assert.Equal(t, http.StatusBadRequest, rr.Code)
assert.Contains(t, rr.Body.String(), "Invalid token claims") assert.Contains(t, rr.Body.String(), "Invalid token claims")
rr = httptest.NewRecorder()
searchFsEvents(rr, req)
assert.Equal(t, http.StatusBadRequest, rr.Code)
assert.Contains(t, rr.Body.String(), "Invalid token claims")
rr = httptest.NewRecorder()
searchProviderEvents(rr, req)
assert.Equal(t, http.StatusBadRequest, rr.Code)
assert.Contains(t, rr.Body.String(), "Invalid token claims")
rr = httptest.NewRecorder() rr = httptest.NewRecorder()
server.handleGetWebUsers(rr, req) server.handleGetWebUsers(rr, req)
assert.Equal(t, http.StatusBadRequest, rr.Code) assert.Equal(t, http.StatusBadRequest, rr.Code)
@ -863,7 +873,7 @@ func TestRetentionInvalidTokenClaims(t *testing.T) {
user.Permissions = make(map[string][]string) user.Permissions = make(map[string][]string)
user.Permissions["/"] = []string{dataprovider.PermAny} user.Permissions["/"] = []string{dataprovider.PermAny}
user.Filters.AllowAPIKeyAuth = true user.Filters.AllowAPIKeyAuth = true
err := dataprovider.AddUser(&user, "", "") err := dataprovider.AddUser(&user, "", "", "")
assert.NoError(t, err) assert.NoError(t, err)
folderRetention := []dataprovider.FolderRetention{ folderRetention := []dataprovider.FolderRetention{
{ {
@ -1144,7 +1154,7 @@ func TestCreateTokenError(t *testing.T) {
user.Permissions = make(map[string][]string) user.Permissions = make(map[string][]string)
user.Permissions["/"] = []string{dataprovider.PermAny} user.Permissions["/"] = []string{dataprovider.PermAny}
user.Filters.AllowAPIKeyAuth = true user.Filters.AllowAPIKeyAuth = true
err = dataprovider.AddUser(&user, "", "") err = dataprovider.AddUser(&user, "", "", "")
assert.NoError(t, err) assert.NoError(t, err)
rr = httptest.NewRecorder() rr = httptest.NewRecorder()
@ -1170,13 +1180,13 @@ func TestCreateTokenError(t *testing.T) {
admin.Status = 1 admin.Status = 1
admin.Filters.AllowAPIKeyAuth = true admin.Filters.AllowAPIKeyAuth = true
admin.Permissions = []string{dataprovider.PermAdminAny} admin.Permissions = []string{dataprovider.PermAdminAny}
err = dataprovider.AddAdmin(&admin, "", "") err = dataprovider.AddAdmin(&admin, "", "", "")
assert.NoError(t, err) assert.NoError(t, err)
err = authenticateAdminWithAPIKey(admin.Username, "", server.tokenAuth, req) err = authenticateAdminWithAPIKey(admin.Username, "", server.tokenAuth, req)
assert.Error(t, err) assert.Error(t, err)
err = dataprovider.DeleteAdmin(admin.Username, "", "") err = dataprovider.DeleteAdmin(admin.Username, "", "", "")
assert.NoError(t, err) assert.NoError(t, err)
} }
@ -1346,7 +1356,7 @@ func TestCookieExpiration(t *testing.T) {
assert.Empty(t, cookie) assert.Empty(t, cookie)
admin.Status = 0 admin.Status = 0
err = dataprovider.AddAdmin(&admin, "", "") err = dataprovider.AddAdmin(&admin, "", "", "")
assert.NoError(t, err) assert.NoError(t, err)
req, _ = http.NewRequest(http.MethodGet, tokenPath, nil) req, _ = http.NewRequest(http.MethodGet, tokenPath, nil)
ctx = jwtauth.NewContext(req.Context(), token, nil) ctx = jwtauth.NewContext(req.Context(), token, nil)
@ -1356,7 +1366,7 @@ func TestCookieExpiration(t *testing.T) {
admin.Status = 1 admin.Status = 1
admin.Filters.AllowList = []string{"172.16.1.0/24"} admin.Filters.AllowList = []string{"172.16.1.0/24"}
err = dataprovider.UpdateAdmin(&admin, "", "") err = dataprovider.UpdateAdmin(&admin, "", "", "")
assert.NoError(t, err) assert.NoError(t, err)
req, _ = http.NewRequest(http.MethodGet, tokenPath, nil) req, _ = http.NewRequest(http.MethodGet, tokenPath, nil)
ctx = jwtauth.NewContext(req.Context(), token, nil) ctx = jwtauth.NewContext(req.Context(), token, nil)
@ -1388,7 +1398,7 @@ func TestCookieExpiration(t *testing.T) {
cookie = rr.Header().Get("Set-Cookie") cookie = rr.Header().Get("Set-Cookie")
assert.True(t, strings.HasPrefix(cookie, "jwt=")) assert.True(t, strings.HasPrefix(cookie, "jwt="))
err = dataprovider.DeleteAdmin(admin.Username, "", "") err = dataprovider.DeleteAdmin(admin.Username, "", "", "")
assert.NoError(t, err) assert.NoError(t, err)
// now check client cookie expiration // now check client cookie expiration
username := "client" username := "client"
@ -1420,7 +1430,7 @@ func TestCookieExpiration(t *testing.T) {
cookie = rr.Header().Get("Set-Cookie") cookie = rr.Header().Get("Set-Cookie")
assert.Empty(t, cookie) assert.Empty(t, cookie)
// the password will be hashed and so the signature will change // the password will be hashed and so the signature will change
err = dataprovider.AddUser(&user, "", "") err = dataprovider.AddUser(&user, "", "", "")
assert.NoError(t, err) assert.NoError(t, err)
req, _ = http.NewRequest(http.MethodGet, webClientFilesPath, nil) req, _ = http.NewRequest(http.MethodGet, webClientFilesPath, nil)
ctx = jwtauth.NewContext(req.Context(), token, nil) ctx = jwtauth.NewContext(req.Context(), token, nil)
@ -1431,7 +1441,7 @@ func TestCookieExpiration(t *testing.T) {
user, err = dataprovider.UserExists(user.Username, "") user, err = dataprovider.UserExists(user.Username, "")
assert.NoError(t, err) assert.NoError(t, err)
user.Filters.AllowedIP = []string{"172.16.4.0/24"} user.Filters.AllowedIP = []string{"172.16.4.0/24"}
err = dataprovider.UpdateUser(&user, "", "") err = dataprovider.UpdateUser(&user, "", "", "")
assert.NoError(t, err) assert.NoError(t, err)
user, err = dataprovider.UserExists(user.Username, "") user, err = dataprovider.UserExists(user.Username, "")
@ -1755,7 +1765,7 @@ func TestProxyHeaders(t *testing.T) {
}, },
} }
err := dataprovider.AddAdmin(&admin, "", "") err := dataprovider.AddAdmin(&admin, "", "", "")
assert.NoError(t, err) assert.NoError(t, err)
testIP := "10.29.1.9" testIP := "10.29.1.9"
@ -1846,7 +1856,7 @@ func TestProxyHeaders(t *testing.T) {
cookie = rr.Header().Get("Set-Cookie") cookie = rr.Header().Get("Set-Cookie")
assert.NotContains(t, cookie, "Secure") assert.NotContains(t, cookie, "Secure")
err = dataprovider.DeleteAdmin(username, "", "") err = dataprovider.DeleteAdmin(username, "", "", "")
assert.NoError(t, err) assert.NoError(t, err)
} }
@ -2521,7 +2531,7 @@ func TestMetadataAPI(t *testing.T) {
} }
user.Permissions = make(map[string][]string) user.Permissions = make(map[string][]string)
user.Permissions["/"] = []string{dataprovider.PermAny} user.Permissions["/"] = []string{dataprovider.PermAny}
err := dataprovider.AddUser(&user, "", "") err := dataprovider.AddUser(&user, "", "", "")
assert.NoError(t, err) assert.NoError(t, err)
assert.True(t, common.ActiveMetadataChecks.Add(username, "")) assert.True(t, common.ActiveMetadataChecks.Add(username, ""))
@ -2725,7 +2735,7 @@ func TestWebAdminSetupWithInstallCode(t *testing.T) {
admins, err := dataprovider.GetAdmins(100, 0, dataprovider.OrderASC) admins, err := dataprovider.GetAdmins(100, 0, dataprovider.OrderASC)
assert.NoError(t, err) assert.NoError(t, err)
for _, admin := range admins { for _, admin := range admins {
err = dataprovider.DeleteAdmin(admin.Username, "", "") err = dataprovider.DeleteAdmin(admin.Username, "", "", "")
assert.NoError(t, err) assert.NoError(t, err)
} }
// close the provider and initializes it without creating the default admin // close the provider and initializes it without creating the default admin
@ -2787,7 +2797,7 @@ func TestWebAdminSetupWithInstallCode(t *testing.T) {
assert.NoError(t, err) assert.NoError(t, err)
// delete the admin and test the installation code resolver // delete the admin and test the installation code resolver
err = dataprovider.DeleteAdmin(defaultAdminUsername, "", "") err = dataprovider.DeleteAdmin(defaultAdminUsername, "", "", "")
assert.NoError(t, err) assert.NoError(t, err)
err = dataprovider.Close() err = dataprovider.Close()
@ -2891,6 +2901,16 @@ func TestDbResetCodeManager(t *testing.T) {
} }
} }
func TestEventRoleFilter(t *testing.T) {
defaultVal := "default"
req, err := http.NewRequest(http.MethodGet, fsEventsPath+"?role=role1", nil)
require.NoError(t, err)
role := getRoleFilterForEventSearch(req, defaultVal)
assert.Equal(t, defaultVal, role)
role = getRoleFilterForEventSearch(req, "")
assert.Equal(t, "role1", role)
}
func isSharedProviderSupported() bool { func isSharedProviderSupported() bool {
// SQLite shares the implementation with other SQL-based provider but it makes no sense // SQLite shares the implementation with other SQL-based provider but it makes no sense
// to use it outside test cases // to use it outside test cases

View file

@ -445,6 +445,7 @@ func authenticateAdminWithAPIKey(username, keyID string, tokenAuth *jwtauth.JWTA
Username: admin.Username, Username: admin.Username,
Permissions: admin.Permissions, Permissions: admin.Permissions,
Signature: admin.GetSignature(), Signature: admin.GetSignature(),
Role: admin.Role,
APIKeyID: keyID, APIKeyID: keyID,
} }
@ -499,6 +500,7 @@ func authenticateUserWithAPIKey(username, keyID string, tokenAuth *jwtauth.JWTAu
Username: user.Username, Username: user.Username,
Permissions: user.Filters.WebClient, Permissions: user.Filters.WebClient,
Signature: user.GetSignature(), Signature: user.GetSignature(),
Role: user.Role,
APIKeyID: keyID, APIKeyID: keyID,
} }

View file

@ -205,8 +205,8 @@ type oidcToken struct {
Username string `json:"username"` Username string `json:"username"`
Permissions []string `json:"permissions"` Permissions []string `json:"permissions"`
HideUserPageSections int `json:"hide_user_page_sections,omitempty"` HideUserPageSections int `json:"hide_user_page_sections,omitempty"`
AdminRole string `json:"admin_role,omitempty"` TokenRole string `json:"token_role,omitempty"` // SFTPGo role name
Role any `json:"role"` Role any `json:"role"` // oidc user role: SFTPGo user or admin
CustomFields *map[string]any `json:"custom_fields,omitempty"` CustomFields *map[string]any `json:"custom_fields,omitempty"`
Cookie string `json:"cookie"` Cookie string `json:"cookie"`
UsedAt int64 `json:"used_at"` UsedAt int64 `json:"used_at"`
@ -390,7 +390,7 @@ func (t *oidcToken) refreshUser(r *http.Request) error {
return err return err
} }
t.Permissions = admin.Permissions t.Permissions = admin.Permissions
t.AdminRole = admin.Role t.TokenRole = admin.Role
t.HideUserPageSections = admin.Filters.Preferences.HideUserPageSections t.HideUserPageSections = admin.Filters.Preferences.HideUserPageSections
return nil return nil
} }
@ -405,6 +405,7 @@ func (t *oidcToken) refreshUser(r *http.Request) error {
return err return err
} }
t.Permissions = user.Filters.WebClient t.Permissions = user.Filters.WebClient
t.TokenRole = user.Role
return nil return nil
} }
@ -418,7 +419,7 @@ func (t *oidcToken) getUser(r *http.Request) error {
return err return err
} }
t.Permissions = admin.Permissions t.Permissions = admin.Permissions
t.AdminRole = admin.Role t.TokenRole = admin.Role
t.HideUserPageSections = admin.Filters.Preferences.HideUserPageSections t.HideUserPageSections = admin.Filters.Preferences.HideUserPageSections
dataprovider.UpdateAdminLastLogin(&admin) dataprovider.UpdateAdminLastLogin(&admin)
return nil return nil
@ -451,6 +452,7 @@ func (t *oidcToken) getUser(r *http.Request) error {
updateLoginMetrics(&user, dataprovider.LoginMethodIDP, ipAddr, nil) updateLoginMetrics(&user, dataprovider.LoginMethodIDP, ipAddr, nil)
dataprovider.UpdateLastLogin(&user) dataprovider.UpdateLastLogin(&user)
t.Permissions = user.Filters.WebClient t.Permissions = user.Filters.WebClient
t.TokenRole = user.Role
return nil return nil
} }
@ -518,7 +520,7 @@ func (s *httpdServer) oidcTokenAuthenticator(audience tokenAudience) func(next h
jwtTokenClaims := jwtTokenClaims{ jwtTokenClaims := jwtTokenClaims{
Username: token.Username, Username: token.Username,
Permissions: token.Permissions, Permissions: token.Permissions,
Role: token.AdminRole, Role: token.TokenRole,
HideUserPageSections: token.HideUserPageSections, HideUserPageSections: token.HideUserPageSections,
} }
_, tokenString, err := jwtTokenClaims.createToken(s.tokenAuth, audience, util.GetIPFromRemoteAddress(r.RemoteAddr)) _, tokenString, err := jwtTokenClaims.createToken(s.tokenAuth, audience, util.GetIPFromRemoteAddress(r.RemoteAddr))

View file

@ -444,7 +444,7 @@ func TestOIDCLoginLogout(t *testing.T) {
}, },
}, },
} }
err = dataprovider.AddUser(&user, "", "") err = dataprovider.AddUser(&user, "", "", "")
assert.NoError(t, err) assert.NoError(t, err)
authReq = newOIDCPendingAuth(tokenAudienceWebClient) authReq = newOIDCPendingAuth(tokenAudienceWebClient)
@ -656,7 +656,7 @@ func TestOIDCRefreshUser(t *testing.T) {
}, },
}, },
} }
err = dataprovider.AddAdmin(&admin, "", "") err = dataprovider.AddAdmin(&admin, "", "", "")
assert.NoError(t, err) assert.NoError(t, err)
token.Username = admin.Username token.Username = admin.Username
@ -666,14 +666,14 @@ func TestOIDCRefreshUser(t *testing.T) {
} }
admin.Status = 1 admin.Status = 1
err = dataprovider.UpdateAdmin(&admin, "", "") err = dataprovider.UpdateAdmin(&admin, "", "", "")
assert.NoError(t, err) assert.NoError(t, err)
err = token.refreshUser(r) err = token.refreshUser(r)
assert.NoError(t, err) assert.NoError(t, err)
assert.Equal(t, admin.Permissions, token.Permissions) assert.Equal(t, admin.Permissions, token.Permissions)
assert.Equal(t, admin.Filters.Preferences.HideUserPageSections, token.HideUserPageSections) assert.Equal(t, admin.Filters.Preferences.HideUserPageSections, token.HideUserPageSections)
err = dataprovider.DeleteAdmin(admin.Username, "", "") err = dataprovider.DeleteAdmin(admin.Username, "", "", "")
assert.NoError(t, err) assert.NoError(t, err)
username := "test_oidc_user_refresh_token" username := "test_oidc_user_refresh_token"
@ -694,7 +694,7 @@ func TestOIDCRefreshUser(t *testing.T) {
}, },
}, },
} }
err = dataprovider.AddUser(&user, "", "") err = dataprovider.AddUser(&user, "", "", "")
assert.NoError(t, err) assert.NoError(t, err)
r, err = http.NewRequest(http.MethodGet, webClientFilesPath, nil) r, err = http.NewRequest(http.MethodGet, webClientFilesPath, nil)
@ -709,7 +709,7 @@ func TestOIDCRefreshUser(t *testing.T) {
user, err = dataprovider.UserExists(username, "") user, err = dataprovider.UserExists(username, "")
assert.NoError(t, err) assert.NoError(t, err)
user.Status = 1 user.Status = 1
err = dataprovider.UpdateUser(&user, "", "") err = dataprovider.UpdateUser(&user, "", "", "")
assert.NoError(t, err) assert.NoError(t, err)
err = token.refreshUser(r) err = token.refreshUser(r)
if assert.Error(t, err) { if assert.Error(t, err) {
@ -717,7 +717,7 @@ func TestOIDCRefreshUser(t *testing.T) {
} }
user.Filters.DeniedProtocols = []string{common.ProtocolFTP} user.Filters.DeniedProtocols = []string{common.ProtocolFTP}
err = dataprovider.UpdateUser(&user, "", "") err = dataprovider.UpdateUser(&user, "", "", "")
assert.NoError(t, err) assert.NoError(t, err)
err = token.refreshUser(r) err = token.refreshUser(r)
assert.NoError(t, err) assert.NoError(t, err)
@ -830,7 +830,7 @@ func TestOIDCToken(t *testing.T) {
Permissions: []string{dataprovider.PermAdminAny}, Permissions: []string{dataprovider.PermAdminAny},
Status: 0, Status: 0,
} }
err := dataprovider.AddAdmin(&admin, "", "") err := dataprovider.AddAdmin(&admin, "", "", "")
assert.NoError(t, err) assert.NoError(t, err)
token := oidcToken{ token := oidcToken{
@ -843,7 +843,7 @@ func TestOIDCToken(t *testing.T) {
if assert.Error(t, err) { if assert.Error(t, err) {
assert.Contains(t, err.Error(), "is disabled") assert.Contains(t, err.Error(), "is disabled")
} }
err = dataprovider.DeleteAdmin(admin.Username, "", "") err = dataprovider.DeleteAdmin(admin.Username, "", "", "")
assert.NoError(t, err) assert.NoError(t, err)
username := "test_oidc_user" username := "test_oidc_user"
@ -871,7 +871,7 @@ func TestOIDCToken(t *testing.T) {
}, },
}, },
} }
err = dataprovider.AddUser(&user, "", "") err = dataprovider.AddUser(&user, "", "", "")
assert.NoError(t, err) assert.NoError(t, err)
err = token.getUser(req) err = token.getUser(req)
if assert.Error(t, err) { if assert.Error(t, err) {
@ -881,7 +881,7 @@ func TestOIDCToken(t *testing.T) {
assert.NoError(t, err) assert.NoError(t, err)
user.Status = 1 user.Status = 1
user.Password = "np" user.Password = "np"
err = dataprovider.UpdateUser(&user, "", "") err = dataprovider.UpdateUser(&user, "", "", "")
assert.NoError(t, err) assert.NoError(t, err)
err = token.getUser(req) err = token.getUser(req)
@ -898,7 +898,7 @@ func TestOIDCToken(t *testing.T) {
}, },
Password: kms.NewPlainSecret("np"), Password: kms.NewPlainSecret("np"),
} }
err = dataprovider.UpdateUser(&user, "", "") err = dataprovider.UpdateUser(&user, "", "", "")
assert.NoError(t, err) assert.NoError(t, err)
err = token.getUser(req) err = token.getUser(req)
if assert.Error(t, err) { if assert.Error(t, err) {
@ -1001,7 +1001,7 @@ func TestOIDCImplicitRoles(t *testing.T) {
}, },
}, },
} }
err = dataprovider.AddUser(&user, "", "") err = dataprovider.AddUser(&user, "", "", "")
assert.NoError(t, err) assert.NoError(t, err)
authReq = newOIDCPendingAuth(tokenAudienceWebClient) authReq = newOIDCPendingAuth(tokenAudienceWebClient)
@ -1390,7 +1390,7 @@ func TestOIDCWithLoginFormsDisabled(t *testing.T) {
assert.Equal(t, http.StatusSeeOther, rr.Code) assert.Equal(t, http.StatusSeeOther, rr.Code)
_, err = dataprovider.AdminExists(adminUsername) _, err = dataprovider.AdminExists(adminUsername)
assert.NoError(t, err) assert.NoError(t, err)
err = dataprovider.DeleteAdmin(adminUsername, "", "") err = dataprovider.DeleteAdmin(adminUsername, "", "", "")
assert.NoError(t, err) assert.NoError(t, err)
// login and password related routes are disabled // login and password related routes are disabled
rr = httptest.NewRecorder() rr = httptest.NewRecorder()

View file

@ -349,7 +349,7 @@ func (s *httpdServer) handleWebClientTwoFactorRecoveryPost(w http.ResponseWriter
return return
} }
user.Filters.RecoveryCodes[idx].Used = true user.Filters.RecoveryCodes[idx].Used = true
err = dataprovider.UpdateUser(&user, dataprovider.ActionExecutorSelf, ipAddr) err = dataprovider.UpdateUser(&user, dataprovider.ActionExecutorSelf, ipAddr, user.Role)
if err != nil { if err != nil {
logger.Warn(logSender, "", "unable to set the recovery code %#v as used: %v", recoveryCode, err) logger.Warn(logSender, "", "unable to set the recovery code %#v as used: %v", recoveryCode, err)
s.renderClientInternalServerErrorPage(w, r, errors.New("unable to set the recovery code as used")) s.renderClientInternalServerErrorPage(w, r, errors.New("unable to set the recovery code as used"))
@ -453,7 +453,7 @@ func (s *httpdServer) handleWebAdminTwoFactorRecoveryPost(w http.ResponseWriter,
return return
} }
admin.Filters.RecoveryCodes[idx].Used = true admin.Filters.RecoveryCodes[idx].Used = true
err = dataprovider.UpdateAdmin(&admin, dataprovider.ActionExecutorSelf, ipAddr) err = dataprovider.UpdateAdmin(&admin, dataprovider.ActionExecutorSelf, ipAddr, admin.Role)
if err != nil { if err != nil {
logger.Warn(logSender, "", "unable to set the recovery code %#v as used: %v", recoveryCode, err) logger.Warn(logSender, "", "unable to set the recovery code %#v as used: %v", recoveryCode, err)
s.renderInternalServerErrorPage(w, r, errors.New("unable to set the recovery code as used")) s.renderInternalServerErrorPage(w, r, errors.New("unable to set the recovery code as used"))
@ -666,7 +666,7 @@ func (s *httpdServer) handleWebAdminSetupPost(w http.ResponseWriter, r *http.Req
Status: 1, Status: 1,
Permissions: []string{dataprovider.PermAdminAny}, Permissions: []string{dataprovider.PermAdminAny},
} }
err = dataprovider.AddAdmin(&admin, username, ipAddr) err = dataprovider.AddAdmin(&admin, username, ipAddr, "")
if err != nil { if err != nil {
s.renderAdminSetupPage(w, r, username, err.Error()) s.renderAdminSetupPage(w, r, username, err.Error())
return return
@ -682,6 +682,7 @@ func (s *httpdServer) loginUser(
Username: user.Username, Username: user.Username,
Permissions: user.Filters.WebClient, Permissions: user.Filters.WebClient,
Signature: user.GetSignature(), Signature: user.GetSignature(),
Role: user.Role,
MustSetTwoFactorAuth: user.MustSetSecondFactor(), MustSetTwoFactorAuth: user.MustSetSecondFactor(),
RequiredTwoFactorProtocols: user.Filters.TwoFactorAuthProtocols, RequiredTwoFactorProtocols: user.Filters.TwoFactorAuthProtocols,
} }
@ -839,6 +840,7 @@ func (s *httpdServer) generateAndSendUserToken(w http.ResponseWriter, r *http.Re
Username: user.Username, Username: user.Username,
Permissions: user.Filters.WebClient, Permissions: user.Filters.WebClient,
Signature: user.GetSignature(), Signature: user.GetSignature(),
Role: user.Role,
MustSetTwoFactorAuth: user.MustSetSecondFactor(), MustSetTwoFactorAuth: user.MustSetSecondFactor(),
RequiredTwoFactorProtocols: user.Filters.TwoFactorAuthProtocols, RequiredTwoFactorProtocols: user.Filters.TwoFactorAuthProtocols,
} }
@ -946,16 +948,17 @@ func (s *httpdServer) refreshClientToken(w http.ResponseWriter, r *http.Request,
return return
} }
if user.GetSignature() != tokenClaims.Signature { if user.GetSignature() != tokenClaims.Signature {
logger.Debug(logSender, "", "signature mismatch for user %#v, unable to refresh cookie", user.Username) logger.Debug(logSender, "", "signature mismatch for user %q, unable to refresh cookie", user.Username)
return return
} }
if err := checkHTTPClientUser(&user, r, xid.New().String(), true); err != nil { if err := checkHTTPClientUser(&user, r, xid.New().String(), true); err != nil {
logger.Debug(logSender, "", "unable to refresh cookie for user %#v: %v", user.Username, err) logger.Debug(logSender, "", "unable to refresh cookie for user %q: %v", user.Username, err)
return return
} }
tokenClaims.Permissions = user.Filters.WebClient tokenClaims.Permissions = user.Filters.WebClient
logger.Debug(logSender, "", "cookie refreshed for user %#v", user.Username) tokenClaims.Role = user.Role
logger.Debug(logSender, "", "cookie refreshed for user %q", user.Username)
tokenClaims.createAndSetCookie(w, r, s.tokenAuth, tokenAudienceWebClient, util.GetIPFromRemoteAddress(r.RemoteAddr)) //nolint:errcheck tokenClaims.createAndSetCookie(w, r, s.tokenAuth, tokenAudienceWebClient, util.GetIPFromRemoteAddress(r.RemoteAddr)) //nolint:errcheck
} }

View file

@ -2407,7 +2407,7 @@ func (s *httpdServer) handleWebAdminProfilePost(w http.ResponseWriter, r *http.R
admin.Filters.AllowAPIKeyAuth = r.Form.Get("allow_api_key_auth") != "" admin.Filters.AllowAPIKeyAuth = r.Form.Get("allow_api_key_auth") != ""
admin.Email = r.Form.Get("email") admin.Email = r.Form.Get("email")
admin.Description = r.Form.Get("description") admin.Description = r.Form.Get("description")
err = dataprovider.UpdateAdmin(&admin, dataprovider.ActionExecutorSelf, ipAddr) err = dataprovider.UpdateAdmin(&admin, dataprovider.ActionExecutorSelf, ipAddr, admin.Role)
if err != nil { if err != nil {
s.renderProfilePage(w, r, err.Error()) s.renderProfilePage(w, r, err.Error())
return return
@ -2466,7 +2466,7 @@ func (s *httpdServer) handleWebRestore(w http.ResponseWriter, r *http.Request) {
return return
} }
if err := restoreBackup(backupContent, "", scanQuota, restoreMode, claims.Username, ipAddr); err != nil { if err := restoreBackup(backupContent, "", scanQuota, restoreMode, claims.Username, ipAddr, claims.Role); err != nil {
s.renderMaintenancePage(w, r, err.Error()) s.renderMaintenancePage(w, r, err.Error())
return return
} }
@ -2554,7 +2554,7 @@ func (s *httpdServer) handleWebAddAdminPost(w http.ResponseWriter, r *http.Reque
s.renderForbiddenPage(w, r, err.Error()) s.renderForbiddenPage(w, r, err.Error())
return return
} }
err = dataprovider.AddAdmin(&admin, claims.Username, ipAddr) err = dataprovider.AddAdmin(&admin, claims.Username, ipAddr, claims.Role)
if err != nil { if err != nil {
s.renderAddUpdateAdminPage(w, r, &admin, err.Error(), true) s.renderAddUpdateAdminPage(w, r, &admin, err.Error(), true)
return return
@ -2611,7 +2611,7 @@ func (s *httpdServer) handleWebUpdateAdminPost(w http.ResponseWriter, r *http.Re
return return
} }
} }
err = dataprovider.UpdateAdmin(&updatedAdmin, claims.Username, ipAddr) err = dataprovider.UpdateAdmin(&updatedAdmin, claims.Username, ipAddr, claims.Role)
if err != nil { if err != nil {
s.renderAddUpdateAdminPage(w, r, &updatedAdmin, err.Error(), false) s.renderAddUpdateAdminPage(w, r, &updatedAdmin, err.Error(), false)
return return
@ -2739,7 +2739,7 @@ func (s *httpdServer) handleWebTemplateFolderPost(w http.ResponseWriter, r *http
render.JSON(w, r, dump) render.JSON(w, r, dump)
return return
} }
if err = RestoreFolders(dump.Folders, "", 1, 0, claims.Username, ipAddr); err != nil { if err = RestoreFolders(dump.Folders, "", 1, 0, claims.Username, ipAddr, claims.Role); err != nil {
s.renderMessagePage(w, r, "Unable to save folders", "Cannot save the defined folders:", s.renderMessagePage(w, r, "Unable to save folders", "Cannot save the defined folders:",
getRespStatus(err), err, "") getRespStatus(err), err, "")
return return
@ -2836,7 +2836,7 @@ func (s *httpdServer) handleWebTemplateUserPost(w http.ResponseWriter, r *http.R
render.JSON(w, r, dump) render.JSON(w, r, dump)
return return
} }
if err = RestoreUsers(dump.Users, "", 1, 0, claims.Username, ipAddr); err != nil { if err = RestoreUsers(dump.Users, "", 1, 0, claims.Username, ipAddr, claims.Role); err != nil {
s.renderMessagePage(w, r, "Unable to save users", "Cannot save the defined users:", s.renderMessagePage(w, r, "Unable to save users", "Cannot save the defined users:",
getRespStatus(err), err, "") getRespStatus(err), err, "")
return return
@ -2911,7 +2911,7 @@ func (s *httpdServer) handleWebAddUserPost(w http.ResponseWriter, r *http.Reques
user.Filters.TOTPConfig = dataprovider.UserTOTPConfig{ user.Filters.TOTPConfig = dataprovider.UserTOTPConfig{
Enabled: false, Enabled: false,
} }
err = dataprovider.AddUser(&user, claims.Username, ipAddr) err = dataprovider.AddUser(&user, claims.Username, ipAddr, claims.Role)
if err != nil { if err != nil {
s.renderUserPage(w, r, &user, userPageModeAdd, err.Error(), nil) s.renderUserPage(w, r, &user, userPageModeAdd, err.Error(), nil)
return return
@ -2967,7 +2967,7 @@ func (s *httpdServer) handleWebUpdateUserPost(w http.ResponseWriter, r *http.Req
updatedUser.Role = claims.Role updatedUser.Role = claims.Role
} }
err = dataprovider.UpdateUser(&updatedUser, claims.Username, ipAddr) err = dataprovider.UpdateUser(&updatedUser, claims.Username, ipAddr, claims.Role)
if err != nil { if err != nil {
s.renderUserPage(w, r, &updatedUser, userPageModeUpdate, err.Error(), nil) s.renderUserPage(w, r, &updatedUser, userPageModeUpdate, err.Error(), nil)
return return
@ -3039,7 +3039,7 @@ func (s *httpdServer) handleWebAddFolderPost(w http.ResponseWriter, r *http.Requ
folder.FsConfig = fsConfig folder.FsConfig = fsConfig
folder = getFolderFromTemplate(folder, folder.Name) folder = getFolderFromTemplate(folder, folder.Name)
err = dataprovider.AddFolder(&folder, claims.Username, ipAddr) err = dataprovider.AddFolder(&folder, claims.Username, ipAddr, claims.Role)
if err == nil { if err == nil {
http.Redirect(w, r, webFoldersPath, http.StatusSeeOther) http.Redirect(w, r, webFoldersPath, http.StatusSeeOther)
} else { } else {
@ -3109,7 +3109,7 @@ func (s *httpdServer) handleWebUpdateFolderPost(w http.ResponseWriter, r *http.R
updatedFolder = getFolderFromTemplate(updatedFolder, updatedFolder.Name) updatedFolder = getFolderFromTemplate(updatedFolder, updatedFolder.Name)
err = dataprovider.UpdateFolder(&updatedFolder, folder.Users, folder.Groups, claims.Username, ipAddr) err = dataprovider.UpdateFolder(&updatedFolder, folder.Users, folder.Groups, claims.Username, ipAddr, claims.Role)
if err != nil { if err != nil {
s.renderFolderPage(w, r, updatedFolder, folderPageModeUpdate, err.Error()) s.renderFolderPage(w, r, updatedFolder, folderPageModeUpdate, err.Error())
return return
@ -3215,7 +3215,7 @@ func (s *httpdServer) handleWebAddGroupPost(w http.ResponseWriter, r *http.Reque
s.renderForbiddenPage(w, r, err.Error()) s.renderForbiddenPage(w, r, err.Error())
return return
} }
err = dataprovider.AddGroup(&group, claims.Username, ipAddr) err = dataprovider.AddGroup(&group, claims.Username, ipAddr, claims.Role)
if err != nil { if err != nil {
s.renderGroupPage(w, r, group, genericPageModeAdd, err.Error()) s.renderGroupPage(w, r, group, genericPageModeAdd, err.Error())
return return
@ -3273,7 +3273,7 @@ func (s *httpdServer) handleWebUpdateGroupPost(w http.ResponseWriter, r *http.Re
group.UserSettings.FsConfig.SFTPConfig.KeyPassphrase, group.UserSettings.FsConfig.HTTPConfig.Password, group.UserSettings.FsConfig.SFTPConfig.KeyPassphrase, group.UserSettings.FsConfig.HTTPConfig.Password,
group.UserSettings.FsConfig.HTTPConfig.APIKey) group.UserSettings.FsConfig.HTTPConfig.APIKey)
err = dataprovider.UpdateGroup(&updatedGroup, group.Users, claims.Username, ipAddr) err = dataprovider.UpdateGroup(&updatedGroup, group.Users, claims.Username, ipAddr, claims.Role)
if err != nil { if err != nil {
s.renderGroupPage(w, r, updatedGroup, genericPageModeUpdate, err.Error()) s.renderGroupPage(w, r, updatedGroup, genericPageModeUpdate, err.Error())
return return
@ -3345,7 +3345,7 @@ func (s *httpdServer) handleWebAddEventActionPost(w http.ResponseWriter, r *http
s.renderForbiddenPage(w, r, err.Error()) s.renderForbiddenPage(w, r, err.Error())
return return
} }
if err = dataprovider.AddEventAction(&action, claims.Username, ipAddr); err != nil { if err = dataprovider.AddEventAction(&action, claims.Username, ipAddr, claims.Role); err != nil {
s.renderEventActionPage(w, r, action, genericPageModeAdd, err.Error()) s.renderEventActionPage(w, r, action, genericPageModeAdd, err.Error())
return return
} }
@ -3400,7 +3400,7 @@ func (s *httpdServer) handleWebUpdateEventActionPost(w http.ResponseWriter, r *h
updatedAction.Options.HTTPConfig.Password = action.Options.HTTPConfig.Password updatedAction.Options.HTTPConfig.Password = action.Options.HTTPConfig.Password
} }
} }
err = dataprovider.UpdateEventAction(&updatedAction, claims.Username, ipAddr) err = dataprovider.UpdateEventAction(&updatedAction, claims.Username, ipAddr, claims.Role)
if err != nil { if err != nil {
s.renderEventActionPage(w, r, updatedAction, genericPageModeUpdate, err.Error()) s.renderEventActionPage(w, r, updatedAction, genericPageModeUpdate, err.Error())
return return
@ -3462,7 +3462,7 @@ func (s *httpdServer) handleWebAddEventRulePost(w http.ResponseWriter, r *http.R
s.renderForbiddenPage(w, r, err.Error()) s.renderForbiddenPage(w, r, err.Error())
return return
} }
if err = dataprovider.AddEventRule(&rule, claims.Username, ipAddr); err != nil { if err = dataprovider.AddEventRule(&rule, claims.Username, ipAddr, claims.Role); err != nil {
s.renderEventRulePage(w, r, rule, genericPageModeAdd, err.Error()) s.renderEventRulePage(w, r, rule, genericPageModeAdd, err.Error())
return return
} }
@ -3510,7 +3510,7 @@ func (s *httpdServer) handleWebUpdateEventRulePost(w http.ResponseWriter, r *htt
} }
updatedRule.ID = rule.ID updatedRule.ID = rule.ID
updatedRule.Name = rule.Name updatedRule.Name = rule.Name
err = dataprovider.UpdateEventRule(&updatedRule, claims.Username, ipAddr) err = dataprovider.UpdateEventRule(&updatedRule, claims.Username, ipAddr, claims.Role)
if err != nil { if err != nil {
s.renderEventRulePage(w, r, updatedRule, genericPageModeUpdate, err.Error()) s.renderEventRulePage(w, r, updatedRule, genericPageModeUpdate, err.Error())
return return
@ -3569,7 +3569,7 @@ func (s *httpdServer) handleWebAddRolePost(w http.ResponseWriter, r *http.Reques
s.renderForbiddenPage(w, r, err.Error()) s.renderForbiddenPage(w, r, err.Error())
return return
} }
err = dataprovider.AddRole(&role, claims.Username, ipAddr) err = dataprovider.AddRole(&role, claims.Username, ipAddr, claims.Role)
if err != nil { if err != nil {
s.renderRolePage(w, r, role, genericPageModeAdd, err.Error()) s.renderRolePage(w, r, role, genericPageModeAdd, err.Error())
return return
@ -3617,7 +3617,7 @@ func (s *httpdServer) handleWebUpdateRolePost(w http.ResponseWriter, r *http.Req
} }
updatedRole.ID = role.ID updatedRole.ID = role.ID
updatedRole.Name = role.Name updatedRole.Name = role.Name
err = dataprovider.UpdateRole(&updatedRole, claims.Username, ipAddr) err = dataprovider.UpdateRole(&updatedRole, claims.Username, ipAddr, claims.Role)
if err != nil { if err != nil {
s.renderRolePage(w, r, updatedRole, genericPageModeUpdate, err.Error()) s.renderRolePage(w, r, updatedRole, genericPageModeUpdate, err.Error())
return return

View file

@ -1103,7 +1103,7 @@ func (s *httpdServer) handleClientAddSharePost(w http.ResponseWriter, r *http.Re
return return
} }
} }
err = dataprovider.AddShare(share, claims.Username, ipAddr) err = dataprovider.AddShare(share, claims.Username, ipAddr, claims.Role)
if err == nil { if err == nil {
http.Redirect(w, r, webClientSharesPath, http.StatusSeeOther) http.Redirect(w, r, webClientSharesPath, http.StatusSeeOther)
} else { } else {
@ -1148,7 +1148,7 @@ func (s *httpdServer) handleClientUpdateSharePost(w http.ResponseWriter, r *http
return return
} }
} }
err = dataprovider.UpdateShare(updatedShare, claims.Username, ipAddr) err = dataprovider.UpdateShare(updatedShare, claims.Username, ipAddr, claims.Role)
if err == nil { if err == nil {
http.Redirect(w, r, webClientSharesPath, http.StatusSeeOther) http.Redirect(w, r, webClientSharesPath, http.StatusSeeOther)
} else { } else {
@ -1237,7 +1237,7 @@ func (s *httpdServer) handleWebClientProfilePost(w http.ResponseWriter, r *http.
user.Email = r.Form.Get("email") user.Email = r.Form.Get("email")
user.Description = r.Form.Get("description") user.Description = r.Form.Get("description")
} }
err = dataprovider.UpdateUser(&user, dataprovider.ActionExecutorSelf, ipAddr) err = dataprovider.UpdateUser(&user, dataprovider.ActionExecutorSelf, ipAddr, user.Role)
if err != nil { if err != nil {
s.renderClientProfilePage(w, r, err.Error()) s.renderClientProfilePage(w, r, err.Error())
return return

View file

@ -162,7 +162,7 @@ func (s *Service) initializeServices(disableAWSInstallationCode bool) error {
if s.PortableMode == 1 { if s.PortableMode == 1 {
// create the user for portable mode // create the user for portable mode
err = dataprovider.AddUser(&s.PortableUser, dataprovider.ActionExecutorSystem, "") err = dataprovider.AddUser(&s.PortableUser, dataprovider.ActionExecutorSystem, "", "")
if err != nil { if err != nil {
logger.ErrorToConsole("error adding portable user: %v", err) logger.ErrorToConsole("error adding portable user: %v", err)
return err return err
@ -350,39 +350,39 @@ func (s *Service) LoadInitialData() error {
} }
func (s *Service) restoreDump(dump *dataprovider.BackupData) error { func (s *Service) restoreDump(dump *dataprovider.BackupData) error {
err := httpd.RestoreRoles(dump.Roles, s.LoadDataFrom, s.LoadDataMode, dataprovider.ActionExecutorSystem, "") err := httpd.RestoreRoles(dump.Roles, s.LoadDataFrom, s.LoadDataMode, dataprovider.ActionExecutorSystem, "", "")
if err != nil { if err != nil {
return fmt.Errorf("unable to restore roles from file %#v: %v", s.LoadDataFrom, err) return fmt.Errorf("unable to restore roles from file %#v: %v", s.LoadDataFrom, err)
} }
err = httpd.RestoreFolders(dump.Folders, s.LoadDataFrom, s.LoadDataMode, s.LoadDataQuotaScan, dataprovider.ActionExecutorSystem, "") err = httpd.RestoreFolders(dump.Folders, s.LoadDataFrom, s.LoadDataMode, s.LoadDataQuotaScan, dataprovider.ActionExecutorSystem, "", "")
if err != nil { if err != nil {
return fmt.Errorf("unable to restore folders from file %#v: %v", s.LoadDataFrom, err) return fmt.Errorf("unable to restore folders from file %#v: %v", s.LoadDataFrom, err)
} }
err = httpd.RestoreGroups(dump.Groups, s.LoadDataFrom, s.LoadDataMode, dataprovider.ActionExecutorSystem, "") err = httpd.RestoreGroups(dump.Groups, s.LoadDataFrom, s.LoadDataMode, dataprovider.ActionExecutorSystem, "", "")
if err != nil { if err != nil {
return fmt.Errorf("unable to restore groups from file %#v: %v", s.LoadDataFrom, err) return fmt.Errorf("unable to restore groups from file %#v: %v", s.LoadDataFrom, err)
} }
err = httpd.RestoreUsers(dump.Users, s.LoadDataFrom, s.LoadDataMode, s.LoadDataQuotaScan, dataprovider.ActionExecutorSystem, "") err = httpd.RestoreUsers(dump.Users, s.LoadDataFrom, s.LoadDataMode, s.LoadDataQuotaScan, dataprovider.ActionExecutorSystem, "", "")
if err != nil { if err != nil {
return fmt.Errorf("unable to restore users from file %#v: %v", s.LoadDataFrom, err) return fmt.Errorf("unable to restore users from file %#v: %v", s.LoadDataFrom, err)
} }
err = httpd.RestoreAdmins(dump.Admins, s.LoadDataFrom, s.LoadDataMode, dataprovider.ActionExecutorSystem, "") err = httpd.RestoreAdmins(dump.Admins, s.LoadDataFrom, s.LoadDataMode, dataprovider.ActionExecutorSystem, "", "")
if err != nil { if err != nil {
return fmt.Errorf("unable to restore admins from file %#v: %v", s.LoadDataFrom, err) return fmt.Errorf("unable to restore admins from file %#v: %v", s.LoadDataFrom, err)
} }
err = httpd.RestoreAPIKeys(dump.APIKeys, s.LoadDataFrom, s.LoadDataMode, dataprovider.ActionExecutorSystem, "") err = httpd.RestoreAPIKeys(dump.APIKeys, s.LoadDataFrom, s.LoadDataMode, dataprovider.ActionExecutorSystem, "", "")
if err != nil { if err != nil {
return fmt.Errorf("unable to restore API keys from file %#v: %v", s.LoadDataFrom, err) return fmt.Errorf("unable to restore API keys from file %#v: %v", s.LoadDataFrom, err)
} }
err = httpd.RestoreShares(dump.Shares, s.LoadDataFrom, s.LoadDataMode, dataprovider.ActionExecutorSystem, "") err = httpd.RestoreShares(dump.Shares, s.LoadDataFrom, s.LoadDataMode, dataprovider.ActionExecutorSystem, "", "")
if err != nil { if err != nil {
return fmt.Errorf("unable to restore API keys from file %#v: %v", s.LoadDataFrom, err) return fmt.Errorf("unable to restore API keys from file %#v: %v", s.LoadDataFrom, err)
} }
err = httpd.RestoreEventActions(dump.EventActions, s.LoadDataFrom, s.LoadDataMode, dataprovider.ActionExecutorSystem, "") err = httpd.RestoreEventActions(dump.EventActions, s.LoadDataFrom, s.LoadDataMode, dataprovider.ActionExecutorSystem, "", "")
if err != nil { if err != nil {
return fmt.Errorf("unable to restore event actions from file %#v: %v", s.LoadDataFrom, err) return fmt.Errorf("unable to restore event actions from file %#v: %v", s.LoadDataFrom, err)
} }
err = httpd.RestoreEventRules(dump.EventRules, s.LoadDataFrom, s.LoadDataMode, dataprovider.ActionExecutorSystem, "") err = httpd.RestoreEventRules(dump.EventRules, s.LoadDataFrom, s.LoadDataMode, dataprovider.ActionExecutorSystem, "", "")
if err != nil { if err != nil {
return fmt.Errorf("unable to restore event rules from file %#v: %v", s.LoadDataFrom, err) return fmt.Errorf("unable to restore event rules from file %#v: %v", s.LoadDataFrom, err)
} }

View file

@ -2790,7 +2790,7 @@ func TestInteractiveLoginWithPasscode(t *testing.T) {
Secret: kms.NewPlainSecret(secret), Secret: kms.NewPlainSecret(secret),
Protocols: []string{common.ProtocolSSH}, Protocols: []string{common.ProtocolSSH},
} }
err = dataprovider.UpdateUser(&user, "", "") err = dataprovider.UpdateUser(&user, "", "", "")
assert.NoError(t, err) assert.NoError(t, err)
passcode, err := totp.GenerateCodeCustom(secret, time.Now(), totp.ValidateOpts{ passcode, err := totp.GenerateCodeCustom(secret, time.Now(), totp.ValidateOpts{
@ -2839,7 +2839,7 @@ func TestInteractiveLoginWithPasscode(t *testing.T) {
Secret: kms.NewPlainSecret(secret), Secret: kms.NewPlainSecret(secret),
Protocols: []string{common.ProtocolSSH}, Protocols: []string{common.ProtocolSSH},
} }
err = dataprovider.UpdateUser(&user, "", "") err = dataprovider.UpdateUser(&user, "", "", "")
assert.NoError(t, err) assert.NoError(t, err)
passcode, err = totp.GenerateCodeCustom(secret, time.Now(), totp.ValidateOpts{ passcode, err = totp.GenerateCodeCustom(secret, time.Now(), totp.ValidateOpts{
Period: 30, Period: 30,
@ -2897,7 +2897,7 @@ func TestSecondFactorRequirement(t *testing.T) {
Secret: kms.NewPlainSecret(secret), Secret: kms.NewPlainSecret(secret),
Protocols: []string{common.ProtocolSSH}, Protocols: []string{common.ProtocolSSH},
} }
err = dataprovider.UpdateUser(&user, "", "") err = dataprovider.UpdateUser(&user, "", "", "")
assert.NoError(t, err) assert.NoError(t, err)
conn, client, err := getSftpClient(user, usePubKey) conn, client, err := getSftpClient(user, usePubKey)
@ -3111,7 +3111,7 @@ func TestPreLoginHookPreserveMFAConfig(t *testing.T) {
Secret: kms.NewPlainSecret(fmt.Sprintf("RC-%v", strings.ToUpper(util.GenerateUniqueID()))), Secret: kms.NewPlainSecret(fmt.Sprintf("RC-%v", strings.ToUpper(util.GenerateUniqueID()))),
}) })
} }
err = dataprovider.UpdateUser(&user, "", "") err = dataprovider.UpdateUser(&user, "", "", "")
assert.NoError(t, err) assert.NoError(t, err)
conn, client, err = getSftpClient(u, usePubKey) conn, client, err = getSftpClient(u, usePubKey)
@ -4166,7 +4166,7 @@ func TestExternalAuthPreserveMFAConfig(t *testing.T) {
Secret: kms.NewPlainSecret(fmt.Sprintf("RC-%v", strings.ToUpper(util.GenerateUniqueID()))), Secret: kms.NewPlainSecret(fmt.Sprintf("RC-%v", strings.ToUpper(util.GenerateUniqueID()))),
}) })
} }
err = dataprovider.UpdateUser(&user, "", "") err = dataprovider.UpdateUser(&user, "", "", "")
assert.NoError(t, err) assert.NoError(t, err)
// login again and check that the MFA configs are preserved // login again and check that the MFA configs are preserved
conn, client, err = getSftpClient(u, usePubKey) conn, client, err = getSftpClient(u, usePubKey)
@ -4274,7 +4274,7 @@ func TestMaxConnections(t *testing.T) {
usePubKey := true usePubKey := true
user := getTestUser(usePubKey) user := getTestUser(usePubKey)
err := dataprovider.AddUser(&user, "", "") err := dataprovider.AddUser(&user, "", "", "")
assert.NoError(t, err) assert.NoError(t, err)
user.Password = "" user.Password = ""
conn, client, err := getSftpClient(user, usePubKey) conn, client, err := getSftpClient(user, usePubKey)
@ -4309,7 +4309,7 @@ func TestMaxPerHostConnections(t *testing.T) {
usePubKey := true usePubKey := true
user := getTestUser(usePubKey) user := getTestUser(usePubKey)
err := dataprovider.AddUser(&user, "", "") err := dataprovider.AddUser(&user, "", "", "")
assert.NoError(t, err) assert.NoError(t, err)
user.Password = "" user.Password = ""
conn, client, err := getSftpClient(user, usePubKey) conn, client, err := getSftpClient(user, usePubKey)

View file

@ -958,7 +958,7 @@ func TestBasicUsersCache(t *testing.T) {
} }
u.Permissions = make(map[string][]string) u.Permissions = make(map[string][]string)
u.Permissions["/"] = []string{dataprovider.PermAny} u.Permissions["/"] = []string{dataprovider.PermAny}
err := dataprovider.AddUser(&u, "", "") err := dataprovider.AddUser(&u, "", "", "")
assert.NoError(t, err) assert.NoError(t, err)
user, err := dataprovider.UserExists(u.Username, "") user, err := dataprovider.UserExists(u.Username, "")
assert.NoError(t, err) assert.NoError(t, err)
@ -1030,7 +1030,7 @@ func TestBasicUsersCache(t *testing.T) {
assert.False(t, cachedUser.IsExpired()) assert.False(t, cachedUser.IsExpired())
} }
// cache is not invalidated after a user modification if the fs does not change // cache is not invalidated after a user modification if the fs does not change
err = dataprovider.UpdateUser(&user, "", "") err = dataprovider.UpdateUser(&user, "", "", "")
assert.NoError(t, err) assert.NoError(t, err)
_, ok = dataprovider.GetCachedWebDAVUser(username) _, ok = dataprovider.GetCachedWebDAVUser(username)
assert.True(t, ok) assert.True(t, ok)
@ -1043,7 +1043,7 @@ func TestBasicUsersCache(t *testing.T) {
VirtualPath: "/vdir", VirtualPath: "/vdir",
}) })
err = dataprovider.UpdateUser(&user, "", "") err = dataprovider.UpdateUser(&user, "", "", "")
assert.NoError(t, err) assert.NoError(t, err)
_, ok = dataprovider.GetCachedWebDAVUser(username) _, ok = dataprovider.GetCachedWebDAVUser(username)
assert.False(t, ok) assert.False(t, ok)
@ -1060,7 +1060,7 @@ func TestBasicUsersCache(t *testing.T) {
_, ok = dataprovider.GetCachedWebDAVUser(username) _, ok = dataprovider.GetCachedWebDAVUser(username)
assert.False(t, ok) assert.False(t, ok)
err = dataprovider.DeleteFolder(folderName, "", "") err = dataprovider.DeleteFolder(folderName, "", "", "")
assert.NoError(t, err) assert.NoError(t, err)
err = os.RemoveAll(u.GetHomeDir()) err = os.RemoveAll(u.GetHomeDir())
@ -1089,7 +1089,7 @@ func TestCachedUserWithFolders(t *testing.T) {
}, },
VirtualPath: "/vpath", VirtualPath: "/vpath",
}) })
err := dataprovider.AddUser(&u, "", "") err := dataprovider.AddUser(&u, "", "", "")
assert.NoError(t, err) assert.NoError(t, err)
user, err := dataprovider.UserExists(u.Username, "") user, err := dataprovider.UserExists(u.Username, "")
assert.NoError(t, err) assert.NoError(t, err)
@ -1142,7 +1142,7 @@ func TestCachedUserWithFolders(t *testing.T) {
folder, err := dataprovider.GetFolderByName(folderName) folder, err := dataprovider.GetFolderByName(folderName)
assert.NoError(t, err) assert.NoError(t, err)
// updating a used folder should invalidate the cache only if the fs changed // updating a used folder should invalidate the cache only if the fs changed
err = dataprovider.UpdateFolder(&folder, folder.Users, folder.Groups, "", "") err = dataprovider.UpdateFolder(&folder, folder.Users, folder.Groups, "", "", "")
assert.NoError(t, err) assert.NoError(t, err)
_, isCached, _, loginMethod, err = server.authenticate(req, ipAddr) _, isCached, _, loginMethod, err = server.authenticate(req, ipAddr)
@ -1155,7 +1155,7 @@ func TestCachedUserWithFolders(t *testing.T) {
} }
// changing the folder path should invalidate the cache // changing the folder path should invalidate the cache
folder.MappedPath = filepath.Join(os.TempDir(), "anotherpath") folder.MappedPath = filepath.Join(os.TempDir(), "anotherpath")
err = dataprovider.UpdateFolder(&folder, folder.Users, folder.Groups, "", "") err = dataprovider.UpdateFolder(&folder, folder.Users, folder.Groups, "", "", "")
assert.NoError(t, err) assert.NoError(t, err)
_, isCached, _, loginMethod, err = server.authenticate(req, ipAddr) _, isCached, _, loginMethod, err = server.authenticate(req, ipAddr)
assert.NoError(t, err) assert.NoError(t, err)
@ -1166,7 +1166,7 @@ func TestCachedUserWithFolders(t *testing.T) {
assert.False(t, cachedUser.IsExpired()) assert.False(t, cachedUser.IsExpired())
} }
err = dataprovider.DeleteFolder(folderName, "", "") err = dataprovider.DeleteFolder(folderName, "", "", "")
assert.NoError(t, err) assert.NoError(t, err)
// removing a used folder should invalidate the cache // removing a used folder should invalidate the cache
_, isCached, _, loginMethod, err = server.authenticate(req, ipAddr) _, isCached, _, loginMethod, err = server.authenticate(req, ipAddr)
@ -1204,25 +1204,25 @@ func TestUsersCacheSizeAndExpiration(t *testing.T) {
u.Password = password + "1" u.Password = password + "1"
u.Permissions = make(map[string][]string) u.Permissions = make(map[string][]string)
u.Permissions["/"] = []string{dataprovider.PermAny} u.Permissions["/"] = []string{dataprovider.PermAny}
err := dataprovider.AddUser(&u, "", "") err := dataprovider.AddUser(&u, "", "", "")
assert.NoError(t, err) assert.NoError(t, err)
user1, err := dataprovider.UserExists(u.Username, "") user1, err := dataprovider.UserExists(u.Username, "")
assert.NoError(t, err) assert.NoError(t, err)
u.Username = username + "2" u.Username = username + "2"
u.Password = password + "2" u.Password = password + "2"
err = dataprovider.AddUser(&u, "", "") err = dataprovider.AddUser(&u, "", "", "")
assert.NoError(t, err) assert.NoError(t, err)
user2, err := dataprovider.UserExists(u.Username, "") user2, err := dataprovider.UserExists(u.Username, "")
assert.NoError(t, err) assert.NoError(t, err)
u.Username = username + "3" u.Username = username + "3"
u.Password = password + "3" u.Password = password + "3"
err = dataprovider.AddUser(&u, "", "") err = dataprovider.AddUser(&u, "", "", "")
assert.NoError(t, err) assert.NoError(t, err)
user3, err := dataprovider.UserExists(u.Username, "") user3, err := dataprovider.UserExists(u.Username, "")
assert.NoError(t, err) assert.NoError(t, err)
u.Username = username + "4" u.Username = username + "4"
u.Password = password + "4" u.Password = password + "4"
err = dataprovider.AddUser(&u, "", "") err = dataprovider.AddUser(&u, "", "", "")
assert.NoError(t, err) assert.NoError(t, err)
user4, err := dataprovider.UserExists(u.Username, "") user4, err := dataprovider.UserExists(u.Username, "")
assert.NoError(t, err) assert.NoError(t, err)
@ -1355,7 +1355,7 @@ func TestUsersCacheSizeAndExpiration(t *testing.T) {
// now remove user1 after an update // now remove user1 after an update
user1.HomeDir += "_mod" user1.HomeDir += "_mod"
err = dataprovider.UpdateUser(&user1, "", "") err = dataprovider.UpdateUser(&user1, "", "", "")
assert.NoError(t, err) assert.NoError(t, err)
_, ok = dataprovider.GetCachedWebDAVUser(user1.Username) _, ok = dataprovider.GetCachedWebDAVUser(user1.Username)
assert.False(t, ok) assert.False(t, ok)
@ -1414,7 +1414,7 @@ func TestUserCacheIsolation(t *testing.T) {
} }
u.Permissions = make(map[string][]string) u.Permissions = make(map[string][]string)
u.Permissions["/"] = []string{dataprovider.PermAny} u.Permissions["/"] = []string{dataprovider.PermAny}
err := dataprovider.AddUser(&u, "", "") err := dataprovider.AddUser(&u, "", "", "")
assert.NoError(t, err) assert.NoError(t, err)
user, err := dataprovider.UserExists(u.Username, "") user, err := dataprovider.UserExists(u.Username, "")
assert.NoError(t, err) assert.NoError(t, err)

View file

@ -2299,6 +2299,12 @@ paths:
description: 'the event id must not be included among those specified. This is useful for cursor based pagination. Empty or missing means omit this filter. Values must be specified comma separated' description: 'the event id must not be included among those specified. This is useful for cursor based pagination. Empty or missing means omit this filter. Values must be specified comma separated'
explode: false explode: false
required: false required: false
- in: query
name: role
schema:
type: string
description: 'User role. Empty or missing means omit this filter. Ignored if the admin has a role'
required: false
- in: query - in: query
name: limit name: limit
schema: schema:
@ -2417,6 +2423,12 @@ paths:
description: 'the event id must not be included among those specified. This is useful for cursor based pagination. Empty or missing means omit this filter. Values must be specified comma separated' description: 'the event id must not be included among those specified. This is useful for cursor based pagination. Empty or missing means omit this filter. Values must be specified comma separated'
explode: false explode: false
required: false required: false
- in: query
name: role
schema:
type: string
description: 'Admin role. Empty or missing means omit this filter. Ignored if the admin has a role'
required: false
- in: query - in: query
name: limit name: limit
schema: schema:
@ -5482,7 +5494,7 @@ components:
description: Last user login as unix timestamp in milliseconds. It is saved at most once every 10 minutes description: Last user login as unix timestamp in milliseconds. It is saved at most once every 10 minutes
role: role:
type: string type: string
description: 'If set the admin can only administer users with the same role. Role admins cannot have the following permissions: "manage_admins", "manage_apikeys", "manage_system", "manage_event_rules", "manage_roles", "view_events"' description: 'If set the admin can only administer users with the same role. Role admins cannot have the following permissions: "manage_admins", "manage_apikeys", "manage_system", "manage_event_rules", "manage_roles"'
AdminProfile: AdminProfile:
type: object type: object
properties: properties:

View file

@ -1,6 +1,6 @@
#!/bin/bash #!/bin/bash
NFPM_VERSION=2.22.1 NFPM_VERSION=2.22.2
NFPM_ARCH=${NFPM_ARCH:-amd64} NFPM_ARCH=${NFPM_ARCH:-amd64}
if [ -z ${SFTPGO_VERSION} ] if [ -z ${SFTPGO_VERSION} ]
then then

View file

@ -702,6 +702,9 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
<p> <p>
<span class="shortcut"><b>{{`{{IP}}`}}</b></span> => Client IP address. <span class="shortcut"><b>{{`{{IP}}`}}</b></span> => Client IP address.
</p> </p>
<p>
<span class="shortcut"><b>{{`{{Role}}`}}</b></span> => User or admin role.
</p>
<p> <p>
<span class="shortcut"><b>{{`{{Timestamp}}`}}</b></span> => Event timestamp as nanoseconds since epoch. <span class="shortcut"><b>{{`{{Timestamp}}`}}</b></span> => Event timestamp as nanoseconds since epoch.
</p> </p>

View file

@ -3,8 +3,8 @@ module github.com/drakkan/sftpgo/tests/eventsearcher
go 1.19 go 1.19
require ( require (
github.com/hashicorp/go-plugin v1.4.5 github.com/hashicorp/go-plugin v1.4.6
github.com/sftpgo/sdk v0.1.2 github.com/sftpgo/sdk v0.1.3-0.20221203095324-2feef3600930
) )
require ( require (
@ -17,10 +17,10 @@ require (
github.com/mattn/go-isatty v0.0.16 // indirect github.com/mattn/go-isatty v0.0.16 // indirect
github.com/mitchellh/go-testing-interface v1.14.1 // indirect github.com/mitchellh/go-testing-interface v1.14.1 // indirect
github.com/oklog/run v1.1.0 // indirect github.com/oklog/run v1.1.0 // indirect
golang.org/x/net v0.1.0 // indirect golang.org/x/net v0.2.0 // indirect
golang.org/x/sys v0.1.0 // indirect golang.org/x/sys v0.2.0 // indirect
golang.org/x/text v0.4.0 // indirect golang.org/x/text v0.4.0 // indirect
google.golang.org/genproto v0.0.0-20221018160656-63c7b68cfc55 // indirect google.golang.org/genproto v0.0.0-20221202195650-67e5cbc046fd // indirect
google.golang.org/grpc v1.50.1 // indirect google.golang.org/grpc v1.51.0 // indirect
google.golang.org/protobuf v1.28.1 // indirect google.golang.org/protobuf v1.28.1 // indirect
) )

View file

@ -11,8 +11,8 @@ github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/hashicorp/go-hclog v1.3.1 h1:vDwF1DFNZhntP4DAjuTpOw3uEgMUpXh1pB5fW9DqHpo= github.com/hashicorp/go-hclog v1.3.1 h1:vDwF1DFNZhntP4DAjuTpOw3uEgMUpXh1pB5fW9DqHpo=
github.com/hashicorp/go-hclog v1.3.1/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M= github.com/hashicorp/go-hclog v1.3.1/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M=
github.com/hashicorp/go-plugin v1.4.5 h1:oTE/oQR4eghggRg8VY7PAz3dr++VwDNBGCcOfIvHpBo= github.com/hashicorp/go-plugin v1.4.6 h1:MDV3UrKQBM3du3G7MApDGvOsMYy3JQJ4exhSoKBAeVA=
github.com/hashicorp/go-plugin v1.4.5/go.mod h1:viDMjcLJuDui6pXb8U4HVfb8AamCWhHGUjr2IrTF67s= github.com/hashicorp/go-plugin v1.4.6/go.mod h1:viDMjcLJuDui6pXb8U4HVfb8AamCWhHGUjr2IrTF67s=
github.com/hashicorp/yamux v0.1.1 h1:yrQxtgseBDrq9Y652vSRDvsKCJKOUD+GzTS4Y0Y8pvE= github.com/hashicorp/yamux v0.1.1 h1:yrQxtgseBDrq9Y652vSRDvsKCJKOUD+GzTS4Y0Y8pvE=
github.com/hashicorp/yamux v0.1.1/go.mod h1:CtWFDAQgb7dxtzFs4tWbplKIe2jSi3+5vKbgIO0SLnQ= github.com/hashicorp/yamux v0.1.1/go.mod h1:CtWFDAQgb7dxtzFs4tWbplKIe2jSi3+5vKbgIO0SLnQ=
github.com/jhump/protoreflect v1.6.0 h1:h5jfMVslIg6l29nsMs0D8Wj17RDVdNYti0vDN/PZZoE= github.com/jhump/protoreflect v1.6.0 h1:h5jfMVslIg6l29nsMs0D8Wj17RDVdNYti0vDN/PZZoE=
@ -30,28 +30,28 @@ github.com/oklog/run v1.1.0 h1:GEenZ1cK0+q0+wsJew9qUg/DyD8k3JzYsZAi5gYi2mA=
github.com/oklog/run v1.1.0/go.mod h1:sVPdnTZT1zYwAJeCMu2Th4T21pA3FPOQRfWjQlk7DVU= github.com/oklog/run v1.1.0/go.mod h1:sVPdnTZT1zYwAJeCMu2Th4T21pA3FPOQRfWjQlk7DVU=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/sftpgo/sdk v0.1.2 h1:j4V63RuVcYfJAOWV0zRUofa1PlQvKU2ujly0lB7quVA= github.com/sftpgo/sdk v0.1.3-0.20221203095324-2feef3600930 h1:znJ52fQBSAQhacaQvZAfkpTioqpcutDREM/H8NttKzU=
github.com/sftpgo/sdk v0.1.2/go.mod h1:PTp1TfXa+95wHw9yuZu7BA3vmzLqbRkz3gBmMNnwFQg= github.com/sftpgo/sdk v0.1.3-0.20221203095324-2feef3600930/go.mod h1:S2S/Q9fgUpXmL11YoCCt0hyCkEwH1LzQM/6QVsbUCFg=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.7.2 h1:4jaiDzPyXQvSd7D0EjG45355tLlV3VOECpq10pLC+8s= github.com/stretchr/testify v1.7.2 h1:4jaiDzPyXQvSd7D0EjG45355tLlV3VOECpq10pLC+8s=
github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals= github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals=
golang.org/x/net v0.1.0 h1:hZ/3BUoy5aId7sCpA/Tc5lt8DkFgdVS2onTpJsZ/fl0= golang.org/x/net v0.2.0 h1:sZfSu1wtKLGlWI4ZZayP0ck9Y73K1ynO6gqzTdBVdPU=
golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco= golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY=
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.1.0 h1:kunALQeHf1/185U1i0GOB/fy1IPRDDpuoOOqRReG57U= golang.org/x/sys v0.2.0 h1:ljd4t30dBnAvMZaQCevtY0xLLD0A+bRZXbgLMLU1F/A=
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/text v0.4.0 h1:BrVqGRd7+k1DiOgtnFvAkoQEWQvBc25ouMJM6429SFg= golang.org/x/text v0.4.0 h1:BrVqGRd7+k1DiOgtnFvAkoQEWQvBc25ouMJM6429SFg=
golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/genproto v0.0.0-20221018160656-63c7b68cfc55 h1:U1u4KB2kx6KR/aJDjQ97hZ15wQs8ZPvDcGcRynBhkvg= google.golang.org/genproto v0.0.0-20221202195650-67e5cbc046fd h1:OjndDrsik+Gt+e6fs45z9AxiewiKyLKYpA45W5Kpkks=
google.golang.org/genproto v0.0.0-20221018160656-63c7b68cfc55/go.mod h1:45EK0dUbEZ2NHjCeAd2LXmyjAgGUGrpGROgjhC3ADck= google.golang.org/genproto v0.0.0-20221202195650-67e5cbc046fd/go.mod h1:cTsE614GARnxrLsqKREzmNYJACSWWpAWdNMwnD7c2BE=
google.golang.org/grpc v1.50.1 h1:DS/BukOZWp8s6p4Dt/tOaJaTQyPyOoCcrjroHuCeLzY= google.golang.org/grpc v1.51.0 h1:E1eGv1FTqoLIdnBCZufiSHgKjlqG6fKFf6pPWtMTh8U=
google.golang.org/grpc v1.50.1/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= google.golang.org/grpc v1.51.0/go.mod h1:wgNDFcnuBGmxLKI/qn4T+m5BtEBYXJPvibbUPsAIPww=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w= google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w=

View file

@ -31,6 +31,7 @@ type fsEvent struct {
Bucket string `json:"bucket,omitempty"` Bucket string `json:"bucket,omitempty"`
Endpoint string `json:"endpoint,omitempty"` Endpoint string `json:"endpoint,omitempty"`
OpenFlags int `json:"open_flags,omitempty"` OpenFlags int `json:"open_flags,omitempty"`
Role string `json:"role,omitempty"`
InstanceID string `json:"instance_id,omitempty"` InstanceID string `json:"instance_id,omitempty"`
} }
@ -43,6 +44,7 @@ type providerEvent struct {
ObjectType string `json:"object_type"` ObjectType string `json:"object_type"`
ObjectName string `json:"object_name"` ObjectName string `json:"object_name"`
ObjectData []byte `json:"object_data"` ObjectData []byte `json:"object_data"`
Role string `json:"role,omitempty"`
InstanceID string `json:"instance_id,omitempty"` InstanceID string `json:"instance_id,omitempty"`
} }
@ -74,6 +76,7 @@ func (s *Searcher) SearchFsEvents(filters *eventsearcher.FsEventSearch) ([]byte,
Bucket: "bucket", Bucket: "bucket",
Endpoint: "endpoint", Endpoint: "endpoint",
OpenFlags: 512, OpenFlags: 512,
Role: "role1",
}, },
} }
@ -100,6 +103,7 @@ func (s *Searcher) SearchProviderEvents(filters *eventsearcher.ProviderEventSear
ObjectType: "api_key", ObjectType: "api_key",
ObjectName: "123", ObjectName: "123",
ObjectData: []byte("data"), ObjectData: []byte("data"),
Role: "role2",
InstanceID: "instance1", InstanceID: "instance1",
}, },
} }

View file

@ -3,7 +3,7 @@ module github.com/drakkan/sftpgo/tests/ipfilter
go 1.19 go 1.19
require ( require (
github.com/hashicorp/go-plugin v1.4.5 github.com/hashicorp/go-plugin v1.4.6
github.com/sftpgo/sdk v0.1.2 github.com/sftpgo/sdk v0.1.2
) )
@ -16,10 +16,10 @@ require (
github.com/mattn/go-isatty v0.0.16 // indirect github.com/mattn/go-isatty v0.0.16 // indirect
github.com/mitchellh/go-testing-interface v1.14.1 // indirect github.com/mitchellh/go-testing-interface v1.14.1 // indirect
github.com/oklog/run v1.1.0 // indirect github.com/oklog/run v1.1.0 // indirect
golang.org/x/net v0.1.0 // indirect golang.org/x/net v0.2.0 // indirect
golang.org/x/sys v0.1.0 // indirect golang.org/x/sys v0.2.0 // indirect
golang.org/x/text v0.4.0 // indirect golang.org/x/text v0.4.0 // indirect
google.golang.org/genproto v0.0.0-20221018160656-63c7b68cfc55 // indirect google.golang.org/genproto v0.0.0-20221202195650-67e5cbc046fd // indirect
google.golang.org/grpc v1.50.1 // indirect google.golang.org/grpc v1.51.0 // indirect
google.golang.org/protobuf v1.28.1 // indirect google.golang.org/protobuf v1.28.1 // indirect
) )

View file

@ -10,8 +10,8 @@ github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
github.com/google/go-cmp v0.5.6 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ= github.com/google/go-cmp v0.5.6 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ=
github.com/hashicorp/go-hclog v1.3.1 h1:vDwF1DFNZhntP4DAjuTpOw3uEgMUpXh1pB5fW9DqHpo= github.com/hashicorp/go-hclog v1.3.1 h1:vDwF1DFNZhntP4DAjuTpOw3uEgMUpXh1pB5fW9DqHpo=
github.com/hashicorp/go-hclog v1.3.1/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M= github.com/hashicorp/go-hclog v1.3.1/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M=
github.com/hashicorp/go-plugin v1.4.5 h1:oTE/oQR4eghggRg8VY7PAz3dr++VwDNBGCcOfIvHpBo= github.com/hashicorp/go-plugin v1.4.6 h1:MDV3UrKQBM3du3G7MApDGvOsMYy3JQJ4exhSoKBAeVA=
github.com/hashicorp/go-plugin v1.4.5/go.mod h1:viDMjcLJuDui6pXb8U4HVfb8AamCWhHGUjr2IrTF67s= github.com/hashicorp/go-plugin v1.4.6/go.mod h1:viDMjcLJuDui6pXb8U4HVfb8AamCWhHGUjr2IrTF67s=
github.com/hashicorp/yamux v0.1.1 h1:yrQxtgseBDrq9Y652vSRDvsKCJKOUD+GzTS4Y0Y8pvE= github.com/hashicorp/yamux v0.1.1 h1:yrQxtgseBDrq9Y652vSRDvsKCJKOUD+GzTS4Y0Y8pvE=
github.com/hashicorp/yamux v0.1.1/go.mod h1:CtWFDAQgb7dxtzFs4tWbplKIe2jSi3+5vKbgIO0SLnQ= github.com/hashicorp/yamux v0.1.1/go.mod h1:CtWFDAQgb7dxtzFs4tWbplKIe2jSi3+5vKbgIO0SLnQ=
github.com/jhump/protoreflect v1.6.0 h1:h5jfMVslIg6l29nsMs0D8Wj17RDVdNYti0vDN/PZZoE= github.com/jhump/protoreflect v1.6.0 h1:h5jfMVslIg6l29nsMs0D8Wj17RDVdNYti0vDN/PZZoE=
@ -34,24 +34,24 @@ github.com/sftpgo/sdk v0.1.2/go.mod h1:PTp1TfXa+95wHw9yuZu7BA3vmzLqbRkz3gBmMNnwF
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.7.2 h1:4jaiDzPyXQvSd7D0EjG45355tLlV3VOECpq10pLC+8s= github.com/stretchr/testify v1.7.2 h1:4jaiDzPyXQvSd7D0EjG45355tLlV3VOECpq10pLC+8s=
github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals= github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals=
golang.org/x/net v0.1.0 h1:hZ/3BUoy5aId7sCpA/Tc5lt8DkFgdVS2onTpJsZ/fl0= golang.org/x/net v0.2.0 h1:sZfSu1wtKLGlWI4ZZayP0ck9Y73K1ynO6gqzTdBVdPU=
golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco= golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY=
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.1.0 h1:kunALQeHf1/185U1i0GOB/fy1IPRDDpuoOOqRReG57U= golang.org/x/sys v0.2.0 h1:ljd4t30dBnAvMZaQCevtY0xLLD0A+bRZXbgLMLU1F/A=
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/text v0.4.0 h1:BrVqGRd7+k1DiOgtnFvAkoQEWQvBc25ouMJM6429SFg= golang.org/x/text v0.4.0 h1:BrVqGRd7+k1DiOgtnFvAkoQEWQvBc25ouMJM6429SFg=
golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
google.golang.org/genproto v0.0.0-20221018160656-63c7b68cfc55 h1:U1u4KB2kx6KR/aJDjQ97hZ15wQs8ZPvDcGcRynBhkvg= google.golang.org/genproto v0.0.0-20221202195650-67e5cbc046fd h1:OjndDrsik+Gt+e6fs45z9AxiewiKyLKYpA45W5Kpkks=
google.golang.org/genproto v0.0.0-20221018160656-63c7b68cfc55/go.mod h1:45EK0dUbEZ2NHjCeAd2LXmyjAgGUGrpGROgjhC3ADck= google.golang.org/genproto v0.0.0-20221202195650-67e5cbc046fd/go.mod h1:cTsE614GARnxrLsqKREzmNYJACSWWpAWdNMwnD7c2BE=
google.golang.org/grpc v1.50.1 h1:DS/BukOZWp8s6p4Dt/tOaJaTQyPyOoCcrjroHuCeLzY= google.golang.org/grpc v1.51.0 h1:E1eGv1FTqoLIdnBCZufiSHgKjlqG6fKFf6pPWtMTh8U=
google.golang.org/grpc v1.50.1/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= google.golang.org/grpc v1.51.0/go.mod h1:wgNDFcnuBGmxLKI/qn4T+m5BtEBYXJPvibbUPsAIPww=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w= google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w=