From e13d03bb249e3067fa924d7aaaecd15bffa56daa Mon Sep 17 00:00:00 2001 From: Abhinav Sarkar Date: Mon, 11 Sep 2017 11:58:37 +0530 Subject: [PATCH] Adds create user handler. --- package-lock.json | 38 ++++++++++++++++++++ package.json | 1 + src/SimpleService/Handler.purs | 27 ++++++++++++-- src/SimpleService/Middleware/BodyParser.js | 7 ++++ src/SimpleService/Middleware/BodyParser.purs | 7 ++++ src/SimpleService/Server.purs | 8 +++-- 6 files changed, 83 insertions(+), 5 deletions(-) create mode 100644 src/SimpleService/Middleware/BodyParser.js create mode 100644 src/SimpleService/Middleware/BodyParser.purs diff --git a/package-lock.json b/package-lock.json index a65cf3a..9cafbdf 100644 --- a/package-lock.json +++ b/package-lock.json @@ -18,11 +18,33 @@ "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" }, + "body-parser": { + "version": "1.18.0", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.18.0.tgz", + "integrity": "sha1-07Ik1Gf6LOjUNYnAJFBDJnwJNjQ=", + "requires": { + "bytes": "3.0.0", + "content-type": "1.0.2", + "debug": "2.6.8", + "depd": "1.1.1", + "http-errors": "1.6.2", + "iconv-lite": "0.4.18", + "on-finished": "2.3.0", + "qs": "6.5.0", + "raw-body": "2.3.1", + "type-is": "1.6.15" + } + }, "buffer-writer": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/buffer-writer/-/buffer-writer-1.0.1.tgz", "integrity": "sha1-Iqk2kB4wKa/NdUfrRIfOtpejvwg=" }, + "bytes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", + "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=" + }, "content-disposition": { "version": "0.5.2", "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.2.tgz", @@ -156,6 +178,11 @@ "statuses": "1.3.1" } }, + "iconv-lite": { + "version": "0.4.18", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.18.tgz", + "integrity": "sha512-sr1ZQph3UwHTR0XftSbK85OvBbxe/abLGzEnPENCQwmHf7sck8Oyu4ob3LgBxWWxRoM+QszeUyl7jbqapu2TqA==" + }, "inherits": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", @@ -326,6 +353,17 @@ "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz", "integrity": "sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4=" }, + "raw-body": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.3.1.tgz", + "integrity": "sha512-sxkd1uqaSj41SG5Vet9sNAxBMCMsmZ3LVhRkDlK8SbCpelTUB7JiMGHG70AZS6cFiCRgfNQhU2eLnTHYRFf7LA==", + "requires": { + "bytes": "3.0.0", + "http-errors": "1.6.2", + "iconv-lite": "0.4.18", + "unpipe": "1.0.0" + } + }, "semver": { "version": "4.3.2", "resolved": "https://registry.npmjs.org/semver/-/semver-4.3.2.tgz", diff --git a/package.json b/package.json index acd196c..43eb9ce 100644 --- a/package.json +++ b/package.json @@ -13,6 +13,7 @@ "author": "", "license": "ISC", "dependencies": { + "body-parser": "^1.18.0", "express": "^4.15.4", "pg": "^6.4.0" } diff --git a/src/SimpleService/Handler.purs b/src/SimpleService/Handler.purs index c18f0d2..6e73b90 100644 --- a/src/SimpleService/Handler.purs +++ b/src/SimpleService/Handler.purs @@ -3,14 +3,18 @@ module SimpleService.Handler where import Prelude import Control.Monad.Aff.Class (liftAff) +import Data.Either (Either(..)) +import Data.Foldable (intercalate) +import Data.Foreign (renderForeignError) import Data.Foreign.Class (encode) import Data.Int (fromString) import Data.Maybe (Maybe(..)) import Database.PostgreSQL as PG import Node.Express.Handler (Handler) -import Node.Express.Request (getRouteParam) -import Node.Express.Response (sendJson, setStatus) +import Node.Express.Request (getBody, getRouteParam) +import Node.Express.Response (end, sendJson, setStatus) import SimpleServer.Persistence as P +import SimpleServer.Types (User(..)) getUser :: forall eff. PG.Pool -> Handler (postgreSQL :: PG.POSTGRESQL | eff) getUser pool = getRouteParam "id" >>= case _ of @@ -34,10 +38,27 @@ deleteUser pool = getRouteParam "id" >>= case _ of P.deleteUser conn userId pure true if found - then respond 204 {} + then respondNoContent 204 else respond 404 { error: "User not found with id: " <> sUserId } +createUser :: forall eff. PG.Pool -> Handler (postgreSQL :: PG.POSTGRESQL | eff) +createUser pool = getBody >>= case _ of + Left errs -> respond 422 { error: intercalate ", " $ map renderForeignError errs} + Right u@(User user) -> + if user.id <= 0 + then respond 422 { error: "User ID must be more than 0: " <> show user.id} + else if user.name == "" + then respond 422 { error: "User name must not be empty" } + else do + liftAff (PG.withConnection pool $ flip P.insertUser u) + respondNoContent 201 + respond :: forall eff a. Int -> a -> Handler eff respond status body = do setStatus status sendJson body + +respondNoContent :: forall eff a. Int -> Handler eff +respondNoContent status = do + setStatus status + end diff --git a/src/SimpleService/Middleware/BodyParser.js b/src/SimpleService/Middleware/BodyParser.js new file mode 100644 index 0000000..cb03aab --- /dev/null +++ b/src/SimpleService/Middleware/BodyParser.js @@ -0,0 +1,7 @@ +"use strict"; + +var bodyParser = require("body-parser"); + +exports.jsonBodyParser = bodyParser.json({ + limit: "5mb" +}); diff --git a/src/SimpleService/Middleware/BodyParser.purs b/src/SimpleService/Middleware/BodyParser.purs new file mode 100644 index 0000000..5536c22 --- /dev/null +++ b/src/SimpleService/Middleware/BodyParser.purs @@ -0,0 +1,7 @@ +module SimpleService.Middleware.BodyParser where + +import Prelude +import Data.Function.Uncurried (Fn3) +import Node.Express.Types (ExpressM, Response, Request) + +foreign import jsonBodyParser :: forall e. Fn3 Request Response (ExpressM e Unit) (ExpressM e Unit) diff --git a/src/SimpleService/Server.purs b/src/SimpleService/Server.purs index f9f5372..7e2eefd 100644 --- a/src/SimpleService/Server.purs +++ b/src/SimpleService/Server.purs @@ -8,14 +8,18 @@ import Control.Monad.Eff.Class (liftEff) import Control.Monad.Eff.Console (CONSOLE, log, logShow) import Control.Monad.Eff.Exception (catchException) import Database.PostgreSQL as PG -import Node.Express.App (App, delete, get, listenHttp) +import Node.Express.App (App, delete, get, listenHttp, post, useExternal) import Node.Express.Types (EXPRESS) -import SimpleService.Handler (deleteUser, getUser) +import SimpleService.Handler (createUser, deleteUser, getUser) +import SimpleService.Middleware.BodyParser (jsonBodyParser) app :: forall eff. PG.Pool -> App (postgreSQL :: PG.POSTGRESQL | eff) app pool = do + useExternal jsonBodyParser + get "/v1/user/:id" $ getUser pool delete "/v1/user/:id" $ deleteUser pool + post "/v1/users" $ createUser pool runServer :: forall eff. Int