Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
bd304c9fc3 | ||
|
|
3989aaa144 | ||
|
|
1d51a5f543 | ||
|
|
e4dafad64d | ||
|
|
3f31c60f1d | ||
|
|
83f48dcd15 | ||
|
|
1cc53245c5 | ||
|
|
f24ba048af | ||
|
|
a980db6d2d | ||
|
|
4277284a69 | ||
|
|
b070994912 | ||
|
|
988df54e53 |
@@ -3,6 +3,15 @@
|
|||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
This project adheres to [Semantic Versioning](http://semver.org/).
|
This project adheres to [Semantic Versioning](http://semver.org/).
|
||||||
|
|
||||||
|
## [0.2.10.0] - 2015-06-03
|
||||||
|
### Added
|
||||||
|
- Full text search, eg `/foo?text_vector=@@.bar`
|
||||||
|
- Include auth id as well as db role to views (for row-level security)
|
||||||
|
|
||||||
|
## [0.2.9.1] - 2015-05-20
|
||||||
|
### Fixed
|
||||||
|
- Put -Werror behind a cabal flag (for CI) so Hackage accepts package
|
||||||
|
|
||||||
## [0.2.9.0] - 2015-05-20
|
## [0.2.9.0] - 2015-05-20
|
||||||
### Added
|
### Added
|
||||||
- Return range headers in PATCH
|
- Return range headers in PATCH
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ your own projects.
|
|||||||
|
|
||||||
### Usage
|
### Usage
|
||||||
|
|
||||||
Download the binary ([OS X](http://bin.begriffs.com/dbapi/osx/postgrest-0.2.9.0.tar.xz) / [Linux](http://bin.begriffs.com/dbapi/heroku/postgrest-0.2.9.0.tar.xz)) and invoke like so:
|
Download the binary ([latest release](https://github.com/begriffs/postgrest/releases/latest)) and invoke like so:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
postgrest --db-host localhost --db-port 5432 \
|
postgrest --db-host localhost --db-port 5432 \
|
||||||
@@ -75,12 +75,14 @@ Other optimizations are possible, and some are outlined in the
|
|||||||
|
|
||||||
### Security
|
### Security
|
||||||
|
|
||||||
PostgREST handles authentication (HTTP Basic over SSL) and delegates
|
PostgREST handles authentication (HTTP Basic over SSL or [JSON Web
|
||||||
authorization to the role information defined in the database. This
|
Tokens](https://github.com/begriffs/postgrest/wiki/Security-and-Permissions#json-web-tokens))
|
||||||
ensures there is a single declarative source of truth for security.
|
and delegates authorization to the role information defined in the
|
||||||
When dealing with the database the server assumes the identity of
|
database. This ensures there is a single declarative source of truth
|
||||||
the currently authenticated user, and for the duration of the
|
for security. When dealing with the database the server assumes
|
||||||
connection cannot do anything the user themselves couldn't.
|
the identity of the currently authenticated user, and for the
|
||||||
|
duration of the connection cannot do anything the user themselves
|
||||||
|
couldn't.
|
||||||
|
|
||||||
Postgres 9.5 will soon support true [row-level
|
Postgres 9.5 will soon support true [row-level
|
||||||
security](http://michael.otacoo.com/postgresql-2/postgres-9-5-feature-highlight-row-level-security/).
|
security](http://michael.otacoo.com/postgresql-2/postgres-9-5-feature-highlight-row-level-security/).
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
},
|
},
|
||||||
"POSTGREST_VER": {
|
"POSTGREST_VER": {
|
||||||
"description": "Version of PostgREST to deploy",
|
"description": "Version of PostgREST to deploy",
|
||||||
"value": "0.2.9.0"
|
"value": "0.2.10.0"
|
||||||
},
|
},
|
||||||
"DB_NAME": {
|
"DB_NAME": {
|
||||||
"description": "Database name",
|
"description": "Database name",
|
||||||
|
|||||||
@@ -4,6 +4,12 @@ machine:
|
|||||||
- createdb -O postgrest_test -U ubuntu postgrest_test
|
- createdb -O postgrest_test -U ubuntu postgrest_test
|
||||||
ghc:
|
ghc:
|
||||||
version: 7.8.3
|
version: 7.8.3
|
||||||
|
dependencies:
|
||||||
|
override:
|
||||||
|
- cabal update
|
||||||
|
- cabal sandbox init
|
||||||
|
- cabal install --upgrade-dependencies --constraint="template-haskell installed" --dependencies-only --enable-tests
|
||||||
|
- cabal configure --enable-tests -f ci
|
||||||
test:
|
test:
|
||||||
post:
|
post:
|
||||||
- cabal exec hlint -- -X QuasiQuotes src/**/*.hs test/**/*.hs
|
- cabal exec hlint -- -X QuasiQuotes src/**/*.hs test/**/*.hs
|
||||||
|
|||||||
+18
-3
@@ -2,7 +2,7 @@ name: postgrest
|
|||||||
description: Reads the schema of a PostgreSQL database and creates RESTful routes
|
description: Reads the schema of a PostgreSQL database and creates RESTful routes
|
||||||
for the tables and views, supporting all HTTP verbs that security
|
for the tables and views, supporting all HTTP verbs that security
|
||||||
permits.
|
permits.
|
||||||
version: 0.2.9.0
|
version: 0.2.10.0
|
||||||
synopsis: REST API for any Postgres database
|
synopsis: REST API for any Postgres database
|
||||||
license: MIT
|
license: MIT
|
||||||
license-file: LICENSE
|
license-file: LICENSE
|
||||||
@@ -12,6 +12,14 @@ maintainer: cred+github@begriffs.com
|
|||||||
category: Web
|
category: Web
|
||||||
build-type: Simple
|
build-type: Simple
|
||||||
cabal-version: >=1.10
|
cabal-version: >=1.10
|
||||||
|
source-repository head
|
||||||
|
type: git
|
||||||
|
location: git://github.com/begriffs/postgrest.git
|
||||||
|
|
||||||
|
Flag CI
|
||||||
|
Description: No warnings allowed in continuous integration
|
||||||
|
Manual: True
|
||||||
|
Default: False
|
||||||
|
|
||||||
executable postgrest
|
executable postgrest
|
||||||
main-is: PostgREST/Main.hs
|
main-is: PostgREST/Main.hs
|
||||||
@@ -47,7 +55,11 @@ executable postgrest
|
|||||||
hs-source-dirs: src
|
hs-source-dirs: src
|
||||||
|
|
||||||
library
|
library
|
||||||
ghc-options: -Wall -W -O2
|
if flag(ci)
|
||||||
|
ghc-options: -Wall -W -Werror
|
||||||
|
else
|
||||||
|
ghc-options: -Wall -W -O2
|
||||||
|
|
||||||
default-language: Haskell2010
|
default-language: Haskell2010
|
||||||
default-extensions: OverloadedStrings, ScopedTypeVariables, QuasiQuotes
|
default-extensions: OverloadedStrings, ScopedTypeVariables, QuasiQuotes
|
||||||
build-depends: base >=4.6 && <5
|
build-depends: base >=4.6 && <5
|
||||||
@@ -91,7 +103,10 @@ Test-Suite spec
|
|||||||
Default-Language: Haskell2010
|
Default-Language: Haskell2010
|
||||||
default-extensions: OverloadedStrings, ScopedTypeVariables, QuasiQuotes
|
default-extensions: OverloadedStrings, ScopedTypeVariables, QuasiQuotes
|
||||||
Hs-Source-Dirs: test, src
|
Hs-Source-Dirs: test, src
|
||||||
ghc-options: -Wall -W -Werror
|
if flag(ci)
|
||||||
|
ghc-options: -Wall -W -Werror
|
||||||
|
else
|
||||||
|
ghc-options: -Wall -W -O2
|
||||||
Main-Is: Main.hs
|
Main-Is: Main.hs
|
||||||
Other-Modules: PostgREST.App
|
Other-Modules: PostgREST.App
|
||||||
, PostgREST.Auth
|
, PostgREST.Auth
|
||||||
|
|||||||
@@ -120,9 +120,9 @@ app conf reqBody req =
|
|||||||
login <- signInRole (cs $ userId u)
|
login <- signInRole (cs $ userId u)
|
||||||
(cs $ userPass u)
|
(cs $ userPass u)
|
||||||
case login of
|
case login of
|
||||||
LoginSuccess role ->
|
LoginSuccess role uid ->
|
||||||
return $ responseLBS status201 [ jsonH ] $
|
return $ responseLBS status201 [ jsonH ] $
|
||||||
encode . object $ [("token", String $ tokenJWT jwtSecret (cs $ userId u) role)]
|
encode . object $ [("token", String $ tokenJWT jwtSecret uid role)]
|
||||||
_ -> return $ responseLBS status401 [jsonH] $
|
_ -> return $ responseLBS status401 [jsonH] $
|
||||||
encode . object $ [("message", String "Failed authentication.")]
|
encode . object $ [("message", String "Failed authentication.")]
|
||||||
|
|
||||||
|
|||||||
+18
-5
@@ -40,12 +40,13 @@ instance ToJSON AuthUser where
|
|||||||
, "role" .= userRole u ]
|
, "role" .= userRole u ]
|
||||||
|
|
||||||
type DbRole = Text
|
type DbRole = Text
|
||||||
|
type UserId = Text
|
||||||
|
|
||||||
data LoginAttempt =
|
data LoginAttempt =
|
||||||
NoCredentials
|
NoCredentials
|
||||||
| MalformedAuth
|
| MalformedAuth
|
||||||
| LoginFailed
|
| LoginFailed
|
||||||
| LoginSuccess DbRole
|
| LoginSuccess DbRole UserId
|
||||||
deriving (Eq, Show)
|
deriving (Eq, Show)
|
||||||
|
|
||||||
checkPass :: Text -> Text -> Bool
|
checkPass :: Text -> Text -> Bool
|
||||||
@@ -57,6 +58,15 @@ setRole role = H.unitEx $ B.Stmt ("set role " <> cs (pgFmtLit role)) V.empty Tru
|
|||||||
resetRole :: H.Tx P.Postgres s ()
|
resetRole :: H.Tx P.Postgres s ()
|
||||||
resetRole = H.unitEx [H.stmt|reset role|]
|
resetRole = H.unitEx [H.stmt|reset role|]
|
||||||
|
|
||||||
|
setUserId :: Text -> H.Tx P.Postgres s ()
|
||||||
|
setUserId uid = if uid /= "" then
|
||||||
|
H.unitEx $ B.Stmt ("set user_vars.user_id = " <> cs (pgFmtLit uid)) V.empty True
|
||||||
|
else
|
||||||
|
resetUserId
|
||||||
|
|
||||||
|
resetUserId :: H.Tx P.Postgres s ()
|
||||||
|
resetUserId = H.unitEx [H.stmt|reset user_vars.user_id|]
|
||||||
|
|
||||||
addUser :: Text -> Text -> Text -> H.Tx P.Postgres s ()
|
addUser :: Text -> Text -> Text -> H.Tx P.Postgres s ()
|
||||||
addUser identity pass role = do
|
addUser identity pass role = do
|
||||||
let Just hashed = unsafePerformIO $ hashPasswordUsingPolicy fastBcryptHashingPolicy (cs pass)
|
let Just hashed = unsafePerformIO $ hashPasswordUsingPolicy fastBcryptHashingPolicy (cs pass)
|
||||||
@@ -66,20 +76,23 @@ addUser identity pass role = do
|
|||||||
|
|
||||||
signInRole :: Text -> Text -> H.Tx P.Postgres s LoginAttempt
|
signInRole :: Text -> Text -> H.Tx P.Postgres s LoginAttempt
|
||||||
signInRole user pass = do
|
signInRole user pass = do
|
||||||
u <- H.maybeEx $ [H.stmt|select pass, rolname from postgrest.auth where id = ?|] user
|
u <- H.maybeEx $ [H.stmt|select id, pass, rolname from postgrest.auth where id = ?|] user
|
||||||
return $ maybe LoginFailed (\r ->
|
return $ maybe LoginFailed (\r ->
|
||||||
let (hashed, role) = r in
|
let (uid, hashed, role) = r in
|
||||||
if checkPass hashed pass
|
if checkPass hashed pass
|
||||||
then LoginSuccess role
|
then LoginSuccess role uid
|
||||||
else LoginFailed
|
else LoginFailed
|
||||||
) u
|
) u
|
||||||
|
|
||||||
signInWithJWT :: Text -> Text -> LoginAttempt
|
signInWithJWT :: Text -> Text -> LoginAttempt
|
||||||
signInWithJWT secret input = case maybeRole of
|
signInWithJWT secret input = case maybeRole of
|
||||||
Just (Just (String role)) -> LoginSuccess $ cs role
|
Just (Just (String role)) -> case maybeUserId of
|
||||||
|
Just (Just (String uid)) -> LoginSuccess (cs role) (cs uid)
|
||||||
|
_ -> LoginFailed
|
||||||
_ -> LoginFailed
|
_ -> LoginFailed
|
||||||
where
|
where
|
||||||
maybeRole = (Data.Map.lookup "role" <$> claims) ::Maybe (Maybe Value)
|
maybeRole = (Data.Map.lookup "role" <$> claims) ::Maybe (Maybe Value)
|
||||||
|
maybeUserId = (Data.Map.lookup "id" <$> claims) ::Maybe (Maybe Value)
|
||||||
claims = JWT.unregisteredClaims <$> JWT.claims <$> decoded
|
claims = JWT.unregisteredClaims <$> JWT.claims <$> decoded
|
||||||
decoded = JWT.decodeAndVerifySignature (JWT.secret secret) input
|
decoded = JWT.decodeAndVerifySignature (JWT.secret secret) input
|
||||||
|
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ import Network.Wai (Application, requestHeaders, responseLBS, rawPathInfo,
|
|||||||
import Network.URI (URI(..), parseURI)
|
import Network.URI (URI(..), parseURI)
|
||||||
|
|
||||||
import PostgREST.Config (AppConfig(..))
|
import PostgREST.Config (AppConfig(..))
|
||||||
import PostgREST.Auth (LoginAttempt(..), signInRole, signInWithJWT, setRole, resetRole)
|
import PostgREST.Auth (LoginAttempt(..), signInRole, signInWithJWT, setRole, resetRole, setUserId, resetUserId)
|
||||||
import Codec.Binary.Base64.String (decode)
|
import Codec.Binary.Base64.String (decode)
|
||||||
|
|
||||||
import Prelude
|
import Prelude
|
||||||
@@ -35,8 +35,8 @@ authenticated conf app req = do
|
|||||||
return $ responseLBS status400 [] "Malformed basic auth header"
|
return $ responseLBS status400 [] "Malformed basic auth header"
|
||||||
LoginFailed ->
|
LoginFailed ->
|
||||||
return $ responseLBS status401 [] "Invalid username or password"
|
return $ responseLBS status401 [] "Invalid username or password"
|
||||||
LoginSuccess role -> if role /= currentRole then runInRole role else app req
|
LoginSuccess role uid -> if role /= currentRole then runInRole role uid else app req
|
||||||
NoCredentials -> if anon /= currentRole then runInRole anon else app req
|
NoCredentials -> if anon /= currentRole then runInRole anon "" else app req
|
||||||
|
|
||||||
where
|
where
|
||||||
jwtSecret = cs $ configJwtSecret conf
|
jwtSecret = cs $ configJwtSecret conf
|
||||||
@@ -54,11 +54,13 @@ authenticated conf app req = do
|
|||||||
return $ signInWithJWT jwtSecret jwt
|
return $ signInWithJWT jwtSecret jwt
|
||||||
_ -> return NoCredentials
|
_ -> return NoCredentials
|
||||||
|
|
||||||
runInRole :: Text -> H.Tx P.Postgres s Response
|
runInRole :: Text -> Text -> H.Tx P.Postgres s Response
|
||||||
runInRole r = do
|
runInRole r uid = do
|
||||||
|
setUserId uid
|
||||||
setRole r
|
setRole r
|
||||||
res <- app req
|
res <- app req
|
||||||
resetRole
|
resetRole
|
||||||
|
resetUserId
|
||||||
return res
|
return res
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -175,6 +175,7 @@ wherePred (col, predicate) =
|
|||||||
"like" -> unknownLiteral $ T.map star value
|
"like" -> unknownLiteral $ T.map star value
|
||||||
"ilike" -> unknownLiteral $ T.map star value
|
"ilike" -> unknownLiteral $ T.map star value
|
||||||
"in" -> "(" <> T.intercalate ", " (map unknownLiteral $ T.split (==',') value) <> ") "
|
"in" -> "(" <> T.intercalate ", " (map unknownLiteral $ T.split (==',') value) <> ") "
|
||||||
|
"@@" -> "to_tsquery(" <> unknownLiteral value <> ") "
|
||||||
_ -> unknownLiteral value
|
_ -> unknownLiteral value
|
||||||
|
|
||||||
op = case opCode of
|
op = case opCode of
|
||||||
@@ -189,6 +190,7 @@ wherePred (col, predicate) =
|
|||||||
"in" -> "in"
|
"in" -> "in"
|
||||||
"is" -> "is"
|
"is" -> "is"
|
||||||
"isnot" -> "is not"
|
"isnot" -> "is not"
|
||||||
|
"@@" -> "@@"
|
||||||
_ -> "="
|
_ -> "="
|
||||||
|
|
||||||
orderParse :: Net.Query -> [OrderTerm]
|
orderParse :: Net.Query -> [OrderTerm]
|
||||||
|
|||||||
@@ -274,3 +274,23 @@ spec = afterAll_ resetDb $ around withApp $ do
|
|||||||
[("Prefer", "return=representation")]
|
[("Prefer", "return=representation")]
|
||||||
[json| { id: 99 } |]
|
[json| { id: 99 } |]
|
||||||
`shouldRespondWith` [json| [{id:99}] |]
|
`shouldRespondWith` [json| [{id:99}] |]
|
||||||
|
|
||||||
|
describe "Row level permission" $
|
||||||
|
it "set user_id when inserting rows" $ do
|
||||||
|
_ <- post "/postgrest/users" [json| { "id":"jdoe", "pass": "1234", "role": "postgrest_test_author" } |]
|
||||||
|
_ <- post "/postgrest/users" [json| { "id":"jroe", "pass": "1234", "role": "postgrest_test_author" } |]
|
||||||
|
|
||||||
|
p1 <- request methodPost "/authors_only"
|
||||||
|
[ authHeaderBasic "jdoe" "1234", ("Prefer", "return=representation") ]
|
||||||
|
[json| { "secret": "nyancat" } |]
|
||||||
|
liftIO $ do
|
||||||
|
simpleBody p1 `shouldBe` [json| { "owner":"jdoe", "secret":"nyancat" } |]
|
||||||
|
simpleStatus p1 `shouldBe` created201
|
||||||
|
|
||||||
|
p2 <- request methodPost "/authors_only"
|
||||||
|
-- jwt token for jroe
|
||||||
|
[ authHeaderJWT "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJyb2xlIjoicG9zdGdyZXN0X3Rlc3RfYXV0aG9yIiwiaWQiOiJqcm9lIn0.YuF_VfmyIxWyuceT7crnNKEprIYXsJAyXid3rjPjIow", ("Prefer", "return=representation") ]
|
||||||
|
[json| { "secret": "lolcat", "owner": "hacker" } |]
|
||||||
|
liftIO $ do
|
||||||
|
simpleBody p2 `shouldBe` [json| { "owner":"jroe", "secret":"lolcat" } |]
|
||||||
|
simpleStatus p2 `shouldBe` created201
|
||||||
|
|||||||
@@ -56,6 +56,10 @@ spec =
|
|||||||
get "/simple_pk?k=ilike.*YY*&order=extra.asc" `shouldRespondWith`
|
get "/simple_pk?k=ilike.*YY*&order=extra.asc" `shouldRespondWith`
|
||||||
"[{\"k\":\"xyyx\",\"extra\":\"u\"},{\"k\":\"xYYx\",\"extra\":\"v\"}]"
|
"[{\"k\":\"xyyx\",\"extra\":\"u\"},{\"k\":\"xYYx\",\"extra\":\"v\"}]"
|
||||||
|
|
||||||
|
it "matches with tsearch @@" $
|
||||||
|
get "/tsearch?text_search_vector=@@.foo" `shouldRespondWith`
|
||||||
|
"[{\"text_search_vector\":\"'bar':2 'foo':1\"}]"
|
||||||
|
|
||||||
describe "ordering response" $ do
|
describe "ordering response" $ do
|
||||||
it "by a column asc" $
|
it "by a column asc" $
|
||||||
get "/items?id=lte.2&order=id.asc"
|
get "/items?id=lte.2&order=id.asc"
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ spec = around withApp $ do
|
|||||||
, {"schema":"1","name":"menagerie","insertable":true}
|
, {"schema":"1","name":"menagerie","insertable":true}
|
||||||
, {"schema":"1","name":"no_pk","insertable":true}
|
, {"schema":"1","name":"no_pk","insertable":true}
|
||||||
, {"schema":"1","name":"simple_pk","insertable":true}
|
, {"schema":"1","name":"simple_pk","insertable":true}
|
||||||
|
, {"schema":"1","name":"tsearch","insertable":true}
|
||||||
] |]
|
] |]
|
||||||
{matchStatus = 200}
|
{matchStatus = 200}
|
||||||
|
|
||||||
|
|||||||
@@ -79,7 +79,7 @@ spec = around dbWithSchema $ do
|
|||||||
addUser user pass role conn
|
addUser user pass role conn
|
||||||
return conn) $ do
|
return conn) $ do
|
||||||
it "accepts correct credentials and return the role" $ \conn ->
|
it "accepts correct credentials and return the role" $ \conn ->
|
||||||
signInRole user pass conn `shouldReturn` LoginSuccess role
|
signInRole user pass conn `shouldReturn` LoginSuccess role user
|
||||||
|
|
||||||
it "returns nothing with bad creds" $ \conn -> do
|
it "returns nothing with bad creds" $ \conn -> do
|
||||||
signInRole "not-a-user" pass conn `shouldReturn` LoginFailed
|
signInRole "not-a-user" pass conn `shouldReturn` LoginFailed
|
||||||
|
|||||||
Vendored
+29
-8
@@ -72,6 +72,18 @@ $$;
|
|||||||
|
|
||||||
ALTER FUNCTION postgrest.update_owner() OWNER TO postgrest_test;
|
ALTER FUNCTION postgrest.update_owner() OWNER TO postgrest_test;
|
||||||
|
|
||||||
|
|
||||||
|
CREATE FUNCTION set_authors_only_owner() RETURNS trigger
|
||||||
|
LANGUAGE plpgsql
|
||||||
|
AS $$
|
||||||
|
begin
|
||||||
|
NEW.owner = current_setting('user_vars.user_id');
|
||||||
|
RETURN NEW;
|
||||||
|
end
|
||||||
|
$$;
|
||||||
|
|
||||||
|
ALTER FUNCTION postgrest.set_authors_only_owner() OWNER TO postgrest_test;
|
||||||
|
|
||||||
SET search_path = "1", pg_catalog;
|
SET search_path = "1", pg_catalog;
|
||||||
|
|
||||||
SET default_tablespace = '';
|
SET default_tablespace = '';
|
||||||
@@ -80,6 +92,7 @@ SET default_with_oids = false;
|
|||||||
|
|
||||||
|
|
||||||
CREATE TABLE authors_only (
|
CREATE TABLE authors_only (
|
||||||
|
owner character varying NOT NULL,
|
||||||
secret character varying NOT NULL
|
secret character varying NOT NULL
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -212,6 +225,12 @@ CREATE TABLE json
|
|||||||
ALTER TABLE "1".json OWNER TO postgrest_test;
|
ALTER TABLE "1".json OWNER TO postgrest_test;
|
||||||
|
|
||||||
|
|
||||||
|
CREATE TABLE tsearch (
|
||||||
|
text_search_vector tsvector
|
||||||
|
);
|
||||||
|
|
||||||
|
ALTER TABLE "1".tsearch OWNER TO postgrest_test;
|
||||||
|
|
||||||
SET search_path = postgrest, pg_catalog;
|
SET search_path = postgrest, pg_catalog;
|
||||||
|
|
||||||
|
|
||||||
@@ -299,14 +318,8 @@ INSERT INTO items (id) VALUES (1);
|
|||||||
SELECT pg_catalog.setval('items_id_seq', 1, true);
|
SELECT pg_catalog.setval('items_id_seq', 1, true);
|
||||||
|
|
||||||
|
|
||||||
|
INSERT INTO tsearch (text_search_vector) VALUES ('''bar'':2 ''foo'':1');
|
||||||
|
INSERT INTO tsearch (text_search_vector) VALUES ('''baz'':1 ''qux'':2');
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
SET search_path = postgrest, pg_catalog;
|
SET search_path = postgrest, pg_catalog;
|
||||||
|
|
||||||
@@ -328,6 +341,7 @@ SET search_path = "1", pg_catalog;
|
|||||||
ALTER TABLE ONLY authors_only
|
ALTER TABLE ONLY authors_only
|
||||||
ADD CONSTRAINT authors_only_pkey PRIMARY KEY (secret);
|
ADD CONSTRAINT authors_only_pkey PRIMARY KEY (secret);
|
||||||
|
|
||||||
|
CREATE TRIGGER secrets_owner_track BEFORE INSERT OR UPDATE ON authors_only FOR EACH ROW EXECUTE PROCEDURE postgrest.set_authors_only_owner();
|
||||||
|
|
||||||
|
|
||||||
ALTER TABLE ONLY auto_incrementing_pk
|
ALTER TABLE ONLY auto_incrementing_pk
|
||||||
@@ -491,6 +505,13 @@ GRANT ALL ON TABLE json TO postgrest_test;
|
|||||||
GRANT ALL ON TABLE json TO postgrest_anonymous;
|
GRANT ALL ON TABLE json TO postgrest_anonymous;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
REVOKE ALL ON TABLE tsearch FROM PUBLIC;
|
||||||
|
REVOKE ALL ON TABLE tsearch FROM postgrest_test;
|
||||||
|
GRANT ALL ON TABLE tsearch TO postgrest_test;
|
||||||
|
GRANT ALL ON TABLE tsearch TO postgrest_anonymous;
|
||||||
|
|
||||||
|
|
||||||
SET search_path = postgrest, pg_catalog;
|
SET search_path = postgrest, pg_catalog;
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user