Files
DoGaMa-serv/internal/web/users.go
T
2026-08-26 22:35:42 +02:00

141 lines
4.5 KiB
Go

package web
import (
"errors"
"net/http"
"git.zaynet.fr/DoGaMa/DoGaMa-serv/internal/auth"
"git.zaynet.fr/DoGaMa/DoGaMa-serv/internal/authorization"
)
func (s *server) usersPage(w http.ResponseWriter, r *http.Request) {
data, ok := s.adminPageData(w, r, "Users", "administration")
if !ok {
return
}
if err := s.populateAdminUsers(r, &data); err != nil {
s.problem(w, http.StatusInternalServerError, "The users are unavailable.")
return
}
s.render(w, http.StatusOK, "settings.html", data)
}
func (s *server) populateAdminUsers(r *http.Request, data *pageData) error {
users, err := s.auth.ListUsers(r.Context())
if err != nil {
return err
}
data.Users, data.Permissions = users, authorization.Permissions()
data.UserAccess = make(map[string]map[string]authorization.Membership, len(users))
for _, user := range users {
data.UserAccess[user.ID] = make(map[string]authorization.Membership)
}
if s.repository == nil {
return nil
}
data.Instances = mustLifecycleInstances(r.Context(), s.repository)
for _, current := range data.Instances {
memberships, membershipErr := s.permissions.ListMemberships(r.Context(), data.User, current.ID)
if membershipErr != nil {
return errors.New("instance access unavailable")
}
for _, membership := range memberships {
if data.UserAccess[membership.UserID] != nil {
data.UserAccess[membership.UserID][current.ID] = membership
}
}
}
return nil
}
func (s *server) adminUserForm(w http.ResponseWriter, r *http.Request) (auth.User, bool) {
if !s.parseForm(w, r) {
return auth.User{}, false
}
actor, err := s.currentUser(r)
session, sessionErr := r.Cookie(sessionCookie)
if err != nil || sessionErr != nil || actor.Role != "admin" || !s.auth.ValidateCSRF(r.Context(), session.Value, r.FormValue("csrf_token")) {
s.problem(w, http.StatusForbidden, message("error.csrf"))
return auth.User{}, false
}
if actor.Role != "admin" || actor.Disabled {
s.problem(w, http.StatusForbidden, "Administrator access is required.")
return auth.User{}, false
}
return actor, true
}
func (s *server) userCreateForm(w http.ResponseWriter, r *http.Request) {
if _, ok := s.adminUserForm(w, r); !ok {
return
}
_, err := s.auth.CreateUserWithEmail(r.Context(), r.FormValue("username"), r.FormValue("email"), r.FormValue("password"), r.FormValue("role"), r.FormValue("disabled") == "yes")
if err != nil {
s.problem(w, http.StatusUnprocessableEntity, "The user could not be created.")
return
}
http.Redirect(w, r, "/administration#users", http.StatusSeeOther)
}
func (s *server) userUpdateForm(w http.ResponseWriter, r *http.Request) {
if _, ok := s.adminUserForm(w, r); !ok {
return
}
err := s.auth.UpdateUser(r.Context(), r.PathValue("id"), r.FormValue("email"), r.FormValue("role"), r.FormValue("disabled") == "yes")
if errors.Is(err, auth.ErrLastAdmin) {
s.problem(w, http.StatusConflict, "At least one active administrator is required.")
return
}
if err != nil {
s.problem(w, http.StatusUnprocessableEntity, "The user could not be updated.")
return
}
http.Redirect(w, r, "/administration#users", http.StatusSeeOther)
}
func (s *server) userMembershipForm(w http.ResponseWriter, r *http.Request) {
if s.permissions == nil {
http.NotFound(w, r)
return
}
actor, ok := s.adminUserForm(w, r)
if !ok {
return
}
role := r.FormValue("role")
var err error
if role == "none" {
err = s.permissions.DeleteMembership(r.Context(), actor, r.PathValue("instanceID"), r.PathValue("id"))
} else {
err = s.permissions.SetMembership(r.Context(), actor, r.PathValue("instanceID"), r.PathValue("id"), role)
}
if err != nil && !(role == "none" && errors.Is(err, authorization.ErrNotFound)) {
s.authorizationProblem(w, err)
return
}
http.Redirect(w, r, "/administration#users", http.StatusSeeOther)
}
func (s *server) userPermissionForm(w http.ResponseWriter, r *http.Request) {
if s.permissions == nil {
http.NotFound(w, r)
return
}
actor, ok := s.adminUserForm(w, r)
if !ok {
return
}
effect := r.FormValue("effect")
var err error
if effect == "inherit" {
err = s.permissions.DeleteOverride(r.Context(), actor, r.PathValue("instanceID"), r.PathValue("id"), r.PathValue("permission"))
} else {
err = s.permissions.SetOverride(r.Context(), actor, r.PathValue("instanceID"), r.PathValue("id"), r.PathValue("permission"), effect)
}
if err != nil && !(effect == "inherit" && errors.Is(err, authorization.ErrNotFound)) {
s.authorizationProblem(w, err)
return
}
http.Redirect(w, r, "/administration#users", http.StatusSeeOther)
}