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.
Files changed (139) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/javascripts/mno_enterprise/config.js.coffee.erb +7 -1
  3. data/app/controllers/mno_enterprise/auth/omniauth_callbacks_controller.rb +3 -27
  4. data/app/controllers/mno_enterprise/auth/sessions_controller.rb +1 -3
  5. data/app/controllers/mno_enterprise/jpi/v1/admin/app_answers_controller.rb +26 -0
  6. data/app/controllers/mno_enterprise/jpi/v1/admin/app_comments_controller.rb +28 -0
  7. data/app/controllers/mno_enterprise/jpi/v1/admin/app_instances_controller.rb +16 -0
  8. data/app/controllers/mno_enterprise/jpi/v1/admin/app_reviews_controller.rb +30 -0
  9. data/app/controllers/mno_enterprise/jpi/v1/admin/invites_controller.rb +1 -1
  10. data/app/controllers/mno_enterprise/jpi/v1/admin/organizations_controller.rb +55 -37
  11. data/app/controllers/mno_enterprise/jpi/v1/app_answers_controller.rb +22 -0
  12. data/app/controllers/mno_enterprise/jpi/v1/app_comments_controller.rb +22 -0
  13. data/app/controllers/mno_enterprise/jpi/v1/app_feedbacks_controller.rb +14 -0
  14. data/app/controllers/mno_enterprise/jpi/v1/app_instances_controller.rb +1 -20
  15. data/app/controllers/mno_enterprise/jpi/v1/app_questions_controller.rb +25 -0
  16. data/app/controllers/mno_enterprise/jpi/v1/app_reviews_controller.rb +94 -0
  17. data/app/controllers/mno_enterprise/jpi/v1/base_resource_controller.rb +12 -0
  18. data/app/controllers/mno_enterprise/jpi/v1/impac/alerts_controller.rb +5 -0
  19. data/app/controllers/mno_enterprise/jpi/v1/impac/kpis_controller.rb +1 -76
  20. data/app/controllers/mno_enterprise/jpi/v1/marketplace_controller.rb +1 -18
  21. data/app/controllers/mno_enterprise/jpi/v1/teams_controller.rb +1 -83
  22. data/app/jobs/mno_enterprise/event_logger_job.rb +10 -0
  23. data/app/views/mno_enterprise/auth/confirmations/new.html.haml +6 -6
  24. data/app/views/mno_enterprise/auth/passwords/new.html.haml +8 -8
  25. data/app/views/mno_enterprise/auth/registrations/new.html.haml +1 -0
  26. data/app/views/mno_enterprise/auth/sessions/new.html.haml +1 -0
  27. data/app/views/mno_enterprise/auth/shared/_links.html.haml +0 -5
  28. data/app/views/mno_enterprise/auth/shared/_omniauth.html.haml +10 -0
  29. data/app/views/mno_enterprise/jpi/v1/admin/app_answers/show.json.jbuilder +15 -0
  30. data/app/views/mno_enterprise/jpi/v1/admin/app_comments/show.json.jbuilder +15 -0
  31. data/app/views/mno_enterprise/jpi/v1/admin/app_reviews/_app_review.json.jbuilder +13 -0
  32. data/app/views/mno_enterprise/jpi/v1/admin/app_reviews/index.json.jbuilder +1 -0
  33. data/app/views/mno_enterprise/jpi/v1/admin/app_reviews/show.json.jbuilder +3 -0
  34. data/app/views/mno_enterprise/jpi/v1/admin/organizations/show.json.jbuilder +1 -0
  35. data/app/views/mno_enterprise/jpi/v1/admin/users/_user.json.jbuilder +1 -1
  36. data/app/views/mno_enterprise/jpi/v1/app_answers/_resource.json.jbuilder +4 -0
  37. data/app/views/mno_enterprise/jpi/v1/app_answers/index.json.jbuilder +5 -0
  38. data/app/views/mno_enterprise/jpi/v1/app_answers/show.json.jbuilder +3 -0
  39. data/app/views/mno_enterprise/jpi/v1/app_comments/_resource.json.jbuilder +3 -0
  40. data/app/views/mno_enterprise/jpi/v1/app_comments/index.json.jbuilder +5 -0
  41. data/app/views/mno_enterprise/jpi/v1/app_comments/show.json.jbuilder +3 -0
  42. data/app/views/mno_enterprise/jpi/v1/app_feedbacks/_comment.json.jbuilder +10 -0
  43. data/app/views/mno_enterprise/jpi/v1/app_feedbacks/_resource.json.jbuilder +7 -0
  44. data/app/views/mno_enterprise/jpi/v1/app_feedbacks/index.json.jbuilder +5 -0
  45. data/app/views/mno_enterprise/jpi/v1/app_feedbacks/show.json.jbuilder +4 -0
  46. data/app/views/mno_enterprise/jpi/v1/app_instances/_resource.json.jbuilder +9 -0
  47. data/app/views/mno_enterprise/jpi/v1/app_questions/_answer.json.jbuilder +3 -0
  48. data/app/views/mno_enterprise/jpi/v1/app_questions/_resource.json.jbuilder +8 -0
  49. data/app/views/mno_enterprise/jpi/v1/app_questions/index.json.jbuilder +5 -0
  50. data/app/views/mno_enterprise/jpi/v1/app_questions/show.json.jbuilder +3 -0
  51. data/app/views/mno_enterprise/jpi/v1/app_reviews/_resource.json.jbuilder +13 -0
  52. data/app/views/mno_enterprise/jpi/v1/app_reviews/index.json.jbuilder +5 -0
  53. data/app/views/mno_enterprise/jpi/v1/app_reviews/show.json.jbuilder +4 -0
  54. data/app/views/mno_enterprise/jpi/v1/base_resource/_app_review.json.jbuilder +17 -0
  55. data/app/views/mno_enterprise/jpi/v1/current_users/show.json.jbuilder +9 -1
  56. data/app/views/mno_enterprise/jpi/v1/impac/alerts/_alert.json.jbuilder +7 -0
  57. data/app/views/mno_enterprise/jpi/v1/impac/alerts/index.json.jbuilder +1 -0
  58. data/app/views/mno_enterprise/jpi/v1/impac/alerts/show.json.jbuilder +1 -0
  59. data/app/views/mno_enterprise/jpi/v1/impac/dashboards/_dashboard.json.jbuilder +8 -3
  60. data/app/views/mno_enterprise/jpi/v1/impac/kpis/_kpi.json.jbuilder +4 -1
  61. data/app/views/mno_enterprise/jpi/v1/impac/widgets/_widget.json.jbuilder +1 -1
  62. data/app/views/mno_enterprise/jpi/v1/impac/widgets/index.json.jbuilder +3 -0
  63. data/app/views/mno_enterprise/jpi/v1/marketplace/_app.json.jbuilder +4 -0
  64. data/app/views/mno_enterprise/jpi/v1/marketplace/index.json.jbuilder +1 -2
  65. data/app/views/mno_enterprise/jpi/v1/marketplace/show.json.jbuilder +1 -1
  66. data/app/views/mno_enterprise/jpi/v1/organizations/_current_user.json.jbuilder +1 -1
  67. data/app/views/mno_enterprise/jpi/v1/organizations/_invoices.json.jbuilder +3 -2
  68. data/app/views/mno_enterprise/jpi/v1/organizations/_member.json.jbuilder +2 -2
  69. data/app/views/mno_enterprise/jpi/v1/organizations/_organization.json.jbuilder +2 -2
  70. data/app/views/mno_enterprise/jpi/v1/teams/_team.json.jbuilder +11 -5
  71. data/app/views/mno_enterprise/pages/terms.html.haml +219 -0
  72. data/app/views/mno_enterprise/provision/_select_organization.html.haml +6 -2
  73. data/config/initializers/devise.rb +31 -9
  74. data/config/initializers/devise_log.rb +4 -4
  75. data/config/routes.rb +41 -6
  76. data/lib/mno_enterprise/api.rb +1 -0
  77. data/lib/mno_enterprise/audit_events_listener.rb +28 -0
  78. data/lib/mno_enterprise/concerns/controllers/jpi/v1/app_instances_controller.rb +45 -0
  79. data/lib/mno_enterprise/concerns/controllers/jpi/v1/current_users_controller.rb +14 -4
  80. data/lib/mno_enterprise/concerns/controllers/jpi/v1/impac/alerts_controller.rb +76 -0
  81. data/lib/mno_enterprise/concerns/controllers/jpi/v1/impac/dashboards_controller.rb +49 -23
  82. data/lib/mno_enterprise/concerns/controllers/jpi/v1/impac/kpis_controller.rb +167 -0
  83. data/lib/mno_enterprise/concerns/controllers/jpi/v1/impac/widgets_controller.rb +33 -17
  84. data/lib/mno_enterprise/concerns/controllers/jpi/v1/marketplace_controller.rb +32 -0
  85. data/lib/mno_enterprise/concerns/controllers/jpi/v1/organizations_controller.rb +68 -28
  86. data/lib/mno_enterprise/concerns/controllers/jpi/v1/teams_controller.rb +92 -0
  87. data/lib/mno_enterprise/concerns/controllers/pages_controller.rb +17 -3
  88. data/lib/mno_enterprise/concerns/controllers/provision_controller.rb +17 -2
  89. data/lib/mno_enterprise/concerns/mailers/system_notification_mailer.rb +27 -3
  90. data/lib/mno_enterprise/event_logger.rb +34 -16
  91. data/lib/mno_enterprise/intercom_events_listener.rb +96 -0
  92. data/spec/controllers/mno_enterprise/auth/confirmation_controller_spec.rb +28 -0
  93. data/spec/controllers/mno_enterprise/auth/omniauth_callback_controller_spec.rb +34 -0
  94. data/spec/controllers/mno_enterprise/jpi/v1/admin/app_answers_controller_spec.rb +45 -0
  95. data/spec/controllers/mno_enterprise/jpi/v1/admin/app_comments_controller_spec.rb +45 -0
  96. data/spec/controllers/mno_enterprise/jpi/v1/admin/app_instances_controller_spec.rb +31 -0
  97. data/spec/controllers/mno_enterprise/jpi/v1/admin/app_reviews_controller_spec.rb +103 -0
  98. data/spec/controllers/mno_enterprise/jpi/v1/admin/audit_events_controller_spec.rb +4 -15
  99. data/spec/controllers/mno_enterprise/jpi/v1/admin/cloud_apps_controller_spec.rb +12 -3
  100. data/spec/controllers/mno_enterprise/jpi/v1/admin/invites_controller_spec.rb +4 -0
  101. data/spec/controllers/mno_enterprise/jpi/v1/admin/invoices_controller_spec.rb +15 -0
  102. data/spec/controllers/mno_enterprise/jpi/v1/admin/organizations_controller_spec.rb +17 -1
  103. data/spec/controllers/mno_enterprise/jpi/v1/admin/tenant_invoices_controller_spec.rb +5 -0
  104. data/spec/controllers/mno_enterprise/jpi/v1/admin/users_controller_spec.rb +30 -16
  105. data/spec/controllers/mno_enterprise/jpi/v1/app_answers_controller_spec.rb +74 -0
  106. data/spec/controllers/mno_enterprise/jpi/v1/app_comments_controller_spec.rb +74 -0
  107. data/spec/controllers/mno_enterprise/jpi/v1/app_feedbacks_controller_spec.rb +84 -0
  108. data/spec/controllers/mno_enterprise/jpi/v1/app_instances_controller_spec.rb +36 -22
  109. data/spec/controllers/mno_enterprise/jpi/v1/app_questions_controller_spec.rb +80 -0
  110. data/spec/controllers/mno_enterprise/jpi/v1/app_reviews_controller_spec.rb +107 -0
  111. data/spec/controllers/mno_enterprise/jpi/v1/current_users_controller_spec.rb +16 -1
  112. data/spec/controllers/mno_enterprise/jpi/v1/impac/alerts_controller_spec.rb +82 -0
  113. data/spec/controllers/mno_enterprise/jpi/v1/impac/kpis_controller_spec.rb +147 -10
  114. data/spec/controllers/mno_enterprise/jpi/v1/impac/widgets_controller_spec.rb +39 -0
  115. data/spec/controllers/mno_enterprise/jpi/v1/marketplace_controller_spec.rb +19 -26
  116. data/spec/controllers/mno_enterprise/jpi/v1/organizations_controller_spec.rb +248 -303
  117. data/spec/controllers/mno_enterprise/jpi/v1/team_controller_spec.rb +4 -1
  118. data/spec/controllers/mno_enterprise/pages_controller_spec.rb +21 -0
  119. data/spec/controllers/mno_enterprise/provision_controller_spec.rb +65 -22
  120. data/spec/controllers/mno_enterprise/webhook/o_auth_controller_spec.rb +1 -1
  121. data/spec/jobs/mno_enterprise/event_logger_job_spec.rb +11 -0
  122. data/spec/lib/mno_enterprise/audit_events_listener_spec.rb +28 -0
  123. data/spec/lib/mno_enterprise/intercom_events_listener_spec.rb +110 -0
  124. data/spec/mailer/mno_enterprise/system_notification_mailer_spec.rb +81 -46
  125. data/spec/routing/mno_enterprise/jpi/v1/admin/app_instances_controller_routing_spec.rb +11 -0
  126. data/spec/routing/mno_enterprise/jpi/v1/admin/app_reviews_controller_routing_spec.rb +19 -0
  127. data/spec/routing/mno_enterprise/jpi/v1/app_instances_controller_routing_spec.rb +9 -2
  128. data/spec/routing/mno_enterprise/jpi/v1/app_reviews_controller_routing_spec.rb +15 -0
  129. data/spec/routing/mno_enterprise/jpi/v1/current_users_controller_routing_spec.rb +5 -0
  130. data/spec/routing/mno_enterprise/jpi/v1/impac/alerts_controller_routing_spec.rb +24 -0
  131. data/spec/routing/mno_enterprise/jpi/v1/impac/dashboards_controller_routing_spec.rb +28 -0
  132. data/spec/routing/mno_enterprise/jpi/v1/impac/kpis_controller_routing_spec.rb +17 -11
  133. data/spec/routing/mno_enterprise/jpi/v1/impac/widgets_controller_routing_spec.rb +24 -0
  134. data/spec/routing/mno_enterprise/jpi/v1/marketplace_controller_routing_spec.rb +2 -2
  135. data/spec/routing/mno_enterprise/pages_controller_routing_spec.rb +4 -0
  136. metadata +178 -9
  137. data/app/controllers/mno_enterprise/jpi/v1/industry_bundle_controller.rb +0 -25
  138. data/app/controllers/mno_enterprise/jpi/v1/shopping_cart_controller.rb +0 -93
  139. data/spec/lib/mno_enterprise/event_logger_spec.rb +0 -28
@@ -0,0 +1,167 @@
1
+ module MnoEnterprise::Concerns::Controllers::Jpi::V1::Impac::KpisController
2
+ extend ActiveSupport::Concern
3
+
4
+ #==================================================================
5
+ # Included methods
6
+ #==================================================================
7
+ # 'included do' causes the included code to be evaluated in the
8
+ # context where it is included rather than being executed in the module's context
9
+ included do
10
+ respond_to :json
11
+
12
+ before_filter :find_valid_kpi, only: [:update, :delete]
13
+ end
14
+
15
+ #==================================================================
16
+ # Instance methods
17
+ #==================================================================
18
+ # GET /mnoe/jpi/v1/impac/kpis
19
+ # This action is used as a sort of 'proxy' for retrieving KPI templates which are
20
+ # usually retrieved from Impac! API, and customising the attributes.
21
+ def index
22
+ # Retrieve kpis templates from impac api.
23
+ # TODO: improve request params to work for strong parameters
24
+ attrs = params.slice('metadata', 'opts')
25
+ auth = { username: MnoEnterprise.tenant_id, password: MnoEnterprise.tenant_key }
26
+
27
+ response = begin
28
+ MnoEnterprise::ImpacClient.send_get('/api/v2/kpis', attrs, basic_auth: auth)
29
+ rescue => e
30
+ return render json: { message: "Unable to retrieve kpis from Impac API | Error #{e}" }
31
+ end
32
+
33
+ # customise available kpis
34
+ kpis = (response['kpis'] || []).map do |kpi|
35
+ kpi = kpi.with_indifferent_access
36
+ kpi[:watchables].map do |watchable|
37
+ kpi.merge(
38
+ name: "#{kpi[:name]} #{watchable.capitalize unless kpi[:name].downcase.index(watchable)}".strip,
39
+ watchables: [watchable],
40
+ target_placeholders: {watchable => kpi[:target_placeholders][watchable]},
41
+ )
42
+ end
43
+ end
44
+ .flatten
45
+
46
+ render json: { kpis: kpis }
47
+ end
48
+
49
+ # POST /mnoe/jpi/v1/impac/dashboards/:dashboard_id/kpis
50
+ # -> POST /api/mnoe/v1/dashboards/:id/kpis
51
+ # -> POST /api/mnoe/v1/users/:id/alerts
52
+ def create
53
+ # TODO: ability for managing widget.
54
+ authorize! :manage_dashboard, dashboard
55
+ # TODO: attach widget onto KPI capability.
56
+ # authorize! :manage_widget, widget if widget
57
+
58
+ # TODO: nest alert in as a param, with the current user as a recipient.
59
+ if @kpi = kpi_parent.kpis.create(kpi_create_params)
60
+ # Creates a default alert for kpis created with targets defined.
61
+ if kpi.targets.present?
62
+ current_user.alerts.create({service: 'inapp', impac_kpi_id: kpi.id})
63
+ # TODO: reload is adding the recipients to the kpi alerts (making another request).
64
+ kpi.reload
65
+ end
66
+ render 'show'
67
+ else
68
+ msg = kpi.errors.full_messages.join(', ') || 'unable to create KPI.'
69
+ render_bad_request("create kpi (id=#{kpi.id})", msg)
70
+ end
71
+ end
72
+
73
+ # PUT /mnoe/jpi/v1/impac/kpis/:id
74
+ # -> PUT /api/mnoe/v1/kpis/:id
75
+ def update
76
+ authorize! :manage_kpi, kpi
77
+
78
+ params = kpi_update_params
79
+
80
+ # TODO: refactor into models
81
+ # --
82
+ # Creates an in-app alert if target is set for the first time (in-app alerts should be activated by default)
83
+ if kpi.targets.blank? && params[:targets].present?
84
+ current_user.alerts.create({service: 'inapp', impac_kpi_id: kpi.id})
85
+
86
+ # If targets have changed, reset all the alerts 'sent' status to false.
87
+ elsif kpi.targets && params[:targets].present? && params[:targets] != kpi.targets
88
+ kpi.alerts.each { |alert| alert.update(sent: false) }
89
+
90
+ # Removes all the alerts if the targets are removed (kpi has no targets set,
91
+ # and params contains no targets to be set)
92
+ elsif params[:targets].blank? && kpi.targets.blank?
93
+ kpi.alerts.each(&:destroy)
94
+ end
95
+
96
+ if kpi.update(kpi_update_params)
97
+ render 'show'
98
+ else
99
+ msg = @kpi.errors.full_messages.join(', ') || 'unable to update KPI.'
100
+ render_bad_request("update kpi (id=#{kpi.id})", msg)
101
+ end
102
+ end
103
+
104
+ # DELETE /mnoe/jpi/v1/impac/kpis/:id
105
+ # -> DELETE /api/mnoe/v1/kpis/:id
106
+ def destroy
107
+ authorize! :manage_kpi, kpi
108
+
109
+ if kpi.destroy
110
+ head status: :ok
111
+ else
112
+ render_bad_request('destroy kpi', "impossible to destroy kpi (id=#{kpi.id})")
113
+ end
114
+ end
115
+
116
+ #=================================================
117
+ # Private methods
118
+ #=================================================
119
+ private
120
+
121
+ def dashboard
122
+ @dashboard ||= MnoEnterprise::Impac::Dashboard.find(params.require(:dashboard_id))
123
+ return render_not_found('dashboard') unless @dashboard
124
+ @dashboard
125
+ end
126
+
127
+ def widget
128
+ return nil if (id = params.require(:kpi)[:widget_id]).blank?
129
+ @widget ||= MnoEnterprise::Impac::Widget.find(id)
130
+ return render_not_found('widget') unless @widget
131
+ @widget
132
+ end
133
+
134
+ def kpi
135
+ @kpi ||= MnoEnterprise::Impac::Kpi.find(params[:id])
136
+ return @kpi || render_not_found('kpi')
137
+ end
138
+
139
+ def kpi_parent
140
+ # TODO: attach kpi onto widget capability
141
+ # widget || dashboard
142
+ dashboard
143
+ end
144
+
145
+ def kpi_create_params
146
+ whitelist = [:dashboard_id, :endpoint, :source, :element_watched, {extra_watchables: []}]
147
+ extract_params(whitelist)
148
+ end
149
+
150
+ def kpi_update_params
151
+ whitelist = [:name, :element_watched, {extra_watchables: []}]
152
+ extract_params(whitelist)
153
+ end
154
+
155
+ def extract_params(whitelist)
156
+ (p = params).require(:kpi).permit(*whitelist).tap do |whitelisted|
157
+ whitelisted[:settings] = p[:kpi][:metadata] || {}
158
+ # TODO: strong params for targets & extra_params attributes (keys will depend on the kpi).
159
+ whitelisted[:targets] = p[:kpi][:targets] unless p[:kpi][:targets].blank?
160
+ whitelisted[:extra_params] = p[:kpi][:extra_params] unless p[:kpi][:extra_params].blank?
161
+ end
162
+ .except(:metadata)
163
+ end
164
+
165
+ alias :find_valid_kpi :kpi
166
+
167
+ end
@@ -13,43 +13,52 @@ module MnoEnterprise::Concerns::Controllers::Jpi::V1::Impac::WidgetsController
13
13
  #==================================================================
14
14
  # Instance methods
15
15
  #==================================================================
16
+ # GET /mnoe/jpi/v1/impac/organizations/:organization_id/widgets
17
+ # -> GET /api/mnoe/v1/organizations/:id/widgets
18
+ def index
19
+ render_not_found('organization') unless parent_organization
20
+ @widgets = parent_organization.widgets
21
+ end
22
+
16
23
  # POST /mnoe/jpi/v1/impac/dashboards/:id/widgets
17
24
  # -> POST /api/mnoe/v1/dashboards/:id/widgets
18
25
  def create
19
26
  if widgets
20
- if @widget = widgets.create(format_attrs(['widget_category','metadata']))
21
- MnoEnterprise::EventLogger.info('widget_create', current_user.id, 'Widget Creation', nil, @widget)
27
+ if @widget = widgets.create(widget_create_params)
28
+ MnoEnterprise::EventLogger.info('widget_create', current_user.id, 'Widget Creation', @widget)
22
29
  @nocontent = true # no data fetch from Connec!
23
30
  render 'show'
24
31
  else
25
- render json: @widget.errors, status: :bad_request
32
+ render_bad_request('create widget', @widget.errors)
26
33
  end
27
34
  else
28
- render json: { errors: "Dashboard id #{params[:id]} doesn't exist" }, status: :not_found
35
+ render_not_found('widget')
29
36
  end
30
37
  end
31
38
 
32
39
  # PUT /mnoe/jpi/v1/impac/widgets/:id
40
+ # -> PUT /api/mnoe/v1/widgets/:id
33
41
  def update
34
- if widget.update(format_attrs(['name','metadata']))
42
+ if widget.update(widget_update_params)
35
43
  @nocontent = !params['metadata']
36
44
  render 'show'
37
45
  else
38
- render json: @widget.errors, status: :bad_request
46
+ render_bad_request('update widget', @widget.errors)
39
47
  end
40
48
  end
41
-
42
- # DELETE /mnoe/jpi/v1/impac/dashboards/1
49
+
50
+ # DELETE /mnoe/jpi/v1/impac/widgets/:id
51
+ # -> DELETE /api/mnoe/v1/widgets/:id
43
52
  def destroy
44
53
  if widget.destroy
45
- MnoEnterprise::EventLogger.info('widget_delete', current_user.id, 'Widget Deletion', nil, widget)
54
+ MnoEnterprise::EventLogger.info('widget_delete', current_user.id, 'Widget Deletion', widget)
46
55
  head status: :ok
47
56
  else
48
- render json: 'Unable to destroy widget', status: :bad_request
57
+ render_bad_request('destroy widget', 'Unable to destroy widget')
49
58
  end
50
59
  end
51
-
52
-
60
+
61
+
53
62
  #=================================================
54
63
  # Private methods
55
64
  #=================================================
@@ -63,10 +72,17 @@ module MnoEnterprise::Concerns::Controllers::Jpi::V1::Impac::WidgetsController
63
72
  @widgets ||= MnoEnterprise::Impac::Dashboard.find(params[:dashboard_id]).widgets
64
73
  end
65
74
 
66
- def format_attrs(whitelist)
67
- attrs = (params[:widget] || {}).select { |k,v| whitelist.include?(k.to_s) }
68
- attrs['settings'] = widget ? widget.settings || {} : {}
69
- attrs['settings'].merge!(attrs['metadata']) if attrs['metadata']
70
- attrs.except!('metadata')
75
+ def widget_create_params
76
+ params.require(:widget).permit(:widget_category).tap do |whitelisted|
77
+ whitelisted[:settings] = params[:widget][:metadata] || {}
78
+ end
79
+ .except(:metadata)
80
+ end
81
+
82
+ def widget_update_params
83
+ params.require(:widget).permit(:name).tap do |whitelisted|
84
+ whitelisted[:settings] = params[:widget][:metadata] || {}
85
+ end
86
+ .except(:metadata)
71
87
  end
72
88
  end
@@ -0,0 +1,32 @@
1
+ module MnoEnterprise::Concerns::Controllers::Jpi::V1::MarketplaceController
2
+ extend ActiveSupport::Concern
3
+
4
+ #==================================================================
5
+ # Included methods
6
+ #==================================================================
7
+ # 'included do' causes the included code to be evaluated in the
8
+ # context where it is included rather than being executed in the module's context
9
+ included do
10
+ respond_to :json
11
+ end
12
+
13
+ #==================================================================
14
+ # Instance methods
15
+ #==================================================================
16
+ # GET /mnoe/mnoe/jpi/v1/marketplace
17
+ def index
18
+ @apps = if MnoEnterprise.marketplace_listing
19
+ MnoEnterprise::App.where('nid.in' => MnoEnterprise.marketplace_listing).to_a
20
+ else
21
+ MnoEnterprise::App.all.to_a
22
+ end
23
+ @apps.sort_by! { |app| [app.rank ? 0 : 1 , app.rank] } # the nil ranks will appear at the end
24
+ @categories = MnoEnterprise::App.categories(@apps)
25
+ @categories.delete('Most Popular')
26
+ end
27
+
28
+ # GET /mnoe/jpi/v1/marketplace/1
29
+ def show
30
+ @app = MnoEnterprise::App.find(params[:id])
31
+ end
32
+ end
@@ -28,9 +28,10 @@ module MnoEnterprise::Concerns::Controllers::Jpi::V1::OrganizationsController
28
28
  # Update and Authorize
29
29
  organization.assign_attributes(organization_update_params)
30
30
  authorize! :update, organization
31
-
31
+ changes = organization.changes
32
32
  # Save
33
33
  if organization.save
34
+ MnoEnterprise::EventLogger.info('organization_update', current_user.id, 'Organization update', organization, changes)
34
35
  render 'show_reduced'
35
36
  else
36
37
  render json: organization.errors, status: :bad_request
@@ -41,6 +42,7 @@ module MnoEnterprise::Concerns::Controllers::Jpi::V1::OrganizationsController
41
42
  def destroy
42
43
  if organization
43
44
  authorize! :destroy, organization
45
+ MnoEnterprise::EventLogger.info('organization_destroy', current_user.id, 'Organization deleted', organization)
44
46
  organization.destroy
45
47
  end
46
48
 
@@ -57,7 +59,7 @@ module MnoEnterprise::Concerns::Controllers::Jpi::V1::OrganizationsController
57
59
 
58
60
  # Bust cache
59
61
  current_user.refresh_user_cache
60
-
62
+ MnoEnterprise::EventLogger.info('organization_create', current_user.id, 'Organization created', organization)
61
63
  render 'show'
62
64
  end
63
65
 
@@ -81,13 +83,11 @@ module MnoEnterprise::Concerns::Controllers::Jpi::V1::OrganizationsController
81
83
 
82
84
  # PUT /mnoe/jpi/v1/organizations/:id/update_billing
83
85
  def update_billing
84
- whitelist = ['title','first_name','last_name','number','month','year','country','verification_value','billing_address','billing_city','billing_postcode', 'billing_country']
85
- attributes = params[:credit_card].select { |k,v| whitelist.include?(k.to_s) }
86
86
  authorize! :manage_billing, organization
87
87
 
88
88
  # Upsert
89
- if @credit_card = organization.credit_card
90
- @credit_card.assign_attributes(attributes.merge(organization_id: @credit_card.organization_id))
89
+ if (@credit_card = organization.credit_card) && check_valid_payment_method
90
+ @credit_card.assign_attributes(organization_billing_params.merge(organization_id: @credit_card.organization_id))
91
91
  @credit_card.save
92
92
  end
93
93
 
@@ -98,14 +98,13 @@ module MnoEnterprise::Concerns::Controllers::Jpi::V1::OrganizationsController
98
98
  end
99
99
  end
100
100
 
101
- # TODO: specs
102
101
  # PUT /mnoe/jpi/v1/organizations/:id/invite_members
103
102
  def invite_members
104
103
  # Filter
105
104
  whitelist = ['email','role','team_id']
106
105
  attributes = []
107
106
  params[:invites].each do |invite|
108
- attributes << invite.select { |k,v| whitelist.include?(k.to_s) }
107
+ attributes << invite.slice(*whitelist)
109
108
  end
110
109
 
111
110
  # Authorize and create
@@ -127,46 +126,68 @@ module MnoEnterprise::Concerns::Controllers::Jpi::V1::OrganizationsController
127
126
  render 'members'
128
127
  end
129
128
 
130
- # TODO: specs
131
129
  # PUT /mnoe/jpi/v1/organizations/:id/update_member
132
130
  def update_member
133
131
  attributes = params[:member]
134
- @member = organization.users.where(email: attributes[:email]).first
135
- @member ||= organization.org_invites.active.where(user_email: attributes[:email]).first
136
132
 
137
- # Authorize and update
133
+ # Authorize and update => Admin or Super Admin
138
134
  authorize! :invite_member, organization
139
- if @member.is_a?(MnoEnterprise::User)
140
- organization.users.update(id: @member.id, role: attributes[:role])
141
- elsif @member.is_a?(MnoEnterprise::OrgInvite)
142
- @member.user_role = attributes[:role]
143
- @member.save
135
+
136
+ if organization.role == 'Admin'
137
+ # Admin cannot assign Super Admin role
138
+ raise CanCan::AccessDenied if attributes[:role] == 'Super Admin'
139
+
140
+ # Admin cannot edit Super Admin
141
+ raise CanCan::AccessDenied if (member.is_a?(MnoEnterprise::User) && member.role == 'Super Admin') ||
142
+ (member.is_a?(MnoEnterprise::OrgInvite) && member.user_role == 'Super Admin')
143
+ elsif member.id == current_user.id && attributes[:role] != 'Super Admin' && organization.users.count {|u| u.role == 'Super Admin'} <= 1
144
+ # A super admin cannot modify his role if he's the last super admin
145
+ raise CanCan::AccessDenied
144
146
  end
145
147
 
148
+ # Happy Path
149
+ case member
150
+ when MnoEnterprise::User
151
+ organization.users.update(id: member.id, role: attributes[:role])
152
+ when MnoEnterprise::OrgInvite
153
+ member.update(user_role: attributes[:role])
154
+ end
146
155
  render 'members'
147
156
  end
148
157
 
149
- # TODO: specs
150
158
  # PUT /mnoe/jpi/v1/organizations/:id/remove_member
151
159
  def remove_member
152
- attributes = params[:member]
153
- @member = organization.users.where(email: attributes[:email]).first
154
- @member ||= organization.org_invites.active.where(user_email: attributes[:email]).first
155
-
156
- # Authorize and update
157
160
  authorize! :invite_member, organization
158
- if @member.is_a?(MnoEnterprise::User)
159
- organization.remove_user(@member)
160
- elsif @member.is_a?(MnoEnterprise::OrgInvite)
161
- @member.cancel!
161
+
162
+ if member.is_a?(MnoEnterprise::User)
163
+ organization.remove_user(member)
164
+ elsif member.is_a?(MnoEnterprise::OrgInvite)
165
+ member.cancel!
162
166
  end
163
167
 
164
168
  render 'members'
165
169
  end
166
170
 
167
171
  protected
172
+ def member
173
+ @member ||= begin
174
+ email = params.require(:member).require(:email)
175
+ # Organizations are already loaded with all users
176
+ organization.users.to_a.find { |u| u.email == email } ||
177
+ organization.org_invites.active.where(user_email: email).first
178
+ end
179
+ end
180
+
168
181
  def organization
169
- @organization ||= current_user.organizations.to_a.find{ |o| o.id.to_s == params[:id].to_s }
182
+ @organization ||= begin
183
+ # Find in arrays if organizations have been fetched
184
+ # already. Perform remote query otherwise
185
+ if current_user.organizations.loaded?
186
+ current_user.organizations.to_a.find { |o| o.id.to_s == params[:id].to_s }
187
+ else
188
+ current_user.organizations.where(id: params[:id]).first
189
+ end
190
+ end
170
191
  end
171
192
 
172
193
  def organization_permitted_update_params
@@ -176,4 +197,23 @@ module MnoEnterprise::Concerns::Controllers::Jpi::V1::OrganizationsController
176
197
  def organization_update_params
177
198
  params.fetch(:organization, {}).permit(*organization_permitted_update_params)
178
199
  end
200
+
201
+ def organization_billing_params
202
+ params.require(:credit_card).permit(
203
+ 'title', 'first_name', 'last_name', 'number', 'month', 'year', 'country', 'verification_value',
204
+ 'billing_address', 'billing_city', 'billing_postcode', 'billing_country'
205
+ )
206
+ end
207
+
208
+ def check_valid_payment_method
209
+ return true unless organization.payment_restriction.present?
210
+
211
+ if CreditCardValidations::Detector.new(organization_billing_params[:number]).valid?(*organization.payment_restriction)
212
+ true
213
+ else
214
+ cards = organization.payment_restriction.map(&:capitalize).to_sentence
215
+ @credit_card.errors.add(:number, "Payment is limited to #{cards} Card Holders")
216
+ false
217
+ end
218
+ end
179
219
  end