From d4bcb97f9b26dee5b0eca91d65d3a0d734b560ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juan=20Ignacio=20S=C3=A1nchez=20Lara?= Date: Fri, 14 Aug 2015 13:55:52 +0200 Subject: [PATCH] CDB_CONF and create and drop group api calls --- scripts-available/CDB_Conf.sql | 20 +++++----- scripts-available/CDB_Groups.sql | 27 +++++++++++--- scripts-available/CDB_Groups_API.sql | 55 ++++++++++++++++++++++++++++ test/organization/test.sh | 18 ++++++--- 4 files changed, 99 insertions(+), 21 deletions(-) create mode 100644 scripts-available/CDB_Groups_API.sql diff --git a/scripts-available/CDB_Conf.sql b/scripts-available/CDB_Conf.sql index ff22588..a51136b 100644 --- a/scripts-available/CDB_Conf.sql +++ b/scripts-available/CDB_Conf.sql @@ -1,34 +1,34 @@ -- This will trigger NOTICE if CDB_CONF already exists DO LANGUAGE 'plpgsql' $$ BEGIN - CREATE TABLE IF NOT EXISTS CDB_CONF ( PARAM TEXT PRIMARY KEY, VALUE TEXT NOT NULL ); + CREATE TABLE IF NOT EXISTS cartodb.CDB_CONF ( PARAM TEXT PRIMARY KEY, CONF TEXT NOT NULL ); END $$; CREATE OR REPLACE -FUNCTION cartodb.CDB_Conf_SetParam(param text, value text) +FUNCTION cartodb.CDB_Conf_SetConf(param text, conf text) RETURNS void AS $$ BEGIN - PERFORM cartodb.CDB_Conf_RemoveParam(param); - EXECUTE 'INSERT INTO CDB_CONF (PARAM, VALUE) VALUES ($1, $2);' USING param, value; + PERFORM cartodb.CDB_Conf_RemoveConf(param); + EXECUTE 'INSERT INTO cartodb.CDB_CONF (PARAM, CONF) VALUES ($1, $2);' USING param, conf; END $$ LANGUAGE PLPGSQL VOLATILE; CREATE OR REPLACE -FUNCTION cartodb.CDB_Conf_RemoveParam(param text) +FUNCTION cartodb.CDB_Conf_RemoveConf(param text) RETURNS void AS $$ BEGIN - EXECUTE 'DELETE FROM CDB_CONF WHERE PARAM = $1;' USING param; + EXECUTE 'DELETE FROM cartodb.CDB_CONF WHERE PARAM = $1;' USING param; END $$ LANGUAGE PLPGSQL VOLATILE; CREATE OR REPLACE -FUNCTION cartodb.CDB_Conf_GetParam(param text) +FUNCTION cartodb.CDB_Conf_GetConf(param text) RETURNS TEXT AS $$ DECLARE - value TEXT; + conf TEXT; BEGIN - EXECUTE 'SELECT VALUE FROM CDB_CONF WHERE PARAM = $1;' INTO value USING param; - RETURN value; + EXECUTE 'SELECT CONF FROM cartodb.CDB_CONF WHERE PARAM = $1;' INTO conf USING param; + RETURN conf; END $$ LANGUAGE PLPGSQL STABLE; diff --git a/scripts-available/CDB_Groups.sql b/scripts-available/CDB_Groups.sql index 9aec6c1..e036531 100644 --- a/scripts-available/CDB_Groups.sql +++ b/scripts-available/CDB_Groups.sql @@ -3,9 +3,11 @@ CREATE OR REPLACE FUNCTION cartodb.CDB_Group_CreateGroup(group_name text) RETURNS VOID AS $$ DECLARE - cdb_group_role TEXT; + group_role TEXT; BEGIN - EXECUTE 'CREATE ROLE "' || cdb_group_role || '" NOLOGIN;'; + group_role := cartodb._CDB_Group_GroupRole(group_name); + PERFORM cartodb._CDB_Group_CreateGroup_API(current_database(), group_name, group_role); + EXECUTE 'CREATE ROLE "' || group_role || '" NOLOGIN;'; END $$ LANGUAGE PLPGSQL VOLATILE; @@ -21,6 +23,7 @@ DECLARE cdb_group_role TEXT; BEGIN cdb_group_role := cartodb._CDB_Group_GroupRole(group_name); + PERFORM cartodb._CDB_Group_DropGroup_API(current_database(), group_name); EXECUTE 'DROP OWNED BY "' || cdb_group_role || '"'; EXECUTE 'DROP ROLE IF EXISTS "' || cdb_group_role || '"'; END @@ -110,16 +113,18 @@ FUNCTION cartodb._CDB_Group_GroupRole(group_name text) RETURNS TEXT AS $$ DECLARE group_role TEXT; - max_length constant INTEGER := 60; + prefix TEXT; + max_length constant INTEGER := 63; BEGIN IF group_name !~ '^[a-zA-Z_][a-zA-Z0-9_]*$' THEN RAISE EXCEPTION 'Group name (%) must be a valid identifier. See http://www.postgresql.org/docs/9.2/static/sql-syntax-lexical.html#SQL-SYNTAX-IDENTIFIERS', group_name; END IF; - group_role := current_database() || '_g_' || group_name; + prefix = cartodb._CDB_Group_ShortDatabaseName() || '_g_'; + group_role := prefix || group_name; IF LENGTH(group_role) > max_length THEN - RAISE EXCEPTION 'Group name should be shorter. Resulting role must have less than % characters, but it is longer: %', max_length, group_role; + RAISE EXCEPTION 'Group name must be shorter. It can''t have more than % characters, but it is longer (%): %', max_length - LENGTH(prefix), length(group_name), group_name; END IF; RETURN group_role; END @@ -138,3 +143,15 @@ BEGIN RETURN user_role; END $$ LANGUAGE PLPGSQL IMMUTABLE; + +-- Database names are too long, we need a shorter version for composing role names +CREATE OR REPLACE +FUNCTION cartodb._CDB_Group_ShortDatabaseName() + RETURNS TEXT AS $$ +DECLARE + short_database_name TEXT; +BEGIN + EXECUTE 'SELECT md5(current_database())' INTO short_database_name; + RETURN short_database_name; +END +$$ LANGUAGE PLPGSQL IMMUTABLE; diff --git a/scripts-available/CDB_Groups_API.sql b/scripts-available/CDB_Groups_API.sql new file mode 100644 index 0000000..5f82706 --- /dev/null +++ b/scripts-available/CDB_Groups_API.sql @@ -0,0 +1,55 @@ +-- Sends the create group request +CREATE OR REPLACE +FUNCTION cartodb._CDB_Group_CreateGroup_API(database_name text, group_name text, group_role text) + RETURNS VOID AS +$$ + import httplib + import base64 + import string + import json + + try: + conf = plpy.execute("SELECT cartodb.CDB_Conf_GetConf('groups_api') conf")[0]['conf'] + if conf is None: + return + params = json.loads(conf) + client = httplib.HTTPConnection(params['host'], params['port'], False, params['timeout']) + url = '/api/v1/databases/%s/groups' % database_name + body = '{ "name": "%s", "database_role": "%s" }' % (group_name, group_role) + auth = base64.encodestring('%s:%s' % (params['username'], params['password'])).replace('\n', '') + headers = { 'Authorization': ('Basic %s' % auth), 'Content-Type': 'application/json' } + client.request('POST', url, body, headers) + response = client.getresponse() + assert response.status == 200 + except Exception as err: + plpy.warning('group creation error: ' + str(err)) + raise err + +$$ LANGUAGE 'plpythonu' VOLATILE; + +CREATE OR REPLACE +FUNCTION cartodb._CDB_Group_DropGroup_API(database_name text, group_name text) + RETURNS VOID AS +$$ + import httplib + import base64 + import string + import json + + try: + conf = plpy.execute("SELECT cartodb.CDB_Conf_GetConf('groups_api') conf")[0]['conf'] + if conf is None: + return + params = json.loads(conf) + client = httplib.HTTPConnection(params['host'], params['port'], False, params['timeout']) + url = '/api/v1/databases/%s/groups/%s' % (database_name, group_name) + auth = base64.encodestring('%s:%s' % (params['username'], params['password'])).replace('\n', '') + headers = { 'Authorization': ('Basic %s' % auth), 'Content-Type': 'application/json' } + client.request('DELETE', url, '', headers) + response = client.getresponse() + assert response.status == 200 + except Exception as err: + plpy.warning('group creation error: ' + str(err)) + raise err + +$$ LANGUAGE 'plpythonu' VOLATILE; diff --git a/test/organization/test.sh b/test/organization/test.sh index 4cb1cc3..c1e86f3 100644 --- a/test/organization/test.sh +++ b/test/organization/test.sh @@ -159,9 +159,11 @@ function create_table() { function setup() { ${CMD} -c "CREATE DATABASE ${DATABASE}" sql "CREATE SCHEMA cartodb;" + sql "CREATE EXTENSION plpythonu;" sql "GRANT USAGE ON SCHEMA cartodb TO public;" log_info "########################### BOOTSTRAP ###########################" + ${CMD} -d ${DATABASE} -f scripts-available/CDB_Conf.sql ${CMD} -d ${DATABASE} -f scripts-available/CDB_Organizations.sql ${CMD} -d ${DATABASE} -f scripts-available/CDB_Groups.sql ${CMD} -d ${DATABASE} -f scripts-available/CDB_Groups_API.sql @@ -378,21 +380,18 @@ function test_user_can_read_when_it_has_permission_after_organization_permission } function test_cdb_querytables_returns_schema_and_table_name() { - sql "CREATE EXTENSION plpythonu;" ${CMD} -d ${DATABASE} -f scripts-available/CDB_QueryStatements.sql ${CMD} -d ${DATABASE} -f scripts-available/CDB_QueryTables.sql sql cdb_testmember_1 "select * from CDB_QueryTables('select * from foo');" should "{cdb_testmember_1.foo}" } function test_cdb_querytables_returns_schema_and_table_name_for_several_schemas() { - sql "CREATE EXTENSION plpythonu;" ${CMD} -d ${DATABASE} -f scripts-available/CDB_QueryStatements.sql ${CMD} -d ${DATABASE} -f scripts-available/CDB_QueryTables.sql sql postgres "select * from CDB_QueryTables('select * from cdb_testmember_1.foo, cdb_testmember_2.bar');" should "{cdb_testmember_1.foo,cdb_testmember_2.bar}" } function test_cdb_querytables_does_not_return_functions_as_part_of_the_resultset() { - sql "CREATE EXTENSION plpythonu;" ${CMD} -d ${DATABASE} -f scripts-available/CDB_QueryStatements.sql ${CMD} -d ${DATABASE} -f scripts-available/CDB_QueryTables.sql sql postgres "select * from CDB_QueryTables('select * from cdb_testmember_1.foo, cdb_testmember_2.bar, plainto_tsquery(''foo'')');" should "{cdb_testmember_1.foo,cdb_testmember_2.bar}" @@ -519,9 +518,9 @@ function test_org_admin_cant_grant_permissions_on_tables_he_does_not_own() { } function test_valid_group_names() { - sql "select cartodb._CDB_Group_GroupRole('group_1$_a');" - sql "select cartodb._CDB_Group_GroupRole('GROUP_1$_A');" - sql "select cartodb._CDB_Group_GroupRole('_group_1$_a');" + sql postgres "select cartodb._CDB_Group_GroupRole('group_1$_a');" + sql postgres "select cartodb._CDB_Group_GroupRole('GROUP_1$_A');" + sql postgres "select cartodb._CDB_Group_GroupRole('_group_1$_a');" } function test_not_valid_group_names() { @@ -538,6 +537,13 @@ function test_administrator_name_generation() { sql postgres "select cartodb._CDB_Organization_Admin_Role_Name();" } +function test_conf() { + sql postgres "SELECT cartodb.CDB_Conf_SetConf('test_conf', 'test_val')" + sql postgres "SELECT cartodb.CDB_Conf_GetConf('test_conf')" should 'test_val' + sql postgres "SELECT cartodb.CDB_Conf_RemoveConf('test_conf')" + sql postgres "SELECT cartodb.CDB_Conf_GetConf('test_conf')" should '' +} + #################################################### TESTS END HERE ####################################################