diff --git a/assets/intervine_deletion.js b/assets/intervine_deletion.js new file mode 100644 index 0000000..a0a9dfb --- /dev/null +++ b/assets/intervine_deletion.js @@ -0,0 +1,36 @@ +/* +There's a delete buttotn to delete a post. If javascript is enabled, replace +the button with one that will ask for confirmation before deleting. +*/ + +function delete_intervine(){ + var forms = document.getElementsByTagName("form"); + if(forms.length == 0){return;}//Don't load if the story is missing. + var delete_form; + for(var i = 0; i < forms.length; i++){ + if(forms[i].action.endsWith("_delete")){ + delete_form = forms[i]; + break; + } + } + if(delete_form == null){return;}//Don't load if we're not logged in + var delete_parent = delete_form.parentNode; + delete_parent.removeChild(delete_form); + var delete_wrapper = document.createElement("div"); + var delete_button = document.createElement("button"); + delete_button.classList.add("button"); + delete_button.classList.add("column"); + delete_button.classList.add("column-0"); + delete_button.textContent = "Delete"; + delete_button.addEventListener("click",function(){ + if(confirm("Are you sure you want to delete this story?")){ + document.documentElement.appendChild(delete_form); + delete_form.submit(); + } + }); + delete_parent.appendChild(delete_wrapper); + delete_wrapper.appendChild(delete_button); + +} + +document.addEventListener("DOMContentLoaded",delete_intervine,false); diff --git a/conf/smr.conf.in b/conf/smr.conf.in index 9de3ed0..5d44c41 100644 --- a/conf/smr.conf.in +++ b/conf/smr.conf.in @@ -46,6 +46,7 @@ domain * { route /_faq asset_serve_faq_html route /_js/suggest_tags.js asset_serve_suggest_tags_js route /_js/bookmark.js asset_serve_bookmark_js + route /_js/intervine_deletion.js asset_serve_intervine_deletion_js route /favicon.ico asset_serve_favicon_ico route /_paste post_story route /_edit edit_story @@ -58,6 +59,7 @@ domain * { route /_search search route /_archive archive route /_api api + route /_delete delete # Leading ^ is needed for dynamic routes, kore says the route is dynamic if it does not start with '/' route ^/[^_].* read_story @@ -119,4 +121,7 @@ domain * { validate call v_any validate data v_any } + params post /_delete { + validate story v_storyid + } } diff --git a/src/lua/endpoints/delete_post.lua b/src/lua/endpoints/delete_post.lua new file mode 100644 index 0000000..f548b18 --- /dev/null +++ b/src/lua/endpoints/delete_post.lua @@ -0,0 +1,64 @@ +local tags = require("tags") +local util = require("util") +local pages = require("pages") +local config = require("config") +local session = require("session") +local db = require("db") +local queries = require("queries") +local sql = require("lsqlite3") +local cache = require("cache") + +local oldconfigure = configure +local stmnt_delete +function configure(...) + stmnt_delete = assert(db.conn:prepare(queries.delete_post),db.conn:errmsg()) + return oldconfigure(...) +end + +local function delete_post(req) + local host = http_request_get_host(req) + local path = http_request_get_path(req) + http_request_populate_post(req) + local storystr = assert(http_argument_get_string(req,"story")) + print("Looking at storystr:",storystr) + local storyid = util.decode_id(storystr) + local author, authorid = session.get(req) + if not author then + http_response(req, 401, pages.error{ + errcode = 401, + errcodemsg = "Not authorized", + explanation = "You must be logged in to delete posts. You are either not logged in or your session has expired.", + should_traceback = true + }) + return + end + log(LOG_DEBUG,string.format("Deleting post %d with proposed owner %d",storyid, authorid)) + stmnt_delete:bind_names{ + postid = storyid, + authorid = authorid + } + local err = util.do_sql(stmnt_delete) + if err ~= sql.DONE then + log(LOG_DEBUG,string.format("Failed to delete: %d:%s",err, db.conn:errmsg())) + http_response(req,500,pages.error{ + errcode = 500, + errcodemsg = "Internal error", + explanation = "Failed to delete posts from database:" .. db.conn:errmsg(), + should_traceback = true, + }) + stmnt_delete:reset() + else + local loc = string.format("https://%s/%s",config.domain,storystr) + http_response_header(req,"Location",loc) + http_response(req,303,"") + stmnt_delete:reset() + cache.dirty(string.format("%s",config.domain)) + cache.dirty(string.format("%s-logout",config.domain)) + cache.dirty(string.format("%s.%s",author,config.domain)) + cache.dirty(string.format("%s",storystr)) + cache.dirty(string.format("%s?comments=1",storystr)) + + end +end + +return delete_post diff --git a/src/lua/endpoints/read_get.lua b/src/lua/endpoints/read_get.lua index 877fe08..67ac4a7 100644 --- a/src/lua/endpoints/read_get.lua +++ b/src/lua/endpoints/read_get.lua @@ -99,7 +99,8 @@ local function read_get(req) path = http_request_get_path(req), method = http_method_text(req), extra_load = { - '' + '', + '', } } local err diff --git a/src/lua/init.lua b/src/lua/init.lua index 61aac35..d671694 100644 --- a/src/lua/init.lua +++ b/src/lua/init.lua @@ -35,6 +35,7 @@ local endpoint_names = { search = {"get"}, archive = {"get"}, api = {"get"}, + delete = {"post"}, } local endpoints = {} for name, methods in pairs(endpoint_names) do @@ -119,6 +120,10 @@ function edit(req) end end +function delete(req) + endpoints.delete_post(req) +end + --TODO function edit_bio() error("Not yet implemented") diff --git a/src/pages/read.etlua.in b/src/pages/read.etlua.in index 94e692b..4bed22a 100644 --- a/src/pages/read.etlua.in +++ b/src/pages/read.etlua.in @@ -3,10 +3,16 @@ <%= domain %>/<%= idp %> <% if owner then -%> +