mno-enterprise-api 3.1.4 → 3.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/app/assets/javascripts/mno_enterprise/config.js.coffee.erb +7 -1
- data/app/controllers/mno_enterprise/auth/omniauth_callbacks_controller.rb +3 -27
- data/app/controllers/mno_enterprise/auth/sessions_controller.rb +1 -3
- data/app/controllers/mno_enterprise/jpi/v1/admin/app_answers_controller.rb +26 -0
- data/app/controllers/mno_enterprise/jpi/v1/admin/app_comments_controller.rb +28 -0
- data/app/controllers/mno_enterprise/jpi/v1/admin/app_instances_controller.rb +16 -0
- data/app/controllers/mno_enterprise/jpi/v1/admin/app_reviews_controller.rb +30 -0
- data/app/controllers/mno_enterprise/jpi/v1/admin/invites_controller.rb +1 -1
- data/app/controllers/mno_enterprise/jpi/v1/admin/organizations_controller.rb +55 -37
- data/app/controllers/mno_enterprise/jpi/v1/app_answers_controller.rb +22 -0
- data/app/controllers/mno_enterprise/jpi/v1/app_comments_controller.rb +22 -0
- data/app/controllers/mno_enterprise/jpi/v1/app_feedbacks_controller.rb +14 -0
- data/app/controllers/mno_enterprise/jpi/v1/app_instances_controller.rb +1 -20
- data/app/controllers/mno_enterprise/jpi/v1/app_questions_controller.rb +25 -0
- data/app/controllers/mno_enterprise/jpi/v1/app_reviews_controller.rb +94 -0
- data/app/controllers/mno_enterprise/jpi/v1/base_resource_controller.rb +12 -0
- data/app/controllers/mno_enterprise/jpi/v1/impac/alerts_controller.rb +5 -0
- data/app/controllers/mno_enterprise/jpi/v1/impac/kpis_controller.rb +1 -76
- data/app/controllers/mno_enterprise/jpi/v1/marketplace_controller.rb +1 -18
- data/app/controllers/mno_enterprise/jpi/v1/teams_controller.rb +1 -83
- data/app/jobs/mno_enterprise/event_logger_job.rb +10 -0
- data/app/views/mno_enterprise/auth/confirmations/new.html.haml +6 -6
- data/app/views/mno_enterprise/auth/passwords/new.html.haml +8 -8
- data/app/views/mno_enterprise/auth/registrations/new.html.haml +1 -0
- data/app/views/mno_enterprise/auth/sessions/new.html.haml +1 -0
- data/app/views/mno_enterprise/auth/shared/_links.html.haml +0 -5
- data/app/views/mno_enterprise/auth/shared/_omniauth.html.haml +10 -0
- data/app/views/mno_enterprise/jpi/v1/admin/app_answers/show.json.jbuilder +15 -0
- data/app/views/mno_enterprise/jpi/v1/admin/app_comments/show.json.jbuilder +15 -0
- data/app/views/mno_enterprise/jpi/v1/admin/app_reviews/_app_review.json.jbuilder +13 -0
- data/app/views/mno_enterprise/jpi/v1/admin/app_reviews/index.json.jbuilder +1 -0
- data/app/views/mno_enterprise/jpi/v1/admin/app_reviews/show.json.jbuilder +3 -0
- data/app/views/mno_enterprise/jpi/v1/admin/organizations/show.json.jbuilder +1 -0
- data/app/views/mno_enterprise/jpi/v1/admin/users/_user.json.jbuilder +1 -1
- data/app/views/mno_enterprise/jpi/v1/app_answers/_resource.json.jbuilder +4 -0
- data/app/views/mno_enterprise/jpi/v1/app_answers/index.json.jbuilder +5 -0
- data/app/views/mno_enterprise/jpi/v1/app_answers/show.json.jbuilder +3 -0
- data/app/views/mno_enterprise/jpi/v1/app_comments/_resource.json.jbuilder +3 -0
- data/app/views/mno_enterprise/jpi/v1/app_comments/index.json.jbuilder +5 -0
- data/app/views/mno_enterprise/jpi/v1/app_comments/show.json.jbuilder +3 -0
- data/app/views/mno_enterprise/jpi/v1/app_feedbacks/_comment.json.jbuilder +10 -0
- data/app/views/mno_enterprise/jpi/v1/app_feedbacks/_resource.json.jbuilder +7 -0
- data/app/views/mno_enterprise/jpi/v1/app_feedbacks/index.json.jbuilder +5 -0
- data/app/views/mno_enterprise/jpi/v1/app_feedbacks/show.json.jbuilder +4 -0
- data/app/views/mno_enterprise/jpi/v1/app_instances/_resource.json.jbuilder +9 -0
- data/app/views/mno_enterprise/jpi/v1/app_questions/_answer.json.jbuilder +3 -0
- data/app/views/mno_enterprise/jpi/v1/app_questions/_resource.json.jbuilder +8 -0
- data/app/views/mno_enterprise/jpi/v1/app_questions/index.json.jbuilder +5 -0
- data/app/views/mno_enterprise/jpi/v1/app_questions/show.json.jbuilder +3 -0
- data/app/views/mno_enterprise/jpi/v1/app_reviews/_resource.json.jbuilder +13 -0
- data/app/views/mno_enterprise/jpi/v1/app_reviews/index.json.jbuilder +5 -0
- data/app/views/mno_enterprise/jpi/v1/app_reviews/show.json.jbuilder +4 -0
- data/app/views/mno_enterprise/jpi/v1/base_resource/_app_review.json.jbuilder +17 -0
- data/app/views/mno_enterprise/jpi/v1/current_users/show.json.jbuilder +9 -1
- data/app/views/mno_enterprise/jpi/v1/impac/alerts/_alert.json.jbuilder +7 -0
- data/app/views/mno_enterprise/jpi/v1/impac/alerts/index.json.jbuilder +1 -0
- data/app/views/mno_enterprise/jpi/v1/impac/alerts/show.json.jbuilder +1 -0
- data/app/views/mno_enterprise/jpi/v1/impac/dashboards/_dashboard.json.jbuilder +8 -3
- data/app/views/mno_enterprise/jpi/v1/impac/kpis/_kpi.json.jbuilder +4 -1
- data/app/views/mno_enterprise/jpi/v1/impac/widgets/_widget.json.jbuilder +1 -1
- data/app/views/mno_enterprise/jpi/v1/impac/widgets/index.json.jbuilder +3 -0
- data/app/views/mno_enterprise/jpi/v1/marketplace/_app.json.jbuilder +4 -0
- data/app/views/mno_enterprise/jpi/v1/marketplace/index.json.jbuilder +1 -2
- data/app/views/mno_enterprise/jpi/v1/marketplace/show.json.jbuilder +1 -1
- data/app/views/mno_enterprise/jpi/v1/organizations/_current_user.json.jbuilder +1 -1
- data/app/views/mno_enterprise/jpi/v1/organizations/_invoices.json.jbuilder +3 -2
- data/app/views/mno_enterprise/jpi/v1/organizations/_member.json.jbuilder +2 -2
- data/app/views/mno_enterprise/jpi/v1/organizations/_organization.json.jbuilder +2 -2
- data/app/views/mno_enterprise/jpi/v1/teams/_team.json.jbuilder +11 -5
- data/app/views/mno_enterprise/pages/terms.html.haml +219 -0
- data/app/views/mno_enterprise/provision/_select_organization.html.haml +6 -2
- data/config/initializers/devise.rb +31 -9
- data/config/initializers/devise_log.rb +4 -4
- data/config/routes.rb +41 -6
- data/lib/mno_enterprise/api.rb +1 -0
- data/lib/mno_enterprise/audit_events_listener.rb +28 -0
- data/lib/mno_enterprise/concerns/controllers/jpi/v1/app_instances_controller.rb +45 -0
- data/lib/mno_enterprise/concerns/controllers/jpi/v1/current_users_controller.rb +14 -4
- data/lib/mno_enterprise/concerns/controllers/jpi/v1/impac/alerts_controller.rb +76 -0
- data/lib/mno_enterprise/concerns/controllers/jpi/v1/impac/dashboards_controller.rb +49 -23
- data/lib/mno_enterprise/concerns/controllers/jpi/v1/impac/kpis_controller.rb +167 -0
- data/lib/mno_enterprise/concerns/controllers/jpi/v1/impac/widgets_controller.rb +33 -17
- data/lib/mno_enterprise/concerns/controllers/jpi/v1/marketplace_controller.rb +32 -0
- data/lib/mno_enterprise/concerns/controllers/jpi/v1/organizations_controller.rb +68 -28
- data/lib/mno_enterprise/concerns/controllers/jpi/v1/teams_controller.rb +92 -0
- data/lib/mno_enterprise/concerns/controllers/pages_controller.rb +17 -3
- data/lib/mno_enterprise/concerns/controllers/provision_controller.rb +17 -2
- data/lib/mno_enterprise/concerns/mailers/system_notification_mailer.rb +27 -3
- data/lib/mno_enterprise/event_logger.rb +34 -16
- data/lib/mno_enterprise/intercom_events_listener.rb +96 -0
- data/spec/controllers/mno_enterprise/auth/confirmation_controller_spec.rb +28 -0
- data/spec/controllers/mno_enterprise/auth/omniauth_callback_controller_spec.rb +34 -0
- data/spec/controllers/mno_enterprise/jpi/v1/admin/app_answers_controller_spec.rb +45 -0
- data/spec/controllers/mno_enterprise/jpi/v1/admin/app_comments_controller_spec.rb +45 -0
- data/spec/controllers/mno_enterprise/jpi/v1/admin/app_instances_controller_spec.rb +31 -0
- data/spec/controllers/mno_enterprise/jpi/v1/admin/app_reviews_controller_spec.rb +103 -0
- data/spec/controllers/mno_enterprise/jpi/v1/admin/audit_events_controller_spec.rb +4 -15
- data/spec/controllers/mno_enterprise/jpi/v1/admin/cloud_apps_controller_spec.rb +12 -3
- data/spec/controllers/mno_enterprise/jpi/v1/admin/invites_controller_spec.rb +4 -0
- data/spec/controllers/mno_enterprise/jpi/v1/admin/invoices_controller_spec.rb +15 -0
- data/spec/controllers/mno_enterprise/jpi/v1/admin/organizations_controller_spec.rb +17 -1
- data/spec/controllers/mno_enterprise/jpi/v1/admin/tenant_invoices_controller_spec.rb +5 -0
- data/spec/controllers/mno_enterprise/jpi/v1/admin/users_controller_spec.rb +30 -16
- data/spec/controllers/mno_enterprise/jpi/v1/app_answers_controller_spec.rb +74 -0
- data/spec/controllers/mno_enterprise/jpi/v1/app_comments_controller_spec.rb +74 -0
- data/spec/controllers/mno_enterprise/jpi/v1/app_feedbacks_controller_spec.rb +84 -0
- data/spec/controllers/mno_enterprise/jpi/v1/app_instances_controller_spec.rb +36 -22
- data/spec/controllers/mno_enterprise/jpi/v1/app_questions_controller_spec.rb +80 -0
- data/spec/controllers/mno_enterprise/jpi/v1/app_reviews_controller_spec.rb +107 -0
- data/spec/controllers/mno_enterprise/jpi/v1/current_users_controller_spec.rb +16 -1
- data/spec/controllers/mno_enterprise/jpi/v1/impac/alerts_controller_spec.rb +82 -0
- data/spec/controllers/mno_enterprise/jpi/v1/impac/kpis_controller_spec.rb +147 -10
- data/spec/controllers/mno_enterprise/jpi/v1/impac/widgets_controller_spec.rb +39 -0
- data/spec/controllers/mno_enterprise/jpi/v1/marketplace_controller_spec.rb +19 -26
- data/spec/controllers/mno_enterprise/jpi/v1/organizations_controller_spec.rb +248 -303
- data/spec/controllers/mno_enterprise/jpi/v1/team_controller_spec.rb +4 -1
- data/spec/controllers/mno_enterprise/pages_controller_spec.rb +21 -0
- data/spec/controllers/mno_enterprise/provision_controller_spec.rb +65 -22
- data/spec/controllers/mno_enterprise/webhook/o_auth_controller_spec.rb +1 -1
- data/spec/jobs/mno_enterprise/event_logger_job_spec.rb +11 -0
- data/spec/lib/mno_enterprise/audit_events_listener_spec.rb +28 -0
- data/spec/lib/mno_enterprise/intercom_events_listener_spec.rb +110 -0
- data/spec/mailer/mno_enterprise/system_notification_mailer_spec.rb +81 -46
- data/spec/routing/mno_enterprise/jpi/v1/admin/app_instances_controller_routing_spec.rb +11 -0
- data/spec/routing/mno_enterprise/jpi/v1/admin/app_reviews_controller_routing_spec.rb +19 -0
- data/spec/routing/mno_enterprise/jpi/v1/app_instances_controller_routing_spec.rb +9 -2
- data/spec/routing/mno_enterprise/jpi/v1/app_reviews_controller_routing_spec.rb +15 -0
- data/spec/routing/mno_enterprise/jpi/v1/current_users_controller_routing_spec.rb +5 -0
- data/spec/routing/mno_enterprise/jpi/v1/impac/alerts_controller_routing_spec.rb +24 -0
- data/spec/routing/mno_enterprise/jpi/v1/impac/dashboards_controller_routing_spec.rb +28 -0
- data/spec/routing/mno_enterprise/jpi/v1/impac/kpis_controller_routing_spec.rb +17 -11
- data/spec/routing/mno_enterprise/jpi/v1/impac/widgets_controller_routing_spec.rb +24 -0
- data/spec/routing/mno_enterprise/jpi/v1/marketplace_controller_routing_spec.rb +2 -2
- data/spec/routing/mno_enterprise/pages_controller_routing_spec.rb +4 -0
- metadata +178 -9
- data/app/controllers/mno_enterprise/jpi/v1/industry_bundle_controller.rb +0 -25
- data/app/controllers/mno_enterprise/jpi/v1/shopping_cart_controller.rb +0 -93
- data/spec/lib/mno_enterprise/event_logger_spec.rb +0 -28
@@ -49,12 +49,15 @@ module MnoEnterprise
|
|
49
49
|
before { allow(ability).to receive(:can?).with(any_args).and_return(true) }
|
50
50
|
|
51
51
|
# Stub user and user call
|
52
|
+
let!(:app) { build(:app) }
|
52
53
|
let(:user) { build(:user, :with_organizations) }
|
53
54
|
let(:user2) { build(:user, :with_organizations, name: "Joe") }
|
54
55
|
let(:organization) { build(:organization) }
|
55
56
|
let(:team) { build(:team, organization: organization) }
|
56
|
-
let(:app_instance) { build(:app_instance) }
|
57
|
+
let(:app_instance) { build(:app_instance, app: app, app_id: app.id) }
|
57
58
|
before do
|
59
|
+
api_stub_for(get: '/apps', response: from_api([app]))
|
60
|
+
api_stub_for(get: "/apps/#{app.id}", response: from_api(app))
|
58
61
|
api_stub_for(get: "/users/#{user.id}", response: from_api(user))
|
59
62
|
api_stub_for(get: "/users/#{user.id}/organizations", response: from_api(organization))
|
60
63
|
api_stub_for(post: "/organizations", response: from_api(organization))
|
@@ -31,6 +31,19 @@ module MnoEnterprise
|
|
31
31
|
end
|
32
32
|
end
|
33
33
|
|
34
|
+
describe 'GET #launch with parameters' do
|
35
|
+
let(:app_instance) { build(:app_instance) }
|
36
|
+
before { sign_in user }
|
37
|
+
subject { get :launch, id: app_instance.uid, specific_parameters: 'specific_parameters_value' }
|
38
|
+
|
39
|
+
it_behaves_like "a navigatable protected user action"
|
40
|
+
|
41
|
+
it 'redirects to the mno enterprise launch page with a web token and extra params' do
|
42
|
+
subject
|
43
|
+
expect(response).to redirect_to(MnoEnterprise.router.launch_url(app_instance.uid, wtk: MnoEnterprise.jwt({user_id: user.uid}), specific_parameters: 'specific_parameters_value'))
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
34
47
|
describe 'GET #app_access_unauthorized' do
|
35
48
|
subject { get :app_access_unauthorized }
|
36
49
|
before { subject }
|
@@ -49,5 +62,13 @@ module MnoEnterprise
|
|
49
62
|
it { expect(response).to be_success }
|
50
63
|
end
|
51
64
|
|
65
|
+
describe 'GET #terms' do
|
66
|
+
before { api_stub_for(get: "/apps", response: from_api([build(:app)])) }
|
67
|
+
|
68
|
+
subject { get :terms }
|
69
|
+
before { subject }
|
70
|
+
it { expect(response).to be_success }
|
71
|
+
end
|
72
|
+
|
52
73
|
end
|
53
74
|
end
|
@@ -1,5 +1,9 @@
|
|
1
1
|
require 'rails_helper'
|
2
2
|
|
3
|
+
def mnoe_home_path
|
4
|
+
controller.send(:mnoe_home_path)
|
5
|
+
end
|
6
|
+
|
3
7
|
module MnoEnterprise
|
4
8
|
describe ProvisionController, type: :controller do
|
5
9
|
render_views
|
@@ -27,39 +31,73 @@ module MnoEnterprise
|
|
27
31
|
it { expect(response).to redirect_to(new_user_registration_path) }
|
28
32
|
end
|
29
33
|
|
30
|
-
|
31
|
-
describe 'signed in and missing organization with multiple organizations available' do
|
32
|
-
let(:params_org_id) { nil }
|
34
|
+
context 'signed in' do
|
33
35
|
let(:authorized) { true }
|
34
36
|
before do
|
35
|
-
allow_any_instance_of(User).to receive(:organizations).and_return(
|
37
|
+
allow_any_instance_of(User).to receive(:organizations).and_return(organizations)
|
36
38
|
sign_in user
|
37
|
-
allow(ability).to receive(:
|
39
|
+
allow(ability).to receive(:cannot?).with(:manage_app_instances, organization).and_return(!authorized)
|
38
40
|
subject
|
39
41
|
end
|
40
42
|
|
41
|
-
|
43
|
+
context 'without organization_id' do
|
44
|
+
let(:params_org_id) { nil }
|
42
45
|
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
end
|
46
|
+
context 'with multiple organizations available' do
|
47
|
+
let(:organizations) { [organization, organization] }
|
48
|
+
it { expect(response).to render_template('mno_enterprise/provision/_select_organization') }
|
49
|
+
end
|
48
50
|
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
51
|
+
context 'with one organization available' do
|
52
|
+
let(:organizations) { [organization] }
|
53
|
+
|
54
|
+
it { expect(response).to render_template('mno_enterprise/provision/_provision_apps') }
|
55
|
+
it { expect(assigns[:organization]).to eq(organization) }
|
56
|
+
|
57
|
+
describe "unauthorized" do
|
58
|
+
let(:authorized) { false }
|
59
|
+
|
60
|
+
let(:error_fragment) { "#?#{URI.encode_www_form([['flash', {msg: "Unfortunately you do not have permission to purchase products for this organization", type: :error}.to_json]])}" }
|
61
|
+
|
62
|
+
it 'redirect to the dashboard with an error message' do
|
63
|
+
expect(response).to redirect_to(mnoe_home_path + error_fragment)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
56
67
|
end
|
57
68
|
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
69
|
+
context 'with organization_id' do
|
70
|
+
let(:organizations) { [organization, organization] }
|
71
|
+
|
72
|
+
context 'authorized' do
|
73
|
+
it { expect(response).to render_template('mno_enterprise/provision/_provision_apps') }
|
74
|
+
end
|
75
|
+
|
76
|
+
context 'unauthorized' do
|
77
|
+
let(:authorized) { false }
|
78
|
+
context 'with multiple organizations available' do
|
79
|
+
let(:organizations) { [organization, organization] }
|
80
|
+
|
81
|
+
it 'display an errors message and display the list of organization' do
|
82
|
+
subject
|
83
|
+
expect(controller).to set_flash.now[:alert] #.to('Unfortunately you do not have permission to purchase products for this organization')
|
84
|
+
expect(response).to be_success
|
85
|
+
end
|
86
|
+
|
87
|
+
it { expect(response).to render_template('mno_enterprise/provision/_select_organization') }
|
88
|
+
end
|
89
|
+
|
90
|
+
context 'with one organization available' do
|
91
|
+
let(:organizations) { [organization] }
|
92
|
+
let(:error_fragment) { "#?#{URI.encode_www_form([['flash', {msg: "Unfortunately you do not have permission to purchase products for this organization", type: :error}.to_json]])}" }
|
93
|
+
|
94
|
+
it 'redirect to the dashboard with an error message' do
|
95
|
+
expect(response).to redirect_to(mnoe_home_path + error_fragment)
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
62
99
|
end
|
100
|
+
|
63
101
|
end
|
64
102
|
end
|
65
103
|
|
@@ -87,6 +125,11 @@ module MnoEnterprise
|
|
87
125
|
end
|
88
126
|
|
89
127
|
it { expect(response).to be_success }
|
128
|
+
|
129
|
+
it 'deletes the previous url from session to avoid double provisioning' do
|
130
|
+
subject
|
131
|
+
expect(session[:previous_url]).to be_nil
|
132
|
+
end
|
90
133
|
end
|
91
134
|
end
|
92
135
|
|
@@ -80,7 +80,7 @@ module MnoEnterprise
|
|
80
80
|
it_behaves_like 'a navigatable protected user action'
|
81
81
|
it_behaves_like 'a user protected resource'
|
82
82
|
|
83
|
-
it { subject; expect(response).to redirect_to
|
83
|
+
it { subject; expect(response).to redirect_to redirect_url }
|
84
84
|
end
|
85
85
|
|
86
86
|
describe 'GET #sync' do
|
@@ -0,0 +1,11 @@
|
|
1
|
+
require 'rails_helper'
|
2
|
+
|
3
|
+
module MnoEnterprise
|
4
|
+
RSpec.describe EventLoggerJob, type: :job do
|
5
|
+
it 'dispatch the notification to the event logger' do
|
6
|
+
args = ['app_destroy', 1, 'App destroyed', 'Xero', build(:app_instance)]
|
7
|
+
expect(EventLogger).to receive(:send_info).with(*args)
|
8
|
+
EventLoggerJob.perform_now(:info, *args)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'rails_helper'
|
2
|
+
|
3
|
+
module MnoEnterprise
|
4
|
+
RSpec.describe AuditEventsListener do
|
5
|
+
|
6
|
+
def info_data(user)
|
7
|
+
{
|
8
|
+
data: {
|
9
|
+
key: 'user_update_password',
|
10
|
+
user_id: user.id,
|
11
|
+
description: 'User password change',
|
12
|
+
metadata: user.email,
|
13
|
+
subject_type: user.class.name,
|
14
|
+
subject_id: user.id
|
15
|
+
}
|
16
|
+
}
|
17
|
+
end
|
18
|
+
|
19
|
+
let(:user) { build(:user) }
|
20
|
+
|
21
|
+
describe '#info' do
|
22
|
+
subject { MnoEnterprise::AuditEventsListener.new.info('user_update_password', user.id, 'User password change', user.class.name, user.id, user.email) }
|
23
|
+
|
24
|
+
it { expect(subject.code).to eq(200) }
|
25
|
+
it { expect(subject.request.options[:body]).to eq(info_data(user)) }
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,110 @@
|
|
1
|
+
require 'rails_helper'
|
2
|
+
|
3
|
+
module MnoEnterprise
|
4
|
+
RSpec.describe IntercomEventsListener do
|
5
|
+
let(:app) { build(:app) }
|
6
|
+
let(:app_instance) { build(:app_instance, app: app, organization_id: organization.id) }
|
7
|
+
let(:user) { build(:user) }
|
8
|
+
let(:organization) { build(:organization) }
|
9
|
+
before do
|
10
|
+
api_stub_for(get: "/users/#{user.id}", response: from_api(user))
|
11
|
+
api_stub_for(get: "/users/#{user.id}/organizations", response: from_api([organization]))
|
12
|
+
api_stub_for(get: "/organizations/#{organization.id}/app_instances", response: from_api([app_instance]))
|
13
|
+
end
|
14
|
+
|
15
|
+
# Stub Intercom client
|
16
|
+
let(:tags) { double('tags') }
|
17
|
+
let(:events) { double('events') }
|
18
|
+
let(:users) { double('users') }
|
19
|
+
let(:client) { double('client', users: users, events: events, tags: tags) }
|
20
|
+
before do
|
21
|
+
expect(Intercom::Client).to receive(:new).with(app_id: MnoEnterprise.intercom_app_id, api_key: MnoEnterprise.intercom_api_key).and_return(client)
|
22
|
+
end
|
23
|
+
|
24
|
+
let(:expected_user_data) {
|
25
|
+
{
|
26
|
+
user_id: user.id,
|
27
|
+
name: [user.name, user.surname].join(' '),
|
28
|
+
email: user.email,
|
29
|
+
created_at: user.created_at.to_i,
|
30
|
+
last_seen_ip: user.last_sign_in_ip,
|
31
|
+
custom_attributes: {phone: user.phone},
|
32
|
+
update_last_request_at: true,
|
33
|
+
companies:[
|
34
|
+
{
|
35
|
+
company_id: organization.id,
|
36
|
+
name: organization.name,
|
37
|
+
created_at: organization.created_at.to_i,
|
38
|
+
custom_attributes: {
|
39
|
+
industry: organization.industry,
|
40
|
+
size: organization.size,
|
41
|
+
credit_card_details: organization.credit_card?,
|
42
|
+
app_count: organization.app_instances.count,
|
43
|
+
app_list: organization.app_instances.map { |app| app.name }.to_sentence
|
44
|
+
}
|
45
|
+
}
|
46
|
+
]
|
47
|
+
}
|
48
|
+
}
|
49
|
+
|
50
|
+
describe '#info' do
|
51
|
+
context 'when the user already exist in intercom' do
|
52
|
+
before { allow(users).to receive(:find) }
|
53
|
+
subject { described_class.new }
|
54
|
+
|
55
|
+
it 'add an event when an password is changed' do
|
56
|
+
expect(events).to receive(:create).with(hash_including(email: user.email, user_id: user.id, event_name: 'user-update-password'))
|
57
|
+
subject.info('user_update_password', user.id, 'User password change', user.class.name, user.id, user.email)
|
58
|
+
end
|
59
|
+
|
60
|
+
it 'add an event when an app is added' do
|
61
|
+
expect(events).to receive(:create).with(hash_including(email: user.email, user_id: user.id, event_name: 'added-app-' + app.nid, metadata: {type: 'single', app_list: app.nid}))
|
62
|
+
subject.info('app_add', user.id, 'App Added', app_instance.class.name, app_instance.id, {name: app_instance.name, app_nid: app_instance.app.nid} )
|
63
|
+
end
|
64
|
+
|
65
|
+
it 'add an event when an app is launched' do
|
66
|
+
expect(events).to receive(:create).with(hash_including(email: user.email, user_id: user.id, event_name: 'launched-app-' + app.nid))
|
67
|
+
subject.info('app_launch', user.id, 'App Launched', app_instance.class.name, app_instance.id, {name: app_instance.name, app_nid: app_instance.app.nid} )
|
68
|
+
end
|
69
|
+
|
70
|
+
end
|
71
|
+
context 'when the user does not exist in intercom' do
|
72
|
+
before do
|
73
|
+
allow(users).to receive(:find).and_raise(Intercom::ResourceNotFound.new('not found'))
|
74
|
+
expect(users).to receive(:create).with(expected_user_data)
|
75
|
+
end
|
76
|
+
|
77
|
+
it 'add an event when an password is changed' do
|
78
|
+
expect(events).to receive(:create).with(hash_including(email: user.email, event_name: 'user-update-password'))
|
79
|
+
subject.info('user_update_password', user.id, 'User password change', user.class.name, user.id, user.email)
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
describe '#update_intercom_user' do
|
85
|
+
subject { described_class.new.update_intercom_user(user) }
|
86
|
+
before { allow(users).to receive(:create) }
|
87
|
+
|
88
|
+
it 'updates the user' do
|
89
|
+
expect(users).to receive(:create).with(expected_user_data)
|
90
|
+
subject
|
91
|
+
end
|
92
|
+
|
93
|
+
context 'when the user has an external_id' do
|
94
|
+
before { user.external_id = '132456' }
|
95
|
+
it 'updates the user' do
|
96
|
+
expect(users).to receive(:create).with(hash_including(custom_attributes: { phone: user.phone, external_id: '132456' }))
|
97
|
+
subject
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
context 'when the user has a source' do
|
102
|
+
before { user.meta_data = {source: 'acme'}}
|
103
|
+
it 'tags the user' do
|
104
|
+
expect(tags).to receive(:tag).with(name: 'acme', users: [{user_id: user.id}])
|
105
|
+
subject
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
@@ -14,6 +14,10 @@ module MnoEnterprise
|
|
14
14
|
{ first_name: user.name, last_name: user.surname, full_name: "#{user.name} #{user.surname}".strip }
|
15
15
|
end
|
16
16
|
|
17
|
+
def recipient(user)
|
18
|
+
{ name: "#{user.name} #{user.surname}".strip, email: user.email }
|
19
|
+
end
|
20
|
+
|
17
21
|
def invite_vars(org_invite)
|
18
22
|
new_user = !org_invite.user.confirmed?
|
19
23
|
|
@@ -31,63 +35,95 @@ module MnoEnterprise
|
|
31
35
|
}
|
32
36
|
end
|
33
37
|
|
38
|
+
# Custom matcher to DRY the code
|
39
|
+
# TODO: extract to `testing_support`? Still dependent on local variables
|
40
|
+
RSpec::Matchers.define :send_the_correct_user_email do |template, extra_user_vars|
|
41
|
+
match do |block|
|
42
|
+
expect(MnoEnterprise::MailClient).to receive(:deliver).with(
|
43
|
+
template,
|
44
|
+
SystemNotificationMailer::DEFAULT_SENDER,
|
45
|
+
recipient(user),
|
46
|
+
user_vars(user).merge(extra_user_vars)
|
47
|
+
)
|
48
|
+
block.call
|
49
|
+
true
|
50
|
+
end
|
51
|
+
|
52
|
+
description do
|
53
|
+
"send the correct user email (\"#{template}\")"
|
54
|
+
end
|
55
|
+
|
56
|
+
supports_block_expectations
|
57
|
+
end
|
58
|
+
|
34
59
|
describe 'confirmation_instructions' do
|
35
60
|
describe 'new user' do
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
61
|
+
let(:user) { build(:user, :unconfirmed) }
|
62
|
+
it do
|
63
|
+
expect {
|
64
|
+
subject.confirmation_instructions(user,token).deliver_now
|
65
|
+
}.to send_the_correct_user_email(
|
66
|
+
'confirmation-instructions',
|
67
|
+
confirmation_link: routes.user_confirmation_url(confirmation_token: token)
|
41
68
|
)
|
42
|
-
|
43
|
-
subject.confirmation_instructions(user,token).deliver_now
|
44
69
|
end
|
45
70
|
end
|
46
|
-
|
71
|
+
|
47
72
|
describe 'existing user with new email address' do
|
48
|
-
before {
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
73
|
+
before { user.unconfirmed_email = 'unconfirmed@test.com' }
|
74
|
+
|
75
|
+
it 'sends confirmation to new and old email address' do
|
76
|
+
expect(MnoEnterprise::MailClient).to receive(:deliver).with(
|
77
|
+
'reconfirmation-instructions',
|
53
78
|
SystemNotificationMailer::DEFAULT_SENDER,
|
54
|
-
|
79
|
+
recipient(user).merge(email: 'unconfirmed@test.com'),
|
55
80
|
user_vars(user).merge(confirmation_link: routes.user_confirmation_url(confirmation_token: token))
|
56
81
|
)
|
57
|
-
|
58
|
-
|
82
|
+
|
83
|
+
expect {
|
84
|
+
subject.confirmation_instructions(user,token).deliver_now
|
85
|
+
}.to send_the_correct_user_email(
|
86
|
+
'email-change',
|
87
|
+
unconfirmed_email: 'unconfirmed@test.com'
|
88
|
+
)
|
59
89
|
end
|
60
90
|
end
|
61
91
|
end
|
62
|
-
|
92
|
+
|
63
93
|
describe 'reset_password_instructions' do
|
64
|
-
it
|
65
|
-
expect
|
66
|
-
|
67
|
-
|
68
|
-
|
94
|
+
it do
|
95
|
+
expect {
|
96
|
+
subject.reset_password_instructions(user,token).deliver_now
|
97
|
+
}.to send_the_correct_user_email(
|
98
|
+
'reset-password-instructions',
|
99
|
+
reset_password_link: routes.edit_user_password_url(reset_password_token: token)
|
69
100
|
)
|
70
|
-
|
71
|
-
subject.reset_password_instructions(user,token).deliver_now
|
72
101
|
end
|
73
102
|
end
|
74
|
-
|
103
|
+
|
75
104
|
describe 'unlock_instructions' do
|
76
|
-
it
|
77
|
-
expect
|
78
|
-
|
79
|
-
|
80
|
-
|
105
|
+
it do
|
106
|
+
expect {
|
107
|
+
subject.unlock_instructions(user,token).deliver_now
|
108
|
+
}.to send_the_correct_user_email(
|
109
|
+
'unlock-instructions',
|
110
|
+
unlock_link: routes.user_unlock_url(unlock_token: token)
|
81
111
|
)
|
82
|
-
|
83
|
-
subject.unlock_instructions(user,token).deliver_now
|
84
112
|
end
|
85
113
|
end
|
86
|
-
|
114
|
+
|
115
|
+
describe 'password_change' do
|
116
|
+
it 'sends an email to notify the user' do
|
117
|
+
expect {
|
118
|
+
subject.password_change(user).deliver_now
|
119
|
+
}.to send_the_correct_user_email('password-change', {})
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
87
123
|
describe 'organization_invite' do
|
88
124
|
let(:invitee) { build(:user) }
|
89
125
|
let(:org_invite) { build(:org_invite, user: invitee, referrer: user) }
|
90
|
-
|
126
|
+
|
91
127
|
context 'when invitee is a confirmed user' do
|
92
128
|
it 'sends the right email' do
|
93
129
|
expect(MnoEnterprise::MailClient).to receive(:deliver).with('organization-invite-existing-user',
|
@@ -95,21 +131,21 @@ module MnoEnterprise
|
|
95
131
|
{ name: "#{invitee.name} #{invitee.surname}".strip, email: invitee.email },
|
96
132
|
invite_vars(org_invite).merge(confirmation_link: routes.org_invite_url(id: org_invite.id, token: org_invite.token))
|
97
133
|
)
|
98
|
-
|
134
|
+
|
99
135
|
subject.organization_invite(org_invite).deliver_now
|
100
136
|
end
|
101
137
|
end
|
102
|
-
|
138
|
+
|
103
139
|
context 'when inviteee is an unconfirmed user' do
|
104
140
|
let(:invitee) { build(:user, :unconfirmed) }
|
105
|
-
|
141
|
+
|
106
142
|
it 'sends the right email' do
|
107
143
|
expect(MnoEnterprise::MailClient).to receive(:deliver).with('organization-invite-new-user',
|
108
144
|
SystemNotificationMailer::DEFAULT_SENDER,
|
109
145
|
{ email: invitee.email },
|
110
146
|
invite_vars(org_invite).merge(confirmation_link: routes.user_confirmation_url(confirmation_token: invitee.confirmation_token))
|
111
147
|
)
|
112
|
-
|
148
|
+
|
113
149
|
subject.organization_invite(org_invite).deliver_now
|
114
150
|
end
|
115
151
|
end
|
@@ -117,14 +153,13 @@ module MnoEnterprise
|
|
117
153
|
end
|
118
154
|
|
119
155
|
describe 'deletion_request_instructions' do
|
120
|
-
it
|
121
|
-
expect
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
subject.deletion_request_instructions(user,deletion_request).deliver_now
|
156
|
+
it do
|
157
|
+
expect {
|
158
|
+
subject.deletion_request_instructions(user,deletion_request).deliver_now
|
159
|
+
}.to send_the_correct_user_email(
|
160
|
+
'deletion-request-instructions',
|
161
|
+
terminate_account_link: routes.deletion_request_url(deletion_request)
|
162
|
+
)
|
128
163
|
end
|
129
164
|
end
|
130
165
|
|