141 lines
4.5 KiB
Go
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)
|
|
}
|