Refactor: change number of return parameters from page functions, include error handling in wrapper

This commit is contained in:
2026-02-10 16:32:20 -07:00
parent e163224a62
commit 080f78a414
15 changed files with 497 additions and 589 deletions
+41 -49
View File
@@ -10,7 +10,6 @@
package main
import (
"errors"
"fmt"
"net/http"
"strconv"
@@ -28,28 +27,27 @@ import (
* Returns:
* Command string dictating what to be rendered.
* Data as a parameter for the command string.
* Standard Go error status.
*/
func ShowCommunity(ctxt ui.AmContext) (string, any, error) {
func ShowCommunity(ctxt ui.AmContext) (string, any) {
me := ctxt.CurrentUser()
prefs, err := me.Prefs(ctxt.Ctx())
if err != nil {
return ui.ErrorPage(ctxt, err)
return "error", err
}
comm := ctxt.CurrentCommunity() // set by middleware
ci, err := comm.ContactInfo(ctxt.Ctx())
if err != nil {
return ui.ErrorPage(ctxt, err)
return "error", err
}
host, err := comm.Host(ctxt.Ctx())
if err != nil {
return ui.ErrorPage(ctxt, err)
return "error", err
}
var cats []*database.Category
if !ctxt.GlobalFlags().Get(database.GlobalFlagNoCategories) {
cats, err = database.AmGetCategoryHierarchy(ctxt.Ctx(), comm.CategoryId)
if err != nil {
return ui.ErrorPage(ctxt, err)
return "error", err
}
}
var pvtAddr bool
@@ -128,7 +126,7 @@ func ShowCommunity(ctxt ui.AmContext) (string, any, error) {
}
ctxt.VarMap().Set("amsterdam_pageTitle", "Community Profile: "+comm.Name)
return "framed_template", "comprofile.jet", nil
return "framed", "comprofile.jet"
}
/* JoinCommunity joins a public community, or starts the process of joining a private one.
@@ -137,24 +135,23 @@ func ShowCommunity(ctxt ui.AmContext) (string, any, error) {
* Returns:
* Command string dictating what to be rendered.
* Data as a parameter for the command string.
* Standard Go error status.
*/
func JoinCommunity(ctxt ui.AmContext) (string, any, error) {
func JoinCommunity(ctxt ui.AmContext) (string, any) {
me := ctxt.CurrentUser()
comm := ctxt.CurrentCommunity() // set by middleware
mbr, _, _, err := comm.Membership(ctxt.Ctx(), me)
if err != nil {
return ui.ErrorPage(ctxt, err)
return "error", err
}
if mbr {
// already member, this is a no-op
return "redirect", fmt.Sprintf("/comm/%s/profile", comm.Alias), nil
return "redirect", fmt.Sprintf("/comm/%s/profile", comm.Alias)
}
if comm.TestPermission("Community.Join", me.BaseLevel) {
if comm.JoinKey != nil && *comm.JoinKey != "" {
dlg, err := ui.AmLoadDialog("join")
if err != nil {
return ui.ErrorPage(ctxt, err)
return "error", err
}
dlg.SetCommunity(comm)
dlg.Field("cc").Value = comm.Alias
@@ -163,12 +160,12 @@ func JoinCommunity(ctxt ui.AmContext) (string, any, error) {
// if get here, this is a public community, and we can join
err = comm.SetMembership(ctxt.Ctx(), me, database.AmDefaultRole("Community.NewUser").Level(), false, me.Uid, ctxt.RemoteIP())
if err != nil {
return ui.ErrorPage(ctxt, err)
return "error", err
}
} else {
return ui.ErrorPage(ctxt, errors.New("you are not permitted to join this community"))
return "error", "you are not permitted to join this community"
}
return "redirect", fmt.Sprintf("/comm/%s/profile", comm.Alias), nil
return "redirect", fmt.Sprintf("/comm/%s/profile", comm.Alias)
}
/* JoinCommunityWithKey joins a private community with a properly specified join key.
@@ -177,29 +174,28 @@ func JoinCommunity(ctxt ui.AmContext) (string, any, error) {
* Returns:
* Command string dictating what to be rendered.
* Data as a parameter for the command string.
* Standard Go error status.
*/
func JoinCommunityWithKey(ctxt ui.AmContext) (string, any, error) {
func JoinCommunityWithKey(ctxt ui.AmContext) (string, any) {
me := ctxt.CurrentUser()
comm := ctxt.CurrentCommunity() // set by middleware
mbr, _, _, err := comm.Membership(ctxt.Ctx(), me)
if err != nil {
return ui.ErrorPage(ctxt, err)
return "error", err
}
if mbr {
// already member, this is a no-op
return "redirect", fmt.Sprintf("/comm/%s/profile", comm.Alias), nil
return "redirect", fmt.Sprintf("/comm/%s/profile", comm.Alias)
}
if comm.TestPermission("Community.Join", me.BaseLevel) {
dlg, err := ui.AmLoadDialog("join")
if err != nil {
return ui.ErrorPage(ctxt, err)
return "error", err
}
dlg.SetCommunity(comm)
dlg.LoadFromForm(ctxt)
action := dlg.WhichButton(ctxt)
if action == "cancel" {
return "redirect", fmt.Sprintf("/comm/%s/profile", comm.Alias), nil
return "redirect", fmt.Sprintf("/comm/%s/profile", comm.Alias)
}
if action == "join_now" {
key := dlg.Field("key").Value
@@ -214,11 +210,11 @@ func JoinCommunityWithKey(ctxt ui.AmContext) (string, any, error) {
if err != nil {
return dlg.RenderError(ctxt, fmt.Sprintf("Error joining: %v", err))
}
return "redirect", fmt.Sprintf("/comm/%s/profile", comm.Alias), nil
return "redirect", fmt.Sprintf("/comm/%s/profile", comm.Alias)
}
return dlg.RenderError(ctxt, "Unknown button pressed on join form.")
}
return "redirect", fmt.Sprintf("/comm/%s/profile", comm.Alias), nil
return "redirect", fmt.Sprintf("/comm/%s/profile", comm.Alias)
}
/* UnjoinCommunity starts the process of unjoining a community.
@@ -227,26 +223,25 @@ func JoinCommunityWithKey(ctxt ui.AmContext) (string, any, error) {
* Returns:
* Command string dictating what to be rendered.
* Data as a parameter for the command string.
* Standard Go error status.
*/
func UnjoinCommunity(ctxt ui.AmContext) (string, any, error) {
func UnjoinCommunity(ctxt ui.AmContext) (string, any) {
me := ctxt.CurrentUser()
comm := ctxt.CurrentCommunity() // set by middleware
mbr, lock, _, err := comm.Membership(ctxt.Ctx(), me)
if err != nil {
return ui.ErrorPage(ctxt, err)
return "error", err
}
if !mbr {
// not a member, just redirect to profile
return "redirect", fmt.Sprintf("/comm/%s/profile", comm.Alias), nil
return "redirect", fmt.Sprintf("/comm/%s/profile", comm.Alias)
}
if lock {
ctxt.SetRC(http.StatusForbidden)
return ui.ErrorPage(ctxt, errors.New("you are not permitted to unjoin this community"))
return "error", "you are not permitted to unjoin this community"
}
ctxt.VarMap().Set("comm", comm)
ctxt.VarMap().Set("amsterdam_pageTitle", "Unjoin Community")
return "framed_template", "unjoin.jet", nil
return "framed", "unjoin.jet"
}
/* UnjoinCommunityConfirm finishes the process of unjoining a community.
@@ -255,35 +250,34 @@ func UnjoinCommunity(ctxt ui.AmContext) (string, any, error) {
* Returns:
* Command string dictating what to be rendered.
* Data as a parameter for the command string.
* Standard Go error status.
*/
func UnjoinCommunityConfirm(ctxt ui.AmContext) (string, any, error) {
func UnjoinCommunityConfirm(ctxt ui.AmContext) (string, any) {
me := ctxt.CurrentUser()
comm := ctxt.CurrentCommunity() // set by middleware
mbr, lock, _, err := comm.Membership(ctxt.Ctx(), me)
if err != nil {
return ui.ErrorPage(ctxt, err)
return "error", err
}
if !mbr {
// not a member, just redirect to profile
return "redirect", fmt.Sprintf("/comm/%s/profile", comm.Alias), nil
return "redirect", fmt.Sprintf("/comm/%s/profile", comm.Alias)
}
if lock {
ctxt.SetRC(http.StatusForbidden)
return ui.ErrorPage(ctxt, errors.New("you are not permitted to unjoin this community"))
return "error", "you are not permitted to unjoin this community"
}
if ctxt.FormFieldIsSet("cancel") {
return "redirect", fmt.Sprintf("/comm/%s/profile", comm.Alias), nil
return "redirect", fmt.Sprintf("/comm/%s/profile", comm.Alias)
}
if ctxt.FormFieldIsSet("unjoin") {
err = comm.SetMembership(ctxt.Ctx(), me, 0, false, me.Uid, ctxt.RemoteIP())
if err != nil {
return ui.ErrorPage(ctxt, err)
return "error", err
}
ctxt.ClearCommunityContext()
return "redirect", fmt.Sprintf("/comm/%s/profile", comm.Alias), nil
return "redirect", fmt.Sprintf("/comm/%s/profile", comm.Alias)
}
return ui.ErrorPage(ctxt, errors.New("unknown button pressed to confirm unjoin"))
return "error", "unknown button pressed to confirm unjoin"
}
/* MemberList lists the members of the community.
@@ -292,9 +286,8 @@ func UnjoinCommunityConfirm(ctxt ui.AmContext) (string, any, error) {
* Returns:
* Command string dictating what to be rendered.
* Data as a parameter for the command string.
* Standard Go error status.
*/
func MemberList(ctxt ui.AmContext) (string, any, error) {
func MemberList(ctxt ui.AmContext) (string, any) {
comm := ctxt.CurrentCommunity() // set by middleware
ofs := 0
p := ctxt.Parameter("ofs")
@@ -316,7 +309,7 @@ func MemberList(ctxt ui.AmContext) (string, any, error) {
listMax := int(ctxt.Globals().MaxCommunityMemberPage)
results, total, err := comm.ListMembers(ctxt.Ctx(), database.ListMembersFieldNone, database.ListMembersOperNone, "", ofs*listMax, listMax, showHidden)
if err != nil {
return ui.ErrorPage(ctxt, err)
return "error", err
}
if total == 0 {
ctxt.VarMap().Set("headerLine", "Community Members: (None)")
@@ -333,7 +326,7 @@ func MemberList(ctxt ui.AmContext) (string, any, error) {
ctxt.VarMap().Set("resultShowNext", true)
}
}
return "framed_template", "memberlist.jet", nil
return "framed", "memberlist.jet"
}
/* MemberSearch searches for members of the community.
@@ -342,9 +335,8 @@ func MemberList(ctxt ui.AmContext) (string, any, error) {
* Returns:
* Command string dictating what to be rendered.
* Data as a parameter for the command string.
* Standard Go error status.
*/
func MemberSearch(ctxt ui.AmContext) (string, any, error) {
func MemberSearch(ctxt ui.AmContext) (string, any) {
comm := ctxt.CurrentCommunity() // set by middleware
ofs, _ := ctxt.FormFieldInt("ofs")
field := ctxt.FormField("field")
@@ -371,7 +363,7 @@ func MemberSearch(ctxt ui.AmContext) (string, any, error) {
iField = database.ListMembersFieldLastName
default:
ctxt.VarMap().Set("errorMessage", "invalid parameter to find")
return "framed_template", "memberlist.jet", nil
return "framed", "memberlist.jet"
}
switch oper {
case "st":
@@ -382,12 +374,12 @@ func MemberSearch(ctxt ui.AmContext) (string, any, error) {
iOper = database.ListMembersOperRegex
default:
ctxt.VarMap().Set("errorMessage", "invalid parameter to find")
return "framed_template", "memberlist.jet", nil
return "framed", "memberlist.jet"
}
listMax := int(ctxt.Globals().MaxCommunityMemberPage)
results, total, err := comm.ListMembers(ctxt.Ctx(), iField, iOper, term, ofs*listMax, listMax, showHidden)
if err != nil {
return ui.ErrorPage(ctxt, err)
return "error", err
}
if total == 0 {
ctxt.VarMap().Set("headerLine", "Search Results: (None)")
@@ -404,5 +396,5 @@ func MemberSearch(ctxt ui.AmContext) (string, any, error) {
ctxt.VarMap().Set("resultShowNext", true)
}
}
return "framed_template", "memberlist.jet", nil
return "framed", "memberlist.jet"
}
+38 -49
View File
@@ -21,6 +21,7 @@ import (
"git.erbosoft.com/amy/amsterdam/database"
"git.erbosoft.com/amy/amsterdam/ui"
"git.erbosoft.com/amy/amsterdam/util"
"github.com/labstack/echo/v4"
log "github.com/sirupsen/logrus"
)
@@ -30,13 +31,11 @@ import (
* 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) {
func CommunityAdminMenu(ctxt ui.AmContext) (string, any) {
comm := ctxt.CurrentCommunity() // set by middleware
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"))
return "error", ENOACCESS
}
menu := ui.AmMenu("communityadmin")
defs := make(map[string]bool)
@@ -46,7 +45,7 @@ func CommunityAdminMenu(ctxt ui.AmContext) (string, any, error) {
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
return "framed", "menu.jet"
}
// setupCommunityProfileDialog sets up fields in the Community Profile dialog.
@@ -79,22 +78,20 @@ func communityLogoURL(ci *database.ContactInfo) string {
* Returns:
* Command string dictating what to be rendered.
* Data as a parameter for the command string.
* Standard Go error status.
*/
func CommunityProfileForm(ctxt ui.AmContext) (string, any, error) {
func CommunityProfileForm(ctxt ui.AmContext) (string, any) {
comm := ctxt.CurrentCommunity() // set by middleware
if !comm.TestPermission("Community.Write", ctxt.EffectiveLevel()) {
ctxt.SetRC(http.StatusForbidden)
return ui.ErrorPage(ctxt, errors.New("you are not permitted to access this page"))
return "error", ENOACCESS
}
var ci *database.ContactInfo
ci, err := comm.ContactInfo(ctxt.Ctx())
if err != nil {
return ui.ErrorPage(ctxt, err)
return "error", err
}
flags, err := comm.Flags(ctxt.Ctx())
if err != nil {
return ui.ErrorPage(ctxt, err)
return "error", err
}
dlg, err := ui.AmLoadDialog("commprofile")
if err == nil {
@@ -136,7 +133,7 @@ func CommunityProfileForm(ctxt ui.AmContext) (string, any, error) {
dlg.Field("pic_in_post").SetChecked(flags.Get(database.CommunityFlagPicturesInPosts))
return dlg.Render(ctxt)
}
return ui.ErrorPage(ctxt, err)
return "error", err
}
// validateJoinKey is an extra validation step for the join key.
@@ -157,13 +154,11 @@ func validateJoinKey(dlg *ui.Dialog) error {
* Returns:
* Command string dictating what to be rendered.
* Data as a parameter for the command string.
* Standard Go error status.
*/
func EditCommunityProfile(ctxt ui.AmContext) (string, any, error) {
func EditCommunityProfile(ctxt ui.AmContext) (string, any) {
comm := ctxt.CurrentCommunity() // set by middleware
if !comm.TestPermission("Community.Write", ctxt.EffectiveLevel()) {
ctxt.SetRC(http.StatusForbidden)
return ui.ErrorPage(ctxt, errors.New("you are not permitted to access this page"))
return "error", ENOACCESS
}
dlg, err := ui.AmLoadDialog("commprofile")
if err == nil {
@@ -172,7 +167,7 @@ func EditCommunityProfile(ctxt ui.AmContext) (string, any, error) {
action := dlg.WhichButton(ctxt)
if action == "cancel" {
return "redirect", fmt.Sprintf("/comm/%s/admin", comm.Alias), nil
return "redirect", fmt.Sprintf("/comm/%s/admin", comm.Alias)
}
if action == "update" {
err = dlg.Validate()
@@ -191,7 +186,7 @@ func EditCommunityProfile(ctxt ui.AmContext) (string, any, error) {
var flags *util.OptionSet
flags, err = comm.Flags(ctxt.Ctx())
if err != nil {
return ui.ErrorPage(ctxt, err)
return "error", err
}
nci := ci.Clone()
nci.URL = dlg.Field("url").ValPtr()
@@ -237,12 +232,12 @@ func EditCommunityProfile(ctxt ui.AmContext) (string, any, error) {
ctxt.ClearCommunityContext()
return dlg.RenderError(ctxt, err.Error())
} else {
return "redirect", fmt.Sprintf("/comm/%s/admin", comm.Alias), nil
return "redirect", fmt.Sprintf("/comm/%s/admin", comm.Alias)
}
}
return dlg.RenderError(ctxt, "No known button click on POST to community profile.")
}
return ui.ErrorPage(ctxt, err)
return "error", err
}
/* CommunityLogoForm renders the form for changing the community logo.
@@ -251,13 +246,11 @@ func EditCommunityProfile(ctxt ui.AmContext) (string, any, error) {
* Returns:
* Command string dictating what to be rendered.
* Data as a parameter for the command string.
* Standard Go error status.
*/
func CommunityLogoForm(ctxt ui.AmContext) (string, any, error) {
func CommunityLogoForm(ctxt ui.AmContext) (string, any) {
comm := ctxt.CurrentCommunity() // set by middleware
if !comm.TestPermission("Community.Write", ctxt.EffectiveLevel()) {
ctxt.SetRC(http.StatusForbidden)
return ui.ErrorPage(ctxt, errors.New("you are not permitted to access this page"))
return "error", ENOACCESS
}
ci, err := comm.ContactInfo(ctxt.Ctx())
if err == nil {
@@ -265,9 +258,9 @@ func CommunityLogoForm(ctxt ui.AmContext) (string, any, error) {
ctxt.VarMap().Set("commAlias", comm.Alias)
ctxt.VarMap().Set("logo_url", communityLogoURL(ci))
ctxt.VarMap().Set("amsterdam_pageTitle", "Upload Community Logo: "+comm.Name)
return "framed_template", "logo_upload.jet", nil
return "framed", "logo_upload.jet"
}
return ui.ErrorPage(ctxt, err)
return "error", err
}
/* EditCommunityLogo handles setting the community logo.
@@ -278,18 +271,17 @@ func CommunityLogoForm(ctxt ui.AmContext) (string, any, error) {
* Data as a parameter for the command string.
* Standard Go error status.
*/
func EditCommunityLogo(ctxt ui.AmContext) (string, any, error) {
func EditCommunityLogo(ctxt ui.AmContext) (string, any) {
comm := ctxt.CurrentCommunity() // set by middleware
if !comm.TestPermission("Community.Write", ctxt.EffectiveLevel()) {
ctxt.SetRC(http.StatusForbidden)
return ui.ErrorPage(ctxt, errors.New("you are not permitted to access this page"))
return "error", ENOACCESS
}
ci, err := comm.ContactInfo(ctxt.Ctx())
if err != nil {
return ui.ErrorPage(ctxt, err)
return "error", err
}
if ctxt.FormFieldIsSet("cancel") {
return "redirect", "/comm/" + comm.Alias + "/admin/profile", nil
return "redirect", "/comm/" + comm.Alias + "/admin/profile"
}
if ctxt.FormFieldIsSet("upload") {
file, err := ctxt.FormFile("thepic")
@@ -309,7 +301,7 @@ func EditCommunityLogo(ctxt ui.AmContext) (string, any, error) {
err = comm.TouchUpdate(ctxt.Ctx())
}
if err == nil {
return "redirect", "/comm/" + comm.Alias + "/admin/profile", nil
return "redirect", "/comm/" + comm.Alias + "/admin/profile"
}
}
}
@@ -319,19 +311,19 @@ func EditCommunityLogo(ctxt ui.AmContext) (string, any, error) {
ctxt.VarMap().Set("commAlias", comm.Alias)
ctxt.VarMap().Set("logo_url", communityLogoURL(ci))
ctxt.VarMap().Set("amsterdam_pageTitle", "Upload Community Logo: "+comm.Name)
return "framed_template", "logo_upload.jet", nil
return "framed", "logo_upload.jet"
}
if ctxt.FormFieldIsSet("remove") {
purl := ci.PhotoURL
happy := false
if purl == nil || *purl == "" {
// this is a no-op
return "redirect", "/comm/" + comm.Alias + "/admin/profile", nil
return "redirect", "/comm/" + comm.Alias + "/admin/profile"
}
if strings.HasPrefix(*purl, "/img/store/") {
id, err := strconv.Atoi((*purl)[11:])
if err != nil {
return ui.ErrorPage(ctxt, err)
return "error", err
}
defer func() {
if happy {
@@ -347,12 +339,12 @@ func EditCommunityLogo(ctxt ui.AmContext) (string, any, error) {
ci.PhotoURL = nil
_, err := ci.Save(ctxt.Ctx())
if err != nil {
return ui.ErrorPage(ctxt, err)
return "error", err
}
happy = true
return "redirect", "/comm/" + comm.Alias + "/admin/profile", nil
return "redirect", "/comm/" + comm.Alias + "/admin/profile"
}
return ui.ErrorPage(ctxt, errors.New("invalid button detected in logo upload"))
return "error", "invalid button detected in logo upload"
}
/* CreateCommunityForm renders the form for creating a new community.
@@ -363,11 +355,10 @@ func EditCommunityLogo(ctxt ui.AmContext) (string, any, error) {
* Data as a parameter for the command string.
* Standard Go error status.
*/
func CreateCommunityForm(ctxt ui.AmContext) (string, any, error) {
func CreateCommunityForm(ctxt ui.AmContext) (string, any) {
user := ctxt.CurrentUser()
if user.BaseLevel < uint16(ctxt.Globals().CommunityCreateLevel) {
ctxt.SetRC(http.StatusForbidden)
return ui.ErrorPage(ctxt, errors.New("you are not permitted to create a community"))
return "error", echo.NewHTTPError(http.StatusForbidden, "you are not permitted to create a community")
}
dlg, err := ui.AmLoadDialog("create_comm")
if err == nil {
@@ -375,7 +366,7 @@ func CreateCommunityForm(ctxt ui.AmContext) (string, any, error) {
dlg.Field("country").Value = "US"
return dlg.Render(ctxt)
}
return ui.ErrorPage(ctxt, err)
return "error", err
}
/* CreateCommunity creates a new community.
@@ -384,20 +375,18 @@ func CreateCommunityForm(ctxt ui.AmContext) (string, any, error) {
* Returns:
* Command string dictating what to be rendered.
* Data as a parameter for the command string.
* Standard Go error status.
*/
func CreateCommunity(ctxt ui.AmContext) (string, any, error) {
func CreateCommunity(ctxt ui.AmContext) (string, any) {
user := ctxt.CurrentUser()
if user.BaseLevel < uint16(ctxt.Globals().CommunityCreateLevel) {
ctxt.SetRC(http.StatusForbidden)
return ui.ErrorPage(ctxt, errors.New("you are not permitted to create a community"))
return "error", echo.NewHTTPError(http.StatusForbidden, "you are not permitted to create a community")
}
dlg, err := ui.AmLoadDialog("create_comm")
if err == nil {
dlg.LoadFromForm(ctxt)
action := dlg.WhichButton(ctxt)
if action == "cancel" {
return "redirect", "/", nil
return "redirect", "/"
}
if action == "create" {
err = dlg.Validate()
@@ -451,9 +440,9 @@ func CreateCommunity(ctxt ui.AmContext) (string, any, error) {
return dlg.RenderError(ctxt, err.Error())
}
// new community is now created! redirect to the new profile
return "redirect", fmt.Sprintf("/comm/%s/profile", comm.Alias), nil
return "redirect", fmt.Sprintf("/comm/%s/profile", comm.Alias)
}
return dlg.RenderError(ctxt, "No known button click on POST to community creation.")
}
return ui.ErrorPage(ctxt, err)
return "error", err
}
+54 -68
View File
@@ -12,7 +12,6 @@ package main
import (
"context"
"errors"
"fmt"
"net/http"
"reflect"
@@ -24,6 +23,7 @@ import (
"git.erbosoft.com/amy/amsterdam/htmlcheck"
"git.erbosoft.com/amy/amsterdam/ui"
"github.com/CloudyKit/jet/v6"
"github.com/labstack/echo/v4"
log "github.com/sirupsen/logrus"
)
@@ -35,7 +35,7 @@ import (
* Data as a parameter for the command string.
* Standard Go error status.
*/
func Conferences(ctxt ui.AmContext) (string, any, error) {
func Conferences(ctxt ui.AmContext) (string, any) {
comm := ctxt.CurrentCommunity()
ctxt.VarMap().Set("commName", comm.Name)
ctxt.VarMap().Set("commAlias", comm.Alias)
@@ -43,7 +43,7 @@ func Conferences(ctxt ui.AmContext) (string, any, error) {
clist, err := database.AmGetCommunityConferences(ctxt.Ctx(), comm.Id,
comm.TestPermission("Community.ShowHiddenObjects", ctxt.EffectiveLevel()))
if err != nil {
return ui.ErrorPage(ctxt, err)
return "error", err
}
ctxt.VarMap().Set("conferences", clist)
if len(clist) > 0 {
@@ -51,7 +51,7 @@ func Conferences(ctxt ui.AmContext) (string, any, error) {
for i, conf := range clist {
msgCount, err := conf.UnreadMessages(ctxt.Ctx(), ctxt.CurrentUser())
if err != nil {
return ui.ErrorPage(ctxt, err)
return "error", err
}
newflag[i] = msgCount > 0
}
@@ -59,7 +59,7 @@ func Conferences(ctxt ui.AmContext) (string, any, error) {
}
ctxt.VarMap().Set("canCreate", comm.TestPermission("Community.Create", ctxt.EffectiveLevel()))
ctxt.VarMap().Set("canManage", comm.TestPermission("Community.Create", ctxt.EffectiveLevel()))
return "framed_template", "conflist.jet", err
return "framed", "conflist.jet"
}
/* Topics displays the list of topics in a conference.
@@ -68,19 +68,17 @@ func Conferences(ctxt ui.AmContext) (string, any, error) {
* Returns:
* Command string dictating what to be rendered.
* Data as a parameter for the command string.
* Standard Go error status.
*/
func Topics(ctxt ui.AmContext) (string, any, error) {
func Topics(ctxt ui.AmContext) (string, any) {
prefs, err := ctxt.CurrentUser().Prefs(ctxt.Ctx())
if err != nil {
return ui.ErrorPage(ctxt, err)
return "error", err
}
comm := ctxt.CurrentCommunity()
conf := ctxt.GetScratch("currentConference").(*database.Conference)
myLevel := ctxt.GetScratch("levelInConference").(uint16)
if !conf.TestPermission("Conference.Read", myLevel) {
ctxt.SetRC(http.StatusForbidden)
return ui.ErrorPage(ctxt, errors.New("you are not permitted to read this conference"))
return "error", echo.NewHTTPError(http.StatusForbidden, "you are not permitted to read this conference")
}
// Get view and sort parameters from query, session, or defaults. Store to session.
@@ -109,14 +107,14 @@ func Topics(ctxt ui.AmContext) (string, any, error) {
topics, err := database.AmListTopics(ctxt.Ctx(), conf.ConfId, ctxt.CurrentUserId(), view, sort, false)
if err != nil {
return ui.ErrorPage(ctxt, err)
return "error", err
}
var hotlistTest bool = false
if !ctxt.CurrentUser().IsAnon {
hotlistTest, err = database.AmIsInHotlist(ctxt.Ctx(), ctxt.CurrentUser(), comm.Id, conf.ConfId)
if err != nil {
return ui.ErrorPage(ctxt, err)
return "error", err
}
}
@@ -152,7 +150,7 @@ func Topics(ctxt ui.AmContext) (string, any, error) {
ctxt.VarMap().Set("topics", topics)
ctxt.VarMap().Set("formattedDate", fdate)
ctxt.VarMap().Set("amsterdam_pageTitle", "Topics in "+conf.Name)
return "framed_template", "topiclist.jet", nil
return "framed", "topiclist.jet"
}
/* NewTopicForm displays the form for creating a new topic.
@@ -161,27 +159,25 @@ func Topics(ctxt ui.AmContext) (string, any, error) {
* Returns:
* Command string dictating what to be rendered.
* Data as a parameter for the command string.
* Standard Go error status.
*/
func NewTopicForm(ctxt ui.AmContext) (string, any, error) {
func NewTopicForm(ctxt ui.AmContext) (string, any) {
comm := ctxt.CurrentCommunity()
conf := ctxt.GetScratch("currentConference").(*database.Conference)
myLevel := ctxt.GetScratch("levelInConference").(uint16)
if !conf.TestPermission("Conference.Create", myLevel) {
ctxt.SetRC(http.StatusForbidden)
return ui.ErrorPage(ctxt, errors.New("you are not permitted to create topics in this conference"))
return "error", echo.NewHTTPError(http.StatusForbidden, "you are not permitted to create topics in this conference")
}
ctxt.VarMap().Set("conferenceName", conf.Name)
ctxt.VarMap().Set("urlStem", fmt.Sprintf("/comm/%s/conf/%s", comm.Alias, ctxt.GetScratch("currentAlias")))
ctxt.VarMap().Set("topicName", "")
pseud, err := conf.DefaultPseud(ctxt.Ctx(), ctxt.CurrentUser())
if err != nil {
return ui.ErrorPage(ctxt, err)
return "error", err
}
ctxt.VarMap().Set("pseud", pseud)
ctxt.VarMap().Set("pb", "")
ctxt.VarMap().Set("amsterdam_pageTitle", "Create New Topic")
return "framed_template", "new_topic.jet", nil
return "framed", "new_topic.jet"
}
/* NewTopic creates a new topic and posts the initial message.
@@ -190,26 +186,24 @@ func NewTopicForm(ctxt ui.AmContext) (string, any, error) {
* Returns:
* Command string dictating what to be rendered.
* Data as a parameter for the command string.
* Standard Go error status.
*/
func NewTopic(ctxt ui.AmContext) (string, any, error) {
func NewTopic(ctxt ui.AmContext) (string, any) {
comm := ctxt.CurrentCommunity()
conf := ctxt.GetScratch("currentConference").(*database.Conference)
myLevel := ctxt.GetScratch("levelInConference").(uint16)
if !conf.TestPermission("Conference.Create", myLevel) {
ctxt.SetRC(http.StatusForbidden)
return ui.ErrorPage(ctxt, errors.New("you are not permitted to create topics in this conference"))
return "error", echo.NewHTTPError(http.StatusForbidden, "you are not permitted to create topics in this conference")
}
urlStem := fmt.Sprintf("/comm/%s/conf/%s", comm.Alias, ctxt.GetScratch("currentAlias"))
if ctxt.FormFieldIsSet("cancel") {
return "redirect", urlStem, nil
return "redirect", urlStem
}
if ctxt.FormFieldIsSet("preview") {
// start by escaping the title
checker, err := htmlcheck.AmNewHTMLChecker(ctxt.Ctx(), "escaper")
if err != nil {
return ui.ErrorPage(ctxt, err)
return "error", err
}
checker.Append(ctxt.FormField("title"))
checker.Finish()
@@ -234,7 +228,7 @@ func NewTopic(ctxt ui.AmContext) (string, any, error) {
// run the preview
checker, err = htmlcheck.AmNewHTMLChecker(ctxt.Ctx(), "preview")
if err != nil {
return ui.ErrorPage(ctxt, err)
return "error", err
}
checker.SetContext("PostLinkDecoderContext", database.AmCreatePostLinkContext(comm.Alias, ctxt.URLParam("cid"), conf.TopTopic+1))
checker.Append(postdata)
@@ -250,13 +244,13 @@ func NewTopic(ctxt ui.AmContext) (string, any, error) {
ctxt.VarMap().Set("conferenceName", conf.Name)
ctxt.VarMap().Set("urlStem", urlStem)
ctxt.VarMap().Set("amsterdam_pageTitle", "Preview New Topic")
return "framed_template", "new_topic.jet", nil
return "framed", "new_topic.jet"
}
if ctxt.FormFieldIsSet("post1") {
// start by checking the title and pseud
checker, err := htmlcheck.AmNewHTMLChecker(ctxt.Ctx(), "post-pseud")
if err != nil {
return ui.ErrorPage(ctxt, err)
return "error", err
}
checker.Append(ctxt.FormField("title"))
checker.Finish()
@@ -269,7 +263,7 @@ func NewTopic(ctxt ui.AmContext) (string, any, error) {
// now check the post data itself
checker, err = htmlcheck.AmNewHTMLChecker(ctxt.Ctx(), "post-body")
if err != nil {
return ui.ErrorPage(ctxt, err)
return "error", err
}
checker.SetContext("PostLinkDecoderContext", database.AmCreatePostLinkContext(comm.Alias, ctxt.URLParam("cid"), conf.TopTopic+1))
checker.Append(ctxt.FormField("pb"))
@@ -280,26 +274,26 @@ func NewTopic(ctxt ui.AmContext) (string, any, error) {
// Add the topic!
topic, err := database.AmNewTopic(ctxt.Ctx(), conf, ctxt.CurrentUser(), topicName, zeroPostPseud, zeroPost, int32(lines), ctxt.RemoteIP())
if err != nil {
return ui.ErrorPage(ctxt, err)
return "error", err
}
if !ctxt.FormFieldIsSet("attach") {
return "redirect", urlStem, nil // no attachment - just redisplay topic list
return "redirect", urlStem // no attachment - just redisplay topic list
}
post, err := topic.GetPost(ctxt.Ctx(), 0) // get the initial post in the new topic
if err != nil {
return ui.ErrorPage(ctxt, err)
return "error", err
}
// go upload the attachment
ctxt.VarMap().Set("target", urlStem)
ctxt.VarMap().Set("post", post.PostId)
ctxt.VarMap().Set("amsterdam_pageTitle", "Upload Attachment")
return "framed_template", "attachment_upload.jet", nil
return "framed_template", "attachment_upload.jet"
}
return ui.ErrorPage(ctxt, errors.New("invalid button clicked on form"))
return "error", "invalid button clicked on form"
}
/* breakRange breaks up a post range into two elements.
@@ -434,9 +428,8 @@ func templateBozo(args jet.Arguments) reflect.Value {
* Returns:
* Command string dictating what to be rendered.
* Data as a parameter for the command string.
* Standard Go error status.
*/
func ReadPosts(ctxt ui.AmContext) (string, any, error) {
func ReadPosts(ctxt ui.AmContext) (string, any) {
// Extract the traverser first, so we can unclear it in background tasks.
var traverser ui.TopicTraverser = nil
if ctxt.IsSession("topic.traverser") {
@@ -466,7 +459,7 @@ func ReadPosts(ctxt ui.AmContext) (string, any, error) {
// Get user prefs.
prefs, err := ctxt.CurrentUser().Prefs(ctxt.Ctx())
if err != nil {
return ui.ErrorPage(ctxt, err)
return "error", err
}
// Locate community, conference, and topic.
comm := ctxt.CurrentCommunity()
@@ -478,21 +471,18 @@ func ReadPosts(ctxt ui.AmContext) (string, any, error) {
// Determine the range of posts to display. The "pin" is the post number after which we display the horizontal line separating old and new posts.
lastRead, err := topic.GetLastRead(ctxt.Ctx(), ctxt.CurrentUser())
if err != nil {
ctxt.SetRC(http.StatusNotFound)
return ui.ErrorPage(ctxt, fmt.Errorf("posts not found in topic %d - %v", topic.Number, err))
return "error", echo.NewHTTPError(http.StatusNotFound, fmt.Sprintf("posts not found in topic %d - %v", topic.Number, err))
}
postRange := make([]int32, 2)
var pin int32 = -1
resetLastRead := false
if ctxt.HasParameter("r") {
if err := breakRange(topic, postRange, ctxt.Parameter("r"), ","); err != nil {
ctxt.SetRC(http.StatusNotFound)
return ui.ErrorPage(ctxt, err)
return "error", echo.NewHTTPError(http.StatusNotFound).SetInternal(err)
}
} else if ctxt.HasParameter("rgo") {
if err := breakRange(topic, postRange, ctxt.Parameter("rgo"), "-"); err != nil {
ctxt.SetRC(http.StatusNotFound)
return ui.ErrorPage(ctxt, err)
return "error", echo.NewHTTPError(http.StatusNotFound).SetInternal(err)
}
} else {
postRange[0] = lastRead + 1
@@ -515,7 +505,7 @@ func ReadPosts(ctxt ui.AmContext) (string, any, error) {
// Load the actual posts.
posts, err := database.AmGetPostRange(ctxt.Ctx(), topic, postRange[0], postRange[1])
if err != nil {
return ui.ErrorPage(ctxt, fmt.Errorf("internal error getting posts <%d:%d-%d> - %v", topic.Number, postRange[0], postRange[1], err))
return "error", fmt.Sprintf("internal error getting posts <%d:%d-%d> - %v", topic.Number, postRange[0], postRange[1], err)
}
// Determine other required data.
@@ -547,7 +537,7 @@ func ReadPosts(ctxt ui.AmContext) (string, any, error) {
// Set the user's pseud.
pseud, err := conf.DefaultPseud(ctxt.Ctx(), ctxt.CurrentUser())
if err != nil {
return ui.ErrorPage(ctxt, err)
return "error", err
}
ctxt.VarMap().Set("pseud", pseud)
@@ -572,7 +562,7 @@ func ReadPosts(ctxt ui.AmContext) (string, any, error) {
if nbozo >= 0 {
err = topic.SetBozo(ctxt.Ctx(), ctxt.CurrentUser(), posts[0].CreatorUid, nbozo != 0)
if err != nil {
return ui.ErrorPage(ctxt, err)
return "error", err
}
}
isMyPost := (posts[0].CreatorUid == ctxt.CurrentUserId()) && !ctxt.CurrentUser().IsAnon
@@ -632,7 +622,7 @@ func ReadPosts(ctxt ui.AmContext) (string, any, error) {
topic.SetLastRead(ctx, user, topic.TopMessage)
})
}
return "framed_template", "posts.jet", nil
return "framed", "posts.jet"
}
/* PostInTopic adds a new post to a topic.
@@ -641,9 +631,8 @@ func ReadPosts(ctxt ui.AmContext) (string, any, error) {
* Returns:
* Command string dictating what to be rendered.
* Data as a parameter for the command string.
* Standard Go error status.
*/
func PostInTopic(ctxt ui.AmContext) (string, any, error) {
func PostInTopic(ctxt ui.AmContext) (string, any) {
// Locate community, conference, and topic.
comm := ctxt.CurrentCommunity()
conf := ctxt.GetScratch("currentConference").(*database.Conference)
@@ -653,28 +642,25 @@ func PostInTopic(ctxt ui.AmContext) (string, any, error) {
urlStem := fmt.Sprintf("/comm/%s/conf/%s/r/%d", comm.Alias, ctxt.GetScratch("currentAlias"), topic.Number)
if ctxt.FormFieldIsSet("cancel") {
return "redirect", urlStem, nil
return "redirect", urlStem
}
if !conf.TestPermission("Conference.Post", level) {
ctxt.SetRC(http.StatusForbidden)
return ui.ErrorPage(ctxt, errors.New("you do not have permission to post in this conference"))
return "error", echo.NewHTTPError(http.StatusForbidden, "you do not have permission to post in this conference")
}
if topic.Frozen && !conf.TestPermission("Conference.Hide", level) {
ctxt.SetRC(http.StatusForbidden)
return ui.ErrorPage(ctxt, errors.New("this topic is frozen, and you do not have permission to post to it"))
return "error", echo.NewHTTPError(http.StatusForbidden, "this topic is frozen, and you do not have permission to post to it")
}
if topic.Archived && !conf.TestPermission("Conference.Hide", level) {
ctxt.SetRC(http.StatusForbidden)
return ui.ErrorPage(ctxt, errors.New("this topic is archived, and you do not have permission to post to it"))
return "error", echo.NewHTTPError(http.StatusForbidden, "this topic is archived, and you do not have permission to post to it")
}
// Set the escaped version of the text into the varmap, because it'll be needed if we do anything other than redirect.
checker, err := htmlcheck.AmNewHTMLChecker(ctxt.Ctx(), "escaper")
if err != nil {
return ui.ErrorPage(ctxt, err)
return "error", err
}
checker.Append(ctxt.FormField("pseud"))
checker.Finish()
@@ -700,7 +686,7 @@ func PostInTopic(ctxt ui.AmContext) (string, any, error) {
// Preview the post.
checker, err = htmlcheck.AmNewHTMLChecker(ctxt.Ctx(), "preview")
if err != nil {
return ui.ErrorPage(ctxt, err)
return "error", err
}
checker.SetContext("PostLinkDecoderContext", database.AmCreatePostLinkContext(comm.Alias, ctxt.URLParam("cid"), topic.Number))
checker.Append(postdata)
@@ -713,7 +699,7 @@ func PostInTopic(ctxt ui.AmContext) (string, any, error) {
ctxt.VarMap().Set("maxPost", ctxt.FormField("xp"))
ctxt.VarMap().Set("urlStem", urlStem)
ctxt.VarMap().Set("amsterdam_pageTitle", "Previewing Message")
return "framed_template", "preview_post.jet", nil
return "framed", "preview_post.jet"
}
// Figure out which URL to return to once this post is made.
var returnURL string
@@ -724,20 +710,20 @@ func PostInTopic(ctxt ui.AmContext) (string, any, error) {
} else if ctxt.FormFieldIsSet("posttopics") {
returnURL = fmt.Sprintf("/comm/%s/conf/%s", comm.Alias, ctxt.GetScratch("currentAlias"))
} else {
return ui.ErrorPage(ctxt, errors.New("unknown post button"))
return "error", "unknown post button"
}
// Check for slippage.
maxPost, err := ctxt.FormFieldInt("xp")
if err != nil {
return ui.ErrorPage(ctxt, err)
return "error", err
}
if int32(maxPost) < topic.TopMessage {
// Slippage detected! Display the slipped posts and another post box.
// Start by getting the slipped posts.
posts, err := database.AmGetPostRange(ctxt.Ctx(), topic, int32(maxPost), topic.TopMessage)
if err != nil {
return ui.ErrorPage(ctxt, err)
return "error", err
}
plc := database.AmCreatePostLinkContext("", ctxt.GetScratch("currentAlias").(string), topic.Number)
@@ -757,12 +743,12 @@ func PostInTopic(ctxt ui.AmContext) (string, any, error) {
ctxt.VarMap().Set("topicName", topic.Name)
ctxt.VarMap().Set("amsterdam_pageTitle", "Slippage or Double-Click Detected")
return "framed_template", "slippage.jet", nil
return "framed", "slippage.jet"
}
// if we get here, we are posting - start by checking the title and pseud
checker, err = htmlcheck.AmNewHTMLChecker(ctxt.Ctx(), "post-pseud")
if err != nil {
return ui.ErrorPage(ctxt, err)
return "error", err
}
checker.Append(ctxt.FormField("pseud"))
checker.Finish()
@@ -771,7 +757,7 @@ func PostInTopic(ctxt ui.AmContext) (string, any, error) {
// now check the post data itself
checker, err = htmlcheck.AmNewHTMLChecker(ctxt.Ctx(), "post-body")
if err != nil {
return ui.ErrorPage(ctxt, err)
return "error", err
}
checker.SetContext("PostLinkDecoderContext", database.AmCreatePostLinkContext(comm.Alias, ctxt.URLParam("cid"), topic.Number))
checker.Append(ctxt.FormField("pb"))
@@ -782,7 +768,7 @@ func PostInTopic(ctxt ui.AmContext) (string, any, error) {
// Add the post!
hdr, err := database.AmNewPost(ctxt.Ctx(), conf, topic, ctxt.CurrentUser(), postPseud, postText, int32(lines), ctxt.RemoteIP())
if err != nil {
return ui.ErrorPage(ctxt, err)
return "error", err
}
// Check who's subscribed to this topic.
@@ -800,12 +786,12 @@ func PostInTopic(ctxt ui.AmContext) (string, any, error) {
}
if !ctxt.FormFieldIsSet("attach") {
return "redirect", returnURL, nil // no attachment - just bounce directly to the destination
return "redirect", returnURL // no attachment - just bounce directly to the destination
}
// go upload the attachment
ctxt.VarMap().Set("target", returnURL)
ctxt.VarMap().Set("post", hdr.PostId)
ctxt.VarMap().Set("amsterdam_pageTitle", "Upload Attachment")
return "framed_template", "attachment_upload.jet", nil
return "framed", "attachment_upload.jet"
}
+119 -152
View File
@@ -23,9 +23,13 @@ import (
"git.erbosoft.com/amy/amsterdam/database"
"git.erbosoft.com/amy/amsterdam/email"
"git.erbosoft.com/amy/amsterdam/ui"
"github.com/labstack/echo/v4"
log "github.com/sirupsen/logrus"
)
// EPOSTREF is the internal error for post references.
var EPOSTREF error = errors.New("internal error getting post reference")
// slurpFile reads the contrents of a multipart.File into memory.
func slurpFile(file *multipart.FileHeader) ([]byte, error) {
f, err := file.Open()
@@ -42,14 +46,13 @@ func slurpFile(file *multipart.FileHeader) ([]byte, error) {
* Returns:
* Command string dictating what to be rendered.
* Data as a parameter for the command string.
* Standard Go error status.
*/
func AttachmentUpload(ctxt ui.AmContext) (string, any, error) {
func AttachmentUpload(ctxt ui.AmContext) (string, any) {
target := ctxt.FormField("tgt")
postidStr := ctxt.FormField("post")
postId, err := strconv.ParseInt(postidStr, 10, 64)
if err != nil {
return ui.ErrorPage(ctxt, fmt.Errorf("internal error converting postID: %v", err))
return "error", fmt.Sprintf("internal error converting postID: %v", err)
}
if ctxt.FormFieldIsSet("upload") {
file, err := ctxt.FormFile("thefile")
@@ -62,7 +65,7 @@ func AttachmentUpload(ctxt ui.AmContext) (string, any, error) {
if err == nil {
err = post.SetAttachment(ctxt.Ctx(), ctxt.CurrentUser(), file.Filename, file.Header.Get("Content-Type"), int32(file.Size), data, ctxt.RemoteIP())
if err == nil {
return "redirect", target, nil
return "redirect", target
}
}
}
@@ -72,9 +75,9 @@ func AttachmentUpload(ctxt ui.AmContext) (string, any, error) {
ctxt.VarMap().Set("post", postId)
ctxt.VarMap().Set("amsterdam_pageTitle", "Upload Attachment")
ctxt.VarMap().Set("errorMessage", err.Error())
return "framed_template", "attachment_upload.jet", nil
return "framed", "attachment_upload.jet"
}
return ui.ErrorPage(ctxt, errors.New("invalid button clicked on form"))
return "error", "invalid button clicked on form"
}
/* AttachmentSend sends the data of an attachment to the browser.
@@ -83,30 +86,29 @@ func AttachmentUpload(ctxt ui.AmContext) (string, any, error) {
* Returns:
* Command string dictating what to be rendered.
* Data as a parameter for the command string.
* Standard Go error status.
*/
func AttachmentSend(ctxt ui.AmContext) (string, any, error) {
func AttachmentSend(ctxt ui.AmContext) (string, any) {
postIdStr := ctxt.URLParam("post")
postId, err := strconv.ParseInt(postIdStr, 10, 64)
if err != nil {
return ui.ErrorPage(ctxt, fmt.Errorf("internal error converting postID: %v", err))
return "error", fmt.Sprintf("internal error converting postID: %v", err)
}
hdr, err := database.AmGetPost(ctxt.Ctx(), postId)
if err != nil {
return ui.ErrorPage(ctxt, err)
return "error", err
}
// Retrieve attachment info and data.
info, err := hdr.AttachmentInfo(ctxt.Ctx())
if err != nil {
return ui.ErrorPage(ctxt, err)
return "error", err
} else if info == nil {
return ui.ErrorPage(ctxt, errors.New("attachment not found"))
return "error", echo.NewHTTPError(http.StatusNotFound, "attachment not found")
}
data, err := hdr.AttachmentData(ctxt.Ctx())
if err != nil {
return ui.ErrorPage(ctxt, err)
return "error", err
}
// Record a "hit" on this attachment in the background.
@@ -119,7 +121,7 @@ func AttachmentSend(ctxt ui.AmContext) (string, any, error) {
if !strings.HasPrefix(info.MIMEType, "image/") {
ctxt.SetHeader("Content-Disposition", fmt.Sprintf("attachment; filename=\"%s\"", info.Filename))
}
return "bytes", data, nil
return "bytes", data
}
/* ConfManage displays the "manage conference" page.
@@ -128,9 +130,8 @@ func AttachmentSend(ctxt ui.AmContext) (string, any, error) {
* 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) {
func ConfManage(ctxt ui.AmContext) (string, any) {
comm := ctxt.CurrentCommunity()
conf := ctxt.GetScratch("currentConference").(*database.Conference)
myLevel := ctxt.GetScratch("levelInConference").(uint16)
@@ -140,7 +141,7 @@ func ConfManage(ctxt ui.AmContext) (string, any, error) {
pseud, err := conf.DefaultPseud(ctxt.Ctx(), ctxt.CurrentUser())
if err != nil {
return ui.ErrorPage(ctxt, err)
return "error", err
}
ctxt.VarMap().Set("pseud", pseud)
@@ -149,7 +150,7 @@ func ConfManage(ctxt ui.AmContext) (string, any, error) {
} else {
member, _, _, err := comm.Membership(ctxt.Ctx(), ctxt.CurrentUser())
if err != nil {
return ui.ErrorPage(ctxt, err)
return "error", err
}
ctxt.VarMap().Set("canInvite", member)
}
@@ -160,7 +161,7 @@ func ConfManage(ctxt ui.AmContext) (string, any, error) {
}
ctxt.VarMap().Set("amsterdam_pageTitle", "Manage Conference: "+conf.Name)
return "framed_template", "manage_conf.jet", nil
return "framed", "manage_conf.jet"
}
/* SetPseud sets the user's default pseud for the conference.
@@ -169,17 +170,16 @@ func ConfManage(ctxt ui.AmContext) (string, any, error) {
* Returns:
* Command string dictating what to be rendered.
* Data as a parameter for the command string.
* Standard Go error status.
*/
func SetPseud(ctxt ui.AmContext) (string, any, error) {
func SetPseud(ctxt ui.AmContext) (string, any) {
comm := ctxt.CurrentCommunity()
conf := ctxt.GetScratch("currentConference").(*database.Conference)
pseud := ctxt.FormField("pseud")
err := conf.SetDefaultPseud(ctxt.Ctx(), ctxt.CurrentUser(), pseud)
if err != nil {
return ui.ErrorPage(ctxt, err)
return "error", err
}
return "redirect", fmt.Sprintf("/comm/%s/conf/%s/manage", comm.Alias, ctxt.GetScratch("currentAlias")), nil
return "redirect", fmt.Sprintf("/comm/%s/conf/%s/manage", comm.Alias, ctxt.GetScratch("currentAlias"))
}
/* ConfFixseen marks all messages in a conference as read.
@@ -188,16 +188,15 @@ func SetPseud(ctxt ui.AmContext) (string, any, error) {
* Returns:
* Command string dictating what to be rendered.
* Data as a parameter for the command string.
* Standard Go error status.
*/
func ConfFixseen(ctxt ui.AmContext) (string, any, error) {
func ConfFixseen(ctxt ui.AmContext) (string, any) {
comm := ctxt.CurrentCommunity()
conf := ctxt.GetScratch("currentConference").(*database.Conference)
err := conf.Fixseen(ctxt.Ctx(), ctxt.CurrentUser())
if err != nil {
return ui.ErrorPage(ctxt, err)
return "error", err
}
return "redirect", fmt.Sprintf("/comm/%s/conf/%s/manage", comm.Alias, ctxt.GetScratch("currentAlias")), nil
return "redirect", fmt.Sprintf("/comm/%s/conf/%s/manage", comm.Alias, ctxt.GetScratch("currentAlias"))
}
/* AddToHotlist adds the current community and conference to the user's hotlist..
@@ -206,16 +205,15 @@ func ConfFixseen(ctxt ui.AmContext) (string, any, error) {
* Returns:
* Command string dictating what to be rendered.
* Data as a parameter for the command string.
* Standard Go error status.
*/
func AddToHotlist(ctxt ui.AmContext) (string, any, error) {
func AddToHotlist(ctxt ui.AmContext) (string, any) {
comm := ctxt.CurrentCommunity()
conf := ctxt.GetScratch("currentConference").(*database.Conference)
err := database.AmAppendToHotlist(ctxt.Ctx(), ctxt.CurrentUser(), comm.Id, conf.ConfId)
if err != nil {
return ui.ErrorPage(ctxt, err)
return "error", err
}
return "redirect", fmt.Sprintf("/comm/%s/conf/%s", comm.Alias, ctxt.GetScratch("currentAlias")), nil
return "redirect", fmt.Sprintf("/comm/%s/conf/%s", comm.Alias, ctxt.GetScratch("currentAlias"))
}
/* HideTopic hides or shows the current topic for the current user.
@@ -224,19 +222,18 @@ func AddToHotlist(ctxt ui.AmContext) (string, any, error) {
* Returns:
* Command string dictating what to be rendered.
* Data as a parameter for the command string.
* Standard Go error status.
*/
func HideTopic(ctxt ui.AmContext) (string, any, error) {
func HideTopic(ctxt ui.AmContext) (string, any) {
topic := ctxt.GetScratch("currentTopic").(*database.Topic)
hidden, err := topic.IsHidden(ctxt.Ctx(), ctxt.CurrentUser())
if err != nil {
return ui.ErrorPage(ctxt, err)
return "error", err
}
err = topic.SetHidden(ctxt.Ctx(), ctxt.CurrentUser(), !hidden)
if err != nil {
return ui.ErrorPage(ctxt, err)
return "error", err
}
return "redirect", fmt.Sprintf("/comm/%s/conf/%s/r/%d", ctxt.CurrentCommunity().Alias, ctxt.GetScratch("currentAlias"), topic.Number), nil
return "redirect", fmt.Sprintf("/comm/%s/conf/%s/r/%d", ctxt.CurrentCommunity().Alias, ctxt.GetScratch("currentAlias"), topic.Number)
}
/* FreezeTopic freezes or unfreezes the current topic.
@@ -245,21 +242,19 @@ func HideTopic(ctxt ui.AmContext) (string, any, error) {
* Returns:
* Command string dictating what to be rendered.
* Data as a parameter for the command string.
* Standard Go error status.
*/
func FreezeTopic(ctxt ui.AmContext) (string, any, error) {
func FreezeTopic(ctxt ui.AmContext) (string, any) {
conf := ctxt.GetScratch("currentConference").(*database.Conference)
myLevel := ctxt.GetScratch("levelInConference").(uint16)
topic := ctxt.GetScratch("currentTopic").(*database.Topic)
if !conf.TestPermission("Conference.Hide", myLevel) {
ctxt.SetRC(http.StatusForbidden)
return ui.ErrorPage(ctxt, ENOPERM)
return "error", ENOPERM
}
err := topic.SetFrozen(ctxt.Ctx(), !topic.Frozen, ctxt.CurrentUser(), ctxt.RemoteIP())
if err != nil {
return ui.ErrorPage(ctxt, err)
return "error", err
}
return "redirect", fmt.Sprintf("/comm/%s/conf/%s/r/%d", ctxt.CurrentCommunity().Alias, ctxt.GetScratch("currentAlias"), topic.Number), nil
return "redirect", fmt.Sprintf("/comm/%s/conf/%s/r/%d", ctxt.CurrentCommunity().Alias, ctxt.GetScratch("currentAlias"), topic.Number)
}
/* ArchiveTopic archives or unarchives the current topic.
@@ -268,21 +263,19 @@ func FreezeTopic(ctxt ui.AmContext) (string, any, error) {
* Returns:
* Command string dictating what to be rendered.
* Data as a parameter for the command string.
* Standard Go error status.
*/
func ArchiveTopic(ctxt ui.AmContext) (string, any, error) {
func ArchiveTopic(ctxt ui.AmContext) (string, any) {
conf := ctxt.GetScratch("currentConference").(*database.Conference)
myLevel := ctxt.GetScratch("levelInConference").(uint16)
topic := ctxt.GetScratch("currentTopic").(*database.Topic)
if !conf.TestPermission("Conference.Hide", myLevel) {
ctxt.SetRC(http.StatusForbidden)
return ui.ErrorPage(ctxt, ENOPERM)
return "error", ENOPERM
}
err := topic.SetArchived(ctxt.Ctx(), !topic.Archived, ctxt.CurrentUser(), ctxt.RemoteIP())
if err != nil {
return ui.ErrorPage(ctxt, err)
return "error", err
}
return "redirect", fmt.Sprintf("/comm/%s/conf/%s/r/%d", ctxt.CurrentCommunity().Alias, ctxt.GetScratch("currentAlias"), topic.Number), nil
return "redirect", fmt.Sprintf("/comm/%s/conf/%s/r/%d", ctxt.CurrentCommunity().Alias, ctxt.GetScratch("currentAlias"), topic.Number)
}
/* StickTopic sticks or unsticks the current topic.
@@ -291,21 +284,19 @@ func ArchiveTopic(ctxt ui.AmContext) (string, any, error) {
* Returns:
* Command string dictating what to be rendered.
* Data as a parameter for the command string.
* Standard Go error status.
*/
func StickTopic(ctxt ui.AmContext) (string, any, error) {
func StickTopic(ctxt ui.AmContext) (string, any) {
conf := ctxt.GetScratch("currentConference").(*database.Conference)
myLevel := ctxt.GetScratch("levelInConference").(uint16)
topic := ctxt.GetScratch("currentTopic").(*database.Topic)
if !conf.TestPermission("Conference.Hide", myLevel) {
ctxt.SetRC(http.StatusForbidden)
return ui.ErrorPage(ctxt, ENOPERM)
return "error", ENOPERM
}
err := topic.SetSticky(ctxt.Ctx(), !topic.Sticky, ctxt.CurrentUser(), ctxt.RemoteIP())
if err != nil {
return ui.ErrorPage(ctxt, err)
return "error", err
}
return "redirect", fmt.Sprintf("/comm/%s/conf/%s/r/%d", ctxt.CurrentCommunity().Alias, ctxt.GetScratch("currentAlias"), topic.Number), nil
return "redirect", fmt.Sprintf("/comm/%s/conf/%s/r/%d", ctxt.CurrentCommunity().Alias, ctxt.GetScratch("currentAlias"), topic.Number)
}
/* DeleteTopic deletes the current topic.
@@ -314,32 +305,29 @@ func StickTopic(ctxt ui.AmContext) (string, any, error) {
* Returns:
* Command string dictating what to be rendered.
* Data as a parameter for the command string.
* Standard Go error status.
*/
func DeleteTopic(ctxt ui.AmContext) (string, any, error) {
func DeleteTopic(ctxt ui.AmContext) (string, any) {
if ctxt.CurrentUser().IsAnon {
ctxt.SetRC(http.StatusForbidden)
return ui.ErrorPage(ctxt, ENOPERM)
return "error", ENOPERM
}
conf := ctxt.GetScratch("currentConference").(*database.Conference)
myLevel := ctxt.GetScratch("levelInConference").(uint16)
topic := ctxt.GetScratch("currentTopic").(*database.Topic)
if !conf.TestPermission("Conference.Nuke", myLevel) {
ctxt.SetRC(http.StatusForbidden)
return ui.ErrorPage(ctxt, ENOPERM)
return "error", ENOPERM
}
// Load the message box, and, if we have a valid "yes," then perform the delete
mbox, err := ui.AmLoadMessageBox("deleteTopic")
if err != nil {
return ui.ErrorPage(ctxt, err)
return "error", err
}
if mbox.Validate(ctxt, "yes") {
err := topic.Delete(ctxt.Ctx(), ctxt.CurrentUser(), ctxt.RemoteIP(), ampool)
if err != nil {
return ui.ErrorPage(ctxt, err)
return "error", err
}
return "redirect", fmt.Sprintf("/comm/%s/conf/%s", ctxt.CurrentCommunity().Alias, ctxt.GetScratch("currentAlias")), nil
return "redirect", fmt.Sprintf("/comm/%s/conf/%s", ctxt.CurrentCommunity().Alias, ctxt.GetScratch("currentAlias"))
}
// Set up to display the message box.
@@ -356,35 +344,32 @@ func DeleteTopic(ctxt ui.AmContext) (string, any, error) {
* Returns:
* Command string dictating what to be rendered.
* Data as a parameter for the command string.
* Standard Go error status.
*/
func HideMessage(ctxt ui.AmContext) (string, any, error) {
func HideMessage(ctxt ui.AmContext) (string, any) {
if ctxt.CurrentUser().IsAnon {
ctxt.SetRC(http.StatusForbidden)
return ui.ErrorPage(ctxt, ENOPERM)
return "error", ENOPERM
}
conf := ctxt.GetScratch("currentConference").(*database.Conference)
myLevel := ctxt.GetScratch("levelInConference").(uint16)
topic := ctxt.GetScratch("currentTopic").(*database.Topic)
msgNum, err := strconv.Atoi(ctxt.URLParam("msg"))
if err != nil {
return ui.ErrorPage(ctxt, err)
return "error", err
}
hdrs, err := database.AmGetPostRange(ctxt.Ctx(), topic, int32(msgNum), int32(msgNum))
if err != nil {
return ui.ErrorPage(ctxt, err)
return "error", err
} else if len(hdrs) != 1 {
return ui.ErrorPage(ctxt, errors.New("internal error getting post reference"))
return "error", EPOSTREF
}
if (hdrs[0].CreatorUid != ctxt.CurrentUserId()) && !conf.TestPermission("Conference.Hide", myLevel) {
ctxt.SetRC(http.StatusForbidden)
return ui.ErrorPage(ctxt, ENOPERM)
return "error", ENOPERM
}
err = hdrs[0].SetHidden(ctxt.Ctx(), ctxt.CurrentUser(), !(hdrs[0].Hidden), ctxt.RemoteIP())
if err != nil {
return ui.ErrorPage(ctxt, err)
return "error", err
}
return "redirect", fmt.Sprintf("/comm/%s/conf/%s/r/%d?r=%d&ac=1", ctxt.CurrentCommunity().Alias, ctxt.GetScratch("currentAlias"), topic.Number, hdrs[0].Num), nil
return "redirect", fmt.Sprintf("/comm/%s/conf/%s/r/%d?r=%d&ac=1", ctxt.CurrentCommunity().Alias, ctxt.GetScratch("currentAlias"), topic.Number, hdrs[0].Num)
}
/* ScribbleMessage scribbles a topic message.
@@ -393,35 +378,32 @@ func HideMessage(ctxt ui.AmContext) (string, any, error) {
* Returns:
* Command string dictating what to be rendered.
* Data as a parameter for the command string.
* Standard Go error status.
*/
func ScribbleMessage(ctxt ui.AmContext) (string, any, error) {
func ScribbleMessage(ctxt ui.AmContext) (string, any) {
if ctxt.CurrentUser().IsAnon {
ctxt.SetRC(http.StatusForbidden)
return ui.ErrorPage(ctxt, ENOPERM)
return "error", ENOPERM
}
conf := ctxt.GetScratch("currentConference").(*database.Conference)
myLevel := ctxt.GetScratch("levelInConference").(uint16)
topic := ctxt.GetScratch("currentTopic").(*database.Topic)
msgNum, err := strconv.Atoi(ctxt.URLParam("msg"))
if err != nil {
return ui.ErrorPage(ctxt, err)
return "error", err
}
hdrs, err := database.AmGetPostRange(ctxt.Ctx(), topic, int32(msgNum), int32(msgNum))
if err != nil {
return ui.ErrorPage(ctxt, err)
return "error", err
} else if len(hdrs) != 1 {
return ui.ErrorPage(ctxt, errors.New("internal error getting post reference"))
return "error", EPOSTREF
}
if (hdrs[0].CreatorUid != ctxt.CurrentUserId()) && !conf.TestPermission("Conference.Nuke", myLevel) {
ctxt.SetRC(http.StatusForbidden)
return ui.ErrorPage(ctxt, ENOPERM)
return "error", ENOPERM
}
err = hdrs[0].Scribble(ctxt.Ctx(), ctxt.CurrentUser(), ctxt.RemoteIP())
if err != nil {
return ui.ErrorPage(ctxt, err)
return "error", err
}
return "redirect", fmt.Sprintf("/comm/%s/conf/%s/r/%d?r=%d&ac=1", ctxt.CurrentCommunity().Alias, ctxt.GetScratch("currentAlias"), topic.Number, hdrs[0].Num), nil
return "redirect", fmt.Sprintf("/comm/%s/conf/%s/r/%d?r=%d&ac=1", ctxt.CurrentCommunity().Alias, ctxt.GetScratch("currentAlias"), topic.Number, hdrs[0].Num)
}
/* NukeMessage nukes (deletes entirely) a topic message.
@@ -430,53 +412,50 @@ func ScribbleMessage(ctxt ui.AmContext) (string, any, error) {
* Returns:
* Command string dictating what to be rendered.
* Data as a parameter for the command string.
* Standard Go error status.
*/
func NukeMessage(ctxt ui.AmContext) (string, any, error) {
func NukeMessage(ctxt ui.AmContext) (string, any) {
if ctxt.CurrentUser().IsAnon {
ctxt.SetRC(http.StatusForbidden)
return ui.ErrorPage(ctxt, ENOPERM)
return "error", ENOPERM
}
conf := ctxt.GetScratch("currentConference").(*database.Conference)
myLevel := ctxt.GetScratch("levelInConference").(uint16)
topic := ctxt.GetScratch("currentTopic").(*database.Topic)
msgNum, err := strconv.Atoi(ctxt.URLParam("msg"))
if err != nil {
return ui.ErrorPage(ctxt, err)
return "error", err
}
hdrs, err := database.AmGetPostRange(ctxt.Ctx(), topic, int32(msgNum), int32(msgNum))
if err != nil {
return ui.ErrorPage(ctxt, err)
return "error", err
} else if len(hdrs) != 1 {
return ui.ErrorPage(ctxt, errors.New("internal error getting post reference"))
return "error", EPOSTREF
}
if !conf.TestPermission("Conference.Nuke", myLevel) {
ctxt.SetRC(http.StatusForbidden)
return ui.ErrorPage(ctxt, ENOPERM)
return "error", ENOPERM
}
// Load the message box, and, if we have a valid "yes," then perform the nuke!
mbox, err := ui.AmLoadMessageBox("nuke")
if err != nil {
return ui.ErrorPage(ctxt, err)
return "error", err
}
if mbox.Validate(ctxt, "yes") {
// do the nuking!
err := hdrs[0].Nuke(ctxt.Ctx(), ctxt.CurrentUser(), ctxt.RemoteIP())
if err != nil {
return ui.ErrorPage(ctxt, err)
return "error", err
}
return "redirect", fmt.Sprintf("/comm/%s/conf/%s/r/%d", ctxt.CurrentCommunity().Alias, ctxt.GetScratch("currentAlias"), topic.Number), nil
return "redirect", fmt.Sprintf("/comm/%s/conf/%s/r/%d", ctxt.CurrentCommunity().Alias, ctxt.GetScratch("currentAlias"), topic.Number)
}
// Set up to display the message box.
link, err := hdrs[0].Link(ctxt.Ctx(), "community")
if err != nil {
return ui.ErrorPage(ctxt, err)
return "error", err
}
creator, err := hdrs[0].Creator(ctxt.Ctx())
if err != nil {
return ui.ErrorPage(ctxt, err)
return "error", err
}
mbox.SetMessage(fmt.Sprintf(`You are about to nuke message <span class="font-mono font-bold text-red-600">&lt;%s&gt;</span>,
originally composed by <span class="font-bold text-red-600">&lt;%s&gt;</span>!`, link, creator.Username))
@@ -491,40 +470,37 @@ func NukeMessage(ctxt ui.AmContext) (string, any, error) {
* Returns:
* Command string dictating what to be rendered.
* Data as a parameter for the command string.
* Standard Go error status.
*/
func MoveMessageForm(ctxt ui.AmContext) (string, any, error) {
func MoveMessageForm(ctxt ui.AmContext) (string, any) {
if ctxt.CurrentUser().IsAnon {
ctxt.SetRC(http.StatusForbidden)
return ui.ErrorPage(ctxt, ENOPERM)
return "error", ENOPERM
}
conf := ctxt.GetScratch("currentConference").(*database.Conference)
myLevel := ctxt.GetScratch("levelInConference").(uint16)
topic := ctxt.GetScratch("currentTopic").(*database.Topic)
msgNum, err := strconv.Atoi(ctxt.URLParam("msg"))
if err != nil {
return ui.ErrorPage(ctxt, err)
return "error", err
}
hdrs, err := database.AmGetPostRange(ctxt.Ctx(), topic, int32(msgNum), int32(msgNum))
if err != nil {
return ui.ErrorPage(ctxt, err)
return "error", err
} else if len(hdrs) != 1 {
return ui.ErrorPage(ctxt, errors.New("internal error getting post reference"))
return "error", EPOSTREF
}
if !conf.TestPermission("Conference.Nuke", myLevel) || !conf.TestPermission("Conference.Post", myLevel) || topic.TopMessage == 0 {
ctxt.SetRC(http.StatusForbidden)
return ui.ErrorPage(ctxt, ENOPERM)
return "error", ENOPERM
}
creator, err := hdrs[0].Creator(ctxt.Ctx())
if err != nil {
return ui.ErrorPage(ctxt, err)
return "error", err
}
ctxt.VarMap().Set("creator", creator)
topiclist, err := database.AmListTopics(ctxt.Ctx(), conf.ConfId, ctxt.CurrentUserId(), database.TopicViewAll, database.TopicSortName, true)
if err != nil {
return ui.ErrorPage(ctxt, err)
return "error", err
}
for i := range topiclist {
if topiclist[i].TopicID == topic.TopicId {
@@ -540,7 +516,7 @@ func MoveMessageForm(ctxt ui.AmContext) (string, any, error) {
ctxt.VarMap().Set("formLink", formLink)
ctxt.VarMap().Set("amsterdam_pageTitle", "Move Message")
return "framed_template", "move_message.jet", nil
return "framed", "move_message.jet"
}
/* PublishMessage publishes a message to the front page.
@@ -549,30 +525,28 @@ func MoveMessageForm(ctxt ui.AmContext) (string, any, error) {
* Returns:
* Command string dictating what to be rendered.
* Data as a parameter for the command string.
* Standard Go error status.
*/
func PublishMessage(ctxt ui.AmContext) (string, any, error) {
func PublishMessage(ctxt ui.AmContext) (string, any) {
if !ctxt.TestPermission("Global.PublishFP") {
ctxt.SetRC(http.StatusForbidden)
return ui.ErrorPage(ctxt, ENOPERM)
return "error", ENOPERM
}
comm := ctxt.CurrentCommunity()
topic := ctxt.GetScratch("currentTopic").(*database.Topic)
msgNum, err := strconv.Atoi(ctxt.URLParam("msg"))
if err != nil {
return ui.ErrorPage(ctxt, err)
return "error", err
}
hdrs, err := database.AmGetPostRange(ctxt.Ctx(), topic, int32(msgNum), int32(msgNum))
if err != nil {
return ui.ErrorPage(ctxt, err)
return "error", err
} else if len(hdrs) != 1 {
return ui.ErrorPage(ctxt, errors.New("internal error getting post reference"))
return "error", EPOSTREF
}
if err = hdrs[0].Publish(ctxt.Ctx(), comm, ctxt.CurrentUser(), ctxt.RemoteIP()); err != nil {
return ui.ErrorPage(ctxt, err)
return "error", err
}
return "redirect", fmt.Sprintf("/comm/%s/conf/%s/r/%d?r=%d&ac=1", ctxt.CurrentCommunity().Alias, ctxt.GetScratch("currentAlias"), topic.Number, hdrs[0].Num), nil
return "redirect", fmt.Sprintf("/comm/%s/conf/%s/r/%d?r=%d&ac=1", ctxt.CurrentCommunity().Alias, ctxt.GetScratch("currentAlias"), topic.Number, hdrs[0].Num)
}
/* MoveMessage moves a message to a different topic.
@@ -581,12 +555,10 @@ func PublishMessage(ctxt ui.AmContext) (string, any, error) {
* Returns:
* Command string dictating what to be rendered.
* Data as a parameter for the command string.
* Standard Go error status.
*/
func MoveMessage(ctxt ui.AmContext) (string, any, error) {
func MoveMessage(ctxt ui.AmContext) (string, any) {
if ctxt.CurrentUser().IsAnon {
ctxt.SetRC(http.StatusForbidden)
return ui.ErrorPage(ctxt, ENOPERM)
return "error", ENOPERM
}
comm := ctxt.CurrentCommunity()
conf := ctxt.GetScratch("currentConference").(*database.Conference)
@@ -594,34 +566,33 @@ func MoveMessage(ctxt ui.AmContext) (string, any, error) {
topic := ctxt.GetScratch("currentTopic").(*database.Topic)
msgNum, err := strconv.Atoi(ctxt.URLParam("msg"))
if err != nil {
return ui.ErrorPage(ctxt, err)
return "error", err
}
hdrs, err := database.AmGetPostRange(ctxt.Ctx(), topic, int32(msgNum), int32(msgNum))
if err != nil {
return ui.ErrorPage(ctxt, err)
return "error", err
} else if len(hdrs) != 1 {
return ui.ErrorPage(ctxt, errors.New("internal error getting post reference"))
return "error", EPOSTREF
}
if ctxt.FormFieldIsSet("cancel") {
return "redirect", fmt.Sprintf("/comm/%s/conf/%s/r/%d?r=%d&ac=1", comm.Alias, ctxt.GetScratch("currentAlias"), topic.Number, hdrs[0].Num), nil
return "redirect", fmt.Sprintf("/comm/%s/conf/%s/r/%d?r=%d&ac=1", comm.Alias, ctxt.GetScratch("currentAlias"), topic.Number, hdrs[0].Num)
}
if !conf.TestPermission("Conference.Nuke", myLevel) || !conf.TestPermission("Conference.Post", myLevel) || topic.TopMessage == 0 {
ctxt.SetRC(http.StatusForbidden)
return ui.ErrorPage(ctxt, ENOPERM)
return "error", ENOPERM
}
targetId, err := ctxt.FormFieldInt("target")
if err != nil {
return ui.ErrorPage(ctxt, err)
return "error", err
}
target, err := database.AmGetTopic(ctxt.Ctx(), int32(targetId))
if err != nil {
return ui.ErrorPage(ctxt, err)
return "error", err
}
// Move the topic!
err = hdrs[0].MoveTo(ctxt.Ctx(), target, ctxt.CurrentUser(), ctxt.RemoteIP())
if err != nil {
return ui.ErrorPage(ctxt, err)
return "error", err
}
// Now, we need to send this post to whoever subscribed to the NEW topic. But it's tricky because we don't have
@@ -646,7 +617,7 @@ func MoveMessage(ctxt ui.AmContext) (string, any, error) {
})
}
return "redirect", fmt.Sprintf("/comm/%s/conf/%s/r/%d", ctxt.CurrentCommunity().Alias, ctxt.GetScratch("currentAlias"), topic.Number), nil
return "redirect", fmt.Sprintf("/comm/%s/conf/%s/r/%d", ctxt.CurrentCommunity().Alias, ctxt.GetScratch("currentAlias"), topic.Number)
}
/* TopicManage displays the "manage topic" page.
@@ -655,9 +626,8 @@ func MoveMessage(ctxt ui.AmContext) (string, any, error) {
* Returns:
* Command string dictating what to be rendered.
* Data as a parameter for the command string.
* Standard Go error status.
*/
func TopicManage(ctxt ui.AmContext) (string, any, error) {
func TopicManage(ctxt ui.AmContext) (string, any) {
comm := ctxt.CurrentCommunity()
topic := ctxt.GetScratch("currentTopic").(*database.Topic)
ctxt.VarMap().Set("backlink", fmt.Sprintf("/comm/%s/conf/%s/r/%d", comm.Alias, ctxt.GetScratch("currentAlias"), topic.Number))
@@ -668,26 +638,26 @@ func TopicManage(ctxt ui.AmContext) (string, any, error) {
// Get the invitation flag.
member, _, _, err := comm.Membership(ctxt.Ctx(), ctxt.CurrentUser())
if err != nil {
return ui.ErrorPage(ctxt, err)
return "error", err
}
ctxt.VarMap().Set("canInvite", member)
// Get the E-mail subscription status.
sub, err := topic.IsSubscribed(ctxt.Ctx(), ctxt.CurrentUser())
if err != nil {
return ui.ErrorPage(ctxt, err)
return "error", err
}
ctxt.VarMap().Set("subscribed", sub)
// Get the filtered users list.
bozos, err := topic.GetBozos(ctxt.Ctx(), ctxt.CurrentUser())
if err != nil {
return ui.ErrorPage(ctxt, err)
return "error", err
}
ctxt.VarMap().Set("bozos", bozos)
ctxt.VarMap().Set("amsterdam_pageTitle", "Manage Topic: "+topic.Name)
return "framed_template", "manage_topic.jet", nil
return "framed", "manage_topic.jet"
}
/* TopicSetSubscribe toggles the "subscription" flag on the current topic for the current user.
@@ -696,24 +666,22 @@ func TopicManage(ctxt ui.AmContext) (string, any, error) {
* Returns:
* Command string dictating what to be rendered.
* Data as a parameter for the command string.
* Standard Go error status.
*/
func TopicSetSubscribe(ctxt ui.AmContext) (string, any, error) {
func TopicSetSubscribe(ctxt ui.AmContext) (string, any) {
if ctxt.CurrentUser().IsAnon {
ctxt.SetRC(http.StatusForbidden)
return ui.ErrorPage(ctxt, ENOPERM)
return "error", ENOPERM
}
comm := ctxt.CurrentCommunity()
topic := ctxt.GetScratch("currentTopic").(*database.Topic)
flag, err := topic.IsSubscribed(ctxt.Ctx(), ctxt.CurrentUser())
if err != nil {
return ui.ErrorPage(ctxt, err)
return "error", err
}
err = topic.SetSubscribed(ctxt.Ctx(), ctxt.CurrentUser(), !flag)
if err != nil {
return ui.ErrorPage(ctxt, err)
return "error", err
}
return "redirect", fmt.Sprintf("/comm/%s/conf/%s/op/%d/manage", comm.Alias, ctxt.GetScratch("currentAlias"), topic.Number), nil
return "redirect", fmt.Sprintf("/comm/%s/conf/%s/op/%d/manage", comm.Alias, ctxt.GetScratch("currentAlias"), topic.Number)
}
/* TopicRemoveBozo removes filtering from a specified user in the topic.
@@ -722,18 +690,17 @@ func TopicSetSubscribe(ctxt ui.AmContext) (string, any, error) {
* Returns:
* Command string dictating what to be rendered.
* Data as a parameter for the command string.
* Standard Go error status.
*/
func TopicRemoveBozo(ctxt ui.AmContext) (string, any, error) {
func TopicRemoveBozo(ctxt ui.AmContext) (string, any) {
comm := ctxt.CurrentCommunity()
topic := ctxt.GetScratch("currentTopic").(*database.Topic)
bozoUid, err := strconv.Atoi(ctxt.URLParam("uid"))
if err != nil {
return ui.ErrorPage(ctxt, err)
return "error", err
}
err = topic.SetBozo(ctxt.Ctx(), ctxt.CurrentUser(), int32(bozoUid), false)
if err != nil {
return ui.ErrorPage(ctxt, err)
return "error", err
}
return "redirect", fmt.Sprintf("/comm/%s/conf/%s/op/%d/manage", comm.Alias, ctxt.GetScratch("currentAlias"), topic.Number), nil
return "redirect", fmt.Sprintf("/comm/%s/conf/%s/op/%d/manage", comm.Alias, ctxt.GetScratch("currentAlias"), topic.Number)
}
+32 -47
View File
@@ -13,7 +13,6 @@ package main
import (
"errors"
"fmt"
"net/http"
"strconv"
"strings"
@@ -29,20 +28,18 @@ import (
* Returns:
* Command string dictating what to be rendered.
* Data as a parameter for the command string.
* Standard Go error status.
*/
func EditConferenceForm(ctxt ui.AmContext) (string, any, error) {
func EditConferenceForm(ctxt ui.AmContext) (string, any) {
comm := ctxt.CurrentCommunity()
conf := ctxt.GetScratch("currentConference").(*database.Conference)
myLevel := ctxt.GetScratch("levelInConference").(uint16)
if !conf.TestPermission("Conference.Change", myLevel) {
ctxt.SetRC(http.StatusForbidden)
return ui.ErrorPage(ctxt, ENOPERM)
return "error", ENOPERM
}
dlg, err := ui.AmLoadDialog("edit_conference")
if err != nil {
return ui.ErrorPage(ctxt, err)
return "error", err
}
dlg.SetCommunity(comm)
dlg.SetConference(conf, ctxt.GetScratch("currentAlias").(string))
@@ -51,7 +48,7 @@ func EditConferenceForm(ctxt ui.AmContext) (string, any, error) {
if comm.TestPermission("Community.Create", ctxt.EffectiveLevel()) {
f, err := conf.HiddenInList(ctxt.Ctx(), comm)
if err != nil {
return ui.ErrorPage(ctxt, err)
return "error", err
}
dlg.Field("hide").SetChecked(f)
} else {
@@ -66,7 +63,7 @@ func EditConferenceForm(ctxt ui.AmContext) (string, any, error) {
dlg.Field("delete_lvl").SetLevel(conf.DeleteLevel)
flags, err := conf.Flags(ctxt.Ctx())
if err != nil {
return ui.ErrorPage(ctxt, err)
return "error", err
}
dlg.Field("pic_in_post").SetChecked(flags.Get(database.ConferenceFlagPicturesInPosts))
return dlg.Render(ctxt)
@@ -78,24 +75,22 @@ func EditConferenceForm(ctxt ui.AmContext) (string, any, error) {
* Returns:
* Command string dictating what to be rendered.
* Data as a parameter for the command string.
* Standard Go error status.
*/
func EditConference(ctxt ui.AmContext) (string, any, error) {
func EditConference(ctxt ui.AmContext) (string, any) {
comm := ctxt.CurrentCommunity()
conf := ctxt.GetScratch("currentConference").(*database.Conference)
myLevel := ctxt.GetScratch("levelInConference").(uint16)
if !conf.TestPermission("Conference.Change", myLevel) {
ctxt.SetRC(http.StatusForbidden)
return ui.ErrorPage(ctxt, ENOPERM)
return "error", ENOPERM
}
dlg, err := ui.AmLoadDialog("edit_conference")
if err != nil {
return ui.ErrorPage(ctxt, err)
return "error", err
}
button := dlg.WhichButton(ctxt)
if button == "cancel" {
return "redirect", fmt.Sprintf("/comm/%s/conf/%s/manage", comm.Alias, ctxt.GetScratch("currentAlias")), nil
return "redirect", fmt.Sprintf("/comm/%s/conf/%s/manage", comm.Alias, ctxt.GetScratch("currentAlias"))
} else if button != "update" {
dlg.SetCommunity(comm)
dlg.SetConference(conf, ctxt.GetScratch("currentAlias").(string))
@@ -123,7 +118,7 @@ func EditConference(ctxt ui.AmContext) (string, any, error) {
return dlg.RenderError(ctxt, err.Error())
}
return "redirect", fmt.Sprintf("/comm/%s/conf/%s/manage", comm.Alias, ctxt.GetScratch("currentAlias")), nil
return "redirect", fmt.Sprintf("/comm/%s/conf/%s/manage", comm.Alias, ctxt.GetScratch("currentAlias"))
}
/* ConferenceAliasForm displays the form for managing conference aliases.
@@ -132,15 +127,13 @@ func EditConference(ctxt ui.AmContext) (string, any, error) {
* Returns:
* Command string dictating what to be rendered.
* Data as a parameter for the command string.
* Standard Go error status.
*/
func ConferenceAliasForm(ctxt ui.AmContext) (string, any, error) {
func ConferenceAliasForm(ctxt ui.AmContext) (string, any) {
comm := ctxt.CurrentCommunity()
conf := ctxt.GetScratch("currentConference").(*database.Conference)
myLevel := ctxt.GetScratch("levelInConference").(uint16)
if !conf.TestPermission("Conference.Change", myLevel) {
ctxt.SetRC(http.StatusForbidden)
return ui.ErrorPage(ctxt, ENOPERM)
return "error", ENOPERM
}
ctxt.VarMap().Set("newAlias", "")
@@ -158,11 +151,11 @@ func ConferenceAliasForm(ctxt ui.AmContext) (string, any, error) {
aliases, err := conf.Aliases(ctxt.Ctx())
if err != nil {
return ui.ErrorPage(ctxt, err)
return "error", err
}
ctxt.VarMap().Set("aliases", aliases)
return "framed_template", "conf_aliases.jet", nil
return "framed", "conf_aliases.jet"
}
/* ConferenceAliasAdd adds a new alias to the current conference.
@@ -171,15 +164,13 @@ func ConferenceAliasForm(ctxt ui.AmContext) (string, any, error) {
* Returns:
* Command string dictating what to be rendered.
* Data as a parameter for the command string.
* Standard Go error status.
*/
func ConferenceAliasAdd(ctxt ui.AmContext) (string, any, error) {
func ConferenceAliasAdd(ctxt ui.AmContext) (string, any) {
comm := ctxt.CurrentCommunity()
conf := ctxt.GetScratch("currentConference").(*database.Conference)
myLevel := ctxt.GetScratch("levelInConference").(uint16)
if !conf.TestPermission("Conference.Change", myLevel) {
ctxt.SetRC(http.StatusForbidden)
return ui.ErrorPage(ctxt, ENOPERM)
return "error", ENOPERM
}
ctxt.VarMap().Set("confName", conf.Name)
@@ -207,12 +198,12 @@ func ConferenceAliasAdd(ctxt ui.AmContext) (string, any, error) {
aliases, err := conf.Aliases(ctxt.Ctx())
if err != nil {
return ui.ErrorPage(ctxt, err)
return "error", err
}
ctxt.VarMap().Set("newAlias", "")
ctxt.VarMap().Set("aliases", aliases)
return "framed_template", "conf_aliases.jet", nil
return "framed", "conf_aliases.jet"
}
// CMData is the result data passed to the conference members page.
@@ -242,15 +233,13 @@ var operMap = map[string]int{
* Returns:
* Command string dictating what to be rendered.
* Data as a parameter for the command string.
* Standard Go error status.
*/
func ConferenceMembers(ctxt ui.AmContext) (string, any, error) {
func ConferenceMembers(ctxt ui.AmContext) (string, any) {
comm := ctxt.CurrentCommunity()
conf := ctxt.GetScratch("currentConference").(*database.Conference)
myLevel := ctxt.GetScratch("levelInConference").(uint16)
if !conf.TestPermission("Conference.Change", myLevel) {
ctxt.SetRC(http.StatusForbidden)
return ui.ErrorPage(ctxt, ENOPERM)
return "error", ENOPERM
}
// Set the first batch of page variables.
@@ -324,7 +313,7 @@ func ConferenceMembers(ctxt ui.AmContext) (string, any, error) {
}
}
if err != nil {
return ui.ErrorPage(ctxt, err)
return "error", err
}
}
}
@@ -334,7 +323,7 @@ func ConferenceMembers(ctxt ui.AmContext) (string, any, error) {
// Get the member list for the conference.
members, err := conf.Members(ctxt.Ctx())
if err != nil {
return ui.ErrorPage(ctxt, err)
return "error", err
}
// Generate the result list.
@@ -357,7 +346,7 @@ func ConferenceMembers(ctxt ui.AmContext) (string, any, error) {
case "comm":
ulist, t, err := database.AmSearchCommunityMembers(ctxt.Ctx(), comm, fieldMap[field], operMap[oper], term, offset, int(maxPage))
if err != nil {
return ui.ErrorPage(ctxt, err)
return "error", err
}
total = t
mr = make([]CMData, len(ulist))
@@ -385,7 +374,7 @@ func ConferenceMembers(ctxt ui.AmContext) (string, any, error) {
if (offset + len(mr)) < total {
ctxt.VarMap().Set("showNext", true)
}
return "framed_template", "conf_members.jet", nil
return "framed", "conf_members.jet"
}
/* CreateConferenceForm displays the dialog for creating a new conference.
@@ -394,18 +383,16 @@ func ConferenceMembers(ctxt ui.AmContext) (string, any, error) {
* Returns:
* Command string dictating what to be rendered.
* Data as a parameter for the command string.
* Standard Go error status.
*/
func CreateConferenceForm(ctxt ui.AmContext) (string, any, error) {
func CreateConferenceForm(ctxt ui.AmContext) (string, any) {
comm := ctxt.CurrentCommunity()
if !comm.TestPermission("Community.Create", ctxt.EffectiveLevel()) {
ctxt.SetRC(http.StatusForbidden)
return ui.ErrorPage(ctxt, ENOPERM)
return "error", ENOPERM
}
dlg, err := ui.AmLoadDialog("create_conference")
if err != nil {
return ui.ErrorPage(ctxt, err)
return "error", err
}
dlg.SetCommunity(comm)
return dlg.Render(ctxt)
@@ -417,22 +404,20 @@ func CreateConferenceForm(ctxt ui.AmContext) (string, any, error) {
* Returns:
* Command string dictating what to be rendered.
* Data as a parameter for the command string.
* Standard Go error status.
*/
func CreateConference(ctxt ui.AmContext) (string, any, error) {
func CreateConference(ctxt ui.AmContext) (string, any) {
comm := ctxt.CurrentCommunity()
if !comm.TestPermission("Community.Create", ctxt.EffectiveLevel()) {
ctxt.SetRC(http.StatusForbidden)
return ui.ErrorPage(ctxt, ENOPERM)
return "error", ENOPERM
}
dlg, err := ui.AmLoadDialog("create_conference")
if err != nil {
return ui.ErrorPage(ctxt, err)
return "error", err
}
button := dlg.WhichButton(ctxt)
if button == "cancel" {
return "redirect", fmt.Sprintf("/comm/%s/conf", comm.Alias), nil
return "redirect", fmt.Sprintf("/comm/%s/conf", comm.Alias)
} else if button != "create" {
dlg.SetCommunity(comm)
return dlg.RenderError(ctxt, "invalid button pressed")
@@ -446,5 +431,5 @@ func CreateConference(ctxt ui.AmContext) (string, any, error) {
return dlg.RenderError(ctxt, err.Error())
}
log.Infof("Created conference '%s'", conf.Name)
return "redirect", fmt.Sprintf("/comm/%s/conf/%s", comm.Alias, alias), nil
return "redirect", fmt.Sprintf("/comm/%s/conf/%s", comm.Alias, alias)
}
+6 -4
View File
@@ -10,7 +10,6 @@
package main
import (
"errors"
"net/http"
"git.erbosoft.com/amy/amsterdam/ui"
@@ -19,7 +18,10 @@ import (
)
// ENOPERM is the standard "not permitted" error message.
var ENOPERM error = errors.New("you are not permitted to perform this operation")
var ENOPERM *echo.HTTPError = echo.NewHTTPError(http.StatusForbidden, "you are not permitted to perform this operation")
// ENOACCESS is the standard "no access" error message.
var ENOACCESS *echo.HTTPError = echo.NewHTTPError(http.StatusForbidden, "you are not permitted to access this page")
/* NotImplPage is used for all TODO links, to show that something hasn't yet been implemented.
* Parameters:
@@ -29,11 +31,11 @@ var ENOPERM error = errors.New("you are not permitted to perform this operation"
* Data as a parameter for the command string.
* Standard Go error status.
*/
func NotImplPage(ctxt ui.AmContext) (string, any, error) {
func NotImplPage(ctxt ui.AmContext) (string, any) {
ctxt.SetLeftMenu("top")
ctxt.VarMap().Set("amsterdam_pageTitle", "Function Not Implemented")
ctxt.VarMap().Set("path", ctxt.URLPath())
return "framed_template", "notimpl.jet", nil
return "framed", "notimpl.jet"
}
/* AmErrorHandler handles all the mundane HTTP errors generated by the Echo engine.
+22 -30
View File
@@ -91,9 +91,8 @@ func loadCategoryInformation(ctxt ui.AmContext, offset int) error {
* Returns:
* Command string dictating what to be rendered.
* Data as a parameter for the command string.
* Standard Go error status.
*/
func FindPage(ctxt ui.AmContext) (string, any, error) {
func FindPage(ctxt ui.AmContext) (string, any) {
mode := ""
p := ctxt.Parameter("mode")
if p != "" {
@@ -128,7 +127,7 @@ func FindPage(ctxt ui.AmContext) (string, any, error) {
ctxt.VarMap().Set("term", "")
err := loadCategoryInformation(ctxt, ofs)
if err != nil {
return ui.ErrorPage(ctxt, err)
return "error", err
}
case "USR":
ctxt.VarMap().Set("field", "name")
@@ -146,7 +145,7 @@ func FindPage(ctxt ui.AmContext) (string, any, error) {
ctxt.VarMap().Set("amsterdam_pageTitle", "Find")
ctxt.SetLeftMenu("top")
return "framed_template", "find.jet", nil
return "framed", "find.jet"
}
/* Find performs the "find" operation.
@@ -155,9 +154,8 @@ func FindPage(ctxt ui.AmContext) (string, any, error) {
* Returns:
* Command string dictating what to be rendered.
* Data as a parameter for the command string.
* Standard Go error status.
*/
func Find(ctxt ui.AmContext) (string, any, error) {
func Find(ctxt ui.AmContext) (string, any) {
if !ctxt.GlobalFlags().Get(database.GlobalFlagNoCategories) {
ctxt.VarMap().Set("catIsPresent", true)
}
@@ -193,7 +191,7 @@ func Find(ctxt ui.AmContext) (string, any, error) {
iField = database.SearchCommFieldSynopsis
default:
ctxt.VarMap().Set("errorMessage", "invalid parameter to find")
return "framed_template", "find.jet", nil
return "framed", "find.jet"
}
switch oper {
case "st":
@@ -204,7 +202,7 @@ func Find(ctxt ui.AmContext) (string, any, error) {
iOper = database.SearchCommOperRegex
default:
ctxt.VarMap().Set("errorMessage", "invalid parameter to find")
return "framed_template", "find.jet", nil
return "framed", "find.jet"
}
var clist []*database.Community
clist, total, err = database.AmSearchCommunities(ctxt.Ctx(), iField, iOper, term, ofs*listMax, listMax,
@@ -230,7 +228,7 @@ func Find(ctxt ui.AmContext) (string, any, error) {
iField = database.SearchUserFieldLastName
default:
ctxt.VarMap().Set("errorMessage", "invalid parameter to find")
return "framed_template", "find.jet", nil
return "framed", "find.jet"
}
switch oper {
case "st":
@@ -241,7 +239,7 @@ func Find(ctxt ui.AmContext) (string, any, error) {
iOper = database.SearchUserOperRegex
default:
ctxt.VarMap().Set("errorMessage", "invalid parameter to find")
return "framed_template", "find.jet", nil
return "framed", "find.jet"
}
var ulist []*database.User
ulist, total, err = database.AmSearchUsers(ctxt.Ctx(), iField, iOper, term, ofs*listMax, listMax)
@@ -265,7 +263,7 @@ func Find(ctxt ui.AmContext) (string, any, error) {
iOper = database.SearchCatOperRegex
default:
ctxt.VarMap().Set("errorMessage", "invalid parameter to find")
return "framed_template", "find.jet", nil
return "framed", "find.jet"
}
var catlist []*database.Category
catlist, total, err = database.AmSearchCategories(ctxt.Ctx(), iOper, term, ofs*listMax, listMax,
@@ -288,7 +286,7 @@ func Find(ctxt ui.AmContext) (string, any, error) {
}
if err != nil {
ctxt.VarMap().Set("errorMessage", err.Error())
return "framed_template", "find.jet", nil
return "framed", "find.jet"
}
if numResults == 0 {
ctxt.VarMap().Set("resultHeader", "Search Results: (None)")
@@ -302,11 +300,11 @@ func Find(ctxt ui.AmContext) (string, any, error) {
ctxt.VarMap().Set("resultShowNext", true)
}
}
return "framed_template", "find.jet", nil
return "framed", "find.jet"
}
// commonFindGetBackend is the common "back end" function for Find Posts in Community/Conference/Topic.
func commonFindGetBackend(ctxt ui.AmContext) (string, any, error) {
func commonFindGetBackend(ctxt ui.AmContext) (string, any) {
ofs := 0
p := ctxt.Parameter("ofs")
if p != "" {
@@ -318,7 +316,7 @@ func commonFindGetBackend(ctxt ui.AmContext) (string, any, error) {
ctxt.VarMap().Set("ofs", ofs)
ctxt.VarMap().Set("term", "")
ctxt.VarMap().Set("amsterdam_pageTitle", "Find Posts")
return "framed_template", "find_posts.jet", nil
return "framed", "find_posts.jet"
}
/* FindPostsPageCommunity renders the page for finding posts in a community.
@@ -327,9 +325,8 @@ func commonFindGetBackend(ctxt ui.AmContext) (string, any, error) {
* Returns:
* Command string dictating what to be rendered.
* Data as a parameter for the command string.
* Standard Go error status.
*/
func FindPostsPageCommunity(ctxt ui.AmContext) (string, any, error) {
func FindPostsPageCommunity(ctxt ui.AmContext) (string, any) {
comm := ctxt.CurrentCommunity()
ctxt.VarMap().Set("scope", "community")
ctxt.VarMap().Set("entityName", comm.Name)
@@ -344,9 +341,8 @@ func FindPostsPageCommunity(ctxt ui.AmContext) (string, any, error) {
* Returns:
* Command string dictating what to be rendered.
* Data as a parameter for the command string.
* Standard Go error status.
*/
func FindPostsPageConference(ctxt ui.AmContext) (string, any, error) {
func FindPostsPageConference(ctxt ui.AmContext) (string, any) {
comm := ctxt.CurrentCommunity()
conf := ctxt.GetScratch("currentConference").(*database.Conference)
ctxt.VarMap().Set("scope", "conference")
@@ -362,9 +358,8 @@ func FindPostsPageConference(ctxt ui.AmContext) (string, any, error) {
* Returns:
* Command string dictating what to be rendered.
* Data as a parameter for the command string.
* Standard Go error status.
*/
func FindPostsPageTopic(ctxt ui.AmContext) (string, any, error) {
func FindPostsPageTopic(ctxt ui.AmContext) (string, any) {
comm := ctxt.CurrentCommunity()
topic := ctxt.GetScratch("currentTopic").(*database.Topic)
ctxt.VarMap().Set("scope", "topic")
@@ -375,7 +370,7 @@ func FindPostsPageTopic(ctxt ui.AmContext) (string, any, error) {
}
// commonFindPostBackend is the common "back end" function for Find Posts in Community/Conference/Topic.
func commonFindPostBackend(ctxt ui.AmContext, comm *database.Community, conf *database.Conference, topic *database.Topic) (string, any, error) {
func commonFindPostBackend(ctxt ui.AmContext, comm *database.Community, conf *database.Conference, topic *database.Topic) (string, any) {
term := ctxt.FormField("term")
ctxt.VarMap().Set("term", term)
ctxt.VarMap().Set("amsterdam_pageTitle", "Find Posts")
@@ -396,7 +391,7 @@ func commonFindPostBackend(ctxt ui.AmContext, comm *database.Community, conf *da
ctxt.VarMap().Set("resultList", postlist)
} else {
ctxt.VarMap().Set("errorMessage", err.Error())
return "framed_template", "find_posts.jet", nil
return "framed", "find_posts.jet"
}
if numResults == 0 {
ctxt.VarMap().Set("resultHeader", "Search Results: (None)")
@@ -410,7 +405,7 @@ func commonFindPostBackend(ctxt ui.AmContext, comm *database.Community, conf *da
ctxt.VarMap().Set("resultShowNext", true)
}
}
return "framed_template", "find_posts.jet", nil
return "framed", "find_posts.jet"
}
/* FindPostsCommunity finds posts in a community.
@@ -419,9 +414,8 @@ func commonFindPostBackend(ctxt ui.AmContext, comm *database.Community, conf *da
* Returns:
* Command string dictating what to be rendered.
* Data as a parameter for the command string.
* Standard Go error status.
*/
func FindPostsCommunity(ctxt ui.AmContext) (string, any, error) {
func FindPostsCommunity(ctxt ui.AmContext) (string, any) {
comm := ctxt.CurrentCommunity()
ctxt.VarMap().Set("scope", "community")
ctxt.VarMap().Set("entityName", comm.Name)
@@ -436,9 +430,8 @@ func FindPostsCommunity(ctxt ui.AmContext) (string, any, error) {
* Returns:
* Command string dictating what to be rendered.
* Data as a parameter for the command string.
* Standard Go error status.
*/
func FindPostsConference(ctxt ui.AmContext) (string, any, error) {
func FindPostsConference(ctxt ui.AmContext) (string, any) {
comm := ctxt.CurrentCommunity()
conf := ctxt.GetScratch("currentConference").(*database.Conference)
ctxt.VarMap().Set("scope", "conference")
@@ -454,9 +447,8 @@ func FindPostsConference(ctxt ui.AmContext) (string, any, error) {
* Returns:
* Command string dictating what to be rendered.
* Data as a parameter for the command string.
* Standard Go error status.
*/
func FindPostsTopic(ctxt ui.AmContext) (string, any, error) {
func FindPostsTopic(ctxt ui.AmContext) (string, any) {
comm := ctxt.CurrentCommunity()
conf := ctxt.GetScratch("currentConference").(*database.Conference)
topic := ctxt.GetScratch("currentTopic").(*database.Topic)
+19 -27
View File
@@ -12,7 +12,6 @@ package main
import (
"errors"
"fmt"
"net/http"
"net/mail"
"git.erbosoft.com/amy/amsterdam/database"
@@ -26,12 +25,10 @@ import (
* Returns:
* Command string dictating what to be rendered.
* Data as a parameter for the command string.
* Standard Go error status.
*/
func InviteToCommunity(ctxt ui.AmContext) (string, any, error) {
func InviteToCommunity(ctxt ui.AmContext) (string, any) {
if ctxt.CurrentUser().IsAnon {
ctxt.SetRC(http.StatusForbidden)
return ui.ErrorPage(ctxt, ENOPERM)
return "error", ENOPERM
}
comm := ctxt.CurrentCommunity()
@@ -40,7 +37,7 @@ func InviteToCommunity(ctxt ui.AmContext) (string, any, error) {
ctxt.VarMap().Set("subtitle", comm.Name)
ctxt.VarMap().Set("backlink", fmt.Sprintf("/comm/%s/profile", comm.Alias))
ctxt.VarMap().Set("cid", fmt.Sprintf("%d", comm.Id))
return "framed_template", "invite.jet", nil
return "framed", "invite.jet"
}
/* InviteToConference displays the conference invitation form.
@@ -49,12 +46,10 @@ func InviteToCommunity(ctxt ui.AmContext) (string, any, error) {
* Returns:
* Command string dictating what to be rendered.
* Data as a parameter for the command string.
* Standard Go error status.
*/
func InviteToConference(ctxt ui.AmContext) (string, any, error) {
func InviteToConference(ctxt ui.AmContext) (string, any) {
if ctxt.CurrentUser().IsAnon {
ctxt.SetRC(http.StatusForbidden)
return ui.ErrorPage(ctxt, ENOPERM)
return "error", ENOPERM
}
comm := ctxt.CurrentCommunity()
conf := ctxt.GetScratch("currentConference").(*database.Conference)
@@ -65,7 +60,7 @@ func InviteToConference(ctxt ui.AmContext) (string, any, error) {
ctxt.VarMap().Set("backlink", fmt.Sprintf("/comm/%s/conf/%s/manage", comm.Alias, ctxt.GetScratch("currentAlias")))
ctxt.VarMap().Set("cid", fmt.Sprintf("%d", comm.Id))
ctxt.VarMap().Set("confid", fmt.Sprintf("%d", conf.ConfId))
return "framed_template", "invite.jet", nil
return "framed", "invite.jet"
}
/* InviteToTopic displays the topic invitation form.
@@ -74,12 +69,10 @@ func InviteToConference(ctxt ui.AmContext) (string, any, error) {
* Returns:
* Command string dictating what to be rendered.
* Data as a parameter for the command string.
* Standard Go error status.
*/
func InviteToTopic(ctxt ui.AmContext) (string, any, error) {
func InviteToTopic(ctxt ui.AmContext) (string, any) {
if ctxt.CurrentUser().IsAnon {
ctxt.SetRC(http.StatusForbidden)
return ui.ErrorPage(ctxt, ENOPERM)
return "error", ENOPERM
}
comm := ctxt.CurrentCommunity()
conf := ctxt.GetScratch("currentConference").(*database.Conference)
@@ -92,7 +85,7 @@ func InviteToTopic(ctxt ui.AmContext) (string, any, error) {
ctxt.VarMap().Set("cid", fmt.Sprintf("%d", comm.Id))
ctxt.VarMap().Set("confid", fmt.Sprintf("%d", conf.ConfId))
ctxt.VarMap().Set("topicid", fmt.Sprintf("%d", topic.TopicId))
return "framed_template", "invite.jet", nil
return "framed", "invite.jet"
}
/* InviteSend is the back end that handles sending invitations.
@@ -101,14 +94,13 @@ func InviteToTopic(ctxt ui.AmContext) (string, any, error) {
* Returns:
* Command string dictating what to be rendered.
* Data as a parameter for the command string.
* Standard Go error status.
*/
func InviteSend(ctxt ui.AmContext) (string, any, error) {
func InviteSend(ctxt ui.AmContext) (string, any) {
backlink := ctxt.FormField("backlink")
if ctxt.FormFieldIsSet("cancel") {
return "redirect", backlink, nil
return "redirect", backlink
} else if !ctxt.FormFieldIsSet("send") {
return ui.ErrorPage(ctxt, errors.New("invalid command"))
return "error", "invalid command"
}
var comm *database.Community
if ctxt.FormFieldIsSet("cid") {
@@ -117,10 +109,10 @@ func InviteSend(ctxt ui.AmContext) (string, any, error) {
comm, err = database.AmGetCommunity(ctxt.Ctx(), int32(id))
}
if err != nil {
return ui.ErrorPage(ctxt, err)
return "error", err
}
} else {
return ui.ErrorPage(ctxt, errors.New("no parameters specified"))
return "error", "no parameters specified"
}
mode := "community"
var conf *database.Conference = nil
@@ -138,7 +130,7 @@ func InviteSend(ctxt ui.AmContext) (string, any, error) {
}
}
if err != nil {
return ui.ErrorPage(ctxt, err)
return "errors", err
}
if ctxt.FormFieldIsSet("topicid") {
id, err := ctxt.FormFieldInt("topicid")
@@ -149,7 +141,7 @@ func InviteSend(ctxt ui.AmContext) (string, any, error) {
}
}
if err != nil {
return ui.ErrorPage(ctxt, err)
return "errors", err
}
mode = "topic"
} else {
@@ -159,12 +151,12 @@ func InviteSend(ctxt ui.AmContext) (string, any, error) {
addr := ctxt.FormField("addr")
_, err := mail.ParseAddress(addr)
if err != nil {
return ui.ErrorPage(ctxt, err)
return "errors", err
}
ci, err := database.AmGetContactInfoForUser(ctxt.Ctx(), ctxt.CurrentUserId())
if err != nil {
return ui.ErrorPage(ctxt, err)
return "errors", err
}
mailMessage := email.AmNewEmailMessage(ctxt.CurrentUserId(), ctxt.RemoteIP())
@@ -183,5 +175,5 @@ func InviteSend(ctxt ui.AmContext) (string, any, error) {
mailMessage.AddVariable("username", ctxt.CurrentUser().Username)
mailMessage.Send()
return "redirect", backlink, nil
return "redirect", backlink
}
+38 -48
View File
@@ -11,7 +11,6 @@ package main
import (
"errors"
"fmt"
"net/url"
"time"
@@ -28,9 +27,8 @@ import (
* Returns:
* Command string dictating what to be rendered.
* Data as a parameter for the command string.
* Standard Go error status.
*/
func LoginForm(ctxt ui.AmContext) (string, any, error) {
func LoginForm(ctxt ui.AmContext) (string, any) {
// Get target URI.
target := ctxt.Parameter("tgt")
if target == "" {
@@ -39,7 +37,7 @@ func LoginForm(ctxt ui.AmContext) (string, any, error) {
// If user is already logged in, this is a no-op.
if !ctxt.CurrentUser().IsAnon {
return "redirect", target, nil
return "redirect", target
}
dlg, err := ui.AmLoadDialog("login")
@@ -47,7 +45,7 @@ func LoginForm(ctxt ui.AmContext) (string, any, error) {
dlg.Field("tgt").Value = target
return dlg.Render(ctxt)
}
return ui.ErrorPage(ctxt, err)
return "error", err
}
/* Login handles logging in to Amsterdam.
@@ -56,9 +54,8 @@ func LoginForm(ctxt ui.AmContext) (string, any, error) {
* Returns:
* Command string dictating what to be rendered.
* Data as a parameter for the command string.
* Standard Go error status.
*/
func Login(ctxt ui.AmContext) (string, any, error) {
func Login(ctxt ui.AmContext) (string, any) {
dlg, err := ui.AmLoadDialog("login")
if err == nil {
dlg.LoadFromForm(ctxt)
@@ -68,12 +65,12 @@ func Login(ctxt ui.AmContext) (string, any, error) {
}
// If user is already logged in, this is a no-op.
if !ctxt.CurrentUser().IsAnon {
return "redirect", target, nil
return "redirect", target
}
action := dlg.WhichButton(ctxt)
if action == "cancel" { // Cancel button pressed
return "redirect", target, nil
return "redirect", target
}
username := dlg.Field("user").Value // since the dialog won't check this for us
if len(username) == 0 {
@@ -125,14 +122,14 @@ func Login(ctxt ui.AmContext) (string, any, error) {
}
}
if user.VerifyEMail {
return "redirect", target, nil
return "redirect", target
} else {
return "redirect", "/verify?tgt=" + url.QueryEscape(target), nil
return "redirect", "/verify?tgt=" + url.QueryEscape(target)
}
}
return dlg.RenderError(ctxt, "No known button click on POST to login function.")
}
return ui.ErrorPage(ctxt, err)
return "error", err
}
/* Logout handles logging out from Amsterdam.
@@ -141,9 +138,8 @@ func Login(ctxt ui.AmContext) (string, any, error) {
* Returns:
* Command string dictating what to be rendered.
* Data as a parameter for the command string.
* Standard Go error status.
*/
func Logout(ctxt ui.AmContext) (string, any, error) {
func Logout(ctxt ui.AmContext) (string, any) {
// Get target URI.
target := ctxt.Parameter("tgt")
if target == "" {
@@ -154,7 +150,7 @@ func Logout(ctxt ui.AmContext) (string, any, error) {
ctxt.ClearLoginCookie()
ctxt.ClearSession()
}
return "redirect", target, nil
return "redirect", target
}
/* VerifyEmailForm renders the E-mail address verification form.
@@ -163,9 +159,8 @@ func Logout(ctxt ui.AmContext) (string, any, error) {
* Returns:
* Command string dictating what to be rendered.
* Data as a parameter for the command string.
* Standard Go error status.
*/
func VerifyEmailForm(ctxt ui.AmContext) (string, any, error) {
func VerifyEmailForm(ctxt ui.AmContext) (string, any) {
// Get target URI.
target := ctxt.Parameter("tgt")
if target == "" {
@@ -175,12 +170,12 @@ func VerifyEmailForm(ctxt ui.AmContext) (string, any, error) {
// If user is not logged in, this is an error.
user := ctxt.CurrentUser()
if user.IsAnon {
return ui.ErrorPage(ctxt, errors.New("you must log in before you can verify your account's E-mail address"))
return "error", "you must log in before you can verify your account's E-mail address"
}
// If user is already verified, this is a no-op.
if user.VerifyEMail {
return "redirect", target, nil
return "redirect", target
}
dlg, err := ui.AmLoadDialog("verify_email")
@@ -188,7 +183,7 @@ func VerifyEmailForm(ctxt ui.AmContext) (string, any, error) {
dlg.Field("tgt").Value = target
return dlg.Render(ctxt)
}
return ui.ErrorPage(ctxt, err)
return "error", err
}
// sendEmailConfirmationEmail sends the "E-mail confirmation number" E-mail message.
@@ -212,13 +207,12 @@ func sendEmailConfirmationEmail(user *database.User, ci *database.ContactInfo, r
* Returns:
* Command string dictating what to be rendered.
* Data as a parameter for the command string.
* Standard Go error status.
*/
func VerifyEMail(ctxt ui.AmContext) (string, any, error) {
func VerifyEMail(ctxt ui.AmContext) (string, any) {
// If user is not logged in, this is an error.
user := ctxt.CurrentUser()
if user.IsAnon {
return ui.ErrorPage(ctxt, errors.New("you must log in before you can verify your account's E-mail address"))
return "error", "you must log in before you can verify your account's E-mail address"
}
dlg, err := ui.AmLoadDialog("verify_email")
@@ -231,12 +225,12 @@ func VerifyEMail(ctxt ui.AmContext) (string, any, error) {
// If user is already verified, this is a no-op.
if user.VerifyEMail {
return "redirect", target, nil
return "redirect", target
}
action := dlg.WhichButton(ctxt)
if action == "cancel" { // Cancel button pressed
return "redirect", target, nil
return "redirect", target
}
if action == "sendagain" {
var ci *database.ContactInfo
@@ -259,14 +253,14 @@ func VerifyEMail(ctxt ui.AmContext) (string, any, error) {
cn, _ := dlg.Field("num").ValueInt()
err = user.ConfirmEMailAddress(ctxt.Ctx(), int32(cn), ctxt.RemoteIP())
if err == nil {
return "redirect", target, nil
return "redirect", target
}
}
return dlg.RenderError(ctxt, err.Error())
}
return dlg.RenderError(ctxt, "No known button click on POST to verify function.")
}
return ui.ErrorPage(ctxt, err)
return "error", err
}
/* NewAccountUserAgreement renders the Amsterdam user agreement for new accounts.
@@ -275,9 +269,8 @@ func VerifyEMail(ctxt ui.AmContext) (string, any, error) {
* Returns:
* Command string dictating what to be rendered.
* Data as a parameter for the command string.
* Standard Go error status.
*/
func NewAccountUserAgreement(ctxt ui.AmContext) (string, any, error) {
func NewAccountUserAgreement(ctxt ui.AmContext) (string, any) {
// Get target URI.
target := ctxt.Parameter("tgt")
if target == "" {
@@ -286,14 +279,14 @@ func NewAccountUserAgreement(ctxt ui.AmContext) (string, any, error) {
// If user is already logged in, this is an error.
if !ctxt.CurrentUser().IsAnon {
return ui.ErrorPage(ctxt, errors.New("you cannot create a new account while logged in on an existing one. You must log out first"))
return "error", "you cannot create a new account while logged in on an existing one. You must log out first"
}
ctxt.SetLeftMenu("top")
ctxt.VarMap().Set("target", target)
ctxt.VarMap().Set("amsterdam_pageTitle", "New Account User Agreement")
ctxt.VarMap().Set("amsterdam_suppressLogin", true)
return "framed_template", "agreement.jet", nil
return "framed", "agreement.jet"
}
/* NewAccountUserAgreement renders the Amsterdam account creation form.
@@ -302,9 +295,8 @@ func NewAccountUserAgreement(ctxt ui.AmContext) (string, any, error) {
* Returns:
* Command string dictating what to be rendered.
* Data as a parameter for the command string.
* Standard Go error status.
*/
func NewAccountForm(ctxt ui.AmContext) (string, any, error) {
func NewAccountForm(ctxt ui.AmContext) (string, any) {
// Get target URI.
target := ctxt.Parameter("tgt")
if target == "" {
@@ -313,7 +305,7 @@ func NewAccountForm(ctxt ui.AmContext) (string, any, error) {
// If user is already logged in, this is an error.
if !ctxt.CurrentUser().IsAnon {
return ui.ErrorPage(ctxt, fmt.Errorf("you cannot create a new account while logged in on an existing one. You must log out first"))
return "error", "you cannot create a new account while logged in on an existing one. You must log out first"
}
dlg, err := ui.AmLoadDialog("newaccount")
@@ -322,7 +314,7 @@ func NewAccountForm(ctxt ui.AmContext) (string, any, error) {
dlg.Field("country").Value = "XX"
return dlg.Render(ctxt)
}
return ui.ErrorPage(ctxt, err)
return "error", err
}
/* NewAccount handles creating a new Amsterdam account.
@@ -331,12 +323,11 @@ func NewAccountForm(ctxt ui.AmContext) (string, any, error) {
* Returns:
* Command string dictating what to be rendered.
* Data as a parameter for the command string.
* Standard Go error status.
*/
func NewAccount(ctxt ui.AmContext) (string, any, error) {
func NewAccount(ctxt ui.AmContext) (string, any) {
// If user is already logged in, this is an error.
if !ctxt.CurrentUser().IsAnon {
return ui.ErrorPage(ctxt, fmt.Errorf("you cannot create a new account while logged in on an existing one. You must log out first"))
return "error", "you cannot create a new account while logged in on an existing one. You must log out first"
}
dlg, err := ui.AmLoadDialog("newaccount")
@@ -349,7 +340,7 @@ func NewAccount(ctxt ui.AmContext) (string, any, error) {
action := dlg.WhichButton(ctxt)
if action == "cancel" { // Cancel button pressed
return "redirect", target, nil
return "redirect", target
}
if action == "create" {
err = dlg.Validate()
@@ -394,7 +385,7 @@ func NewAccount(ctxt ui.AmContext) (string, any, error) {
if err == nil {
// user is now logged in! redirect to E-mail verification
ctxt.ReplaceUser(user)
return "redirect", "/verify?tgt=" + url.QueryEscape(target), nil
return "redirect", "/verify?tgt=" + url.QueryEscape(target)
}
}
}
@@ -403,7 +394,7 @@ func NewAccount(ctxt ui.AmContext) (string, any, error) {
}
return dlg.RenderError(ctxt, "No known button click on POST to new account.")
}
return ui.ErrorPage(ctxt, err)
return "error", err
}
/* PasswordRecovery handles a click on a "password recovery" link to fix the user's password.
@@ -412,9 +403,8 @@ func NewAccount(ctxt ui.AmContext) (string, any, error) {
* Returns:
* Command string dictating what to be rendered.
* Data as a parameter for the command string.
* Standard Go error status.
*/
func PasswordRecovery(ctxt ui.AmContext) (string, any, error) {
func PasswordRecovery(ctxt ui.AmContext) (string, any) {
var emailaddy string
uid, err := ctxt.URLParamInt("uid")
if err == nil {
@@ -422,13 +412,13 @@ func PasswordRecovery(ctxt ui.AmContext) (string, any, error) {
if err == nil {
pchange := database.AmGetPasswordChangeRequest(int32(uid))
if pchange == nil {
return ui.ErrorPage(ctxt, errors.New("password change request not found"))
return "error", "password change request not found"
}
if auth != int(pchange.Authentication) {
return ui.ErrorPage(ctxt, errors.New("invalid password change request"))
return "error", "invalid password change request"
}
if time.Now().Compare(pchange.Expires) > 0 {
return ui.ErrorPage(ctxt, errors.New("password change request has expired"))
return "error", "password change request has expired"
}
emailaddy = pchange.Email
}
@@ -449,9 +439,9 @@ func PasswordRecovery(ctxt ui.AmContext) (string, any, error) {
msg.Send()
ctxt.SetLeftMenu("top")
ctxt.VarMap().Set("amsterdam_pageTitle", "Your Password Has Been Changed")
return "framed_template", "password_changed.jet", nil
return "framed_template", "password_changed.jet"
}
}
}
return ui.ErrorPage(ctxt, err)
return "error", err
}
+3 -8
View File
@@ -11,9 +11,6 @@
package main
import (
"errors"
"net/http"
"git.erbosoft.com/amy/amsterdam/database"
"git.erbosoft.com/amy/amsterdam/ui"
)
@@ -24,17 +21,15 @@ import (
* Returns:
* Command string dictating what to be rendered.
* Data as a parameter for the command string.
* Standard Go error status.
*/
func SysAdminMenu(ctxt ui.AmContext) (string, any, error) {
func SysAdminMenu(ctxt ui.AmContext) (string, any) {
u := ctxt.CurrentUser()
if !database.AmTestPermission("Global.SysAdminAccess", u.BaseLevel) {
ctxt.SetRC(http.StatusForbidden)
return ui.ErrorPage(ctxt, errors.New("you are not authorized access to this page"))
return "error", ENOACCESS
}
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
return "framed", "menu.jet"
}
+14 -18
View File
@@ -17,6 +17,7 @@ import (
"git.erbosoft.com/amy/amsterdam/database"
"git.erbosoft.com/amy/amsterdam/ui"
"github.com/CloudyKit/jet/v6"
"github.com/labstack/echo/v4"
)
// RenderedSideboxItem is an item for display inside a rendered sidebox.
@@ -232,16 +233,15 @@ func templateTopicLink(args jet.Arguments) reflect.Value {
* Returns:
* Command string dictating what to be rendered.
* Data as a parameter for the command string.
* Standard Go error status.
*/
func TopPage(ctxt ui.AmContext) (string, any, error) {
func TopPage(ctxt ui.AmContext) (string, any) {
// Set the page title.
ctxt.VarMap().Set("amsterdam_pageTitle", "My Front Page")
// Retrieve the published posts.
hdrs, err := database.AmGetPublishedPosts(ctxt.Ctx())
if err != nil {
return ui.ErrorPage(ctxt, err)
return "error", err
}
ctxt.VarMap().Set("posts", hdrs)
@@ -254,14 +254,14 @@ func TopPage(ctxt ui.AmContext) (string, any, error) {
uid := ctxt.CurrentUserId()
sboxes, err := database.AmGetSideboxes(ctxt.Ctx(), uid)
if err != nil {
return ui.ErrorPage(ctxt, err)
return "error", err
}
rc := make([]RenderedSidebox, len(sboxes))
for i, sb := range sboxes {
err = buildRenderedSidebox(ctxt, uid, &(rc[i]), sb)
if err != nil {
return ui.ErrorPage(ctxt, err)
return "error", err
}
}
ctxt.VarMap().Set("sideboxes", rc)
@@ -269,7 +269,7 @@ func TopPage(ctxt ui.AmContext) (string, any, error) {
// Final data set.
ctxt.SetLeftMenu("top")
ctxt.VarMap().Set("amsterdam_genRefresh", true)
return "framed_template", "top.jet", nil
return "framed", "top.jet"
}
/* AboutPage renders the "About Amsterdam" page.
@@ -278,12 +278,11 @@ func TopPage(ctxt ui.AmContext) (string, any, error) {
* Returns:
* Command string dictating what to be rendered.
* Data as a parameter for the command string.
* Standard Go error status.
*/
func AboutPage(ctxt ui.AmContext) (string, any, error) {
func AboutPage(ctxt ui.AmContext) (string, any) {
// Set the page title.
ctxt.VarMap().Set("amsterdam_pageTitle", "About Amsterdam")
return "framed_template", "about.jet", nil
return "framed", "about.jet"
}
/* JumpToShortcut resolves "/go" links by redirecting them to the appropriate page.
@@ -292,22 +291,19 @@ func AboutPage(ctxt ui.AmContext) (string, any, error) {
* Returns:
* Command string dictating what to be rendered.
* Data as a parameter for the command string.
* Standard Go error status.
*/
func JumpToShortcut(ctxt ui.AmContext) (string, any, error) {
func JumpToShortcut(ctxt ui.AmContext) (string, any) {
link, err := database.AmDecodePostLink(ctxt.URLParam("postlink"))
if err != nil {
ctxt.SetRC(http.StatusNotFound)
return ui.ErrorPage(ctxt, fmt.Errorf("not found: %s (%v)", ctxt.URLParam("postlink"), err))
return "error", echo.NewHTTPError(http.StatusNotFound, fmt.Sprintf("not found: %s", ctxt.URLParam("postlink"))).SetInternal(err)
}
scope, target := link.Classify()
if scope != "global" {
ctxt.SetRC(http.StatusNotFound)
return ui.ErrorPage(ctxt, fmt.Errorf("not found: %s", ctxt.URLParam("postlink")))
return "error", echo.NewHTTPError(http.StatusNotFound, fmt.Sprintf("not found: %s", ctxt.URLParam("postlink")))
}
if err = link.VerifyNames(ctxt.Ctx()); err != nil {
ctxt.SetRC(http.StatusNotFound)
return ui.ErrorPage(ctxt, fmt.Errorf("not found: %s (%v)", ctxt.URLParam("postlink"), err))
return "error", echo.NewHTTPError(http.StatusNotFound, fmt.Sprintf("not found: %s", ctxt.URLParam("postlink"))).SetInternal(err)
}
targetURL := ""
switch target {
@@ -320,7 +316,7 @@ func JumpToShortcut(ctxt ui.AmContext) (string, any, error) {
case "post", "postrange", "postopenrange":
targetURL = fmt.Sprintf("/comm/%s/conf/%s/r/%d?r=%d,%d", link.Community, link.Conference, link.Topic, link.FirstPost, link.LastPost)
default:
return ui.ErrorPage(ctxt, fmt.Errorf("invalid target '%s' for link: %s", target, ctxt.URLParam("postlink")))
return "error", fmt.Sprintf("invalid target '%s' for link: %s", target, ctxt.URLParam("postlink"))
}
return "redirect", targetURL, nil
return "redirect", targetURL
}
+4 -7
View File
@@ -261,9 +261,8 @@ func (d *Dialog) Field(name string) *DialogItem {
* Returns:
* Command string dictating what to be rendered.
* Data as a parameter for the command string.
* Standard Go error status.
*/
func (d *Dialog) Render(ctxt AmContext) (string, any, error) {
func (d *Dialog) Render(ctxt AmContext) (string, any) {
required := false
for i, fld := range d.Fields {
if fld.Required {
@@ -323,7 +322,7 @@ func (d *Dialog) Render(ctxt AmContext) (string, any, error) {
if strings.Contains(d.Options, "suppresslogin") {
ctxt.VarMap().Set("amsterdam_suppressLogin", true)
}
return "framed_template", "dialog.jet", nil
return "framed", "dialog.jet"
}
/* RenderError sets up the rendering parameters to send this dialog to the output with an error message.
@@ -333,9 +332,8 @@ func (d *Dialog) Render(ctxt AmContext) (string, any, error) {
* Returns:
* Command string dictating what to be rendered.
* Data as a parameter for the command string.
* Standard Go error status.
*/
func (d *Dialog) RenderError(ctxt AmContext, errormessage string) (string, any, error) {
func (d *Dialog) RenderError(ctxt AmContext, errormessage string) (string, any) {
ctxt.VarMap().Set("amsterdam_errorMessage", errormessage)
return d.Render(ctxt)
}
@@ -347,9 +345,8 @@ func (d *Dialog) RenderError(ctxt AmContext, errormessage string) (string, any,
* Returns:
* Command string dictating what to be rendered.
* Data as a parameter for the command string.
* Standard Go error status.
*/
func (d *Dialog) RenderInfo(ctxt AmContext, infoMessage string) (string, any, error) {
func (d *Dialog) RenderInfo(ctxt AmContext, infoMessage string) (string, any) {
ctxt.VarMap().Set("amsterdam_infoMessage", infoMessage)
return d.Render(ctxt)
}
+2 -2
View File
@@ -103,7 +103,7 @@ func (mb *MessageBox) SetLink(id, link string) {
}
// Render sets up to render the message box.
func (mb *MessageBox) Render(ctxt AmContext) (string, any, error) {
func (mb *MessageBox) Render(ctxt AmContext) (string, any) {
blinks := mb.buttonLinks
if mb.def.useConfirm {
nonce := util.GenerateRandomAuthString()
@@ -133,7 +133,7 @@ func (mb *MessageBox) Render(ctxt AmContext) (string, any, error) {
ctxt.VarMap().Set("warningLines", mb.def.WarningLines)
ctxt.VarMap().Set("buttons", mb.def.Buttons)
ctxt.VarMap().Set("buttonLinks", blinks)
return "framed_template", "messagebox.jet", nil
return "framed_template", "messagebox.jet"
}
// Validate validates that the correct button was clicked by verifying the confirmation parameter.
+59 -27
View File
@@ -37,6 +37,44 @@ import (
*/
func AmSendPageData(ctxt echo.Context, amctxt AmContext, command string, data any) error {
var err error
if command == "error" {
httprc := amctxt.RC()
message := ""
if data == nil {
message = fmt.Sprintf("Unspecified error in %s", ctxt.Request().URL.String())
} else if he, ok := data.(*echo.HTTPError); ok {
httprc = he.Code
m1 := he.Message
e1 := he.Unwrap()
if m1 == nil || m1 == "" {
if e1 == nil {
message = fmt.Sprintf("Unspecified error in %s", ctxt.Request().URL.String())
} else {
message = e1.Error()
}
} else {
if e1 == nil {
message = fmt.Sprintf("%v", m1)
} else {
message = fmt.Sprintf("%v (%v)", m1, e1)
}
}
} else if er, ok := data.(error); ok {
message = er.Error()
} else {
message = fmt.Sprintf("%v", data)
}
if httprc < 400 {
httprc = http.StatusInternalServerError
}
amctxt.VarMap().Set("amsterdam_pageTitle", "Internal Server Error")
amctxt.VarMap().Set("error", message)
amctxt.SetRC(httprc)
command = "framed"
data = "error.jet"
}
switch command {
case "bytes":
err = ctxt.Blob(amctxt.RC(), amctxt.OutputType(), data.([]byte))
@@ -46,7 +84,7 @@ func AmSendPageData(ctxt echo.Context, amctxt AmContext, command string, data an
err = ctxt.String(amctxt.RC(), data.(string))
case "template":
err = ctxt.Render(amctxt.RC(), data.(string), amctxt)
case "framed_template":
case "framed", "framed_template":
amctxt.VarMap().Set("amsterdam_innerPage", data)
menus := make([]*MenuDefinition, 2)
switch amctxt.LeftMenu() {
@@ -59,16 +97,16 @@ func AmSendPageData(ctxt echo.Context, amctxt AmContext, command string, data an
}
menus[0] = md
default:
return fmt.Errorf("unknown left menu context: %s", amctxt.LeftMenu())
return fmt.Errorf("AmSendPageData(): unknown left menu context: %s", amctxt.LeftMenu())
}
menus[1] = AmMenu("fixed")
amctxt.VarMap().Set("amsterdam_leftMenus", menus)
err = ctxt.Render(amctxt.RC(), "frame.jet", amctxt)
default:
err = fmt.Errorf("unknown rendering type: %s", command)
err = fmt.Errorf("AmSendPageData(): unknown rendering type: %s", command)
}
if err != nil {
log.Errorf("sendPageData() barfed with %v", err)
log.Errorf("AmSendPageData() barfed with %v", err)
}
return err
}
@@ -94,6 +132,8 @@ func ErrorPage(ctxt AmContext, input_err error) (string, any, error) {
// expireTime is the expiration time sent in the dynamic headers.
var expireTime string = lctime.Strftime("%c", time.Unix(1, 0))
type PageFunc func(AmContext) (string, any)
/* AmWrap wraps the Amsterdam handler function in a wrapper that implements the spec for
* Echo handler functions.
* Parameters:
@@ -101,33 +141,25 @@ var expireTime string = lctime.Strftime("%c", time.Unix(1, 0))
* Returns:
* The wrapped function.
*/
func AmWrap(myfunc func(AmContext) (string, any, error)) echo.HandlerFunc {
return func(ctxt echo.Context) error {
amctxt := AmContextFromEchoContext(ctxt)
func AmWrap(myfunc PageFunc) echo.HandlerFunc {
return func(c echo.Context) error {
ctxt := AmContextFromEchoContext(c)
// Add the dynamic headers.
ctxt.Response().Header().Set("Pragma", "No-cache")
ctxt.Response().Header().Set("Cache-Control", "no-cache")
ctxt.Response().Header().Set("Expires", expireTime)
c.Response().Header().Set("Pragma", "No-cache")
c.Response().Header().Set("Cache-Control", "no-cache")
c.Response().Header().Set("Expires", expireTime)
// Exec the wrapped function.
what, rc, err := myfunc(amctxt)
if err == nil {
if err = amctxt.SaveSession(); err != nil {
ctxt.Logger().Errorf("Session save error: %v", err)
return err
}
err = AmSendPageData(ctxt, amctxt, what, rc)
if err != nil {
ctxt.Logger().Errorf("Rendering error: %v", err)
}
} else {
ctxt.Logger().Errorf("Page function error: %v", err)
_, rc, _ = ErrorPage(amctxt, err)
amctxt.SetRC(http.StatusInternalServerError)
newerr := AmSendPageData(ctxt, amctxt, "framed_template", rc)
err = newerr
command, arg := myfunc(ctxt)
if err := ctxt.SaveSession(); err != nil {
c.Logger().Errorf("Session save error: %v", err)
return err
}
return err
if err := AmSendPageData(c, ctxt, command, arg); err != nil {
c.Logger().Errorf("Rendering error: %v", err)
return err
}
return nil
}
}
+46 -53
View File
@@ -23,6 +23,7 @@ import (
"git.erbosoft.com/amy/amsterdam/ui"
"git.erbosoft.com/amy/amsterdam/util"
"github.com/biter777/countries"
"github.com/labstack/echo/v4"
log "github.com/sirupsen/logrus"
)
@@ -40,9 +41,8 @@ func userPhotoURL(ci *database.ContactInfo) string {
* Returns:
* Command string dictating what to be rendered.
* Data as a parameter for the command string.
* Standard Go error status.
*/
func EditProfileForm(ctxt ui.AmContext) (string, any, error) {
func EditProfileForm(ctxt ui.AmContext) (string, any) {
// Get target URI.
target := ctxt.Parameter("tgt")
if target == "" {
@@ -50,7 +50,7 @@ func EditProfileForm(ctxt ui.AmContext) (string, any, error) {
}
u := ctxt.CurrentUser()
if u.IsAnon {
return ui.ErrorPage(ctxt, errors.New("you are not logged in"))
return "error", "you are not logged in"
}
dlg, err := ui.AmLoadDialog("profile")
if err == nil {
@@ -95,7 +95,7 @@ func EditProfileForm(ctxt ui.AmContext) (string, any, error) {
}
}
}
return ui.ErrorPage(ctxt, err)
return "error", err
}
/* EditProfile handles profile editing.
@@ -104,12 +104,11 @@ func EditProfileForm(ctxt ui.AmContext) (string, any, error) {
* Returns:
* Command string dictating what to be rendered.
* Data as a parameter for the command string.
* Standard Go error status.
*/
func EditProfile(ctxt ui.AmContext) (string, any, error) {
func EditProfile(ctxt ui.AmContext) (string, any) {
u := ctxt.CurrentUser()
if u.IsAnon {
return ui.ErrorPage(ctxt, errors.New("you are not logged in"))
return "error", "you are not logged in"
}
dlg, err := ui.AmLoadDialog("profile")
if err == nil {
@@ -122,7 +121,7 @@ func EditProfile(ctxt ui.AmContext) (string, any, error) {
action := dlg.WhichButton(ctxt)
if action == "cancel" { // Cancel button pressed
return "redirect", target, nil
return "redirect", target
}
if action == "update" {
err = dlg.Validate()
@@ -192,17 +191,17 @@ func EditProfile(ctxt ui.AmContext) (string, any, error) {
if emailChange {
err = sendEmailConfirmationEmail(u, ci, ctxt.RemoteIP())
if err == nil {
return "redirect", "/verify?tgt=" + url.QueryEscape(target), nil
return "redirect", "/verify?tgt=" + url.QueryEscape(target)
}
} else {
return "redirect", target, nil
return "redirect", target
}
}
}
}
return dlg.RenderError(ctxt, "No known button click on POST to profile.")
}
return ui.ErrorPage(ctxt, err)
return "error", err
}
/* ProfilePhotoForm renders the Amsterdam profile photo upload form.
@@ -211,9 +210,8 @@ func EditProfile(ctxt ui.AmContext) (string, any, error) {
* Returns:
* Command string dictating what to be rendered.
* Data as a parameter for the command string.
* Standard Go error status.
*/
func ProfilePhotoForm(ctxt ui.AmContext) (string, any, error) {
func ProfilePhotoForm(ctxt ui.AmContext) (string, any) {
// Get target URI.
target := ctxt.Parameter("tgt")
if target == "" {
@@ -221,7 +219,7 @@ func ProfilePhotoForm(ctxt ui.AmContext) (string, any, error) {
}
u := ctxt.CurrentUser()
if u.IsAnon {
return ui.ErrorPage(ctxt, errors.New("you are not logged in"))
return "error", "you are not logged in"
}
ci, err := u.ContactInfo(ctxt.Ctx())
if err == nil {
@@ -229,9 +227,9 @@ func ProfilePhotoForm(ctxt ui.AmContext) (string, any, error) {
ctxt.VarMap().Set("photo_url", userPhotoURL(ci))
ctxt.VarMap().Set("amsterdam_pageTitle", "Upload User Photo")
ctxt.VarMap().Set("amsterdam_suppressLogin", true)
return "framed_template", "photo_upload.jet", nil
return "framed", "photo_upload.jet"
}
return ui.ErrorPage(ctxt, err)
return "error", err
}
/* ProfilePhoto handles processing the uploaded user photo.
@@ -240,23 +238,22 @@ func ProfilePhotoForm(ctxt ui.AmContext) (string, any, error) {
* Returns:
* Command string dictating what to be rendered.
* Data as a parameter for the command string.
* Standard Go error status.
*/
func ProfilePhoto(ctxt ui.AmContext) (string, any, error) {
func ProfilePhoto(ctxt ui.AmContext) (string, any) {
u := ctxt.CurrentUser()
if u.IsAnon {
return ui.ErrorPage(ctxt, errors.New("you are not logged in"))
return "error", "you are not logged in"
}
ci, err := u.ContactInfo(ctxt.Ctx())
if err != nil {
return ui.ErrorPage(ctxt, err)
return "error", err
}
target := ctxt.FormField("tgt")
if target == "" {
target = "/"
}
if ctxt.FormFieldIsSet("cancel") {
return "redirect", "/profile?tgt=" + url.QueryEscape(target), nil
return "redirect", "/profile?tgt=" + url.QueryEscape(target)
}
if ctxt.FormFieldIsSet("upload") {
file, err := ctxt.FormFile("thepic")
@@ -273,7 +270,7 @@ func ProfilePhoto(ctxt ui.AmContext) (string, any, error) {
ci.PhotoURL = &photourl
_, err = ci.Save(ctxt.Ctx())
if err == nil {
return "redirect", "/profile?tgt=" + url.QueryEscape(target), nil
return "redirect", "/profile?tgt=" + url.QueryEscape(target)
}
}
}
@@ -283,19 +280,19 @@ func ProfilePhoto(ctxt ui.AmContext) (string, any, error) {
ctxt.VarMap().Set("photo_url", userPhotoURL(ci))
ctxt.VarMap().Set("amsterdam_pageTitle", "Upload User Photo")
ctxt.VarMap().Set("amsterdam_suppressLogin", true)
return "framed_template", "photo_upload.jet", nil
return "framed", "photo_upload.jet"
}
if ctxt.FormFieldIsSet("remove") {
purl := ci.PhotoURL
happy := false
if purl == nil || *purl == "" {
// this is a no-op
return "redirect", "/profile?tgt=" + url.QueryEscape(target), nil
return "redirect", "/profile?tgt=" + url.QueryEscape(target)
}
if strings.HasPrefix(*purl, "/img/store/") {
id, err := strconv.Atoi((*purl)[11:])
if err != nil {
return ui.ErrorPage(ctxt, err)
return "error", err
}
defer func() {
if happy {
@@ -311,12 +308,12 @@ func ProfilePhoto(ctxt ui.AmContext) (string, any, error) {
ci.PhotoURL = nil
_, err := ci.Save(ctxt.Ctx())
if err != nil {
return ui.ErrorPage(ctxt, err)
return "error", err
}
happy = true
return "redirect", "/profile?tgt=" + url.QueryEscape(target), nil
return "redirect", "/profile?tgt=" + url.QueryEscape(target)
}
return ui.ErrorPage(ctxt, errors.New("invalid button detected in photo upload"))
return "error", "invalid button detected in photo upload"
}
/* ShowProfile displays a user's profile.
@@ -325,24 +322,22 @@ func ProfilePhoto(ctxt ui.AmContext) (string, any, error) {
* Returns:
* Command string dictating what to be rendered.
* Data as a parameter for the command string.
* Standard Go error status.
*/
func ShowProfile(ctxt ui.AmContext) (string, any, error) {
func ShowProfile(ctxt ui.AmContext) (string, any) {
me := ctxt.CurrentUser()
prefs, err := me.Prefs(ctxt.Ctx())
if err != nil {
return ui.ErrorPage(ctxt, err)
return "error", err
}
// Gather the info on the current user.
user, err := database.AmGetUserByName(ctxt.Ctx(), ctxt.URLParam("uname"), nil)
if err != nil {
ctxt.SetRC(http.StatusNotFound)
return ui.ErrorPage(ctxt, err)
return "error", echo.NewHTTPError(http.StatusNotFound).SetInternal(err)
}
ci, err := user.ContactInfo(ctxt.Ctx())
if err != nil {
return ui.ErrorPage(ctxt, err)
return "error", err
}
var pvtAddr, pvtPhone, pvtFax, pvtEmail bool
if database.AmTestPermission("Global.SeeHiddenContactInfo", me.BaseLevel) {
@@ -433,7 +428,7 @@ func ShowProfile(ctxt ui.AmContext) (string, any, error) {
ctxt.VarMap().Set("mobile", *ci.Mobile)
}
ctxt.VarMap().Set("amsterdam_pageTitle", fmt.Sprintf("User Profile - %s", user.Username))
return "framed_template", "profile.jet", nil
return "framed", "profile.jet"
}
/* QuickEMail sends quick E-mail to a user.
@@ -442,31 +437,30 @@ func ShowProfile(ctxt ui.AmContext) (string, any, error) {
* Returns:
* Command string dictating what to be rendered.
* Data as a parameter for the command string.
* Standard Go error status.
*/
func QuickEMail(ctxt ui.AmContext) (string, any, error) {
func QuickEMail(ctxt ui.AmContext) (string, any) {
me := ctxt.CurrentUser()
if me.IsAnon {
return ui.ErrorPage(ctxt, errors.New("you are not logged in"))
return "error", "you are not logged in"
}
myCI, err := me.ContactInfo(ctxt.Ctx())
if err != nil {
return ui.ErrorPage(ctxt, err)
return "error", err
}
toUid, err := ctxt.FormFieldInt("to_uid")
if err != nil {
return ui.ErrorPage(ctxt, err)
return "error", err
}
user, err := database.AmGetUser(ctxt.Ctx(), int32(toUid))
if err != nil {
return ui.ErrorPage(ctxt, err)
return "error", err
}
if user.IsAnon {
return ui.ErrorPage(ctxt, errors.New("cannot send quick E-mail to anonymous user"))
return "error", "cannot send quick E-mail to anonymous user"
}
ci, err := user.ContactInfo(ctxt.Ctx())
if err != nil {
return ui.ErrorPage(ctxt, err)
return "error", err
}
msg := email.AmNewEmailMessage(me.Uid, ctxt.RemoteIP())
msg.AddTo(*ci.Email, user.Username)
@@ -474,7 +468,7 @@ func QuickEMail(ctxt ui.AmContext) (string, any, error) {
msg.SetSubject(ctxt.FormField("subj"))
msg.SetText(ctxt.FormField("pb"))
msg.Send()
return "redirect", "/user/" + user.Username, nil
return "redirect", "/user/" + user.Username
}
/* Hotlist displays and edits the user's conference hotlist.
@@ -483,16 +477,15 @@ func QuickEMail(ctxt ui.AmContext) (string, any, error) {
* Returns:
* Command string dictating what to be rendered.
* Data as a parameter for the command string.
* Standard Go error status.
*/
func Hotlist(ctxt ui.AmContext) (string, any, error) {
func Hotlist(ctxt ui.AmContext) (string, any) {
me := ctxt.CurrentUser()
if me.IsAnon {
return ui.ErrorPage(ctxt, errors.New("you are not logged in"))
return "error", "you are not logged in"
}
hotlist, err := database.AmGetConferenceHotlist(ctxt.Ctx(), me)
if err != nil {
return ui.ErrorPage(ctxt, err)
return "error", err
}
if ctxt.HasParameter("m") {
@@ -501,7 +494,7 @@ func Hotlist(ctxt ui.AmContext) (string, any, error) {
if index >= 0 && (index+dir) != index {
err := database.AmReorderHotlist(ctxt.Ctx(), me, hotlist[index].Sequence, hotlist[index+dir].Sequence)
if err != nil {
return ui.ErrorPage(ctxt, err)
return "error", err
}
tmp := hotlist[index].CommId
hotlist[index].CommId = hotlist[index+dir].CommId
@@ -515,7 +508,7 @@ func Hotlist(ctxt ui.AmContext) (string, any, error) {
if index >= 0 {
err := database.AmRemoveEntryFromHotlist(ctxt.Ctx(), me, hotlist[index].Sequence)
if err != nil {
return ui.ErrorPage(ctxt, err)
return "error", err
}
hotlist = append(hotlist[:index], hotlist[index+1:]...)
}
@@ -526,12 +519,12 @@ func Hotlist(ctxt ui.AmContext) (string, any, error) {
for i := range hotlist {
comm, err := hotlist[i].Community(ctxt.Ctx())
if err != nil {
return ui.ErrorPage(ctxt, err)
return "error", err
}
communities[i] = comm.Name
conf, err := hotlist[i].Conference(ctxt.Ctx())
if err != nil {
return ui.ErrorPage(ctxt, err)
return "error", err
}
conferences[i] = conf.Name
}
@@ -540,5 +533,5 @@ func Hotlist(ctxt ui.AmContext) (string, any, error) {
ctxt.VarMap().Set("communities", communities)
ctxt.VarMap().Set("conferences", conferences)
ctxt.VarMap().Set("amsterdam_pageTitle", "Your Conference Hotlist")
return "framed_template", "hotlist.jet", nil
return "framed", "hotlist.jet"
}