summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYorhel <git@yorhel.nl>2020-03-21 09:59:25 +0100
committerYorhel <git@yorhel.nl>2020-03-21 10:01:33 +0100
commit45a4cc5efc3ca1f7cb174cfa30205e36a40d2420 (patch)
tree702565b1b54b9f82a51402008977f2de90b4b0fa
parent8837061d105aa44e6df294523b8295ea8f66daa6 (diff)
boardmod feature: Full deletion of threads/posts
Intended to prevent unecessary "deleted" posts, bumping of old threads and stray notifications when a spammer hits the boards. To make that easier, there should also be a "delete all posts by this user" function, but that'll be even trickier.
-rw-r--r--elm/Discussions/Edit.elm17
-rw-r--r--lib/VNWeb/Discussions/Edit.pm22
2 files changed, 38 insertions, 1 deletions
diff --git a/elm/Discussions/Edit.elm b/elm/Discussions/Edit.elm
index 4eaf7aa9..1ce6bd75 100644
--- a/elm/Discussions/Edit.elm
+++ b/elm/Discussions/Edit.elm
@@ -33,6 +33,7 @@ type alias Model =
, hidden : Bool
, private : Bool
, nolastmod : Bool
+ , delete : Bool
, title : Maybe String
, boards : Maybe (List GDE.SendBoards)
, boardAdd : A.Model GApi.ApiBoardResult
@@ -54,6 +55,7 @@ init d =
, hidden = d.hidden
, private = d.private
, nolastmod = False
+ , delete = False
, title = d.title
, boards = d.boards
, boardAdd = A.init ""
@@ -76,6 +78,7 @@ encode m =
, hidden = m.hidden
, private = m.private
, nolastmod = m.nolastmod
+ , delete = m.delete
, boards = m.boards
, poll = if m.pollEnabled then m.poll else Nothing
, title = m.title
@@ -98,6 +101,7 @@ type Msg
| Hidden Bool
| Private Bool
| Nolastmod Bool
+ | Delete Bool
| Content TP.Msg
| Title String
| BoardDel Int
@@ -119,6 +123,7 @@ update msg model =
Hidden b -> ({ model | hidden = b }, Cmd.none)
Private b -> ({ model | private = b }, Cmd.none)
Nolastmod b -> ({ model | nolastmod=b }, Cmd.none)
+ Delete b -> ({ model | delete = b }, Cmd.none)
Content m -> let (nm,nc) = TP.update m model.msg in ({ model | msg = nm }, Cmd.map Content nc)
Title s -> ({ model | title = Just s }, Cmd.none)
PollEnabled b -> ({ model | pollEnabled = b, poll = if model.poll == Nothing then Just { question = "", max_options = 1, options = ["",""] } else model.poll }, Cmd.none)
@@ -233,7 +238,17 @@ view model =
, a [ href "/d9#3" ] [ text "Formatting" ]
]
]
- ] ++ if thread then poll () else []
+ ]
+ ++ (if thread then poll () else [])
+ ++ (if not model.can_mod then [] else
+ [ tr [ class "newpart" ] [ td [ colspan 2 ] [ text "DANGER ZONE" ] ]
+ , formField ""
+ [ inputCheck "" model.delete Delete
+ , text <| " Permanently delete this " ++ if thread then "thread and all replies." else "post."
+ , text <| if thread then "" else " This causes all replies after this one to be renumbered."
+ , text <| " This action can not be reverted, only do this with obvious spam!"
+ ]
+ ])
]
, div [ class "mainbox" ]
[ fieldset [ class "submit" ] [ submitButton "Submit" model.state (isValid model) ] ]
diff --git a/lib/VNWeb/Discussions/Edit.pm b/lib/VNWeb/Discussions/Edit.pm
index 15e5c198..a0627448 100644
--- a/lib/VNWeb/Discussions/Edit.pm
+++ b/lib/VNWeb/Discussions/Edit.pm
@@ -27,6 +27,7 @@ my $FORM = {
hidden => { anybool => 1 }, # When can_mod
private => { anybool => 1 }, # When can_private && (num = 1 || tid = undef)
nolastmod => { anybool => 1, _when => 'in' }, # When can_mod
+ delete => { anybool => 1 }, # When can_mod
msg => { maxlength => 32768 },
};
@@ -49,6 +50,26 @@ elm_api DiscussionsEdit => $FORM_OUT, $FORM_IN, sub {
return tuwf->resNotFound if $tid && !$t->{id};
return elm_Unauth if !can_edit t => $t;
+ if($data->{delete} && auth->permBoardmod) {
+ warn "AUDIT: Delete t$tid.$num\n";
+ # BUG: Doesn't cause stats_cache to be updated. But who cares about that.
+ if($num == 1) {
+ # (This could be a single query if there were proper ON DELETE CASCADE in the DB, though that's hard for notifications...)
+ tuwf->dbExeci('DELETE FROM threads_posts WHERE tid =', \$tid);
+ tuwf->dbExeci('DELETE FROM threads_boards WHERE tid =', \$tid);
+ tuwf->dbExeci('DELETE FROM threads WHERE id =', \$tid);
+ tuwf->dbExeci(q{DELETE FROM notifications WHERE ltype = 't' AND iid =}, \$tid);
+ return elm_Redirect '/t';
+ } else {
+ tuwf->dbExeci('DELETE FROM threads_posts WHERE tid =', \$tid, 'AND num =', \$num);
+ tuwf->dbExeci('UPDATE threads_posts SET num = num - 1 WHERE tid =', \$tid, 'AND num >', \$num);
+ tuwf->dbExeci('UPDATE threads SET count = count - 1 WHERE id =', \$tid);
+ tuwf->dbExeci(q{DELETE FROM notifications WHERE ltype = 't' AND iid =}, \$tid, 'AND subid =', \$num);
+ tuwf->dbExeci(q{UPDATE notifications SET subid = subid - 1 WHERE ltype = 't' AND iid =}, \$tid, 'AND subid >', \$num);
+ return elm_Redirect "/t$tid";
+ }
+ }
+
my $pollchanged = !$data->{tid} && $data->{poll};
if($num == 1) {
die "Invalid title" if !length $data->{title};
@@ -152,6 +173,7 @@ TUWF::get qr{(?:/t/(?<board>$BOARD_RE)/new|/$RE{postid}/edit)}, sub {
$t->{num} //= undef;
$t->{private} //= 0;
$t->{locked} //= 0;
+ $t->{delete} = 0;
framework_ title => $tid ? 'Edit post' : 'Create new thread', sub {
elm_ 'Discussions.Edit' => $FORM_OUT, $t;