feat: add user status and path permissions
This commit is contained in:
@@ -110,7 +110,7 @@ func account(r *http.Request, s *Server) *auth.Account {
|
||||
if err != nil {
|
||||
return s.Auth.Guest
|
||||
}
|
||||
if a, ok := s.Auth.Accounts[username]; ok {
|
||||
if a, ok := s.Auth.Accounts[username]; ok && (a.Enabled || a.PasswordHash == "") {
|
||||
return a
|
||||
}
|
||||
return s.Auth.Guest
|
||||
@@ -465,7 +465,7 @@ func (s *Server) me(w http.ResponseWriter, r *http.Request) {
|
||||
writeJSONError(w, http.StatusUnauthorized, "not authenticated")
|
||||
return
|
||||
}
|
||||
writeJSON(w, map[string]any{"username": a.Username, "home": a.Home, "admin": a.Admin, "mask": permString(a.MaskFor(a.Home)), "managed": a.PasswordHash != ""})
|
||||
writeJSON(w, map[string]any{"username": a.Username, "home": a.Home, "admin": a.Admin, "mask": permString(a.MaskFor(a.Home)), "managed": a.PasswordHash != "", "enabled": a.Enabled})
|
||||
}
|
||||
|
||||
func (s *Server) password(w http.ResponseWriter, r *http.Request) {
|
||||
@@ -502,6 +502,21 @@ func (s *Server) password(w http.ResponseWriter, r *http.Request) {
|
||||
writeJSON(w, map[string]any{"ok": true})
|
||||
}
|
||||
|
||||
type userRuleJSON struct {
|
||||
Dir string `json:"dir"`
|
||||
Mask string `json:"mask"`
|
||||
Deny bool `json:"deny,omitempty"`
|
||||
ChildrenOnly bool `json:"childrenOnly,omitempty"`
|
||||
}
|
||||
|
||||
func userRulesJSON(rules []auth.PathRule) []userRuleJSON {
|
||||
out := make([]userRuleJSON, 0, len(rules))
|
||||
for _, r := range rules {
|
||||
out = append(out, userRuleJSON{Dir: r.Dir, Mask: permString(r.Mask), Deny: r.Deny, ChildrenOnly: r.ChildrenOnly})
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
func (s *Server) users(w http.ResponseWriter, r *http.Request) {
|
||||
a := account(r, s)
|
||||
if a == nil || !a.Admin {
|
||||
@@ -519,7 +534,7 @@ func (s *Server) users(w http.ResponseWriter, r *http.Request) {
|
||||
if u.Username == "" || u == s.Auth.Guest {
|
||||
continue
|
||||
}
|
||||
out = append(out, map[string]any{"username": u.Username, "home": u.Home, "admin": u.Admin, "managed": u.PasswordHash != ""})
|
||||
out = append(out, map[string]any{"username": u.Username, "home": u.Home, "admin": u.Admin, "managed": u.PasswordHash != "", "enabled": u.Enabled, "rules": userRulesJSON(u.Rules)})
|
||||
}
|
||||
writeJSON(w, map[string]any{"users": out})
|
||||
case http.MethodPost:
|
||||
@@ -550,8 +565,10 @@ func (s *Server) users(w http.ResponseWriter, r *http.Request) {
|
||||
writeJSON(w, map[string]any{"username": u.Username, "home": u.Home})
|
||||
case http.MethodPut:
|
||||
var req struct {
|
||||
Username string `json:"username"`
|
||||
Password string `json:"password"`
|
||||
Username string `json:"username"`
|
||||
Password string `json:"password"`
|
||||
Enabled *bool `json:"enabled"`
|
||||
Rules []userRuleJSON `json:"rules"`
|
||||
}
|
||||
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
||||
writeJSONError(w, http.StatusBadRequest, "invalid json")
|
||||
@@ -561,11 +578,22 @@ func (s *Server) users(w http.ResponseWriter, r *http.Request) {
|
||||
writeJSONError(w, http.StatusBadRequest, "invalid username")
|
||||
return
|
||||
}
|
||||
if err := s.UserStore.UpdatePassword(s.Auth, req.Username, req.Password); err != nil {
|
||||
var rules []auth.PathRule
|
||||
if req.Rules != nil {
|
||||
for _, rr := range req.Rules {
|
||||
dir := strings.Trim(strings.ReplaceAll(rr.Dir, "\\", "/"), "/")
|
||||
if dir == "" || unsafePath(dir) {
|
||||
writeJSONError(w, http.StatusBadRequest, "invalid rule path")
|
||||
return
|
||||
}
|
||||
rules = append(rules, auth.PathRule{Dir: dir, Mask: auth.ParseMask(rr.Mask), Deny: rr.Deny, ChildrenOnly: rr.ChildrenOnly})
|
||||
}
|
||||
}
|
||||
if err := s.UserStore.Update(s.Auth, req.Username, req.Password, req.Enabled, rules); err != nil {
|
||||
writeJSONError(w, http.StatusBadRequest, err.Error())
|
||||
return
|
||||
}
|
||||
s.logOp(r, fmt.Sprintf("reset password for '%s'", req.Username))
|
||||
s.logOp(r, fmt.Sprintf("updated user '%s'", req.Username))
|
||||
writeJSON(w, map[string]any{"ok": true})
|
||||
case http.MethodDelete:
|
||||
username := r.URL.Query().Get("username")
|
||||
|
||||
Reference in New Issue
Block a user