mno-enterprise-api 3.3.1 → 3.3.2

Sign up to get free protection for your applications and to get access to all the features.
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