Compare commits

...

10 Commits

Author SHA1 Message Date
Paul Liverman III
c28c4a00b7 rename api helper 2018-05-11 14:12:44 -07:00
Paul Liverman III
0433e71560 configs updated for githook 2018-05-11 13:55:52 -07:00
Paul Liverman III
73ce07dc01 Merge commit '1968f5e88ed0cc59f5db07be1d162b12120d7f96' as 'applications/githook' 2018-05-11 13:51:27 -07:00
Paul Liverman III
1968f5e88e Squashed 'applications/githook/' content from commit 853c905
git-subtree-dir: applications/githook
git-subtree-split: 853c905433ef1ecd7d9ea4b1f6fd6f73f28d7b20
2018-05-11 13:51:27 -07:00
Paul Liverman III
8463fc218d rm githook test 2018-05-11 13:40:27 -07:00
Paul Liverman III
f2b05fde71 temporary testing of webhook sent by Gitea 2018-05-11 13:32:23 -07:00
Paul Liverman III
87cf00673c notes 2018-05-01 21:36:00 -07:00
Paul Liverman III
695306a242 fixed minor inconsistency in main layout 2018-05-01 18:59:46 -07:00
Paul Liverman III
d859a94280 update logged out view, prettier formatting 2018-05-01 18:58:25 -07:00
Paul Liverman III
44e7a33d7d update logged out view 2018-05-01 18:56:10 -07:00
14 changed files with 349 additions and 16 deletions

45
api notes Normal file
View File

@ -0,0 +1,45 @@
/random/:id ?
- id specified for random is currently undefined, but will be used to get a random from a list id/name
/list/:page
- id specified for list is currently undefined, but will be used to get via list ids/names
---- new stuff to do with multiple lists:
lists {
id: serial
user_id: user this belongs to!
parent_id: another list, optional
name: when generated, make a slug, if slug is not unique, append a number and try again (incrementing number until a new unique slug is found)
slug: based on name, uniqueness required (enforced behind the scenes by name, unless explicitly given (in which case, must meet constraints and not exist already))
timestamp
}
tasks -> {
list_id: optional foreign key
parent_id: optional foreign key (to a task!)
}
/new -> option to add list_id or parent_id or parent_content or list_name
/edit -> option to add / remove same things
/list -> option to only select from same things
- deprecate /list and use /get for its options!
/random -> option to only select from same things
/get -> option to get from list / parent via id/content/name
/list/new/:name -> create a list
/list/get/:nameORslugORid -> get a list
/list/do/:nameORslugORid -> mark everything on a list done (alternately, lists themselves can have seperate done values!!)
/list/undo/:nameORslugORid ->
/list/edit/:nameORslugORid ->
/list/delete/:nameORslugORid -> all tasks are deleted or are removed from list to either its parent, or no list (depending on options sent)
/list/parent -> get parent list
/list/children -> get children lists
/parent -> get parent task
/children -> get children tasks
/list(/:id_or_slug)(/:page) --- ?

View File

@ -12,6 +12,7 @@ class Simplex extends Application
layout: main
@include locate "githook"
@include locate "users"
@include locate "api"
@include locate "docs"

View File

@ -4,7 +4,7 @@ import unescape from require "lapis.util"
import APIKeys, Users, Tasks from require "models"
import locate from require "locator"
import api_request, abort, assert_model from locate "helpers.api"
import request, abort, assert_model from locate "helpers.api"
-- import random from locate "calc"
-- import escape_similar_to from locate "db"
@ -43,7 +43,7 @@ class API extends Application
@path: "/v1"
@name: "api_"
@before_filter( api_request =>
@before_filter( request =>
return if @user
if auth = @req.headers["authorization"]
if auth\len! > 0
@ -55,7 +55,7 @@ class API extends Application
abort "Auth: Invalid api_key." unless @user -- NOTE this should also delete the api_key and error (this should never happen!)
)
[action: "/:action(/:id)"]: api_request =>
[action: "/:action(/:id)"]: request =>
switch @params.action
when "new"
unless @params.content or tonumber @params.id
@ -89,7 +89,7 @@ class API extends Application
[list: "/list"]: api_request =>
[list: "/list"]: request =>
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."}
@ -120,7 +120,7 @@ class API extends Application
[random: "/random"]: api_request =>
[random: "/random"]: request =>
-- 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."}
@ -146,11 +146,11 @@ class API extends Application
-- else
-- abort!
[new_key: "/key/new"]: api_request =>
[new_key: "/key/new"]: request =>
api_key = assert_model APIKeys\create(@user)
return json: { success: true, :api_key }
[delete_key: "/key/delete(/:key)"]: api_request =>
[delete_key: "/key/delete(/:key)"]: request =>
if @params.id
abort "api_key IDs do not exist anymore (sorry!)." -- no one should ever run into this
elseif @params.key

1
applications/githook/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
*.lua

View File

@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) 2016-2018 Paul Liverman III
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@ -0,0 +1,55 @@
## Installation
(Note: I'm going to rewrite this to explain how to use with locator, a simple
server locator I designed for use with Lapis and these sub-applications.)
Dependencies:
- Lapis (duh)
- MoonScript
- OpenResty user needs a bash shell (ch -s /bin/bash user)
From the shell:
```bash
git subtree add --prefix githook https://github.com/lazuscripts/githook.git master --squash
```
(`--prefix` specifies where it will be saved.)
Alternately, you can add it as a remote for easier maintenance:
```bash
git remote add -f githook https://github.com/lazuscripts/githook.git
git subtree add --prefix githook githook master --squash
```
From your main application class: `@include "githook.githook"` (or wherever you put it)
### Updating
From the shell:
```bash
git subtree pull --prefix githook https://github.com/lazuscripts/githook.git master --squash
```
Or, if it is set up as remote:
```bash
git subtree pull --prefix githook githook master --squash
```
## Config
All configuration is optional. Without configuration, will attempt to update any
time it is visited.
- `githook_branch "branch"` which branch you want updating (as string)
(to prevent updates triggering when pushing unrelated branches)
- `githook_secret "secret"` the secret string used on GitHub
Will attempt to checkout, pull, update submodules if needed, compile all code,
then run migrations, and finally update the running server without interruption.
Returns a log along with exit codes on success or failure.

View File

@ -0,0 +1,152 @@
lapis = require "lapis"
config = require("lapis.config").get!
import respond_to, json_params from require "lapis.application"
import hmac_sha1, hmac_sha256 from require "lapis.util.encoding"
import encode from require "cjson"
import GithookLogs from require "models"
import locate, autoload, registry from require "locator"
import settings from autoload "utility"
import execute from locate "utility.shell"
import insert, concat from table
const_compare = (string1, string2) ->
local fail, dummy
for i = 1, math.max #string1, #string2, 100
if string1\sub(i,i) ~= string2\sub(i,i)
fail = true
else
dummy = true -- attempting to make execution time equal
return not fail
hex_dump = (str) ->
len = string.len str
hex = ""
for i = 1, len
hex ..= string.format( "%02x", string.byte( str, i ) )
return hex
run_update = (branch) ->
exit_codes, logs = {}, {}
failure = false
commands = registry.githook_commands branch, config._name
unless commands
commands = {
{"git checkout #{branch} 2> /dev/stdout"}
{"git pull origin 2> /dev/stdout"}
{"git submodule init 2> /dev/stdout"}
{"git submodule update 2> /dev/stdout"}
{"code=0\nfor file in $(find . -type f -name \"*.moon\"); do moonc \"$file\" 2> /dev/stdout\ntmp=$?\nif [ ! $tmp -eq 0 ]; then code=$tmp\nfi; done\necho $code", false}
{"lapis migrate #{config._name} 2> /dev/stdout"}
{"lapis build #{config._name} 2> /dev/stdout"}
}
for cmd in *commands
code, output = execute unpack cmd
insert exit_codes, code
insert logs, cmd[1]
insert logs, " #{output\gsub "\n", "\n "}"
if code != 0
failure = true
break
log = concat logs, "\n"
if failure
if settings["githook.save_logs"]
GithookLogs\create {
success: false
exit_codes: encode exit_codes
:log
}
return status: 500, json: {
status: "failure"
message: "a subprocess returned a non-zero exit code"
:log
:exit_codes
}
else
if settings["githook.save_logs"] and settings["githook.save_on_success"]
GithookLogs\create {
exit_codes: encode exit_codes
:log
}
elseif settings["githook.save_logs"]
GithookLogs\create! -- we still record WHEN there was a success
return status: 200, json: {
status: "success"
message: "server updated to latest version of '#{branch}'"
:log
:exit_codes
}
ignored = (branch) ->
return status: 200, json: {
status: "success"
message: "ignored push (looking for updates to '#{branch}')"
}
unauthorized = ->
return status: 401, json: {
status: "unauthorized",
message: "invalid credentials or no credentials were sent"
}
invalid = (reason) ->
return status: 400, json: {
status: "invalid request"
message: reason
}
class extends lapis.Application
[githook: "/githook"]: respond_to {
before: =>
@branch = config.githook_branch or settings["githook.branch"] or "master"
GET: =>
unless settings["githook.allow_get"]
return status: 405, json: {
status: "method not allowed",
message: "Githook is not accepting GET requests."
}
unless settings["githook.run_without_auth"]
return unauthorized!
@results = run_update(@branch)
return render: locate "views.githook_get"
POST: json_params =>
secret = config.githook_secret or settings["githook.secret"]
if secret
ngx.req.read_body!
if body = ngx.req.get_body_data!
local authorized
if github_hash = @req.headers["X-Hub-Signature"]
authorized = const_compare "sha1=#{hex_dump hmac_sha1 secret, body}", github_hash
elseif gogs_hash = @req.headers["X-Gogs-Signature"]
authorized = const_compare gogs_hash, hex_dump hmac_sha256 secret, body
elseif @params.secret
authorized = const_compare @params.secret, secret
unless authorized
return unauthorized!
if @params.ref == "refs/heads/#{@branch}"
return run_update(@branch)
elseif @params.ref == nil
return invalid "'ref' not defined in request body"
else
return ignored(@branch)
else
return invalid "no request body"
elseif settings["githook.run_without_auth"]
if @params.ref == "refs/heads/#{@branch}"
return run_update(@branch)
else
return ignored(@branch)
else
return unauthorized!
}

View File

@ -0,0 +1,25 @@
import create_table, types, create_index from require "lapis.db.schema"
import autoload from require "locator"
import settings from autoload "utility"
{
[1519992142]: =>
create_table "githook_logs", {
{"id", types.serial primary_key: true}
{"success", types.boolean default: true}
{"exit_codes", types.text null: true}
{"log", types.text null: true}
{"created_at", types.time}
{"updated_at", types.time}
}
create_index "githook_logs", "id", unique: true
create_index "githook_logs", "success"
settings["githook.save_logs"] = true
settings["githook.save_on_success"] = true
settings["githook.allow_get"] = true
settings["githook.run_without_auth"] = false
-- settings["githook.branch"] = "master"
settings.save!
}

View File

@ -0,0 +1,4 @@
import Model from require "lapis.db.model"
class GithookLogs extends Model
@timestamp: true

View File

@ -0,0 +1,10 @@
import Widget from require "lapis.html"
class extends Widget
content: =>
h2 "#{@results.json.status\sub(1, 1)\upper!}#{@results.json.status\sub 2}"
element "table", ->
tr ->
for code in *@results.json.exit_codes
th code
pre @results.json.log

View File

@ -2,7 +2,7 @@ import json_params, capture_errors, yield_error from require "lapis.application"
import insert, remove from table
import max from math
api_request = (fn) ->
request = (fn) ->
json_params capture_errors {
fn,
on_error: =>
@ -28,7 +28,7 @@ assert_model = (result, err) ->
return result
{
:api_request
:request
:abort
:assert_model
}

View File

@ -20,7 +20,7 @@ class extends Widget
link rel: "stylesheet", href: "/static/main.css"
body ->
div class: "container", ->
h1(@title or "Simplex")
h1(@title or "Simplex Task Manager")
div class: "row", ->
div class: "column btns", ->
if @user

View File

@ -6,12 +6,19 @@
fetch: "https://github.com/lazuscripts/users"
}
}
{
path: "applications.githook"
remote: {
name: "githook"
fetch: "https://github.com/lazuscripts/githook"
}
}
{
path: "applications"
}
-- { -- not actually useful
-- path: "helpers"
-- }
-- } -- NOTE also to be deprecated by the version added to utility
{
path: "utility"
remote: {

View File

@ -2,11 +2,23 @@ import Widget from require "lapis.html"
class LoggedOut extends Widget
content: =>
p "This introduction will be written soon(TM)."
p ->
text "For now, forward any questions or ideas to "
text "Simplex is a task manager designed to be as flexible as possible. Organize your tasks the way you want to, instead of conforming to someone else's idea. Right now, Simplex offers a minimal web interface, and "
a href: @url_for("docs_index"), "extensive API documentation"
text ". It is developed by making the easiest to use API first, and then building a website to utilize its functionality."
p ->
text "Forward any questions or ideas to "
a href: "https://twitter.com/Guard13007", "@Guard13007"
text " on Twitter."
p ->
text "Or email me: "
text " on Twitter. Or email me: "
a href: "mailto:paul.liverman.iii@gmail.com", "paul.liverman.iii@gmail.com"
hr!
p "The ultimate goal of Simplex is a task manager anyone can use, and only costing $1.50/year to garuntee the servers remain working. So affordable, even a broke college student could pay for it."
p "Next features to be implemented:"
ul ->
li "Multiple task lists."
li "Duplicating tasks and lists."
li "Optional hierarchical structure for lists and tasks."