From 8e99a010ca67abca6df4e1f0c62fc30572abb58d Mon Sep 17 00:00:00 2001 From: Martin Edenhofer Date: Wed, 26 Sep 2018 11:51:53 +0200 Subject: [PATCH] Improved external credential managment via rest controller. --- .../external_credentials_controller.rb | 25 +++- lib/external_credential/facebook.rb | 2 +- lib/external_credential/twitter.rb | 1 + spec/factories/external_credential.rb | 5 + spec/requests/external_credential_spec.rb | 136 ++++++++++++++++++ 5 files changed, 167 insertions(+), 2 deletions(-) create mode 100644 spec/factories/external_credential.rb create mode 100644 spec/requests/external_credential_spec.rb diff --git a/app/controllers/external_credentials_controller.rb b/app/controllers/external_credentials_controller.rb index 5b68e9f3c..af387cae3 100644 --- a/app/controllers/external_credentials_controller.rb +++ b/app/controllers/external_credentials_controller.rb @@ -1,7 +1,7 @@ # Copyright (C) 2012-2016 Zammad Foundation, http://zammad-foundation.org/ class ExternalCredentialsController < ApplicationController - prepend_before_action { authentication_check(permission: ['admin.channel_twitter', 'admin.channel_facebook']) } + prepend_before_action :permission_check def index model_index_render(ExternalCredential, params) @@ -54,4 +54,27 @@ class ExternalCredentialsController < ApplicationController ExternalCredential.app_url(provider, channel_id) end + def permission_check + if params[:id].present? && ExternalCredential.exists?(params[:id]) + external_credential = ExternalCredential.find(params[:id]) + raise 'No such ExternalCredential!' if !external_credential + authentication_check(permission: ["admin.channel_#{external_credential.name}"]) + return + end + + if params[:name].present? || params[:provider].present? + if params[:name].present? + name = params[:name].downcase + elsif params[:provider].present? + name = params[:provider].downcase + else + raise 'Missing name/provider!' + end + authentication_check(permission: ["admin.channel_#{name}"]) + return + end + + authentication_check(permission: ['admin']) + end + end diff --git a/lib/external_credential/facebook.rb b/lib/external_credential/facebook.rb index 0c3afcc8d..89546082f 100644 --- a/lib/external_credential/facebook.rb +++ b/lib/external_credential/facebook.rb @@ -7,13 +7,13 @@ class ExternalCredential::Facebook def self.request_account_to_link(credentials = {}) external_credential = ExternalCredential.find_by(name: 'facebook') + raise Exceptions::UnprocessableEntity, 'No facebook app configured!' if !external_credential if !credentials[:application_id] credentials[:application_id] = external_credential.credentials['application_id'] end if !credentials[:application_secret] credentials[:application_secret] = external_credential.credentials['application_secret'] end - oauth = Koala::Facebook::OAuth.new( credentials[:application_id], credentials[:application_secret], diff --git a/lib/external_credential/twitter.rb b/lib/external_credential/twitter.rb index 8b9cfc9ef..41b6165e3 100644 --- a/lib/external_credential/twitter.rb +++ b/lib/external_credential/twitter.rb @@ -7,6 +7,7 @@ class ExternalCredential::Twitter def self.request_account_to_link(credentials = {}) external_credential = ExternalCredential.find_by(name: 'twitter') + raise Exceptions::UnprocessableEntity, 'No twitter app configured!' if !external_credential if !credentials[:consumer_key] credentials[:consumer_key] = external_credential.credentials['consumer_key'] end diff --git a/spec/factories/external_credential.rb b/spec/factories/external_credential.rb new file mode 100644 index 000000000..d4fc84f70 --- /dev/null +++ b/spec/factories/external_credential.rb @@ -0,0 +1,5 @@ +FactoryBot.define do + factory :external_credential do + credentials { { 'application_id' => '1234', 'application_secret' => 'secret' } } + end +end diff --git a/spec/requests/external_credential_spec.rb b/spec/requests/external_credential_spec.rb new file mode 100644 index 000000000..afdd96ccb --- /dev/null +++ b/spec/requests/external_credential_spec.rb @@ -0,0 +1,136 @@ +require 'rails_helper' + +RSpec.describe 'ExternalCredentials', type: :request do + + let(:admin_user) do + create(:admin_user) + end + + describe 'request handling' do + + it 'does external_credential index with nobody' do + get '/api/v1/external_credentials', as: :json + expect(response).to have_http_status(401) + expect(json_response).to be_a_kind_of(Hash) + expect(json_response['error']).to eq('authentication failed') + end + + it 'does external_credential app_verify with nobody' do + post '/api/v1/external_credentials/facebook/app_verify', as: :json + expect(response).to have_http_status(401) + expect(json_response).to be_a_kind_of(Hash) + expect(json_response['error']).to eq('authentication failed') + end + + it 'does link_account app_verify with nobody' do + get '/api/v1/external_credentials/facebook/link_account', as: :json + expect(response).to have_http_status(401) + expect(json_response).to be_a_kind_of(Hash) + expect(json_response['error']).to eq('authentication failed') + end + + it 'does external_credential callback with nobody' do + get '/api/v1/external_credentials/facebook/callback', as: :json + expect(response).to have_http_status(401) + expect(json_response).to be_a_kind_of(Hash) + expect(json_response['error']).to eq('authentication failed') + end + + it 'does external_credential index with admin' do + authenticated_as(admin_user) + get '/api/v1/external_credentials', as: :json + expect(response).to have_http_status(200) + expect(json_response).to be_a_kind_of(Array) + expect(json_response).to be_truthy + expect(json_response.count).to eq(0) + + get '/api/v1/external_credentials?expand=true', as: :json + expect(response).to have_http_status(200) + expect(json_response).to be_a_kind_of(Array) + expect(json_response).to be_truthy + expect(json_response.count).to eq(0) + end + + it 'does external_credential app_verify with admin' do + authenticated_as(admin_user) + post '/api/v1/external_credentials/facebook/app_verify', as: :json + expect(response).to have_http_status(200) + expect(json_response).to be_a_kind_of(Hash) + expect(json_response['error']).to eq('No facebook app configured!') + + create(:external_credential, name: 'facebook') + + post '/api/v1/external_credentials/facebook/app_verify', as: :json + expect(response).to have_http_status(200) + expect(json_response).to be_a_kind_of(Hash) + expect(json_response['error']).to eq('type: OAuthException, code: 101, message: Error validating application. Cannot get application info due to a system error. [HTTP 400]') + end + + it 'does link_account app_verify with admin' do + authenticated_as(admin_user) + get '/api/v1/external_credentials/facebook/link_account', as: :json + expect(response).to have_http_status(422) + expect(json_response).to be_a_kind_of(Hash) + expect(json_response['error']).to eq('No facebook app configured!') + + create(:external_credential, name: 'facebook') + + get '/api/v1/external_credentials/facebook/link_account', as: :json + expect(response).to have_http_status(500) + expect(json_response).to be_a_kind_of(Hash) + expect(json_response['error']).to eq('type: OAuthException, code: 101, message: Error validating application. Cannot get application info due to a system error. [HTTP 400]') + end + + it 'does external_credential callback with admin' do + authenticated_as(admin_user) + get '/api/v1/external_credentials/facebook/callback', as: :json + expect(response).to have_http_status(500) + expect(json_response).to be_a_kind_of(Hash) + expect(json_response['error']).to eq('No such account') + + create(:external_credential, name: 'facebook') + + get '/api/v1/external_credentials/facebook/callback', as: :json + expect(response).to have_http_status(500) + expect(json_response).to be_a_kind_of(Hash) + expect(json_response['error']).to eq('type: OAuthException, code: 101, message: Error validating application. Cannot get application info due to a system error. [HTTP 400]') + end + + it 'does external_credential app_verify with admin and different permissions' do + authenticated_as(admin_user) + + create(:external_credential, name: 'twitter') + + post '/api/v1/external_credentials/twitter/app_verify', as: :json + expect(response).to have_http_status(200) + expect(json_response).to be_a_kind_of(Hash) + expect(json_response['error']).to eq('400 Bad Request') + + permission = Permission.find_by(name: 'admin.channel_twitter') + permission.active = false + permission.save! + + post '/api/v1/external_credentials/twitter/app_verify', as: :json + expect(response).to have_http_status(401) + expect(json_response).to be_a_kind_of(Hash) + expect(json_response['error']).to eq('Not authorized (user)!') + + create(:external_credential, name: 'facebook') + + post '/api/v1/external_credentials/facebook/app_verify', as: :json + expect(response).to have_http_status(200) + expect(json_response).to be_a_kind_of(Hash) + expect(json_response['error']).to eq('type: OAuthException, code: 101, message: Error validating application. Cannot get application info due to a system error. [HTTP 400]') + + permission = Permission.find_by(name: 'admin.channel_facebook') + permission.active = false + permission.save! + + post '/api/v1/external_credentials/facebook/app_verify', as: :json + expect(response).to have_http_status(401) + expect(json_response).to be_a_kind_of(Hash) + expect(json_response['error']).to eq('Not authorized (user)!') + end + + end +end