diff --git a/src/Dbapi.hs b/src/Dbapi.hs index d6e25bc1d..4729dd6ef 100644 --- a/src/Dbapi.hs +++ b/src/Dbapi.hs @@ -75,85 +75,98 @@ filterByKeys m keys = if null keys then m else m `intersection` fromList (zip keys $ repeat undefined) -httpRequesterRole :: RequestHeaders -> Connection -> IO(Maybe DbRole) +httpRequesterRole :: RequestHeaders -> Connection -> IO LoginAttempt httpRequesterRole hdrs conn = do let auth = fromMaybe "" $ lookup hAuthorization hdrs case BS.split ' ' (cs auth) of ("Basic " : b64 : _) -> case BS.split ':' $ cs (decode $ cs b64) of (u:p:_) -> signInRole u p conn - _ -> return Nothing - _ -> return Nothing + _ -> return MalformedAuth + _ -> return NoCredentials + app :: Connection -> DbRole -> Application app conn anonymous req respond = do - r <- try $ do - role <- fromMaybe anonymous <$> httpRequesterRole hdrs conn + attempt <- httpRequesterRole (requestHeaders req) conn - bracket_ (pgSetRole conn role) (pgResetRole conn) $ - case (path, verb) of - ([], _) -> - responseLBS status200 [jsonContentType] <$> printTables ver conn + case attempt of + MalformedAuth -> + respond $ responseLBS status400 [] "Malformed basic auth header" + LoginFailed -> + respond $ responseLBS status403 [] "Invalid username or password" + LoginSuccess role -> + bracket_ (pgSetRole conn role) (pgResetRole conn) $ appWithRole conn req respond + NoCredentials -> + bracket_ (pgSetRole conn anonymous) (pgResetRole conn) $ appWithRole conn req respond - ([table], "OPTIONS") -> - responseLBS status200 [jsonContentType, allOrigins] <$> - printColumns ver (cs table) conn - ([table], "GET") -> - if range == Just emptyRange - then return $ responseLBS status416 [] "HTTP Range error" - else do - r <- respondWithRangedResult <$> getRows ver (cs table) qq range conn - let canonical = urlEncodeVars $ sort $ - map (join (***) cs) $ - parseSimpleQuery $ - rawQueryString req - return $ addHeaders [ - ("Content-Location", - "/" <> cs table <> "?" <> cs canonical - )] r +appWithRole :: Connection -> Application +appWithRole conn req respond = do + r <- try $ + case (path, verb) of + ([], _) -> + responseLBS status200 [jsonContentType] <$> printTables ver conn - ([table], "POST") -> - jsonBodyAction req (\row -> do - allvals <- insert ver table row conn - keys <- primaryKeyColumns ver (cs table) conn - let params = urlEncodeVars $ map (\t -> (fst t, "eq." <> convert (snd t) :: String)) $ toList $ filterByKeys allvals keys - return $ responseLBS status201 - [ jsonContentType - , (hLocation, "/" <> cs table <> "?" <> cs params) - ] "" - ) + ([table], "OPTIONS") -> + responseLBS status200 [jsonContentType, allOrigins] <$> + printColumns ver (cs table) conn - ([table], "PUT") -> - jsonBodyAction req (\row -> do - keys <- primaryKeyColumns ver (cs table) conn - let specifiedKeys = map (cs . fst) qq - if S.fromList keys /= S.fromList specifiedKeys - then return $ responseLBS status405 [] - "You must speficy all and only primary keys as params" - else - if isJust cRange - then return $ responseLBS status400 [] - "Content-Range is not allowed in PUT request" - else do - cols <- columns ver (cs table) conn - let colNames = S.fromList $ map (cs . colName) cols - let specifiedCols = S.fromList $ map fst $ getRow row - if colNames == specifiedCols then do - allvals <- upsert ver table row qq conn - let params = urlEncodeVars $ map (\t -> (fst t, "eq." <> convert (snd t) :: String)) $ toList $ filterByKeys allvals keys - return $ responseLBS status201 - [ jsonContentType - , (hLocation, "/" <> cs table <> "?" <> cs params) - ] "" + ([table], "GET") -> + if range == Just emptyRange + then return $ responseLBS status416 [] "HTTP Range error" + else do + r <- respondWithRangedResult <$> getRows ver (cs table) qq range conn + let canonical = urlEncodeVars $ sort $ + map (join (***) cs) $ + parseSimpleQuery $ + rawQueryString req + return $ addHeaders [ + ("Content-Location", + "/" <> cs table <> "?" <> cs canonical + )] r - else return $ if S.null colNames then responseLBS status404 [] "" - else responseLBS status400 [] - "You must specify all columns in PUT request" - ) + ([table], "POST") -> + jsonBodyAction req (\row -> do + allvals <- insert ver table row conn + keys <- primaryKeyColumns ver (cs table) conn + let params = urlEncodeVars $ map (\t -> (fst t, "eq." <> convert (snd t) :: String)) $ toList $ filterByKeys allvals keys + return $ responseLBS status201 + [ jsonContentType + , (hLocation, "/" <> cs table <> "?" <> cs params) + ] "" + ) - (_, _) -> - return $ responseLBS status404 [] "" + ([table], "PUT") -> + jsonBodyAction req (\row -> do + keys <- primaryKeyColumns ver (cs table) conn + let specifiedKeys = map (cs . fst) qq + if S.fromList keys /= S.fromList specifiedKeys + then return $ responseLBS status405 [] + "You must speficy all and only primary keys as params" + else + if isJust cRange + then return $ responseLBS status400 [] + "Content-Range is not allowed in PUT request" + else do + cols <- columns ver (cs table) conn + let colNames = S.fromList $ map (cs . colName) cols + let specifiedCols = S.fromList $ map fst $ getRow row + if colNames == specifiedCols then do + allvals <- upsert ver table row qq conn + let params = urlEncodeVars $ map (\t -> (fst t, "eq." <> convert (snd t) :: String)) $ toList $ filterByKeys allvals keys + return $ responseLBS status201 + [ jsonContentType + , (hLocation, "/" <> cs table <> "?" <> cs params) + ] "" + + else return $ if S.null colNames then responseLBS status404 [] "" + else responseLBS status400 [] + "You must specify all columns in PUT request" + ) + + (_, _) -> + return $ responseLBS status404 [] "" respond $ either sqlErrorHandler id r diff --git a/src/PgQuery.hs b/src/PgQuery.hs index 6909d37b0..82fb628dc 100644 --- a/src/PgQuery.hs +++ b/src/PgQuery.hs @@ -3,16 +3,17 @@ -- {{{ Imports module PgQuery ( - getRows, - insert, - upsert, - addUser, - signInRole, - pgSetRole, - pgResetRole, - checkPass, - RangedResult(..), - DbRole + getRows +, insert +, upsert +, addUser +, signInRole +, pgSetRole +, pgResetRole +, checkPass +, RangedResult(..) +, LoginAttempt(..) +, DbRole ) where import Data.Text (Text) @@ -50,6 +51,13 @@ type QuotedSql = (String, [SqlValue]) type Schema = String type DbRole = BS.ByteString +data LoginAttempt = + NoCredentials + | MalformedAuth + | LoginFailed + | LoginSuccess DbRole + deriving (Eq, Show) + getRows :: Schema -> String -> Net.Query -> Maybe R.NonnegRange -> Connection -> IO RangedResult getRows schema table qq range conn = do query <- populateSql conn @@ -132,18 +140,18 @@ addUser identity pass role conn = do ]) conn return () -checkPass :: BS.ByteString -> BS.ByteString -> Bool -checkPass = validatePassword - -signInRole :: BS.ByteString -> BS.ByteString -> Connection -> IO(Maybe DbRole) +signInRole :: BS.ByteString -> BS.ByteString -> Connection -> IO LoginAttempt signInRole user pass conn = do u <- quickQuery conn "select pass, rolname from dbapi.auth where id = ?" [toSql user] return $ case u of [[hashed, role]] -> if checkPass (fromSql hashed) (cs pass) - then Just $ fromSql role - else Nothing - _ -> Nothing + then LoginSuccess $ fromSql role + else LoginFailed + _ -> LoginFailed + +checkPass :: BS.ByteString -> BS.ByteString -> Bool +checkPass = validatePassword upsert :: Schema -> Text -> SqlRow -> Net.Query -> Connection -> IO (M.Map String SqlValue) upsert schema table row qq conn = do diff --git a/test/Feature/AuthSpec.hs b/test/Feature/AuthSpec.hs new file mode 100644 index 000000000..f7596a0f7 --- /dev/null +++ b/test/Feature/AuthSpec.hs @@ -0,0 +1,25 @@ +{-# LANGUAGE OverloadedStrings #-} +module Feature.AuthSpec where + +-- {{{ Imports +import Test.Hspec +import Test.Hspec.Wai +import Network.HTTP.Types + +import SpecHelper +-- }}} + +spec :: Spec +spec = around appWithFixture $ + describe "authorization" $ do + it "hides tables that anonymous does not own" $ + -- TODO: should be 404 + get "/authors_only" `shouldRespondWith` 400 + it "indicates login failure" $ do + let auth = authHeader "dbapi_test_author_a" "fakefake" + request methodGet "/authors_only" [auth] "" + `shouldRespondWith` 403 + it "allows users with permissions to see their tables" $ do + let auth = authHeader "dbapi_test_author_a" "" + request methodGet "/authors_only" [auth] "" + `shouldRespondWith` 400 diff --git a/test/SpecHelper.hs b/test/SpecHelper.hs index 4f46d508a..24764b9d2 100644 --- a/test/SpecHelper.hs +++ b/test/SpecHelper.hs @@ -7,9 +7,15 @@ import Test.Hspec import Database.HDBC import Database.HDBC.PostgreSQL -import Control.Exception.Base (bracket) +import Data.String.Conversions (cs) +import Data.Either (isLeft) -import Network.HTTP.Types.Header +import Control.Exception.Base (bracket, tryJust) +import Control.Monad (when) + +import Network.HTTP.Types.Header (Header, ByteRange, renderByteRange, + hRange, hAuthorization) +import Codec.Binary.Base64.String (encode) import Data.CaseInsensitive (CI(..)) import Text.Regex.TDFA ((=~)) import qualified Data.HashMap.Strict as Hash @@ -40,9 +46,18 @@ dbWithSchema action = withDatabaseConnection $ \c -> do appWithFixture :: ActionWith Application -> IO () appWithFixture action = withDatabaseConnection $ \c -> do - runRaw c "begin;" - action $ cors corsPolicy $ app c "dbapi_anonymous" - rollback c + result <- tryJust transactionAborted $ do + runRaw c "begin;" + action $ cors corsPolicy $ app c "dbapi_anonymous" + rollback c + + when (isLeft result) $ + putStrLn "note: commands ignored after aborted transaction" + + where + transactionAborted :: SqlError -> Maybe () + transactionAborted e = + if seState e == "25P02" then Just () else Nothing rangeHdrs :: ByteRange -> [Header] rangeHdrs r = [rangeUnit, (hRange, renderByteRange r)] @@ -57,3 +72,7 @@ getHeader name headers = matchHeader :: CI BS.ByteString -> String -> [Header] -> Bool matchHeader name valRegex headers = maybe False (=~ valRegex) $ getHeader name headers + +authHeader :: String -> String -> Header +authHeader user pass = + (hAuthorization, cs $ "Basic: " ++ encode (user ++ ":" ++ pass)) diff --git a/test/Unit/PgQuerySpec.hs b/test/Unit/PgQuerySpec.hs index 82c20bc92..8bc853e58 100644 --- a/test/Unit/PgQuerySpec.hs +++ b/test/Unit/PgQuerySpec.hs @@ -7,7 +7,7 @@ import Test.Hspec import Database.HDBC (IConnection, SqlValue, toSql, prepare, quickQuery, fromSql, execute, seState, fetchAllRowsAL) -import PgQuery (insert, addUser, signInRole, checkPass) +import PgQuery (LoginAttempt(..), insert, addUser, signInRole, checkPass) import Types (SqlRow(SqlRow)) import TestTypes (fromList, incStr, incNullableStr, incInsert, incId) import Data.Map (toList) @@ -67,12 +67,13 @@ spec = around dbWithSchema $ do addUser user pass "not-a-real-role" conn `shouldThrow` \e -> take 2 (seState e) == "23" --integrity constraint violation + describe "signInRole" $ beforeWith (\conn -> do addUser user pass role conn return conn) $ do it "accepts correct credentials and return the role" $ \conn -> - signInRole user pass conn `shouldReturn` Just role + signInRole user pass conn `shouldReturn` LoginSuccess role it "returns nothing with bad creds" $ \conn -> do - signInRole "not-a-user" pass conn `shouldReturn` Nothing - signInRole user (pass <> "crap") conn `shouldReturn` Nothing + signInRole "not-a-user" pass conn `shouldReturn` LoginFailed + signInRole user (pass <> "crap") conn `shouldReturn` LoginFailed diff --git a/test/fixtures/roles.sql b/test/fixtures/roles.sql index cf68a5369..609c6e40d 100644 --- a/test/fixtures/roles.sql +++ b/test/fixtures/roles.sql @@ -11,9 +11,9 @@ BEGIN END; $$; -select pg_temp.create_role_if_not_exists('dbapi_anonymous', 'with login'); -select pg_temp.create_role_if_not_exists('test_default_role', 'with login'); +select pg_temp.create_role_if_not_exists('dbapi_anonymous', 'with nologin'); +select pg_temp.create_role_if_not_exists('test_default_role', 'with nologin'); select pg_temp.create_role_if_not_exists('dbapi_test_author', 'with nologin'); -select pg_temp.create_role_if_not_exists('dbapi_test_author_a', 'with login in role dbapi_test_author'); -select pg_temp.create_role_if_not_exists('dbapi_test_author_b', 'with login in role dbapi_test_author'); +select pg_temp.create_role_if_not_exists('dbapi_test_author_a', 'with nologin in role dbapi_test_author'); +select pg_temp.create_role_if_not_exists('dbapi_test_author_b', 'with nologin in role dbapi_test_author'); diff --git a/test/fixtures/schema.sql b/test/fixtures/schema.sql index c3dc14559..a0875d213 100644 --- a/test/fixtures/schema.sql +++ b/test/fixtures/schema.sql @@ -4,7 +4,7 @@ -- Dumped from database version 9.3.4 -- Dumped by pg_dump version 9.3.4 --- Started on 2014-09-30 15:17:14 PDT +-- Started on 2014-10-01 13:41:39 PDT SET statement_timeout = 0; SET lock_timeout = 0; @@ -14,7 +14,7 @@ SET check_function_bodies = false; SET client_min_messages = warning; -- --- TOC entry 8 (class 2615 OID 280279) +-- TOC entry 11 (class 2615 OID 280932) -- Name: 1; Type: SCHEMA; Schema: -; Owner: dbapi_test -- @@ -24,7 +24,7 @@ CREATE SCHEMA "1"; ALTER SCHEMA "1" OWNER TO dbapi_test; -- --- TOC entry 7 (class 2615 OID 280280) +-- TOC entry 9 (class 2615 OID 280933) -- Name: dbapi; Type: SCHEMA; Schema: -; Owner: dbapi_test -- @@ -34,7 +34,7 @@ CREATE SCHEMA dbapi; ALTER SCHEMA dbapi OWNER TO dbapi_test; -- --- TOC entry 5 (class 2615 OID 280341) +-- TOC entry 10 (class 2615 OID 280934) -- Name: private; Type: SCHEMA; Schema: -; Owner: dbapi_test -- @@ -44,7 +44,7 @@ CREATE SCHEMA private; ALTER SCHEMA private OWNER TO dbapi_test; -- --- TOC entry 183 (class 3079 OID 12018) +-- TOC entry 187 (class 3079 OID 12018) -- Name: plpgsql; Type: EXTENSION; Schema: -; Owner: -- @@ -52,8 +52,8 @@ CREATE EXTENSION IF NOT EXISTS plpgsql WITH SCHEMA pg_catalog; -- --- TOC entry 2276 (class 0 OID 0) --- Dependencies: 183 +-- TOC entry 2288 (class 0 OID 0) +-- Dependencies: 187 -- Name: EXTENSION plpgsql; Type: COMMENT; Schema: -; Owner: -- @@ -63,11 +63,11 @@ COMMENT ON EXTENSION plpgsql IS 'PL/pgSQL procedural language'; SET search_path = dbapi, pg_catalog; -- --- TOC entry 196 (class 1255 OID 280281) +-- TOC entry 200 (class 1255 OID 280935) -- Name: check_role_exists(); Type: FUNCTION; Schema: dbapi; Owner: dbapi_test -- -CREATE FUNCTION dbapi.check_role_exists() RETURNS trigger +CREATE FUNCTION check_role_exists() RETURNS trigger LANGUAGE plpgsql AS $$ begin @@ -83,7 +83,7 @@ $$; ALTER FUNCTION dbapi.check_role_exists() OWNER TO dbapi_test; -- --- TOC entry 198 (class 1255 OID 280353) +-- TOC entry 201 (class 1255 OID 280936) -- Name: update_owner(); Type: FUNCTION; Schema: dbapi; Owner: dbapi_test -- @@ -106,7 +106,19 @@ SET default_tablespace = ''; SET default_with_oids = false; -- --- TOC entry 172 (class 1259 OID 280283) +-- TOC entry 186 (class 1259 OID 281006) +-- Name: authors_only; Type: TABLE; Schema: 1; Owner: dbapi_test_author; Tablespace: +-- + +CREATE TABLE authors_only ( + secret character varying NOT NULL +); + + +ALTER TABLE "1".authors_only OWNER TO dbapi_test_author; + +-- +-- TOC entry 175 (class 1259 OID 280937) -- Name: auto_incrementing_pk; Type: TABLE; Schema: 1; Owner: dbapi_test; Tablespace: -- @@ -121,7 +133,7 @@ CREATE TABLE auto_incrementing_pk ( ALTER TABLE "1".auto_incrementing_pk OWNER TO dbapi_test; -- --- TOC entry 173 (class 1259 OID 280290) +-- TOC entry 176 (class 1259 OID 280944) -- Name: auto_incrementing_pk_id_seq; Type: SEQUENCE; Schema: 1; Owner: dbapi_test -- @@ -136,8 +148,8 @@ CREATE SEQUENCE auto_incrementing_pk_id_seq ALTER TABLE "1".auto_incrementing_pk_id_seq OWNER TO dbapi_test; -- --- TOC entry 2278 (class 0 OID 0) --- Dependencies: 173 +-- TOC entry 2291 (class 0 OID 0) +-- Dependencies: 176 -- Name: auto_incrementing_pk_id_seq; Type: SEQUENCE OWNED BY; Schema: 1; Owner: dbapi_test -- @@ -145,7 +157,7 @@ ALTER SEQUENCE auto_incrementing_pk_id_seq OWNED BY auto_incrementing_pk.id; -- --- TOC entry 174 (class 1259 OID 280292) +-- TOC entry 177 (class 1259 OID 280946) -- Name: compound_pk; Type: TABLE; Schema: 1; Owner: dbapi_test; Tablespace: -- @@ -159,7 +171,7 @@ CREATE TABLE compound_pk ( ALTER TABLE "1".compound_pk OWNER TO dbapi_test; -- --- TOC entry 175 (class 1259 OID 280295) +-- TOC entry 178 (class 1259 OID 280949) -- Name: items; Type: TABLE; Schema: 1; Owner: dbapi_test; Tablespace: -- @@ -171,7 +183,7 @@ CREATE TABLE items ( ALTER TABLE "1".items OWNER TO dbapi_test; -- --- TOC entry 176 (class 1259 OID 280298) +-- TOC entry 179 (class 1259 OID 280952) -- Name: items_id_seq; Type: SEQUENCE; Schema: 1; Owner: dbapi_test -- @@ -186,8 +198,8 @@ CREATE SEQUENCE items_id_seq ALTER TABLE "1".items_id_seq OWNER TO dbapi_test; -- --- TOC entry 2282 (class 0 OID 0) --- Dependencies: 176 +-- TOC entry 2295 (class 0 OID 0) +-- Dependencies: 179 -- Name: items_id_seq; Type: SEQUENCE OWNED BY; Schema: 1; Owner: dbapi_test -- @@ -195,7 +207,7 @@ ALTER SEQUENCE items_id_seq OWNED BY items.id; -- --- TOC entry 177 (class 1259 OID 280300) +-- TOC entry 180 (class 1259 OID 280954) -- Name: menagerie; Type: TABLE; Schema: 1; Owner: dbapi_test; Tablespace: -- @@ -212,7 +224,7 @@ CREATE TABLE menagerie ( ALTER TABLE "1".menagerie OWNER TO dbapi_test; -- --- TOC entry 178 (class 1259 OID 280306) +-- TOC entry 181 (class 1259 OID 280960) -- Name: no_pk; Type: TABLE; Schema: 1; Owner: dbapi_test; Tablespace: -- @@ -225,7 +237,7 @@ CREATE TABLE no_pk ( ALTER TABLE "1".no_pk OWNER TO dbapi_test; -- --- TOC entry 179 (class 1259 OID 280312) +-- TOC entry 182 (class 1259 OID 280966) -- Name: simple_pk; Type: TABLE; Schema: 1; Owner: dbapi_test; Tablespace: -- @@ -240,7 +252,7 @@ ALTER TABLE "1".simple_pk OWNER TO dbapi_test; SET search_path = dbapi, pg_catalog; -- --- TOC entry 180 (class 1259 OID 280318) +-- TOC entry 183 (class 1259 OID 280972) -- Name: auth; Type: TABLE; Schema: dbapi; Owner: dbapi_test; Tablespace: -- @@ -256,7 +268,7 @@ ALTER TABLE dbapi.auth OWNER TO dbapi_test; SET search_path = private, pg_catalog; -- --- TOC entry 182 (class 1259 OID 280356) +-- TOC entry 184 (class 1259 OID 280978) -- Name: articles; Type: TABLE; Schema: private; Owner: dbapi_test; Tablespace: -- @@ -270,7 +282,7 @@ CREATE TABLE articles ( ALTER TABLE private.articles OWNER TO dbapi_test; -- --- TOC entry 181 (class 1259 OID 280354) +-- TOC entry 185 (class 1259 OID 280984) -- Name: articles_id_seq; Type: SEQUENCE; Schema: private; Owner: dbapi_test -- @@ -285,8 +297,8 @@ CREATE SEQUENCE articles_id_seq ALTER TABLE private.articles_id_seq OWNER TO dbapi_test; -- --- TOC entry 2288 (class 0 OID 0) --- Dependencies: 181 +-- TOC entry 2301 (class 0 OID 0) +-- Dependencies: 185 -- Name: articles_id_seq; Type: SEQUENCE OWNED BY; Schema: private; Owner: dbapi_test -- @@ -296,7 +308,7 @@ ALTER SEQUENCE articles_id_seq OWNED BY articles.id; SET search_path = "1", pg_catalog; -- --- TOC entry 2133 (class 2604 OID 280324) +-- TOC entry 2140 (class 2604 OID 280986) -- Name: id; Type: DEFAULT; Schema: 1; Owner: dbapi_test -- @@ -304,7 +316,7 @@ ALTER TABLE ONLY auto_incrementing_pk ALTER COLUMN id SET DEFAULT nextval('auto_ -- --- TOC entry 2134 (class 2604 OID 280325) +-- TOC entry 2141 (class 2604 OID 280987) -- Name: id; Type: DEFAULT; Schema: 1; Owner: dbapi_test -- @@ -314,7 +326,7 @@ ALTER TABLE ONLY items ALTER COLUMN id SET DEFAULT nextval('items_id_seq'::regcl SET search_path = private, pg_catalog; -- --- TOC entry 2135 (class 2604 OID 280359) +-- TOC entry 2142 (class 2604 OID 280988) -- Name: id; Type: DEFAULT; Schema: private; Owner: dbapi_test -- @@ -324,33 +336,41 @@ ALTER TABLE ONLY articles ALTER COLUMN id SET DEFAULT nextval('articles_id_seq': SET search_path = "1", pg_catalog; -- --- TOC entry 2259 (class 0 OID 280283) --- Dependencies: 172 +-- TOC entry 2279 (class 0 OID 281006) +-- Dependencies: 186 +-- Data for Name: authors_only; Type: TABLE DATA; Schema: 1; Owner: dbapi_test_author +-- + + + +-- +-- TOC entry 2268 (class 0 OID 280937) +-- Dependencies: 175 -- Data for Name: auto_incrementing_pk; Type: TABLE DATA; Schema: 1; Owner: dbapi_test -- -- --- TOC entry 2289 (class 0 OID 0) --- Dependencies: 173 +-- TOC entry 2302 (class 0 OID 0) +-- Dependencies: 176 -- Name: auto_incrementing_pk_id_seq; Type: SEQUENCE SET; Schema: 1; Owner: dbapi_test -- -SELECT pg_catalog.setval('auto_incrementing_pk_id_seq', 42, true); +SELECT pg_catalog.setval('auto_incrementing_pk_id_seq', 46, true); -- --- TOC entry 2261 (class 0 OID 280292) --- Dependencies: 174 +-- TOC entry 2270 (class 0 OID 280946) +-- Dependencies: 177 -- Data for Name: compound_pk; Type: TABLE DATA; Schema: 1; Owner: dbapi_test -- -- --- TOC entry 2262 (class 0 OID 280295) --- Dependencies: 175 +-- TOC entry 2271 (class 0 OID 280949) +-- Dependencies: 178 -- Data for Name: items; Type: TABLE DATA; Schema: 1; Owner: dbapi_test -- @@ -372,8 +392,8 @@ INSERT INTO items (id) VALUES (15); -- --- TOC entry 2290 (class 0 OID 0) --- Dependencies: 176 +-- TOC entry 2303 (class 0 OID 0) +-- Dependencies: 179 -- Name: items_id_seq; Type: SEQUENCE SET; Schema: 1; Owner: dbapi_test -- @@ -381,24 +401,24 @@ SELECT pg_catalog.setval('items_id_seq', 15, true); -- --- TOC entry 2264 (class 0 OID 280300) --- Dependencies: 177 +-- TOC entry 2273 (class 0 OID 280954) +-- Dependencies: 180 -- Data for Name: menagerie; Type: TABLE DATA; Schema: 1; Owner: dbapi_test -- -- --- TOC entry 2265 (class 0 OID 280306) --- Dependencies: 178 +-- TOC entry 2274 (class 0 OID 280960) +-- Dependencies: 181 -- Data for Name: no_pk; Type: TABLE DATA; Schema: 1; Owner: dbapi_test -- -- --- TOC entry 2266 (class 0 OID 280312) --- Dependencies: 179 +-- TOC entry 2275 (class 0 OID 280966) +-- Dependencies: 182 -- Data for Name: simple_pk; Type: TABLE DATA; Schema: 1; Owner: dbapi_test -- @@ -407,8 +427,8 @@ SELECT pg_catalog.setval('items_id_seq', 15, true); SET search_path = dbapi, pg_catalog; -- --- TOC entry 2267 (class 0 OID 280318) --- Dependencies: 180 +-- TOC entry 2276 (class 0 OID 280972) +-- Dependencies: 183 -- Data for Name: auth; Type: TABLE DATA; Schema: dbapi; Owner: dbapi_test -- @@ -417,16 +437,16 @@ SET search_path = dbapi, pg_catalog; SET search_path = private, pg_catalog; -- --- TOC entry 2269 (class 0 OID 280356) --- Dependencies: 182 +-- TOC entry 2277 (class 0 OID 280978) +-- Dependencies: 184 -- Data for Name: articles; Type: TABLE DATA; Schema: private; Owner: dbapi_test -- -- --- TOC entry 2291 (class 0 OID 0) --- Dependencies: 181 +-- TOC entry 2304 (class 0 OID 0) +-- Dependencies: 185 -- Name: articles_id_seq; Type: SEQUENCE SET; Schema: private; Owner: dbapi_test -- @@ -436,7 +456,16 @@ SELECT pg_catalog.setval('articles_id_seq', 1, false); SET search_path = "1", pg_catalog; -- --- TOC entry 2137 (class 2606 OID 280327) +-- TOC entry 2158 (class 2606 OID 281013) +-- Name: authors_only_pkey; Type: CONSTRAINT; Schema: 1; Owner: dbapi_test_author; Tablespace: +-- + +ALTER TABLE ONLY authors_only + ADD CONSTRAINT authors_only_pkey PRIMARY KEY (secret); + + +-- +-- TOC entry 2144 (class 2606 OID 280990) -- Name: auto_incrementing_pk_pkey; Type: CONSTRAINT; Schema: 1; Owner: dbapi_test; Tablespace: -- @@ -445,7 +474,7 @@ ALTER TABLE ONLY auto_incrementing_pk -- --- TOC entry 2139 (class 2606 OID 280329) +-- TOC entry 2146 (class 2606 OID 280992) -- Name: compound_pk_pkey; Type: CONSTRAINT; Schema: 1; Owner: dbapi_test; Tablespace: -- @@ -454,7 +483,7 @@ ALTER TABLE ONLY compound_pk -- --- TOC entry 2145 (class 2606 OID 280331) +-- TOC entry 2152 (class 2606 OID 280994) -- Name: contacts_pkey; Type: CONSTRAINT; Schema: 1; Owner: dbapi_test; Tablespace: -- @@ -463,7 +492,7 @@ ALTER TABLE ONLY simple_pk -- --- TOC entry 2141 (class 2606 OID 280333) +-- TOC entry 2148 (class 2606 OID 280996) -- Name: items_pkey; Type: CONSTRAINT; Schema: 1; Owner: dbapi_test; Tablespace: -- @@ -472,7 +501,7 @@ ALTER TABLE ONLY items -- --- TOC entry 2143 (class 2606 OID 280335) +-- TOC entry 2150 (class 2606 OID 280998) -- Name: menagerie_pkey; Type: CONSTRAINT; Schema: 1; Owner: dbapi_test; Tablespace: -- @@ -483,7 +512,7 @@ ALTER TABLE ONLY menagerie SET search_path = dbapi, pg_catalog; -- --- TOC entry 2147 (class 2606 OID 280337) +-- TOC entry 2154 (class 2606 OID 281000) -- Name: auth_pkey; Type: CONSTRAINT; Schema: dbapi; Owner: dbapi_test; Tablespace: -- @@ -494,7 +523,7 @@ ALTER TABLE ONLY auth SET search_path = private, pg_catalog; -- --- TOC entry 2149 (class 2606 OID 280364) +-- TOC entry 2156 (class 2606 OID 281002) -- Name: articles_pkey; Type: CONSTRAINT; Schema: private; Owner: dbapi_test; Tablespace: -- @@ -505,7 +534,7 @@ ALTER TABLE ONLY articles SET search_path = dbapi, pg_catalog; -- --- TOC entry 2150 (class 2620 OID 280339) +-- TOC entry 2159 (class 2620 OID 281004) -- Name: ensure_auth_role_exists; Type: TRIGGER; Schema: dbapi; Owner: dbapi_test -- @@ -515,7 +544,7 @@ CREATE CONSTRAINT TRIGGER ensure_auth_role_exists AFTER INSERT OR UPDATE ON auth SET search_path = private, pg_catalog; -- --- TOC entry 2151 (class 2620 OID 280365) +-- TOC entry 2160 (class 2620 OID 281005) -- Name: articles_owner_track; Type: TRIGGER; Schema: private; Owner: dbapi_test -- @@ -523,8 +552,8 @@ CREATE TRIGGER articles_owner_track BEFORE INSERT OR UPDATE ON articles FOR EACH -- --- TOC entry 2275 (class 0 OID 0) --- Dependencies: 8 +-- TOC entry 2285 (class 0 OID 0) +-- Dependencies: 11 -- Name: 1; Type: ACL; Schema: -; Owner: dbapi_test -- @@ -534,11 +563,35 @@ GRANT ALL ON SCHEMA "1" TO dbapi_test; GRANT USAGE ON SCHEMA "1" TO dbapi_anonymous; +-- +-- TOC entry 2287 (class 0 OID 0) +-- Dependencies: 5 +-- Name: public; Type: ACL; Schema: -; Owner: j +-- + +REVOKE ALL ON SCHEMA public FROM PUBLIC; +REVOKE ALL ON SCHEMA public FROM j; +GRANT ALL ON SCHEMA public TO j; +GRANT ALL ON SCHEMA public TO PUBLIC; + + SET search_path = "1", pg_catalog; -- --- TOC entry 2277 (class 0 OID 0) --- Dependencies: 172 +-- TOC entry 2289 (class 0 OID 0) +-- Dependencies: 186 +-- Name: authors_only; Type: ACL; Schema: 1; Owner: dbapi_test_author +-- + +REVOKE ALL ON TABLE authors_only FROM PUBLIC; +REVOKE ALL ON TABLE authors_only FROM dbapi_test_author; +GRANT ALL ON TABLE authors_only TO dbapi_test_author; +GRANT ALL ON TABLE authors_only TO author; + + +-- +-- TOC entry 2290 (class 0 OID 0) +-- Dependencies: 175 -- Name: auto_incrementing_pk; Type: ACL; Schema: 1; Owner: dbapi_test -- @@ -549,8 +602,8 @@ GRANT ALL ON TABLE auto_incrementing_pk TO dbapi_anonymous; -- --- TOC entry 2279 (class 0 OID 0) --- Dependencies: 173 +-- TOC entry 2292 (class 0 OID 0) +-- Dependencies: 176 -- Name: auto_incrementing_pk_id_seq; Type: ACL; Schema: 1; Owner: dbapi_test -- @@ -561,8 +614,8 @@ GRANT USAGE ON SEQUENCE auto_incrementing_pk_id_seq TO dbapi_anonymous; -- --- TOC entry 2280 (class 0 OID 0) --- Dependencies: 174 +-- TOC entry 2293 (class 0 OID 0) +-- Dependencies: 177 -- Name: compound_pk; Type: ACL; Schema: 1; Owner: dbapi_test -- @@ -573,8 +626,8 @@ GRANT ALL ON TABLE compound_pk TO dbapi_anonymous; -- --- TOC entry 2281 (class 0 OID 0) --- Dependencies: 175 +-- TOC entry 2294 (class 0 OID 0) +-- Dependencies: 178 -- Name: items; Type: ACL; Schema: 1; Owner: dbapi_test -- @@ -585,8 +638,8 @@ GRANT ALL ON TABLE items TO dbapi_anonymous; -- --- TOC entry 2283 (class 0 OID 0) --- Dependencies: 176 +-- TOC entry 2296 (class 0 OID 0) +-- Dependencies: 179 -- Name: items_id_seq; Type: ACL; Schema: 1; Owner: dbapi_test -- @@ -597,8 +650,8 @@ GRANT USAGE ON SEQUENCE items_id_seq TO dbapi_anonymous; -- --- TOC entry 2284 (class 0 OID 0) --- Dependencies: 177 +-- TOC entry 2297 (class 0 OID 0) +-- Dependencies: 180 -- Name: menagerie; Type: ACL; Schema: 1; Owner: dbapi_test -- @@ -609,8 +662,8 @@ GRANT ALL ON TABLE menagerie TO dbapi_anonymous; -- --- TOC entry 2285 (class 0 OID 0) --- Dependencies: 178 +-- TOC entry 2298 (class 0 OID 0) +-- Dependencies: 181 -- Name: no_pk; Type: ACL; Schema: 1; Owner: dbapi_test -- @@ -621,8 +674,8 @@ GRANT ALL ON TABLE no_pk TO dbapi_anonymous; -- --- TOC entry 2286 (class 0 OID 0) --- Dependencies: 179 +-- TOC entry 2299 (class 0 OID 0) +-- Dependencies: 182 -- Name: simple_pk; Type: ACL; Schema: 1; Owner: dbapi_test -- @@ -635,8 +688,8 @@ GRANT ALL ON TABLE simple_pk TO dbapi_anonymous; SET search_path = private, pg_catalog; -- --- TOC entry 2287 (class 0 OID 0) --- Dependencies: 182 +-- TOC entry 2300 (class 0 OID 0) +-- Dependencies: 184 -- Name: articles; Type: ACL; Schema: private; Owner: dbapi_test -- @@ -645,7 +698,7 @@ REVOKE ALL ON TABLE articles FROM dbapi_test; GRANT ALL ON TABLE articles TO dbapi_test; --- Completed on 2014-09-30 15:17:14 PDT +-- Completed on 2014-10-01 13:41:40 PDT -- -- PostgreSQL database dump complete