Skip to content

Commit

Permalink
Adjust routing
Browse files Browse the repository at this point in the history
Add chaning users' passwords
  • Loading branch information
utking committed Sep 29, 2024
1 parent 39fe433 commit ed09e11
Show file tree
Hide file tree
Showing 19 changed files with 430 additions and 71 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ A simple UI for Etcd clusters. Tested with Etcd API v3 only.
- [x] Allow getting and setting KV pairs
- [x] Allow creating/modifying leases
- [x] Allow creating/modifying roles
- [ ] Allow creating/modifying users
- [x] Allow creating/modifying users
- [ ] Allow enabling/disabling auth

## Configuration
Expand Down
4 changes: 2 additions & 2 deletions internal/controllers/cluster/keys.go
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ func createKey(c echo.Context) error {
err = etcdClient.Put(item.Key, item.Value, item.TTL)

if err == nil {
return c.Redirect(http.StatusSeeOther, "/cluster/keys/list")
return c.Redirect(http.StatusSeeOther, "/cluster/keys")
}
}
}
Expand Down Expand Up @@ -156,5 +156,5 @@ func deleteKey(c echo.Context) error {
}
}

return c.Redirect(http.StatusSeeOther, "/cluster/keys/list")
return c.Redirect(http.StatusSeeOther, "/cluster/keys")
}
6 changes: 3 additions & 3 deletions internal/controllers/cluster/leases.go
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ func deleteLease(c echo.Context) error {
}
}

return c.Redirect(http.StatusSeeOther, "/cluster/leases/list")
return c.Redirect(http.StatusSeeOther, "/cluster/leases")
}

func createLease(c echo.Context) error {
Expand Down Expand Up @@ -142,15 +142,15 @@ func createLease(c echo.Context) error {
renewed, err = etcdClient.RenewLease(item.LeaseID)

if err == nil && renewed {
return c.Redirect(http.StatusSeeOther, fmt.Sprintf("/cluster/leases/list?filter=%x", item.LeaseID))
return c.Redirect(http.StatusSeeOther, fmt.Sprintf("/cluster/leases?filter=%x", item.LeaseID))
}
} else {
var newLease types.LeaseRecord

// Create new
newLease, err = etcdClient.GrantLease(item.TTL)
if err == nil {
return c.Redirect(http.StatusSeeOther, fmt.Sprintf("/cluster/leases/list?filter=%x", newLease.ID))
return c.Redirect(http.StatusSeeOther, fmt.Sprintf("/cluster/leases?filter=%x", newLease.ID))
}
}
}
Expand Down
6 changes: 3 additions & 3 deletions internal/controllers/cluster/roles.go
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ func createRole(c echo.Context) error {
err = etcdClient.AddRole(item.Name)

if err == nil {
return c.Redirect(http.StatusSeeOther, "/cluster/roles/list?filter="+item.Name)
return c.Redirect(http.StatusSeeOther, "/cluster/roles?filter="+item.Name)
}
}
}
Expand Down Expand Up @@ -142,7 +142,7 @@ func deleteRole(c echo.Context) error {
}
}

return c.Redirect(http.StatusSeeOther, "/cluster/roles/list?filter="+name)
return c.Redirect(http.StatusSeeOther, "/cluster/roles?filter="+name)
}

func editRolePermissions(c echo.Context) error {
Expand Down Expand Up @@ -185,7 +185,7 @@ func editRolePermissions(c echo.Context) error {
err = etcdClient.AddRole(item.Name)

if err == nil {
return c.Redirect(http.StatusSeeOther, "/cluster/roles/list?filter="+item.Name)
return c.Redirect(http.StatusSeeOther, "/cluster/roles?filter="+item.Name)
}
}
}
Expand Down
32 changes: 15 additions & 17 deletions internal/controllers/cluster/setup.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,37 +11,35 @@ func Setup(app *echo.Echo, webMenu *types.WebMenu) {
router.GET("/stats", clusterIndex)
router.GET("/elect/:id", electNewLeader)

router.GET("/leases/list", indexLeases)
router.GET("/leases", indexLeases)
router.GET("/lease/:id", infoLease)

router.GET("/lease/create", createLease)
router.Match([]string{"GET", "POST"}, "/lease/create", createLease)
router.GET("/lease/edit/:id", createLease)
router.POST("/lease/create", createLease)
router.POST("/lease/delete", deleteLease)

router.GET("/users/list", indexUsers)
router.GET("/user", infoUser)
router.GET("/user/edit", createUser)
router.GET("/user/create", createUser)
router.POST("/user/create", createUser)
router.GET("/users", indexUsers)
router.POST("/user/edit", revokeUserGroups)
router.POST("/user/delete", deleteUser)
router.Match([]string{"GET", "POST"}, "/user/roles/add", addUserGroups)
router.Match([]string{"GET", "POST"}, "/user/create", createUser)
router.Match([]string{"GET", "POST"}, "/user/passwd", passwdUser)

router.GET("/roles/list", indexRoles)
router.GET("/role", infoRole)
router.GET("/roles", indexRoles)
router.GET("/role/edit/:name", editRolePermissions)
router.POST("/role/revoke/:name", revokeRolePermissions)
router.POST("/role/grant/:name", grantRolePermissions)
router.GET("/role/create", createRole)
router.POST("/role/create", createRole)
router.POST("/role/delete", deleteRole)
router.Match([]string{"GET", "POST"}, "/role/create", createRole)

router.GET("/keys/list", listKeys)
router.GET("/key", infoKey)
router.GET("/keys", listKeys)

router.GET("/key/create", createKey)
router.GET("/key/edit", createKey)
router.POST("/key/create", createKey)
router.POST("/key/delete", deleteKey)
router.Match([]string{"GET", "POST"}, "/key/create", createKey)

webMenu.UserItems = append(webMenu.UserItems, map[string][]types.WebMenuItem{
"Cluster": {
Expand All @@ -63,7 +61,7 @@ func Setup(app *echo.Echo, webMenu *types.WebMenu) {
{
Type: "item",
Title: "List",
URIPath: "/cluster/keys/list",
URIPath: "/cluster/keys",
},
},
"Leases": {
Expand All @@ -78,7 +76,7 @@ func Setup(app *echo.Echo, webMenu *types.WebMenu) {
{
Type: "item",
Title: "List",
URIPath: "/cluster/leases/list",
URIPath: "/cluster/leases",
},
},
"Users": {
Expand All @@ -93,7 +91,7 @@ func Setup(app *echo.Echo, webMenu *types.WebMenu) {
{
Type: "item",
Title: "List",
URIPath: "/cluster/users/list",
URIPath: "/cluster/users",
},
},
"Roles": {
Expand All @@ -108,7 +106,7 @@ func Setup(app *echo.Echo, webMenu *types.WebMenu) {
{
Type: "item",
Title: "List",
URIPath: "/cluster/roles/list",
URIPath: "/cluster/roles",
},
},
})
Expand Down
154 changes: 141 additions & 13 deletions internal/controllers/cluster/users.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package cluster

import (
"errors"
"net/http"
"slices"
"strings"

"github.com/labstack/echo/v4"
Expand Down Expand Up @@ -92,22 +94,13 @@ func createUser(c echo.Context) error {
)

if err == nil {
// GET request
item.Name = c.QueryParam("name")
if c.Request().Method == http.MethodGet && item.Name != "" {
userItem, getErr := etcdClient.UserInfo(item.Name)
if getErr == nil {
item.Name = string(userItem.Name)
item.Roles = userItem.Roles
}
} else if c.Request().Method == http.MethodPost {
// POST request
if c.Request().Method == http.MethodPost {
err = c.Bind(&item)
if err == nil {
err = etcdClient.AddUser(item.Name, item.Password)

if err == nil {
return c.Redirect(http.StatusSeeOther, "/cluster/users/list?filter="+item.Name)
return c.Redirect(http.StatusSeeOther, "/cluster/users?filter="+item.Name)
}
}
}
Expand All @@ -121,14 +114,149 @@ func createUser(c echo.Context) error {
code,
"users/create.html",
map[string]interface{}{
"Title": "Create User", // FIX: for edit
"Title": "Create User",
"Item": item,
"Error": utils.ErrorMessage(err),
"csrf": c.Get("csrf").(string),
},
)
}

func passwdUser(c echo.Context) error {
var (
code = http.StatusOK
item types.UserInfo
request requests.UserCreate
err error
etcdClient *v3.Client
)

etcdClient, err = v3.New(
utils.GetEntryPoints(),
utils.GetSSLCertFile(), utils.GetSSLKeyFile(), utils.GetSSLCAFile(),
utils.GetUsername(), utils.GetPassword(),
)

if err == nil {
if c.Request().Method == http.MethodGet {
item, err = etcdClient.UserInfo(c.QueryParam("name"))
} else if c.Request().Method == http.MethodPost {
err = errors.Join(c.Bind(&request), request.Validate())
item.Name = types.UserRecord(request.Name)

if err == nil {
err = etcdClient.ChangeUserPassword(request.Name, request.Password)

if err == nil {
return c.Redirect(http.StatusSeeOther, "/cluster/users?filter="+request.Name)
}
}
}
}

if err != nil {
code = http.StatusInternalServerError
}

return c.Render(
code,
"users/passwd.html",
map[string]interface{}{
"Title": "Change User Password",
"Item": item,
"Error": utils.ErrorMessage(err),
"csrf": c.Get("csrf").(string),
},
)
}

func revokeUserGroups(c echo.Context) error {
var (
item requests.UserEditRoles
err error
etcdClient *v3.Client
)

etcdClient, err = v3.New(
utils.GetEntryPoints(),
utils.GetSSLCertFile(), utils.GetSSLKeyFile(), utils.GetSSLCAFile(),
utils.GetUsername(), utils.GetPassword(),
)

if err == nil {
if c.Request().Method == http.MethodPost {
err = c.Bind(&item)
if err == nil {
err = etcdClient.RevokeUserRoles(item.Name, item.RevokeRoles)

if err == nil {
return c.Redirect(http.StatusSeeOther, "/cluster/user?name="+item.Name)
}
}
}
}

return c.Redirect(http.StatusSeeOther, "/cluster/user?name="+item.Name)
}

func addUserGroups(c echo.Context) error {
var (
code = http.StatusOK
item requests.UserEditRoles
err error
etcdClient *v3.Client
roles []string
allRoles []string
grantedRoles []string
)

etcdClient, err = v3.New(
utils.GetEntryPoints(),
utils.GetSSLCertFile(), utils.GetSSLKeyFile(), utils.GetSSLCAFile(),
utils.GetUsername(), utils.GetPassword(),
)

if err == nil {
if c.Request().Method == http.MethodGet {
item.Name = c.QueryParam("name")
allRoles, _ = etcdClient.GetRoles("")

if userInfo, userInfoErr := etcdClient.UserInfo(item.Name); userInfoErr == nil {
grantedRoles = userInfo.Roles
roles = make([]string, 0, max(len(allRoles)-len(grantedRoles), 0))

for _, role := range allRoles {
if !slices.Contains(grantedRoles, role) {
roles = append(roles, role)
}
}
}
} else if c.Request().Method == http.MethodPost {
err = c.Bind(&item)
if err == nil {
err = etcdClient.AddUserRoles(item.Name, item.AddRoles)

if err == nil {
return c.Redirect(http.StatusSeeOther, "/cluster/user?name="+item.Name)
}
}
}
}

return c.Render(
code,
"users/add-roles.html",
map[string]interface{}{
"Title": "Grant Roles",
"Item": item,
"Roles": roles,
"GrantedRoles": grantedRoles,
"Error": utils.ErrorMessage(err),
"csrf": c.Get("csrf").(string),
},
)
}

func deleteUser(c echo.Context) error {
var (
name = c.FormValue("name")
Expand All @@ -149,5 +277,5 @@ func deleteUser(c echo.Context) error {
}
}

return c.Redirect(http.StatusSeeOther, "/cluster/users/list?filter="+name)
return c.Redirect(http.StatusSeeOther, "/cluster/users?filter="+name)
}
Loading

0 comments on commit ed09e11

Please sign in to comment.