user: add a field to indicate whether the password is set
A structure similar to the one used for secrets would be better, but we don't want to break backwards compatibility. Also document that omitting the password field in the request body will preserve the current password when updating a user using the REST API. Added a test case for this. Signed-off-by: Nicola Murino <nicola.murino@gmail.com>
This commit is contained in:
parent
74f05e5305
commit
184b99d500
25 changed files with 192 additions and 77 deletions
26
go.mod
26
go.mod
|
@ -34,17 +34,17 @@ require (
|
||||||
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
|
||||||
github.com/hashicorp/go-hclog v1.5.0
|
github.com/hashicorp/go-hclog v1.5.0
|
||||||
github.com/hashicorp/go-plugin v1.4.10-0.20230321181155-4b35dc2fedaa
|
github.com/hashicorp/go-plugin v1.4.10-0.20230403150917-e889c1ba1044
|
||||||
github.com/hashicorp/go-retryablehttp v0.7.2
|
github.com/hashicorp/go-retryablehttp v0.7.2
|
||||||
github.com/jackc/pgx/v5 v5.3.2-0.20230325152211-ca022267dbbf
|
github.com/jackc/pgx/v5 v5.3.2-0.20230325152211-ca022267dbbf
|
||||||
github.com/jlaffaye/ftp v0.0.0-20201112195030-9aae4d151126
|
github.com/jlaffaye/ftp v0.0.0-20201112195030-9aae4d151126
|
||||||
github.com/klauspost/compress v1.16.3
|
github.com/klauspost/compress v1.16.4
|
||||||
github.com/lestrrat-go/jwx/v2 v2.0.9
|
github.com/lestrrat-go/jwx/v2 v2.0.9
|
||||||
github.com/lithammer/shortuuid/v3 v3.0.7
|
github.com/lithammer/shortuuid/v3 v3.0.7
|
||||||
github.com/mattn/go-sqlite3 v1.14.16
|
github.com/mattn/go-sqlite3 v1.14.16
|
||||||
github.com/mhale/smtpd v0.8.0
|
github.com/mhale/smtpd v0.8.0
|
||||||
github.com/minio/sio v0.3.1
|
github.com/minio/sio v0.3.1
|
||||||
github.com/otiai10/copy v1.9.0
|
github.com/otiai10/copy v1.10.0
|
||||||
github.com/pires/go-proxyproto v0.7.0
|
github.com/pires/go-proxyproto v0.7.0
|
||||||
github.com/pkg/sftp v1.13.6-0.20230213180117-971c283182b6
|
github.com/pkg/sftp v1.13.6-0.20230213180117-971c283182b6
|
||||||
github.com/pquerna/otp v1.4.0
|
github.com/pquerna/otp v1.4.0
|
||||||
|
@ -53,10 +53,10 @@ require (
|
||||||
github.com/rs/cors v1.8.3
|
github.com/rs/cors v1.8.3
|
||||||
github.com/rs/xid v1.4.0
|
github.com/rs/xid v1.4.0
|
||||||
github.com/rs/zerolog v1.29.0
|
github.com/rs/zerolog v1.29.0
|
||||||
github.com/sftpgo/sdk v0.1.3-0.20230331165215-d823c5f1b120
|
github.com/sftpgo/sdk v0.1.3-0.20230406132142-15f26d806282
|
||||||
github.com/shirou/gopsutil/v3 v3.23.3
|
github.com/shirou/gopsutil/v3 v3.23.3
|
||||||
github.com/spf13/afero v1.9.5
|
github.com/spf13/afero v1.9.5
|
||||||
github.com/spf13/cobra v1.6.1
|
github.com/spf13/cobra v1.7.0
|
||||||
github.com/spf13/viper v1.15.0
|
github.com/spf13/viper v1.15.0
|
||||||
github.com/stretchr/testify v1.8.2
|
github.com/stretchr/testify v1.8.2
|
||||||
github.com/studio-b12/gowebdav v0.0.0-20230203202212-3282f94193f2
|
github.com/studio-b12/gowebdav v0.0.0-20230203202212-3282f94193f2
|
||||||
|
@ -71,10 +71,10 @@ require (
|
||||||
golang.org/x/crypto v0.7.0
|
golang.org/x/crypto v0.7.0
|
||||||
golang.org/x/net v0.8.0
|
golang.org/x/net v0.8.0
|
||||||
golang.org/x/oauth2 v0.6.0
|
golang.org/x/oauth2 v0.6.0
|
||||||
golang.org/x/sys v0.6.0
|
golang.org/x/sys v0.7.0
|
||||||
golang.org/x/term v0.6.0
|
golang.org/x/term v0.7.0
|
||||||
golang.org/x/time v0.3.0
|
golang.org/x/time v0.3.0
|
||||||
google.golang.org/api v0.114.0
|
google.golang.org/api v0.116.0
|
||||||
gopkg.in/natefinch/lumberjack.v2 v2.2.1
|
gopkg.in/natefinch/lumberjack.v2 v2.2.1
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -82,8 +82,8 @@ require (
|
||||||
cloud.google.com/go v0.110.0 // indirect
|
cloud.google.com/go v0.110.0 // indirect
|
||||||
cloud.google.com/go/compute v1.19.0 // indirect
|
cloud.google.com/go/compute v1.19.0 // indirect
|
||||||
cloud.google.com/go/compute/metadata v0.2.3 // indirect
|
cloud.google.com/go/compute/metadata v0.2.3 // indirect
|
||||||
cloud.google.com/go/iam v0.13.0 // indirect
|
cloud.google.com/go/iam v1.0.0 // indirect
|
||||||
github.com/Azure/azure-sdk-for-go/sdk/internal v1.2.0 // indirect
|
github.com/Azure/azure-sdk-for-go/sdk/internal v1.3.0 // 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.10 // 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.31 // indirect
|
github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.31 // indirect
|
||||||
|
@ -146,7 +146,7 @@ require (
|
||||||
github.com/prometheus/common v0.42.0 // indirect
|
github.com/prometheus/common v0.42.0 // indirect
|
||||||
github.com/prometheus/procfs v0.9.0 // indirect
|
github.com/prometheus/procfs v0.9.0 // indirect
|
||||||
github.com/russross/blackfriday/v2 v2.1.0 // indirect
|
github.com/russross/blackfriday/v2 v2.1.0 // indirect
|
||||||
github.com/shoenig/go-m1cpu v0.1.4 // indirect
|
github.com/shoenig/go-m1cpu v0.1.5 // indirect
|
||||||
github.com/spf13/cast v1.5.0 // indirect
|
github.com/spf13/cast v1.5.0 // indirect
|
||||||
github.com/spf13/jwalterweatherman v1.1.0 // indirect
|
github.com/spf13/jwalterweatherman v1.1.0 // indirect
|
||||||
github.com/spf13/pflag v1.0.5 // indirect
|
github.com/spf13/pflag v1.0.5 // indirect
|
||||||
|
@ -154,8 +154,8 @@ require (
|
||||||
github.com/tklauser/numcpus v0.6.0 // indirect
|
github.com/tklauser/numcpus v0.6.0 // indirect
|
||||||
github.com/yusufpapurcu/wmi v1.2.2 // indirect
|
github.com/yusufpapurcu/wmi v1.2.2 // indirect
|
||||||
go.opencensus.io v0.24.0 // indirect
|
go.opencensus.io v0.24.0 // indirect
|
||||||
golang.org/x/mod v0.9.0 // indirect
|
golang.org/x/mod v0.10.0 // indirect
|
||||||
golang.org/x/text v0.8.0 // indirect
|
golang.org/x/text v0.9.0 // indirect
|
||||||
golang.org/x/tools v0.7.0 // indirect
|
golang.org/x/tools v0.7.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
|
||||||
|
|
56
go.sum
56
go.sum
|
@ -218,8 +218,8 @@ cloud.google.com/go/iam v0.6.0/go.mod h1:+1AH33ueBne5MzYccyMHtEKqLE4/kJOibtffMHD
|
||||||
cloud.google.com/go/iam v0.7.0/go.mod h1:H5Br8wRaDGNc8XP3keLc4unfUUZeyH3Sfl9XpQEYOeg=
|
cloud.google.com/go/iam v0.7.0/go.mod h1:H5Br8wRaDGNc8XP3keLc4unfUUZeyH3Sfl9XpQEYOeg=
|
||||||
cloud.google.com/go/iam v0.8.0/go.mod h1:lga0/y3iH6CX7sYqypWJ33hf7kkfXJag67naqGESjkE=
|
cloud.google.com/go/iam v0.8.0/go.mod h1:lga0/y3iH6CX7sYqypWJ33hf7kkfXJag67naqGESjkE=
|
||||||
cloud.google.com/go/iam v0.10.0/go.mod h1:nXAECrMt2qHpF6RZUZseteD6QyanL68reN4OXPw0UWM=
|
cloud.google.com/go/iam v0.10.0/go.mod h1:nXAECrMt2qHpF6RZUZseteD6QyanL68reN4OXPw0UWM=
|
||||||
cloud.google.com/go/iam v0.13.0 h1:+CmB+K0J/33d0zSQ9SlFWUeCCEn5XJA0ZMZ3pHE9u8k=
|
cloud.google.com/go/iam v1.0.0 h1:hlQJMovyJJwYjZcTohUH4o1L8Z8kYz+E+W/zktiLCBc=
|
||||||
cloud.google.com/go/iam v0.13.0/go.mod h1:ljOg+rcNfzZ5d6f1nAUJ8ZIxOaZUVoS14bKCtaLZ/D0=
|
cloud.google.com/go/iam v1.0.0/go.mod h1:ikbQ4f1r91wTmBmmOtBCOtuEOei6taatNXytzB7Cxew=
|
||||||
cloud.google.com/go/iap v1.4.0/go.mod h1:RGFwRJdihTINIe4wZ2iCP0zF/qu18ZwyKxrhMhygBEc=
|
cloud.google.com/go/iap v1.4.0/go.mod h1:RGFwRJdihTINIe4wZ2iCP0zF/qu18ZwyKxrhMhygBEc=
|
||||||
cloud.google.com/go/iap v1.5.0/go.mod h1:UH/CGgKd4KyohZL5Pt0jSKE4m3FR51qg6FKQ/z/Ix9A=
|
cloud.google.com/go/iap v1.5.0/go.mod h1:UH/CGgKd4KyohZL5Pt0jSKE4m3FR51qg6FKQ/z/Ix9A=
|
||||||
cloud.google.com/go/ids v1.1.0/go.mod h1:WIuwCaYVOzHIj2OhN9HAwvW+DBdmUAdcWlFxRl+KubM=
|
cloud.google.com/go/ids v1.1.0/go.mod h1:WIuwCaYVOzHIj2OhN9HAwvW+DBdmUAdcWlFxRl+KubM=
|
||||||
|
@ -440,8 +440,8 @@ github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.2.1/go.mod h1:gLa1CL2RNE4s7M
|
||||||
github.com/Azure/azure-sdk-for-go/sdk/internal v1.0.0/go.mod h1:eWRD7oawr1Mu1sLCawqVc0CUiF43ia3qQMxLscsKQ9w=
|
github.com/Azure/azure-sdk-for-go/sdk/internal v1.0.0/go.mod h1:eWRD7oawr1Mu1sLCawqVc0CUiF43ia3qQMxLscsKQ9w=
|
||||||
github.com/Azure/azure-sdk-for-go/sdk/internal v1.1.1/go.mod h1:eWRD7oawr1Mu1sLCawqVc0CUiF43ia3qQMxLscsKQ9w=
|
github.com/Azure/azure-sdk-for-go/sdk/internal v1.1.1/go.mod h1:eWRD7oawr1Mu1sLCawqVc0CUiF43ia3qQMxLscsKQ9w=
|
||||||
github.com/Azure/azure-sdk-for-go/sdk/internal v1.1.2/go.mod h1:eWRD7oawr1Mu1sLCawqVc0CUiF43ia3qQMxLscsKQ9w=
|
github.com/Azure/azure-sdk-for-go/sdk/internal v1.1.2/go.mod h1:eWRD7oawr1Mu1sLCawqVc0CUiF43ia3qQMxLscsKQ9w=
|
||||||
github.com/Azure/azure-sdk-for-go/sdk/internal v1.2.0 h1:leh5DwKv6Ihwi+h60uHtn6UWAxBbZ0q8DwQVMzf61zw=
|
github.com/Azure/azure-sdk-for-go/sdk/internal v1.3.0 h1:sXr+ck84g/ZlZUOZiNELInmMgOsuGwdjjVkEIde0OtY=
|
||||||
github.com/Azure/azure-sdk-for-go/sdk/internal v1.2.0/go.mod h1:eWRD7oawr1Mu1sLCawqVc0CUiF43ia3qQMxLscsKQ9w=
|
github.com/Azure/azure-sdk-for-go/sdk/internal v1.3.0/go.mod h1:okt5dMMTOFjX/aovMlrjvvXoPMBVSPzk9185BT0+eZM=
|
||||||
github.com/Azure/azure-sdk-for-go/sdk/keyvault/azkeys v0.9.0/go.mod h1:EAyXOW1F6BTJPiK2pDvmnvxOHPxoTYWoqBeIlql+QhI=
|
github.com/Azure/azure-sdk-for-go/sdk/keyvault/azkeys v0.9.0/go.mod h1:EAyXOW1F6BTJPiK2pDvmnvxOHPxoTYWoqBeIlql+QhI=
|
||||||
github.com/Azure/azure-sdk-for-go/sdk/keyvault/internal v0.7.0/go.mod h1:9V2j0jn9jDEkCkv8w/bKTNppX/d0FVA1ud77xCIP4KA=
|
github.com/Azure/azure-sdk-for-go/sdk/keyvault/internal v0.7.0/go.mod h1:9V2j0jn9jDEkCkv8w/bKTNppX/d0FVA1ud77xCIP4KA=
|
||||||
github.com/Azure/azure-sdk-for-go/sdk/keyvault/internal v0.7.1/go.mod h1:9V2j0jn9jDEkCkv8w/bKTNppX/d0FVA1ud77xCIP4KA=
|
github.com/Azure/azure-sdk-for-go/sdk/keyvault/internal v0.7.1/go.mod h1:9V2j0jn9jDEkCkv8w/bKTNppX/d0FVA1ud77xCIP4KA=
|
||||||
|
@ -1291,8 +1291,8 @@ github.com/hashicorp/go-multierror v0.0.0-20161216184304-ed905158d874/go.mod h1:
|
||||||
github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk=
|
github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk=
|
||||||
github.com/hashicorp/go-multierror v1.1.0/go.mod h1:spPvp8C1qA32ftKqdAHm4hHTbPw+vmowP0z+KUhOZdA=
|
github.com/hashicorp/go-multierror v1.1.0/go.mod h1:spPvp8C1qA32ftKqdAHm4hHTbPw+vmowP0z+KUhOZdA=
|
||||||
github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM=
|
github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM=
|
||||||
github.com/hashicorp/go-plugin v1.4.10-0.20230321181155-4b35dc2fedaa h1:Sal5OjHO1V800z3WahvH5C8QLlu8UFDZAQXA8o2QVvE=
|
github.com/hashicorp/go-plugin v1.4.10-0.20230403150917-e889c1ba1044 h1:dEFpX4X++vjyeh0mqp0rGbTF2/gXfSc8bOKSTrh0ucg=
|
||||||
github.com/hashicorp/go-plugin v1.4.10-0.20230321181155-4b35dc2fedaa/go.mod h1:6/1TEzT0eQznvI/gV2CM29DLSkAK/e58mUWKVsPaph0=
|
github.com/hashicorp/go-plugin v1.4.10-0.20230403150917-e889c1ba1044/go.mod h1:6/1TEzT0eQznvI/gV2CM29DLSkAK/e58mUWKVsPaph0=
|
||||||
github.com/hashicorp/go-retryablehttp v0.5.3/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es7NDiJgTc6Er0maI1Xs=
|
github.com/hashicorp/go-retryablehttp v0.5.3/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es7NDiJgTc6Er0maI1Xs=
|
||||||
github.com/hashicorp/go-retryablehttp v0.7.1/go.mod h1:vAew36LZh98gCBJNLH42IQ1ER/9wtLZZ8meHqQvEYWY=
|
github.com/hashicorp/go-retryablehttp v0.7.1/go.mod h1:vAew36LZh98gCBJNLH42IQ1ER/9wtLZZ8meHqQvEYWY=
|
||||||
github.com/hashicorp/go-retryablehttp v0.7.2 h1:AcYqCvkpalPnPF2pn0KamgwamS42TqUDDYFRKq/RAd0=
|
github.com/hashicorp/go-retryablehttp v0.7.2 h1:AcYqCvkpalPnPF2pn0KamgwamS42TqUDDYFRKq/RAd0=
|
||||||
|
@ -1346,7 +1346,6 @@ 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/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
|
|
||||||
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
|
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
|
||||||
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
|
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
|
||||||
github.com/influxdata/influxdb1-client v0.0.0-20200827194710-b269163b24ab/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo=
|
github.com/influxdata/influxdb1-client v0.0.0-20200827194710-b269163b24ab/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo=
|
||||||
|
@ -1441,8 +1440,8 @@ github.com/klauspost/compress v1.11.13/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdY
|
||||||
github.com/klauspost/compress v1.13.4/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg=
|
github.com/klauspost/compress v1.13.4/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg=
|
||||||
github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
|
github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
|
||||||
github.com/klauspost/compress v1.15.1/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
|
github.com/klauspost/compress v1.15.1/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
|
||||||
github.com/klauspost/compress v1.16.3 h1:XuJt9zzcnaz6a16/OU53ZjWp/v7/42WcR5t2a0PcNQY=
|
github.com/klauspost/compress v1.16.4 h1:91KN02FnsOYhuunwU4ssRe8lc2JosWmizWa91B5v1PU=
|
||||||
github.com/klauspost/compress v1.16.3/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE=
|
github.com/klauspost/compress v1.16.4/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE=
|
||||||
github.com/klauspost/cpuid/v2 v2.0.4/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
|
github.com/klauspost/cpuid/v2 v2.0.4/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
|
||||||
github.com/klauspost/cpuid/v2 v2.2.4 h1:acbojRNwl3o09bUq+yDCtZFc1aiwaAAxtcn8YkZXnvk=
|
github.com/klauspost/cpuid/v2 v2.2.4 h1:acbojRNwl3o09bUq+yDCtZFc1aiwaAAxtcn8YkZXnvk=
|
||||||
github.com/klauspost/cpuid/v2 v2.2.4/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY=
|
github.com/klauspost/cpuid/v2 v2.2.4/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY=
|
||||||
|
@ -1693,13 +1692,9 @@ github.com/opencontainers/selinux v1.10.0/go.mod h1:2i0OySw99QjzBBQByd1Gr9gSjvuh
|
||||||
github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
|
github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
|
||||||
github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc=
|
github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc=
|
||||||
github.com/openzipkin/zipkin-go v0.2.5/go.mod h1:KpXfKdgRDnnhsxw4pNIH9Md5lyFqKUa4YDFlwRYAMyE=
|
github.com/openzipkin/zipkin-go v0.2.5/go.mod h1:KpXfKdgRDnnhsxw4pNIH9Md5lyFqKUa4YDFlwRYAMyE=
|
||||||
github.com/otiai10/copy v1.9.0 h1:7KFNiCgZ91Ru4qW4CWPf/7jqtxLagGRmIxWldPP9VY4=
|
github.com/otiai10/copy v1.10.0 h1:znyI7l134wNg/wDktoVQPxPkgvhDfGCYUasey+h0rDQ=
|
||||||
github.com/otiai10/copy v1.9.0/go.mod h1:hsfX19wcn0UWIHUQ3/4fHuehhk2UyArQ9dVFAn3FczI=
|
github.com/otiai10/copy v1.10.0/go.mod h1:rSaLseMUsZFFbsFGc7wCJnnkTAvdc5L6VWxPE4308Ww=
|
||||||
github.com/otiai10/curr v0.0.0-20150429015615-9b4961190c95/go.mod h1:9qAhocn7zKJG+0mI8eUu6xqkFDYS2kb2saOteoSB3cE=
|
github.com/otiai10/mint v1.5.1 h1:XaPLeE+9vGbuyEHem1JNk3bYc7KKqyI/na0/mLd/Kks=
|
||||||
github.com/otiai10/curr v1.0.0/go.mod h1:LskTG5wDwr8Rs+nNQ+1LlxRjAtTZZjtJW4rMXl6j4vs=
|
|
||||||
github.com/otiai10/mint v1.3.0/go.mod h1:F5AjcsTsWUqX+Na9fpHb52P8pcRX2CI6A3ctIT91xUo=
|
|
||||||
github.com/otiai10/mint v1.4.0 h1:umwcf7gbpEwf7WFzqmWwSv0CzbeMsae2u9ZvpP8j2q4=
|
|
||||||
github.com/otiai10/mint v1.4.0/go.mod h1:gifjb2MYOoULtKLqUAEILUG/9KONW6f7YsJ6vQLTlFI=
|
|
||||||
github.com/ovh/go-ovh v1.3.0/go.mod h1:AxitLZ5HBRPyUd+Zl60Ajaag+rNTdVXWIkzfrVuTXWA=
|
github.com/ovh/go-ovh v1.3.0/go.mod h1:AxitLZ5HBRPyUd+Zl60Ajaag+rNTdVXWIkzfrVuTXWA=
|
||||||
github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
|
github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
|
||||||
github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
|
github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
|
||||||
|
@ -1840,12 +1835,13 @@ 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.20230331165215-d823c5f1b120 h1:HSuWbDcEQidm1nXwxLBAUzEYtG0Zy93I+w0PV7DxAGs=
|
github.com/sftpgo/sdk v0.1.3-0.20230406132142-15f26d806282 h1:6RTcCXSQ0+8G4T4eGF6aCkK9+tQ96dhpDb7tAaMRhdU=
|
||||||
github.com/sftpgo/sdk v0.1.3-0.20230331165215-d823c5f1b120/go.mod h1:3IX7CxQwZM27z3NCZYgEQGIglTKWWfHlatxdp3wGzv4=
|
github.com/sftpgo/sdk v0.1.3-0.20230406132142-15f26d806282/go.mod h1:NZ7CYZf0VuQ2sQHhBEnUVmzQJ/N0l0Nyq9tGLAKf14s=
|
||||||
github.com/shirou/gopsutil/v3 v3.23.3 h1:Syt5vVZXUDXPEXpIBt5ziWsJ4LdSAAxF4l/xZeQgSEE=
|
github.com/shirou/gopsutil/v3 v3.23.3 h1:Syt5vVZXUDXPEXpIBt5ziWsJ4LdSAAxF4l/xZeQgSEE=
|
||||||
github.com/shirou/gopsutil/v3 v3.23.3/go.mod h1:lSBNN6t3+D6W5e5nXTxc8KIMMVxAcS+6IJlffjRRlMU=
|
github.com/shirou/gopsutil/v3 v3.23.3/go.mod h1:lSBNN6t3+D6W5e5nXTxc8KIMMVxAcS+6IJlffjRRlMU=
|
||||||
github.com/shoenig/go-m1cpu v0.1.4 h1:SZPIgRM2sEF9NJy50mRHu9PKGwxyyTTJIWvCtgVbozs=
|
|
||||||
github.com/shoenig/go-m1cpu v0.1.4/go.mod h1:Wwvst4LR89UxjeFtLRMrpgRiyY4xPsejnVZym39dbAQ=
|
github.com/shoenig/go-m1cpu v0.1.4/go.mod h1:Wwvst4LR89UxjeFtLRMrpgRiyY4xPsejnVZym39dbAQ=
|
||||||
|
github.com/shoenig/go-m1cpu v0.1.5 h1:LF57Z/Fpb/WdGLjt2HZilNnmZOxg/q2bSKTQhgbrLrQ=
|
||||||
|
github.com/shoenig/go-m1cpu v0.1.5/go.mod h1:Wwvst4LR89UxjeFtLRMrpgRiyY4xPsejnVZym39dbAQ=
|
||||||
github.com/shoenig/test v0.6.0/go.mod h1:xYtyGBC5Q3kzCNyJg/SjgNpfAa2kvmgA0i5+lQso8x0=
|
github.com/shoenig/test v0.6.0/go.mod h1:xYtyGBC5Q3kzCNyJg/SjgNpfAa2kvmgA0i5+lQso8x0=
|
||||||
github.com/shoenig/test v0.6.3 h1:GVXWJFk9PiOjN0KoJ7VrJGH6uLPnqxR7/fe3HUPfE0c=
|
github.com/shoenig/test v0.6.3 h1:GVXWJFk9PiOjN0KoJ7VrJGH6uLPnqxR7/fe3HUPfE0c=
|
||||||
github.com/shoenig/test v0.6.3/go.mod h1:byHiCGXqrVaflBLAMq/srcZIHynQPQgeyvkvXnjqq0k=
|
github.com/shoenig/test v0.6.3/go.mod h1:byHiCGXqrVaflBLAMq/srcZIHynQPQgeyvkvXnjqq0k=
|
||||||
|
@ -1886,8 +1882,8 @@ github.com/spf13/cobra v0.0.2-0.20171109065643-2da4a54c5cee/go.mod h1:1l0Ry5zgKv
|
||||||
github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
|
github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
|
||||||
github.com/spf13/cobra v1.0.0/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE=
|
github.com/spf13/cobra v1.0.0/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE=
|
||||||
github.com/spf13/cobra v1.1.3/go.mod h1:pGADOWyqRD/YMrPZigI/zbliZ2wVD/23d+is3pSWzOo=
|
github.com/spf13/cobra v1.1.3/go.mod h1:pGADOWyqRD/YMrPZigI/zbliZ2wVD/23d+is3pSWzOo=
|
||||||
github.com/spf13/cobra v1.6.1 h1:o94oiPyS4KD1mPy2fmcYYHHfCxLqYjJOhGsCHFZtEzA=
|
github.com/spf13/cobra v1.7.0 h1:hyqWnYt1ZQShIddO5kBpj3vu05/++x6tJ6dg8EC572I=
|
||||||
github.com/spf13/cobra v1.6.1/go.mod h1:IOw/AERYS7UzyrGinqmz6HLUo219MORXGxhbaJUqzrY=
|
github.com/spf13/cobra v1.7.0/go.mod h1:uLxZILRyS/50WlhOIKD7W6V5bgeIt+4sICxh6uRMrb0=
|
||||||
github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
|
github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
|
||||||
github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk=
|
github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk=
|
||||||
github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo=
|
github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo=
|
||||||
|
@ -2158,8 +2154,8 @@ golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91
|
||||||
golang.org/x/mod v0.6.0/go.mod h1:4mET923SAdbXp2ki8ey+zGs1SLqsuM2Y0uvdZR/fUNI=
|
golang.org/x/mod v0.6.0/go.mod h1:4mET923SAdbXp2ki8ey+zGs1SLqsuM2Y0uvdZR/fUNI=
|
||||||
golang.org/x/mod v0.7.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
golang.org/x/mod v0.7.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||||
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||||
golang.org/x/mod v0.9.0 h1:KENHtAZL2y3NLMYZeHY9DW8HW8V+kQyJsY/V9JlKvCs=
|
golang.org/x/mod v0.10.0 h1:lFO9qtOdlre5W1jxS3r/4szv2/6iXxScdzjoBMXNhYk=
|
||||||
golang.org/x/mod v0.9.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
golang.org/x/mod v0.10.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
|
@ -2441,7 +2437,6 @@ golang.org/x/sys v0.0.0-20220610221304-9f5ed59c137d/go.mod h1:oPkhp1MJrh7nUepCBc
|
||||||
golang.org/x/sys v0.0.0-20220615213510-4f61da869c0c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220615213510-4f61da869c0c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20220624220833-87e55d714810/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220624220833-87e55d714810/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20220704084225-05e143d24a9e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220704084225-05e143d24a9e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
|
||||||
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20220731174439-a90be440212d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220731174439-a90be440212d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
@ -2453,8 +2448,9 @@ golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.6.0 h1:MVltZSvRTcU2ljQOhs94SXPftV6DCNnZViHeQps87pQ=
|
|
||||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.7.0 h1:3jlCCIQZPdOYu1h8BkNvLz8Kgwtae2cagcG/VamtZRU=
|
||||||
|
golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||||
golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||||
golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||||
|
@ -2464,8 +2460,9 @@ golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc=
|
||||||
golang.org/x/term v0.3.0/go.mod h1:q750SLmJuPmVoN1blW3UFBPREJfb1KmY3vwxfr+nFDA=
|
golang.org/x/term v0.3.0/go.mod h1:q750SLmJuPmVoN1blW3UFBPREJfb1KmY3vwxfr+nFDA=
|
||||||
golang.org/x/term v0.4.0/go.mod h1:9P2UbLfCdcvo3p/nzKvsmas4TnlujnuoV9hGgYzW1lQ=
|
golang.org/x/term v0.4.0/go.mod h1:9P2UbLfCdcvo3p/nzKvsmas4TnlujnuoV9hGgYzW1lQ=
|
||||||
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
||||||
golang.org/x/term v0.6.0 h1:clScbb1cHjoCkyRbWwBEUZ5H/tIFu5TAXIqaZD0Gcjw=
|
|
||||||
golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U=
|
golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U=
|
||||||
|
golang.org/x/term v0.7.0 h1:BEvjmm5fURWqcfbSKTdpkDXYBrUS1c0m8agp14W48vQ=
|
||||||
|
golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY=
|
||||||
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
|
@ -2480,8 +2477,9 @@ golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||||
golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||||
golang.org/x/text v0.6.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
golang.org/x/text v0.6.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||||
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||||
golang.org/x/text v0.8.0 h1:57P1ETyNKtuIjB4SRd15iJxuhj8Gc416Y78H3qgMh68=
|
|
||||||
golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
||||||
|
golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE=
|
||||||
|
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
||||||
golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
|
@ -2663,8 +2661,8 @@ google.golang.org/api v0.106.0/go.mod h1:2Ts0XTHNVWxypznxWOYUeI4g3WdP9Pk2Qk58+a/
|
||||||
google.golang.org/api v0.107.0/go.mod h1:2Ts0XTHNVWxypznxWOYUeI4g3WdP9Pk2Qk58+a/O9MY=
|
google.golang.org/api v0.107.0/go.mod h1:2Ts0XTHNVWxypznxWOYUeI4g3WdP9Pk2Qk58+a/O9MY=
|
||||||
google.golang.org/api v0.108.0/go.mod h1:2Ts0XTHNVWxypznxWOYUeI4g3WdP9Pk2Qk58+a/O9MY=
|
google.golang.org/api v0.108.0/go.mod h1:2Ts0XTHNVWxypznxWOYUeI4g3WdP9Pk2Qk58+a/O9MY=
|
||||||
google.golang.org/api v0.110.0/go.mod h1:7FC4Vvx1Mooxh8C5HWjzZHcavuS2f6pmJpZx60ca7iI=
|
google.golang.org/api v0.110.0/go.mod h1:7FC4Vvx1Mooxh8C5HWjzZHcavuS2f6pmJpZx60ca7iI=
|
||||||
google.golang.org/api v0.114.0 h1:1xQPji6cO2E2vLiI+C/XiFAnsn1WV3mjaEwGLhi3grE=
|
google.golang.org/api v0.116.0 h1:09tOPVufPwfm5W4aA8EizGHJ7BcoRDsIareM2a15gO4=
|
||||||
google.golang.org/api v0.114.0/go.mod h1:ifYI2ZsFK6/uGddGfAD5BMxlnkBqCmqHSDUVi45N5Yg=
|
google.golang.org/api v0.116.0/go.mod h1:9cD4/t6uvd9naoEJFA+M96d0IuB6BqFuyhpw68+mRGg=
|
||||||
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
||||||
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||||
google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||||
|
|
|
@ -342,6 +342,17 @@ func (c *BaseConnection) CheckParentDirs(virtualPath string) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetCreateChecks returns the checks for creating new files
|
||||||
|
func (c *BaseConnection) GetCreateChecks(virtualPath string, isNewFile bool) int {
|
||||||
|
if !isNewFile {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
if !c.User.HasPerm(dataprovider.PermCreateDirs, path.Dir(virtualPath)) {
|
||||||
|
return vfs.CheckParentDir
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
// CreateDir creates a new directory at the specified fsPath
|
// CreateDir creates a new directory at the specified fsPath
|
||||||
func (c *BaseConnection) CreateDir(virtualPath string, checkFilePatterns bool) error {
|
func (c *BaseConnection) CreateDir(virtualPath string, checkFilePatterns bool) error {
|
||||||
if !c.User.HasPerm(dataprovider.PermCreateDirs, path.Dir(virtualPath)) {
|
if !c.User.HasPerm(dataprovider.PermCreateDirs, path.Dir(virtualPath)) {
|
||||||
|
|
|
@ -917,8 +917,7 @@ func getFileWriter(conn *BaseConnection, virtualPath string, expectedSize int64)
|
||||||
if err := checkWriterPermsAndQuota(conn, virtualPath, numFiles, expectedSize, truncatedSize); err != nil {
|
if err := checkWriterPermsAndQuota(conn, virtualPath, numFiles, expectedSize, truncatedSize); err != nil {
|
||||||
return nil, numFiles, truncatedSize, nil, err
|
return nil, numFiles, truncatedSize, nil, err
|
||||||
}
|
}
|
||||||
|
f, w, cancelFn, err := fs.Create(fsPath, 0, conn.GetCreateChecks(virtualPath, numFiles == 1))
|
||||||
f, w, cancelFn, err := fs.Create(fsPath, 0)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, numFiles, truncatedSize, nil, conn.GetFsError(fs, err)
|
return nil, numFiles, truncatedSize, nil, conn.GetFsError(fs, err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -3019,6 +3019,7 @@ func ValidateFolder(folder *vfs.BaseVirtualFolder) error {
|
||||||
// FIXME: this should be defined as User struct method
|
// FIXME: this should be defined as User struct method
|
||||||
func ValidateUser(user *User) error {
|
func ValidateUser(user *User) error {
|
||||||
user.OIDCCustomFields = nil
|
user.OIDCCustomFields = nil
|
||||||
|
user.HasPassword = false
|
||||||
user.SetEmptySecretsIfNil()
|
user.SetEmptySecretsIfNil()
|
||||||
buildUserHomeDir(user)
|
buildUserHomeDir(user)
|
||||||
if err := validateBaseParams(user); err != nil {
|
if err := validateBaseParams(user); err != nil {
|
||||||
|
|
|
@ -1566,6 +1566,7 @@ func (u *User) CountUnusedRecoveryCodes() int {
|
||||||
|
|
||||||
// SetEmptySecretsIfNil sets the secrets to empty if nil
|
// SetEmptySecretsIfNil sets the secrets to empty if nil
|
||||||
func (u *User) SetEmptySecretsIfNil() {
|
func (u *User) SetEmptySecretsIfNil() {
|
||||||
|
u.HasPassword = u.Password != ""
|
||||||
u.FsConfig.SetEmptySecretsIfNil()
|
u.FsConfig.SetEmptySecretsIfNil()
|
||||||
for idx := range u.VirtualFolders {
|
for idx := range u.VirtualFolders {
|
||||||
vfolder := &u.VirtualFolders[idx]
|
vfolder := &u.VirtualFolders[idx]
|
||||||
|
@ -1931,6 +1932,7 @@ func (u *User) getACopy() User {
|
||||||
Email: u.Email,
|
Email: u.Email,
|
||||||
Password: u.Password,
|
Password: u.Password,
|
||||||
PublicKeys: pubKeys,
|
PublicKeys: pubKeys,
|
||||||
|
HasPassword: u.HasPassword,
|
||||||
HomeDir: u.HomeDir,
|
HomeDir: u.HomeDir,
|
||||||
UID: u.UID,
|
UID: u.UID,
|
||||||
GID: u.GID,
|
GID: u.GID,
|
||||||
|
|
|
@ -408,7 +408,7 @@ func (c *Connection) handleFTPUploadToNewFile(fs vfs.Fs, flags int, resolvedPath
|
||||||
c.Log(logger.LevelDebug, "upload for file %q denied by pre action: %v", requestPath, err)
|
c.Log(logger.LevelDebug, "upload for file %q denied by pre action: %v", requestPath, err)
|
||||||
return nil, ftpserver.ErrFileNameNotAllowed
|
return nil, ftpserver.ErrFileNameNotAllowed
|
||||||
}
|
}
|
||||||
file, w, cancelFn, err := fs.Create(filePath, flags)
|
file, w, cancelFn, err := fs.Create(filePath, flags, c.GetCreateChecks(requestPath, true))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.Log(logger.LevelError, "error creating file %q, flags %v: %+v", resolvedPath, flags, err)
|
c.Log(logger.LevelError, "error creating file %q, flags %v: %+v", resolvedPath, flags, err)
|
||||||
return nil, c.GetFsError(fs, err)
|
return nil, c.GetFsError(fs, err)
|
||||||
|
@ -463,7 +463,7 @@ func (c *Connection) handleFTPUploadToExistingFile(fs vfs.Fs, flags int, resolve
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
file, w, cancelFn, err := fs.Create(filePath, flags)
|
file, w, cancelFn, err := fs.Create(filePath, flags, c.GetCreateChecks(requestPath, false))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.Log(logger.LevelError, "error opening existing file, flags: %v, source: %q, err: %+v", flags, filePath, err)
|
c.Log(logger.LevelError, "error opening existing file, flags: %v, source: %q, err: %+v", flags, filePath, err)
|
||||||
return nil, c.GetFsError(fs, err)
|
return nil, c.GetFsError(fs, err)
|
||||||
|
|
|
@ -201,7 +201,7 @@ func (c *Connection) handleUploadFile(fs vfs.Fs, resolvedPath, filePath, request
|
||||||
|
|
||||||
maxWriteSize, _ := c.GetMaxWriteSize(diskQuota, false, fileSize, fs.IsUploadResumeSupported())
|
maxWriteSize, _ := c.GetMaxWriteSize(diskQuota, false, fileSize, fs.IsUploadResumeSupported())
|
||||||
|
|
||||||
file, w, cancelFn, err := fs.Create(filePath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC)
|
file, w, cancelFn, err := fs.Create(filePath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, c.GetCreateChecks(requestPath, isNewFile))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.Log(logger.LevelError, "error opening existing file, source: %q, err: %+v", filePath, err)
|
c.Log(logger.LevelError, "error opening existing file, source: %q, err: %+v", filePath, err)
|
||||||
return nil, c.GetFsError(fs, err)
|
return nil, c.GetFsError(fs, err)
|
||||||
|
|
|
@ -613,6 +613,7 @@ func TestBasicUserHandling(t *testing.T) {
|
||||||
user, _, err = httpdtest.GetUserByUsername(defaultUsername, http.StatusOK)
|
user, _, err = httpdtest.GetUserByUsername(defaultUsername, http.StatusOK)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Nil(t, user.OIDCCustomFields)
|
assert.Nil(t, user.OIDCCustomFields)
|
||||||
|
assert.True(t, user.HasPassword)
|
||||||
|
|
||||||
user.Email = "invalid@email"
|
user.Email = "invalid@email"
|
||||||
_, body, err := httpdtest.UpdateUser(user, http.StatusBadRequest, "")
|
_, body, err := httpdtest.UpdateUser(user, http.StatusBadRequest, "")
|
||||||
|
@ -5578,6 +5579,7 @@ func TestUserHiddenFields(t *testing.T) {
|
||||||
user, _, err := httpdtest.GetUserByUsername(username, http.StatusOK)
|
user, _, err := httpdtest.GetUserByUsername(username, http.StatusOK)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Empty(t, user.Password)
|
assert.Empty(t, user.Password)
|
||||||
|
assert.True(t, user.HasPassword)
|
||||||
}
|
}
|
||||||
user1, _, err = httpdtest.GetUserByUsername(user1.Username, http.StatusOK)
|
user1, _, err = httpdtest.GetUserByUsername(user1.Username, http.StatusOK)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
@ -5949,6 +5951,11 @@ func TestGetUsers(t *testing.T) {
|
||||||
users, _, err := httpdtest.GetUsers(0, 0, http.StatusOK)
|
users, _, err := httpdtest.GetUsers(0, 0, http.StatusOK)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.GreaterOrEqual(t, len(users), 2)
|
assert.GreaterOrEqual(t, len(users), 2)
|
||||||
|
for _, user := range users {
|
||||||
|
if u.Username == user.Username {
|
||||||
|
assert.True(t, user.HasPassword)
|
||||||
|
}
|
||||||
|
}
|
||||||
users, _, err = httpdtest.GetUsers(1, 0, http.StatusOK)
|
users, _, err = httpdtest.GetUsers(1, 0, http.StatusOK)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Equal(t, 1, len(users))
|
assert.Equal(t, 1, len(users))
|
||||||
|
@ -6628,6 +6635,59 @@ func TestNamingRules(t *testing.T) {
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestUserPassword(t *testing.T) {
|
||||||
|
u := getTestUser()
|
||||||
|
u.Password = ""
|
||||||
|
user, _, err := httpdtest.AddUser(u, http.StatusCreated)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.False(t, user.HasPassword)
|
||||||
|
user, _, err = httpdtest.UpdateUser(user, http.StatusOK, "")
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.False(t, user.HasPassword)
|
||||||
|
|
||||||
|
user.Password = defaultPassword
|
||||||
|
user, _, err = httpdtest.UpdateUser(user, http.StatusOK, "")
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.True(t, user.HasPassword)
|
||||||
|
|
||||||
|
token, err := getJWTAPITokenFromTestServer(defaultTokenAuthUser, defaultTokenAuthPass)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
rawUser := map[string]any{
|
||||||
|
"username": user.Username,
|
||||||
|
"home_dir": filepath.Join(homeBasePath, defaultUsername),
|
||||||
|
"permissions": map[string][]string{
|
||||||
|
"/": {"*"},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
userAsJSON, err := json.Marshal(rawUser)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
req, err := http.NewRequest(http.MethodPut, path.Join(userPath, user.Username), bytes.NewBuffer(userAsJSON))
|
||||||
|
assert.NoError(t, err)
|
||||||
|
setBearerForReq(req, token)
|
||||||
|
rr := executeRequest(req)
|
||||||
|
checkResponseCode(t, http.StatusOK, rr)
|
||||||
|
// the previous password must be preserved
|
||||||
|
user, _, err = httpdtest.GetUserByUsername(user.Username, http.StatusOK)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.True(t, user.HasPassword)
|
||||||
|
// update the user with an empty password field, the password will be unset
|
||||||
|
rawUser["password"] = ""
|
||||||
|
userAsJSON, err = json.Marshal(rawUser)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
req, err = http.NewRequest(http.MethodPut, path.Join(userPath, user.Username), bytes.NewBuffer(userAsJSON))
|
||||||
|
assert.NoError(t, err)
|
||||||
|
setBearerForReq(req, token)
|
||||||
|
rr = executeRequest(req)
|
||||||
|
checkResponseCode(t, http.StatusOK, rr)
|
||||||
|
user, _, err = httpdtest.GetUserByUsername(user.Username, http.StatusOK)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.False(t, user.HasPassword)
|
||||||
|
|
||||||
|
_, err = httpdtest.RemoveUser(user, http.StatusOK)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
func TestSaveErrors(t *testing.T) {
|
func TestSaveErrors(t *testing.T) {
|
||||||
err := dataprovider.Close()
|
err := dataprovider.Close()
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
|
@ -175,7 +175,7 @@ func AddUser(user dataprovider.User, expectedStatusCode int) (dataprovider.User,
|
||||||
func UpdateUserWithJSON(user dataprovider.User, expectedStatusCode int, disconnect string, userAsJSON []byte) (dataprovider.User, []byte, error) {
|
func UpdateUserWithJSON(user dataprovider.User, expectedStatusCode int, disconnect string, userAsJSON []byte) (dataprovider.User, []byte, error) {
|
||||||
var newUser dataprovider.User
|
var newUser dataprovider.User
|
||||||
var body []byte
|
var body []byte
|
||||||
url, err := addDisconnectQueryParam(buildURLRelativeToBase(userPath, url.PathEscape(user.Username)), disconnect)
|
url, err := addUpdateUserQueryParams(buildURLRelativeToBase(userPath, url.PathEscape(user.Username)), disconnect)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return user, body, err
|
return user, body, err
|
||||||
}
|
}
|
||||||
|
@ -2900,13 +2900,13 @@ func addModeQueryParam(rawurl, mode string) (*url.URL, error) {
|
||||||
return url, err
|
return url, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func addDisconnectQueryParam(rawurl, disconnect string) (*url.URL, error) {
|
func addUpdateUserQueryParams(rawurl, disconnect string) (*url.URL, error) {
|
||||||
url, err := url.Parse(rawurl)
|
url, err := url.Parse(rawurl)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
q := url.Query()
|
q := url.Query()
|
||||||
if len(disconnect) > 0 {
|
if disconnect != "" {
|
||||||
q.Add("disconnect", disconnect)
|
q.Add("disconnect", disconnect)
|
||||||
}
|
}
|
||||||
url.RawQuery = q.Encode()
|
url.RawQuery = q.Encode()
|
||||||
|
|
|
@ -407,7 +407,7 @@ func (c *Connection) handleSFTPUploadToNewFile(fs vfs.Fs, pflags sftp.FileOpenFl
|
||||||
}
|
}
|
||||||
|
|
||||||
osFlags := getOSOpenFlags(pflags)
|
osFlags := getOSOpenFlags(pflags)
|
||||||
file, w, cancelFn, err := fs.Create(filePath, osFlags)
|
file, w, cancelFn, err := fs.Create(filePath, osFlags, c.GetCreateChecks(requestPath, true))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.Log(logger.LevelError, "error creating file %q, os flags %d, pflags %+v: %+v", resolvedPath, osFlags, pflags, err)
|
c.Log(logger.LevelError, "error creating file %q, os flags %d, pflags %+v: %+v", resolvedPath, osFlags, pflags, err)
|
||||||
return nil, c.GetFsError(fs, err)
|
return nil, c.GetFsError(fs, err)
|
||||||
|
@ -463,7 +463,7 @@ func (c *Connection) handleSFTPUploadToExistingFile(fs vfs.Fs, pflags sftp.FileO
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
file, w, cancelFn, err := fs.Create(filePath, osFlags)
|
file, w, cancelFn, err := fs.Create(filePath, osFlags, c.GetCreateChecks(requestPath, false))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.Log(logger.LevelError, "error opening existing file, os flags %v, pflags: %+v, source: %q, err: %+v",
|
c.Log(logger.LevelError, "error opening existing file, os flags %v, pflags: %+v, source: %q, err: %+v",
|
||||||
osFlags, pflags, filePath, err)
|
osFlags, pflags, filePath, err)
|
||||||
|
|
|
@ -245,7 +245,7 @@ func (c *scpCommand) handleUploadFile(fs vfs.Fs, resolvedPath, filePath string,
|
||||||
|
|
||||||
maxWriteSize, _ := c.connection.GetMaxWriteSize(diskQuota, false, fileSize, fs.IsUploadResumeSupported())
|
maxWriteSize, _ := c.connection.GetMaxWriteSize(diskQuota, false, fileSize, fs.IsUploadResumeSupported())
|
||||||
|
|
||||||
file, w, cancelFn, err := fs.Create(filePath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC)
|
file, w, cancelFn, err := fs.Create(filePath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, c.connection.GetCreateChecks(requestPath, isNewFile))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.connection.Log(logger.LevelError, "error creating file %q: %v", resolvedPath, err)
|
c.connection.Log(logger.LevelError, "error creating file %q: %v", resolvedPath, err)
|
||||||
c.sendErrorMessage(fs, err)
|
c.sendErrorMessage(fs, err)
|
||||||
|
|
|
@ -227,7 +227,13 @@ func (fs *AzureBlobFs) Open(name string, offset int64) (File, *pipeat.PipeReader
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create creates or opens the named file for writing
|
// Create creates or opens the named file for writing
|
||||||
func (fs *AzureBlobFs) Create(name string, flag int) (File, *PipeWriter, func(), error) {
|
func (fs *AzureBlobFs) Create(name string, flag, checks int) (File, *PipeWriter, func(), error) {
|
||||||
|
if checks&CheckParentDir != 0 {
|
||||||
|
_, err := fs.Stat(path.Dir(name))
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
r, w, err := pipeat.PipeInDir(fs.localTempDir)
|
r, w, err := pipeat.PipeInDir(fs.localTempDir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, nil, err
|
return nil, nil, nil, err
|
||||||
|
@ -269,6 +275,10 @@ func (fs *AzureBlobFs) Rename(source, target string) (int, int64, error) {
|
||||||
if source == target {
|
if source == target {
|
||||||
return -1, -1, nil
|
return -1, -1, nil
|
||||||
}
|
}
|
||||||
|
_, err := fs.Stat(path.Dir(target))
|
||||||
|
if err != nil {
|
||||||
|
return -1, -1, err
|
||||||
|
}
|
||||||
fi, err := fs.Stat(source)
|
fi, err := fs.Stat(source)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return -1, -1, err
|
return -1, -1, err
|
||||||
|
@ -880,7 +890,7 @@ func (fs *AzureBlobFs) renameInternal(source, target string, fi os.FileInfo) (in
|
||||||
}
|
}
|
||||||
|
|
||||||
func (fs *AzureBlobFs) mkdirInternal(name string) error {
|
func (fs *AzureBlobFs) mkdirInternal(name string) error {
|
||||||
_, w, _, err := fs.Create(name, -1)
|
_, w, _, err := fs.Create(name, -1, 0)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -150,7 +150,7 @@ func (fs *CryptFs) Open(name string, offset int64) (File, *pipeat.PipeReaderAt,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create creates or opens the named file for writing
|
// Create creates or opens the named file for writing
|
||||||
func (fs *CryptFs) Create(name string, flag int) (File, *PipeWriter, func(), error) {
|
func (fs *CryptFs) Create(name string, flag, _ int) (File, *PipeWriter, func(), error) {
|
||||||
var err error
|
var err error
|
||||||
var f *os.File
|
var f *os.File
|
||||||
if flag == 0 {
|
if flag == 0 {
|
||||||
|
|
|
@ -161,7 +161,13 @@ func (fs *GCSFs) Open(name string, offset int64) (File, *pipeat.PipeReaderAt, fu
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create creates or opens the named file for writing
|
// Create creates or opens the named file for writing
|
||||||
func (fs *GCSFs) Create(name string, flag int) (File, *PipeWriter, func(), error) {
|
func (fs *GCSFs) Create(name string, flag, checks int) (File, *PipeWriter, func(), error) {
|
||||||
|
if checks&CheckParentDir != 0 {
|
||||||
|
_, err := fs.Stat(path.Dir(name))
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
r, w, err := pipeat.PipeInDir(fs.localTempDir)
|
r, w, err := pipeat.PipeInDir(fs.localTempDir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, nil, err
|
return nil, nil, nil, err
|
||||||
|
@ -227,6 +233,10 @@ func (fs *GCSFs) Rename(source, target string) (int, int64, error) {
|
||||||
if source == target {
|
if source == target {
|
||||||
return -1, -1, nil
|
return -1, -1, nil
|
||||||
}
|
}
|
||||||
|
_, err := fs.Stat(path.Dir(target))
|
||||||
|
if err != nil {
|
||||||
|
return -1, -1, err
|
||||||
|
}
|
||||||
fi, err := fs.getObjectStat(source)
|
fi, err := fs.getObjectStat(source)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return -1, -1, err
|
return -1, -1, err
|
||||||
|
@ -704,7 +714,7 @@ func (fs *GCSFs) resolve(name, prefix, contentType string) (string, bool) {
|
||||||
return result, isDir
|
return result, isDir
|
||||||
}
|
}
|
||||||
|
|
||||||
// getObjectStat returns the stat result and the real object name as first value
|
// getObjectStat returns the stat result
|
||||||
func (fs *GCSFs) getObjectStat(name string) (os.FileInfo, error) {
|
func (fs *GCSFs) getObjectStat(name string) (os.FileInfo, error) {
|
||||||
attrs, err := fs.headObject(name)
|
attrs, err := fs.headObject(name)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
|
@ -823,7 +833,7 @@ func (fs *GCSFs) mkdirInternal(name string) error {
|
||||||
if !strings.HasSuffix(name, "/") {
|
if !strings.HasSuffix(name, "/") {
|
||||||
name += "/"
|
name += "/"
|
||||||
}
|
}
|
||||||
_, w, _, err := fs.Create(name, -1)
|
_, w, _, err := fs.Create(name, -1, 0)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -330,7 +330,7 @@ func (fs *HTTPFs) Open(name string, offset int64) (File, *pipeat.PipeReaderAt, f
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create creates or opens the named file for writing
|
// Create creates or opens the named file for writing
|
||||||
func (fs *HTTPFs) Create(name string, flag int) (File, *PipeWriter, func(), error) {
|
func (fs *HTTPFs) Create(name string, flag, checks int) (File, *PipeWriter, func(), error) {
|
||||||
r, w, err := pipeat.PipeInDir(fs.localTempDir)
|
r, w, err := pipeat.PipeInDir(fs.localTempDir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, nil, err
|
return nil, nil, nil, err
|
||||||
|
@ -338,15 +338,11 @@ func (fs *HTTPFs) Create(name string, flag int) (File, *PipeWriter, func(), erro
|
||||||
p := NewPipeWriter(w)
|
p := NewPipeWriter(w)
|
||||||
ctx, cancelFn := context.WithCancel(context.Background())
|
ctx, cancelFn := context.WithCancel(context.Background())
|
||||||
|
|
||||||
var queryString string
|
|
||||||
if flag > 0 {
|
|
||||||
queryString = fmt.Sprintf("?flags=%d", flag)
|
|
||||||
}
|
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
defer cancelFn()
|
defer cancelFn()
|
||||||
|
|
||||||
contentType := mime.TypeByExtension(path.Ext(name))
|
contentType := mime.TypeByExtension(path.Ext(name))
|
||||||
|
queryString := fmt.Sprintf("?flags=%d&checks=%d", flag, checks)
|
||||||
resp, err := fs.sendHTTPRequest(ctx, http.MethodPost, "create", name, queryString, contentType,
|
resp, err := fs.sendHTTPRequest(ctx, http.MethodPost, "create", name, queryString, contentType,
|
||||||
&wrapReader{reader: r})
|
&wrapReader{reader: r})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -104,7 +104,7 @@ func (*OsFs) Open(name string, offset int64) (File, *pipeat.PipeReaderAt, func()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create creates or opens the named file for writing
|
// Create creates or opens the named file for writing
|
||||||
func (*OsFs) Create(name string, flag int) (File, *PipeWriter, func(), error) {
|
func (*OsFs) Create(name string, flag, _ int) (File, *PipeWriter, func(), error) {
|
||||||
var err error
|
var err error
|
||||||
var f *os.File
|
var f *os.File
|
||||||
if flag == 0 {
|
if flag == 0 {
|
||||||
|
|
|
@ -242,7 +242,13 @@ func (fs *S3Fs) Open(name string, offset int64) (File, *pipeat.PipeReaderAt, fun
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create creates or opens the named file for writing
|
// Create creates or opens the named file for writing
|
||||||
func (fs *S3Fs) Create(name string, flag int) (File, *PipeWriter, func(), error) {
|
func (fs *S3Fs) Create(name string, flag, checks int) (File, *PipeWriter, func(), error) {
|
||||||
|
if checks&CheckParentDir != 0 {
|
||||||
|
_, err := fs.Stat(path.Dir(name))
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
r, w, err := pipeat.PipeInDir(fs.localTempDir)
|
r, w, err := pipeat.PipeInDir(fs.localTempDir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, nil, err
|
return nil, nil, nil, err
|
||||||
|
@ -290,6 +296,10 @@ func (fs *S3Fs) Rename(source, target string) (int, int64, error) {
|
||||||
if source == target {
|
if source == target {
|
||||||
return -1, -1, nil
|
return -1, -1, nil
|
||||||
}
|
}
|
||||||
|
_, err := fs.Stat(path.Dir(target))
|
||||||
|
if err != nil {
|
||||||
|
return -1, -1, err
|
||||||
|
}
|
||||||
fi, err := fs.Stat(source)
|
fi, err := fs.Stat(source)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return -1, -1, err
|
return -1, -1, err
|
||||||
|
@ -803,7 +813,7 @@ func (fs *S3Fs) mkdirInternal(name string) error {
|
||||||
if !strings.HasSuffix(name, "/") {
|
if !strings.HasSuffix(name, "/") {
|
||||||
name += "/"
|
name += "/"
|
||||||
}
|
}
|
||||||
_, w, _, err := fs.Create(name, -1)
|
_, w, _, err := fs.Create(name, -1, 0)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -374,7 +374,7 @@ func (fs *SFTPFs) Open(name string, offset int64) (File, *pipeat.PipeReaderAt, f
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create creates or opens the named file for writing
|
// Create creates or opens the named file for writing
|
||||||
func (fs *SFTPFs) Create(name string, flag int) (File, *PipeWriter, func(), error) {
|
func (fs *SFTPFs) Create(name string, flag, _ int) (File, *PipeWriter, func(), error) {
|
||||||
client, err := fs.conn.getClient()
|
client, err := fs.conn.getClient()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, nil, err
|
return nil, nil, nil, err
|
||||||
|
|
|
@ -45,6 +45,11 @@ const (
|
||||||
azBlobFsName = "AzureBlobFs"
|
azBlobFsName = "AzureBlobFs"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Additional checks for files
|
||||||
|
const (
|
||||||
|
CheckParentDir = 1
|
||||||
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
validAzAccessTier = []string{"", "Archive", "Hot", "Cool"}
|
validAzAccessTier = []string{"", "Archive", "Hot", "Cool"}
|
||||||
// ErrStorageSizeUnavailable is returned if the storage backend does not support getting the size
|
// ErrStorageSizeUnavailable is returned if the storage backend does not support getting the size
|
||||||
|
@ -89,7 +94,7 @@ type Fs interface {
|
||||||
Stat(name string) (os.FileInfo, error)
|
Stat(name string) (os.FileInfo, error)
|
||||||
Lstat(name string) (os.FileInfo, error)
|
Lstat(name string) (os.FileInfo, error)
|
||||||
Open(name string, offset int64) (File, *pipeat.PipeReaderAt, func(), error)
|
Open(name string, offset int64) (File, *pipeat.PipeReaderAt, func(), error)
|
||||||
Create(name string, flag int) (File, *PipeWriter, func(), error)
|
Create(name string, flag, checks int) (File, *PipeWriter, func(), error)
|
||||||
Rename(source, target string) (int, int64, error)
|
Rename(source, target string) (int, int64, error)
|
||||||
Remove(name string, isDir bool) error
|
Remove(name string, isDir bool) error
|
||||||
Mkdir(name string) error
|
Mkdir(name string) error
|
||||||
|
|
|
@ -215,7 +215,7 @@ func (c *Connection) handleUploadToNewFile(fs vfs.Fs, resolvedPath, filePath, re
|
||||||
c.Log(logger.LevelDebug, "upload for file %q denied by pre action: %v", requestPath, err)
|
c.Log(logger.LevelDebug, "upload for file %q denied by pre action: %v", requestPath, err)
|
||||||
return nil, c.GetPermissionDeniedError()
|
return nil, c.GetPermissionDeniedError()
|
||||||
}
|
}
|
||||||
file, w, cancelFn, err := fs.Create(filePath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC)
|
file, w, cancelFn, err := fs.Create(filePath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, c.GetCreateChecks(requestPath, true))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.Log(logger.LevelError, "error creating file %q: %+v", resolvedPath, err)
|
c.Log(logger.LevelError, "error creating file %q: %+v", resolvedPath, err)
|
||||||
return nil, c.GetFsError(fs, err)
|
return nil, c.GetFsError(fs, err)
|
||||||
|
@ -262,7 +262,7 @@ func (c *Connection) handleUploadToExistingFile(fs vfs.Fs, resolvedPath, filePat
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
file, w, cancelFn, err := fs.Create(filePath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC)
|
file, w, cancelFn, err := fs.Create(filePath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, c.GetCreateChecks(requestPath, false))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.Log(logger.LevelError, "error creating file %q: %+v", resolvedPath, err)
|
c.Log(logger.LevelError, "error creating file %q: %+v", resolvedPath, err)
|
||||||
return nil, c.GetFsError(fs, err)
|
return nil, c.GetFsError(fs, err)
|
||||||
|
|
|
@ -101,6 +101,13 @@ paths:
|
||||||
schema:
|
schema:
|
||||||
type: integer
|
type: integer
|
||||||
format: int32
|
format: int32
|
||||||
|
- name: checks
|
||||||
|
in: query
|
||||||
|
description: 'If set to `1`, the parent directory must exist before creating the file'
|
||||||
|
required: false
|
||||||
|
schema:
|
||||||
|
type: integer
|
||||||
|
format: int32
|
||||||
post:
|
post:
|
||||||
tags:
|
tags:
|
||||||
- fs
|
- fs
|
||||||
|
|
|
@ -3368,7 +3368,7 @@ paths:
|
||||||
tags:
|
tags:
|
||||||
- users
|
- users
|
||||||
summary: Update user
|
summary: Update user
|
||||||
description: 'Updates an existing user and optionally disconnects it, if connected, to apply the new settings. Recovery codes and TOTP configuration cannot be set/updated using this API: each user must use the specific APIs'
|
description: 'Updates an existing user and optionally disconnects it, if connected, to apply the new settings. The current password will be preserved if the password field is omitted in the request body. Recovery codes and TOTP configuration cannot be set/updated using this API: each user must use the specific APIs'
|
||||||
operationId: update_user
|
operationId: update_user
|
||||||
parameters:
|
parameters:
|
||||||
- in: query
|
- in: query
|
||||||
|
@ -5682,13 +5682,16 @@ components:
|
||||||
password:
|
password:
|
||||||
type: string
|
type: string
|
||||||
format: password
|
format: password
|
||||||
description: password or public key/SSH user certificate are mandatory. If the password has no known hashing algo prefix it will be stored, by default, using bcrypt, argon2id is supported too. You can send a password hashed as bcrypt ($2a$ prefix), argon2id, pbkdf2 or unix crypt and it will be stored as is. For security reasons this field is omitted when you search/get users
|
description: If the password has no known hashing algo prefix it will be stored, by default, using bcrypt, argon2id is supported too. You can send a password hashed as bcrypt ($2a$ prefix), argon2id, pbkdf2 or unix crypt and it will be stored as is. For security reasons this field is omitted when you search/get users
|
||||||
public_keys:
|
public_keys:
|
||||||
type: array
|
type: array
|
||||||
items:
|
items:
|
||||||
type: string
|
type: string
|
||||||
example: ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBEUWwDwEWhTbF0MqAsp/oXK1HR2cElhM8oo1uVmL3ZeDKDiTm4ljMr92wfTgIGDqIoxmVqgYIkAOAhuykAVWBzc= user@host
|
example: ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBEUWwDwEWhTbF0MqAsp/oXK1HR2cElhM8oo1uVmL3ZeDKDiTm4ljMr92wfTgIGDqIoxmVqgYIkAOAhuykAVWBzc= user@host
|
||||||
description: Public keys in OpenSSH format. A password or at least one public key/SSH user certificate are mandatory.
|
description: Public keys in OpenSSH format.
|
||||||
|
has_password:
|
||||||
|
type: boolean
|
||||||
|
description: Indicates whether the password is set
|
||||||
home_dir:
|
home_dir:
|
||||||
type: string
|
type: string
|
||||||
description: path to the user home directory. The user cannot upload or download files outside this directory. SFTPGo tries to automatically create this folder if missing. Must be an absolute path
|
description: path to the user home directory. The user cannot upload or download files outside this directory. SFTPGo tries to automatically create this folder if missing. Must be an absolute path
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
NFPM_VERSION=2.27.1
|
NFPM_VERSION=2.28.0
|
||||||
NFPM_ARCH=${NFPM_ARCH:-amd64}
|
NFPM_ARCH=${NFPM_ARCH:-amd64}
|
||||||
if [ -z ${SFTPGO_VERSION} ]
|
if [ -z ${SFTPGO_VERSION} ]
|
||||||
then
|
then
|
||||||
|
|
|
@ -159,7 +159,10 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="copy_new_name" class="col-form-label">Target</label>
|
<label for="copy_new_name" class="col-form-label">Target</label>
|
||||||
<input type="text" class="form-control" id="copy_new_name" required>
|
<input type="text" class="form-control" id="copy_new_name" required aria-describedby="copyTargetDirHelpBlock">
|
||||||
|
<small id="copyNewDirHelpBlock" class="form-text text-muted">
|
||||||
|
If the target ends with "/", for example "adir/", it is treated as a directory and the source will be copied to the target. The target directory will be created if it doesn't exist
|
||||||
|
</small>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-footer">
|
<div class="modal-footer">
|
||||||
|
|
Loading…
Reference in a new issue