WebAdmin: allow to simplify the user page

Signed-off-by: Nicola Murino <nicola.murino@gmail.com>
This commit is contained in:
Nicola Murino 2022-09-21 19:36:08 +02:00
parent 7349598b19
commit bd294bb3cf
No known key found for this signature in database
GPG key ID: 2F1FB59433D5A8CB
16 changed files with 337 additions and 124 deletions

40
go.mod
View file

@ -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
View file

@ -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=

View file

@ -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{

View file

@ -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()
}

View file

@ -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
}

View file

@ -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,

View file

@ -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 {

View file

@ -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
}

View file

@ -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))

View file

@ -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 {

View file

@ -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:

View file

@ -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">

View file

@ -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>

View file

@ -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">

View file

@ -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,

View file

@ -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: {