added the Manage Conference page; also fixed password hash matching in authentication
This commit is contained in:
@@ -122,6 +122,47 @@ func AttachmentSend(ctxt ui.AmContext) (string, any, error) {
|
|||||||
return "bytes", data, nil
|
return "bytes", data, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ConfManage displays the "manage conference" page.
|
||||||
|
* 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 ConfManage(ctxt ui.AmContext) (string, any, error) {
|
||||||
|
comm := ctxt.CurrentCommunity()
|
||||||
|
conf := ctxt.GetScratch("currentConference").(*database.Conference)
|
||||||
|
myLevel := ctxt.GetScratch("levelInConference").(uint16)
|
||||||
|
urlStem := fmt.Sprintf("/comm/%s/conf/%s", comm.Alias, ctxt.GetScratch("currentAlias"))
|
||||||
|
ctxt.VarMap().Set("confName", conf.Name)
|
||||||
|
ctxt.VarMap().Set("urlStem", urlStem)
|
||||||
|
|
||||||
|
pseud, err := conf.DefaultPseud(ctxt.Ctx(), ctxt.CurrentUser())
|
||||||
|
if err != nil {
|
||||||
|
return ui.ErrorPage(ctxt, err)
|
||||||
|
}
|
||||||
|
ctxt.VarMap().Set("pseud", pseud)
|
||||||
|
|
||||||
|
if ctxt.CurrentUser().IsAnon {
|
||||||
|
ctxt.VarMap().Set("canInvite", false)
|
||||||
|
} else {
|
||||||
|
member, _, _, err := comm.Membership(ctxt.Ctx(), ctxt.CurrentUser())
|
||||||
|
if err != nil {
|
||||||
|
return ui.ErrorPage(ctxt, err)
|
||||||
|
}
|
||||||
|
ctxt.VarMap().Set("canInvite", member)
|
||||||
|
}
|
||||||
|
|
||||||
|
if conf.TestPermission("Conference.Change", myLevel) || conf.TestPermission("Conference.Delete", myLevel) {
|
||||||
|
menu := ui.AmMenu("confhost").FilterConference(comm, ctxt.GetScratch("currentAlias").(string))
|
||||||
|
ctxt.VarMap().Set("menu", menu)
|
||||||
|
}
|
||||||
|
|
||||||
|
ctxt.VarMap().Set("amsterdam_pageTitle", "Manage Conference: "+conf.Name)
|
||||||
|
return "framed_template", "manage_conf.jet", nil
|
||||||
|
}
|
||||||
|
|
||||||
/* AddToHotlist adds the current community and conference to the user's hotlist..
|
/* AddToHotlist adds the current community and conference to the user's hotlist..
|
||||||
* Parameters:
|
* Parameters:
|
||||||
* ctxt - The AmContext for the request.
|
* ctxt - The AmContext for the request.
|
||||||
|
|||||||
+7
-1
@@ -564,8 +564,14 @@ func AmAuthenticateUser(ctx context.Context, name string, password string, remot
|
|||||||
ar = AmNewAudit(AuditLoginFail, user.Uid, remoteIP, "Account locked out")
|
ar = AmNewAudit(AuditLoginFail, user.Uid, remoteIP, "Account locked out")
|
||||||
return nil, errors.New("this account has been administratively locked; please contact the system administrator for assistance")
|
return nil, errors.New("this account has been administratively locked; please contact the system administrator for assistance")
|
||||||
}
|
}
|
||||||
|
passok := false
|
||||||
|
if user.Passhash == "" {
|
||||||
|
passok = (password == "")
|
||||||
|
} else {
|
||||||
h := hashPassword(password)
|
h := hashPassword(password)
|
||||||
if h != user.Passhash {
|
passok = strings.EqualFold(h, user.Passhash)
|
||||||
|
}
|
||||||
|
if !passok {
|
||||||
log.Warn("...invalid password")
|
log.Warn("...invalid password")
|
||||||
ar = AmNewAudit(AuditLoginFail, user.Uid, remoteIP, "Bad password")
|
ar = AmNewAudit(AuditLoginFail, user.Uid, remoteIP, "Bad password")
|
||||||
return nil, errors.New("the password you have specified is incorrect; please try again")
|
return nil, errors.New("the password you have specified is incorrect; please try again")
|
||||||
|
|||||||
+13
-1
@@ -49,5 +49,17 @@ _(italicized items can be deferred)_
|
|||||||
- Sidebox configuration
|
- Sidebox configuration
|
||||||
- Topics view:
|
- Topics view:
|
||||||
- Find
|
- Find
|
||||||
- Manage
|
- Manage:
|
||||||
|
- Set pseud
|
||||||
|
- Fixseen
|
||||||
|
- Send invite
|
||||||
|
- Change information
|
||||||
|
- Manage aliases
|
||||||
|
- Manage members
|
||||||
|
- Custom appearance
|
||||||
|
- Activity reports
|
||||||
|
- E-mail
|
||||||
|
- Export Messages
|
||||||
|
- Import Messages
|
||||||
|
- Delete Conference
|
||||||
- ~~Add to Hotlist/Remove from Hotlist~~
|
- ~~Add to Hotlist/Remove from Hotlist~~
|
||||||
|
|||||||
@@ -101,6 +101,7 @@ func setupEcho() *echo.Echo {
|
|||||||
confGroup.GET("", ui.AmWrap(Topics))
|
confGroup.GET("", ui.AmWrap(Topics))
|
||||||
confGroup.GET("/new_topic", ui.AmWrap(NewTopicForm))
|
confGroup.GET("/new_topic", ui.AmWrap(NewTopicForm))
|
||||||
confGroup.POST("/new_topic", ui.AmWrap(NewTopic))
|
confGroup.POST("/new_topic", ui.AmWrap(NewTopic))
|
||||||
|
confGroup.GET("/manage", ui.AmWrap(ConfManage))
|
||||||
confGroup.GET("/hotlist", ui.AmWrap(AddToHotlist))
|
confGroup.GET("/hotlist", ui.AmWrap(AddToHotlist))
|
||||||
confGroup.GET("/r/:topic", ui.AmWrap(ReadPosts), ui.SetTopic)
|
confGroup.GET("/r/:topic", ui.AmWrap(ReadPosts), ui.SetTopic)
|
||||||
confGroup.POST("/r/:topic", ui.AmWrap(PostInTopic), ui.SetTopic)
|
confGroup.POST("/r/:topic", ui.AmWrap(PostInTopic), ui.SetTopic)
|
||||||
|
|||||||
+27
-1
@@ -1,6 +1,6 @@
|
|||||||
#
|
#
|
||||||
# Amsterdam Web Communities System
|
# Amsterdam Web Communities System
|
||||||
# Copyright (c) 2025 Erbosoft Metaverse Design Solutions, All Rights Reserved
|
# Copyright (c) 2025-2026 Erbosoft Metaverse Design Solutions, All Rights Reserved
|
||||||
#
|
#
|
||||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
# 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
|
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
@@ -84,3 +84,29 @@ menudefs:
|
|||||||
link: "/TODO/comm/[CID]/admin/delete"
|
link: "/TODO/comm/[CID]/admin/delete"
|
||||||
permission: "Community.Delete"
|
permission: "Community.Delete"
|
||||||
hazard: true
|
hazard: true
|
||||||
|
- id: "confhost"
|
||||||
|
title: "Host Tools"
|
||||||
|
permset: "conference"
|
||||||
|
warning: >
|
||||||
|
<strong>Note:</strong> These tools provide access to sensitive administrative features for the
|
||||||
|
conference. Use with care and review all changes before applying them to the conference.
|
||||||
|
items:
|
||||||
|
- text: "Change Conference Information"
|
||||||
|
link: "/TODO/comm/[CID]/conf/[CONFID]/info"
|
||||||
|
- text: "Manage Conference Aliases"
|
||||||
|
link: "/TODO/comm/[CID]/conf/[CONFID]/aliases"
|
||||||
|
- text: "Manage Conference Members"
|
||||||
|
link: "/TODO/comm/[CID]/conf/[CONFID]/members"
|
||||||
|
- text: "Customize Conference Appearance"
|
||||||
|
link: "/TODO/comm/[CID]/conf/[CONFID]/custom"
|
||||||
|
- text: "Conference Activity Reports"
|
||||||
|
link: "/TODO/comm/[CID]/conf/[CONFID]/activity"
|
||||||
|
- text: "Conference E-Mail"
|
||||||
|
link: "/TODO/comm/[CID]/conf/[CONFID]/email"
|
||||||
|
- text: "Export Messages"
|
||||||
|
link: "/TODO/comm/[CID]/conf/[CONFID]/export"
|
||||||
|
- text: "Import Messages"
|
||||||
|
link: "/TODO/comm/[CID]/conf/[CONFID]/import"
|
||||||
|
- text: "Delete Conference"
|
||||||
|
link: "/TODO/comm/[CID]/conf/[CONFID]/delete"
|
||||||
|
hazard: true
|
||||||
|
|||||||
+25
-1
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Amsterdam Web Communities System
|
* Amsterdam Web Communities System
|
||||||
* Copyright (c) 2025 Erbosoft Metaverse Design Solutions, All Rights Reserved
|
* Copyright (c) 2025-2026 Erbosoft Metaverse Design Solutions, All Rights Reserved
|
||||||
*
|
*
|
||||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
* 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
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
@@ -98,6 +98,30 @@ func (mdef *MenuDefinition) FilterCommunity(comm *database.Community) *MenuDefin
|
|||||||
return &newmd
|
return &newmd
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FilterConference creates a copy of this menu filtered to the specified community and conference.
|
||||||
|
func (mdef *MenuDefinition) FilterConference(comm *database.Community, confAlias string) *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
|
||||||
|
s1 := strings.ReplaceAll(it.Link, "[CID]", comm.Alias)
|
||||||
|
newmd.Items[i].Link = strings.ReplaceAll(s1, "[CONFID]", confAlias)
|
||||||
|
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.
|
// MenuDefs represents the set of all menu definitions.
|
||||||
type MenuDefs struct {
|
type MenuDefs struct {
|
||||||
D []MenuDefinition `yaml:"menudefs"`
|
D []MenuDefinition `yaml:"menudefs"`
|
||||||
|
|||||||
@@ -0,0 +1,91 @@
|
|||||||
|
{*
|
||||||
|
* Amsterdam Web Communities System
|
||||||
|
* Copyright (c) 2025-2026 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/.
|
||||||
|
*}
|
||||||
|
<div class="p-4">
|
||||||
|
<!-- Top Title -->
|
||||||
|
<div class="mb-2">
|
||||||
|
<h1 class="text-blue-800 text-4xl font-bold inline">Manage Conference:</h1>
|
||||||
|
<span class="text-blue-800 text-xl font-bold ml-2">{{ confName }}</span>
|
||||||
|
<hr class="border-2 border-gray-400 w-4/5 mt-2 mb-6">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Backlink -->
|
||||||
|
<div class="mb-4">
|
||||||
|
<a class="text-blue-700 hover:text-blue-900 text-sm font-medium" href="{{ urlStem }}">Return to Topic List</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Pseud setter -->
|
||||||
|
<div class="flex justify-between items-center mb-4">
|
||||||
|
<form method="POST" action="/TODO/{{ urlStem }}/pseud" class="flex items-center gap-2">
|
||||||
|
<label for="pseud"
|
||||||
|
class="w-64 text-right pr-4 text-black text-sm">Set default pseud for conference:</label>
|
||||||
|
<input type="text" name="pseud" value="{{ pseud }}" size="37" maxlength="255"
|
||||||
|
class="px-3 py-2 border border-gray-300 rounded font-mono text-sm focus:outline-none focus:ring-2 focus:ring-blue-500">
|
||||||
|
<button type="submit" name="set" class="bg-blue-600 hover:bg-blue-700 text-white px-4 py-2 rounded text-sm font-medium transition-colors">Set</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Fixseen link -->
|
||||||
|
<div class="mb-4">
|
||||||
|
<a class="text-blue-700 hover:text-blue-900 text-sm font-bold" href="/TODO/{{ urlStem }}/fixseen">Mark entire conference as read (fixseen)</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{{ if canInvite }}
|
||||||
|
<!-- Invite header -->
|
||||||
|
<div class="mb-2">
|
||||||
|
<h1 class="text-blue-800 text-4xl font-bold inline">Send Invitation</h1>
|
||||||
|
<hr class="border-2 border-gray-400 w-4/5 mt-2 mb-6">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Invite text and link -->
|
||||||
|
<div class="mb-4 text-black text-sm">
|
||||||
|
You may send an invitation via E-mail to outside individuals to join this community and read this conference.
|
||||||
|
</div>
|
||||||
|
<div class="mb-4">
|
||||||
|
<a class="text-blue-700 hover:text-blue-900 text-sm font-bold" href="/TODO/{{ urlStem }}/invite">Click here to send an invitation</a>
|
||||||
|
</div>
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
|
{{ if isset(menu) }}
|
||||||
|
<!-- Host Tools menu header -->
|
||||||
|
<div class="mb-2">
|
||||||
|
<h1 class="text-blue-800 text-4xl font-bold inline">{{ menu.Title }}</h1>
|
||||||
|
<hr class="border-2 border-gray-400 w-4/5 mt-2 mb-6">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Host Tools menu -->
|
||||||
|
<div class="max-w-2xl">
|
||||||
|
<div class="bg-gray-50 p-6 rounded-lg">
|
||||||
|
<nav class="space-y-3">
|
||||||
|
{{ range i, it := menu.Items }}
|
||||||
|
{{ if it.Show(.) }}
|
||||||
|
<div class="flex items-start gap-3">
|
||||||
|
<span class="text-lg pt-0.5">🟣</span>
|
||||||
|
{{ if it.Disabled }}
|
||||||
|
<span class="text-gray-500 font-medium">{{ it.Text }}</span>
|
||||||
|
{{ else }}
|
||||||
|
{{ if it.Hazard }}
|
||||||
|
<a href="{{ it.Link }}" class="text-red-700 hover:text-red-900 font-medium">⚠️ {{ it.Text }}</a>
|
||||||
|
{{ else }}
|
||||||
|
<a href="{{ it.Link }}" class="text-blue-700 hover:text-blue-900 font-medium">{{ it.Text }}</a>
|
||||||
|
{{ end }}
|
||||||
|
{{ end }}
|
||||||
|
</div>
|
||||||
|
{{ end }}
|
||||||
|
{{ end }}
|
||||||
|
</nav>
|
||||||
|
</div>
|
||||||
|
{{ if menu.Warning != "" }}
|
||||||
|
<div class="mt-6 p-4 bg-yellow-50 border-l-4 border-yellow-400">
|
||||||
|
<p class="text-sm text-gray-700">{{ menu.Warning | raw }}</p>
|
||||||
|
</div>
|
||||||
|
{{ end }}
|
||||||
|
</div>
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
|
</div>
|
||||||
@@ -36,7 +36,7 @@
|
|||||||
class="bg-blue-600 hover:bg-blue-700 text-white px-4 py-2 rounded text-sm font-medium transition-colors">
|
class="bg-blue-600 hover:bg-blue-700 text-white px-4 py-2 rounded text-sm font-medium transition-colors">
|
||||||
Find
|
Find
|
||||||
</a>
|
</a>
|
||||||
<a href="/TODO{{ urlStem }}/manage"
|
<a href="{{ urlStem }}/manage"
|
||||||
class="bg-gray-600 hover:bg-gray-700 text-white px-4 py-2 rounded text-sm font-medium transition-colors">
|
class="bg-gray-600 hover:bg-gray-700 text-white px-4 py-2 rounded text-sm font-medium transition-colors">
|
||||||
Manage
|
Manage
|
||||||
</a>
|
</a>
|
||||||
|
|||||||
Reference in New Issue
Block a user