diff --git a/community.go b/community.go index eced81c..a497905 100644 --- a/community.go +++ b/community.go @@ -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" } diff --git a/communityadmin.go b/communityadmin.go index 5348f59..da4d921 100644 --- a/communityadmin.go +++ b/communityadmin.go @@ -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 } diff --git a/conference.go b/conference.go index fef0b15..5a6a6e6 100644 --- a/conference.go +++ b/conference.go @@ -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" } diff --git a/conference_ops.go b/conference_ops.go index 9a502cf..68c760b 100644 --- a/conference_ops.go +++ b/conference_ops.go @@ -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 <%s>, originally composed by <%s>!`, 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) } diff --git a/conferenceadmin.go b/conferenceadmin.go index 6ddd16a..a4cbe56 100644 --- a/conferenceadmin.go +++ b/conferenceadmin.go @@ -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) } diff --git a/errors.go b/errors.go index fdc5359..325ae07 100644 --- a/errors.go +++ b/errors.go @@ -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. diff --git a/find.go b/find.go index a0317b8..7b4d58e 100644 --- a/find.go +++ b/find.go @@ -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) diff --git a/invites.go b/invites.go index a50c0e6..dbaf297 100644 --- a/invites.go +++ b/invites.go @@ -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 } diff --git a/login.go b/login.go index cf06981..7288be0 100644 --- a/login.go +++ b/login.go @@ -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 } diff --git a/sysadmin.go b/sysadmin.go index 979885f..8f979f5 100644 --- a/sysadmin.go +++ b/sysadmin.go @@ -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" } diff --git a/top.go b/top.go index 8bf4823..7ffe76d 100644 --- a/top.go +++ b/top.go @@ -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 } diff --git a/ui/dialog.go b/ui/dialog.go index b58dc5a..4a5b1b7 100644 --- a/ui/dialog.go +++ b/ui/dialog.go @@ -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) } diff --git a/ui/messagebox.go b/ui/messagebox.go index 2288a56..f641fb0 100644 --- a/ui/messagebox.go +++ b/ui/messagebox.go @@ -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. diff --git a/ui/render_wrap.go b/ui/render_wrap.go index e2673ec..da3a17f 100644 --- a/ui/render_wrap.go +++ b/ui/render_wrap.go @@ -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 } } diff --git a/userdata.go b/userdata.go index c783367..4dd4885 100644 --- a/userdata.go +++ b/userdata.go @@ -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" }