diff --git a/conf/smr.conf.in b/conf/smr.conf.in index 6102105..0a5ac08 100644 --- a/conf/smr.conf.in +++ b/conf/smr.conf.in @@ -47,6 +47,7 @@ domain * { route /_edit edit_story route /_bio edit_bio route /_login login + route /_logout logout route ^/_claim claim route /_download download route /_preview preview @@ -59,6 +60,7 @@ domain * { } params get /_download { validate story v_storyid + validate pwd v_hex_128 } params post /_edit { validate title v_any @@ -95,6 +97,7 @@ domain * { params post ^/[^_].* { validate text v_any validate postas v_subdomain + validate pwd v_hex_128 } params post /_login { validate user v_subdomain diff --git a/src/lua/endpoints/download_get.lua b/src/lua/endpoints/download_get.lua index 59e0172..1c63bd3 100644 --- a/src/lua/endpoints/download_get.lua +++ b/src/lua/endpoints/download_get.lua @@ -18,6 +18,8 @@ local function download_get(req) local path = http_request_get_path(req) http_request_populate_qs(req) local story = assert(http_argument_get_string(req,"story")) + local hashstr = http_argument_get_string(req,"pwd") + local ihash = hashstr and util.decode_unlisted(hashstr) story = util.decodeentities(story) local story_id = util.decode_id(story) stmnt_download:bind_names{ @@ -31,7 +33,14 @@ local function download_get(req) return end assert(err == sql.ROW, "after doing download sql, result was not a row, was:" .. tostring(err)) - local txt_compressed, title = unpack(stmnt_download:get_values()) + local txt_compressed, title, unlisted, hash = unpack(stmnt_download:get_values()) + unlisted = unlisted == 1 + if unlisted and hash ~= ihash then + --Unlisted and hash was incorrect, pretend we don't have it + http_response(req,404,pages.nostory{path=story}) + stmnt_download:reset() + return + end local text = zlib.decompress(txt_compressed) stmnt_download:reset() http_response_header(req,"Content-Type","application/octet-stream") diff --git a/src/lua/endpoints/edit_get.lua b/src/lua/endpoints/edit_get.lua index 8c5a29f..fdca472 100644 --- a/src/lua/endpoints/edit_get.lua +++ b/src/lua/endpoints/edit_get.lua @@ -45,7 +45,8 @@ local function edit_get(req) end assert(err == sql.ROW) local data = stmnt_edit:get_values() - local txt_compressed, markup, isanon, title = unpack(data) + local txt_compressed, markup, isanon, title, unlisted = unpack(data) + print("from query, unlisted was:",unlisted) local text = zlib.decompress(txt_compressed) local tags = tags.get(story_id) local tags_txt = table.concat(tags,";") @@ -59,7 +60,8 @@ local function edit_get(req) domain = config.domain, story = story_id, err = "", - tags = tags_txt + tags = tags_txt, + unlisted = unlisted } http_response(req,200,ret) end diff --git a/src/lua/endpoints/edit_post.lua b/src/lua/endpoints/edit_post.lua index b458462..441acdf 100644 --- a/src/lua/endpoints/edit_post.lua +++ b/src/lua/endpoints/edit_post.lua @@ -18,6 +18,7 @@ function configure(...) stmnt_author_of = assert(db.conn:prepare(queries.select_author_of_post)) stmnt_update_raw = assert(db.conn:prepare(queries.update_raw)) stmnt_update = assert(db.conn:prepare(queries.update_post)) + stmnt_hash = assert(db.conn:prepare(queries.select_post_hash)) return oldconfigure(...) end @@ -33,6 +34,7 @@ local function edit_post(req) local pasteas = assert(http_argument_get_string(req,"pasteas")) local markup = assert(http_argument_get_string(req,"markup")) local unlisted = http_argument_get_string(req,"unlisted") == "on" + print("unlisted was:",unlisted) local tags_str = http_argument_get_string(req,"tags") stmnt_author_of:bind_names{ id = storyid @@ -61,13 +63,23 @@ local function edit_post(req) assert(stmnt_update:bind(1,title) == sql.OK) assert(stmnt_update:bind_blob(2,compr) == sql.OK) assert(stmnt_update:bind(3,pasteas == "anonymous" and 1 or 0) == sql.OK) - assert(stmnt_update:bind(4,storyid) == sql.OK) - assert(stmnt_update:bind(5,unlisted) == sql.OK) + assert(stmnt_update:bind(4,unlisted) == sql.OK) + assert(stmnt_update:bind(5,storyid) == sql.OK) assert(util.do_sql(stmnt_update) == sql.DONE, "Failed to update text") stmnt_update:reset() tagslib.set(storyid,tags) local id_enc = util.encode_id(storyid) + local hash local loc = string.format("https://%s/%s",config.domain,id_enc) + if unlisted then + stmnt_hash:bind_names{id=storyid} + local err = util.do_sql(stmnt_hash) + if err ~= sql.ROW then + error("Failed to get a post's hash while trying to make it unlisted") + end + local hash = stmnt_hash:get_value(0) + loc = loc .. "?pwd=" .. util.encode_unlisted(hash) + end --Turning something from not unlisted to unlisted should dirty all these --places anyway, so the post can now be hidden. cache.dirty(string.format("%s/%s",config.domain,id_enc)) -- This place to read this post diff --git a/src/lua/endpoints/index_get.lua b/src/lua/endpoints/index_get.lua index 32ced5e..177da8c 100644 --- a/src/lua/endpoints/index_get.lua +++ b/src/lua/endpoints/index_get.lua @@ -7,6 +7,7 @@ local util = require("util") local config = require("config") local pages = require("pages") local libtags = require("tags") +local session = require("session") local stmnt_index, stmnt_author, stmnt_author_bio @@ -21,7 +22,7 @@ function configure(...) return oldconfigure(...) end -local function get_site_home(req) +local function get_site_home(req, loggedin) log(LOG_DEBUG,"Cache miss, rendering site index") stmnt_index:bind_names{} local latest = {} @@ -38,14 +39,17 @@ local function get_site_home(req) end return pages.index{ domain = config.domain, - stories = latest + stories = latest, + loggedin = loggedin } end local function get_author_home(req) + print("Looking at author home...") local host = http_request_get_host(req) local subdomain = host:match("([^\\.]+)") stmnt_author_bio:bind_names{author=subdomain} local err = util.do_sql(stmnt_author_bio) + local author, authorid = session.get(req) if err == sql.DONE then log(LOG_INFO,"No such author:" .. subdomain) stmnt_author_bio:reset() @@ -59,19 +63,35 @@ local function get_author_home(req) stmnt_author_bio:reset() stmnt_author:bind_names{author=subdomain} local stories = {} - for id, title, time, hits in util.sql_rows(stmnt_author) do - table.insert(stories,{ - url = util.encode_id(id), - title = title, - author=subdomain, - posted = os.date("%B %d %Y",tonumber(time)), - tags = libtags.get(id), - hits = hits, - }) + for id, title, time, hits, unlisted, hash in util.sql_rows(stmnt_author) do + print("Looking at:",id,title,time,hits,unlisted) + if unlisted == 1 and author == subdomain then + local url = util.encode_id(id) .. "?pwd=" .. util.encode_unlisted(hash) + table.insert(stories,{ + url = url, + title = title, + author=subdomain, + posted = os.date("%B %d %Y",tonumber(time)), + tags = libtags.get(id), + hits = hits, + unlisted = true, + }) + elseif unlisted == 0 then + table.insert(stories,{ + url = util.encode_id(id), + title = title, + author=subdomain, + posted = os.date("%B %d %Y",tonumber(time)), + tags = libtags.get(id), + hits = hits, + unlisted = false, + }) + end end return pages.author_index{ domain=config.domain, author=subdomain, + loggedin = author, stories=stories, bio=bio } @@ -82,19 +102,28 @@ local function index_get(req) local method = http_method_text(req) local host = http_request_get_host(req) local subdomain = host:match("([^\\.]+)") + local author, authorid = session.get(req) local text - if host == config.domain then + if host == config.domain and author == nil then --Default home page local cachepath = string.format("%s",config.domain) text = cache.render(cachepath, function() return get_site_home(req) end) - else + elseif host == config.domain and author then + --Display home page with "log out" button + text = cache.render(config.domain .. "-logout", function() + return get_site_home(req,true) + end) + elseif host ~= config.domain and author ~= subdomain then --author home page local cachepath = string.format("%s.%s",subdomain,config.domain) text = cache.render(cachepath, function() return get_author_home(req) end) + elseif host ~= config.domain and author == subdomain then + --author's home page for the author, don't cache, display unlisted + text = get_author_home(req) end assert(text) http_response(req,200,text) diff --git a/src/lua/endpoints/logout_get.lua b/src/lua/endpoints/logout_get.lua new file mode 100644 index 0000000..2361aed --- /dev/null +++ b/src/lua/endpoints/logout_get.lua @@ -0,0 +1,11 @@ +local session = require("session") +local config = require("config") + +local function logout(req) + local author, authorid = session.get(req) + session.finish(authorid) + http_response_header(req,"Location","https://" .. config.domain) + http_response(req,303,"") +end + +return logout diff --git a/src/lua/endpoints/paste_get.lua b/src/lua/endpoints/paste_get.lua index 5e46475..ba6cd49 100644 --- a/src/lua/endpoints/paste_get.lua +++ b/src/lua/endpoints/paste_get.lua @@ -13,6 +13,7 @@ local function paste_get(req) http_response(req,303,"") return elseif host == config.domain and author == nil then + print("doing anon paste") text = cache.render(string.format("%s/_paste",host),function() log(LOG_DEBUG, "Cache missing, rendering post page") return assert(pages.paste{ @@ -22,6 +23,7 @@ local function paste_get(req) end) http_response(req,200,text) elseif host ~= config.domain and author then + print("doing author paste") text = assert(pages.author_paste{ domain = config.domain, user = author, diff --git a/src/lua/endpoints/paste_post.lua b/src/lua/endpoints/paste_post.lua index 2283612..861d497 100644 --- a/src/lua/endpoints/paste_post.lua +++ b/src/lua/endpoints/paste_post.lua @@ -102,6 +102,7 @@ local function author_paste(req,ps) } end local asanon = assert(http_argument_get_string(req,"pasteas")) + local textsha3 = sha3(ps.text .. get_random_bytes(32)) --No need to check if the author is posting to the --"right" sudomain, just post it to the one they have --the session key for. @@ -111,12 +112,15 @@ local function author_paste(req,ps) assert(stmnt_paste:bind(4,asanon == "anonymous") == sql.OK) assert(stmnt_paste:bind_blob(5,"") == sql.OK) util.sqlbind(stmnt_paste,"bind",6,ps.unlisted) - util.sqlbind(stmnt_paste,"bind_blob",7,sha3(ps.text)) + util.sqlbind(stmnt_paste,"bind_blob",7,textsha3) err = util.do_sql(stmnt_paste) stmnt_paste:reset() if err == sql.DONE then local rowid = stmnt_paste:last_insert_rowid() local url = util.encode_id(rowid) + if ps.unlisted then + url = url .. "?pwd=" .. util.encode_unlisted(textsha3) + end assert(stmnt_raw:bind(1,rowid) == sql.OK) assert(stmnt_raw:bind_blob(2,ps.raw) == sql.OK) assert(stmnt_raw:bind(3,ps.markup) == sql.OK) diff --git a/src/lua/endpoints/read_get.lua b/src/lua/endpoints/read_get.lua index 26f1725..670dd97 100644 --- a/src/lua/endpoints/read_get.lua +++ b/src/lua/endpoints/read_get.lua @@ -41,8 +41,6 @@ local function populate_ps_story(req,ps) stmnt_read:bind_names{ id = ps.storyid, } - print("populating, hash was:",ps.hash) - stmnt_read:bind(2,ps.hash or "") local err = util.do_sql(stmnt_read) if err == sql.DONE then --We got no story @@ -53,9 +51,15 @@ local function populate_ps_story(req,ps) --If we've made it here, we have a story. Populate our settings --with title, text, ect. assert(err == sql.ROW) - local title, storytext, tauthor, isanon, authorname, views = unpack( + local title, storytext, tauthor, isanon, authorname, views, unlisted, hash = unpack( stmnt_read:get_values() ) + ps.unlisted = unlisted == 1 + if ps.unlisted and hash ~= ps.hash then + log(LOG_DEBUG,"Tried to get story id:" .. ps.storyid .. " but it was unlisted and hash was incorrect.") + stmnt_read:reset() + return false + end ps.title = title ps.text = zlib.decompress(storytext) ps.tauthor = tauthor @@ -101,7 +105,6 @@ local function read_get(req) ps.storyid = util.decode_id(ps.idp) add_view(ps.storyid) - --If we're logged in, set author and authorid local author, authorid = session.get(req) if author and authorid then @@ -119,12 +122,11 @@ local function read_get(req) --If this post is unlisted, get the hash local hashstr = http_argument_get_string(req,"pwd") - print("hashstr was:",hashstr) if hashstr then ps.hash = util.decode_unlisted(hashstr) + ps.hashstr = hashstr end - local text --normal story display if (not ps.loggedauthor) then diff --git a/src/lua/endpoints/read_post.lua b/src/lua/endpoints/read_post.lua index 2fde5ef..fed4730 100644 --- a/src/lua/endpoints/read_post.lua +++ b/src/lua/endpoints/read_post.lua @@ -24,6 +24,7 @@ local function read_post(req) local author, authorid = session.get(req) local comment_text = assert(http_argument_get_string(req,"text")) local pasteas = assert(http_argument_get_string(req,"postas")) + local hashstr = http_argument_get_string(req,"pwd") local idp = string.sub(path,2)--remove leading "/" local id = util.decode_id(idp) local isanon = 1 @@ -42,9 +43,10 @@ local function read_post(req) if err ~= sql.DONE then http_response(req,500,"Internal error, failed to post comment. Go back and try again.") else + local needspwd = hashstr and "&pwd=" .. hashstr or "" --When we post a comment, we need to dirty the cache for the "comments displayed" page. - cache.dirty(string.format("%s%s?comments=1",host,path)) - local redir = string.format("https://%s%s?comments=1", config.domain, path) + cache.dirty(string.format("%s%s?comments=1%s",host,path,needspwd)) + local redir = string.format("https://%s%s?comments=1%s", config.domain, path, needspwd) http_response_header(req,"Location",redir) http_response(req,303,"") end diff --git a/src/lua/init.lua b/src/lua/init.lua index 2a855bc..4eaeec4 100644 --- a/src/lua/init.lua +++ b/src/lua/init.lua @@ -29,6 +29,7 @@ local endpoint_names = { paste = {"get","post"}, download = {"get"}, login = {"get","post"}, + logout = {"get"}, edit = {"get","post"}, claim = {"get","post"}, search = {"get"}, @@ -102,6 +103,10 @@ function login(req) end end +function logout(req) + endpoints.logout_get(req) +end + --Edit a story function edit(req) local method = http_method_text(req) diff --git a/src/lua/session.lua b/src/lua/session.lua index cacfbeb..0860515 100644 --- a/src/lua/session.lua +++ b/src/lua/session.lua @@ -9,6 +9,7 @@ local stmnt_get_session, stmnt_insert_session function configure(...) stmnt_get_session = assert(db.conn:prepare(queries.select_valid_sessions)) stmnt_insert_session = assert(db.conn:prepare(queries.insert_session)) + stmnt_delete_session = assert(db.conn:prepare(queries.delete_session)) return oldconfigure(...) end @@ -61,4 +62,19 @@ function session.start(who) return session end +--[[ +End a session, log someone out +]] +function session.finish(who,sessionid) + stmnt_delete_session:bind_names{ + authorid = who, + sessionid = sessionid + } + local err = util.do_sql(stmnt_delete_session) + stmnt_delete_session:reset() + assert(err == sql.DONE) + return true + +end + return session diff --git a/src/pages/edit.etlua.in b/src/pages/edit.etlua.in index 617f515..b2f9382 100644 --- a/src/pages/edit.etlua.in +++ b/src/pages/edit.etlua.in @@ -6,7 +6,7 @@
- + +
+ + + checked + <% end %> + > + +
diff --git a/src/pages/parts/story_breif.etlua.in b/src/pages/parts/story_breif.etlua.in index 42193c2..98b97f1 100644 --- a/src/pages/parts/story_breif.etlua.in +++ b/src/pages/parts/story_breif.etlua.in @@ -1,5 +1,9 @@ + <% if unlisted then %> + ⛔ + <% end %> + <%- story.title %> diff --git a/src/pages/read.etlua.in b/src/pages/read.etlua.in index 2b71e14..94e692b 100644 --- a/src/pages/read.etlua.in +++ b/src/pages/read.etlua.in @@ -17,6 +17,12 @@ By <%= author %> <% end -%> +
    + <% for _,tag in pairs(tags) do -%> + <{system cat src/pages/parts/taglist.etlua}> + <% end -%> +
+ <%- text %> @@ -24,23 +30,26 @@

<%= views %> Hits

-
    - <% for _,tag in pairs(tags) do -%> - <{system cat src/pages/parts/taglist.etlua}> - <% end -%> -
- + <% if unlisted then %> + + <% end %> <% if not show_comments then -%>
+ <% if unlisted then %> + + <% end %>
<% else %>
+ <% if unlisted then %> + + <% end %>
<% if iam then %>