Skip to content

Commit

Permalink
Added Web APIs.
Browse files Browse the repository at this point in the history
  • Loading branch information
kawasima committed Sep 30, 2015
1 parent 3fdc7e6 commit f215555
Show file tree
Hide file tree
Showing 13 changed files with 1,392 additions and 1,238 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Expand Up @@ -4,7 +4,8 @@
/.idea
.lein-*
pom.xml

/datomic*
/data
/voices
.nrepl-*
*~
Expand Down
33 changes: 0 additions & 33 deletions README.ja.md

This file was deleted.

83 changes: 83 additions & 0 deletions README.md
Expand Up @@ -27,3 +27,86 @@ Start a back channeling.

The default port is 3009.

## API

When you signup, select a type of bot account.
You must remember the authorization code.

![Imgur](http://i.imgur.com/diJJjhT.png)

First, you get token by authorization code.

```
POST /api/token
code=[authorization code]
```

You will get a response as follows:

```
{"access_token": , "name": "bot", "email": "bot@example.com"}
```

You must add the token to HTTP headers when you request to BackChanneling web APIs.

```
curl -H 'Accept: application/json' -H 'Authorization: Token xxxxxxxxxxxxxxxx' [API url]
```

And if you send a POST request, Add `Content-Type` to the request header.

```
curl -X POST -H 'Accept: application/json' -H 'Content-Type: application/json' -H 'Authorization: Token xxxxxxxxxxxxxxxx' [API url]
```

### Board

Get a board data.

```
GET /api/board/:board-name
```

An example of response as follows:

```
{
"id":17592186045424,
"name":"default",
"description":"Default board",
"threads":[
{"id":17592186045428,
"title":"aaa",
"since":"20150722T101724.515Z",
"last-updated":"20150722T110108.015Z",
"resnum":1000,"watchers":[]},
{"id":17592186045651,"title":"hohoho",
"since":"20150722T104559.129Z",
"last-updated":"20150929T123754.988Z",
"watchers":["bot2"],"resnum":1000}
]
}
```

### Thread

```
GET /api/thread/:thread-id
```

### New thread

```
POST /api/board/:board-name/threads
{"thread/name": "New thread", "comment/content": "Hello"}
```

### Post comment

```
POST /api/thread/:thread-id/comments
{"comment/content": "Hello"}
```
2 changes: 1 addition & 1 deletion VERSION
@@ -1 +1 @@
0.1.0
0.2.0-beta1
9 changes: 5 additions & 4 deletions project.clj
Expand Up @@ -3,16 +3,17 @@
:java-source-paths ["src/java"]
:dependencies [[org.clojure/clojure "1.7.0"]
[org.clojure/tools.logging "0.3.1"]
[org.clojure/data.json "0.2.6"]
[hiccup "1.0.5"]
[garden "1.2.5"]
[compojure "1.4.0"]
[environ "1.0.0"]
[buddy "0.6.1"]
[environ "1.0.1"]
[buddy "0.6.2"]

[org.clojure/clojurescript "1.7.58" :scope "provided"]
[org.clojure/core.async "0.1.346.0-17112a-alpha"]
[sablono "0.3.5"]
[prismatic/om-tools "0.3.11"]
[sablono "0.3.6"]
[prismatic/om-tools "0.3.12"]
[bouncer "0.3.3"]
[secretary "1.2.3"]
[org.omcljs/om "0.9.0"]
Expand Down
2,236 changes: 1,115 additions & 1,121 deletions resources/public/js/back-channeling.min.js

Large diffs are not rendered by default.

45 changes: 25 additions & 20 deletions src/clj/back_channeling/core.clj
Expand Up @@ -16,20 +16,25 @@
[layout :only [layout]]))
(:require [clojure.edn :as edn]
[clojure.tools.logging :as log]
[liberator.dev]
[hiccup.middleware :refer [wrap-base-url]]
[compojure.core :refer [defroutes GET POST routing] :as compojure]
[compojure.route :as route]
[buddy.auth.http :as http]
(back-channeling [server :as server]
[style :as style]
[model :as model]
[signup :as signup]))
(:import [java.io FileInputStream]))
[signup :as signup]
[token :as token]))
(:import [java.io FileInputStream]
[java.util UUID]))

(defn index-view [req]
(layout req
[:div#app.ui.page.full.height]
(include-js (str "/js/back-channeling"
(when-not (:dev env) ".min") ".js"))))

(defn login-view [req]
(layout
req
Expand Down Expand Up @@ -69,12 +74,6 @@
[(buddy.core.codecs/bytes->hex ?hash) ?hash-hex]
[?s :user/password ?hash-hex]]} username password)))

(defn auth-by-token [token]
(when token
(model/query '{:find [(pull ?s [:*]) .]
:in [$ ?token]
:where [[?s :user/token ?token]]} token)))

(defroutes app-routes
(GET "/" req (index-view req))
(GET "/login" req (login-view req))
Expand Down Expand Up @@ -120,32 +119,38 @@
(server/multicast-message "/ws" [:call message]
(:to message)))

(defmethod handle-command :join [[_ message] ch]
(log/info "bind user " ch message)
(server/bind-user "/ws" ch message)
(server/broadcast-message "/ws" [:join {:user/name (:user/name message)
:user/email (:user/email message)}]))
(defn api-access? [req]
(if-let [accept (get-in req [:headers "accept"])]
(or (.contains accept "application/json")
(.contains accept "application/edn"))))

(def access-rules [{:pattern #"^(/|/api/(?!token).*)$" :handler authenticated?}])

(def access-rules [{:pattern #"^(/|/api/?.*)$" :handler authenticated?}])
(def session-base (session-backend
{:unauthorized-handler
(fn [req meta]
(if (authenticated? req)
(redirect "/login")
(redirect (format "/login?next=%s" (:uri req)))))}))
(if (api-access? req)
(if (authenticated? req)
(http/response "Permission denied" 403)
(http/response "Unauthorized" 401))
(if (authenticated? req)
(redirect "/login")
(redirect (format "/login?next=%s" (:uri req))))))}))

(def token-base (token-backend
{:authfn
(fn [req token]
(auth-by-token token))}))
(try
(token/auth-by (UUID/fromString token))
(catch Exception e)))}))

(defn -main [& args]
(model/create-schema)
(server/run-server
(-> app-routes
(wrap-access-rules {:rules access-rules :policy :allow})
(wrap-authentication token-base session-base)
(wrap-authorization session-base)
(wrap-authentication token-base session-base)
(wrap-defaults (assoc-in site-defaults [:security :anti-forgery] false))
(wrap-reload))
:port (Integer/parseInt (or (:back-channeling-port env) "3009"))
Expand All @@ -154,4 +159,4 @@
(handle-command (edn/read-string message) ch))
:on-close (fn [ch close-reason]
(log/info "disconnect" ch "for" close-reason)
(handle-command [:leave nil] ch))}]))
(handle-command [:leave (server/find-user-by-channel "/ws" ch)] ch))}]))

0 comments on commit f215555

Please sign in to comment.