1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
|
(defpackage oneliners.api
(:use :cl)
(:local-nicknames (#:lzb #:lazybones)
(#:a #:alexandria)
(#:db #:bknr.datastore))
(:import-from #:lazybones
#:defendpoint*
#:http-ok
#:http-err))
(in-package :oneliners.api)
;;; SERVICE CONTROL
(defvar *server* nil)
(defun ensure-server (port address)
(unless *server*
(setf *server* (lzb:create-server :port port :address address))
(lzb:set-canned-response *server* 400 "Bad Request" "text/plain")
(lzb:set-canned-response *server* 404 "Not Found" "text/plain")
(lzb:set-canned-response *server* 500 "Server Error" "text/plain")))
(defun start (&optional (port 8888) (address "127.0.0.1"))
(ensure-server port address)
(lzb:install-app *server* (lzb:app))
(lzb:start-server *server*))
(defun stop ()
(when *server*
(lzb:stop-server *server*)))
;;; API DEFINITION AND PROVISIONING
(defparameter +oneliners-description+
"TBD")
(lzb:provision-app ()
:title "Oneliners Wiki API"
:version "0.0.1"
:desc +oneliners-description+
:content-type "application/json"
:auth 'api-token-authorization)
(defun api-token-authorization ()
"TBD"
t)
;;; ENDPOINT DEFINITIONS
(defendpoint* :get "/search" ()
"A search endpoint returning a JSON encoded array of Command Entries.
/search accepts the following query parameters:
- command : The name of a command. E.g. `ls`, `grep`, `netcat`.
- keywords : A comma-separated list of words that may appear in the title or description of a command entry, e.t. `'foo,bar,goo,zar,moo_blar'
- limit : An integer, limiting the number of results returned. Defaults to 10.
- recent : 0 for false 1 for true; sorts results by how recently they were added. Defaults to 0.
- nextpage : 0 for false 1 for true; requests that the query be accompanied by a nextpage key
- page : a nextpage token that will continue from a previous search. These expire after 10 minutes.
**Note** that either `command` or `keyword` parameters are required.
"
(http-ok "[]"))
(defendpoint* :put "/command/:command command-by-id:" (:auth t)
"Updates a command entry in the wiki database."
(cond
(command
(update-commmand command (lzb:request-body)) ; throws an error if fails, triggering a 500
(http-ok "true"))
(t (http-err 404)))) ;no command with the given id.
(defendpoint* :post "/command" (:auth t)
"Adds a new command entry to the wiki database."
(a:if-let (new-command (add-command-to-db (lzb:request-body)))
(http-ok "{}") ; dummy implementation
(http-err 400)))
(defendpoint* :post "/auth" ()
"Requests an authorization token")
;;; HELPERS
(defun command-by-id (id-string)
"An integer id of a command."
(list :a-dummy-command id-string))
(defun valid-command-update-data-p (jsonplist)
"Checks the fields of jsonplist, return t if they are sufficient to update a command entry."
jsonplist);; dummy implementation
(defun update-commmand (command json-body)
"Accepts a decoded json body, a plist, and "
(assert (valid-command-update-data-p json-body))
(list command json-body)) ;; dummy implmenetation
(defun valid-command-init-data-p (plist)
"dchecks the fields in plist,returns t if they are sufficient to create a new command."
plist);; dummy implementation
(defun add-command-to-db (json-plist)
"adds a new command to the database, returning it upon success "
(assert (valid-command-init-data-p json-plist))
:dummy-ok)
|