2018-04-23 12:00:42 +00:00
|
|
|
import Application from require "lapis"
|
2018-04-23 13:15:44 +00:00
|
|
|
import assert_valid from require "lapis.validate"
|
2018-05-02 00:22:22 +00:00
|
|
|
import unescape from require "lapis.util"
|
2018-04-23 13:15:44 +00:00
|
|
|
|
2018-04-24 03:19:34 +00:00
|
|
|
import APIKeys, Users, Tasks from require "models"
|
2018-04-25 00:32:08 +00:00
|
|
|
import locate from require "locator"
|
2018-05-11 21:12:44 +00:00
|
|
|
import request, abort, assert_model from locate "helpers.api"
|
2018-04-23 12:00:42 +00:00
|
|
|
-- import random from locate "calc"
|
|
|
|
-- import escape_similar_to from locate "db"
|
|
|
|
|
2018-04-25 02:08:59 +00:00
|
|
|
get_task = =>
|
2018-05-02 00:15:46 +00:00
|
|
|
unless @params.content or tonumber @params.id
|
2018-05-02 00:22:22 +00:00
|
|
|
@params.content = unescape(@params.id)
|
2018-05-02 00:15:46 +00:00
|
|
|
@params.id = nil
|
2018-04-25 02:08:59 +00:00
|
|
|
if @params.id
|
|
|
|
assert_valid @params, {
|
|
|
|
{"id", exists: true, min_length: 1, "Attempted to select by task id, but no id specified."}
|
2018-05-01 22:41:08 +00:00
|
|
|
{"id", is_integer: true, "Task id specified is not an integer."}
|
2018-04-25 02:08:59 +00:00
|
|
|
}
|
2018-05-02 00:15:46 +00:00
|
|
|
@task = assert_model Tasks\find id: tonumber(@params.id), user_id: @user.id
|
2018-04-25 02:08:59 +00:00
|
|
|
elseif @params.content
|
|
|
|
assert_valid @params, {
|
|
|
|
{"content", exists: true, min_length: 1, "Attempted to select by task content, but no content specified."}
|
|
|
|
}
|
2018-05-01 22:41:08 +00:00
|
|
|
@task = assert_model Tasks\find content: @params.content, user_id: @user.id
|
2018-04-25 02:08:59 +00:00
|
|
|
else
|
|
|
|
abort "Task id or content not specified."
|
|
|
|
|
|
|
|
abort 404, "Invalid task specified." unless @task
|
|
|
|
|
2018-05-02 00:15:46 +00:00
|
|
|
set_bool = (name) =>
|
|
|
|
if @params[name] == "true"
|
|
|
|
@params[name] = true
|
|
|
|
elseif @params[name] == "false"
|
|
|
|
@params[name] = false
|
|
|
|
if @params[name] != nil and "boolean" != type @params[name]
|
|
|
|
abort "#{name} must be true/false only."
|
|
|
|
|
|
|
|
send_task = =>
|
|
|
|
@write json: { success: true, task: @task }
|
|
|
|
|
2018-04-23 12:00:42 +00:00
|
|
|
class API extends Application
|
|
|
|
@path: "/v1"
|
|
|
|
@name: "api_"
|
|
|
|
|
2018-05-11 21:12:44 +00:00
|
|
|
@before_filter( request =>
|
2018-04-25 01:43:07 +00:00
|
|
|
return if @user
|
|
|
|
if auth = @req.headers["authorization"]
|
|
|
|
if auth\len! > 0
|
|
|
|
@params.api_key = auth
|
2018-04-25 02:08:59 +00:00
|
|
|
abort "Auth: api_key not specified." unless @params.api_key
|
2018-04-23 12:00:42 +00:00
|
|
|
@api_key = APIKeys\find key: @params.api_key
|
2018-04-25 02:08:59 +00:00
|
|
|
abort "Auth: Invalid api_key." unless @api_key
|
2018-04-24 03:19:34 +00:00
|
|
|
@user = Users\find id: @api_key.user_id
|
2018-04-25 02:08:59 +00:00
|
|
|
abort "Auth: Invalid api_key." unless @user -- NOTE this should also delete the api_key and error (this should never happen!)
|
2018-04-23 12:00:42 +00:00
|
|
|
)
|
|
|
|
|
2018-05-11 21:12:44 +00:00
|
|
|
[action: "/:action(/:id)"]: request =>
|
2018-05-02 00:15:46 +00:00
|
|
|
switch @params.action
|
|
|
|
when "new"
|
|
|
|
unless @params.content or tonumber @params.id
|
2018-05-02 00:23:41 +00:00
|
|
|
@params.content = unescape(@params.id)
|
2018-05-02 00:15:46 +00:00
|
|
|
assert_valid @params, { {"content", exists: true, min_length: 1, "Task content not specified."} }
|
|
|
|
@task = assert_model Tasks\create user_id: @user.id, content: @params.content
|
|
|
|
send_task(@)
|
|
|
|
when "get", "do", "undo", "edit", "delete"
|
|
|
|
get_task(@)
|
|
|
|
else
|
|
|
|
abort "Invalid action: #{@params.action}"
|
|
|
|
|
|
|
|
switch @params.action
|
|
|
|
when "do"
|
|
|
|
@task = assert_model @task\update done: true
|
|
|
|
when "undo"
|
|
|
|
@task = assert_model @task\update done: false
|
|
|
|
when "edit"
|
|
|
|
assert_valid @params, {
|
|
|
|
{"new_content", exists: true, min_length: 1, optional: true, "Cannot set no content on a task."}
|
|
|
|
}
|
|
|
|
set_bool(@, "done")
|
|
|
|
@task = assert_model @task\update content: @params.new_content, done: @params.done
|
|
|
|
when "delete"
|
|
|
|
if @task\delete!
|
|
|
|
return json: { success: true }
|
|
|
|
else
|
|
|
|
abort 500, "Error deleting task."
|
|
|
|
|
|
|
|
send_task(@)
|
2018-04-24 03:19:34 +00:00
|
|
|
|
|
|
|
|
2018-04-25 02:44:46 +00:00
|
|
|
|
2018-05-11 21:12:44 +00:00
|
|
|
[list: "/list"]: request =>
|
2018-04-24 03:19:34 +00:00
|
|
|
assert_valid @params, {
|
|
|
|
{"count", exists: true, is_integer: true, optional: true, "Count is not an integer."}
|
|
|
|
{"done", exists: true, one_of: {true, false}, optional: true, "Done is not a boolean."}
|
|
|
|
{"page", exists: true, is_integer: true, optional: true, "Page is not an integer."}
|
|
|
|
{"order", exists: true, one_of: {"asc", "desc"}, optional: true, "Invalid order. (Must be 'asc' or 'desc'.)"}
|
|
|
|
}
|
2018-05-02 00:15:46 +00:00
|
|
|
@params.count = tonumber @params.count
|
2018-04-24 03:19:34 +00:00
|
|
|
@params.count or= 50
|
2018-05-02 00:15:46 +00:00
|
|
|
@params.page = tonumber @params.page
|
2018-04-24 03:19:34 +00:00
|
|
|
@params.page or= 1
|
2018-04-24 17:02:51 +00:00
|
|
|
@params.order or= "asc"
|
2018-05-01 22:41:08 +00:00
|
|
|
@params.page = 1 if @params.page < 1
|
2018-04-24 03:19:34 +00:00
|
|
|
|
|
|
|
local Paginator
|
|
|
|
if @params.done == nil
|
2018-04-25 05:20:16 +00:00
|
|
|
Paginator = Tasks\paginated "WHERE user_id = ? ORDER BY created_at #{@params.order}", @user.id, per_page: @params.count
|
2018-04-24 03:19:34 +00:00
|
|
|
else
|
2018-05-02 00:15:46 +00:00
|
|
|
set_bool(@, "done")
|
2018-04-25 05:20:16 +00:00
|
|
|
Paginator = Tasks\paginated "WHERE user_id = ? AND done = ? ORDER BY created_at #{@params.order}", @user.id, @params.done, per_page: @params.count
|
2018-04-24 03:19:34 +00:00
|
|
|
|
|
|
|
num_pages = Paginator\num_pages!
|
|
|
|
if num_pages < @params.page
|
|
|
|
@params.page = num_pages
|
|
|
|
tasks = Paginator\get_page(@params.page)
|
|
|
|
|
2018-05-02 00:15:46 +00:00
|
|
|
-- returns page in case it returned a different page than you asked for! (in the case you ask for an out-of-range page)
|
2018-04-25 05:20:16 +00:00
|
|
|
return json: { success: true, page: @params.page, pages: num_pages, :tasks }
|
2018-04-24 03:19:34 +00:00
|
|
|
|
2018-05-02 00:15:46 +00:00
|
|
|
|
|
|
|
|
2018-05-11 21:12:44 +00:00
|
|
|
[random: "/random"]: request =>
|
2018-05-01 22:41:08 +00:00
|
|
|
-- assert_valid @params, {
|
|
|
|
-- {"count", exists: true, is_integer: true, optional: true, "Count is not an integer."}
|
|
|
|
-- {"done", exists: true, one_of: {true, false}, optional: true, "Done is not a boolean."}
|
|
|
|
-- }
|
|
|
|
-- @params.count or= 1
|
|
|
|
-- @params.done = false if @params.done == nil
|
2018-04-25 05:02:41 +00:00
|
|
|
|
|
|
|
abort 501, "Not implemented."
|
|
|
|
|
|
|
|
-- possibly need to store how many items each user has and use a different strategy for users with low amounts vs high amounts
|
|
|
|
-- key = get_key(@)
|
|
|
|
--
|
|
|
|
-- local tasks
|
|
|
|
-- if @params.done
|
|
|
|
-- offset = random Tasks\count "user_id = ? AND done = ? ORDER BY id ASC", key.user_id, @params.done
|
|
|
|
-- tasks = Tasks\select "WHERE user_id = ? AND done = ? ORDER BY id ASC OFFSET ? LIMIT 1", key.user_id, @params.done, offset
|
|
|
|
-- else
|
|
|
|
-- offset = random Tasks\count "user_id = ? ORDER BY id ASC", key.user_id
|
|
|
|
-- tasks = Tasks\select "WHERE user_id = ? ORDER BY id ASC OFFSET ? LIMIT 1", key.user_id, offset
|
|
|
|
--
|
|
|
|
-- if tasks and #tasks == 1
|
|
|
|
-- return json: { success: true, task: tasks[1] }
|
|
|
|
-- else
|
|
|
|
-- abort!
|
|
|
|
|
2018-05-11 21:12:44 +00:00
|
|
|
[new_key: "/key/new"]: request =>
|
2018-05-01 22:41:08 +00:00
|
|
|
api_key = assert_model APIKeys\create(@user)
|
2018-04-25 01:33:18 +00:00
|
|
|
return json: { success: true, :api_key }
|
2018-04-24 22:56:40 +00:00
|
|
|
|
2018-05-11 21:12:44 +00:00
|
|
|
[delete_key: "/key/delete(/:key)"]: request =>
|
2018-04-25 02:08:59 +00:00
|
|
|
if @params.id
|
2018-05-02 00:15:46 +00:00
|
|
|
abort "api_key IDs do not exist anymore (sorry!)." -- no one should ever run into this
|
2018-04-25 02:08:59 +00:00
|
|
|
elseif @params.key
|
|
|
|
assert_valid @params, {
|
|
|
|
{"key", exists: true, min_length: 32, max_length: 32, "Invalid api_key specified."}
|
|
|
|
}
|
2018-05-01 22:41:08 +00:00
|
|
|
@key_to_delete = assert_model APIKeys\find key: @params.key, user_id: @user.id
|
2018-04-25 02:08:59 +00:00
|
|
|
else
|
2018-05-02 00:15:46 +00:00
|
|
|
abort "No api_key specified."
|
2018-04-25 02:08:59 +00:00
|
|
|
|
|
|
|
abort 404, "Invalid api_key specified." unless @key_to_delete
|
|
|
|
if @key_to_delete\delete!
|
|
|
|
return json: { success: true }
|
|
|
|
else
|
|
|
|
abort 500, "Error deleting api_key."
|