From 4a7e1371474d7db3931b8f4ee467864e26db9169 Mon Sep 17 00:00:00 2001 From: Amy Gale Ruth Bowersox Date: Mon, 16 Feb 2026 21:39:05 -0700 Subject: [PATCH] landed "Edit Global Properties" --- database/globals.go | 31 ++++++++++++++++++ docs/MISSINGFUNCS.md | 2 +- main.go | 1 + sysadmin.go | 77 ++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 110 insertions(+), 1 deletion(-) diff --git a/database/globals.go b/database/globals.go index fc749dd..e2ea010 100644 --- a/database/globals.go +++ b/database/globals.go @@ -61,6 +61,22 @@ var globalProps map[int32]string = make(map[int32]string) // globalPropMutex controls access to globalProps. var globalPropMutex sync.Mutex +// Clone clones the entire global state. +func (g *Globals) Clone() *Globals { + rc := Globals{ + PostsPerPage: g.PostsPerPage, + OldPostsAtTop: g.OldPostsAtTop, + MaxSearchPage: g.MaxSearchPage, + MaxCommunityMemberPage: g.MaxCommunityMemberPage, + MaxConferenceMemberPage: g.MaxConferenceMemberPage, + FrontPagePosts: g.FrontPagePosts, + NumAuditPage: g.NumAuditPage, + CommunityCreateLevel: g.CommunityCreateLevel, + flags: nil, + } + return &rc +} + // Flags returns the global flags. func (g *Globals) Flags(ctx context.Context) (*util.OptionSet, error) { g.Mutex.Lock() @@ -105,6 +121,21 @@ func AmGlobals(ctx context.Context) (*Globals, error) { return theGlobals, nil } +// AmReplaceGlobals writes the globals to the database and replaces the instance. +func AmReplaceGlobals(ctx context.Context, ng *Globals) error { + globalsMutex.Lock() + defer globalsMutex.Unlock() + _, err := amdb.NamedExecContext(ctx, `UPDATE globals SET posts_per_page = :posts_per_page, old_posts_at_top = :old_posts_at_top, max_search_page = :max_search_page, + max_comm_mbr_page = :max_comm_mbr_page, max_conf_mbr_page = :max_conf_mbr_page, fp_posts = :fp_posts, num_audit_page = :num_audit_page, + comm_create_lvl = :comm_create_lvl`, ng) + if err != nil { + return err + } + ng.flags = nil + theGlobals = ng + return nil +} + /* AmGetGlobalProperty returns the value of a global property. * Parameters: * ctx - Standard Go context value. diff --git a/docs/MISSINGFUNCS.md b/docs/MISSINGFUNCS.md index b3536ba..246a3c0 100644 --- a/docs/MISSINGFUNCS.md +++ b/docs/MISSINGFUNCS.md @@ -13,7 +13,7 @@ _(italicized items can be deferred)_ - _Documentation (top menu link)_ - Quote banner rotation - Sysadmin Menu: - - Edit Global Properties + - ~~Edit Global Properties~~ - View/Edit IP Address Bans - View/Edit Banned Users - User Account Management diff --git a/main.go b/main.go index 655206e..526716c 100644 --- a/main.go +++ b/main.go @@ -77,6 +77,7 @@ func setupEcho() *echo.Echo { e.POST("/sideboxes", ui.AmWrap(AddSidebox)) e.GET("/sysadmin", ui.AmWrap(SysAdminMenu)) e.GET("/sysadmin/globals", ui.AmWrap(GlobalPropertiesForm)) + e.POST("/sysadmin/globals", ui.AmWrap(GlobalPropertiesSet)) e.GET("/create_comm", ui.AmWrap(CreateCommunityForm)) e.POST("/create_comm", ui.AmWrap(CreateCommunity)) e.GET("/manage_comm", ui.AmWrap(ManageCommunities)) diff --git a/sysadmin.go b/sysadmin.go index 4d69e7e..d855212 100644 --- a/sysadmin.go +++ b/sysadmin.go @@ -61,3 +61,80 @@ func GlobalPropertiesForm(ctxt ui.AmContext) (string, any) { dlg.Field("pic_in_post").SetChecked(ctxt.GlobalFlags().Get(database.GlobalFlagPicturesInPosts)) return dlg.Render(ctxt) } + +/* GlobalPropertiesSet resets the global properties. + * Parameters: + * ctxt - The AmContext for the request. + * Returns: + * Command string dictating what to be rendered. + * Data as a parameter for the command string. + */ +func GlobalPropertiesSet(ctxt ui.AmContext) (string, any) { + if !database.AmTestPermission("Global.SysAdminAccess", ctxt.CurrentUser().BaseLevel) { + return "error", ENOACCESS + } + + dlg, err := ui.AmLoadDialog("globalprops") + if err != nil { + return "error", err + } + dlg.LoadFromForm(ctxt) + b := dlg.WhichButton(ctxt) + if b == "cancel" { + return "redirect", "/sysadmin" + } else if b != "update" { + return dlg.RenderError(ctxt, EBUTTON.Error()) + } + + gl, err := database.AmGlobals(ctxt.Ctx()) + if err != nil { + return dlg.RenderError(ctxt, err.Error()) + } + gl = gl.Clone() + var n int + if n, err = dlg.Field("search_items").ValueInt(); err != nil { + return dlg.RenderError(ctxt, err.Error()) + } + gl.MaxSearchPage = int32(n) + if n, err = dlg.Field("fp_posts").ValueInt(); err != nil { + return dlg.RenderError(ctxt, err.Error()) + } + gl.FrontPagePosts = int32(n) + if n, err = dlg.Field("audit_recs").ValueInt(); err != nil { + return dlg.RenderError(ctxt, err.Error()) + } + gl.NumAuditPage = int32(n) + gl.CommunityCreateLevel = int32(dlg.Field("create_lvl").GetLevel()) + if n, err = dlg.Field("comm_mbrs").ValueInt(); err != nil { + return dlg.RenderError(ctxt, err.Error()) + } + gl.MaxCommunityMemberPage = int32(n) + if n, err = dlg.Field("posts_page").ValueInt(); err != nil { + return dlg.RenderError(ctxt, err.Error()) + } + gl.PostsPerPage = int32(n) + if n, err = dlg.Field("old_posts").ValueInt(); err != nil { + return dlg.RenderError(ctxt, err.Error()) + } + gl.OldPostsAtTop = int32(n) + if n, err = dlg.Field("conf_mbrs").ValueInt(); err != nil { + return dlg.RenderError(ctxt, err.Error()) + } + gl.MaxConferenceMemberPage = int32(n) + + flags, err := gl.Flags(ctxt.Ctx()) + if err != nil { + return dlg.RenderError(ctxt, err.Error()) + } + flags.Set(database.GlobalFlagNoCategories, dlg.Field("no_cats").IsChecked()) + flags.Set(database.GlobalFlagPicturesInPosts, dlg.Field("pic_in_post").IsChecked()) + + err = database.AmReplaceGlobals(ctxt.Ctx(), gl) + if err == nil { + err = gl.SaveFlags(ctxt.Ctx(), flags) + } + if err != nil { + return "error", err + } + return "redirect", "/sysadmin" +}