diff --git a/api/lib/mno_enterprise/concerns/controllers/jpi/v1/deletion_requests_controller.rb b/api/lib/mno_enterprise/concerns/controllers/jpi/v1/deletion_requests_controller.rb index 4c55cc98b..40ef4e2a2 100644 --- a/api/lib/mno_enterprise/concerns/controllers/jpi/v1/deletion_requests_controller.rb +++ b/api/lib/mno_enterprise/concerns/controllers/jpi/v1/deletion_requests_controller.rb @@ -58,5 +58,4 @@ def destroy head :bad_request end end - end diff --git a/api/spec/controllers/mno_enterprise/auth/omniauth_callback_controller_spec.rb b/api/spec/controllers/mno_enterprise/auth/omniauth_callback_controller_spec.rb index 33f2d2e8f..ad64bff83 100644 --- a/api/spec/controllers/mno_enterprise/auth/omniauth_callback_controller_spec.rb +++ b/api/spec/controllers/mno_enterprise/auth/omniauth_callback_controller_spec.rb @@ -3,7 +3,9 @@ module MnoEnterprise describe Auth::OmniauthCallbacksController, type: :controller do routes { MnoEnterprise::Engine.routes } - supported_providers = %i(linkedin google facebook) + + ACTIVE_STATUSES = MnoEnterprise::AppInstance::ACTIVE_STATUSES.join(',') + describe 'provides callbacks for the providers' do before do @@ -17,5 +19,57 @@ module MnoEnterprise it { expect(controller).to respond_to(:intuit) } it { expect(controller).to respond_to(:facebook) } end + + describe '.setup_apps' do + let(:app) { build(:app) } + let(:app_instance) { build(:app_instance, app: app, oauth_keys_valid: false) } + let(:user) { build(:user) } + let(:orga_relation) { build(:orga_relation, :super_admin) } + let(:organization) { build(:organization) } + let(:app_nids) { [app.nid] } + let(:options) { {} } + let(:get_app_instances_params) { { filter: { 'owner.id': organization.id, 'status.in': ACTIVE_STATUSES } } } + + # setup_apps is a private method + subject { controller.send(:setup_apps, user, app_nids, options) } + + before do + stub_api_v2(:get, '/organizations', [organization], [], { filter: { 'users.id': user.id }, fields: { organizations: 'id' } }) + stub_api_v2(:get, '/orga_relations', [orga_relation], [], { filter: { 'user.id': user.id }, fields: { orga_relations: 'role' } }) + stub_api_v2(:get, '/apps', [app], [], { filter: { 'nid.in': app.nid }, fields: { apps: 'id,nid' } }) + end + + context 'when the app_instance already exists' do + before { stub_api_v2(:get, '/app_instances', [app_instance], [:app], get_app_instances_params) } + it 'does not create a new app instance' do + expect(subject.length).to be(1) + expect(subject.first.id).to eq(app_instance.id) + end + + describe 'when there is a oauth_keyset' do + let(:options) { { oauth_keyset: 'oauth_keyset' } } + let!(:stub) { stub_api_v2(:patch, "/app_instances/#{app_instance.id}", app_instance) } + it do + subject + expect(stub).to have_been_requested + end + end + + end + context 'when there is no previous app instance' do + let(:provisioned_app_instance) { build(:app_instance) } + before do + stub_audit_events + stub_api_v2(:get, '/app_instances', [], [:app], get_app_instances_params) + stub_api_v2(:get, '/app_instances/' + provisioned_app_instance.id, provisioned_app_instance, [:owner]) + end + let!(:stub) { stub_api_v2(:post, '/app_instances/provision', provisioned_app_instance) } + it 'provisions the app_instance' do + expect(subject.length).to be(1) + expect(subject.first.id).to eq(provisioned_app_instance.id) + expect(stub).to have_been_requested + end + end + end end end diff --git a/core/lib/mno_enterprise/concerns/controllers/auth/omniauth_callbacks_controller.rb b/core/lib/mno_enterprise/concerns/controllers/auth/omniauth_callbacks_controller.rb index 75de66a68..62fba11ac 100644 --- a/core/lib/mno_enterprise/concerns/controllers/auth/omniauth_callbacks_controller.rb +++ b/core/lib/mno_enterprise/concerns/controllers/auth/omniauth_callbacks_controller.rb @@ -99,7 +99,7 @@ def intuit # to the user orga # Only for new users for which an orga was created (not an invited user # typically) - app_instances = setup_apps(@user,['quickbooks',params[:app]], oauth_keyset: params[:app]) + app_instances = setup_apps(@user, ['quickbooks', params[:app]], oauth_keyset: params[:app]) qb_instance = app_instances.first # On Intuit, Mno is configured to add qb_initiated=true if the user @@ -141,63 +141,64 @@ def intuit #================================================ private - def cleanup_intuit_session - session.delete("omniauth.intuit.passthru_email") - session.delete("omniauth.intuit.request_account_link") - end + def cleanup_intuit_session + session.delete("omniauth.intuit.passthru_email") + session.delete("omniauth.intuit.request_account_link") + end - # Whether to create an orga on user creation - def create_orga_on_user_creation(user_email = nil) - return false if user_email.blank? - return false if MnoEnterprise::User.exists?(email: user_email) + # Whether to create an orga on user creation + def create_orga_on_user_creation(user_email = nil) + return false if user_email.blank? + return false if MnoEnterprise::User.exists?(email: user_email) - # First check previous url to see if the user - # was trying to accept an orga - if !session[:previous_url].blank? && (r = session[:previous_url].match(/\/orga_invites\/(\d+)\?token=(\w+)/)) - invite_params = { id: r.captures[0].to_i, token: r.captures[1] } - return false if MnoEnterprise::OrgaInvite.where(invite_params).any? - end - - # Get remaining invites via email address - return MnoEnterprise::OrgaInvite.where(user_email: user_email).empty? + # First check previous url to see if the user + # was trying to accept an orga + if !session[:previous_url].blank? && (r = session[:previous_url].match(/\/orga_invites\/(\d+)\?token=(\w+)/)) + invite_params = { id: r.captures[0].to_i, token: r.captures[1] } + return false if MnoEnterprise::OrgaInvite.where(invite_params).any? end - # Create or find the apps provided in argument - # Accept an array of app nid (named id - e.g: 'quickbooks') - # opts: - # oauth_keyset: If a oauth_keyset is provided then it will be added to the - # oauth_keys of any app that is oauth ready (QuickBooks for example) - # - # Return an array of app instances (found or created) - def setup_apps(user = nil, app_nids = [], opts = {}) - return [] unless user - return [] unless (user.organizations.reload.count == 1) - return [] unless (org = user.organizations.first) - return [] unless MnoEnterprise::Ability.new(user).can?(:edit,org) - - results = [] - - apps = MnoEnterprise::App.where(nid: app_nids.compact) - existing = org.app_instances.active.index_by(&:app_id) - - # For each app nid (which is not nil), try to find an existing instance or create one - apps.each do |app| - if (app_instance = existing[app.id]) - results << app_instance - else - # Provision instance and add to results - app_instance = org.provision_app_instance!(app.nid) - results << app_instance - MnoEnterprise::EventLogger.info('app_add', user.id, 'App added', app_instance) - end + # Get remaining invites via email address + return MnoEnterprise::OrgaInvite.where(user_email: user_email).empty? + end - # Add oauth keyset if defined and app_instance is - # oauth ready and does not have a valid set of oauth keys - if app_instance && opts[:oauth_keyset].present? && !app_instance.oauth_keys_valid - app_instance.oauth_keys = { keyset: opts[:oauth_keyset] } - app_instance.save - end + # Create or find the apps provided in argument + # Accept an array of app nid (named id - e.g: 'quickbooks') + # opts: + # oauth_keyset: If a oauth_keyset is provided then it will be added to the + # oauth_keys of any app that is oauth ready (QuickBooks for example) + # + # Return an array of app instances (found or created) + def setup_apps(user, app_nids, opts) + organizations = MnoEnterprise::Organization.where('users.id': user.id).select(:id) + orga_relations = MnoEnterprise::OrgaRelation.where('user.id': user.id).select(:role) + return [] unless (organizations.count == 1 && orga_relations.count == 1) + organization = organizations.first + return [] unless MnoEnterprise::Ability.new(user).can?(:update, orga_relations.first) + apps = MnoEnterprise::App.where('nid.in': app_nids.compact.join(',')).select('id,nid') + existing = MnoEnterprise::AppInstance + .where( + 'owner.id': organization.id, + 'status.in': MnoEnterprise::AppInstance::ACTIVE_STATUSES.join(',') + ).includes(:app) + .index_by { |a| a.app.id } + + # For each app nid (which is not nil), try to find an existing instance or create one + results = apps.map do |app| + unless (app_instance = existing[app.id]) + # Provision instance + app_instance = MnoEnterprise::AppInstance.provision!(app.nid, organization.id, 'Organization' ) + app_instance = app_instance.load_required(:owner) + MnoEnterprise::EventLogger.info('app_add', user.id, 'App added', app_instance) end - return results + # Add oauth keyset if defined and app_instance is + # oauth ready and does not have a valid set of oauth keys + if opts[:oauth_keyset].present? && !app_instance.oauth_keys_valid + app_instance.oauth_keys = { keyset: opts[:oauth_keyset] } + app_instance.save! + end + app_instance end + return results + end end diff --git a/core/lib/mno_enterprise/testing_support/factories/orga_relations.rb b/core/lib/mno_enterprise/testing_support/factories/orga_relations.rb index 4f921923c..d6d67d2d2 100644 --- a/core/lib/mno_enterprise/testing_support/factories/orga_relations.rb +++ b/core/lib/mno_enterprise/testing_support/factories/orga_relations.rb @@ -10,5 +10,8 @@ user_id '265' organization_id '265' role 'Admin' + trait :super_admin do + role 'Super Admin' + end end end