mno-enterprise-api 3.3.1 → 3.3.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/javascripts/mno_enterprise/config.js.coffee.erb +1 -0
  3. data/app/controllers/mno_enterprise/impersonate_controller.rb +5 -1
  4. data/app/controllers/mno_enterprise/jpi/v1/admin/impac/dashboard_templates_controller.rb +93 -0
  5. data/app/controllers/mno_enterprise/jpi/v1/admin/impac/kpis_controller.rb +71 -0
  6. data/app/controllers/mno_enterprise/jpi/v1/admin/impac/widgets_controller.rb +70 -0
  7. data/app/controllers/mno_enterprise/jpi/v1/impac/dashboard_templates_controller.rb +5 -0
  8. data/app/views/mno_enterprise/auth/confirmations/_form.html.haml +10 -1
  9. data/app/views/mno_enterprise/jpi/v1/admin/base_resource/_member.json.jbuilder +1 -0
  10. data/app/views/mno_enterprise/jpi/v1/admin/impac/dashboard_templates/_template.json.jbuilder +16 -0
  11. data/app/views/mno_enterprise/jpi/v1/admin/impac/dashboard_templates/index.json.jbuilder +1 -0
  12. data/app/views/mno_enterprise/jpi/v1/admin/impac/dashboard_templates/show.json.jbuilder +1 -0
  13. data/app/views/mno_enterprise/jpi/v1/admin/impac/kpis/_kpi.json.jbuilder +2 -0
  14. data/app/views/mno_enterprise/jpi/v1/admin/impac/kpis/show.json.jbuilder +1 -0
  15. data/app/views/mno_enterprise/jpi/v1/admin/impac/widgets/_widget.json.jbuilder +7 -0
  16. data/app/views/mno_enterprise/jpi/v1/admin/impac/widgets/show.json.jbuilder +1 -0
  17. data/app/views/mno_enterprise/jpi/v1/app_feedbacks/_resource.json.jbuilder +1 -0
  18. data/app/views/mno_enterprise/jpi/v1/app_questions/_resource.json.jbuilder +1 -0
  19. data/app/views/mno_enterprise/jpi/v1/current_users/show.json.jbuilder +1 -0
  20. data/app/views/mno_enterprise/jpi/v1/impac/dashboard_templates/index.json.jbuilder +1 -0
  21. data/app/views/mno_enterprise/jpi/v1/impac/kpis/_kpi.json.jbuilder +1 -1
  22. data/app/views/mno_enterprise/pages/loading.html.erb +1 -1
  23. data/config/routes.rb +12 -0
  24. data/lib/mno_enterprise/concerns/controllers/jpi/v1/impac/dashboard_templates_controller.rb +20 -0
  25. data/lib/mno_enterprise/concerns/controllers/jpi/v1/impac/dashboards_controller.rb +25 -2
  26. data/lib/mno_enterprise/concerns/controllers/jpi/v1/impac/kpis_controller.rb +13 -11
  27. data/lib/mno_enterprise/concerns/controllers/jpi/v1/marketplace_controller.rb +1 -1
  28. data/lib/mno_enterprise/concerns/controllers/pages_controller.rb +3 -1
  29. data/spec/controllers/mno_enterprise/impersonate_controller_spec.rb +11 -2
  30. data/spec/controllers/mno_enterprise/jpi/v1/admin/impac/dashboard_templates_controller_spec.rb +225 -0
  31. data/spec/controllers/mno_enterprise/jpi/v1/admin/impac/kpis_controller_spec.rb +134 -0
  32. data/spec/controllers/mno_enterprise/jpi/v1/admin/impac/widgets_controller_spec.rb +150 -0
  33. data/spec/controllers/mno_enterprise/jpi/v1/app_feedbacks_controller_spec.rb +2 -1
  34. data/spec/controllers/mno_enterprise/jpi/v1/app_questions_controller_spec.rb +2 -1
  35. data/spec/controllers/mno_enterprise/jpi/v1/impac/dashboard_templates_controller_spec.rb +97 -0
  36. data/spec/controllers/mno_enterprise/jpi/v1/impac/dashboards_controller_spec.rb +223 -0
  37. data/spec/controllers/mno_enterprise/jpi/v1/marketplace_controller_spec.rb +31 -1
  38. data/spec/controllers/mno_enterprise/pages_controller_spec.rb +13 -2
  39. data/spec/routing/mno_enterprise/jpi/v1/admin/impac/dashboard_templates_controller_routing_spec.rb +28 -0
  40. data/spec/routing/mno_enterprise/jpi/v1/admin/impac/kpis_controller_routing_spec.rb +20 -0
  41. data/spec/routing/mno_enterprise/jpi/v1/admin/impac/widgets_controller_routing_spec.rb +20 -0
  42. data/spec/routing/mno_enterprise/jpi/v1/impac/dashboard_templates_controller_routing_spec.rb +11 -0
  43. metadata +35 -4
@@ -74,14 +74,37 @@ module MnoEnterprise::Concerns::Controllers::Jpi::V1::Impac::DashboardsControlle
74
74
  end
75
75
  end
76
76
 
77
+ # Allows to create a dashboard using another dashboard as a source
78
+ # At the moment, only dashboards of type "template" can be copied
79
+ # Ultimately we could allow the creation of dashboards from any other dashboard
80
+ # ---------------------------------
81
+ # POST mnoe/jpi/v1/impac/dashboards/1/copy
82
+ def copy
83
+ return render_not_found('template') unless template
84
+
85
+ # Owner is the current user by default, can be overriden to something else (eg: current organization)
86
+ @dashboard = template.copy(current_user, dashboard_params[:name], dashboard_params[:organization_ids])
87
+ return render_bad_request('copy template', 'Unable to copy template') unless dashboard.present?
88
+
89
+ render 'show'
90
+ end
91
+
77
92
  private
78
93
 
94
+ def dashboards
95
+ @dashboards ||= current_user.dashboards
96
+ end
97
+
79
98
  def dashboard
80
99
  @dashboard ||= current_user.dashboards.find(params[:id].to_i)
81
100
  end
82
101
 
83
- def dashboards
84
- @dashboards ||= current_user.dashboards
102
+ def templates
103
+ @templates ||= MnoEnterprise::Impac::Dashboard.templates
104
+ end
105
+
106
+ def template
107
+ @template ||= templates.find(params[:id].to_i)
85
108
  end
86
109
 
87
110
  def whitelisted_params
@@ -50,11 +50,14 @@ module MnoEnterprise::Concerns::Controllers::Jpi::V1::Impac::KpisController
50
50
  # -> POST /api/mnoe/v1/dashboards/:id/kpis
51
51
  # -> POST /api/mnoe/v1/users/:id/alerts
52
52
  def create
53
- if widget.present?
53
+ if params[:kpi][:widget_id].present?
54
+ return render_not_found('widget') if widget.blank?
54
55
  authorize! :manage_widget, widget
55
56
  else
57
+ return render_not_found('dashboard') if dashboard.blank?
56
58
  authorize! :manage_dashboard, dashboard
57
- end
59
+ end
60
+
58
61
  # TODO: nest alert in as a param, with the current user as a recipient.
59
62
  @kpi = kpi_parent.kpis.create(kpi_create_params)
60
63
  unless kpi.errors?
@@ -76,6 +79,8 @@ module MnoEnterprise::Concerns::Controllers::Jpi::V1::Impac::KpisController
76
79
  # PUT /mnoe/jpi/v1/impac/kpis/:id
77
80
  # -> PUT /api/mnoe/v1/kpis/:id
78
81
  def update
82
+ render_not_found('kpi') unless kpi.present?
83
+
79
84
  authorize! :manage_kpi, kpi
80
85
 
81
86
  params = kpi_update_params
@@ -107,6 +112,8 @@ module MnoEnterprise::Concerns::Controllers::Jpi::V1::Impac::KpisController
107
112
  # DELETE /mnoe/jpi/v1/impac/kpis/:id
108
113
  # -> DELETE /api/mnoe/v1/kpis/:id
109
114
  def destroy
115
+ render_not_found('kpi') unless kpi.present?
116
+
110
117
  authorize! :manage_kpi, kpi
111
118
 
112
119
  if kpi.destroy
@@ -122,21 +129,16 @@ module MnoEnterprise::Concerns::Controllers::Jpi::V1::Impac::KpisController
122
129
  private
123
130
 
124
131
  def dashboard
125
- @dashboard ||= MnoEnterprise::Impac::Dashboard.find(params.require(:dashboard_id))
126
- return render_not_found('dashboard') unless @dashboard
127
- @dashboard
132
+ @dashboard ||= MnoEnterprise::Impac::Dashboard.find(params.require(:dashboard_id).to_i)
128
133
  end
129
134
 
130
135
  def widget
131
- return nil if (id = params.require(:kpi)[:widget_id]).blank?
132
- @widget ||= MnoEnterprise::Impac::Widget.find(id)
133
- return render_not_found('widget') unless @widget
134
- @widget
136
+ widget_id = params.require(:kpi)[:widget_id]
137
+ @widget ||= (widget_id.present? && MnoEnterprise::Impac::Widget.find(widget_id.to_i))
135
138
  end
136
139
 
137
140
  def kpi
138
- @kpi ||= MnoEnterprise::Impac::Kpi.find(params[:id])
139
- return @kpi || render_not_found('kpi')
141
+ @kpi ||= MnoEnterprise::Impac::Kpi.find(params.require(:id).to_i)
140
142
  end
141
143
 
142
144
  def kpi_parent
@@ -16,7 +16,7 @@ module MnoEnterprise::Concerns::Controllers::Jpi::V1::MarketplaceController
16
16
  # GET /mnoe/jpi/v1/marketplace
17
17
  def index
18
18
  expires_in 0, public: true, must_revalidate: true
19
- @last_modified = app_relation.order_by('updated_at.desc').limit(1).first.updated_at
19
+ @last_modified = app_relation.order_by('updated_at.desc').limit(1).first.try(:updated_at)
20
20
 
21
21
  if stale?(last_modified: @last_modified)
22
22
  @apps = Rails.cache.fetch("marketplace/index-apps-#{@last_modified}") do
@@ -65,7 +65,9 @@ module MnoEnterprise::Concerns::Controllers::PagesController
65
65
  ts = MnoEnterprise::App.order_by("updated_at.desc").first.try(:updated_at)
66
66
  @apps = if ts
67
67
  Rails.cache.fetch(['pages/terms/app-list', ts]) do
68
- MnoEnterprise::App.order_by("name.ac").reject{|i| i.terms_url.blank?}
68
+ # Temp solution as translated fields can not be filtered or sorted
69
+ # MnoEnterprise::App.order_by("name.ac").reject{|i| i.terms_url.blank?}
70
+ MnoEnterprise::App.all.reject{ |i| i.terms_url.blank? }.sort_by{ |a| a.name.downcase }
69
71
  end
70
72
  else
71
73
  []
@@ -21,17 +21,26 @@ module MnoEnterprise
21
21
  end
22
22
 
23
23
  describe "#create" do
24
+ subject { get :create, user_id: user2.id }
24
25
  it do
25
26
  expect(controller.current_user.id).to eq(user.id)
26
- get :create, user_id: user2.id
27
+ subject
27
28
  expect(controller.current_user.id).to eq(user2.id)
28
29
  end
29
30
 
30
31
  context 'with an organisation id in parameters' do
31
- before { get :create, user_id: user.id, dhbRefId: 10 }
32
+ subject { get :create, user_id: user.id, dhbRefId: 10 }
32
33
 
33
34
  it { is_expected.to redirect_to('/dashboard/#!?dhbRefId=10') }
34
35
  end
36
+
37
+ context 'when the user is a staff member' do
38
+ let(:user2) { build(:user, admin_role: 'staff') }
39
+ it do
40
+ subject
41
+ expect(controller).to set_flash[:notice].to('User is a staff member')
42
+ end
43
+ end
35
44
  end
36
45
 
37
46
  describe "#destroy" do
@@ -0,0 +1,225 @@
1
+ require 'rails_helper'
2
+
3
+ module MnoEnterprise
4
+ describe Jpi::V1::Admin::Impac::DashboardTemplatesController, type: :controller do
5
+ # include MnoEnterprise::TestingSupport::JpiV1TestHelper
6
+ include MnoEnterprise::TestingSupport::SharedExamples::JpiV1Admin
7
+ render_views
8
+ routes { MnoEnterprise::Engine.routes }
9
+ before { request.env["HTTP_ACCEPT"] = 'application/json' }
10
+
11
+ RSpec.shared_context "#{described_class}: dashboard dependencies stubs" do
12
+ before do
13
+ api_stub_for(
14
+ get: "/users/#{user.id}/organizations",
15
+ response: from_api([org])
16
+ )
17
+ api_stub_for(
18
+ get: "/dashboards/#{template.id}/widgets",
19
+ response: from_api([widget])
20
+ )
21
+ api_stub_for(
22
+ get: "/dashboards/#{template.id}/kpis",
23
+ response: from_api([d_kpi])
24
+ )
25
+ api_stub_for(
26
+ get: "/widgets/#{widget.id}/kpis",
27
+ response: from_api([w_kpi])
28
+ )
29
+ end
30
+ end
31
+
32
+ let(:user) { build(:user, :admin, :with_organizations) }
33
+ let(:org) { build(:organization, users: [user]) }
34
+ let(:metadata) { { hist_parameters: { from: '2015-01-01', to: '2015-03-31', period: 'MONTHLY' } } }
35
+ let(:template) { build(:impac_dashboard, dashboard_type: 'template', organization_ids: [org.uid], currency: 'EUR', settings: metadata, owner_type: nil, owner_id: nil, published: true) }
36
+ let(:widget) { build(:impac_widget, dashboard: template) }
37
+ let(:d_kpi) { build(:impac_kpi, dashboard: template) }
38
+ let(:w_kpi) { build(:impac_kpi, widget: widget) }
39
+
40
+ def hash_for_kpi(kpi)
41
+ {
42
+ "id" => kpi.id,
43
+ "element_watched" => kpi.element_watched,
44
+ "endpoint" => kpi.endpoint
45
+ }
46
+ end
47
+ let(:hash_for_widget) do
48
+ {
49
+ "id" => widget.id,
50
+ "name" => widget.name,
51
+ "endpoint" => widget.widget_category,
52
+ "width" => widget.width,
53
+ "kpis" => [hash_for_kpi(w_kpi)]
54
+ }
55
+ end
56
+ let(:hash_for_template) do
57
+ {
58
+ "id" => template.id,
59
+ "name" => template.name,
60
+ "full_name" => template.full_name,
61
+ "currency" => 'EUR',
62
+ "metadata" => metadata.deep_stringify_keys,
63
+ "data_sources" => [{ "id" => org.id, "uid" => org.uid, "label" => org.name}],
64
+ "kpis" => [hash_for_kpi(d_kpi)],
65
+ "widgets" => [hash_for_widget],
66
+ "published" => true
67
+ }
68
+ end
69
+
70
+ before do
71
+ api_stub_for(get: "/users/#{user.id}", response: from_api(user))
72
+ sign_in user
73
+ end
74
+
75
+ describe '#index' do
76
+ subject { get :index }
77
+
78
+ before do
79
+ api_stub_for(
80
+ get: '/dashboards',
81
+ params: { filter: { 'dashboard_type' => 'template' } },
82
+ response: from_api([template])
83
+ )
84
+ end
85
+ include_context "#{described_class}: dashboard dependencies stubs"
86
+
87
+ it_behaves_like "a jpi v1 admin action"
88
+
89
+ it 'returns a list of dashboard templates' do
90
+ subject
91
+ expect(JSON.parse(response.body)).to eq([hash_for_template])
92
+ end
93
+ end
94
+
95
+ describe '#show' do
96
+ subject { get :show, id: template.id }
97
+
98
+ before do
99
+ api_stub_for(
100
+ get: "/dashboards/#{template.id}",
101
+ params: { filter: { 'dashboard_type' => 'template' } },
102
+ response: from_api(template)
103
+ )
104
+ end
105
+ include_context "#{described_class}: dashboard dependencies stubs"
106
+
107
+ it_behaves_like "a jpi v1 admin action"
108
+
109
+ it 'returns a dashboard template' do
110
+ subject
111
+ expect(JSON.parse(response.body)).to eq(hash_for_template)
112
+ end
113
+
114
+ # api_stub should be modified to allow this case to be stubbed
115
+ context 'when the template cannot be found' do
116
+ xit 'spec to be described'
117
+ end
118
+ end
119
+
120
+ describe '#create' do
121
+ let(:template_params) do
122
+ {
123
+ name: template.name,
124
+ currency: template.currency,
125
+ widgets_order: [3, 2, 1],
126
+ organization_ids: [4, 5],
127
+ metadata: metadata,
128
+ forbidden: 'param'
129
+ }
130
+ end
131
+
132
+ subject { post :create, dashboard: template_params }
133
+
134
+ before do
135
+ api_stub_for(
136
+ post: "/dashboards",
137
+ response: from_api(template)
138
+ )
139
+ end
140
+ include_context "#{described_class}: dashboard dependencies stubs"
141
+
142
+ it_behaves_like "a jpi v1 admin action"
143
+
144
+ it 'returns a dashboard template' do
145
+ subject
146
+ expect(JSON.parse(response.body)).to eq(hash_for_template)
147
+ end
148
+
149
+ # api_stub should be modified to allow this case to be stubbed
150
+ context 'when the dashboard creation is unsuccessful' do
151
+ xit 'spec to be described'
152
+ end
153
+ end
154
+
155
+ describe '#update' do
156
+ let(:template_params) do
157
+ {
158
+ name: template.name,
159
+ currency: template.currency,
160
+ widgets_order: [3, 2, 1],
161
+ organization_ids: [4, 5],
162
+ metadata: metadata,
163
+ forbidden: 'param',
164
+ published: true
165
+ }
166
+ end
167
+
168
+ subject { put :update, id: template.id, dashboard: template_params }
169
+
170
+ before do
171
+ api_stub_for(
172
+ get: "/dashboards/#{template.id}",
173
+ params: { filter: { 'dashboard_type' => 'template' } },
174
+ response: from_api(template)
175
+ )
176
+ api_stub_for(
177
+ put: "/dashboards/#{template.id}",
178
+ response: from_api(template)
179
+ )
180
+ end
181
+ include_context "#{described_class}: dashboard dependencies stubs"
182
+
183
+ it_behaves_like "a jpi v1 admin action"
184
+
185
+ it 'returns a dashboard template' do
186
+ subject
187
+ expect(JSON.parse(response.body)).to eq(hash_for_template)
188
+ end
189
+
190
+ # api_stub should be modified to allow these cases to be stubbed
191
+ context 'when the template cannot be found' do
192
+ xit 'spec to be described'
193
+ end
194
+ context 'when the dashboard update is unsuccessful' do
195
+ xit 'spec to be described'
196
+ end
197
+ end
198
+
199
+ describe '#destroy' do
200
+ subject { delete :destroy, id: template.id }
201
+
202
+ before do
203
+ api_stub_for(
204
+ get: "/dashboards/#{template.id}",
205
+ params: { filter: { 'dashboard_type' => 'template' } },
206
+ response: from_api(template)
207
+ )
208
+ api_stub_for(
209
+ delete: "/dashboards/#{template.id}",
210
+ response: from_api(nil)
211
+ )
212
+ end
213
+
214
+ it_behaves_like "a jpi v1 admin action"
215
+
216
+ # api_stub should be modified to allow these cases to be stubbed
217
+ context 'when the template cannot be found' do
218
+ xit 'spec to be described'
219
+ end
220
+ context 'when the dashboard destruction is unsuccessful' do
221
+ xit 'spec to be described'
222
+ end
223
+ end
224
+ end
225
+ end
@@ -0,0 +1,134 @@
1
+ require 'rails_helper'
2
+
3
+ module MnoEnterprise
4
+ describe Jpi::V1::Admin::Impac::KpisController, type: :controller do
5
+ # include MnoEnterprise::TestingSupport::JpiV1TestHelper
6
+ include MnoEnterprise::TestingSupport::SharedExamples::JpiV1Admin
7
+ render_views
8
+ routes { MnoEnterprise::Engine.routes }
9
+ before { request.env["HTTP_ACCEPT"] = 'application/json' }
10
+
11
+ let(:user) { build(:user, :admin, :with_organizations) }
12
+ let(:org) { build(:organization, users: [user]) }
13
+ let(:template) { build(:impac_dashboard, dashboard_type: 'template') }
14
+ let(:metadata) { { hist_parameters: { from: '2015-01-01', to: '2015-03-31', period: 'MONTHLY' } } }
15
+ let(:kpi) { build(:impac_kpi, dashboard: template, settings: metadata) }
16
+
17
+ let(:hash_for_kpi) do
18
+ {
19
+ "id" => kpi.id,
20
+ 'settings' => metadata.deep_stringify_keys,
21
+ "element_watched" => kpi.element_watched,
22
+ "endpoint" => kpi.endpoint
23
+ }
24
+ end
25
+
26
+ before do
27
+ api_stub_for(get: "/users/#{user.id}", response: from_api(user))
28
+ sign_in user
29
+ end
30
+
31
+ describe '#create' do
32
+ let(:kpi_params) do
33
+ {
34
+ dashboard_id: template.id,
35
+ endpoint: kpi.endpoint,
36
+ source: kpi.source,
37
+ element_watched: kpi.element_watched,
38
+ extra_watchables: kpi.extra_watchables,
39
+ metadata: metadata,
40
+ forbidden: 'param'
41
+ }
42
+ end
43
+
44
+ subject { post :create, dashboard_template_id: template.id, kpi: kpi_params }
45
+
46
+ before do
47
+ api_stub_for(
48
+ get: "/dashboards/#{template.id}",
49
+ params: { filter: { 'dashboard_type' => 'template' } },
50
+ response: from_api(template)
51
+ )
52
+ api_stub_for(
53
+ post: "dashboards/#{template.id}/kpis",
54
+ response: from_api(kpi)
55
+ )
56
+ # Why is Her doing a GET /kpis after doing a POST /kpis?
57
+ api_stub_for(
58
+ get: "dashboards/#{template.id}/kpis",
59
+ response: from_api([kpi])
60
+ )
61
+ end
62
+
63
+ it_behaves_like "a jpi v1 admin action"
64
+
65
+ it 'returns a kpi' do
66
+ subject
67
+ expect(JSON.parse(response.body)).to eq(hash_for_kpi)
68
+ end
69
+
70
+ # api_stub should be modified to allow this case to be stubbed
71
+ context 'when the template cannot be found' do
72
+ xit 'spec to be described'
73
+ end
74
+ end
75
+
76
+ describe '#update' do
77
+ let(:kpi_params) do
78
+ {
79
+ element_watched: kpi.element_watched,
80
+ extra_watchables: kpi.extra_watchables,
81
+ metadata: metadata,
82
+ forbidden: 'param'
83
+ }
84
+ end
85
+
86
+ subject { put :update, id: kpi.id, kpi: kpi_params }
87
+
88
+ before do
89
+ api_stub_for(
90
+ get: "kpis/#{kpi.id}",
91
+ response: from_api(kpi)
92
+ )
93
+ api_stub_for(
94
+ put: "/kpis/#{kpi.id}",
95
+ response: from_api(kpi)
96
+ )
97
+ end
98
+
99
+ it_behaves_like "a jpi v1 admin action"
100
+
101
+ it 'returns a kpi' do
102
+ subject
103
+ expect(JSON.parse(response.body)).to eq(hash_for_kpi)
104
+ end
105
+
106
+ # api_stub should be modified to allow this case to be stubbed
107
+ context 'when the kpi update is unsuccessful' do
108
+ xit 'spec to be described'
109
+ end
110
+ end
111
+
112
+ describe '#destroy' do
113
+ subject { delete :destroy, id: kpi.id }
114
+
115
+ before do
116
+ api_stub_for(
117
+ get: "kpis/#{kpi.id}",
118
+ response: from_api(kpi)
119
+ )
120
+ api_stub_for(
121
+ delete: "/kpis/#{kpi.id}",
122
+ response: from_api(nil)
123
+ )
124
+ end
125
+
126
+ it_behaves_like "a jpi v1 admin action"
127
+
128
+ # api_stub should be modified to allow this case to be stubbed
129
+ context 'when the kpi destruction is unsuccessful' do
130
+ xit 'spec to be described'
131
+ end
132
+ end
133
+ end
134
+ end