Do not quote params in Location header

Also treat the enum field in OPTIONS as an array uniformly
This commit is contained in:
Joe Nelson
2014-12-06 17:42:21 -08:00
parent 42faaa97c9
commit f1ecbec543
6 changed files with 44 additions and 42 deletions
+7 -1
View File
@@ -116,7 +116,7 @@ app req =
then inserted then inserted
else filterWithKey (const . (`elem` primaryKeys)) inserted else filterWithKey (const . (`elem` primaryKeys)) inserted
let params = urlEncodeVars let params = urlEncodeVars
$ map (\t -> (cs $ fst t, "eq." <> cs (encode $ snd t))) $ map (\t -> (cs $ fst t, "eq." <> cs (unquoted $ snd t)))
$ sortBy (comparing fst) $ toList primaries $ sortBy (comparing fst) $ toList primaries
return $ responseLBS status201 return $ responseLBS status201
[ jsonH [ jsonH
@@ -224,6 +224,12 @@ handleJsonObj req handler = do
jErr = encode . object $ jErr = encode . object $
[("error", String "Expecting a JSON object")] [("error", String "Expecting a JSON object")]
unquoted :: Value -> Text
unquoted (String t) = t
unquoted (Number n) = cs . show $ n
unquoted (Bool b) = cs . show $ b
unquoted _ = ""
data TableOptions = TableOptions { data TableOptions = TableOptions {
tblOptcolumns :: [Column] tblOptcolumns :: [Column]
, tblOptpkey :: [Text] , tblOptpkey :: [Text]
+12 -6
View File
@@ -1,7 +1,7 @@
{-# LANGUAGE QuasiQuotes, ScopedTypeVariables #-} {-# LANGUAGE QuasiQuotes, ScopedTypeVariables #-}
module Auth where module Auth where
import qualified Data.Aeson as JSON import Data.Aeson
import Control.Monad (mzero) import Control.Monad (mzero)
import Control.Applicative ( (<*>), (<$>) ) import Control.Applicative ( (<*>), (<$>) )
import Crypto.BCrypt import Crypto.BCrypt
@@ -16,13 +16,19 @@ data AuthUser = AuthUser {
, userRole :: String , userRole :: String
} }
instance JSON.FromJSON AuthUser where instance FromJSON AuthUser where
parseJSON (JSON.Object v) = AuthUser <$> parseJSON (Object v) = AuthUser <$>
v JSON..: "id" <*> v .: "id" <*>
v JSON..: "pass" <*> v .: "pass" <*>
v JSON..: "role" v .: "role"
parseJSON _ = mzero parseJSON _ = mzero
instance ToJSON AuthUser where
toJSON u = object [
"id" .= userId u
, "pass" .= userPass u
, "role" .= userRole u ]
type DbRole = Text type DbRole = Text
data LoginAttempt = data LoginAttempt =
+10 -6
View File
@@ -1,4 +1,5 @@
{-# LANGUAGE QuasiQuotes, MultiParamTypeClasses, ScopedTypeVariables #-} {-# LANGUAGE QuasiQuotes, OverloadedStrings,
MultiParamTypeClasses, ScopedTypeVariables #-}
module PgStructure where module PgStructure where
import PgQuery (QualifiedTable(..)) import PgQuery (QualifiedTable(..))
@@ -127,7 +128,7 @@ data Column = Column {
, colMaxLen :: Maybe Int , colMaxLen :: Maybe Int
, colPrecision :: Maybe Int , colPrecision :: Maybe Int
, colDefault :: Maybe Text , colDefault :: Maybe Text
, colEnum :: Maybe [Text] , colEnum :: [Text]
, colFK :: Maybe ForeignKey , colFK :: Maybe ForeignKey
} deriving (Show) } deriving (Show)
@@ -143,19 +144,22 @@ instance H.RowParser H.Postgres Column where
maxLen = H.parseResult $ r V.! 7 maxLen = H.parseResult $ r V.! 7
precision = H.parseResult $ r V.! 8 precision = H.parseResult $ r V.! 8
defValue = H.parseResult $ r V.! 9 defValue = H.parseResult $ r V.! 9
enum = H.parseResult $ r V.! 10 in enum = either (const $ Right []) (Right . split (==','))
(H.parseResult $ r V.! 10 :: Either Text Text)
in
if V.length r /= 11 if V.length r /= 11
then Left "Wrong number of fields in Column" then Left "Wrong number of fields in Column"
else Column <$> schema <*> table <*> name <*> position <*> nullable else Column <$> schema <*> table <*> name <*> position <*> nullable
<*> typ <*> updatable <*> maxLen <*> precision <*> typ <*> updatable <*> maxLen <*> precision
<*> defValue <*> enum <*> return Nothing <*> defValue <*> enum
<*> return Nothing
instance H.RowParser H.Postgres Table where instance H.RowParser H.Postgres Table where
parseRow r = parseRow r =
let schema = H.parseResult $ r V.! 0 let schema = H.parseResult $ r V.! 0
name = H.parseResult $ r V.! 2 name = H.parseResult $ r V.! 1
insertable = toBool <$> (H.parseResult $ r V.! 3 :: Either Text Text) in insertable = toBool <$> (H.parseResult $ r V.! 2 :: Either Text Text) in
if V.length r /= 3 if V.length r /= 3
then Left "Wrong number of fields in Table" then Left "Wrong number of fields in Table"
else Table <$> schema <*> name <*> insertable else Table <$> schema <*> name <*> insertable
-13
View File
@@ -5,19 +5,6 @@ import Test.Hspec.Wai
import SpecHelper import SpecHelper
-- around :: (ActionWith a -> IO ()) -> SpecWith a -> Spec
-- type Spec = SpecWith ()
-- type ActionWith a = a -> IO ()
--
-- get :: ByteString -> WaiSession SResponse
-- newtype WaiSession a = WaiSession {unWaiSession :: Session a}
-- type Session = ReaderT Application (StateT ClientState IO)
--
-- type Application =
-- Request -> (Response -> IO ResponseReceived) -> IO ResponseReceived
--
-- runApp :: Request -> (Response -> IO Postgres) -> IO Postgres
spec :: Spec spec :: Spec
spec = around withApp $ do spec = around withApp $ do
describe "Querying a nonexistent table" $ describe "Querying a nonexistent table" $
@@ -1,4 +1,4 @@
{-# LANGUAGE QuasiQuotes #-} {-# LANGUAGE OverloadedStrings, QuasiQuotes #-}
module Feature.StructureSpec where module Feature.StructureSpec where
import Test.Hspec import Test.Hspec
@@ -13,14 +13,13 @@ import Data.Monoid ((<>))
import Data.String.Conversions (cs) import Data.String.Conversions (cs)
spec :: Spec spec :: Spec
spec = let {uName = "a user"; uPass = "nobody can ever know"; spec = around withApp $ do
uRole = "dbapi_test"} in let uName = "a user"
around withDatabaseConnection $ uPass = "nobody can ever know"
aroundWith (withUser uName uPass uRole) $ aroundWith withApp $ do
describe "GET /" $ describe "GET /" $
it "lists views in schema" $ it "lists views in schema" $
request methodGet "/" request methodGet "/"
[("Authorization", "Basic "<>(cs.encode $ cs uName<>":"<>cs uPass))] "" [("Authorization", "Basic "<>(uName<>":"<>uPass))] ""
`shouldRespondWith` [json| [ `shouldRespondWith` [json| [
{"schema":"1","name":"authors_only","insertable":true} {"schema":"1","name":"authors_only","insertable":true}
, {"schema":"1","name":"auto_incrementing_pk","insertable":true} , {"schema":"1","name":"auto_incrementing_pk","insertable":true}
@@ -48,7 +47,7 @@ uRole = "dbapi_test"} in
"name": "integer", "name": "integer",
"type": "integer", "type": "integer",
"maxLen": null, "maxLen": null,
"enum": null, "enum": [],
"nullable": false, "nullable": false,
"position": 1, "position": 1,
"references": null, "references": null,
@@ -61,7 +60,7 @@ uRole = "dbapi_test"} in
"name": "double", "name": "double",
"type": "double precision", "type": "double precision",
"maxLen": null, "maxLen": null,
"enum": null, "enum": [],
"nullable": false, "nullable": false,
"references": null, "references": null,
"position": 2 "position": 2
@@ -73,7 +72,7 @@ uRole = "dbapi_test"} in
"name": "varchar", "name": "varchar",
"type": "character varying", "type": "character varying",
"maxLen": null, "maxLen": null,
"enum": null, "enum": [],
"nullable": false, "nullable": false,
"position": 3, "position": 3,
"references": null, "references": null,
@@ -86,7 +85,7 @@ uRole = "dbapi_test"} in
"name": "boolean", "name": "boolean",
"type": "boolean", "type": "boolean",
"maxLen": null, "maxLen": null,
"enum": null, "enum": [],
"nullable": false, "nullable": false,
"references": null, "references": null,
"position": 4 "position": 4
@@ -98,7 +97,7 @@ uRole = "dbapi_test"} in
"name": "date", "name": "date",
"type": "date", "type": "date",
"maxLen": null, "maxLen": null,
"enum": null, "enum": [],
"nullable": false, "nullable": false,
"references": null, "references": null,
"position": 5 "position": 5
@@ -110,7 +109,7 @@ uRole = "dbapi_test"} in
"name": "money", "name": "money",
"type": "money", "type": "money",
"maxLen": null, "maxLen": null,
"enum": null, "enum": [],
"nullable": false, "nullable": false,
"position": 6, "position": 6,
"references": null, "references": null,
@@ -153,7 +152,7 @@ uRole = "dbapi_test"} in
"maxLen": null, "maxLen": null,
"nullable": false, "nullable": false,
"position": 1, "position": 1,
"enum": null, "enum": [],
"references": null "references": null
}, { }, {
"default": null, "default": null,
@@ -165,7 +164,7 @@ uRole = "dbapi_test"} in
"maxLen": null, "maxLen": null,
"nullable": true, "nullable": true,
"position": 2, "position": 2,
"enum": null, "enum": [],
"references": {"table": "auto_incrementing_pk", "column": "id"} "references": {"table": "auto_incrementing_pk", "column": "id"}
}, { }, {
"default": null, "default": null,
@@ -177,7 +176,7 @@ uRole = "dbapi_test"} in
"maxLen": 255, "maxLen": 255,
"nullable": true, "nullable": true,
"position": 3, "position": 3,
"enum": null, "enum": [],
"references": {"table": "simple_pk", "column": "k"} "references": {"table": "simple_pk", "column": "k"}
} }
] ]
+1 -1
View File
@@ -23,4 +23,4 @@ main = do
loadFixture :: FilePath -> IO() loadFixture :: FilePath -> IO()
loadFixture name = loadFixture name =
void $ readProcess "psql" ["-U", "postgres", "-d", "dbapi_test", "-a", "-f", "test/fixtures/" ++ name ++ ".sql"] [] void $ readProcess "psql" ["-U", "dbapi_test", "-d", "dbapi_test", "-a", "-f", "test/fixtures/" ++ name ++ ".sql"] []