do/token endpoint

pull/15097/head
Gonzalo Riestra 5 years ago
parent 5f555a1234
commit d97bce870c

@ -355,6 +355,7 @@ SPEC_HELPER_MIN_SPECS = \
spec/requests/carto/api/public/oauth_apps_controller_spec.rb \
spec/requests/carto/api/public/datasets_controller_spec.rb \
spec/models/carto/user_migration_spec.rb \
spec/requests/carto/api/data_observatory_controller_spec.rb \
$(NULL)
# This class must be tested isolated as pollutes namespace

@ -0,0 +1,38 @@
# require_dependency 'carto/controller_helper'
module Carto
module Api
module Public
class DataObservatoryController < Carto::Api::Public::ApplicationController
include Carto::ControllerHelper
extend Carto::DefaultRescueFroms
ssl_required
before_action :load_user
before_action :check_permissions
setup_default_rescues
respond_to :json
def token
response = Cartodb::Central.new.get_do_token(@user.username)
render(json: response)
end
private
def load_user
@user = Carto::User.find(current_viewer.id)
end
def check_permissions
api_key = Carto::ApiKey.find_by_token(params["api_key"])
raise UnauthorizedError unless api_key&.master? || api_key&.data_observatory_token_permissions?
end
end
end
end
end

@ -57,6 +57,8 @@ module Carto
CDB_CONF_KEY_PREFIX = 'api_keys_'.freeze
DATA_OBSERVATORY_TOKEN_GRANT = 'data_observatory_token'.freeze
self.inheritance_column = :_type
belongs_to :user
@ -195,6 +197,10 @@ module Carto
@dataset_metadata_permissions ||= process_dataset_metadata_permissions
end
def data_observatory_token_permissions?
process_user_data_grants&.include?(DATA_OBSERVATORY_TOKEN_GRANT)
end
def table_permissions_from_db
query = %{
WITH permissions AS (

@ -585,6 +585,10 @@ CartoDB::Application.routes.draw do
post 'oauth_apps/:id/revoke', to: 'oauth_apps#revoke', constraints: { id: UUID_REGEXP }, as: :api_v4_oauth_apps_revoke
get 'datasets', to: 'datasets#index', as: :api_v4_datasets
scope 'do' do
get 'token' => 'data_observatory#token', as: :api_v4_do_token
end
end
scope 'v3/' do

@ -57,50 +57,54 @@ module Cartodb
end
def get_user(username_or_email)
return send_request("api/users/#{username_or_email}", nil, :get, [200,404])
end # get_organization_users
send_request("api/users/#{username_or_email}", nil, :get, [200, 404])
end
def get_organization_users(organization_name)
return send_request("api/organizations/#{ organization_name }/users", nil, :get, [200], 600)
end # get_organization_users
send_request("api/organizations/#{ organization_name }/users", nil, :get, [200], 600)
end
def get_organization_user(organization_name, username)
return send_request("api/organizations/#{ organization_name }/users/#{ username }", nil, :get, [200])
end # get_organization_user
send_request("api/organizations/#{ organization_name }/users/#{ username }", nil, :get, [200])
end
def create_organization_user(organization_name, user_attributes)
body = {user: user_attributes}
return send_request("api/organizations/#{ organization_name }/users", body, :post, [201])
end # create_organization_user
send_request("api/organizations/#{ organization_name }/users", body, :post, [201])
end
def update_organization_user(organization_name, username, user_attributes)
body = {user: user_attributes}
return send_request("api/organizations/#{ organization_name }/users/#{ username }", body, :put, [204])
send_request("api/organizations/#{ organization_name }/users/#{ username }", body, :put, [204])
end
def delete_organization_user(organization_name, username)
send_request("api/organizations/#{organization_name}/users/#{username}", nil, :delete, [204, 404])
end # delete_organization_user
end
def update_user(username, user_attributes)
body = {user: user_attributes}
return send_request("api/users/#{username}", body, :put, [204])
send_request("api/users/#{username}", body, :put, [204])
end
def delete_user(username)
send_request("api/users/#{username}", nil, :delete, [204, 404])
end
def get_do_token(username)
send_request("api/users/#{username}/do_token", nil, :get, [200, 403, 404])
end
############################################################################
# Organizations
def get_organizations
return send_request("api/organizations", nil, :get, [200], 600)
end # get_organizations
send_request("api/organizations", nil, :get, [200], 600)
end
def get_organization(organization_name)
return send_request("api/organizations/#{ organization_name }", nil, :get, [200])
end # get_organization
send_request("api/organizations/#{ organization_name }", nil, :get, [200])
end
# Returns remote organization attributes if response code is 201
# otherwise returns nil
@ -108,17 +112,17 @@ module Cartodb
# rilla answers: That's right, but this methods is just a stub: org creation from the editor is still unsupported
def create_organization(organization_name, organization_attributes)
body = {organization: organization_attributes}
return send_request("api/organizations", body, :post, [201])
end # create_organization
send_request("api/organizations", body, :post, [201])
end
def update_organization(organization_name, organization_attributes)
body = {organization: organization_attributes}
return send_request("api/organizations/#{ organization_name }", body, :put, [204])
end # update_organization
send_request("api/organizations/#{ organization_name }", body, :put, [204])
end
def delete_organization(organization_name)
send_request("api/organizations/#{organization_name}", nil, :delete, [204, 404])
end # delete_organization
end
############################################################################
# Mobile apps

@ -0,0 +1,68 @@
require 'spec_helper_min'
require 'support/helpers'
describe Carto::Api::Public::DataObservatoryController do
include_context 'users helper'
include HelperMethods
before(:all) do
@master = @user1.api_key
@not_granted_token = @user1.api_keys.create_regular_key!(name: 'not_do', grants: [{ type: 'apis', apis: [] }]).token
do_grants = [{ type: 'apis', apis: [] }, { type: 'user', data: ['data_observatory_token'] }]
@granted_token = @user1.api_keys.create_regular_key!(name: 'do', grants: do_grants).token
@headers = { 'CONTENT_TYPE' => 'application/json' }
end
describe 'token' do
before(:each) do
host! "#{@user1.username}.localhost.lan"
end
it 'returns 401 if there is no API key' do
get_json api_v4_do_token_url, @headers do |response|
expect(response.status).to eq(401)
end
end
it 'returns 401 if the API key is wrong' do
get_json api_v4_do_token_url(api_key: 'wrong'), @headers do |response|
expect(response.status).to eq(401)
end
end
it 'returns 403 when using a regular API key without DO grant' do
get_json api_v4_do_token_url(api_key: @not_granted_token), @headers do |response|
expect(response.status).to eq(403)
end
end
it 'returns 200 with an access token when using the master API key' do
expected_body = [{ "access_token" => 'tokenuco' }]
Cartodb::Central.any_instance.expects(:get_do_token).with(@user1.username).once.returns(expected_body.to_json)
get_json api_v4_do_token_url(api_key: @master), @headers do |response|
expect(response.status).to eq(200)
expect(response.body).to eq expected_body
end
end
it 'returns 200 with an access token when using a regular API key with DO grant' do
expected_body = [{ "access_token" => 'tokenuco' }]
Cartodb::Central.any_instance.expects(:get_do_token).with(@user1.username).once.returns(expected_body.to_json)
get_json api_v4_do_token_url(api_key: @granted_token), @headers do |response|
expect(response.status).to eq(200)
expect(response.body).to eq expected_body
end
end
it 'returns 500 if the central call fails' do
central_error = CentralCommunicationFailure.new('boom')
Cartodb::Central.any_instance.expects(:get_do_token).with(@user1.username).once.raises(central_error)
get_json api_v4_do_token_url(api_key: @master), @headers do |response|
expect(response.status).to eq(500)
end
end
end
end
Loading…
Cancel
Save