From 8e80176022cba3ac6c6d980d67c90d17a233bba6 Mon Sep 17 00:00:00 2001 From: Amy Gale Ruth Bowersox Date: Fri, 17 Oct 2025 15:57:12 -0600 Subject: [PATCH] implemented the community admin menu and necessary tweaks to the menu system --- communityadmin.go | 50 +++++++++++++++++++++++++++++++++++++ database/securitydefs.yaml | 2 ++ database/servicedefs.yaml | 2 +- main.go | 1 + sysadmin.go | 1 + ui/menudefs.yaml | 32 ++++++++++++++++++++++++ ui/menus.go | 38 +++++++++++++++++++++++----- ui/views/menu.jet | 13 ++++++++-- ui/views/menu_left_comm.jet | 3 +-- 9 files changed, 131 insertions(+), 11 deletions(-) create mode 100644 communityadmin.go diff --git a/communityadmin.go b/communityadmin.go new file mode 100644 index 0000000..e684f6c --- /dev/null +++ b/communityadmin.go @@ -0,0 +1,50 @@ +/* + * Amsterdam Web Communities System + * Copyright (c) 2025 Erbosoft Metaverse Design Solutions, All Rights Reserved + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + +// Package main contains the high-level Amsterdam logic. +package main + +import ( + "errors" + "net/http" + + "git.erbosoft.com/amy/amsterdam/database" + "git.erbosoft.com/amy/amsterdam/ui" +) + +/* CommunityAdminMenu renders the community administration menu. + * Parameters: + * ctxt - The AmContext for the request. + * Returns: + * Command string dictating what to be rendered. + * Data as a parameter for the command string. + * Standard Go error status. + */ +func CommunityAdminMenu(ctxt ui.AmContext) (string, any, error) { + err := ctxt.SetCommunityContext(ctxt.URLParam("cid")) + if err != nil { + ctxt.SetRC(http.StatusNotFound) + return ui.ErrorPage(ctxt, err) + } + comm := ctxt.CurrentCommunity() + if !comm.TestPermission("Community.ShowAdmin", ctxt.EffectiveLevel()) { + ctxt.SetRC(http.StatusForbidden) + return ui.ErrorPage(ctxt, errors.New("you are not permitted to access this page")) + } + menu := ui.AmMenu("communityadmin") + defs := make(map[string]bool) + if !ctxt.GlobalFlags().Get(database.GlobalFlagNoCategories) { + defs["USECAT"] = true + } + ctxt.SetLeftMenu("community") + ctxt.VarMap().Set("menu", menu.FilterCommunity(comm)) + ctxt.VarMap().Set("defs", defs) + ctxt.VarMap().Set("amsterdam_pageTitle", menu.Title+" - "+comm.Name) + return "framed_template", "menu.jet", nil +} diff --git a/database/securitydefs.yaml b/database/securitydefs.yaml index 46f6eda..2488f30 100644 --- a/database/securitydefs.yaml +++ b/database/securitydefs.yaml @@ -184,3 +184,5 @@ permissions: role: "Community.AnyAdmin" - name: "Community.MassMail" role: "Community.AnyAdmin" + - name: "Community.Destroy" + role: "Community.Host" diff --git a/database/servicedefs.yaml b/database/servicedefs.yaml index bef23ea..7a510da 100644 --- a/database/servicedefs.yaml +++ b/database/servicedefs.yaml @@ -25,7 +25,7 @@ domains: requirePermission: "Community.Read" requireRole: "Community.AnyAdmin" linkSequence: 5000 - link: "/TODO/comm/[CID]/admin" + link: "/comm/[CID]/admin" title: "Administration" - id: "SysAdmin" index: 2 diff --git a/main.go b/main.go index b674753..05bd6c6 100644 --- a/main.go +++ b/main.go @@ -65,6 +65,7 @@ func setupEcho() *echo.Echo { e.POST("/quick_email", ui.AmWrap(QuickEMail)) e.GET("/sysadmin", ui.AmWrap(SysAdminMenu)) e.GET("/comm/:cid/profile", ui.AmWrap(ShowCommunity)) + e.GET("/comm/:cid/admin", ui.AmWrap(CommunityAdminMenu)) return e } diff --git a/sysadmin.go b/sysadmin.go index 5269a9f..979885f 100644 --- a/sysadmin.go +++ b/sysadmin.go @@ -34,6 +34,7 @@ func SysAdminMenu(ctxt ui.AmContext) (string, any, error) { } menu := ui.AmMenu("sysadmin") ctxt.VarMap().Set("menu", menu) + ctxt.VarMap().Set("defs", make(map[string]bool)) ctxt.VarMap().Set("amsterdam_pageTitle", menu.Title) return "framed_template", "menu.jet", nil } diff --git a/ui/menudefs.yaml b/ui/menudefs.yaml index ba97e3f..ef5f23e 100644 --- a/ui/menudefs.yaml +++ b/ui/menudefs.yaml @@ -52,3 +52,35 @@ menudefs: - text: "Import User Accounts" link: "/TODO/sysadmin/import" permission: "Global.SysAdminAccess" + - id: "communityadmin" + title: "Community Administration" + subtitle: "[CNAME]" + permSet: "community" + warning: > + Note: These tools provide access to sensitive administrative features for the + community. Use with care and review all changes before applying them to the community. + items: + - text: "Community Profile" + link: "/TODO/comm/[CID]/admin/profile" + permission: "Community.ShowAdmin" + - text: "Set Community Category" + link: "/TODO/comm/[CID]/admin/category" + permission: "Community.ShowAdmin" + ifdef: "USECAT" + - text: "Set Community Services" + link: "/TODO/comm/[CID]/admin/services" + permission: "Community.ShowAdmin" + disabled: true + - text: "Membership Control" + link: "/TODO/comm/[CID]/admin/members" + permission: "Community.ShowAdmin" + - text: "E-Mail to All Members" + link: "/TODO/comm/[CID]/admin/massmail" + permission: "Community.MassMail" + - text: "Display Audit Records" + link: "/TODO/comm/[CID]/admin/audit" + permission: "Community.ShowAdmin" + - text: "Delete Community" + link: "/TODO/comm/[CID]/admin/delete" + permission: "Community.Destroy" + hazard: true diff --git a/ui/menus.go b/ui/menus.go index 8edfe0a..1c88196 100644 --- a/ui/menus.go +++ b/ui/menus.go @@ -28,7 +28,9 @@ type MenuItem struct { Text string `yaml:"text"` Link string `yaml:"link"` Disabled bool `yaml:"disabled"` + Hazard bool `yaml:"hazard"` Permission string `yaml:"permission"` + Ifdef string `yaml:"ifdef"` P *MenuDefinition } @@ -63,12 +65,36 @@ func (mi *MenuItem) Show(ctxt AmContext) bool { // MenuDefinition represents a full menu definition. type MenuDefinition struct { - ID string `yaml:"id"` - Title string `yaml:"title"` - PermSet string `yaml:"permSet"` - Warning string `yaml:"warning"` - Items []MenuItem `yaml:"items"` - Tag string + ID string `yaml:"id"` + Title string `yaml:"title"` + Subtitle string `yaml:"subtitle"` + PermSet string `yaml:"permSet"` + Warning string `yaml:"warning"` + Items []MenuItem `yaml:"items"` + Tag string +} + +// FilterCommunity creates a copy of this menu filtered to the specified community. +func (mdef *MenuDefinition) FilterCommunity(comm *database.Community) *MenuDefinition { + newmd := MenuDefinition{ + ID: mdef.ID, + Title: mdef.Title, + Subtitle: strings.ReplaceAll(mdef.Subtitle, "[CNAME]", comm.Name), + PermSet: mdef.PermSet, + Warning: mdef.Warning, + Items: make([]MenuItem, len(mdef.Items)), + Tag: mdef.Tag, + } + for i, it := range mdef.Items { + newmd.Items[i].Text = it.Text + newmd.Items[i].Link = strings.ReplaceAll(it.Link, "[CID]", comm.Alias) + newmd.Items[i].Disabled = it.Disabled + newmd.Items[i].Hazard = it.Hazard + newmd.Items[i].Permission = it.Permission + newmd.Items[i].Ifdef = it.Ifdef + newmd.Items[i].P = &newmd + } + return &newmd } // MenuDefs represents the set of all menu definitions. diff --git a/ui/views/menu.jet b/ui/views/menu.jet index a8794f9..7401994 100644 --- a/ui/views/menu.jet +++ b/ui/views/menu.jet @@ -10,6 +10,9 @@

{{ menu.Title }}

+ {{ if menu.Subtitle != "" }} + {{ menu.Subtitle }} + {{ end }}
@@ -19,13 +22,19 @@