All green :D
This commit is contained in:
@@ -44,7 +44,7 @@ doesProcReturnJWT = doesProc [H.stmt|
|
|||||||
ON pronamespace = n.oid
|
ON pronamespace = n.oid
|
||||||
WHERE nspname = ?
|
WHERE nspname = ?
|
||||||
AND proname = ?
|
AND proname = ?
|
||||||
AND pg_catalog.pg_get_function_result(p.oid) = 'jwt'
|
AND pg_catalog.pg_get_function_result(p.oid) = 'jwt_claims'
|
||||||
|]
|
|]
|
||||||
|
|
||||||
tableFromRow :: (Text, Text, Bool, Maybe Text) -> Table
|
tableFromRow :: (Text, Text, Bool, Maybe Text) -> Table
|
||||||
@@ -167,7 +167,7 @@ allRelations = do
|
|||||||
allColumns :: [Relation] -> H.Tx P.Postgres s [Column]
|
allColumns :: [Relation] -> H.Tx P.Postgres s [Column]
|
||||||
allColumns rels = do
|
allColumns rels = do
|
||||||
cols <- H.listEx $ [H.stmt|
|
cols <- H.listEx $ [H.stmt|
|
||||||
SELECT
|
SELECT DISTINCT
|
||||||
info.table_schema AS schema,
|
info.table_schema AS schema,
|
||||||
info.table_name AS table_name,
|
info.table_name AS table_name,
|
||||||
info.column_name AS name,
|
info.column_name AS name,
|
||||||
|
|||||||
@@ -18,50 +18,11 @@ spec = beforeAll
|
|||||||
it "hides tables that anonymous does not own" $
|
it "hides tables that anonymous does not own" $
|
||||||
get "/authors_only" `shouldRespondWith` 404
|
get "/authors_only" `shouldRespondWith` 404
|
||||||
|
|
||||||
it "indicates login failure (BasicAuth)" $ do
|
it "returns jwt functions as jwt tokens" $ do
|
||||||
let auth = authHeaderBasic "postgrest_test_author" "fakefake"
|
post "/rpc/login" [json| { "id": "jdoe", "pass": "1234" } |]
|
||||||
request methodGet "/authors_only" [auth] ""
|
|
||||||
`shouldRespondWith` 401
|
|
||||||
|
|
||||||
it "allows users with permissions to see their tables (BasicAuth)" $ do
|
|
||||||
_ <- post "/postgrest/users" [json| { "id": "jdoe", "pass": "1234", "role": "postgrest_test_author" } |]
|
|
||||||
let auth = authHeaderBasic "jdoe" "1234"
|
|
||||||
request methodGet "/authors_only" [auth] ""
|
|
||||||
`shouldRespondWith` 200
|
|
||||||
|
|
||||||
it "respects database constraints for role" $
|
|
||||||
post "/postgrest/users" [json| { "id": "ssmith", "pass": "1234", "role": "SUPER_ADMIN_TRUNCATE_POWERS" } |]
|
|
||||||
`shouldRespondWith` 400
|
|
||||||
|
|
||||||
it "does not send a value when no role is provided" $ do
|
|
||||||
post "/postgrest/users" [json| { "id": "bdeey", "pass": "1234" } |]
|
|
||||||
`shouldRespondWith` 201
|
|
||||||
let auth = authHeaderBasic "jdoe" "1234"
|
|
||||||
request methodGet "/authors_only" [auth] ""
|
|
||||||
`shouldRespondWith` 200
|
|
||||||
|
|
||||||
it "recovers after 400 error with logged in user" $ do
|
|
||||||
_ <- post "/postgrest/users" [json| { "id": "jdoe", "pass": "1234", "role": "postgrest_test_author" } |]
|
|
||||||
let auth = authHeaderBasic "jdoe" "1234"
|
|
||||||
_ <- request methodPost "/rpc/problem" [auth] ""
|
|
||||||
request methodGet "/authors_only" [auth] ""
|
|
||||||
`shouldRespondWith` 200
|
|
||||||
|
|
||||||
it "allows users to login (JWT)" $ do
|
|
||||||
_ <- post "/postgrest/users" [json| { "id": "jdoe", "pass": "1234", "role": "postgrest_test_author" } |]
|
|
||||||
post "/postgrest/tokens" [json| { "id": "jdoe", "pass": "1234" } |]
|
|
||||||
`shouldRespondWith` ResponseMatcher {
|
`shouldRespondWith` ResponseMatcher {
|
||||||
matchBody = Just [json| {"token":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJyb2xlIjoicG9zdGdyZXN0X3Rlc3RfYXV0aG9yIiwiaWQiOiJqZG9lIn0.y4vZuu1dDdwAl0-S00MCRWRYMlJ5YAMSir6Es6WtWx0"} |]
|
matchBody = Just [json| {"token":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJyb2xlIjoicG9zdGdyZXN0X3Rlc3RfYXV0aG9yIiwiaWQiOiJqZG9lIn0.y4vZuu1dDdwAl0-S00MCRWRYMlJ5YAMSir6Es6WtWx0"} |]
|
||||||
, matchStatus = 201
|
, matchStatus = 200
|
||||||
, matchHeaders = ["Content-Type" <:> "application/json"]
|
|
||||||
}
|
|
||||||
|
|
||||||
it "indicates login failure (JWT)" $ do
|
|
||||||
_ <- post "/postgrest/users" [json| { "id": "jdoe", "pass": "1234", "role": "postgrest_test_author" } |]
|
|
||||||
post "/postgrest/tokens" [json| { "id": "jdoe", "pass": "NOPE" } |]
|
|
||||||
`shouldRespondWith` ResponseMatcher {
|
|
||||||
matchBody = Just [json| {"message":"Failed authentication."} |]
|
|
||||||
, matchStatus = 401
|
|
||||||
, matchHeaders = ["Content-Type" <:> "application/json"]
|
, matchHeaders = ["Content-Type" <:> "application/json"]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -284,11 +284,12 @@ spec = afterAll_ resetDb $ around withApp $ do
|
|||||||
|
|
||||||
describe "Row level permission" $
|
describe "Row level permission" $
|
||||||
it "set user_id when inserting rows" $ do
|
it "set user_id when inserting rows" $ do
|
||||||
|
let auth = authHeaderJWT "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJyb2xlIjoicG9zdGdyZXN0X3Rlc3RfYXV0aG9yIiwiaWQiOiJqZG9lIn0.y4vZuu1dDdwAl0-S00MCRWRYMlJ5YAMSir6Es6WtWx0"
|
||||||
_ <- post "/postgrest/users" [json| { "id":"jdoe", "pass": "1234", "role": "postgrest_test_author" } |]
|
_ <- post "/postgrest/users" [json| { "id":"jdoe", "pass": "1234", "role": "postgrest_test_author" } |]
|
||||||
_ <- post "/postgrest/users" [json| { "id":"jroe", "pass": "1234", "role": "postgrest_test_author" } |]
|
_ <- post "/postgrest/users" [json| { "id":"jroe", "pass": "1234", "role": "postgrest_test_author" } |]
|
||||||
|
|
||||||
p1 <- request methodPost "/authors_only"
|
p1 <- request methodPost "/authors_only"
|
||||||
[ authHeaderBasic "jdoe" "1234", ("Prefer", "return=representation") ]
|
[ auth, ("Prefer", "return=representation") ]
|
||||||
[json| { "secret": "nyancat" } |]
|
[json| { "secret": "nyancat" } |]
|
||||||
liftIO $ do
|
liftIO $ do
|
||||||
simpleBody p1 `shouldBe` [json| { "owner":"jdoe", "secret":"nyancat" } |]
|
simpleBody p1 `shouldBe` [json| { "owner":"jdoe", "secret":"nyancat" } |]
|
||||||
|
|||||||
@@ -40,8 +40,7 @@ spec = around withApp $ do
|
|||||||
{matchStatus = 200}
|
{matchStatus = 200}
|
||||||
|
|
||||||
it "lists only views user has permission to see" $ do
|
it "lists only views user has permission to see" $ do
|
||||||
_ <- post "/postgrest/users" [json| { "id":"jdoe", "pass": "1234", "role": "postgrest_test_author" } |]
|
let auth = authHeaderJWT "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJyb2xlIjoicG9zdGdyZXN0X3Rlc3RfYXV0aG9yIiwiaWQiOiJqZG9lIn0.y4vZuu1dDdwAl0-S00MCRWRYMlJ5YAMSir6Es6WtWx0"
|
||||||
let auth = authHeaderBasic "jdoe" "1234"
|
|
||||||
|
|
||||||
request methodGet "/" [auth] ""
|
request methodGet "/" [auth] ""
|
||||||
`shouldRespondWith` [json| [
|
`shouldRespondWith` [json| [
|
||||||
|
|||||||
Vendored
+25
-10
@@ -76,7 +76,7 @@ CREATE FUNCTION set_authors_only_owner() RETURNS trigger
|
|||||||
LANGUAGE plpgsql
|
LANGUAGE plpgsql
|
||||||
AS $$
|
AS $$
|
||||||
begin
|
begin
|
||||||
NEW.owner = current_setting('user_vars.user_id');
|
NEW.owner = current_setting('postgrest.claims.id');
|
||||||
RETURN NEW;
|
RETURN NEW;
|
||||||
end
|
end
|
||||||
$$;
|
$$;
|
||||||
@@ -268,15 +268,6 @@ CREATE VIEW test.projects_view AS
|
|||||||
projects.client_id
|
projects.client_id
|
||||||
FROM projects;
|
FROM projects;
|
||||||
ALTER TABLE test.projects_view OWNER TO postgrest_test;
|
ALTER TABLE test.projects_view OWNER TO postgrest_test;
|
||||||
------- SAMPLE DATA -----
|
|
||||||
INSERT INTO clients VALUES (1, 'Microsoft'),(2, 'Apple');
|
|
||||||
INSERT INTO projects VALUES (1,'Windows 7', 1),(2,'Windows 10', 1),(3,'IOS', 2),(4,'OSX', 2);
|
|
||||||
INSERT INTO tasks VALUES (1,'Design w7',1),(2,'Code w7',1),(3,'Design w10',2),(4,'Code w10',2),(5,'Design IOS',3),(6,'Code IOS',3),(7,'Design OSX',4),(8,'Code OSX',4);
|
|
||||||
INSERT INTO users VALUES (1, 'Angela Martin'),(2, 'Michael Scott'),(3, 'Dwight Schrute');
|
|
||||||
INSERT INTO users_projects VALUES(1,1),(1,2),(2,3),(2,4),(3,1),(3,3);
|
|
||||||
INSERT INTO users_tasks VALUES(1,1),(1,2),(1,3),(1,4),(2,5),(2,6),(2,7),(3,1),(3,5);
|
|
||||||
INSERT INTO comments VALUES (1, 1, 2, 6, 'Needs to be delivered ASAP');
|
|
||||||
----------------
|
|
||||||
|
|
||||||
CREATE SEQUENCE items_id_seq
|
CREATE SEQUENCE items_id_seq
|
||||||
START WITH 1
|
START WITH 1
|
||||||
@@ -298,6 +289,13 @@ CREATE FUNCTION test.getitemrange(min bigint, max bigint) RETURNS SETOF test.ite
|
|||||||
$$ LANGUAGE SQL;
|
$$ LANGUAGE SQL;
|
||||||
|
|
||||||
|
|
||||||
|
CREATE TYPE public.jwt_claims AS (role text, id text);
|
||||||
|
CREATE FUNCTION test.login(id text, pass text)
|
||||||
|
RETURNS public.jwt_claims
|
||||||
|
SECURITY DEFINER
|
||||||
|
AS $$
|
||||||
|
SELECT rolname::text, id::text FROM postgrest.auth WHERE id = id AND pass = pass;
|
||||||
|
$$ LANGUAGE SQL;
|
||||||
|
|
||||||
CREATE FUNCTION test.sayhello(name text) RETURNS text AS $$
|
CREATE FUNCTION test.sayhello(name text) RETURNS text AS $$
|
||||||
SELECT 'Hello, ' || $1;
|
SELECT 'Hello, ' || $1;
|
||||||
@@ -663,6 +661,10 @@ REVOKE ALL ON FUNCTION getitemrange(bigint, bigint) FROM postgrest_test;
|
|||||||
GRANT EXECUTE ON FUNCTION getitemrange(bigint, bigint) TO postgrest_test;
|
GRANT EXECUTE ON FUNCTION getitemrange(bigint, bigint) TO postgrest_test;
|
||||||
GRANT EXECUTE ON FUNCTION getitemrange(bigint, bigint) TO postgrest_anonymous;
|
GRANT EXECUTE ON FUNCTION getitemrange(bigint, bigint) TO postgrest_anonymous;
|
||||||
|
|
||||||
|
REVOKE ALL ON FUNCTION login(text, text) FROM PUBLIC;
|
||||||
|
REVOKE ALL ON FUNCTION login(text, text) FROM postgrest_test;
|
||||||
|
GRANT EXECUTE ON FUNCTION login(text, text) TO postgrest_test;
|
||||||
|
GRANT EXECUTE ON FUNCTION login(text, text) TO postgrest_anonymous;
|
||||||
|
|
||||||
REVOKE ALL ON FUNCTION sayhello(text) FROM PUBLIC;
|
REVOKE ALL ON FUNCTION sayhello(text) FROM PUBLIC;
|
||||||
REVOKE ALL ON FUNCTION sayhello(text) FROM postgrest_test;
|
REVOKE ALL ON FUNCTION sayhello(text) FROM postgrest_test;
|
||||||
@@ -758,3 +760,16 @@ SET search_path = private, pg_catalog;
|
|||||||
REVOKE ALL ON TABLE articles FROM PUBLIC;
|
REVOKE ALL ON TABLE articles FROM PUBLIC;
|
||||||
REVOKE ALL ON TABLE articles FROM postgrest_test;
|
REVOKE ALL ON TABLE articles FROM postgrest_test;
|
||||||
GRANT ALL ON TABLE articles TO postgrest_test;
|
GRANT ALL ON TABLE articles TO postgrest_test;
|
||||||
|
|
||||||
|
SET search_path = test, private, postgrest, public, pg_catalog;
|
||||||
|
|
||||||
|
------- SAMPLE DATA -----
|
||||||
|
INSERT INTO clients VALUES (1, 'Microsoft'),(2, 'Apple');
|
||||||
|
INSERT INTO projects VALUES (1,'Windows 7', 1),(2,'Windows 10', 1),(3,'IOS', 2),(4,'OSX', 2);
|
||||||
|
INSERT INTO tasks VALUES (1,'Design w7',1),(2,'Code w7',1),(3,'Design w10',2),(4,'Code w10',2),(5,'Design IOS',3),(6,'Code IOS',3),(7,'Design OSX',4),(8,'Code OSX',4);
|
||||||
|
INSERT INTO users VALUES (1, 'Angela Martin'),(2, 'Michael Scott'),(3, 'Dwight Schrute');
|
||||||
|
INSERT INTO users_projects VALUES(1,1),(1,2),(2,3),(2,4),(3,1),(3,3);
|
||||||
|
INSERT INTO users_tasks VALUES(1,1),(1,2),(1,3),(1,4),(2,5),(2,6),(2,7),(3,1),(3,5);
|
||||||
|
INSERT INTO comments VALUES (1, 1, 2, 6, 'Needs to be delivered ASAP');
|
||||||
|
INSERT INTO postgrest.auth (id, pass, rolname) VALUES ('jdoe', '1234', 'postgrest_test_author');
|
||||||
|
----------------
|
||||||
|
|||||||
Reference in New Issue
Block a user