Create: POST
Read: GET
Update: PUT
Delete: DELETE
(def schema
{:first-name s/Str
:surname s/Str
:phone-number s/Str
(s/optional-key :address)
{:place s/Str
:country s/Str}})
(def phonebook
(atom
{:db
{"80a8ea00-…"
{:first-name "Thomas"
:surname "van der Veen"
:phone-number "0783312345"
:address {:street "High Street"
:postcode "SO21 1QQ"}}
"38d77ce0-…"
{:first-name "Malcolm"
:surname "Sparks"
:phone-number "07123456"}}
:last-added "38d77ce0-…"}))
(defroutes app-routes
(GET "/v1/phonebook" [] (get-phonebook))
(POST "/v1/phonebook" {body :body}
(add-user (slurp body)))
(PUT "/v1/phonebook/:id"
{body :body params :params}
(update-user (:id params)
(slurp body)))
(DELETE "/v1/phonebook/:id" [id]
(delete-user id))
(GET "/v1/phonebook/search"
{params :params}
(search-users params))
(route/not-found "Not Found"))
(defn atom-user-add [db data]
(let [new-uuid (.toString (UUID/randomUUID))
new-db (assoc-in db [:db new-uuid] data)]
(assoc-in new-db [:last-added] new-uuid)))
(defn add-user [data]
(let [parsed-data (edn/read-string data)]
(if-let [error (s/check schema parsed-data)]
{:status 400
:body (str "malformd request:\n" error)}
(do
(let [{id :last-added}
(swap! phonebook-db atom-user-add parsed-data)]
{:status 201 :body (pr-str id)})))))
(defn get-phonebook []
(let [data (pr-str (:db @phonebook-db))]
(-> (r/response data)
(r/content-type
"application/edn"))))
(defn update-user [id data]
(let [parsed-data (edn/read-string data)]
(if (contains? (:db @phonebook-db) id)
(do
(if-let [error (s/check schema parsed-data)]
{:status 400
:body (str "malformed request\n" error)}
(do
(swap! phonebook-db assoc-in [:db id]
parsed-data)
{:status 200})))
{:status 404 :body (str id " does not exist\n")})))
(defn delete-user [id]
(if (contains? (:db @phonebook-db) id)
(do (swap! phonebook-db update-in
[:db] dissoc id)
{:status 200})
{:status 404 :body
(str id " does not exist\n")}))
(defn search-users [params]
(let [surname (:surname params)
filtered (into {}
(filter
#(= surname (:surname (second %)))
(:db @phonebook-db)))]
(-> (r/response (pr-str filtered))
(r/content-type "application/edn"))))