Allow users to edit biographies
This commit is contained in:
parent
e25d2fd06a
commit
411bcb494d
36
README.md
36
README.md
|
@ -7,7 +7,25 @@ concerns with pastebin.com taking down certain kinds of content. SMR aims to
|
||||||
be small, fast, and secure. It is built on top of [Kore](https://kore.io), using
|
be small, fast, and secure. It is built on top of [Kore](https://kore.io), using
|
||||||
[luajit](https://luajit.org) to expose a Lua programming environment. It uses
|
[luajit](https://luajit.org) to expose a Lua programming environment. It uses
|
||||||
[sqlite3](https://sqlite.org) as it's database. SMR is implemented in about
|
[sqlite3](https://sqlite.org) as it's database. SMR is implemented in about
|
||||||
3.5k SLOC and is expected to never exceed 5k SLOC. Contributions welcome.
|
4k SLOC and is expected to never exceed 5k SLOC. Contributions welcome.
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
Language files blank comment code
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
Lua 36 190 306 1993
|
||||||
|
C 4 61 116 709
|
||||||
|
HTML 18 21 0 561
|
||||||
|
SQL 36 6 35 266
|
||||||
|
JavaScript 3 19 21 203
|
||||||
|
CSS 3 4 8 73
|
||||||
|
C/C++ Header 4 3 0 46
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
SUM: 104 304 486 3851
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
## Roadmap
|
## Roadmap
|
||||||
|
|
||||||
|
@ -15,13 +33,21 @@ be small, fast, and secure. It is built on top of [Kore](https://kore.io), using
|
||||||
* Comments (complete)
|
* Comments (complete)
|
||||||
* Tags (complete)
|
* Tags (complete)
|
||||||
* Search (complete)
|
* Search (complete)
|
||||||
* Archive (in progress)
|
* Archive (complete)
|
||||||
* Author biographies
|
* Author biographies (complete)
|
||||||
* Kore 4.2.0
|
* Kore 4.2.0 (complete)
|
||||||
|
* addon api
|
||||||
|
|
||||||
TODO's:
|
TODO's:
|
||||||
Currently, people can post comments to unlisted stories even if they don't have
|
|
||||||
|
* Currently, people can post comments to unlisted stories even if they don't have
|
||||||
the correct link.
|
the correct link.
|
||||||
|
* Find a replacement preprocessor
|
||||||
|
* The archive is currently generated weekly from a cron job, and served
|
||||||
|
syncronously. We can generate a zip file on-the-fly instead, and if the client
|
||||||
|
disconnects, it's fine to drop the whole thing.
|
||||||
|
* We can simplify a lot of error handling logic by setting sql prepared statements to reset during error unwinding.
|
||||||
|
* We can simplify a lot of business logic by having requests parse their parameters eagerly.
|
||||||
|
|
||||||
## Hacking
|
## Hacking
|
||||||
|
|
||||||
|
|
|
@ -127,6 +127,7 @@ domain * {
|
||||||
methods get post
|
methods get post
|
||||||
|
|
||||||
validate post text v_any
|
validate post text v_any
|
||||||
|
validate post author v_subdomain
|
||||||
}
|
}
|
||||||
|
|
||||||
route /_login {
|
route /_login {
|
||||||
|
|
|
@ -30,7 +30,7 @@ local function bio_edit_get(req)
|
||||||
errcodemsg = "Not authorized",
|
errcodemsg = "Not authorized",
|
||||||
explanation = "You must be logged in to edit your biography."
|
explanation = "You must be logged in to edit your biography."
|
||||||
}
|
}
|
||||||
http_response(req,400,ret)
|
http_response(req,401,ret)
|
||||||
end
|
end
|
||||||
|
|
||||||
--Get the logged in author's bio to display
|
--Get the logged in author's bio to display
|
||||||
|
@ -56,7 +56,7 @@ found, please report this error.
|
||||||
end
|
end
|
||||||
assert(err == sql.ROW)
|
assert(err == sql.ROW)
|
||||||
local data = stmnt_bio:get_values()
|
local data = stmnt_bio:get_values()
|
||||||
local bio = unpack(data)
|
local bio = zlib.decompress(data[1])
|
||||||
stmnt_bio:reset()
|
stmnt_bio:reset()
|
||||||
ret = pages.edit_bio{
|
ret = pages.edit_bio{
|
||||||
text = bio,
|
text = bio,
|
||||||
|
|
|
@ -27,16 +27,17 @@ local function edit_bio(req)
|
||||||
|
|
||||||
http_request_populate_post(req)
|
http_request_populate_post(req)
|
||||||
local text = assert(http_argument_get_string(req,"text"))
|
local text = assert(http_argument_get_string(req,"text"))
|
||||||
local markup = assert(http_argument_get_string(req,"markup"))
|
|
||||||
|
|
||||||
local parsed = parsers[markup](text)
|
local parsed = parsers.plain(text) -- Make sure the plain parser can deal with it, even though we don't store this result.
|
||||||
local compr_raw = zlib.compress(text)
|
local compr_raw = zlib.compress(text)
|
||||||
local compr = zlib.compress(parsed)
|
local compr = zlib.compress(parsed)
|
||||||
|
|
||||||
assert(stmnt_update_bio:bind_blob(1,compr_raw) == sql.OK)
|
assert(stmnt_update_bio:bind_blob(1,compr_raw) == sql.OK)
|
||||||
assert(stmnt_update_bio:bind(2, author_id) == sql.OK)
|
assert(stmnt_update_bio:bind(2, author_id) == sql.OK)
|
||||||
assert(util.do_sql(stmnt_update_bio) == sql.DONE, "Failed to update biography")
|
if util.do_sql(stmnt_update_bio) ~= sql.DONE then
|
||||||
stmnt_update_bio:reset()
|
stmnt_update_bio:reset()
|
||||||
|
error("Faled to update biography")
|
||||||
|
end
|
||||||
local loc = string.format("https://%s.%s",author,config.domain)
|
local loc = string.format("https://%s.%s",author,config.domain)
|
||||||
-- Dirty the cache for the author's index, the only place where the bio is displayed.
|
-- Dirty the cache for the author's index, the only place where the bio is displayed.
|
||||||
cache.dirty(string.format("%s.%s",author,config.domain))
|
cache.dirty(string.format("%s.%s",author,config.domain))
|
||||||
|
@ -45,4 +46,4 @@ local function edit_bio(req)
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
return edit_post
|
return edit_bio
|
||||||
|
|
|
@ -8,6 +8,7 @@ local config = require("config")
|
||||||
local pages = require("pages")
|
local pages = require("pages")
|
||||||
local libtags = require("tags")
|
local libtags = require("tags")
|
||||||
local session = require("session")
|
local session = require("session")
|
||||||
|
local parsers = require("parsers")
|
||||||
|
|
||||||
local stmnt_index, stmnt_author, stmnt_author_bio
|
local stmnt_index, stmnt_author, stmnt_author_bio
|
||||||
|
|
||||||
|
@ -57,9 +58,12 @@ local function get_author_home(req, loggedin)
|
||||||
author = subdomain
|
author = subdomain
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
assert(err == sql.ROW,"failed to get author:" .. subdomain .. " error:" .. tostring(err))
|
if err ~= sql.ROW then
|
||||||
|
stmnt_author_bio:reset()
|
||||||
|
error(string.format("Failed to get author %q error: %q",subdomain, tostring(err)))
|
||||||
|
end
|
||||||
local data = stmnt_author_bio:get_values()
|
local data = stmnt_author_bio:get_values()
|
||||||
local bio = data[1]
|
local bio = parsers.plain(zlib.decompress(data[1]))
|
||||||
stmnt_author_bio:reset()
|
stmnt_author_bio:reset()
|
||||||
stmnt_author:bind_names{author=subdomain}
|
stmnt_author:bind_names{author=subdomain}
|
||||||
local stories = {}
|
local stories = {}
|
||||||
|
|
|
@ -96,11 +96,14 @@ for funcname, spec in pairs({
|
||||||
assert(_G[funcname] == nil, "Tried to overwrite an endpoint, please define endpoints exactly once")
|
assert(_G[funcname] == nil, "Tried to overwrite an endpoint, please define endpoints exactly once")
|
||||||
for k,v in pairs(spec) do
|
for k,v in pairs(spec) do
|
||||||
assert(http_m_rev[k], "Unknown http method '" .. k .. "' defined for endpoint '" .. funcname .. "'")
|
assert(http_m_rev[k], "Unknown http method '" .. k .. "' defined for endpoint '" .. funcname .. "'")
|
||||||
|
assert(type(v) == "function", "Endpoint %s %s must be a function, but was a %s",funcname, k, type(v))
|
||||||
end
|
end
|
||||||
_G[funcname] = function(req)
|
_G[funcname] = function(req)
|
||||||
local method = http_method_text(req)
|
local method = http_method_text(req)
|
||||||
if spec[method] == nil then
|
if spec[method] == nil then
|
||||||
log(LOG_NOTICE,string.format("Endpoint %s called with http method %s, but no such route defined.", funcname, method))
|
log(LOG_WARNING,string.format("Endpoint %s called with http method %s, but no such route defined.", funcname, method))
|
||||||
|
else
|
||||||
|
log(LOG_DEBUG,string.format("Endpoint %s called with method %s",funcname,method))
|
||||||
end
|
end
|
||||||
spec[method](req)
|
spec[method](req)
|
||||||
end
|
end
|
||||||
|
|
|
@ -11,8 +11,8 @@
|
||||||
<a href="/_login" class="button column column-0">Log in</a>
|
<a href="/_login" class="button column column-0">Log in</a>
|
||||||
<% else %>
|
<% else %>
|
||||||
<a href="/_logout" class="button column column-0">Log out</a>
|
<a href="/_logout" class="button column column-0">Log out</a>
|
||||||
<% end %>
|
|
||||||
<a href="/_bio" class="button column column-0">Edit bio</a>
|
<a href="/_bio" class="button column column-0">Edit bio</a>
|
||||||
|
<% end %>
|
||||||
<span class="column column-0"></span>
|
<span class="column column-0"></span>
|
||||||
<form action="https://<%= domain %>/_search" method="get" class="search column row">
|
<form action="https://<%= domain %>/_search" method="get" class="search column row">
|
||||||
<input class="column" type="text" name="q" placeholder="+greentext -dotr +hits>20"/>
|
<input class="column" type="text" name="q" placeholder="+greentext -dotr +hits>20"/>
|
||||||
|
@ -20,8 +20,8 @@
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="content">
|
<div class="container">
|
||||||
<%= bio %>
|
<%- bio %>
|
||||||
</div>
|
</div>
|
||||||
<div class="content">
|
<div class="content">
|
||||||
<% if #stories == 0 then %>
|
<% if #stories == 0 then %>
|
||||||
|
|
|
@ -9,7 +9,9 @@
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<textarea name="text" cols=80 rows=24 class="column"><%= text %></textarea><br/>
|
<textarea name="text" cols=80 rows=24 class="column"><%= text %></textarea><br/>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="row">
|
||||||
<input type="submit">
|
<input type="submit">
|
||||||
|
</div>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
</form>
|
</form>
|
||||||
<{cat src/pages/parts/footer.etlua}>
|
<{cat src/pages/parts/footer.etlua}>
|
||||||
|
|
Loading…
Reference in New Issue