97 lines
2.3 KiB
Go
97 lines
2.3 KiB
Go
package handler
|
|
|
|
import (
|
|
"net/http"
|
|
"time"
|
|
|
|
"github.com/labstack/echo/v4"
|
|
"github.com/labstack/gommon/log"
|
|
|
|
"github.com/DigitalTolk/wireguard-ui/store"
|
|
)
|
|
|
|
// APIListUsers returns all users (read-only, managed via SSO)
|
|
func APIListUsers(db store.IStore) echo.HandlerFunc {
|
|
return func(c echo.Context) error {
|
|
users, err := db.GetUsers()
|
|
if err != nil {
|
|
return apiInternalError(c, "Cannot get user list")
|
|
}
|
|
return c.JSON(http.StatusOK, users)
|
|
}
|
|
}
|
|
|
|
// APIPatchUserAdmin toggles admin status for a user
|
|
func APIPatchUserAdmin(db store.IStore) echo.HandlerFunc {
|
|
return func(c echo.Context) error {
|
|
username := c.Param("username")
|
|
if !usernameRegexp.MatchString(username) {
|
|
return apiBadRequest(c, "Invalid username")
|
|
}
|
|
|
|
var body struct {
|
|
Admin bool `json:"admin"`
|
|
}
|
|
if err := c.Bind(&body); err != nil {
|
|
return apiBadRequest(c, "Invalid request body")
|
|
}
|
|
|
|
user, err := db.GetUserByName(username)
|
|
if err != nil {
|
|
return apiNotFound(c, "User not found")
|
|
}
|
|
|
|
// prevent demoting yourself
|
|
if !body.Admin && username == currentUser(c) {
|
|
return apiBadRequest(c, "Cannot remove your own admin role")
|
|
}
|
|
|
|
// prevent removing the last admin
|
|
if !body.Admin && user.Admin {
|
|
users, err := db.GetUsers()
|
|
if err != nil {
|
|
return apiInternalError(c, "Cannot verify admin count")
|
|
}
|
|
adminCount := 0
|
|
for _, u := range users {
|
|
if u.Admin {
|
|
adminCount++
|
|
}
|
|
}
|
|
if adminCount <= 1 {
|
|
return apiBadRequest(c, "Cannot remove the last admin")
|
|
}
|
|
}
|
|
|
|
user.Admin = body.Admin
|
|
user.UpdatedAt = time.Now().UTC()
|
|
if err := db.SaveUser(user); err != nil {
|
|
return apiInternalError(c, "Cannot update user")
|
|
}
|
|
|
|
action := "user.demote"
|
|
if body.Admin {
|
|
action = "user.promote"
|
|
}
|
|
log.Infof("Changed admin status for %s to %v", username, body.Admin)
|
|
auditLogEvent(c, action, "user", username, nil)
|
|
return c.JSON(http.StatusOK, user)
|
|
}
|
|
}
|
|
|
|
// APIGetUser returns a single user by username
|
|
func APIGetUser(db store.IStore) echo.HandlerFunc {
|
|
return func(c echo.Context) error {
|
|
username := c.Param("username")
|
|
if !usernameRegexp.MatchString(username) {
|
|
return apiBadRequest(c, "Invalid username")
|
|
}
|
|
|
|
user, err := db.GetUserByName(username)
|
|
if err != nil {
|
|
return apiNotFound(c, "User not found")
|
|
}
|
|
return c.JSON(http.StatusOK, user)
|
|
}
|
|
}
|