mirror of
https://github.com/h44z/wg-portal.git
synced 2025-10-05 16:06:17 +00:00
Compare commits
4 Commits
v2.0.0-bet
...
v2.0.0-bet
Author | SHA1 | Date | |
---|---|---|---|
|
f6c8cd5ea8 | ||
|
a04eaa4bfb | ||
|
7a0a2117f5 | ||
|
2cea2e477a |
2
.gitignore
vendored
2
.gitignore
vendored
@@ -38,3 +38,5 @@ venv/
|
||||
.cache/
|
||||
# ignore local frontend dist directory
|
||||
internal/app/api/core/frontend-dist
|
||||
# mkdocs output directory
|
||||
site/
|
||||
|
@@ -134,6 +134,7 @@ The following configuration options are available:
|
||||
| login_filter | auth/ldap | | LDAP filters for users that should be allowed to log in. {{login_identifier}} will be replaced with the login username. |
|
||||
| admin_group | auth/ldap | | Users in this group are marked as administrators. |
|
||||
| disable_missing | auth/ldap | | If synchronization is enabled, missing LDAP users will be disabled in WireGuard Portal. |
|
||||
| auto_re_enable | auth/ldap | | If auto re-enable is true, users that where disabled because they were missing will be re-enabled once they are found again. |
|
||||
| sync_filter | auth/ldap | | LDAP filters for users that should be synchronized to WireGuard Portal. |
|
||||
| sync_interval | auth/ldap | | The time interval after which users will be synchronized from LDAP. Empty value or `0` disables synchronization. |
|
||||
| registration_enabled | auth/ldap | | If registration is enabled, new user accounts will created in WireGuard Portal. |
|
||||
|
@@ -7,9 +7,9 @@ import (
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/swaggo/swag"
|
||||
"github.com/swaggo/swag/gen"
|
||||
"gopkg.in/yaml.v2"
|
||||
)
|
||||
|
||||
var apiRootPath = "/internal/app/api"
|
||||
@@ -26,7 +26,6 @@ func main() {
|
||||
apiBasePath := filepath.Join(wd, apiRootPath)
|
||||
apis := []string{"v0", "v1"}
|
||||
|
||||
hasError := false
|
||||
for _, apiVersion := range apis {
|
||||
apiPath := filepath.Join(apiBasePath, apiVersion, "handlers")
|
||||
|
||||
@@ -37,14 +36,13 @@ func main() {
|
||||
|
||||
err := generateApi(apiBasePath, apiPath, apiVersion)
|
||||
if err != nil {
|
||||
hasError = true
|
||||
logrus.Errorf("failed to generate API docs for %s: %v", apiVersion, err)
|
||||
log.Fatalf("failed to generate API docs for %s: %v", apiVersion, err)
|
||||
}
|
||||
|
||||
// copy the latest version of the API docs for mkdocs
|
||||
if apiVersion == apis[len(apis)-1] {
|
||||
if err = copyDocForMkdocs(wd, apiBasePath, apiVersion); err != nil {
|
||||
logrus.Errorf("failed to copy API docs for mkdocs: %v", err)
|
||||
log.Printf("failed to copy API docs for mkdocs: %v", err)
|
||||
} else {
|
||||
log.Println("Copied API docs " + apiVersion + " for mkdocs")
|
||||
}
|
||||
@@ -52,10 +50,6 @@ func main() {
|
||||
|
||||
log.Println("Generated swagger docs for API", apiVersion)
|
||||
}
|
||||
|
||||
if hasError {
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
func generateApi(basePath, apiPath, version string) error {
|
||||
@@ -92,10 +86,32 @@ func copyDocForMkdocs(workingDir, basePath, version string) error {
|
||||
return fmt.Errorf("error while reading swagger doc: %w", err)
|
||||
}
|
||||
|
||||
err = os.WriteFile(dstPath, input, 0644)
|
||||
output, err := removeAuthorizeButton(input)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error while removing authorize button: %w", err)
|
||||
}
|
||||
|
||||
err = os.WriteFile(dstPath, output, 0644)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error while writing swagger doc: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func removeAuthorizeButton(input []byte) ([]byte, error) {
|
||||
var swagger map[string]interface{}
|
||||
err := yaml.Unmarshal(input, &swagger)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error while unmarshalling swagger file: %w", err)
|
||||
}
|
||||
|
||||
delete(swagger, "securityDefinitions")
|
||||
|
||||
output, err := yaml.Marshal(&swagger)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error while marshalling swagger file: %w", err)
|
||||
}
|
||||
|
||||
return output, nil
|
||||
}
|
||||
|
@@ -444,6 +444,10 @@ Below are the properties for each LDAP provider entry inside `auth.ldap`:
|
||||
- **Default:** *(empty)*
|
||||
- **Description:** If `true`, any user **not** found in LDAP (during sync) is disabled in WireGuard Portal.
|
||||
|
||||
#### `auto_re_enable`
|
||||
- **Default:** *(empty)*
|
||||
- **Description:** If `true`, users that where disabled because they were missing (see `disable_missing`) will be re-enabled once they are found again.
|
||||
|
||||
#### `registration_enabled`
|
||||
- **Default:** *(empty)*
|
||||
- **Description:** If `true`, new user accounts are created in WireGuard Portal upon first login.
|
||||
|
@@ -1540,7 +1540,4 @@ paths:
|
||||
summary: Create a new user record.
|
||||
tags:
|
||||
- Users
|
||||
securityDefinitions:
|
||||
BasicAuth:
|
||||
type: basic
|
||||
swagger: "2.0"
|
||||
|
1
go.mod
1
go.mod
@@ -42,7 +42,6 @@ require (
|
||||
github.com/bytedance/sonic/loader v0.2.2 // indirect
|
||||
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
||||
github.com/cloudwego/base64x v0.1.4 // indirect
|
||||
github.com/cloudwego/iasm v0.2.0 // indirect
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/dchest/uniuri v1.2.0 // indirect
|
||||
github.com/dustin/go-humanize v1.0.1 // indirect
|
||||
|
35
go.sum
35
go.sum
@@ -34,20 +34,15 @@ github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6r
|
||||
github.com/boj/redistore v0.0.0-20180917114910-cd5dcc76aeff/go.mod h1:+RTT1BOk5P97fT2CiHkbFQwkK3mjsFAP6zCYV2aXtjw=
|
||||
github.com/bradfitz/gomemcache v0.0.0-20180710155616-bc664df96737/go.mod h1:PmM6Mmwb0LSuEubjR8N7PtNe1KxZLtOUHtbeikc5h60=
|
||||
github.com/bradleypeabody/gorilla-sessions-memcache v0.0.0-20181103040241-659414f458e1/go.mod h1:dkChI7Tbtx7H1Tj7TqGSZMOeGpMP5gLHtjroHd4agiI=
|
||||
github.com/bytedance/sonic v1.12.6 h1:/isNmCUF2x3Sh8RAp/4mh4ZGkcFAX/hLrzrK3AvpRzk=
|
||||
github.com/bytedance/sonic v1.12.6/go.mod h1:B8Gt/XvtZ3Fqj+iSKMypzymZxw/FVwgIGKzMzT9r/rk=
|
||||
github.com/bytedance/sonic v1.12.7 h1:CQU8pxOy9HToxhndH0Kx/S1qU/CuS9GnKYrGioDcU1Q=
|
||||
github.com/bytedance/sonic v1.12.7/go.mod h1:tnbal4mxOMju17EGfknm2XyYcpyCnIROYOEYuemj13I=
|
||||
github.com/bytedance/sonic/loader v0.1.1/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU=
|
||||
github.com/bytedance/sonic/loader v0.2.1 h1:1GgorWTqf12TA8mma4DDSbaQigE2wOgQo7iCjjJv3+E=
|
||||
github.com/bytedance/sonic/loader v0.2.1/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU=
|
||||
github.com/bytedance/sonic/loader v0.2.2 h1:jxAJuN9fOot/cyz5Q6dUuMJF5OqQ6+5GfA8FjjQ0R4o=
|
||||
github.com/bytedance/sonic/loader v0.2.2/go.mod h1:N8A3vUdtUebEY2/VQC0MyhYeKUFosQU6FxH2JmUe6VI=
|
||||
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
|
||||
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||
github.com/cloudwego/base64x v0.1.4 h1:jwCgWpFanWmN8xoIUHa2rtzmkd5J2plF/dnLS6Xd/0Y=
|
||||
github.com/cloudwego/base64x v0.1.4/go.mod h1:0zlkT4Wn5C6NdauXdJRhSKRlJvmclQ1hhJgA0rcu/8w=
|
||||
github.com/cloudwego/iasm v0.2.0 h1:1KNIy1I1H9hNNFEEH3DVnI4UujN+1zjpuk6gwHLTssg=
|
||||
github.com/cloudwego/iasm v0.2.0/go.mod h1:8rXZaNYT2n95jn+zTI1sDr+IgcD2GVs0nlbbQPiEFhY=
|
||||
github.com/coreos/go-oidc/v3 v3.12.0 h1:sJk+8G2qq94rDI6ehZ71Bol3oUHy63qNYmkiSjrc/Jo=
|
||||
github.com/coreos/go-oidc/v3 v3.12.0/go.mod h1:gE3LgjOgFoHi9a4ce4/tJczr0Ai2/BoDhf0r5lltWI0=
|
||||
@@ -100,8 +95,6 @@ github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/o
|
||||
github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY=
|
||||
github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY=
|
||||
github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
|
||||
github.com/go-playground/validator/v10 v10.23.0 h1:/PwmTwZhS0dPkav3cdK9kV1FsAmrL8sThn8IHr/sO+o=
|
||||
github.com/go-playground/validator/v10 v10.23.0/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM=
|
||||
github.com/go-playground/validator/v10 v10.24.0 h1:KHQckvo8G6hlWnrPX4NJJ+aBfWNAE/HH+qdL2cBpCmg=
|
||||
github.com/go-playground/validator/v10 v10.24.0/go.mod h1:GGzBIJMuE98Ic/kJsBXbz1x/7cByt++cQ+YOuDM5wus=
|
||||
github.com/go-sql-driver/mysql v1.7.0/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI=
|
||||
@@ -308,12 +301,9 @@ golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq
|
||||
golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg=
|
||||
golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
|
||||
golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
|
||||
golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U=
|
||||
golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk=
|
||||
golang.org/x/crypto v0.32.0 h1:euUpcYgM8WcP71gNpTqQCn6rC2t6ULUPiOzfWaXVVfc=
|
||||
golang.org/x/crypto v0.32.0/go.mod h1:ZnnJkOaASj8g0AjIduWNlq2NRxL0PlBrbKVyZ6V/Ugc=
|
||||
golang.org/x/exp v0.0.0-20250103183323-7d7fa50e5329 h1:9kj3STMvgqy3YA4VQXBrN7925ICMxD5wzMRcgA30588=
|
||||
golang.org/x/exp v0.0.0-20250103183323-7d7fa50e5329/go.mod h1:qj5a5QZpwLU2NLQudwIN5koi3beDhSAlJwa67PuM98c=
|
||||
golang.org/x/exp v0.0.0-20250106191152-7588d65b2ba8 h1:yqrTHse8TCMW1M1ZCP+VAR/l0kKxwaAIqN/il7x4voA=
|
||||
golang.org/x/exp v0.0.0-20250106191152-7588d65b2ba8/go.mod h1:tujkw807nyEEAamNbDrEGzRav+ilXA7PCRAd6xsmwiU=
|
||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||
@@ -340,7 +330,6 @@ golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U=
|
||||
golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY=
|
||||
golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
|
||||
golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
|
||||
golang.org/x/net v0.33.0 h1:74SYHlV8BIgHIFC/LrYkOGIwL19eTYXQ5wc6TBuO36I=
|
||||
golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4=
|
||||
golang.org/x/net v0.34.0 h1:Mb7Mrk043xzHgnRM88suvJFwzVrRfHEHJEl5/71CKw0=
|
||||
golang.org/x/net v0.34.0/go.mod h1:di0qlW3YNM5oh6GqDGQr92MyTozJPmybPK4Ev/Gm31k=
|
||||
@@ -413,8 +402,6 @@ golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc
|
||||
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
|
||||
golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58=
|
||||
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk=
|
||||
golang.org/x/tools v0.28.0 h1:WuB6qZ4RPCQo5aP3WdKZS7i595EdWqWR8vqJTlwTVK8=
|
||||
golang.org/x/tools v0.28.0/go.mod h1:dcIOrVd3mfQKTgrDVQHqCPMWy6lnhfhtX3hLXYVLfRw=
|
||||
golang.org/x/tools v0.29.0 h1:Xx0h3TtM9rzQpQuR4dKLrdglAmCEN5Oi+P74JdhdzXE=
|
||||
golang.org/x/tools v0.29.0/go.mod h1:KMQVMRsVxU6nHCFXrBPhDB8XncLNLM0lIy/F14RP588=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
@@ -422,8 +409,6 @@ golang.zx2c4.com/wireguard v0.0.0-20231211153847-12269c276173 h1:/jFs0duh4rdb8uI
|
||||
golang.zx2c4.com/wireguard v0.0.0-20231211153847-12269c276173/go.mod h1:tkCQ4FQXmpAgYVh++1cq16/dH4QJtmvpRv19DWGAHSA=
|
||||
golang.zx2c4.com/wireguard/wgctrl v0.0.0-20241231184526-a9ab2273dd10 h1:3GDAcqdIg1ozBNLgPy4SLT84nfcBjr6rhGtXYtrkWLU=
|
||||
golang.zx2c4.com/wireguard/wgctrl v0.0.0-20241231184526-a9ab2273dd10/go.mod h1:T97yPqesLiNrOYxkwmhMI0ZIlJDm+p0PMR8eRVeR5tQ=
|
||||
google.golang.org/protobuf v1.36.1 h1:yBPeRvTftaleIgM3PZ/WBIZ7XM/eEYAaEyCwvyjq/gk=
|
||||
google.golang.org/protobuf v1.36.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
|
||||
google.golang.org/protobuf v1.36.2 h1:R8FeyR1/eLmkutZOM5CWghmo5itiG9z0ktFlTVLuTmU=
|
||||
google.golang.org/protobuf v1.36.2/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
@@ -451,36 +436,28 @@ gorm.io/gorm v1.25.7-0.20240204074919-46816ad31dde/go.mod h1:hbnx/Oo0ChWMn1BIhpy
|
||||
gorm.io/gorm v1.25.7/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8=
|
||||
gorm.io/gorm v1.25.12 h1:I0u8i2hWQItBq1WfE0o2+WuL9+8L21K9e2HHSTE/0f8=
|
||||
gorm.io/gorm v1.25.12/go.mod h1:xh7N7RHfYlNc5EmcI/El95gXusucDrQnHXe0+CgWcLQ=
|
||||
modernc.org/cc/v4 v4.24.2 h1:uektamHbSXU7egelXcyVpMaaAsrRH4/+uMKUQAQUdOw=
|
||||
modernc.org/cc/v4 v4.24.2/go.mod h1:T1lKJZhXIi2VSqGBiB4LIbKs9NsKTbUXj4IDrmGqtTI=
|
||||
modernc.org/cc/v4 v4.24.4 h1:TFkx1s6dCkQpd6dKurBNmpo+G8Zl4Sq/ztJ+2+DEsh0=
|
||||
modernc.org/ccgo/v4 v4.23.5 h1:6uAwu8u3pnla3l/+UVUrDDO1HIGxHTYmFH6w+X9nsyw=
|
||||
modernc.org/ccgo/v4 v4.23.5/go.mod h1:FogrWfBdzqLWm1ku6cfr4IzEFouq2fSAPf6aSAHdAJQ=
|
||||
modernc.org/cc/v4 v4.24.4/go.mod h1:uVtb5OGqUKpoLWhqwNQo/8LwvoiEBLvZXIQ/SmO6mL0=
|
||||
modernc.org/ccgo/v4 v4.23.10 h1:DnDZT/H6TtoJvQmVf7d8W+lVqEZpIJY/+0ENFh1LIHE=
|
||||
modernc.org/ccgo/v4 v4.23.10/go.mod h1:vdN4h2WR5aEoNondUx26K7G8X+nuBscYnAEWSRmN2/0=
|
||||
modernc.org/fileutil v1.3.0 h1:gQ5SIzK3H9kdfai/5x41oQiKValumqNTDXMvKo62HvE=
|
||||
modernc.org/fileutil v1.3.0/go.mod h1:XatxS8fZi3pS8/hKG2GH/ArUogfxjpEKs3Ku3aK4JyQ=
|
||||
modernc.org/gc/v2 v2.6.0 h1:Tiw3pezQj7PfV8k4Dzyu/vhRHR2e92kOXtTFU8pbCl4=
|
||||
modernc.org/gc/v2 v2.6.0/go.mod h1:wzN5dK1AzVGoH6XOzc3YZ+ey/jPgYHLuVckd62P0GYU=
|
||||
modernc.org/gc/v2 v2.6.1 h1:+Qf6xdG8l7B27TQ8D8lw/iFMUj1RXRBOuMUWziJOsk8=
|
||||
modernc.org/libc v1.61.6 h1:L2jW0wxHPCyHK0YSHaGaVlY0WxjpG/TTVdg6gRJOPqw=
|
||||
modernc.org/libc v1.61.6/go.mod h1:G+DzuaCcReUYYg4nNSfigIfTDCENdj9EByglvaRx53A=
|
||||
modernc.org/gc/v2 v2.6.1/go.mod h1:YgIahr1ypgfe7chRuJi2gD7DBQiKSLMPgBQe9oIiito=
|
||||
modernc.org/libc v1.61.7 h1:exz8rasFniviSgh3dH7QBnQHqYh9lolA5hVYfsiwkfo=
|
||||
modernc.org/libc v1.61.7/go.mod h1:xspSrXRNVSfWfcfqgvZDVe/Hw5kv4FVC6IRfoms5v/0=
|
||||
modernc.org/mathutil v1.7.1 h1:GCZVGXdaN8gTqB1Mf/usp1Y/hSqgI2vAGGP4jZMCxOU=
|
||||
modernc.org/mathutil v1.7.1/go.mod h1:4p5IwJITfppl0G4sUEDtCr4DthTaT47/N3aT6MhfgJg=
|
||||
modernc.org/memory v1.8.1 h1:HS1HRg1jEohnuONobEq2WrLEhLyw8+J42yLFTnllm2A=
|
||||
modernc.org/memory v1.8.1/go.mod h1:ZbjSvMO5NQ1A2i3bWeDiVMxIorXwdClKE/0SZ+BMotU=
|
||||
modernc.org/opt v0.1.3 h1:3XOZf2yznlhC+ibLltsDGzABUGVx8J6pnFMS3E4dcq4=
|
||||
modernc.org/opt v0.1.3/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0=
|
||||
modernc.org/opt v0.1.4 h1:2kNGMRiUjrp4LcaPuLY2PzUfqM/w9N23quVwhKt5Qm8=
|
||||
modernc.org/sortutil v1.2.0 h1:jQiD3PfS2REGJNzNCMMaLSp/wdMNieTbKX920Cqdgqc=
|
||||
modernc.org/sortutil v1.2.0/go.mod h1:TKU2s7kJMf1AE84OoiGppNHJwvB753OYfNl2WRb++Ss=
|
||||
modernc.org/opt v0.1.4/go.mod h1:03fq9lsNfvkYSfxrfUhZCWPk1lm4cq4N+Bh//bEtgns=
|
||||
modernc.org/sortutil v1.2.1 h1:+xyoGf15mM3NMlPDnFqrteY07klSFxLElE2PVuWIJ7w=
|
||||
modernc.org/sortutil v1.2.1/go.mod h1:7ZI3a3REbai7gzCLcotuw9AC4VZVpYMjDzETGsSMqJE=
|
||||
modernc.org/sqlite v1.34.4 h1:sjdARozcL5KJBvYQvLlZEmctRgW9xqIZc2ncN7PU0P8=
|
||||
modernc.org/sqlite v1.34.4/go.mod h1:3QQFCG2SEMtc2nv+Wq4cQCH7Hjcg+p/RMlS1XK+zwbk=
|
||||
modernc.org/strutil v1.2.0 h1:agBi9dp1I+eOnxXeiZawM8F4LawKv4NzGWSaLfyeNZA=
|
||||
modernc.org/strutil v1.2.0/go.mod h1:/mdcBmfOibveCTBxUl5B5l6W+TTH1FXPLHZE6bTosX0=
|
||||
modernc.org/strutil v1.2.1 h1:UneZBkQA+DX2Rp35KcM69cSsNES9ly8mQWD71HKlOA0=
|
||||
modernc.org/strutil v1.2.1/go.mod h1:EHkiggD70koQxjVdSBM3JKM7k6L0FbGE5eymy9i3B9A=
|
||||
modernc.org/token v1.1.0 h1:Xl7Ap9dKaEs5kLoOQeQmPWevfnk/DM5qcLcYlA8ys6Y=
|
||||
modernc.org/token v1.1.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM=
|
||||
nullprogram.com/x/optparse v1.0.0/go.mod h1:KdyPE+Igbe0jQUrVfMqDMeJQIJZEuyV7pjYmp6pbG50=
|
||||
|
@@ -10,6 +10,7 @@ import (
|
||||
"net/url"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/h44z/wg-portal/internal"
|
||||
"github.com/h44z/wg-portal/internal/app"
|
||||
"github.com/h44z/wg-portal/internal/app/api/v0/model"
|
||||
)
|
||||
@@ -70,7 +71,7 @@ func (e configEndpoint) handleConfigJsGet() gin.HandlerFunc {
|
||||
buf := &bytes.Buffer{}
|
||||
err := e.tpl.ExecuteTemplate(buf, "frontend_config.js.gotpl", gin.H{
|
||||
"BackendUrl": backendUrl,
|
||||
"Version": "unknown",
|
||||
"Version": internal.Version,
|
||||
"SiteTitle": e.app.Config.Web.SiteTitle,
|
||||
"SiteCompanyName": e.app.Config.Web.SiteCompanyName,
|
||||
})
|
||||
|
@@ -60,7 +60,8 @@ func getOauthFieldMapping(f config.OauthFields) config.OauthFields {
|
||||
Phone: "phone",
|
||||
Department: "department",
|
||||
},
|
||||
IsAdmin: "admin_flag",
|
||||
IsAdmin: "admin_flag",
|
||||
UserGroups: "", // by default, do not use user groups
|
||||
}
|
||||
if f.UserIdentifier != "" {
|
||||
defaultMap.UserIdentifier = f.UserIdentifier
|
||||
@@ -83,6 +84,9 @@ func getOauthFieldMapping(f config.OauthFields) config.OauthFields {
|
||||
if f.IsAdmin != "" {
|
||||
defaultMap.IsAdmin = f.IsAdmin
|
||||
}
|
||||
if f.UserGroups != "" {
|
||||
defaultMap.UserGroups = f.UserGroups
|
||||
}
|
||||
|
||||
return defaultMap
|
||||
}
|
||||
|
57
internal/app/auth/oauth_common_test.go
Normal file
57
internal/app/auth/oauth_common_test.go
Normal file
@@ -0,0 +1,57 @@
|
||||
package auth
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"testing"
|
||||
|
||||
"github.com/h44z/wg-portal/internal/config"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func Test_parseOauthUserInfo(t *testing.T) {
|
||||
userInfoStr := `
|
||||
{
|
||||
"at_hash": "REDACTED",
|
||||
"aud": "REDACTED",
|
||||
"c_hash": "REDACTED",
|
||||
"email": "test@mydomain.net",
|
||||
"email_verified": true,
|
||||
"exp": 1737404259,
|
||||
"groups": [
|
||||
"abuse@mydomain.net",
|
||||
"postmaster@mydomain.net",
|
||||
"wgportal-admins@mydomain.net"
|
||||
],
|
||||
"iat": 1737317859,
|
||||
"iss": "https://dex.mydomain.net",
|
||||
"name": "Test User",
|
||||
"nonce": "REDACTED",
|
||||
"sub": "REDACTED"
|
||||
}
|
||||
`
|
||||
|
||||
userInfo := map[string]interface{}{}
|
||||
err := json.Unmarshal([]byte(userInfoStr), &userInfo)
|
||||
require.NoError(t, err)
|
||||
|
||||
fieldMapping := getOauthFieldMapping(config.OauthFields{
|
||||
BaseFields: config.BaseFields{
|
||||
UserIdentifier: "email",
|
||||
Email: "email",
|
||||
Firstname: "name",
|
||||
Lastname: "family_name",
|
||||
},
|
||||
UserGroups: "groups",
|
||||
})
|
||||
adminMapping := &config.OauthAdminMapping{
|
||||
AdminGroupRegex: "^wgportal-admins@mydomain.net$",
|
||||
}
|
||||
|
||||
info, err := parseOauthUserInfo(fieldMapping, adminMapping, userInfo)
|
||||
assert.NoError(t, err)
|
||||
assert.True(t, info.IsAdmin)
|
||||
assert.Equal(t, info.Firstname, "Test User")
|
||||
assert.Equal(t, info.Lastname, "")
|
||||
assert.Equal(t, info.Email, "test@mydomain.net")
|
||||
}
|
@@ -71,5 +71,9 @@ func userChangedInLdap(dbUser, ldapUser *domain.User) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
if dbUser.ProviderName != ldapUser.ProviderName {
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
@@ -469,7 +469,7 @@ func (m Manager) synchronizeLdapUsers(ctx context.Context, provider *config.Ldap
|
||||
logrus.Tracef("fetched %d raw ldap users from provider %s...", len(rawUsers), provider.ProviderName)
|
||||
|
||||
// Update existing LDAP users
|
||||
err = m.updateLdapUsers(ctx, provider.ProviderName, rawUsers, &provider.FieldMap, provider.ParsedAdminGroupDN)
|
||||
err = m.updateLdapUsers(ctx, provider, rawUsers, &provider.FieldMap, provider.ParsedAdminGroupDN)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -487,13 +487,13 @@ func (m Manager) synchronizeLdapUsers(ctx context.Context, provider *config.Ldap
|
||||
|
||||
func (m Manager) updateLdapUsers(
|
||||
ctx context.Context,
|
||||
providerName string,
|
||||
provider *config.LdapProvider,
|
||||
rawUsers []internal.RawLdapUser,
|
||||
fields *config.LdapFields,
|
||||
adminGroupDN *ldap.DN,
|
||||
) error {
|
||||
for _, rawUser := range rawUsers {
|
||||
user, err := convertRawLdapUser(providerName, rawUser, fields, adminGroupDN)
|
||||
user, err := convertRawLdapUser(provider.ProviderName, rawUser, fields, adminGroupDN)
|
||||
if err != nil && !errors.Is(err, domain.ErrNotFound) {
|
||||
return fmt.Errorf("failed to convert LDAP data for %v: %w", rawUser["dn"], err)
|
||||
}
|
||||
@@ -506,17 +506,27 @@ func (m Manager) updateLdapUsers(
|
||||
tctx, cancel := context.WithTimeout(ctx, 30*time.Second)
|
||||
tctx = domain.SetUserInfo(tctx, domain.SystemAdminContextUserInfo())
|
||||
|
||||
// create new user
|
||||
if existingUser == nil {
|
||||
err := m.NewUser(tctx, user)
|
||||
if err != nil {
|
||||
cancel()
|
||||
return fmt.Errorf("create error for user id %s: %w", user.Identifier, err)
|
||||
}
|
||||
|
||||
cancel()
|
||||
return nil
|
||||
}
|
||||
|
||||
if existingUser != nil && existingUser.Source == domain.UserSourceLdap && userChangedInLdap(existingUser,
|
||||
user) {
|
||||
|
||||
// update existing user
|
||||
if provider.AutoReEnable && existingUser.DisabledReason == domain.DisabledReasonLdapMissing {
|
||||
user.Disabled = nil
|
||||
user.DisabledReason = ""
|
||||
} else {
|
||||
user.Disabled = existingUser.Disabled
|
||||
user.DisabledReason = existingUser.DisabledReason
|
||||
}
|
||||
if existingUser.Source == domain.UserSourceLdap && userChangedInLdap(existingUser, user) {
|
||||
err := m.users.SaveUser(tctx, user.Identifier, func(u *domain.User) (*domain.User, error) {
|
||||
u.UpdatedAt = time.Now()
|
||||
u.UpdatedBy = domain.CtxSystemLdapSyncer
|
||||
@@ -528,7 +538,8 @@ func (m Manager) updateLdapUsers(
|
||||
u.Phone = user.Phone
|
||||
u.Department = user.Department
|
||||
u.IsAdmin = user.IsAdmin
|
||||
u.Disabled = user.Disabled
|
||||
u.Disabled = nil
|
||||
u.DisabledReason = ""
|
||||
|
||||
return u, nil
|
||||
})
|
||||
@@ -536,6 +547,10 @@ func (m Manager) updateLdapUsers(
|
||||
cancel()
|
||||
return fmt.Errorf("update error for user id %s: %w", user.Identifier, err)
|
||||
}
|
||||
|
||||
if existingUser.IsDisabled() && !user.IsDisabled() {
|
||||
m.bus.Publish(app.TopicUserEnabled, *user)
|
||||
}
|
||||
}
|
||||
|
||||
cancel()
|
||||
|
@@ -114,9 +114,11 @@ type LdapProvider struct {
|
||||
ParsedAdminGroupDN *ldap.DN `yaml:"-"`
|
||||
|
||||
// If DisableMissing is true, missing users will be deactivated
|
||||
DisableMissing bool `yaml:"disable_missing"`
|
||||
SyncFilter string `yaml:"sync_filter"`
|
||||
SyncInterval time.Duration `yaml:"sync_interval"`
|
||||
DisableMissing bool `yaml:"disable_missing"`
|
||||
// If AutoReEnable is true, users that where disabled because they were missing will be re-enabled once they are found again
|
||||
AutoReEnable bool `yaml:"auto_re_enable"`
|
||||
SyncFilter string `yaml:"sync_filter"`
|
||||
SyncInterval time.Duration `yaml:"sync_interval"`
|
||||
|
||||
// If RegistrationEnabled is set to true, wg-portal will create new users that do not exist in the database.
|
||||
RegistrationEnabled bool `yaml:"registration_enabled"`
|
||||
|
@@ -88,6 +88,17 @@ func MapDefaultStringSlice(m map[string]interface{}, key string, dflt []string)
|
||||
return dflt
|
||||
} else {
|
||||
switch v := tmp.(type) {
|
||||
case []any:
|
||||
result := make([]string, 0, len(v))
|
||||
for _, elem := range v {
|
||||
switch vElem := elem.(type) {
|
||||
case string:
|
||||
result = append(result, vElem)
|
||||
default:
|
||||
result = append(result, fmt.Sprintf("%v", vElem))
|
||||
}
|
||||
}
|
||||
return result
|
||||
case []string:
|
||||
return v
|
||||
case string:
|
||||
|
Reference in New Issue
Block a user