Files
cartodb/spec/requests/carto/api/public/oauth_apps_controller_spec.rb
2020-06-15 10:58:47 +08:00

779 lines
25 KiB
Ruby

require 'spec_helper_min'
require 'support/helpers'
describe Carto::Api::Public::OauthAppsController do
include_context 'users helper'
include_context 'organization with users helper'
include HelperMethods
describe 'index' do
context 'regular users' do
before(:all) do
@params = { api_key: @user1.api_key, page: 1, per_page: 10 }
@app1 = FactoryGirl.create(:oauth_app, user_id: @user1.id, name: 'ZZZ', restricted: false)
@app2 = FactoryGirl.create(:oauth_app, user_id: @user1.id, name: 'ABC', restricted: true)
@app3 = FactoryGirl.create(:oauth_app, user_id: @user2.id, name: 'ABC', restricted: true)
end
after(:all) do
[@app1, @app2, @app3].each(&:destroy)
end
before(:each) do
host! "#{@user1.username}.localhost.lan"
end
it 'returns 401 if there is no authenticated user' do
get_json api_v4_oauth_apps_url do |response|
expect(response.status).to eq(401)
end
end
context 'with engine disabled' do
before(:each) do
@user1.engine_enabled = false
@user1.save
end
after(:each) do
@user1.engine_enabled = true
@user1.save
end
it 'returns 404' do
get_json api_v4_oauth_apps_url(@params) do |response|
expect(response.status).to eq(404)
end
end
end
it 'returns 200 with the OAuth apps owned by the current user (sort by updated at by default)' do
get_json api_v4_oauth_apps_url(@params) do |response|
expect(response.status).to eq(200)
expect(response.body[:total]).to eq 2
expect(response.body[:count]).to eq 2
expect(response.body[:result][0][:id]).to eq @app1.id
expect(response.body[:result][0][:username]).to eq @user1.username
end
end
it 'returns 200 with an empty array if the current user does not have apps' do
@user3 = FactoryGirl.create(:valid_user)
host! "#{@user3.username}.localhost.lan"
get_json api_v4_oauth_apps_url(api_key: @user3.api_key) do |response|
expect(response.status).to eq(200)
expect(response.body[:total]).to eq 0
expect(response.body[:count]).to eq 0
expect(response.body[:result]).to be_empty
end
end
context 'pagination' do
it 'paginates the results' do
get_json api_v4_oauth_apps_url(@params.merge(page: 2, per_page: 1)) do |response|
expect(response.status).to eq(200)
expect(response.body[:total]).to eq 2
expect(response.body[:count]).to eq 1
expect(response.body[:result][0][:id]).to eq @app2.id
end
end
it 'returns the expected links' do
base_url = "http://#{@user1.username}.localhost.lan/api/v4/oauth_apps?api_key=#{@user1.api_key}&format=json"
get_json api_v4_oauth_apps_url(@params.merge(page: 1, per_page: 1)) do |response|
expect(response.status).to eq(200)
expect(response.body[:_links][:first][:href]).to eq "#{base_url}&page=1&per_page=1"
expect(response.body[:_links][:next][:href]).to eq "#{base_url}&page=2&per_page=1"
expect(response.body[:_links][:last][:href]).to eq "#{base_url}&page=2&per_page=1"
end
end
end
context 'ordering' do
it 'orders results by name' do
get_json api_v4_oauth_apps_url(@params.merge(order: 'name')) do |response|
expect(response.status).to eq(200)
expect(response.body[:total]).to eq 2
expect(response.body[:count]).to eq 2
expect(response.body[:result][0][:id]).to eq @app2.id
expect(response.body[:result][1][:id]).to eq @app1.id
end
end
it 'orders results by restricted' do
get_json api_v4_oauth_apps_url(@params.merge(order: 'restricted')) do |response|
expect(response.status).to eq(200)
expect(response.body[:total]).to eq 2
expect(response.body[:count]).to eq 2
expect(response.body[:result][0][:id]).to eq @app1.id
expect(response.body[:result][1][:id]).to eq @app2.id
end
end
it 'returns 400 if the ordering param is invalid' do
get_json api_v4_oauth_apps_url(@params.merge(order: 'client_secret')) do |response|
expect(response.status).to eq(400)
expect(response.body[:errors]).to include "Wrong 'order' parameter value"
end
end
end
end
context 'organizational users' do
before(:all) do
@params = { page: 1, per_page: 10 }
@app1 = FactoryGirl.create(:oauth_app, user_id: @org_user_1.id)
@app2 = FactoryGirl.create(:oauth_app, user_id: @org_user_2.id)
@app3 = FactoryGirl.create(:oauth_app, user_id: @org_user_owner.id)
end
after(:all) do
[@app1, @app2, @app3].each(&:destroy)
end
before(:each) do
host! "#{@organization.name}.localhost.lan"
end
it 'returns all the OAuth apps in the organization for the organization owner' do
params = @params.merge(api_key: @org_user_owner.api_key, user_domain: @org_user_owner.username)
get_json api_v4_oauth_apps_url(params) do |response|
expect(response.status).to eq(200)
expect(response.body[:total]).to eq 3
end
end
it 'returns only the user apps for non owners' do
params = @params.merge(api_key: @org_user_1.api_key, user_domain: @org_user_1.username)
get_json api_v4_oauth_apps_url(params) do |response|
expect(response.status).to eq(200)
expect(response.body[:total]).to eq 1
end
end
end
end
describe 'index_granted' do
before(:all) do
@params = { api_key: @carto_org_user_1.api_key, page: 1, per_page: 10 }
@app1 = FactoryGirl.create(:oauth_app, user_id: @carto_org_user_2.id, name: 'ZZZ', restricted: false)
@app2 = FactoryGirl.create(:oauth_app, user_id: @carto_org_user_2.id, name: 'ABC', restricted: true)
@app3 = FactoryGirl.create(:oauth_app, user_id: @carto_org_user_2.id)
@app1.oauth_app_organizations.create!(organization: @carto_organization, seats: 1)
@app2.oauth_app_organizations.create!(organization: @carto_organization, seats: 1)
Carto::OauthAppUser.create!(user: @carto_org_user_1, oauth_app: @app1, scopes: ['user:profile'])
Carto::OauthAppUser.create!(user: @carto_org_user_1, oauth_app: @app2)
end
after(:all) do
[@app1, @app2, @app3].each(&:destroy)
end
before(:each) do
host! "#{@carto_org_user_1.username}.localhost.lan"
end
it 'returns 401 if there is no authenticated user' do
get_json api_v4_oauth_apps_index_granted_url do |response|
expect(response.status).to eq(401)
end
end
context 'with engine disabled' do
before(:each) do
@carto_org_user_1.engine_enabled = false
@carto_org_user_1.save
end
after(:each) do
@carto_org_user_1.engine_enabled = true
@carto_org_user_1.save
end
it 'returns 404' do
get_json api_v4_oauth_apps_index_granted_url(@params) do |response|
expect(response.status).to eq(404)
end
end
end
it 'returns 200 with the OAuth apps granted by the current user and the scopes (sort by updated at by default)' do
get_json api_v4_oauth_apps_index_granted_url(@params) do |response|
expect(response.status).to eq(200)
expect(response.body[:total]).to eq 2
expect(response.body[:count]).to eq 2
expect(response.body[:result][0][:id]).to eq @app1.id
expect(response.body[:result][0][:scopes][0][:description]).to eq 'User and personal data'
expect(response.body[:result][0][:username]).to be_nil
expect(response.body[:result][0][:client_secret]).to be_nil
end
end
it 'returns 200 with an empty array if the current user does not have granted apps' do
host! "#{@carto_org_user_2.username}.localhost.lan"
get_json api_v4_oauth_apps_index_granted_url(api_key: @carto_org_user_2.api_key) do |response|
expect(response.status).to eq(200)
expect(response.body[:total]).to eq 0
expect(response.body[:count]).to eq 0
expect(response.body[:result]).to be_empty
end
end
context 'pagination' do
it 'paginates the results' do
get_json api_v4_oauth_apps_index_granted_url(@params.merge(page: 2, per_page: 1)) do |response|
expect(response.status).to eq(200)
expect(response.body[:total]).to eq 2
expect(response.body[:count]).to eq 1
expect(response.body[:result][0][:id]).to eq @app2.id
end
end
it 'returns the expected links' do
base_url = "http://#{@org_user_1.username}.localhost.lan/api/v4/granted_oauth_apps?"\
"api_key=#{@org_user_1.api_key}&format=json"
get_json api_v4_oauth_apps_index_granted_url(@params.merge(page: 1, per_page: 1)) do |response|
expect(response.status).to eq(200)
expect(response.body[:_links][:first][:href]).to eq "#{base_url}&page=1&per_page=1"
expect(response.body[:_links][:next][:href]).to eq "#{base_url}&page=2&per_page=1"
expect(response.body[:_links][:last][:href]).to eq "#{base_url}&page=2&per_page=1"
end
end
end
context 'ordering' do
it 'orders results by name' do
get_json api_v4_oauth_apps_index_granted_url(@params.merge(order: 'name')) do |response|
expect(response.status).to eq(200)
expect(response.body[:total]).to eq 2
expect(response.body[:count]).to eq 2
expect(response.body[:result][0][:id]).to eq @app2.id
expect(response.body[:result][1][:id]).to eq @app1.id
end
end
it 'orders results by restricted' do
get_json api_v4_oauth_apps_index_granted_url(@params.merge(order: 'restricted')) do |response|
expect(response.status).to eq(200)
expect(response.body[:total]).to eq 2
expect(response.body[:count]).to eq 2
expect(response.body[:result][0][:id]).to eq @app1.id
expect(response.body[:result][1][:id]).to eq @app2.id
end
end
it 'returns 400 if the ordering param is invalid' do
get_json api_v4_oauth_apps_index_granted_url(@params.merge(order: 'client_secret')) do |response|
expect(response.status).to eq(400)
expect(response.body[:errors]).to include "Wrong 'order' parameter value"
end
end
end
end
describe 'show' do
before(:all) do
@app = FactoryGirl.create(:oauth_app, user_id: @user1.id)
@params = { api_key: @user1.api_key, id: @app.id }
end
after(:all) do
@app.destroy
end
before(:each) do
host! "#{@user1.username}.localhost.lan"
end
it 'returns 401 if there is no authenticated user' do
get_json api_v4_oauth_app_url(id: @app.id) do |response|
expect(response.status).to eq(401)
end
end
context 'with engine disabled' do
before(:each) do
@user1.engine_enabled = false
@user1.save
end
after(:each) do
@user1.engine_enabled = true
@user1.save
end
it 'returns 404' do
get_json api_v4_oauth_app_url(@params) do |response|
expect(response.status).to eq(404)
end
end
end
it 'returns 404 if the app is not found' do
wrong_id = @user1.id
get_json api_v4_oauth_app_url(@params.merge(id: wrong_id)) do |response|
expect(response.status).to eq(404)
expect(response.body[:errors]).to eq 'Record not found'
end
end
it 'returns 404 if the app is not owned' do
other_app = FactoryGirl.create(:oauth_app, user_id: @user2.id)
get_json api_v4_oauth_app_url(@params.merge(id: other_app.id)) do |response|
expect(response.status).to eq(404)
end
other_app.destroy
end
it 'returns 200 with all the info from an OAuth App' do
get_json api_v4_oauth_app_url(@params) do |response|
expect(response.status).to eq(200)
expect(response.body[:id]).to eq @app.id
expect(response.body[:name]).to eq @app.name
expect(response.body[:client_secret]).to eq @app.client_secret
expect(response.body[:username]).to eq @user1.username
expect(response.body.size).to eq 13
end
end
end
describe 'create' do
before(:all) do
@params = { api_key: @user1.api_key }
@payload = {
name: 'my app',
redirect_uris: ['https://example.com'],
icon_url: 'https://example.com/icon.png',
website_url: 'https://example.com'
}
end
after(:each) do
@carto_user1.reload.oauth_apps.each(&:destroy)
end
before(:each) do
Carto::OauthApp.any_instance.stubs(:sync_with_central?).returns(false)
host! "#{@user1.username}.localhost.lan"
end
it 'returns 401 if there is no authenticated user' do
post_json api_v4_oauth_apps_url, @payload do |response|
expect(response.status).to eq(401)
end
end
context 'with engine disabled' do
before(:each) do
@user1.engine_enabled = false
@user1.save
end
after(:each) do
@user1.engine_enabled = true
@user1.save
end
it 'returns 404' do
post_json api_v4_oauth_apps_url(@params), @payload do |response|
expect(response.status).to eq(404)
end
end
end
it 'returns 422 if a required parameter is missing' do
post_json api_v4_oauth_apps_url(@params), @payload.except(:name) do |response|
expect(response.status).to eq(422)
expect(response.body[:errors]).to eq ({ name: ["can't be blank"] })
end
end
it 'returns 201 if everything is ok' do
post_json api_v4_oauth_apps_url(@params), @payload do |response|
expect(response.status).to eq(201)
expect(response.body[:name]).to eq 'my app'
expect(@carto_user1.reload.oauth_apps.size).to eq 1
end
end
end
describe 'update' do
context 'regular users' do
before(:all) do
@app = FactoryGirl.create(:oauth_app, user_id: @user1.id)
@params = { id: @app.id, api_key: @user1.api_key }
@payload = { name: 'updated name' }
end
after(:all) do
@app.destroy
end
before(:each) do
Carto::OauthApp.any_instance.stubs(:sync_with_central?).returns(false)
host! "#{@user1.username}.localhost.lan"
end
it 'returns 401 if there is no authenticated user' do
put_json api_v4_oauth_app_url(id: @app.id), @payload do |response|
expect(response.status).to eq(401)
end
end
context 'with engine disabled' do
before(:each) do
@user1.engine_enabled = false
@user1.save
end
after(:each) do
@user1.engine_enabled = true
@user1.save
end
it 'returns 404' do
put_json api_v4_oauth_app_url(@params), @payload do |response|
expect(response.status).to eq(404)
end
end
end
it 'returns 404 if the app is not found' do
wrong_id = @user1.id
put_json api_v4_oauth_app_url(@params.merge(id: wrong_id)), @payload do |response|
expect(response.status).to eq(404)
expect(response.body[:errors]).to eq 'Record not found'
end
end
it 'returns 404 if the app is not owned' do
other_app = FactoryGirl.create(:oauth_app, user_id: @user2.id)
put_json api_v4_oauth_app_url(@params.merge(id: other_app.id)) do |response|
expect(response.status).to eq(404)
end
other_app.destroy
end
it 'returns 200 if everything is ok' do
put_json api_v4_oauth_app_url(@params), @payload do |response|
expect(response.status).to eq(200)
expect(response.body[:name]).to eq 'updated name'
expect(@app.reload.name).to eq 'updated name'
end
end
it 'ignores non-editable fields' do
payload = { client_secret: 'secreto ibérico' }
put_json api_v4_oauth_app_url(@params), payload do |response|
expect(response.status).to eq(200)
expect(@app.reload.client_secret).to_not eq 'secreto ibérico'
end
end
end
context 'organizational users' do
before(:all) do
@app = FactoryGirl.create(:oauth_app, user_id: @org_user_1.id)
@params = { id: @app.id, api_key: @org_user_owner.api_key, user_domain: @org_user_owner.username }
@payload = { name: 'updated name' }
end
after(:all) do
@app.destroy
end
before(:each) do
Carto::OauthApp.any_instance.stubs(:sync_with_central?).returns(false)
host! "#{@organization.name}.localhost.lan"
end
it 'allows the admin to update any app from the organization' do
put_json api_v4_oauth_app_url(@params), @payload do |response|
expect(response.status).to eq(200)
expect(response.body[:name]).to eq 'updated name'
expect(@app.reload.name).to eq 'updated name'
end
end
end
end
describe 'regenerate_secret' do
before(:all) do
@app = FactoryGirl.create(:oauth_app, user_id: @user1.id)
@params = { id: @app.id, api_key: @user1.api_key }
end
after(:all) do
@app.destroy
end
before(:each) do
Carto::OauthApp.any_instance.stubs(:sync_with_central?).returns(false)
host! "#{@user1.username}.localhost.lan"
end
it 'returns 401 if there is no authenticated user' do
post_json api_v4_oauth_apps_regenerate_secret_url(id: @app.id) do |response|
expect(response.status).to eq(401)
end
end
context 'with engine disabled' do
before(:each) do
@user1.engine_enabled = false
@user1.save
end
after(:each) do
@user1.engine_enabled = true
@user1.save
end
it 'returns 404' do
post_json api_v4_oauth_apps_regenerate_secret_url(@params) do |response|
expect(response.status).to eq(404)
end
end
end
it 'returns 404 if the app is not found' do
wrong_id = @user1.id
post_json api_v4_oauth_apps_regenerate_secret_url(@params.merge(id: wrong_id)) do |response|
expect(response.status).to eq(404)
expect(response.body[:errors]).to eq 'Record not found'
end
end
it 'returns 404 if the app is not owned' do
other_app = FactoryGirl.create(:oauth_app, user_id: @user2.id)
post_json api_v4_oauth_apps_regenerate_secret_url(@params.merge(id: other_app.id)) do |response|
expect(response.status).to eq(404)
end
other_app.destroy
end
it 'returns 200 if everything is ok' do
original_secret = @app.client_secret
post_json api_v4_oauth_apps_regenerate_secret_url(@params) do |response|
expect(response.status).to eq(200)
expect(response.body[:client_secret]).to_not eq original_secret
expect(@app.reload.client_secret).to_not eq original_secret
end
end
end
describe 'destroy' do
before(:each) do
Cartodb::Central.stubs(:sync_data_with_cartodb_central?).returns(false)
Carto::OauthAppUser.any_instance.stubs(:reassign_owners).returns(true)
Carto::OauthAppUser.any_instance.stubs(:drop_roles).returns(true)
@app = FactoryGirl.create(:oauth_app, user_id: @user1.id)
@params = { id: @app.id, api_key: @user1.api_key }
end
after(:each) do
::Resque.unstub(:enqueue)
@app.try(:destroy)
Carto::OauthAppUser.any_instance.unstub(:reassign_owners)
Carto::OauthAppUser.any_instance.unstub(:drop_roles)
end
before(:each) do
Carto::OauthApp.any_instance.stubs(:sync_with_central?).returns(false)
host! "#{@user1.username}.localhost.lan"
end
it 'returns 401 if there is no authenticated user' do
delete_json api_v4_oauth_app_url(id: @app.id) do |response|
expect(response.status).to eq(401)
end
end
context 'with engine disabled' do
before(:each) do
@user1.engine_enabled = false
@user1.save
end
after(:each) do
@user1.engine_enabled = true
@user1.save
end
it 'returns 404' do
delete_json api_v4_oauth_app_url(@params) do |response|
expect(response.status).to eq(404)
end
end
end
it 'returns 404 if the app is not found' do
wrong_id = @user1.id
delete_json api_v4_oauth_app_url(@params.merge(id: wrong_id)) do |response|
expect(response.status).to eq(404)
expect(response.body[:errors]).to eq 'Record not found'
end
end
it 'returns 404 if the app is not owned' do
other_app = FactoryGirl.create(:oauth_app, user_id: @user2.id)
delete_json api_v4_oauth_app_url(@params.merge(id: other_app.id)) do |response|
expect(response.status).to eq(404)
end
other_app.destroy
end
it 'returns 204 if everything is ok' do
delete_json api_v4_oauth_app_url(@params) do |response|
expect(response.status).to eq(204)
expect(@carto_user1.reload.oauth_apps.size).to eq 0
end
end
it 'sends notification if everything is ok' do
@app_user = Carto::OauthAppUser.create!(user_id: @app.user.id, oauth_app: @app)
::Resque.expects(:enqueue)
.with(::Resque::UserJobs::Notifications::Send, [@app_user.user.id], anything)
.once
delete_json api_v4_oauth_app_url(@params) do |response|
expect(response.status).to eq(204)
expect(@carto_user1.reload.oauth_apps.size).to eq 0
end
end
it 'does not send notification if no users' do
::Resque.expects(:enqueue)
.with(::Resque::UserJobs::Notifications::Send, anything, anything)
.never
delete_json api_v4_oauth_app_url(@params) do |response|
expect(response.status).to eq(204)
expect(@carto_user1.reload.oauth_apps.size).to eq 0
end
end
it 'returns server error on error in notification when destroying app with users' do
@app_user = Carto::OauthAppUser.create!(user_id: @app.user.id, oauth_app: @app)
::Resque.stubs(:enqueue).raises('unknown error')
delete_json api_v4_oauth_app_url(@params) do |response|
expect(response.status).to eq(500)
expect(@carto_user1.reload.oauth_apps.size).to eq 1
end
end
end
describe 'revoke' do
before(:each) do
@app = FactoryGirl.create(:oauth_app, user_id: @carto_org_user_2.id)
@app.oauth_app_organizations.create!(organization: @carto_organization, seats: 1)
@oauth_app_user = Carto::OauthAppUser.create!(user: @carto_org_user_1, oauth_app: @app)
@params = { id: @app.id, api_key: @carto_org_user_1.api_key }
end
after(:each) do
@app.try(:destroy)
end
before(:each) do
Carto::OauthApp.any_instance.stubs(:sync_with_central?).returns(false)
host! "#{@carto_org_user_1.username}.localhost.lan"
end
it 'returns 401 if there is no authenticated user' do
post_json api_v4_oauth_apps_revoke_url(id: @app.id) do |response|
expect(response.status).to eq(401)
end
end
context 'with engine disabled' do
before(:each) do
@carto_org_user_1.engine_enabled = false
@carto_org_user_1.save
end
after(:each) do
@carto_org_user_1.engine_enabled = true
@carto_org_user_1.save
end
it 'returns 404' do
post_json api_v4_oauth_apps_revoke_url(@params) do |response|
expect(response.status).to eq(404)
end
end
end
it 'returns 404 if the app is not found' do
wrong_id = @user1.id
post_json api_v4_oauth_apps_revoke_url(@params.merge(id: wrong_id)) do |response|
expect(response.status).to eq(404)
expect(response.body[:errors]).to eq 'Record not found'
end
end
it 'returns 404 if the app is not granted' do
@carto_org_user_1.granted_oauth_apps.each(&:destroy)
post_json api_v4_oauth_apps_revoke_url(@params) do |response|
expect(response.status).to eq(404)
expect(response.body[:errors]).to eq 'Record not found'
end
end
it 'returns 204 if role does not exist when reassigning' do
Carto::OauthAppUser.any_instance.stubs(:dataset_role_name).returns('wrong')
post_json api_v4_oauth_apps_revoke_url(@params) do |response|
expect(response.status).to eq(204)
end
Carto::OauthAppUser.any_instance.unstub(:dataset_role_name)
end
it 'returns 500 role does not exist when reassigning' do
mock = OpenStruct.new
mock.stubs(:execute).raises(ActiveRecord::StatementInvalid, 'Error reassigning owners')
Carto::User.any_instance.stubs(:in_database).returns(mock)
post_json api_v4_oauth_apps_revoke_url(@params) do |response|
expect(response.status).to eq(500)
expect(response.body[:errors]).to include 'Error reassigning owners'
end
Carto::OauthAppUser.any_instance.unstub(:dataset_role_name)
Carto::User.any_instance.unstub(:in_database)
end
it 'returns 204 if everything is ok' do
expect(@carto_org_user_1.reload.granted_oauth_apps.size).to eq 1
post_json api_v4_oauth_apps_revoke_url(@params) do |response|
expect(response.status).to eq(204)
expect(@carto_org_user_1.reload.granted_oauth_apps.size).to eq 0
end
end
end
end