website/pkg/controller/admin/scopes.go

196 lines
5.4 KiB
Go

package admin
import (
"net/http"
"strconv"
"strings"
"code.nonshy.com/nonshy/website/pkg/config"
"code.nonshy.com/nonshy/website/pkg/models"
"code.nonshy.com/nonshy/website/pkg/session"
"code.nonshy.com/nonshy/website/pkg/templates"
)
// Scopes controller (/admin/scopes)
func Scopes() http.HandlerFunc {
tmpl := templates.Must("admin/scopes.html")
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// Query parameters.
var (
intent = r.FormValue("intent")
editGroupIDStr = r.FormValue("id")
)
currentUser, err := session.CurrentUser(r)
if err != nil {
session.FlashError(w, r, "Couldn't get your current user: %s", err)
}
_ = currentUser
// List all of the admin users, groups & scopes.
adminUsers, err := models.ListAdminUsers()
if err != nil {
session.FlashError(w, r, "ListAdminUsers: %s", err)
}
adminGroups, err := models.ListAdminGroups()
if err != nil {
session.FlashError(w, r, "ListAdminGroups: %s", err)
}
// Does the Superusers group exist yet?
var needSuperuserInit = true
for _, group := range adminGroups {
if group.Name == config.AdminGroupSuperusers {
needSuperuserInit = false
break
}
}
// Validate that the Edit Group ID exists.
var (
editGroupID int
editGroup = &models.AdminGroup{}
)
if editGroupIDStr != "" {
groupID, err := strconv.Atoi(editGroupIDStr)
if err != nil {
session.FlashError(w, r, "Group ID is not a valid integer")
templates.Redirect(w, r.URL.Path)
return
}
var found bool
for _, group := range adminGroups {
if group.ID == uint64(groupID) {
editGroup = group
found = true
break
}
}
if !found && groupID > 0 {
session.FlashError(w, r, "Group ID not found.")
templates.Redirect(w, r.URL.Path)
return
}
editGroupID = groupID
}
// POST event handlers.
if r.Method == http.MethodPost {
// Scope check.
if !currentUser.HasAdminScope(config.ScopeAdminScopeAdmin) && intent != "init-superusers" {
session.FlashError(w, r, "Missing admin scope: %s", config.ScopeAdminScopeAdmin)
templates.Redirect(w, r.URL.Path)
return
}
switch intent {
case "init-superusers":
// Initialize the Superusers group, if it does not already exist.
if !needSuperuserInit {
session.FlashError(w, r, "Could not initialize the Superusers group: it already exists.")
break
}
group, err := models.CreateAdminGroup(config.AdminGroupSuperusers, []string{"*"})
if err != nil {
session.FlashError(w, r, "Couldn't create Superusers group: %s", err)
break
}
// Add the current admin user to it.
if err := group.AddUser(currentUser); err != nil {
session.FlashError(w, r, "Couldn't add you to the Superusers group: %s", err)
break
}
session.Flash(w, r, "The Superusers group has been initialized and you placed in it.")
case "save":
// Create or Save an AdminGroup.
var (
groupName = r.PostFormValue("name")
groupScopes = strings.Split(r.PostFormValue("scopes"), "\n")
groupUsers = r.PostForm["username"]
)
if editGroupID == 0 {
// New group: easiest option.
group, err := models.CreateAdminGroup(groupName, groupScopes)
if err != nil {
session.FlashError(w, r, "Couldn't create new group: %s", err)
break
}
// Apply the user list to it.
added, removed, err := group.ReplaceUsers(groupUsers)
if err != nil {
session.FlashError(w, r, "Couldn't save users in this group: %s", err)
break
}
session.Flash(w, r, "Saved admin group with %d scopes.", len(groupScopes))
if len(added) > 0 {
session.Flash(w, r, "Added %s to the group.", strings.Join(added, ", "))
}
if len(removed) > 0 {
session.Flash(w, r, "Removed %s from the group.", strings.Join(removed, ", "))
}
} else {
// Updating the existing group.
if err := editGroup.ReplaceScopes(groupScopes); err != nil {
session.FlashError(w, r, "Couldn't replace scopes: %s", err)
break
}
added, removed, err := editGroup.ReplaceUsers(groupUsers)
if err != nil {
session.FlashError(w, r, "Couldn't save users in this group: %s", err)
break
}
session.Flash(w, r, "Saved admin group with %d scopes.", len(groupScopes))
if len(added) > 0 {
session.Flash(w, r, "Added %s to the group.", strings.Join(added, ", "))
}
if len(removed) > 0 {
session.Flash(w, r, "Removed %s from the group.", strings.Join(removed, ", "))
}
}
case "delete":
if editGroupID == 0 {
session.FlashError(w, r, "Can't delete group: no group ID")
} else {
err := editGroup.Delete()
if err != nil {
session.FlashError(w, r, "Couldn't delete group: %s", err)
} else {
session.Flash(w, r, "Group deleted!")
}
}
default:
session.FlashError(w, r, "Unsupported intent: %s", intent)
}
templates.Redirect(w, r.URL.Path)
return
}
var vars = map[string]interface{}{
"Intent": intent,
"AdminUsers": adminUsers,
"AdminGroups": adminGroups,
"AdminScopes": config.ListAdminScopes(),
"NeedSuperuserInit": needSuperuserInit,
"EditGroupID": editGroupID,
"EditGroup": editGroup,
}
if err := tmpl.Execute(w, r, vars); err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
})
}