Merge pull request #323 from CartoDB/314-exception-safe-public-funcs
314 exception safe public funcs
This commit is contained in:
commit
0918f91bfa
1
client/.gitignore
vendored
1
client/.gitignore
vendored
@ -2,6 +2,7 @@ results/
|
|||||||
regression.diffs
|
regression.diffs
|
||||||
regression.out
|
regression.out
|
||||||
20_public_functions.sql
|
20_public_functions.sql
|
||||||
|
25_exception_safe_private_functions.sql
|
||||||
30_plproxy_functions.sql
|
30_plproxy_functions.sql
|
||||||
90_grant_execute.sql
|
90_grant_execute.sql
|
||||||
cdb_geocoder_client--0.0.1.sql
|
cdb_geocoder_client--0.0.1.sql
|
||||||
|
@ -57,9 +57,11 @@ all: $(DATA)
|
|||||||
.PHONY: release
|
.PHONY: release
|
||||||
release: $(EXTENSION).control $(SOURCES_DATA)
|
release: $(EXTENSION).control $(SOURCES_DATA)
|
||||||
test -n "$(NEW_VERSION)" # $$NEW_VERSION VARIABLE MISSING. Eg. make release NEW_VERSION=0.x.0
|
test -n "$(NEW_VERSION)" # $$NEW_VERSION VARIABLE MISSING. Eg. make release NEW_VERSION=0.x.0
|
||||||
mv *.sql old_versions
|
git mv *.sql old_versions
|
||||||
$(SED) $(REPLACEMENTS) $(EXTENSION).control
|
$(SED) $(REPLACEMENTS) $(EXTENSION).control
|
||||||
|
git add $(EXTENSION).control
|
||||||
cat $(SOURCES_DATA_DIR)/*.sql > $(EXTENSION)--$(NEW_VERSION).sql
|
cat $(SOURCES_DATA_DIR)/*.sql > $(EXTENSION)--$(NEW_VERSION).sql
|
||||||
|
git add $(EXTENSION)--$(NEW_VERSION).sql
|
||||||
$(ERB) version=$(NEW_VERSION) upgrade_downgrade_template.erb > $(EXTENSION)--$(EXTVERSION)--$(NEW_VERSION).sql
|
$(ERB) version=$(NEW_VERSION) upgrade_downgrade_template.erb > $(EXTENSION)--$(EXTVERSION)--$(NEW_VERSION).sql
|
||||||
$(ERB) version=$(EXTVERSION) upgrade_downgrade_template.erb > $(EXTENSION)--$(NEW_VERSION)--$(EXTVERSION).sql
|
$(ERB) version=$(EXTVERSION) upgrade_downgrade_template.erb > $(EXTENSION)--$(NEW_VERSION)--$(EXTVERSION).sql
|
||||||
|
|
||||||
|
@ -0,0 +1,61 @@
|
|||||||
|
--
|
||||||
|
-- Exception-safe private DataServices API function
|
||||||
|
--
|
||||||
|
|
||||||
|
CREATE OR REPLACE FUNCTION <%= DATASERVICES_CLIENT_SCHEMA %>._<%= name %>_exception_safe (<%= params_with_type_and_default.join(' ,') %>)
|
||||||
|
RETURNS <%= return_type %> AS $$
|
||||||
|
DECLARE
|
||||||
|
<% if not multi_row %>ret <%= return_type %>;<% end %>
|
||||||
|
username text;
|
||||||
|
orgname text;
|
||||||
|
_returned_sqlstate TEXT;
|
||||||
|
_message_text TEXT;
|
||||||
|
_pg_exception_context TEXT;
|
||||||
|
BEGIN
|
||||||
|
IF session_user = 'publicuser' OR session_user ~ 'cartodb_publicuser_*' THEN
|
||||||
|
RAISE EXCEPTION 'The api_key must be provided';
|
||||||
|
END IF;
|
||||||
|
SELECT u, o INTO username, orgname FROM <%= DATASERVICES_CLIENT_SCHEMA %>._cdb_entity_config() AS (u text, o text);
|
||||||
|
-- JSON value stored "" is taken as literal
|
||||||
|
IF username IS NULL OR username = '' OR username = '""' THEN
|
||||||
|
RAISE EXCEPTION 'Username is a mandatory argument, check it out';
|
||||||
|
END IF;
|
||||||
|
|
||||||
|
<% if multi_row %>
|
||||||
|
BEGIN
|
||||||
|
RETURN QUERY
|
||||||
|
SELECT * FROM <%= DATASERVICES_CLIENT_SCHEMA %>._<%= name %>(<%= ['username', 'orgname'].concat(params).join(', ') %>);
|
||||||
|
EXCEPTION
|
||||||
|
WHEN OTHERS THEN
|
||||||
|
GET STACKED DIAGNOSTICS _returned_sqlstate = RETURNED_SQLSTATE,
|
||||||
|
_message_text = MESSAGE_TEXT,
|
||||||
|
_pg_exception_context = PG_EXCEPTION_CONTEXT;
|
||||||
|
RAISE WARNING USING ERRCODE = _returned_sqlstate, MESSAGE = _message_text, DETAIL = _pg_exception_context;
|
||||||
|
END;
|
||||||
|
<% elsif multi_field %>
|
||||||
|
BEGIN
|
||||||
|
SELECT * FROM <%= DATASERVICES_CLIENT_SCHEMA %>._<%= name %>(<%= ['username', 'orgname'].concat(params).join(', ') %>) INTO ret;
|
||||||
|
RETURN ret;
|
||||||
|
EXCEPTION
|
||||||
|
WHEN OTHERS THEN
|
||||||
|
GET STACKED DIAGNOSTICS _returned_sqlstate = RETURNED_SQLSTATE,
|
||||||
|
_message_text = MESSAGE_TEXT,
|
||||||
|
_pg_exception_context = PG_EXCEPTION_CONTEXT;
|
||||||
|
RAISE WARNING USING ERRCODE = _returned_sqlstate, MESSAGE = _message_text, DETAIL = _pg_exception_context;
|
||||||
|
RETURN ret;
|
||||||
|
END;
|
||||||
|
<% else %>
|
||||||
|
BEGIN
|
||||||
|
SELECT <%= DATASERVICES_CLIENT_SCHEMA %>._<%= name %>(<%= ['username', 'orgname'].concat(params).join(', ') %>) INTO ret;
|
||||||
|
RETURN ret;
|
||||||
|
EXCEPTION
|
||||||
|
WHEN OTHERS THEN
|
||||||
|
GET STACKED DIAGNOSTICS _returned_sqlstate = RETURNED_SQLSTATE,
|
||||||
|
_message_text = MESSAGE_TEXT,
|
||||||
|
_pg_exception_context = PG_EXCEPTION_CONTEXT;
|
||||||
|
RAISE WARNING USING ERRCODE = _returned_sqlstate, MESSAGE = _message_text, DETAIL = _pg_exception_context;
|
||||||
|
RETURN ret;
|
||||||
|
END;
|
||||||
|
<% end %>
|
||||||
|
END;
|
||||||
|
$$ LANGUAGE 'plpgsql' SECURITY DEFINER;
|
@ -1 +1,2 @@
|
|||||||
GRANT EXECUTE ON FUNCTION <%= DATASERVICES_CLIENT_SCHEMA %>.<%= name %>(<%= params_with_type.join(', ') %>) TO publicuser;
|
GRANT EXECUTE ON FUNCTION <%= DATASERVICES_CLIENT_SCHEMA %>.<%= name %>(<%= params_with_type.join(', ') %>) TO publicuser;
|
||||||
|
GRANT EXECUTE ON FUNCTION <%= DATASERVICES_CLIENT_SCHEMA %>._<%= name %>_exception_safe(<%= params_with_type.join(', ') %>) TO publicuser;
|
||||||
|
@ -0,0 +1,56 @@
|
|||||||
|
SET client_min_messages TO warning;
|
||||||
|
SET search_path TO public,cartodb,cdb_dataservices_client;
|
||||||
|
-- Mock the server functions to raise exceptions
|
||||||
|
CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_geocode_street_point (username text, orgname text, searchtext text, city text DEFAULT NULL, state_province text DEFAULT NULL, country text DEFAULT NULL)
|
||||||
|
RETURNS Geometry AS $$
|
||||||
|
BEGIN
|
||||||
|
RAISE EXCEPTION 'Not enough quota or any other exception whatsoever.';
|
||||||
|
RETURN NULL;
|
||||||
|
END;
|
||||||
|
$$ LANGUAGE 'plpgsql';
|
||||||
|
CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_isodistance(username text, orgname text, source geometry, mode text, range integer[], options text[] DEFAULT ARRAY[]::text[])
|
||||||
|
RETURNS SETOF isoline AS $$
|
||||||
|
BEGIN
|
||||||
|
RAISE EXCEPTION 'Not enough quota or any other exception whatsoever.';
|
||||||
|
END;
|
||||||
|
$$ LANGUAGE 'plpgsql';
|
||||||
|
CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_route_point_to_point (username text, orgname text, origin geometry(Point, 4326), destination geometry(Point, 4326), mode TEXT, options text[] DEFAULT ARRAY[]::text[], units text DEFAULT 'kilometers')
|
||||||
|
RETURNS cdb_dataservices_client.simple_route AS $$
|
||||||
|
DECLARE
|
||||||
|
ret cdb_dataservices_client.simple_route;
|
||||||
|
BEGIN
|
||||||
|
RAISE EXCEPTION 'Not enough quota or any other exception whatsoever.';
|
||||||
|
|
||||||
|
-- This code shall never be reached
|
||||||
|
SELECT NULL, 5.33, 100 INTO ret;
|
||||||
|
RETURN ret;
|
||||||
|
END;
|
||||||
|
$$ LANGUAGE 'plpgsql';
|
||||||
|
-- Use regular user role
|
||||||
|
SET ROLE test_regular_user;
|
||||||
|
-- Exercise the exception safe and the proxied functions
|
||||||
|
SELECT _cdb_geocode_street_point_exception_safe('One street, 1');
|
||||||
|
WARNING: cdb_dataservices_client._cdb_geocode_street_point(6): [contrib_regression] REMOTE ERROR: Not enough quota or any other exception whatsoever.
|
||||||
|
DETAIL: SQL statement "SELECT cdb_dataservices_client._cdb_geocode_street_point(username, orgname, searchtext, city, state_province, country)"
|
||||||
|
PL/pgSQL function _cdb_geocode_street_point_exception_safe(text,text,text,text) line 21 at SQL statement
|
||||||
|
_cdb_geocode_street_point_exception_safe
|
||||||
|
------------------------------------------
|
||||||
|
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT * FROM _cdb_isodistance_exception_safe('POINT(-3.70568 40.42028)'::geometry, 'walk', ARRAY[300]::integer[]);
|
||||||
|
WARNING: cdb_dataservices_client._cdb_isodistance(6): [contrib_regression] REMOTE ERROR: Not enough quota or any other exception whatsoever.
|
||||||
|
DETAIL: PL/pgSQL function _cdb_isodistance_exception_safe(geometry,text,integer[],text[]) line 21 at RETURN QUERY
|
||||||
|
center | data_range | the_geom
|
||||||
|
--------+------------+----------
|
||||||
|
(0 rows)
|
||||||
|
|
||||||
|
SELECT * FROM _cdb_route_point_to_point_exception_safe('POINT(-3.70237112 40.41706163)'::geometry,'POINT(-3.69909883 40.41236875)'::geometry, 'car', ARRAY['mode_type=shortest']::text[]);
|
||||||
|
WARNING: cdb_dataservices_client._cdb_route_point_to_point(7): [contrib_regression] REMOTE ERROR: Not enough quota or any other exception whatsoever.
|
||||||
|
DETAIL: SQL statement "SELECT * FROM cdb_dataservices_client._cdb_route_point_to_point(username, orgname, origin, destination, mode, options, units)"
|
||||||
|
PL/pgSQL function _cdb_route_point_to_point_exception_safe(geometry,geometry,text,text[],text) line 21 at SQL statement
|
||||||
|
shape | length | duration
|
||||||
|
-------+--------+----------
|
||||||
|
| |
|
||||||
|
(1 row)
|
||||||
|
|
41
client/test/sql/25_exception_safe_private_functions_test.sql
Normal file
41
client/test/sql/25_exception_safe_private_functions_test.sql
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
SET client_min_messages TO warning;
|
||||||
|
SET search_path TO public,cartodb,cdb_dataservices_client;
|
||||||
|
|
||||||
|
-- Mock the server functions to raise exceptions
|
||||||
|
CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_geocode_street_point (username text, orgname text, searchtext text, city text DEFAULT NULL, state_province text DEFAULT NULL, country text DEFAULT NULL)
|
||||||
|
RETURNS Geometry AS $$
|
||||||
|
BEGIN
|
||||||
|
RAISE EXCEPTION 'Not enough quota or any other exception whatsoever.';
|
||||||
|
RETURN NULL;
|
||||||
|
END;
|
||||||
|
$$ LANGUAGE 'plpgsql';
|
||||||
|
|
||||||
|
CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_isodistance(username text, orgname text, source geometry, mode text, range integer[], options text[] DEFAULT ARRAY[]::text[])
|
||||||
|
RETURNS SETOF isoline AS $$
|
||||||
|
BEGIN
|
||||||
|
RAISE EXCEPTION 'Not enough quota or any other exception whatsoever.';
|
||||||
|
END;
|
||||||
|
$$ LANGUAGE 'plpgsql';
|
||||||
|
|
||||||
|
CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_route_point_to_point (username text, orgname text, origin geometry(Point, 4326), destination geometry(Point, 4326), mode TEXT, options text[] DEFAULT ARRAY[]::text[], units text DEFAULT 'kilometers')
|
||||||
|
RETURNS cdb_dataservices_client.simple_route AS $$
|
||||||
|
DECLARE
|
||||||
|
ret cdb_dataservices_client.simple_route;
|
||||||
|
BEGIN
|
||||||
|
RAISE EXCEPTION 'Not enough quota or any other exception whatsoever.';
|
||||||
|
|
||||||
|
-- This code shall never be reached
|
||||||
|
SELECT NULL, 5.33, 100 INTO ret;
|
||||||
|
RETURN ret;
|
||||||
|
END;
|
||||||
|
$$ LANGUAGE 'plpgsql';
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
-- Use regular user role
|
||||||
|
SET ROLE test_regular_user;
|
||||||
|
|
||||||
|
-- Exercise the exception safe and the proxied functions
|
||||||
|
SELECT _cdb_geocode_street_point_exception_safe('One street, 1');
|
||||||
|
SELECT * FROM _cdb_isodistance_exception_safe('POINT(-3.70568 40.42028)'::geometry, 'walk', ARRAY[300]::integer[]);
|
||||||
|
SELECT * FROM _cdb_route_point_to_point_exception_safe('POINT(-3.70237112 40.41706163)'::geometry,'POINT(-3.69909883 40.41236875)'::geometry, 'car', ARRAY['mode_type=shortest']::text[]);
|
Loading…
Reference in New Issue
Block a user