Files
ClusterCanvas/service/internal/api/authz.go
T
Squid f4dc8f63d7 Add SSH-managed node registry with connection testing and reauth.
Register hosts under Containers/VMs/Docker with encrypted key storage, and require re-authentication for sensitive account changes.
2026-07-18 16:39:10 +02:00

98 lines
2.5 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")
// 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
}