From e04f0caa6c300576d241a6abdd7eaf8e39af1fb8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juan=20Ignacio=20S=C3=A1nchez=20Lara?= Date: Mon, 10 Aug 2015 13:40:59 +0200 Subject: [PATCH] Permission granting --- README.md | 5 +++ scripts-available/CDB_Groups.sql | 63 ++++++++++++++++++++++++++++++++ test/organization/test.sh | 35 +++++++++++++----- 3 files changed, 94 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 771fe12..ec166ca 100644 --- a/README.md +++ b/README.md @@ -98,3 +98,8 @@ ls `pg_config --sharedir`/extension/cartodb* During development the cartodb extension version doesn't change with every commit, so testing latest change requires special steps documented in the CONTRIBUTING document, under "Testing changes live". + +Limitations +----------- + +- The main schema of an organization user must have one only owner (the user). diff --git a/scripts-available/CDB_Groups.sql b/scripts-available/CDB_Groups.sql index 751a86b..ebf824c 100644 --- a/scripts-available/CDB_Groups.sql +++ b/scripts-available/CDB_Groups.sql @@ -14,10 +14,12 @@ BEGIN END $$ LANGUAGE PLPGSQL; +-- Drops group and everything that role owns CREATE OR REPLACE FUNCTION cartodb.CDB_Group_DropGroup(group_name text) RETURNS VOID AS $$ BEGIN + EXECUTE 'DROP OWNED BY "' || cartodb.CDB_Group_GroupRole(group_name) || '"'; EXECUTE 'DROP ROLE IF EXISTS "' || cartodb.CDB_Group_GroupRole(group_name) || '"'; END $$ LANGUAGE PLPGSQL; @@ -31,6 +33,55 @@ BEGIN END $$ LANGUAGE PLPGSQL; +CREATE OR REPLACE +FUNCTION cartodb.CDB_Group_AddMember(group_name text, username text) + RETURNS VOID AS $$ +DECLARE + cdb_group_role TEXT; + cdb_user_role TEXT; +BEGIN + cdb_group_role := cartodb.CDB_Group_GroupRole(group_name); + cdb_user_role := cartodb.CDB_User_RoleFromUsername(username); + EXECUTE 'GRANT "' || cdb_group_role || '" TO "' || cdb_user_role || '"'; +END +$$ LANGUAGE PLPGSQL; + +CREATE OR REPLACE +FUNCTION cartodb.CDB_Group_RemoveMember(group_name text, username text) + RETURNS VOID AS $$ +DECLARE + cdb_group_role TEXT; + cdb_user_role TEXT; +BEGIN + cdb_group_role := cartodb.CDB_Group_GroupRole(group_name); + cdb_user_role := cartodb.CDB_User_RoleFromUsername(username); + EXECUTE 'REVOKE "' || cdb_group_role || '" FROM "' || cdb_user_role || '"'; +END +$$ LANGUAGE PLPGSQL; + +CREATE OR REPLACE +FUNCTION cartodb.CDB_Group_Table_GrantRead(group_name text, username text, table_name text) + RETURNS VOID AS $$ +DECLARE + cdb_group_role TEXT; +BEGIN + cdb_group_role := cartodb.CDB_Group_GroupRole(group_name); + EXECUTE 'GRANT USAGE ON SCHEMA "' || username || '" TO "' || cdb_group_role || '"'; + EXECUTE 'GRANT SELECT ON TABLE "' || username || '"."' || table_name || '" TO "' || cdb_group_role || '"'; +END +$$ LANGUAGE PLPGSQL; + +CREATE OR REPLACE +FUNCTION cartodb.CDB_Group_Table_RevokeAll(group_name text, username text, table_name text) + RETURNS VOID AS $$ +DECLARE + cdb_group_role TEXT; +BEGIN + cdb_group_role := cartodb.CDB_Group_GroupRole(group_name); + EXECUTE 'REVOKE ALL ON TABLE "' || username || '"."' || table_name || '" FROM "' || cdb_group_role || '"'; +END +$$ LANGUAGE PLPGSQL; + ----------------------- -- Private functions ----------------------- @@ -41,3 +92,15 @@ BEGIN RETURN cartoDB.CDB_Organization_Member_Group_Role_Member_Name() || '_g_' || group_name; END $$ LANGUAGE PLPGSQL; + +-- Returns the first owner of the schema matching username. Organization user schemas must have one only owner. +CREATE OR REPLACE +FUNCTION cartodb.CDB_User_RoleFromUsername(username text) + RETURNS TEXT AS $$ +DECLARE + user_role TEXT; +BEGIN + EXECUTE 'SELECT SCHEMA_OWNER FROM INFORMATION_SCHEMA.SCHEMATA WHERE SCHEMA_NAME = ''' || username || ''' LIMIT 1' INTO user_role; + RETURN user_role; +END +$$ LANGUAGE PLPGSQL; diff --git a/test/organization/test.sh b/test/organization/test.sh index 9e68d61..f19f236 100644 --- a/test/organization/test.sh +++ b/test/organization/test.sh @@ -11,8 +11,6 @@ DATABASE=test_organizations CMD='echo psql' CMD=psql -GROUP_A="group_a" - OK=0 PARTIALOK=0 @@ -144,8 +142,8 @@ function setup() { log_info "############################# SETUP #############################" create_role_and_schema cdb_testmember_1 create_role_and_schema cdb_testmember_2 - sql "CREATE ROLE publicuser LOGIN;" - sql "GRANT CONNECT ON DATABASE \"${DATABASE}\" TO publicuser;" + #sql "CREATE ROLE publicuser LOGIN;" + #sql "GRANT CONNECT ON DATABASE \"${DATABASE}\" TO publicuser;" create_table cdb_testmember_1 foo sql cdb_testmember_1 'INSERT INTO cdb_testmember_1.foo VALUES (1), (2), (3), (4), (5);' @@ -155,8 +153,10 @@ function setup() { sql cdb_testmember_2 'INSERT INTO bar VALUES (1), (2), (3), (4), (5);' sql cdb_testmember_2 'SELECT * FROM cdb_testmember_2.bar;' - sql "SELECT cartodb.CDB_Group_CreateGroup('${GROUP_A}_tmp')" - sql "SELECT cartodb.CDB_Group_RenameGroup('${GROUP_A}_tmp', '${GROUP_A}')" + sql "SELECT cartodb.CDB_Group_CreateGroup('group_a_tmp')" + sql "SELECT cartodb.CDB_Group_RenameGroup('group_a_tmp', 'group_a')" + + sql "SELECT cartodb.CDB_Group_AddMember('group_a', 'cdb_testmember_1')" } @@ -168,7 +168,9 @@ function tear_down() { sql cdb_testmember_1 'DROP TABLE cdb_testmember_1.foo;' sql cdb_testmember_2 'DROP TABLE cdb_testmember_2.bar;' - sql "select cartodb.CDB_Group_DropGroup('${GROUP_A}')" + sql "SELECT cartodb.CDB_Group_RemoveMember('group_a', 'cdb_testmember_1')" + + sql "select cartodb.CDB_Group_DropGroup('group_a')" sql "DROP SCHEMA cartodb CASCADE" @@ -178,11 +180,11 @@ function tear_down() { sql "REVOKE CONNECT ON DATABASE \"${DATABASE}\" FROM cdb_testmember_1;" sql "REVOKE CONNECT ON DATABASE \"${DATABASE}\" FROM cdb_testmember_2;" - sql "REVOKE CONNECT ON DATABASE \"${DATABASE}\" FROM publicuser;" + #sql "REVOKE CONNECT ON DATABASE \"${DATABASE}\" FROM publicuser;" sql 'DROP ROLE cdb_testmember_1;' sql 'DROP ROLE cdb_testmember_2;' - sql 'DROP ROLE publicuser;' + #sql 'DROP ROLE publicuser;' ${CMD} -c "DROP DATABASE ${DATABASE}" } @@ -401,6 +403,21 @@ function test_cdb_usertables_should_work_with_orgusers() { sql cdb_testmember_1 "DROP TABLE test_perms_priv" } +function test_CDB_Group_Table_GrantRead_should_grant_select_and_RevokeAll_should_remove() { + create_table cdb_testmember_2 shared_with_group + + sql cdb_testmember_1 'SELECT count(*) FROM cdb_testmember_2.shared_with_group;' fails + sql cdb_testmember_2 'SELECT count(*) FROM cdb_testmember_2.shared_with_group;' + sql cdb_testmember_2 "select cartoDB.CDB_Group_Table_GrantRead('group_a', 'cdb_testmember_2', 'shared_with_group')" + sql cdb_testmember_1 'SELECT count(*) FROM cdb_testmember_2.shared_with_group;' + sql cdb_testmember_2 'SELECT count(*) FROM cdb_testmember_2.shared_with_group;' + sql cdb_testmember_2 "select cartoDB.CDB_Group_Table_RevokeAll('group_a', 'cdb_testmember_2', 'shared_with_group')" + sql cdb_testmember_1 'SELECT count(*) FROM cdb_testmember_2.shared_with_group;' fails + sql cdb_testmember_2 'SELECT count(*) FROM cdb_testmember_2.shared_with_group;' + + sql cdb_testmember_2 'DROP TABLE cdb_testmember_2.shared_with_group;' +} + #################################################### TESTS END HERE ####################################################