diff --git a/conference.go b/conference.go index 19cc678..f9c3626 100644 --- a/conference.go +++ b/conference.go @@ -558,6 +558,8 @@ func PostInTopic(ctxt ui.AmContext) (string, any, error) { // Locate community, conference, and topic. comm := ctxt.CurrentCommunity() conf := ctxt.GetScratch("currentConference").(*database.Conference) + level := ctxt.GetScratch("levelInConference").(uint16) + var topic *database.Topic = nil if rawTopic, err := strconv.ParseInt(ctxt.URLParam("topic"), 10, 16); err == nil { topic, err = database.AmGetTopicByNumber(ctxt.Ctx(), conf, int16(rawTopic)) @@ -571,6 +573,22 @@ func PostInTopic(ctxt ui.AmContext) (string, any, error) { if ctxt.FormFieldIsSet("cancel") { return "redirect", urlStem, nil } + + 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")) + } + + 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")) + } + + 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")) + } + if ctxt.FormFieldIsSet("preview") { // Preview the post. checker, err := htmlcheck.AmNewHTMLChecker(ctxt.Ctx(), "escaper") @@ -595,7 +613,7 @@ func PostInTopic(ctxt ui.AmContext) (string, any, error) { if err != nil { return ui.ErrorPage(ctxt, err) } - checker.SetContext("PostLinkDecoderContext", database.AmCreatePostLinkContext(comm.Alias, ctxt.URLParam("cid"), conf.TopTopic+1)) + checker.SetContext("PostLinkDecoderContext", database.AmCreatePostLinkContext(comm.Alias, ctxt.URLParam("cid"), topic.Number)) checker.Append(postdata) checker.Finish() v, _ = checker.Value() @@ -628,8 +646,51 @@ func PostInTopic(ctxt ui.AmContext) (string, any, error) { } if int32(maxPost) < topic.TopMessage { // Slippage detected! Display the slipped posts and another post box. - // TODO - return "framed_template", "???", nil + // Get the slipped posts. + posts, err := database.AmGetPostRange(ctxt.Ctx(), topic, int32(maxPost), topic.TopMessage) + if err != nil { + return ui.ErrorPage(ctxt, err) + } + + // start with escaping the post data + checker, err := htmlcheck.AmNewHTMLChecker(ctxt.Ctx(), "escaper") + if err != nil { + return ui.ErrorPage(ctxt, err) + } + checker.Append(ctxt.FormField("pseud")) + checker.Finish() + v, _ := checker.Value() + ctxt.VarMap().Set("pseud", v) + + // escape the data + postdata := ctxt.FormField("pb") + checker.Reset() + checker.Append(postdata) + checker.Finish() + v, _ = checker.Value() + ctxt.VarMap().Set("pb", v) + if ctxt.FormFieldIsSet("attach") { + ctxt.VarMap().Set("attachFile", true) + } + + plc := database.AmCreatePostLinkContext("", ctxt.GetScratch("currentAlias").(string), topic.Number) + topicConferenceRef := plc.AsString() + plc.Community = comm.Alias + topicPostRef := plc.AsString() + + ctxt.VarMap().Set("post_confRef", topicConferenceRef) + ctxt.VarMap().SetFunc("post_getOverrideLine", templateOverrideLine) + ctxt.VarMap().SetFunc("post_getOverrideLink", templateOverrideLink) + ctxt.VarMap().SetFunc("post_getText", templatePostText) + ctxt.VarMap().SetFunc("post_getUserName", templateExtractUserName) + ctxt.VarMap().Set("post_stem", fmt.Sprintf("/comm/%s/conf/%s/r/%d", comm.Alias, ctxt.GetScratch("currentAlias").(string), topic.Number)) + ctxt.VarMap().Set("post_max", topic.TopMessage) + ctxt.VarMap().Set("post_topicPermalink", fmt.Sprintf("/go/%s", topicPostRef)) + ctxt.VarMap().Set("posts", posts) + ctxt.VarMap().Set("topicName", topic.Name) + ctxt.VarMap().Set("amsterdam_pageTitle", "Slippage or Double-Click Detected") + + return "framed_template", "slippage.jet", nil } // start by checking the title and pseud checker, err := htmlcheck.AmNewHTMLChecker(ctxt.Ctx(), "post-pseud") @@ -645,14 +706,14 @@ func PostInTopic(ctxt ui.AmContext) (string, any, error) { if err != nil { return ui.ErrorPage(ctxt, err) } - checker.SetContext("PostLinkDecoderContext", database.AmCreatePostLinkContext(comm.Alias, ctxt.URLParam("cid"), conf.TopTopic+1)) + checker.SetContext("PostLinkDecoderContext", database.AmCreatePostLinkContext(comm.Alias, ctxt.URLParam("cid"), topic.Number)) checker.Append(ctxt.FormField("pb")) checker.Finish() postText, _ := checker.Value() lines, _ := checker.Lines() // Add the post! - hdr, err := database.AmNewPost(ctxt.Ctx(), conf, topic, ctxt.CurrentUser(), postPseud, postText, int32(lines)) + hdr, err := database.AmNewPost(ctxt.Ctx(), conf, topic, ctxt.CurrentUser(), postPseud, postText, int32(lines), ctxt.RemoteIP()) if err != nil { return ui.ErrorPage(ctxt, err) } @@ -661,6 +722,8 @@ func PostInTopic(ctxt ui.AmContext) (string, any, error) { return "redirect", returnURL, nil // no attachment - just redisplay topic list } + // TODO: whoever's subscribed needs to get a copy of this post in their E-mail + // go upload the attachment ctxt.VarMap().Set("target", returnURL) ctxt.VarMap().Set("post", hdr.PostId) diff --git a/database/conference.go b/database/conference.go index c8dfbdb..fd0be0a 100644 --- a/database/conference.go +++ b/database/conference.go @@ -178,6 +178,15 @@ func (c *Conference) Settings(ctx context.Context, u *User) (*ConferenceSettings return &(dbdata[0]), nil } +// TouchUpdate updates the "last update" date/time in the conference. +func (c *Conference) TouchUpdate(ctx context.Context, tx *sqlx.Tx, lastUpdate time.Time) error { + _, err := tx.ExecContext(ctx, "UPDATE confs SET lastupdate = ? WHERE confid = ?", lastUpdate, c.ConfId) + if err == nil { + c.LastUpdate = &lastUpdate + } + return err +} + // TouchRead updates the "last posted" date/time in the conference for the user. func (c *Conference) TouchRead(ctx context.Context, tx *sqlx.Tx, u *User) (*ConferenceSettings, error) { cs, err := c.Settings(ctx, u) diff --git a/database/post.go b/database/post.go index 712e166..62295b7 100644 --- a/database/post.go +++ b/database/post.go @@ -128,12 +128,17 @@ func AmGetPostRange(ctx context.Context, topic *Topic, first, last int32) ([]*Po * pseud - Pseud for the new post. * post - New post text. * postLines - Number of lines in the post text. + * ipaddr - IP address of user maing the post. * Returns: * New post header pointer. * Standard Go error status. */ -func AmNewPost(ctx context.Context, conf *Conference, topic *Topic, user *User, pseud string, post string, postLines int32) (*PostHeader, error) { +func AmNewPost(ctx context.Context, conf *Conference, topic *Topic, user *User, pseud string, post string, postLines int32, ipaddr string) (*PostHeader, error) { success := false + var ar *AuditRecord = nil + defer func() { + AmStoreAudit(ar) + }() tx := amdb.MustBegin() defer func() { if !success { @@ -141,7 +146,7 @@ func AmNewPost(ctx context.Context, conf *Conference, topic *Topic, user *User, } }() unlock := true - tx.ExecContext(ctx, "LOCK TABLES topics WRITE, topicsettings WRITE, posts WRITE, postdata WRITE;") + tx.ExecContext(ctx, "LOCK TABLES confs WRITE, topics WRITE, topicsettings WRITE, posts WRITE, postdata WRITE;") defer func() { if unlock { tx.ExecContext(ctx, "UNLOCK TABLES;") @@ -189,7 +194,10 @@ func AmNewPost(ctx context.Context, conf *Conference, topic *Topic, user *User, tx.ExecContext(ctx, "UNLOCK TABLES;") unlock = false - // update the "last posted" date in the conference settings + // update the "last update" date of the conference and the "last posted" date in the conference settings + if err = conf.TouchUpdate(ctx, tx, hdr.Posted); err != nil { + return nil, err + } _, err = conf.TouchPost(ctx, tx, user, hdr.Posted) if err != nil { return nil, err @@ -199,5 +207,10 @@ func AmNewPost(ctx context.Context, conf *Conference, topic *Topic, user *User, return nil, err } success = true + + // create audit record + ar = AmNewAudit(AuditConferencePostMessage, user.Uid, ipaddr, fmt.Sprintf("confid=%d", conf.ConfId), + fmt.Sprintf("topic=%d", topic.Number), fmt.Sprintf("post=%d", hdr.PostId), fmt.Sprintf("pseud=%s", *hdr.Pseud)) + return hdr, nil } diff --git a/ui/views/slippage.jet b/ui/views/slippage.jet index b7fc9f0..a28510e 100644 --- a/ui/views/slippage.jet +++ b/ui/views/slippage.jet @@ -24,7 +24,6 @@ {{ m = map("post_cur", p, "post_userName", post_getUserName(p, .), "post_text", post_getText(p, .), "post_overrideLine", post_getOverrideLine(p, .), "post_overrideLink", post_getOverrideLink(p, post_topicPermalink)) }} {{ .SubRender2("singlepost.jet", m) | raw }} - {{ if pin == p.Num }}