diff --git a/client/renderer/interface.yaml b/client/renderer/interface.yaml index fa7c257..f13f6eb 100644 --- a/client/renderer/interface.yaml +++ b/client/renderer/interface.yaml @@ -421,3 +421,29 @@ params: - { name: service, type: TEXT } - { name: input_size, type: NUMERIC } + +- name: cdb_service_get_rate_limit + return_type: json + params: + - { name: service, type: "text" } + +- name: cdb_service_set_user_rate_limit + private: true + return_type: void + params: + - { name: service, type: "text" } + - { name: rate_limit, type: json } + +- name: cdb_service_set_org_rate_limit + private: true + return_type: void + params: + - { name: service, type: "text" } + - { name: rate_limit, type: json } + +- name: cdb_service_set_server_rate_limit + private: true + return_type: void + params: + - { name: service, type: "text" } + - { name: rate_limit, type: json } diff --git a/client/renderer/sql-template-renderer b/client/renderer/sql-template-renderer index 2516a09..3019730 100755 --- a/client/renderer/sql-template-renderer +++ b/client/renderer/sql-template-renderer @@ -17,7 +17,7 @@ class SqlTemplateRenderer end def render - ERB.new(@template).result(binding) + ERB.new(@template, nil, '-').result(binding) end def name @@ -44,16 +44,29 @@ class SqlTemplateRenderer @function_signature['geocoder_config_key'] end - def params - @function_signature['params'].reject(&:empty?).map { |p| "#{p['name']}"} + def parameters_info(with_credentials) + parameters = [] + if with_credentials + parameters << { 'name' => 'username', 'type' => 'text' } + parameters << { 'name' => 'orgname', 'type' => 'text' } + end + parameters + @function_signature['params'].reject(&:empty?) end - def params_with_type - @function_signature['params'].reject(&:empty?).map { |p| "#{p['name']} #{p['type']}" } + def credentials_declaration() + "username text;\n orgname text;" if public_function? end - def params_with_type_and_default - parameters = @function_signature['params'].reject(&:empty?).map do |p| + def params(with_credentials = !public_function?) + parameters_info(with_credentials).map { |p| p['name'].to_s } + end + + def params_with_type(with_credentials = !public_function?) + parameters_info(with_credentials).map { |p| "#{p['name']} #{p['type']}" } + end + + def params_with_type_and_default(with_credentials = !public_function?) + parameters = parameters_info(with_credentials).map do |p| if not p['default'].nil? "#{p['name']} #{p['type']} DEFAULT #{p['default']}" else @@ -62,6 +75,49 @@ class SqlTemplateRenderer end return parameters end + + def public_function? + !@function_signature['private'] + end + + def void_return_type? + return_type.downcase == 'void' + end + + def return_declaration + "ret #{return_type};" unless void_return_type? || multi_row + end + + def return_statement(&block) + if block + erbout = block.binding.eval('_erbout') + + if multi_row + erbout << 'RETURN QUERY SELECT * FROM ' + elsif multi_field + erbout << 'SELECT * FROM ' + elsif void_return_type? + erbout << 'PERFORM ' + else + erbout << 'SELECT ' + end + yield + if multi_row || void_return_type? + erbout << ';' + else + erbout << ' INTO ret;' + end + if !multi_row && !void_return_type? + erbout << ' RETURN ret;' + end + else + if !multi_row && !void_return_type? + ' RETURN ret;' + end + end + end + + end diff --git a/client/renderer/templates/20_public_functions.erb b/client/renderer/templates/20_public_functions.erb index 88db53d..8e65ed5 100644 --- a/client/renderer/templates/20_public_functions.erb +++ b/client/renderer/templates/20_public_functions.erb @@ -7,9 +7,8 @@ CREATE OR REPLACE FUNCTION <%= DATASERVICES_CLIENT_SCHEMA %>.<%= name %> (<%= params_with_type_and_default.join(' ,') %>) RETURNS <%= return_type %> AS $$ DECLARE - <% if not multi_row %>ret <%= return_type %>;<% end %> - username text; - orgname text; + <%= return_declaration if not multi_row %> + <%= credentials_declaration %> BEGIN IF session_user = 'publicuser' OR session_user ~ 'cartodb_publicuser_*' THEN RAISE EXCEPTION 'The api_key must be provided'; @@ -19,15 +18,7 @@ BEGIN IF username IS NULL OR username = '' OR username = '""' THEN RAISE EXCEPTION 'Username is a mandatory argument, check it out'; END IF; - <% if multi_row %> - RETURN QUERY - SELECT * FROM <%= DATASERVICES_CLIENT_SCHEMA %>._<%= name %>(<%= ['username', 'orgname'].concat(params).join(', ') %>); - <% elsif multi_field %> - SELECT * FROM <%= DATASERVICES_CLIENT_SCHEMA %>._<%= name %>(<%= ['username', 'orgname'].concat(params).join(', ') %>) INTO ret; - RETURN ret; - <% else %> - SELECT <%= DATASERVICES_CLIENT_SCHEMA %>._<%= name %>(<%= ['username', 'orgname'].concat(params).join(', ') %>) INTO ret; - RETURN ret; - <% end %> + + <% return_statement do %><%= DATASERVICES_CLIENT_SCHEMA %>._<%= name %>(<%= params(true).join(', ') %>)<% end %> END; $$ LANGUAGE 'plpgsql' SECURITY DEFINER; diff --git a/client/renderer/templates/25_exception_safe_private_functions.erb b/client/renderer/templates/25_exception_safe_private_functions.erb index 2dde980..4b19b67 100644 --- a/client/renderer/templates/25_exception_safe_private_functions.erb +++ b/client/renderer/templates/25_exception_safe_private_functions.erb @@ -5,9 +5,8 @@ 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; + <%= return_declaration %> + <%= credentials_declaration %> _returned_sqlstate TEXT; _message_text TEXT; _pg_exception_context TEXT; @@ -21,41 +20,16 @@ BEGIN 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 + + BEGIN + <% return_statement do %><%= DATASERVICES_CLIENT_SCHEMA %>._<%= name %>(<%= params(true).join(', ') %>)<% end %> + 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 %> + <%= return_statement %> + END; END; $$ LANGUAGE 'plpgsql' SECURITY DEFINER; diff --git a/client/renderer/templates/30_plproxy_functions.erb b/client/renderer/templates/30_plproxy_functions.erb index 2d5dfe3..92d2469 100644 --- a/client/renderer/templates/30_plproxy_functions.erb +++ b/client/renderer/templates/30_plproxy_functions.erb @@ -1,9 +1,9 @@ -CREATE OR REPLACE FUNCTION <%= DATASERVICES_CLIENT_SCHEMA %>._<%= name %> (<%= ['username text', 'organization_name text'].concat(params_with_type_and_default).join(', ') %>) +CREATE OR REPLACE FUNCTION <%= DATASERVICES_CLIENT_SCHEMA %>._<%= name %> (<%= params_with_type_and_default(true).join(', ') %>) RETURNS <%= return_type %> AS $$ CONNECT <%= DATASERVICES_CLIENT_SCHEMA %>._server_conn_str(); <% if multi_field %> - SELECT * FROM <%= DATASERVICES_SERVER_SCHEMA %>.<%= name %> (<%= ['username', 'organization_name'].concat(params).join(', ') %>); + SELECT * FROM <%= DATASERVICES_SERVER_SCHEMA %>.<%= name %> (<%= params(true).join(', ') %>); <% else %> - SELECT <%= DATASERVICES_SERVER_SCHEMA %>.<%= name %> (<%= ['username', 'organization_name'].concat(params).join(', ') %>); + SELECT <%= DATASERVICES_SERVER_SCHEMA %>.<%= name %> (<%= params(true).join(', ') %>); <% end %> $$ LANGUAGE plproxy; diff --git a/client/renderer/templates/90_grant_execute.erb b/client/renderer/templates/90_grant_execute.erb index b6c797e..924f495 100644 --- a/client/renderer/templates/90_grant_execute.erb +++ b/client/renderer/templates/90_grant_execute.erb @@ -1,2 +1,4 @@ +<% if public_function? %> 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; +GRANT EXECUTE ON FUNCTION <%= DATASERVICES_CLIENT_SCHEMA %>._<%= name %>_exception_safe(<%= params_with_type.join(', ') %> ) TO publicuser; +<% end %> \ No newline at end of file