Get started on author biography.

Get started on implementing author biographies, add endpoints.
This commit is contained in:
Robin Malley 2022-09-02 23:24:39 +00:00
parent f5c729bfde
commit d5ec6d6864
9 changed files with 220 additions and 1 deletions

View File

@ -16,6 +16,11 @@ describe("smr type checking",function()
types.number(t)
end)
end)
it("should check multiple types passed as arugments", function()
local types = require("types")
local num, tbl = 5, {}
types.check(num, types.number, nil)
end)
end)

8
spec/utils.lua Normal file
View File

@ -0,0 +1,8 @@
function assertf(bool, ...)
if bool then return end
local args = {...}
local assertmsg = args[1] or "Assetion failed"
table.remove(args,1)
error(string.format(assertmsg, table.unpack(args)),2)
end

View File

@ -0,0 +1,69 @@
local zlib = require("zlib")
local sql = require("lsqlite3")
local db = require("db")
local queries = require("queries")
local util = require("util")
local pages = require("pages")
local tags = require("tags")
local session = require("session")
local config = require("config")
local stmnt_bio
local oldconfigure = configure
function configure(...)
stmnt_bio = assert(db.conn:prepare(queries.select_bio))
return oldconfigure(...)
end
local function bio_edit_get(req)
local host = http_request_get_host(req)
local path = http_request_get_path(req)
local author, authorid = session.get(req)
http_request_populate_qs(req)
local ret
if (not author) or (not authorid) then
ret = pages.error{
errcode = 401,
errcodemsg = "Not authorized",
explanation = "You must be logged in to edit your biography."
}
http_response(req,400,ret)
end
--Get the logged in author's bio to display
stmnt_bio:bind_names{
authorid = authorid
}
local err = util.do_sql(stmnt_edit)
if err == sql.DONE then
--No rows, we're logged in but an author with our id doesn't
--exist? Something has gone wrong.
ret = pages.error{
errcode = 500,
errcodemsg = "Server error",
explanation = string.format([[
Tried to get the biography of author %q (%d) but no author with that id was
found, please report this error.
]], author, authorid),
should_traceback=true
}
stmnt_bio:reset()
http_response(req,500,ret)
return
end
assert(err == sql.ROW)
local data = stmnt_bio:get_values()
local bio = unpack(data)
stmnt_bio:reset()
ret = pages.edit_bio{
text = bio,
user = author,
domain = config.domain,
}
http_response(req,200,ret)
end
return edit_get

View File

@ -0,0 +1,108 @@
local sql = require("lsqlite3")
local zlib = require("zlib")
local db = require("db")
local queries = require("queries")
local pages = require("pages")
local parsers = require("parsers")
local util = require("util")
local tagslib = require("tags")
local cache = require("cache")
local config = require("config")
local session = require("session")
local stmnt_update_bio
local oldconfigure = configure
function configure(...)
stmnt_update_bio = assert(db.conn:prepare(queries.update_bio))
return oldconfigure(...)
end
local function edit_post(req)
local host = http_request_get_host(req)
local path = http_request_get_path(req)
local author, author_id = session.get(req)
http_request_populate_post(req)
local storyid = tonumber(assert(http_argument_get_string(req,"story")))
local title = assert(http_argument_get_string(req,"title"))
local text = assert(http_argument_get_string(req,"text"))
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"
local tags_str = http_argument_get_string(req,"tags")
stmnt_author_of:bind_names{
id = storyid
}
local err = util.do_sql(stmnt_author_of)
if err ~= sql.ROW then
stmnt_author_of:reset()
local msg = string.format("No author found for story: %d", storyid)
log(LOG_ERR,msg)
local response = pages.error{
errcode = 404,
errcodemsg = "Not Found",
explanation = msg,
should_traceback = true,
}
http_response(req,404,response)
return
end
local data = stmnt_author_of:get_values()
stmnt_author_of:reset()
local realauthor = data[1]
assert(realauthor == author_id) --Make sure the author of the story is the currently logged in user
local parsed = parsers[markup](text)
local compr_raw = zlib.compress(text)
local compr = zlib.compress(parsed)
local tags = {}
if tags_str then
tags = util.parse_tags(tags_str)
end
assert(stmnt_update_raw:bind_blob(1,compr_raw) == sql.OK)
assert(stmnt_update_raw:bind(2,markup) == sql.OK)
assert(stmnt_update_raw:bind(3,storyid) == sql.OK)
assert(util.do_sql(stmnt_update_raw) == sql.DONE, "Failed to update raw")
stmnt_update_raw:reset()
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,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)
-- TODO: Remove this
-- Posts added before the unlisted feature will throw errors
-- when their hash is used to display them, or their url's.
-- when proper database migration tools are in place, remove
-- this bit of code.
if hash == -1 then
error("This post was created before the unlisting feature was added. Temporarily, this breaks. You will be able to unlist it in the future.")
end
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
cache.dirty(string.format("%s",config.domain)) -- The site index (ex, if the author changed the paste from their's to "Anonymous", the cache should reflect that).
cache.dirty(string.format("%s.%s",author,config.domain)) -- The author's index, same reasoning as above.
cache.dirty(string.format("%s-logout",config.domain))
http_response_header(req,"Location",loc)
http_response(req,303,"")
return
end
return edit_post

View File

@ -36,6 +36,7 @@ local endpoint_names = {
archive = {"get"},
api = {"get"},
delete = {"post"},
bio = {"get","post"},
}
local endpoints = {}
for name, methods in pairs(endpoint_names) do
@ -126,7 +127,12 @@ end
--TODO
function edit_bio()
local method = http_method_text(req)
if method == "GET" then
endpoints.bio_edit_get(req)
elseif method == "POST" then
error("Not yet implemented")
end
end
function teardown()

View File

@ -12,6 +12,7 @@
<% else %>
<a href="/_logout" class="button column column-0">Log out</a>
<% end %>
<a href="/_bio" class="button column column-0">Edit bio</a>
<span class="column column-0"></span>
<form action="https://<%= domain %>/_search" method="get" class="search column row">
<input class="column" type="text" name="q" placeholder="+greentext -dotr +hits>20"/>

View File

@ -0,0 +1,16 @@
<{system cat src/pages/parts/header.etlua}>
<h1 class="title">
Edit Biography for <%= user %>
</h1>
<% if err then %><em class="error"><%= err %></em><% end %>
<form action="https://<%= user %>.<%= domain %>/_bio" method="post" class="container">
<fieldset>
<input type="hidden" name="author" value="<%= user %>">
<div class="row">
<textarea name="text" cols=80 rows=24 class="column"><%= text %></textarea><br/>
</div>
<input type="submit">
</fieldset>
</form>
<{cat src/pages/parts/footer.etlua}>

View File

@ -0,0 +1,3 @@
SELECT biography
FROM authors
WHERE authors.id = :authorid;

3
src/sql/update_bio.sql Normal file
View File

@ -0,0 +1,3 @@
UPDATE authors
SET biography = ?
WHERE authors.id = ?;