Allow deleting managed hosts with mandatory inline re-auth, record node mutations in an audit log with a sidebar Logs view, and let Administrators group permissions be edited from the Groups tab.
115 lines
2.9 KiB
Go
115 lines
2.9 KiB
Go
package api
|
|
|
|
import (
|
|
"errors"
|
|
"net/http"
|
|
|
|
"codeberg.org/SquidSE/ClusterCanvas/service/internal/settings"
|
|
)
|
|
|
|
var errUsersManageRequired = errors.New("permission users.manage required")
|
|
var errNodesReadRequired = errors.New("permission nodes.read required")
|
|
var errNodesExecRequired = errors.New("permission nodes.exec required")
|
|
var errNodesDeleteRequired = errors.New("permission nodes.delete required")
|
|
|
|
// permissionsForUser returns the union of permissions from the user's groups.
|
|
func permissionsForUser(user settings.UserCredential, groups []settings.Group) map[string]struct{} {
|
|
groupByName := make(map[string]settings.Group, len(groups))
|
|
for _, group := range groups {
|
|
groupByName[group.Name] = group
|
|
}
|
|
|
|
result := make(map[string]struct{})
|
|
for _, groupName := range user.GroupNames {
|
|
group, ok := groupByName[groupName]
|
|
if !ok {
|
|
continue
|
|
}
|
|
for _, permission := range group.Permissions {
|
|
result[permission] = struct{}{}
|
|
}
|
|
}
|
|
return result
|
|
}
|
|
|
|
func userHasPermission(user settings.UserCredential, groups []settings.Group, permission string) bool {
|
|
_, ok := permissionsForUser(user, groups)[permission]
|
|
return ok
|
|
}
|
|
|
|
func permissionList(user settings.UserCredential, groups []settings.Group) []string {
|
|
set := permissionsForUser(user, groups)
|
|
ordered := allPermissionList()
|
|
result := make([]string, 0, len(set))
|
|
for _, permission := range ordered {
|
|
if _, ok := set[permission]; ok {
|
|
result = append(result, permission)
|
|
}
|
|
}
|
|
return result
|
|
}
|
|
|
|
func (app *App) authorizeUsersWrite(request *http.Request) error {
|
|
user, ok := UserFromContext(request.Context())
|
|
if !ok {
|
|
return errors.New("authentication required")
|
|
}
|
|
|
|
payload, err := loadSettingsOrDefault(app.ConfigDir)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if !userHasPermission(user, payload.Groups, "users.manage") {
|
|
return errUsersManageRequired
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (app *App) authorizeNodesRead(request *http.Request) error {
|
|
user, ok := UserFromContext(request.Context())
|
|
if !ok {
|
|
return errors.New("authentication required")
|
|
}
|
|
|
|
payload, err := loadSettingsOrDefault(app.ConfigDir)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if !userHasPermission(user, payload.Groups, "nodes.read") {
|
|
return errNodesReadRequired
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (app *App) authorizeNodesExec(request *http.Request) error {
|
|
user, ok := UserFromContext(request.Context())
|
|
if !ok {
|
|
return errors.New("authentication required")
|
|
}
|
|
|
|
payload, err := loadSettingsOrDefault(app.ConfigDir)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if !userHasPermission(user, payload.Groups, "nodes.exec") {
|
|
return errNodesExecRequired
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (app *App) authorizeNodesDelete(request *http.Request) error {
|
|
user, ok := UserFromContext(request.Context())
|
|
if !ok {
|
|
return errors.New("authentication required")
|
|
}
|
|
|
|
payload, err := loadSettingsOrDefault(app.ConfigDir)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if !userHasPermission(user, payload.Groups, "nodes.delete") {
|
|
return errNodesDeleteRequired
|
|
}
|
|
return nil
|
|
}
|