mirror of
https://github.com/drakkan/sftpgo.git
synced 2024-11-25 00:50:31 +00:00
WebAdmin: allow to simplify the user page
Signed-off-by: Nicola Murino <nicola.murino@gmail.com>
This commit is contained in:
parent
7349598b19
commit
bd294bb3cf
16 changed files with 337 additions and 124 deletions
40
go.mod
40
go.mod
|
@ -8,15 +8,15 @@ require (
|
|||
github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v0.4.1
|
||||
github.com/GehirnInc/crypt v0.0.0-20200316065508-bb7000b8a962
|
||||
github.com/alexedwards/argon2id v0.0.0-20211130144151-3585854a6387
|
||||
github.com/aws/aws-sdk-go-v2 v1.16.15
|
||||
github.com/aws/aws-sdk-go-v2/config v1.17.6
|
||||
github.com/aws/aws-sdk-go-v2/credentials v1.12.19
|
||||
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.12.16
|
||||
github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.11.32
|
||||
github.com/aws/aws-sdk-go-v2/service/marketplacemetering v1.13.18
|
||||
github.com/aws/aws-sdk-go-v2/service/s3 v1.27.10
|
||||
github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.16.0
|
||||
github.com/aws/aws-sdk-go-v2/service/sts v1.16.18
|
||||
github.com/aws/aws-sdk-go-v2 v1.16.16
|
||||
github.com/aws/aws-sdk-go-v2/config v1.17.7
|
||||
github.com/aws/aws-sdk-go-v2/credentials v1.12.20
|
||||
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.12.17
|
||||
github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.11.33
|
||||
github.com/aws/aws-sdk-go-v2/service/marketplacemetering v1.13.19
|
||||
github.com/aws/aws-sdk-go-v2/service/s3 v1.27.11
|
||||
github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.16.1
|
||||
github.com/aws/aws-sdk-go-v2/service/sts v1.16.19
|
||||
github.com/cockroachdb/cockroach-go/v2 v2.2.16
|
||||
github.com/coreos/go-oidc/v3 v3.4.0
|
||||
github.com/eikenb/pipeat v0.0.0-20210730190139-06b3e6902001
|
||||
|
@ -31,7 +31,7 @@ require (
|
|||
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510
|
||||
github.com/google/uuid v1.3.0
|
||||
github.com/grandcat/zeroconf v1.0.0
|
||||
github.com/hashicorp/go-hclog v1.3.0
|
||||
github.com/hashicorp/go-hclog v1.3.1
|
||||
github.com/hashicorp/go-plugin v1.4.5
|
||||
github.com/hashicorp/go-retryablehttp v0.7.1
|
||||
github.com/jlaffaye/ftp v0.0.0-20201112195030-9aae4d151126
|
||||
|
@ -81,16 +81,16 @@ require (
|
|||
github.com/Azure/azure-sdk-for-go/sdk/internal v1.0.1 // indirect
|
||||
github.com/ajg/form v1.5.1 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.4.8 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.22 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.16 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/internal/ini v1.3.23 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/internal/v4a v1.0.13 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.23 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.17 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/internal/ini v1.3.24 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/internal/v4a v1.0.14 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.9.9 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.1.17 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.16 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.13.16 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/sso v1.11.22 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.13.4 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.1.18 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.17 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.13.17 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/sso v1.11.23 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.13.5 // indirect
|
||||
github.com/aws/smithy-go v1.13.3 // indirect
|
||||
github.com/beorn7/perks v1.0.1 // indirect
|
||||
github.com/boombuler/barcode v1.0.1 // indirect
|
||||
|
@ -156,7 +156,7 @@ require (
|
|||
golang.org/x/tools v0.1.12 // indirect
|
||||
golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect
|
||||
google.golang.org/appengine v1.6.7 // indirect
|
||||
google.golang.org/genproto v0.0.0-20220919141832-68c03719ef51 // indirect
|
||||
google.golang.org/genproto v0.0.0-20220920201722-2b89144ce006 // indirect
|
||||
google.golang.org/grpc v1.49.0 // indirect
|
||||
google.golang.org/protobuf v1.28.1 // indirect
|
||||
gopkg.in/ini.v1 v1.67.0 // indirect
|
||||
|
|
80
go.sum
80
go.sum
|
@ -143,66 +143,66 @@ github.com/aws/aws-sdk-go v1.15.27/go.mod h1:mFuSZ37Z9YOHbQEwBWztmVzqXrEkub65tZo
|
|||
github.com/aws/aws-sdk-go v1.37.0/go.mod h1:hcU610XS61/+aQV88ixoOzUoG7v3b31pl2zKMmprdro=
|
||||
github.com/aws/aws-sdk-go v1.43.31/go.mod h1:y4AeaBuwd2Lk+GepC1E9v0qOiTws0MIWAX4oIKwKHZo=
|
||||
github.com/aws/aws-sdk-go-v2 v1.16.2/go.mod h1:ytwTPBG6fXTZLxxeeCCWj2/EMYp/xDUgX+OET6TLNNU=
|
||||
github.com/aws/aws-sdk-go-v2 v1.16.15 h1:2sInOWGE4HV54R90Pj8QgqBBw3Qf1I0husqbqjPZzys=
|
||||
github.com/aws/aws-sdk-go-v2 v1.16.15/go.mod h1:SwiyXi/1zTUZ6KIAmLK5V5ll8SiURNUYOqTerZPaF9k=
|
||||
github.com/aws/aws-sdk-go-v2 v1.16.16 h1:M1fj4FE2lB4NzRb9Y0xdWsn2P0+2UHVxwKyOa4YJNjk=
|
||||
github.com/aws/aws-sdk-go-v2 v1.16.16/go.mod h1:SwiyXi/1zTUZ6KIAmLK5V5ll8SiURNUYOqTerZPaF9k=
|
||||
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.4.1/go.mod h1:n8Bs1ElDD2wJ9kCRTczA83gYbBmjSwZp3umc6zF4EeM=
|
||||
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.4.8 h1:tcFliCWne+zOuUfKNRn8JdFBuWPDuISDH08wD2ULkhk=
|
||||
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.4.8/go.mod h1:JTnlBSot91steJeti4ryyu/tLd4Sk84O5W22L7O2EQU=
|
||||
github.com/aws/aws-sdk-go-v2/config v1.15.3/go.mod h1:9YL3v07Xc/ohTsxFXzan9ZpFpdTOFl4X65BAKYaz8jg=
|
||||
github.com/aws/aws-sdk-go-v2/config v1.17.6 h1:0xHMch3eQ2C8CByMEi0iJOLF+pTLoAQeHVfhFxN7eyk=
|
||||
github.com/aws/aws-sdk-go-v2/config v1.17.6/go.mod h1:CrxsoI/AcKUoWyL9Zo0YaDxRlBfSnDZKBYKDdkNYDQ0=
|
||||
github.com/aws/aws-sdk-go-v2/config v1.17.7 h1:odVM52tFHhpqZBKNjVW5h+Zt1tKHbhdTQRb+0WHrNtw=
|
||||
github.com/aws/aws-sdk-go-v2/config v1.17.7/go.mod h1:dN2gja/QXxFF15hQreyrqYhLBaQo1d9ZKe/v/uplQoI=
|
||||
github.com/aws/aws-sdk-go-v2/credentials v1.11.2/go.mod h1:j8YsY9TXTm31k4eFhspiQicfXPLZ0gYXA50i4gxPE8g=
|
||||
github.com/aws/aws-sdk-go-v2/credentials v1.12.19 h1:fYtSz4Fd0lUavtj4FAtvol9G2k0lh1TK4LfeP1hdnLw=
|
||||
github.com/aws/aws-sdk-go-v2/credentials v1.12.19/go.mod h1:fRQMbLwSHPr0XRzuez6x7BX5+0nNQs5BzG+oR4bQKyY=
|
||||
github.com/aws/aws-sdk-go-v2/credentials v1.12.20 h1:9+ZhlDY7N9dPnUmf7CDfW9In4sW5Ff3bh7oy4DzS1IE=
|
||||
github.com/aws/aws-sdk-go-v2/credentials v1.12.20/go.mod h1:UKY5HyIux08bbNA7Blv4PcXQ8cTkGh7ghHMFklaviR4=
|
||||
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.12.3/go.mod h1:uk1vhHHERfSVCUnqSqz8O48LBYDSC+k6brng09jcMOk=
|
||||
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.12.16 h1:LX38v4cqSqrBETHUBnc8B+N6p5YA41GaPQ3jwICjetI=
|
||||
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.12.16/go.mod h1:lnJ8tKos2s7JeBdLVFknwVSlQZAKzkgrFNQmUaTWwRQ=
|
||||
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.12.17 h1:r08j4sbZu/RVi+BNxkBJwPMUYY3P8mgSDuKkZ/ZN1lE=
|
||||
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.12.17/go.mod h1:yIkQcCDYNsZfXpd5UX2Cy+sWA1jPgIhGTw9cOBzfVnQ=
|
||||
github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.11.3/go.mod h1:0dHuD2HZZSiwfJSy1FO5bX1hQ1TxVV1QXXjpn3XUE44=
|
||||
github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.11.32 h1:7VX09WtXhjIcJ+CKwYgFsVjypiqg29awSaMH1RQ++Eg=
|
||||
github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.11.32/go.mod h1:zNsdxtYDwAWcxWMgH9+s1U0OOW+jrPLK6HHNw6r76l4=
|
||||
github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.11.33 h1:fAoVmNGhir6BR+RU0/EI+6+D7abM+MCwWf8v4ip5jNI=
|
||||
github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.11.33/go.mod h1:84XgODVR8uRhmOnUkKGUZKqIMxmjmLOR8Uyp7G/TPwc=
|
||||
github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.9/go.mod h1:AnVH5pvai0pAF4lXRq0bmhbes1u9R8wTE+g+183bZNM=
|
||||
github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.22 h1:pE27/u2A7JlwICjOvONQDob8PToShRTkuiUE74ymVWg=
|
||||
github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.22/go.mod h1:/vNv5Al0bpiF8YdX2Ov6Xy05VTiXsql94yUqJMYaj0w=
|
||||
github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.23 h1:s4g/wnzMf+qepSNgTvaQQHNxyMLKSawNhKCPNy++2xY=
|
||||
github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.23/go.mod h1:2DFxAQ9pfIRy0imBCJv+vZ2X6RKxves6fbnEuSry6b4=
|
||||
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.3/go.mod h1:ssOhaLpRlh88H3UmEcsBoVKq309quMvm3Ds8e9d4eJM=
|
||||
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.16 h1:L5LKGHHXOl4t7+5QZMTl38GIzSAq07XUTRtEquiHGMA=
|
||||
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.16/go.mod h1:62dsXI0BqTIGomDl8Hpm33dv0OntGaVblri3ZRParVQ=
|
||||
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.17 h1:/K482T5A3623WJgWT8w1yRAFK4RzGzEl7y39yhtn9eA=
|
||||
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.17/go.mod h1:pRwaTYCJemADaqCbUAxltMoHKata7hmB5PjEXeu0kfg=
|
||||
github.com/aws/aws-sdk-go-v2/internal/ini v1.3.10/go.mod h1:8DcYQcz0+ZJaSxANlHIsbbi6S+zMwjwdDqwW3r9AzaE=
|
||||
github.com/aws/aws-sdk-go-v2/internal/ini v1.3.23 h1:Sy266MXyLZZbObFhStGF9dyJm5nFyA8LINTgNm4Q6Ds=
|
||||
github.com/aws/aws-sdk-go-v2/internal/ini v1.3.23/go.mod h1:XtEkQMmxls+Tb5dZLmpa1QAk0OzSIFDAXanC9Jkf81E=
|
||||
github.com/aws/aws-sdk-go-v2/internal/v4a v1.0.13 h1:ZrdsZJfzniYAF3Au4ngj7vWxJS1ZHGYCE0YlATcWYUg=
|
||||
github.com/aws/aws-sdk-go-v2/internal/v4a v1.0.13/go.mod h1:QyDZ5fgUmZFZztFpVcR7w4HV8vwO0ze1OM9rPy6jkEI=
|
||||
github.com/aws/aws-sdk-go-v2/internal/ini v1.3.24 h1:wj5Rwc05hvUSvKuOF29IYb9QrCLjU+rHAy/x/o0DK2c=
|
||||
github.com/aws/aws-sdk-go-v2/internal/ini v1.3.24/go.mod h1:jULHjqqjDlbyTa7pfM7WICATnOv+iOhjletM3N0Xbu8=
|
||||
github.com/aws/aws-sdk-go-v2/internal/v4a v1.0.14 h1:ZSIPAkAsCCjYrhqfw2+lNzWDzxzHXEckFkTePL5RSWQ=
|
||||
github.com/aws/aws-sdk-go-v2/internal/v4a v1.0.14/go.mod h1:AyGgqiKv9ECM6IZeNQtdT8NnMvUb3/2wokeq2Fgryto=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.9.1/go.mod h1:GeUru+8VzrTXV/83XyMJ80KpH8xO89VPoUileyNQ+tc=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.9.9 h1:Lh1AShsuIJTwMkoxVCAYPJgNG5H+eN6SmoUn8nOZ5wE=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.9.9/go.mod h1:a9j48l6yL5XINLHLcOKInjdvknN+vWqPBxqeIDw7ktw=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.1.3/go.mod h1:Seb8KNmD6kVTjwRjVEgOT5hPin6sq+v4C2ycJQDwuH8=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.1.17 h1:rf0/i+3BMiQZjcQzhjTz3sAXouSl1dcnCrd8mroC4CE=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.1.17/go.mod h1:Uo/4yJjc7RDB7R5q9JA7aQqFXasu/lAJke8mulo2dA8=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.1.18 h1:BBYoNQt2kUZUUK4bIPsKrCcjVPUMNsgQpNAwhznK/zo=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.1.18/go.mod h1:NS55eQ4YixUJPTC+INxi2/jCqe1y2Uw3rnh9wEOVJxY=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.3/go.mod h1:wlY6SVjuwvh3TVRpTqdy4I1JpBFLX4UGeKZdWntaocw=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.16 h1:9jysIwpUt7KGdsKOl+zA+0pG+7MpSsi0KQUcbE48n38=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.16/go.mod h1:faBcf/4ZB4FRc17geaXWOxgzktotyJgBcUBZoHqvdfM=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.17 h1:Jrd/oMh0PKQc6+BowB+pLEwLIgaQF29eYbe7E1Av9Ug=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.17/go.mod h1:4nYOrY41Lrbk2170/BGkcJKBhws9Pfn8MG3aGqjjeFI=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.13.3/go.mod h1:Bm/v2IaN6rZ+Op7zX+bOUMdL4fsrYZiD0dsjLhNKwZc=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.13.16 h1:jnGshlNJoVF3x8e5EbsFakNKeNUc0Pf3EQvU076bkKU=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.13.16/go.mod h1:tMN4hfJxozc/lHWA8Ug/eXEg4ZSm5c4sPB9WE/mdDuw=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.13.17 h1:HfVVR1vItaG6le+Bpw6P4midjBDMKnjMyZnw9MXYUcE=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.13.17/go.mod h1:YqMdV+gEKCQ59NrB7rzrJdALeBIsYiVi8Inj3+KcqHI=
|
||||
github.com/aws/aws-sdk-go-v2/service/kms v1.16.3/go.mod h1:QuiHPBqlOFCi4LqdSskYYAWpQlx3PKmohy+rE2F+o5g=
|
||||
github.com/aws/aws-sdk-go-v2/service/marketplacemetering v1.13.18 h1:VoxHI3YKYQ1ewtBnfSUsZ8he0tdot/mZuE/vP4qJgBw=
|
||||
github.com/aws/aws-sdk-go-v2/service/marketplacemetering v1.13.18/go.mod h1:zan7AawF2v5WynzqKdF0aeYWZboYiOZ7vMWlhSGLCwQ=
|
||||
github.com/aws/aws-sdk-go-v2/service/marketplacemetering v1.13.19 h1:6rxMT+zWZh2+0F1XHdDWCSzuMQIJI+tGlfrFi6V/UlU=
|
||||
github.com/aws/aws-sdk-go-v2/service/marketplacemetering v1.13.19/go.mod h1:wGzRNLBD3V8/KKoBSYz0OWv1dnQNvqTyb193fS97dXQ=
|
||||
github.com/aws/aws-sdk-go-v2/service/s3 v1.26.3/go.mod h1:g1qvDuRsJY+XghsV6zg00Z4KJ7DtFFCx8fJD2a491Ak=
|
||||
github.com/aws/aws-sdk-go-v2/service/s3 v1.27.10 h1:fR5Z06dU41kkSdmSOtHiROealTOu5aNkwidOQ+lT0KQ=
|
||||
github.com/aws/aws-sdk-go-v2/service/s3 v1.27.10/go.mod h1:B+5EUmLgCYrXHxgQ3nTUu3RUbxnrN1JMa41LSXm7lXw=
|
||||
github.com/aws/aws-sdk-go-v2/service/s3 v1.27.11 h1:3/gm/JTX9bX8CpzTgIlrtYpB3EVBDxyg/GY/QdcIEZw=
|
||||
github.com/aws/aws-sdk-go-v2/service/s3 v1.27.11/go.mod h1:fmgDANqTUCxciViKl9hb/zD5LFbvPINFRgWhDbR+vZo=
|
||||
github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.15.4/go.mod h1:PJc8s+lxyU8rrre0/4a0pn2wgwiDvOEzoOjcJUBr67o=
|
||||
github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.16.0 h1:Lh1yssM4dinNZuESsXnbi+pID8hoviejLZdLmT175i8=
|
||||
github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.16.0/go.mod h1:z0y2iDaghoq7uv6kndhrJCTzgVckv8Aak8kpnu2kYjs=
|
||||
github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.16.1 h1:eMsEmvJR6zQ1lDi59RDtCc62x9fKs1kv2b8A8nPpWmY=
|
||||
github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.16.1/go.mod h1:HEBBc70BYi5eUvxBqC3xXjU/04NO96X/XNUe5qhC7Bc=
|
||||
github.com/aws/aws-sdk-go-v2/service/sns v1.17.4/go.mod h1:kElt+uCcXxcqFyc+bQqZPFD9DME/eC6oHBXvFzQ9Bcw=
|
||||
github.com/aws/aws-sdk-go-v2/service/sqs v1.18.3/go.mod h1:skmQo0UPvsjsuYYSYMVmrPc1HWCbHUJyrCEp+ZaLzqM=
|
||||
github.com/aws/aws-sdk-go-v2/service/ssm v1.24.1/go.mod h1:NR/xoKjdbRJ+qx0pMR4mI+N/H1I1ynHwXnO6FowXJc0=
|
||||
github.com/aws/aws-sdk-go-v2/service/sso v1.11.3/go.mod h1:7UQ/e69kU7LDPtY40OyoHYgRmgfGM4mgsLYtcObdveU=
|
||||
github.com/aws/aws-sdk-go-v2/service/sso v1.11.22 h1:LrEyMbp0gMiXVaXpJ67jJkkqKCxivZvOd6wgXem0bWA=
|
||||
github.com/aws/aws-sdk-go-v2/service/sso v1.11.22/go.mod h1:B2nDzX7lppT8j4EV2/WhT20SnRDp/LdNyqxyGYY46Ow=
|
||||
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.13.4 h1:d7Wh4xMQVVYfrJ1KHFGQ6jY/O51LjnTCWJgh85RT+TQ=
|
||||
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.13.4/go.mod h1:mOofcMJCDSJwmtZykUE/i6tWGNwMnkextriwzY1zcbc=
|
||||
github.com/aws/aws-sdk-go-v2/service/sso v1.11.23 h1:pwvCchFUEnlceKIgPUouBJwK81aCkQ8UDMORfeFtW10=
|
||||
github.com/aws/aws-sdk-go-v2/service/sso v1.11.23/go.mod h1:/w0eg9IhFGjGyyncHIQrXtU8wvNsTJOP0R6PPj0wf80=
|
||||
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.13.5 h1:GUnZ62TevLqIoDyHeiWj2P7EqaosgakBKVvWriIdLQY=
|
||||
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.13.5/go.mod h1:csZuQY65DAdFBt1oIjO5hhBR49kQqop4+lcuCjf2arA=
|
||||
github.com/aws/aws-sdk-go-v2/service/sts v1.16.3/go.mod h1:bfBj0iVmsUyUg4weDB4NxktD9rDGeKSVWnjTnwbx9b8=
|
||||
github.com/aws/aws-sdk-go-v2/service/sts v1.16.18 h1:TqEvnK8OceCKNQaDK9d5Ir2bOtC0S0dRQCwSbkV1rz0=
|
||||
github.com/aws/aws-sdk-go-v2/service/sts v1.16.18/go.mod h1:AE4zMc8qCw1JnDvy0ZrDVb/OXRuuweG3BcT2Nv7Qh3E=
|
||||
github.com/aws/aws-sdk-go-v2/service/sts v1.16.19 h1:9pPi0PsFNAGILFfPCk8Y0iyEBGc6lu6OQ97U7hmdesg=
|
||||
github.com/aws/aws-sdk-go-v2/service/sts v1.16.19/go.mod h1:h4J3oPZQbxLhzGnk+j9dfYHi5qIOVJ5kczZd658/ydM=
|
||||
github.com/aws/smithy-go v1.11.2/go.mod h1:3xHYmszWVx2c0kIwQeEVf9uSm4fYZt67FBJnwub1bgM=
|
||||
github.com/aws/smithy-go v1.13.3 h1:l7LYxGuzK6/K+NzJ2mC+VvLUbae0sL3bXU//04MkmnA=
|
||||
github.com/aws/smithy-go v1.13.3/go.mod h1:Tg+OJXh4MB2R/uN61Ko2f6hTZwB/ZYGOtib8J3gBHzA=
|
||||
|
@ -464,8 +464,8 @@ github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtng
|
|||
github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ=
|
||||
github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48=
|
||||
github.com/hashicorp/go-hclog v0.9.2/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ=
|
||||
github.com/hashicorp/go-hclog v1.3.0 h1:G0ACM8Z2WilWgPv3Vdzwm3V0BQu/kSmrkVtpe1fy9do=
|
||||
github.com/hashicorp/go-hclog v1.3.0/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M=
|
||||
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-plugin v1.4.5 h1:oTE/oQR4eghggRg8VY7PAz3dr++VwDNBGCcOfIvHpBo=
|
||||
github.com/hashicorp/go-plugin v1.4.5/go.mod h1:viDMjcLJuDui6pXb8U4HVfb8AamCWhHGUjr2IrTF67s=
|
||||
github.com/hashicorp/go-retryablehttp v0.7.1 h1:sUiuQAnLlbvmExtFQs72iFW/HXeUn8Z1aJLQ4LJJbTQ=
|
||||
|
@ -1229,8 +1229,8 @@ google.golang.org/genproto v0.0.0-20220523171625-347a074981d8/go.mod h1:RAyBrSAP
|
|||
google.golang.org/genproto v0.0.0-20220608133413-ed9918b62aac/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA=
|
||||
google.golang.org/genproto v0.0.0-20220616135557-88e70c0c3a90/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-20220919141832-68c03719ef51 h1:ucpgjuzWqWrj0NEwjUpsGTf2IGxyLtmuSk0oGgifjec=
|
||||
google.golang.org/genproto v0.0.0-20220919141832-68c03719ef51/go.mod h1:0Nb8Qy+Sk5eDzHnzlStwW3itdNaWoZA5XeSG+R3JHSo=
|
||||
google.golang.org/genproto v0.0.0-20220920201722-2b89144ce006 h1:mmbq5q8M1t7dhkLw320YK4PsOXm6jdnUAkErImaIqOg=
|
||||
google.golang.org/genproto v0.0.0-20220920201722-2b89144ce006/go.mod h1:ht8XFiar2npT/g4vkk7O0WYS1sHOHbdujxbEp7CJWbw=
|
||||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
|
||||
google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
|
||||
|
|
|
@ -107,6 +107,82 @@ func (c *AdminTOTPConfig) validate(username string) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// AdminPreferences defines the admin preferences
|
||||
type AdminPreferences struct {
|
||||
// Allow to hide some sections from the user page.
|
||||
// These are not security settings and are not enforced server side
|
||||
// in any way. They are only intended to simplify the user page in
|
||||
// the WebAdmin UI.
|
||||
//
|
||||
// 1 means hide groups section
|
||||
// 2 means hide filesystem section, "users_base_dir" must be set in the config file otherwise this setting is ignored
|
||||
// 4 means hide virtual folders section
|
||||
// 8 means hide profile section
|
||||
// 16 means hide ACLs section
|
||||
// 32 means hide disk and bandwidth quota limits section
|
||||
// 64 means hide advanced settings section
|
||||
//
|
||||
// The settings can be combined
|
||||
HideUserPageSections int `json:"hide_user_page_sections,omitempty"`
|
||||
}
|
||||
|
||||
// HideGroups returns true if the groups section should be hidden
|
||||
func (p *AdminPreferences) HideGroups() bool {
|
||||
return p.HideUserPageSections&1 != 0
|
||||
}
|
||||
|
||||
// HideFilesystem returns true if the filesystem section should be hidden
|
||||
func (p *AdminPreferences) HideFilesystem() bool {
|
||||
return config.UsersBaseDir != "" && p.HideUserPageSections&2 != 0
|
||||
}
|
||||
|
||||
// HideVirtualFolders returns true if the virtual folder section should be hidden
|
||||
func (p *AdminPreferences) HideVirtualFolders() bool {
|
||||
return p.HideUserPageSections&4 != 0
|
||||
}
|
||||
|
||||
// HideProfile returns true if the profile section should be hidden
|
||||
func (p *AdminPreferences) HideProfile() bool {
|
||||
return p.HideUserPageSections&8 != 0
|
||||
}
|
||||
|
||||
// HideACLs returns true if the ACLs section should be hidden
|
||||
func (p *AdminPreferences) HideACLs() bool {
|
||||
return p.HideUserPageSections&16 != 0
|
||||
}
|
||||
|
||||
// HideDiskQuotaAndBandwidthLimits returns true if the disk quota and bandwidth limits
|
||||
// section should be hidden
|
||||
func (p *AdminPreferences) HideDiskQuotaAndBandwidthLimits() bool {
|
||||
return p.HideUserPageSections&32 != 0
|
||||
}
|
||||
|
||||
// HideAdvancedSettings returns true if the advanced settings section should be hidden
|
||||
func (p *AdminPreferences) HideAdvancedSettings() bool {
|
||||
return p.HideUserPageSections&64 != 0
|
||||
}
|
||||
|
||||
// VisibleUserPageSections returns the number of visible sections
|
||||
// in the user page
|
||||
func (p *AdminPreferences) VisibleUserPageSections() int {
|
||||
var result int
|
||||
|
||||
if !p.HideProfile() {
|
||||
result++
|
||||
}
|
||||
if !p.HideACLs() {
|
||||
result++
|
||||
}
|
||||
if !p.HideDiskQuotaAndBandwidthLimits() {
|
||||
result++
|
||||
}
|
||||
if !p.HideAdvancedSettings() {
|
||||
result++
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
// AdminFilters defines additional restrictions for SFTPGo admins
|
||||
// TODO: rename to AdminOptions in v3
|
||||
type AdminFilters struct {
|
||||
|
@ -121,7 +197,8 @@ type AdminFilters struct {
|
|||
// Recovery codes to use if the user loses access to their second factor auth device.
|
||||
// Each code can only be used once, you should use these codes to login and disable or
|
||||
// reset 2FA for your account
|
||||
RecoveryCodes []RecoveryCode `json:"recovery_codes,omitempty"`
|
||||
RecoveryCodes []RecoveryCode `json:"recovery_codes,omitempty"`
|
||||
Preferences AdminPreferences `json:"preferences"`
|
||||
}
|
||||
|
||||
// AdminGroupMappingOptions defines the options for admin/group mapping
|
||||
|
@ -500,6 +577,9 @@ func (a *Admin) getACopy() Admin {
|
|||
Used: code.Used,
|
||||
})
|
||||
}
|
||||
filters.Preferences = AdminPreferences{
|
||||
HideUserPageSections: a.Filters.Preferences.HideUserPageSections,
|
||||
}
|
||||
groups := make([]AdminGroupMapping, 0, len(a.Groups))
|
||||
for _, g := range a.Groups {
|
||||
groups = append(groups, AdminGroupMapping{
|
||||
|
|
|
@ -231,7 +231,14 @@ func (g *Group) getACopy() Group {
|
|||
}
|
||||
}
|
||||
|
||||
// GetUsersAsString returns the list of users as comma separated string
|
||||
func (g *Group) GetUsersAsString() string {
|
||||
return strings.Join(g.Users, ",")
|
||||
// GetMembersAsString returns a string representation for the group members
|
||||
func (g *Group) GetMembersAsString() string {
|
||||
var sb strings.Builder
|
||||
if len(g.Users) > 0 {
|
||||
sb.WriteString(fmt.Sprintf("Users: %d. ", len(g.Users)))
|
||||
}
|
||||
if len(g.Admins) > 0 {
|
||||
sb.WriteString(fmt.Sprintf("Admins: %d. ", len(g.Admins)))
|
||||
}
|
||||
return sb.String()
|
||||
}
|
||||
|
|
|
@ -53,7 +53,8 @@ const (
|
|||
claimPermissionsKey = "permissions"
|
||||
claimAPIKey = "api_key"
|
||||
claimMustSetSecondFactorKey = "2fa_required"
|
||||
claimRequiredTwoFactorProtocols = "2fa_protocols"
|
||||
claimRequiredTwoFactorProtocols = "2fa_protos"
|
||||
claimHideUserPageSection = "hus"
|
||||
basicRealm = "Basic realm=\"SFTPGo\""
|
||||
jwtCookieKey = "jwt"
|
||||
)
|
||||
|
@ -75,6 +76,7 @@ type jwtTokenClaims struct {
|
|||
APIKeyID string
|
||||
MustSetTwoFactorAuth bool
|
||||
RequiredTwoFactorProtocols []string
|
||||
HideUserPageSections int
|
||||
}
|
||||
|
||||
func (c *jwtTokenClaims) hasUserAudience() bool {
|
||||
|
@ -96,12 +98,35 @@ func (c *jwtTokenClaims) asMap() map[string]any {
|
|||
claims[claimAPIKey] = c.APIKeyID
|
||||
}
|
||||
claims[jwt.SubjectKey] = c.Signature
|
||||
claims[claimMustSetSecondFactorKey] = c.MustSetTwoFactorAuth
|
||||
claims[claimRequiredTwoFactorProtocols] = c.RequiredTwoFactorProtocols
|
||||
if c.MustSetTwoFactorAuth {
|
||||
claims[claimMustSetSecondFactorKey] = c.MustSetTwoFactorAuth
|
||||
}
|
||||
if len(c.RequiredTwoFactorProtocols) > 0 {
|
||||
claims[claimRequiredTwoFactorProtocols] = c.RequiredTwoFactorProtocols
|
||||
}
|
||||
if c.HideUserPageSections > 0 {
|
||||
claims[claimHideUserPageSection] = c.HideUserPageSections
|
||||
}
|
||||
|
||||
return claims
|
||||
}
|
||||
|
||||
func (c *jwtTokenClaims) decodeSliceString(val any) []string {
|
||||
var result []string
|
||||
|
||||
switch v := val.(type) {
|
||||
case []any:
|
||||
for _, elem := range v {
|
||||
switch elemValue := elem.(type) {
|
||||
case string:
|
||||
result = append(result, elemValue)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
func (c *jwtTokenClaims) Decode(token map[string]any) {
|
||||
c.Permissions = nil
|
||||
username := token[claimUsernameKey]
|
||||
|
@ -133,30 +158,23 @@ func (c *jwtTokenClaims) Decode(token map[string]any) {
|
|||
}
|
||||
|
||||
permissions := token[claimPermissionsKey]
|
||||
switch v := permissions.(type) {
|
||||
case []any:
|
||||
for _, elem := range v {
|
||||
switch elemValue := elem.(type) {
|
||||
case string:
|
||||
c.Permissions = append(c.Permissions, elemValue)
|
||||
}
|
||||
c.Permissions = c.decodeSliceString(permissions)
|
||||
|
||||
if val, ok := token[claimMustSetSecondFactorKey]; ok {
|
||||
switch v := val.(type) {
|
||||
case bool:
|
||||
c.MustSetTwoFactorAuth = v
|
||||
}
|
||||
}
|
||||
|
||||
secondFactorRequired := token[claimMustSetSecondFactorKey]
|
||||
switch v := secondFactorRequired.(type) {
|
||||
case bool:
|
||||
c.MustSetTwoFactorAuth = v
|
||||
if val, ok := token[claimRequiredTwoFactorProtocols]; ok {
|
||||
c.RequiredTwoFactorProtocols = c.decodeSliceString(val)
|
||||
}
|
||||
|
||||
secondFactorProtocols := token[claimRequiredTwoFactorProtocols]
|
||||
switch v := secondFactorProtocols.(type) {
|
||||
case []any:
|
||||
for _, elem := range v {
|
||||
switch elemValue := elem.(type) {
|
||||
case string:
|
||||
c.RequiredTwoFactorProtocols = append(c.RequiredTwoFactorProtocols, elemValue)
|
||||
}
|
||||
if val, ok := token[claimHideUserPageSection]; ok {
|
||||
switch v := val.(type) {
|
||||
case float64:
|
||||
c.HideUserPageSections = int(v)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -319,6 +337,7 @@ func getAdminFromToken(r *http.Request) *dataprovider.Admin {
|
|||
tokenClaims.Decode(claims)
|
||||
admin.Username = tokenClaims.Username
|
||||
admin.Permissions = tokenClaims.Permissions
|
||||
admin.Filters.Preferences.HideUserPageSections = tokenClaims.HideUserPageSections
|
||||
return admin
|
||||
}
|
||||
|
||||
|
|
|
@ -2707,16 +2707,32 @@ func TestBasicAdminHandling(t *testing.T) {
|
|||
assert.NoError(t, err)
|
||||
|
||||
admin.Username = altAdminUsername
|
||||
admin.Filters.Preferences.HideUserPageSections = 1 + 4 + 8
|
||||
admin, _, err = httpdtest.AddAdmin(admin, http.StatusCreated)
|
||||
assert.NoError(t, err)
|
||||
|
||||
admin, _, err = httpdtest.GetAdminByUsername(admin.Username, http.StatusOK)
|
||||
assert.NoError(t, err)
|
||||
assert.True(t, admin.Filters.Preferences.HideGroups())
|
||||
assert.False(t, admin.Filters.Preferences.HideFilesystem())
|
||||
assert.True(t, admin.Filters.Preferences.HideVirtualFolders())
|
||||
assert.True(t, admin.Filters.Preferences.HideProfile())
|
||||
assert.False(t, admin.Filters.Preferences.HideACLs())
|
||||
assert.False(t, admin.Filters.Preferences.HideDiskQuotaAndBandwidthLimits())
|
||||
assert.False(t, admin.Filters.Preferences.HideAdvancedSettings())
|
||||
|
||||
admin.AdditionalInfo = "test info"
|
||||
admin.Filters.Preferences.HideUserPageSections = 16 + 32 + 64
|
||||
admin, _, err = httpdtest.UpdateAdmin(admin, http.StatusOK)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, "test info", admin.AdditionalInfo)
|
||||
assert.False(t, admin.Filters.Preferences.HideGroups())
|
||||
assert.False(t, admin.Filters.Preferences.HideFilesystem())
|
||||
assert.False(t, admin.Filters.Preferences.HideVirtualFolders())
|
||||
assert.False(t, admin.Filters.Preferences.HideProfile())
|
||||
assert.True(t, admin.Filters.Preferences.HideACLs())
|
||||
assert.True(t, admin.Filters.Preferences.HideDiskQuotaAndBandwidthLimits())
|
||||
assert.True(t, admin.Filters.Preferences.HideAdvancedSettings())
|
||||
|
||||
admins, _, err = httpdtest.GetAdmins(1, 0, http.StatusOK)
|
||||
assert.NoError(t, err)
|
||||
|
@ -15722,6 +15738,7 @@ func TestWebAdminPwdChange(t *testing.T) {
|
|||
admin := getTestAdmin()
|
||||
admin.Username = altAdminUsername
|
||||
admin.Password = altAdminPassword
|
||||
admin.Filters.Preferences.HideUserPageSections = 16 + 32
|
||||
admin, _, err := httpdtest.AddAdmin(admin, http.StatusCreated)
|
||||
assert.NoError(t, err)
|
||||
|
||||
|
@ -16270,6 +16287,13 @@ func TestWebAdminBasicMock(t *testing.T) {
|
|||
form.Set("status", "1")
|
||||
form.Set("permissions", "*")
|
||||
form.Set("description", admin.Description)
|
||||
form.Set("user_page_hidden_sections", "1")
|
||||
form.Add("user_page_hidden_sections", "2")
|
||||
form.Add("user_page_hidden_sections", "3")
|
||||
form.Add("user_page_hidden_sections", "4")
|
||||
form.Add("user_page_hidden_sections", "5")
|
||||
form.Add("user_page_hidden_sections", "6")
|
||||
form.Add("user_page_hidden_sections", "7")
|
||||
req, _ := http.NewRequest(http.MethodPost, webAdminPath, bytes.NewBuffer([]byte(form.Encode())))
|
||||
req.RemoteAddr = defaultRemoteAddr
|
||||
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
|
||||
|
@ -16337,6 +16361,7 @@ func TestWebAdminBasicMock(t *testing.T) {
|
|||
assert.True(t, admin.Filters.TOTPConfig.Enabled)
|
||||
secretPayload := admin.Filters.TOTPConfig.Secret.GetPayload()
|
||||
assert.NotEmpty(t, secretPayload)
|
||||
assert.Equal(t, 1+2+4+8+16+32+64, admin.Filters.Preferences.HideUserPageSections)
|
||||
|
||||
adminTOTPConfig = dataprovider.AdminTOTPConfig{
|
||||
Enabled: true,
|
||||
|
|
|
@ -190,19 +190,20 @@ func newOIDCPendingAuth(audience tokenAudience) oidcPendingAuth {
|
|||
}
|
||||
|
||||
type oidcToken struct {
|
||||
AccessToken string `json:"access_token"`
|
||||
TokenType string `json:"token_type,omitempty"`
|
||||
RefreshToken string `json:"refresh_token,omitempty"`
|
||||
ExpiresAt int64 `json:"expires_at,omitempty"`
|
||||
SessionID string `json:"session_id"`
|
||||
IDToken string `json:"id_token"`
|
||||
Nonce string `json:"nonce"`
|
||||
Username string `json:"username"`
|
||||
Permissions []string `json:"permissions"`
|
||||
Role any `json:"role"`
|
||||
CustomFields *map[string]any `json:"custom_fields,omitempty"`
|
||||
Cookie string `json:"cookie"`
|
||||
UsedAt int64 `json:"used_at"`
|
||||
AccessToken string `json:"access_token"`
|
||||
TokenType string `json:"token_type,omitempty"`
|
||||
RefreshToken string `json:"refresh_token,omitempty"`
|
||||
ExpiresAt int64 `json:"expires_at,omitempty"`
|
||||
SessionID string `json:"session_id"`
|
||||
IDToken string `json:"id_token"`
|
||||
Nonce string `json:"nonce"`
|
||||
Username string `json:"username"`
|
||||
Permissions []string `json:"permissions"`
|
||||
HideUserPageSections int `json:"hide_user_page_sections,omitempty"`
|
||||
Role any `json:"role"`
|
||||
CustomFields *map[string]any `json:"custom_fields,omitempty"`
|
||||
Cookie string `json:"cookie"`
|
||||
UsedAt int64 `json:"used_at"`
|
||||
}
|
||||
|
||||
func (t *oidcToken) parseClaims(claims map[string]any, usernameField, roleField string, customFields []string,
|
||||
|
@ -378,6 +379,7 @@ func (t *oidcToken) getUser(r *http.Request) error {
|
|||
return err
|
||||
}
|
||||
t.Permissions = admin.Permissions
|
||||
t.HideUserPageSections = admin.Filters.Preferences.HideUserPageSections
|
||||
dataprovider.UpdateAdminLastLogin(&admin)
|
||||
return nil
|
||||
}
|
||||
|
@ -474,8 +476,9 @@ func (s *httpdServer) oidcTokenAuthenticator(audience tokenAudience) func(next h
|
|||
return
|
||||
}
|
||||
jwtTokenClaims := jwtTokenClaims{
|
||||
Username: token.Username,
|
||||
Permissions: token.Permissions,
|
||||
Username: token.Username,
|
||||
Permissions: token.Permissions,
|
||||
HideUserPageSections: token.HideUserPageSections,
|
||||
}
|
||||
_, tokenString, err := jwtTokenClaims.createToken(s.tokenAuth, audience, util.GetIPFromRemoteAddress(r.RemoteAddr))
|
||||
if err != nil {
|
||||
|
|
|
@ -715,9 +715,10 @@ func (s *httpdServer) loginAdmin(
|
|||
ipAddr string,
|
||||
) {
|
||||
c := jwtTokenClaims{
|
||||
Username: admin.Username,
|
||||
Permissions: admin.Permissions,
|
||||
Signature: admin.GetSignature(),
|
||||
Username: admin.Username,
|
||||
Permissions: admin.Permissions,
|
||||
Signature: admin.GetSignature(),
|
||||
HideUserPageSections: admin.Filters.Preferences.HideUserPageSections,
|
||||
}
|
||||
|
||||
audience := tokenAudienceWebAdmin
|
||||
|
@ -973,6 +974,7 @@ func (s *httpdServer) refreshAdminToken(w http.ResponseWriter, r *http.Request,
|
|||
return
|
||||
}
|
||||
tokenClaims.Permissions = admin.Permissions
|
||||
tokenClaims.HideUserPageSections = admin.Filters.Preferences.HideUserPageSections
|
||||
logger.Debug(logSender, "", "cookie refreshed for admin %#v", admin.Username)
|
||||
tokenClaims.createAndSetCookie(w, r, s.tokenAuth, tokenAudienceWebAdmin, ipAddr) //nolint:errcheck
|
||||
}
|
||||
|
|
|
@ -207,6 +207,7 @@ type fsWrapper struct {
|
|||
vfs.Filesystem
|
||||
IsUserPage bool
|
||||
IsGroupPage bool
|
||||
IsHidden bool
|
||||
HasUsersBaseDir bool
|
||||
DirPath string
|
||||
}
|
||||
|
@ -855,6 +856,7 @@ func (s *httpdServer) renderUserPage(w http.ResponseWriter, r *http.Request, use
|
|||
Filesystem: user.FsConfig,
|
||||
IsUserPage: true,
|
||||
IsGroupPage: false,
|
||||
IsHidden: basePage.LoggedAdmin.Filters.Preferences.HideFilesystem(),
|
||||
HasUsersBaseDir: dataprovider.HasUsersBaseDir(),
|
||||
DirPath: user.HomeDir,
|
||||
},
|
||||
|
@ -1540,6 +1542,31 @@ func getFsConfigFromPostFields(r *http.Request) (vfs.Filesystem, error) {
|
|||
return fs, nil
|
||||
}
|
||||
|
||||
func getAdminHiddenUserPageSections(r *http.Request) int {
|
||||
var result int
|
||||
|
||||
for _, val := range r.Form["user_page_hidden_sections"] {
|
||||
switch val {
|
||||
case "1":
|
||||
result++
|
||||
case "2":
|
||||
result += 2
|
||||
case "3":
|
||||
result += 4
|
||||
case "4":
|
||||
result += 8
|
||||
case "5":
|
||||
result += 16
|
||||
case "6":
|
||||
result += 32
|
||||
case "7":
|
||||
result += 64
|
||||
}
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
func getAdminFromPostFields(r *http.Request) (dataprovider.Admin, error) {
|
||||
var admin dataprovider.Admin
|
||||
err := r.ParseForm()
|
||||
|
@ -1559,6 +1586,7 @@ func getAdminFromPostFields(r *http.Request) (dataprovider.Admin, error) {
|
|||
admin.Filters.AllowAPIKeyAuth = r.Form.Get("allow_api_key_auth") != ""
|
||||
admin.AdditionalInfo = r.Form.Get("additional_info")
|
||||
admin.Description = r.Form.Get("description")
|
||||
admin.Filters.Preferences.HideUserPageSections = getAdminHiddenUserPageSections(r)
|
||||
for k := range r.Form {
|
||||
if strings.HasPrefix(k, "group") {
|
||||
groupName := strings.TrimSpace(r.Form.Get(k))
|
||||
|
|
|
@ -1624,19 +1624,28 @@ func checkAdmin(expected, actual *dataprovider.Admin) error {
|
|||
return errors.New("permissions content mismatch")
|
||||
}
|
||||
}
|
||||
if expected.Filters.AllowAPIKeyAuth != actual.Filters.AllowAPIKeyAuth {
|
||||
if err := compareAdminFilters(expected.Filters, actual.Filters); err != nil {
|
||||
return err
|
||||
}
|
||||
return compareAdminGroups(expected, actual)
|
||||
}
|
||||
|
||||
func compareAdminFilters(expected, actual dataprovider.AdminFilters) error {
|
||||
if expected.AllowAPIKeyAuth != actual.AllowAPIKeyAuth {
|
||||
return errors.New("allow_api_key_auth mismatch")
|
||||
}
|
||||
if len(expected.Filters.AllowList) != len(actual.Filters.AllowList) {
|
||||
if len(expected.AllowList) != len(actual.AllowList) {
|
||||
return errors.New("allow list mismatch")
|
||||
}
|
||||
for _, v := range expected.Filters.AllowList {
|
||||
if !util.Contains(actual.Filters.AllowList, v) {
|
||||
for _, v := range expected.AllowList {
|
||||
if !util.Contains(actual.AllowList, v) {
|
||||
return errors.New("allow list content mismatch")
|
||||
}
|
||||
}
|
||||
|
||||
return compareAdminGroups(expected, actual)
|
||||
if expected.Preferences.HideUserPageSections != actual.Preferences.HideUserPageSections {
|
||||
return errors.New("hide user page sections mismatch")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func compareAdminEqualFields(expected *dataprovider.Admin, actual *dataprovider.Admin) error {
|
||||
|
|
|
@ -5227,6 +5227,12 @@ components:
|
|||
type: object
|
||||
additionalProperties: true
|
||||
description: 'This field is passed to the pre-login hook if custom OIDC token fields have been configured. Field values can be of any type (this is a free form object) and depend on the type of the configured OIDC token fields'
|
||||
AdminPreferences:
|
||||
type: object
|
||||
properties:
|
||||
hide_user_page_sections:
|
||||
type: integer
|
||||
description: 'Allow to hide some sections from the user page. These are not security settings and are not enforced server side in any way. They are only intended to simplify the user page in the WebAdmin UI. 1 means hide groups section, 2 means hide filesystem section, "users_base_dir" must be set in the config file otherwise this setting is ignored, 4 means hide virtual folders section, 8 means hide profile section, 16 means hide ACLs section, 32 means hide disk and bandwidth quota limits section, 64 means hide advanced settings section. The settings can be combined'
|
||||
AdminFilters:
|
||||
type: object
|
||||
properties:
|
||||
|
@ -5247,6 +5253,8 @@ components:
|
|||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/RecoveryCode'
|
||||
preferences:
|
||||
$ref: '#/components/schemas/AdminPreferences'
|
||||
Admin:
|
||||
type: object
|
||||
properties:
|
||||
|
|
|
@ -162,6 +162,29 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card bg-light mb-3">
|
||||
<div class="card-header">
|
||||
<b>User page preferences</b>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<h6 class="card-title mb-4">You can hide some sections from the user page. These are not security settings and are not enforced server side in any way. They are only intended to simplify the user page in the WebAdmin UI.</h6>
|
||||
<div class="form-group row">
|
||||
<label for="idUserPageHiddenSections" class="col-sm-2 col-form-label">Hide sections</label>
|
||||
<div class="col-sm-10">
|
||||
<select class="form-control selectpicker" id="idUserPageHiddenSections" name="user_page_hidden_sections" multiple>
|
||||
<option value="1" {{if .Admin.Filters.Preferences.HideGroups}}selected{{end}}>Groups</option>
|
||||
<option value="2" {{if .Admin.Filters.Preferences.HideFilesystem}}selected{{end}}>Filesystem</option>
|
||||
<option value="3" {{if .Admin.Filters.Preferences.HideVirtualFolders}}selected{{end}}>Virtual Folders</option>
|
||||
<option value="4" {{if .Admin.Filters.Preferences.HideProfile}}selected{{end}}>Profile</option>
|
||||
<option value="5" {{if .Admin.Filters.Preferences.HideACLs}}selected{{end}}>ACLs</option>
|
||||
<option value="6" {{if .Admin.Filters.Preferences.HideDiskQuotaAndBandwidthLimits}}selected{{end}}>Disk quota and bandwidth limits</option>
|
||||
<option value="7" {{if .Admin.Filters.Preferences.HideAdvancedSettings}}selected{{end}}>Advanced settings</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group row">
|
||||
<label for="idAllowedIP" class="col-sm-2 col-form-label">Allowed IP/Mask</label>
|
||||
<div class="col-sm-10">
|
||||
|
|
|
@ -14,7 +14,7 @@ You should have received a copy of the GNU Affero General Public License
|
|||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
-->
|
||||
{{define "fshtml"}}
|
||||
<div class="card bg-light mb-3">
|
||||
<div class="card bg-light mb-3 {{if .IsHidden}}d-none{{end}}">
|
||||
<div class="card-header">
|
||||
<b>Filesystem</b>
|
||||
</div>
|
||||
|
|
|
@ -382,7 +382,7 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|||
</button>
|
||||
</h2>
|
||||
</div>
|
||||
<div id="collapseQuota" class="collapse" aria-labelledby="headingTwo" data-parent="#accordionUser">
|
||||
<div id="collapseQuota" class="collapse" aria-labelledby="headingQuota" data-parent="#accordionUser">
|
||||
<div class="card-body">
|
||||
|
||||
<div class="form-group row">
|
||||
|
@ -663,7 +663,7 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|||
</button>
|
||||
</h2>
|
||||
</div>
|
||||
<div id="collapseAdvanced" class="collapse" aria-labelledby="headingTwo" data-parent="#accordionUser">
|
||||
<div id="collapseAdvanced" class="collapse" aria-labelledby="headingAdvanced" data-parent="#accordionUser">
|
||||
<div class="card-body">
|
||||
|
||||
<div class="form-group row">
|
||||
|
|
|
@ -41,6 +41,7 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|||
<tr>
|
||||
<th>Name</th>
|
||||
<th>Description</th>
|
||||
<th>Members</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
|
@ -48,6 +49,7 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|||
<tr>
|
||||
<td>{{.Name}}</td>
|
||||
<td>{{.Description}}</td>
|
||||
<td>{{.GetMembersAsString}}</td>
|
||||
</tr>
|
||||
{{end}}
|
||||
</tbody>
|
||||
|
@ -183,7 +185,11 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|||
{
|
||||
"targets": [0],
|
||||
"className": "noVis"
|
||||
}
|
||||
},
|
||||
{
|
||||
"targets": [2],
|
||||
"render": $.fn.dataTable.render.ellipsis(100, true)
|
||||
},
|
||||
],
|
||||
"scrollX": false,
|
||||
"scrollY": false,
|
||||
|
|
|
@ -156,7 +156,8 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|||
</div>
|
||||
{{end}}
|
||||
|
||||
<div class="card bg-light mb-3">
|
||||
{{if .Groups}}
|
||||
<div class="card bg-light mb-3 {{if .LoggedAdmin.Filters.Preferences.HideGroups}}d-none{{end}}">
|
||||
<div class="card-header">
|
||||
<b>Groups</b>
|
||||
</div>
|
||||
|
@ -195,10 +196,11 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{end}}
|
||||
|
||||
{{template "fshtml" .FsWrapper}}
|
||||
{{if .VirtualFolders}}
|
||||
<div class="card bg-light mb-3">
|
||||
<div class="card bg-light mb-3 {{if .LoggedAdmin.Filters.Preferences.HideVirtualFolders}}d-none{{end}}">
|
||||
<div class="card-header">
|
||||
<b>Virtual folders</b>
|
||||
</div>
|
||||
|
@ -285,8 +287,8 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|||
</div>
|
||||
{{end}}
|
||||
|
||||
<div class="accordion" id="accordionUser">
|
||||
<div class="card">
|
||||
<div class="accordion {{if eq .LoggedAdmin.Filters.Preferences.VisibleUserPageSections 0}}d-none{{end}}" id="accordionUser">
|
||||
<div class="card {{if .LoggedAdmin.Filters.Preferences.HideProfile}}d-none{{end}}">
|
||||
<div class="card-header" id="headingProfile">
|
||||
<h2 class="mb-0">
|
||||
<button class="btn btn-link btn-block text-left" type="button" data-toggle="collapse"
|
||||
|
@ -352,7 +354,7 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card">
|
||||
<div class="card {{if .LoggedAdmin.Filters.Preferences.HideACLs}}d-none{{end}}">
|
||||
<div class="card-header" id="headingPermissions">
|
||||
<h2 class="mb-0">
|
||||
<button class="btn btn-link btn-block text-left" type="button" data-toggle="collapse"
|
||||
|
@ -590,7 +592,7 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card">
|
||||
<div class="card {{if .LoggedAdmin.Filters.Preferences.HideDiskQuotaAndBandwidthLimits}}d-none{{end}}">
|
||||
<div class="card-header" id="headingQuota">
|
||||
<h2 class="mb-0">
|
||||
<button class="btn btn-link btn-block text-left collapsed" type="button" data-toggle="collapse"
|
||||
|
@ -599,7 +601,7 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|||
</button>
|
||||
</h2>
|
||||
</div>
|
||||
<div id="collapseQuota" class="collapse" aria-labelledby="headingTwo" data-parent="#accordionUser">
|
||||
<div id="collapseQuota" class="collapse" aria-labelledby="headingQuota" data-parent="#accordionUser">
|
||||
<div class="card-body">
|
||||
|
||||
<div class="form-group row">
|
||||
|
@ -871,7 +873,7 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<div class="card {{if .LoggedAdmin.Filters.Preferences.HideAdvancedSettings}}d-none{{end}}">
|
||||
<div class="card-header" id="headingAdvanced">
|
||||
<h2 class="mb-0">
|
||||
<button class="btn btn-link btn-block text-left collapsed" type="button" data-toggle="collapse"
|
||||
|
@ -880,7 +882,7 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|||
</button>
|
||||
</h2>
|
||||
</div>
|
||||
<div id="collapseAdvanced" class="collapse" aria-labelledby="headingTwo" data-parent="#accordionUser">
|
||||
<div id="collapseAdvanced" class="collapse" aria-labelledby="headingAdvanced" data-parent="#accordionUser">
|
||||
<div class="card-body">
|
||||
|
||||
<div class="form-group row">
|
||||
|
@ -1044,10 +1046,11 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|||
<script src="{{.StaticURL}}/vendor/bootstrap-select/js/bootstrap-select.min.js"></script>
|
||||
<script type="text/javascript">
|
||||
$(document).ready(function () {
|
||||
$.fn.selectpicker.Constructor.BootstrapVersion = '4';
|
||||
{{if .Error}}
|
||||
{{if ne .LoggedAdmin.Filters.Preferences.VisibleUserPageSections 0}}
|
||||
$('#accordionUser .collapse').removeAttr("data-parent").collapse('show');
|
||||
{{end}}
|
||||
{{end}}
|
||||
$('#expirationDatePicker').datetimepicker({
|
||||
format: 'YYYY-MM-DD',
|
||||
buttons: {
|
||||
|
|
Loading…
Reference in a new issue