diff --git a/.gitignore b/.gitignore index fe56ed9..66a968f 100644 --- a/.gitignore +++ b/.gitignore @@ -8,4 +8,5 @@ pom.xml.asc *.class /.lein-* /.nrepl-port -profiles.clj \ No newline at end of file +profiles.clj +.idea diff --git a/README.md b/README.md index ba904bf..68e9960 100644 --- a/README.md +++ b/README.md @@ -16,6 +16,11 @@ To start a web server for the application, run: To test a request/response, run: - curl --data @sample-food-item-post.json --header "Content-Type: application/json" http://localhost:3000/fooditems + curl --data @sample-food-item-post.json \ + --header "Content-Type: application/json" \ + http://localhost:3000/fooditems - curl --data @sample-quantity-post.json --header "Content-Type: application/json" http://localhost:3000/quantity + curl --data @sample-quantity-post.json \ + --header "Content-Type: application/json" \ + --header "authorization: facebook-token " \ + http://localhost:3000/quantity diff --git a/project.clj b/project.clj index 13d26ee..2807b01 100644 --- a/project.clj +++ b/project.clj @@ -15,7 +15,9 @@ [ring/ring-json "0.4.0"] [ring/ring-mock "0.3.1"] [ring/ring-jetty-adapter "1.4.0"] - [com.layerware/hugsql "0.4.8"]] + [com.layerware/hugsql "0.4.8"] + [buddy/buddy-auth "2.1.0"] + [clj-http "3.7.0"]] :plugins [[lein-ring "0.9.7"] [lein-environ "1.1.0"]] :ring {:handler aretherecookies.app/app} :profiles diff --git a/src/aretherecookies/app.clj b/src/aretherecookies/app.clj index cac8c6f..b5e087e 100644 --- a/src/aretherecookies/app.clj +++ b/src/aretherecookies/app.clj @@ -1,25 +1,33 @@ (ns aretherecookies.app (:gen-class) (:require [aretherecookies.handler :refer [food-items-handler quantity-handler]] + [aretherecookies.auth :refer [auth-backend]] [environ.core :refer [env]] - [compojure.handler :refer [site]] + [compojure.handler :refer [api]] [compojure.core :refer :all] - [compojure.route :as route] [ring.adapter.jetty :as jetty] [ring.middleware.anti-forgery :refer :all] [ring.middleware.json :refer [wrap-json-body]] - [ring.middleware.defaults :refer [wrap-defaults api-defaults]])) + [ring.middleware.defaults :refer [wrap-defaults api-defaults]] + [buddy.auth :refer [throw-unauthorized]] + [buddy.auth.middleware :refer [wrap-authentication wrap-authorization]])) (defroutes app-routes (GET "/" [] (str {:csrf-token *anti-forgery-token*})) - (POST "/test" req "ok") - (POST "/fooditems" req (wrap-json-body food-items-handler)) - (POST "/quantity" req (wrap-json-body quantity-handler))) + (POST "/test" [] "ok") + (POST "/fooditems" [] food-items-handler) + (POST "/quantity" [] quantity-handler)) (def app-config (assoc-in api-defaults [:security :anti-forgery] false)) (def app (wrap-defaults app-routes app-config)) -(defn -main [& [port]] +(defn -main + [& [port]] (let [port (Integer. (or port (env :port) 3000))] - (jetty/run-jetty (site #'app) {:port port :join? false}))) \ No newline at end of file + (-> + (api #'app) + (wrap-authorization auth-backend) + (wrap-authentication auth-backend) + (wrap-json-body {:keywords? true}) + (jetty/run-jetty {:port port :join? false})))) diff --git a/src/aretherecookies/auth.clj b/src/aretherecookies/auth.clj new file mode 100644 index 0000000..de28ead --- /dev/null +++ b/src/aretherecookies/auth.clj @@ -0,0 +1,15 @@ +(ns aretherecookies.auth + (:require [buddy.auth.backends :as backends] + [clj-http.client :as client])) + +(defn facebook-me [token] + (client/get (str "https://graph.facebook.com/me?access_token=" token) {:accept :json})) + +(defn facebook-me-ok [token] + (= (:status (facebook-me token)) 200)) + +(defn facebook-token-auth [_ token] + (if (facebook-me-ok token) token)) + +(def auth-backend + (backends/token {:token-name "facebook-token" :authfn facebook-token-auth})) \ No newline at end of file diff --git a/src/aretherecookies/db.clj b/src/aretherecookies/db.clj index 8da46e9..45d1a06 100644 --- a/src/aretherecookies/db.clj +++ b/src/aretherecookies/db.clj @@ -35,7 +35,7 @@ (defonce pooled-db (delay (pool db-spec))) -(defn get-orderby [{orderby "orderby"} & args] +(defn get-orderby [{orderby :orderby} & args] (apply (cond (= orderby "distance") by-distance @@ -48,13 +48,13 @@ (str/replace token #"(^|$)" "'")) (defn get-where [{:keys [:lat :lng :filter]}] - (let [radius (-> (filter "radius") (or 10)) - categories (filter "categories")] + (let [radius (or (:radius filter) 10) + categories (:categories filter)] (cond categories (has-category {:categories (map wrap-in-quotes categories) :lat lat :lng lng :dist radius}) :else (within-radius {:lat lat :lng lng :dist radius})))) -(defn query-food-items [{lat "lat" lng "lng" filter "filter"}] +(defn query-food-items [{lat :lat lng :lng filter :filter}] (select-food-items @pooled-db {:lat lat @@ -62,7 +62,7 @@ :where (get-where {:lat lat :lng lng :filter filter}) :order (get-orderby filter)})) -(defn insert-quantity [{:keys [foodItemId quantity]}] +(defn insert-quantity [{:keys [:foodItemId :quantity]}] (insert-quantity-query @pooled-db {:food_item_id (wrap-in-quotes foodItemId) :quantity (wrap-in-quotes quantity)})) (defn select-latest-quantity [{:keys [:foodItemId]}] diff --git a/src/aretherecookies/handler.clj b/src/aretherecookies/handler.clj index 16a3f45..2fd89db 100644 --- a/src/aretherecookies/handler.clj +++ b/src/aretherecookies/handler.clj @@ -3,19 +3,22 @@ [aretherecookies.parsers :refer [food-items-to-json parse-special-types]] [clojure.data.json :as json] - [clojure.string :as str])) + [clojure.string :as str] + [buddy.auth :refer [authenticated? throw-unauthorized]])) (defn food-items-handler [req] (println "req ---->" (:body req)) (let [{body :body} req] (json/write-str (hash-map - :filter (get body "filter") + :filter (get body :filter) :fooditems (food-items-to-json (query-food-items body))) :value-fn parse-special-types))) -(defn quantity-handler [{{foodItemId "foodItemId" quantity "quantity"} :body}] - (println "req ---->" foodItemId quantity) - (json/write-str - (insert-quantity {:foodItemId foodItemId :quantity quantity}) - :value-fn parse-special-types)) +(defn quantity-handler [req] + (let [{{foodItemId :foodItemId quantity :quantity} :body} req] + (if-not (authenticated? req) (throw-unauthorized)) + (println "req ---->" foodItemId quantity) + (json/write-str + (insert-quantity {:foodItemId foodItemId :quantity quantity}) + :value-fn parse-special-types))) diff --git a/src/aretherecookies/parsers.clj b/src/aretherecookies/parsers.clj index e391fb8..bab40c2 100644 --- a/src/aretherecookies/parsers.clj +++ b/src/aretherecookies/parsers.clj @@ -13,9 +13,9 @@ (defn get-coords [item] (-> item - (get :location) + (:location) json/read-str - (get "coordinates"))) + (:coordinates))) (defn build-lat-lng [[lng lat]] (hash-map :longitude lng :latitude lat))