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 } }) }