Full web : fichiers restants
This commit is contained in:
1 parent
ec3b7c9a01
commit
4826fa5b82
26 files changed
+2537
-793
No files matched your search
@@ -0,0 +1,187 @@
|
||||
package pvetest
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"sort"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// access fakes /access/groups, /access/roles and /access/users (user.cfg).
|
||||
func (s *Server) access(w http.ResponseWriter, r *http.Request, method string, seg []string) {
|
||||
f := r.PostForm
|
||||
if method == http.MethodDelete {
|
||||
f = r.URL.Query()
|
||||
}
|
||||
switch {
|
||||
case len(seg) == 2 && seg[1] == "groups" && method == "GET":
|
||||
var out []any
|
||||
for _, id := range sortedKeys(s.Groups) {
|
||||
o := map[string]any{"groupid": id, "users": strings.Join(s.members(id), ",")}
|
||||
for k, v := range s.Groups[id] {
|
||||
o[k] = v
|
||||
}
|
||||
out = append(out, o)
|
||||
}
|
||||
reply(w, out)
|
||||
case len(seg) == 2 && seg[1] == "groups" && method == "POST":
|
||||
id := f.Get("groupid")
|
||||
if s.Groups[id] != nil {
|
||||
fail(w, 500, "create group failed: group '"+id+"' already exists")
|
||||
return
|
||||
}
|
||||
s.Groups[id] = setFields(map[string]any{}, f, "groupid")
|
||||
reply(w, nil)
|
||||
case len(seg) == 3 && seg[1] == "groups":
|
||||
g := s.Groups[seg[2]]
|
||||
if g == nil {
|
||||
fail(w, 500, "group '"+seg[2]+"' does not exist")
|
||||
return
|
||||
}
|
||||
switch method {
|
||||
case "PUT":
|
||||
setFields(g, f)
|
||||
case "DELETE":
|
||||
delete(s.Groups, seg[2])
|
||||
for _, u := range s.Users {
|
||||
u["groups"] = strings.Join(remove(split(u["groups"]), seg[2]), ",")
|
||||
}
|
||||
}
|
||||
reply(w, nil)
|
||||
case len(seg) == 2 && seg[1] == "roles" && method == "GET":
|
||||
out := []any{
|
||||
map[string]any{"roleid": "Administrator", "privs": "Sys.Audit,Sys.Modify", "special": 1},
|
||||
map[string]any{"roleid": "PVEAuditor", "privs": "Sys.Audit", "special": 1},
|
||||
}
|
||||
for _, id := range sortedKeys(s.Roles) {
|
||||
out = append(out, map[string]any{"roleid": id, "privs": s.Roles[id], "special": 0})
|
||||
}
|
||||
reply(w, out)
|
||||
case len(seg) == 2 && seg[1] == "roles" && method == "POST":
|
||||
s.Roles[f.Get("roleid")] = f.Get("privs")
|
||||
reply(w, nil)
|
||||
case len(seg) == 3 && seg[1] == "roles":
|
||||
if _, ok := s.Roles[seg[2]]; !ok {
|
||||
fail(w, 500, "role '"+seg[2]+"' does not exist")
|
||||
return
|
||||
}
|
||||
if method == "DELETE" {
|
||||
delete(s.Roles, seg[2])
|
||||
} else {
|
||||
s.Roles[seg[2]] = f.Get("privs")
|
||||
}
|
||||
reply(w, nil)
|
||||
case len(seg) == 2 && seg[1] == "users" && method == "GET":
|
||||
var out []any
|
||||
for _, id := range sortedKeys(s.Users) {
|
||||
realm := id[strings.LastIndex(id, "@")+1:]
|
||||
o := map[string]any{"userid": id, "realm-type": realm, "tokens": []any{}}
|
||||
for k, v := range s.Users[id] {
|
||||
o[k] = v
|
||||
}
|
||||
out = append(out, o)
|
||||
}
|
||||
reply(w, out)
|
||||
case len(seg) == 2 && seg[1] == "users" && method == "POST":
|
||||
id := f.Get("userid")
|
||||
if s.Users[id] != nil {
|
||||
fail(w, 500, "create user failed: user '"+id+"' already exists")
|
||||
return
|
||||
}
|
||||
if !s.groupsExist(w, f.Get("groups")) {
|
||||
return
|
||||
}
|
||||
s.Users[id] = setFields(map[string]any{"enable": 1}, f, "userid", "password")
|
||||
reply(w, nil)
|
||||
case len(seg) == 3 && seg[1] == "users":
|
||||
u := s.Users[seg[2]]
|
||||
if u == nil {
|
||||
fail(w, 500, "user '"+seg[2]+"' does not exist")
|
||||
return
|
||||
}
|
||||
switch method {
|
||||
case "PUT":
|
||||
if !s.groupsExist(w, f.Get("groups")) {
|
||||
return
|
||||
}
|
||||
setFields(u, f)
|
||||
case "DELETE":
|
||||
delete(s.Users, seg[2])
|
||||
delete(s.Shadow, strings.TrimSuffix(seg[2], "@pve"))
|
||||
}
|
||||
reply(w, nil)
|
||||
default:
|
||||
fail(w, 501, "not implemented in fake: "+method+" "+strings.Join(seg, "/"))
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Server) groupsExist(w http.ResponseWriter, groups string) bool {
|
||||
for _, g := range split(groups) {
|
||||
if s.Groups[g] == nil {
|
||||
fail(w, 500, "no such group '"+g+"'")
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (s *Server) members(group string) []string {
|
||||
var out []string
|
||||
for id, u := range s.Users {
|
||||
for _, g := range split(u["groups"]) {
|
||||
if g == group {
|
||||
out = append(out, id)
|
||||
}
|
||||
}
|
||||
}
|
||||
sort.Strings(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// setFields copies form values; an empty value removes the field (like user.cfg).
|
||||
func setFields(m map[string]any, f map[string][]string, skip ...string) map[string]any {
|
||||
sk := map[string]bool{}
|
||||
for _, k := range skip {
|
||||
sk[k] = true
|
||||
}
|
||||
for k, v := range f {
|
||||
if sk[k] || len(v) == 0 {
|
||||
continue
|
||||
}
|
||||
if v[0] == "" {
|
||||
delete(m, k)
|
||||
continue
|
||||
}
|
||||
m[k] = v[0]
|
||||
}
|
||||
return m
|
||||
}
|
||||
|
||||
func split(v any) []string {
|
||||
s, _ := v.(string)
|
||||
var out []string
|
||||
for _, x := range strings.Split(s, ",") {
|
||||
if x = strings.TrimSpace(x); x != "" {
|
||||
out = append(out, x)
|
||||
}
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
func remove(l []string, x string) []string {
|
||||
out := l[:0]
|
||||
for _, e := range l {
|
||||
if e != x {
|
||||
out = append(out, e)
|
||||
}
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
func sortedKeys[V any](m map[string]V) []string {
|
||||
out := make([]string, 0, len(m))
|
||||
for k := range m {
|
||||
out = append(out, k)
|
||||
}
|
||||
sort.Strings(out)
|
||||
return out
|
||||
}
|
||||
Reference in new issue
Block a user