mno-enterprise-api 3.2.1 → 3.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (57) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/javascripts/mno_enterprise/config.js.coffee.erb +8 -0
  3. data/app/controllers/mno_enterprise/admin/invoices_controller.rb +18 -0
  4. data/app/controllers/mno_enterprise/impersonate_controller.rb +5 -1
  5. data/app/controllers/mno_enterprise/jpi/v1/admin/audit_events_controller.rb +9 -0
  6. data/app/controllers/mno_enterprise/jpi/v1/admin/users_controller.rb +10 -4
  7. data/app/controllers/mno_enterprise/jpi/v1/audit_events_controller.rb +28 -0
  8. data/app/controllers/mno_enterprise/jpi/v1/base_resource_controller.rb +1 -1
  9. data/app/controllers/mno_enterprise/webhook/events_controller.rb +7 -0
  10. data/app/views/mno_enterprise/auth/confirmations/lounge.html.haml +26 -25
  11. data/app/views/mno_enterprise/jpi/v1/admin/audit_events/_audit_event.json.jbuilder +1 -1
  12. data/app/views/mno_enterprise/jpi/v1/admin/audit_events/index.csv.erb +14 -0
  13. data/app/views/mno_enterprise/jpi/v1/admin/organizations/_invoices.json.jbuilder +1 -0
  14. data/app/views/mno_enterprise/jpi/v1/admin/organizations/_organization.json.jbuilder +1 -1
  15. data/app/views/mno_enterprise/jpi/v1/admin/users/show.json.jbuilder +1 -0
  16. data/app/views/mno_enterprise/jpi/v1/audit_events/_audit_event.json.jbuilder +5 -0
  17. data/app/views/mno_enterprise/jpi/v1/audit_events/index.csv.erb +12 -0
  18. data/app/views/mno_enterprise/jpi/v1/audit_events/index.json.jbuilder +4 -0
  19. data/app/views/mno_enterprise/jpi/v1/current_users/show.json.jbuilder +1 -1
  20. data/app/views/mno_enterprise/jpi/v1/impac/kpis/_kpi.json.jbuilder +1 -1
  21. data/app/views/mno_enterprise/jpi/v1/impac/widgets/_widget.json.jbuilder +3 -1
  22. data/app/views/mno_enterprise/jpi/v1/marketplace/_app.json.jbuilder +10 -1
  23. data/app/views/mno_enterprise/jpi/v1/organizations/_organization.json.jbuilder +1 -1
  24. data/app/views/mno_enterprise/webhook/o_auth/authorize.html.haml +1 -1
  25. data/config/routes.rb +16 -5
  26. data/lib/mno_enterprise/audit_events_listener.rb +11 -6
  27. data/lib/mno_enterprise/concerns/controllers/jpi/v1/current_users_controller.rb +6 -1
  28. data/lib/mno_enterprise/concerns/controllers/jpi/v1/impac/kpis_controller.rb +9 -10
  29. data/lib/mno_enterprise/concerns/controllers/jpi/v1/impac/widgets_controller.rb +6 -3
  30. data/lib/mno_enterprise/concerns/controllers/jpi/v1/marketplace_controller.rb +20 -8
  31. data/lib/mno_enterprise/concerns/controllers/jpi/v1/organizations_controller.rb +12 -0
  32. data/lib/mno_enterprise/concerns/controllers/jpi/v1/teams_controller.rb +13 -0
  33. data/lib/mno_enterprise/concerns/controllers/pages_controller.rb +2 -0
  34. data/lib/mno_enterprise/concerns/controllers/webhook/events_controller.rb +22 -0
  35. data/lib/mno_enterprise/concerns/controllers/webhook/o_auth_controller.rb +12 -3
  36. data/lib/mno_enterprise/event_logger.rb +2 -2
  37. data/lib/mno_enterprise/intercom_events_listener.rb +25 -30
  38. data/spec/controllers/mno_enterprise/admin/invoices_controller_spec.rb +38 -0
  39. data/spec/controllers/mno_enterprise/impersonate_controller_spec.rb +6 -0
  40. data/spec/controllers/mno_enterprise/jpi/v1/admin/audit_events_controller_spec.rb +9 -0
  41. data/spec/controllers/mno_enterprise/jpi/v1/admin/organizations_controller_spec.rb +3 -2
  42. data/spec/controllers/mno_enterprise/jpi/v1/admin/users_controller_spec.rb +2 -1
  43. data/spec/controllers/mno_enterprise/jpi/v1/audit_events_controller_spec.rb +49 -0
  44. data/spec/controllers/mno_enterprise/jpi/v1/current_users_controller_spec.rb +16 -0
  45. data/spec/controllers/mno_enterprise/jpi/v1/impac/kpis_controller_spec.rb +124 -89
  46. data/spec/controllers/mno_enterprise/jpi/v1/marketplace_controller_spec.rb +83 -36
  47. data/spec/controllers/mno_enterprise/jpi/v1/organizations_controller_spec.rb +18 -3
  48. data/spec/controllers/mno_enterprise/org_invites_controller_spec.rb +3 -3
  49. data/spec/controllers/mno_enterprise/provision_controller_spec.rb +2 -2
  50. data/spec/controllers/mno_enterprise/webhook/o_auth_controller_spec.rb +1 -1
  51. data/spec/lib/mno_enterprise/audit_events_listener_spec.rb +11 -0
  52. data/spec/lib/mno_enterprise/intercom_events_listener_spec.rb +74 -31
  53. data/spec/routing/devise/registrations_routing_spec.rb +43 -6
  54. data/spec/routing/mno_enterprise/admin/invoices_controller_routing_spec.rb +11 -0
  55. data/spec/routing/mno_enterprise/impersonate_controller_routing_spec.rb +30 -4
  56. data/spec/routing/mno_enterprise/jpi/v1/audit_events_controller_routing_spec.rb +11 -0
  57. metadata +20 -4
@@ -8,6 +8,7 @@ module MnoEnterprise::Concerns::Controllers::Jpi::V1::CurrentUsersController
8
8
  # context where it is included rather than being executed in the module's context
9
9
  included do
10
10
  before_filter :authenticate_user!, only: [:update, :update_password]
11
+ before_filter :user_management_enabled?, only: [:update, :update_password]
11
12
  respond_to :json
12
13
  end
13
14
 
@@ -37,7 +38,7 @@ module MnoEnterprise::Concerns::Controllers::Jpi::V1::CurrentUsersController
37
38
  def register_developer
38
39
  @user = current_user
39
40
  if @user.update(developer: true)
40
- MnoEnterprise::EventLogger.info('register_developer', current_user.id, "User developer register", @user)
41
+ MnoEnterprise::EventLogger.info('register_developer', current_user.id, "Developer registration", @user)
41
42
  render :show
42
43
  else
43
44
  render json: @user.errors, status: :bad_request
@@ -65,4 +66,8 @@ module MnoEnterprise::Concerns::Controllers::Jpi::V1::CurrentUsersController
65
66
  def password_params
66
67
  params.require(:user).permit(:current_password, :password, :password_confirmation)
67
68
  end
69
+
70
+ def user_management_enabled?
71
+ return head :forbidden unless Settings.user_management.enabled
72
+ end
68
73
  end
@@ -50,13 +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
- # 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
-
53
+ if widget.present?
54
+ authorize! :manage_widget, widget
55
+ else
56
+ authorize! :manage_dashboard, dashboard
57
+ end
58
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)
59
+ @kpi = kpi_parent.kpis.create(kpi_create_params)
60
+ unless kpi.errors?
60
61
  # Creates a default alert for kpis created with targets defined.
61
62
  if kpi.targets.present?
62
63
  current_user.alerts.create({service: 'inapp', impac_kpi_id: kpi.id})
@@ -137,13 +138,11 @@ module MnoEnterprise::Concerns::Controllers::Jpi::V1::Impac::KpisController
137
138
  end
138
139
 
139
140
  def kpi_parent
140
- # TODO: attach kpi onto widget capability
141
- # widget || dashboard
142
- dashboard
141
+ widget || dashboard
143
142
  end
144
143
 
145
144
  def kpi_create_params
146
- whitelist = [:dashboard_id, :endpoint, :source, :element_watched, {extra_watchables: []}]
145
+ whitelist = [:dashboard_id, :widget_id, :endpoint, :source, :element_watched, {extra_watchables: []}]
147
146
  extract_params(whitelist)
148
147
  end
149
148
 
@@ -25,7 +25,7 @@ module MnoEnterprise::Concerns::Controllers::Jpi::V1::Impac::WidgetsController
25
25
  def create
26
26
  if widgets
27
27
  if @widget = widgets.create(widget_create_params)
28
- MnoEnterprise::EventLogger.info('widget_create', current_user.id, 'Widget Creation', @widget)
28
+ MnoEnterprise::EventLogger.info('widget_create', current_user.id, 'Widget Creation', widget)
29
29
  @nocontent = true # no data fetch from Connec!
30
30
  render 'show'
31
31
  else
@@ -40,6 +40,7 @@ module MnoEnterprise::Concerns::Controllers::Jpi::V1::Impac::WidgetsController
40
40
  # -> PUT /api/mnoe/v1/widgets/:id
41
41
  def update
42
42
  if widget.update(widget_update_params)
43
+ MnoEnterprise::EventLogger.info('widget_update', current_user.id, 'Widget Update', widget, {widget_action: params[:widget]})
43
44
  @nocontent = !params['metadata']
44
45
  render 'show'
45
46
  else
@@ -73,14 +74,16 @@ module MnoEnterprise::Concerns::Controllers::Jpi::V1::Impac::WidgetsController
73
74
  end
74
75
 
75
76
  def widget_create_params
76
- params.require(:widget).permit(:widget_category).tap do |whitelisted|
77
+ params.require(:widget).permit(:endpoint, :name, :width).tap do |whitelisted|
77
78
  whitelisted[:settings] = params[:widget][:metadata] || {}
79
+ # TODO: remove when mnohub migrated to new model
80
+ whitelisted[:widget_category] = params[:widget][:endpoint]
78
81
  end
79
82
  .except(:metadata)
80
83
  end
81
84
 
82
85
  def widget_update_params
83
- params.require(:widget).permit(:name).tap do |whitelisted|
86
+ params.require(:widget).permit(:name, :width).tap do |whitelisted|
84
87
  whitelisted[:settings] = params[:widget][:metadata] || {}
85
88
  end
86
89
  .except(:metadata)
@@ -15,18 +15,30 @@ module MnoEnterprise::Concerns::Controllers::Jpi::V1::MarketplaceController
15
15
  #==================================================================
16
16
  # GET /mnoe/mnoe/jpi/v1/marketplace
17
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')
18
+ expires_in 0, public: true, must_revalidate: true
19
+ last_modified = app_relation.order_by('updated_at.desc').limit(1).first.updated_at
20
+
21
+ if stale?(last_modified: last_modified)
22
+ @apps = app_relation.to_a
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
+ respond_to do |format|
27
+ format.json
28
+ end
29
+ end
26
30
  end
27
31
 
28
32
  # GET /mnoe/jpi/v1/marketplace/1
29
33
  def show
30
34
  @app = MnoEnterprise::App.find(params[:id])
31
35
  end
36
+
37
+ def app_relation
38
+ if MnoEnterprise.marketplace_listing
39
+ MnoEnterprise::App.where('nid.in' => MnoEnterprise.marketplace_listing)
40
+ else
41
+ MnoEnterprise::App.all
42
+ end
43
+ end
32
44
  end
@@ -8,6 +8,8 @@ module MnoEnterprise::Concerns::Controllers::Jpi::V1::OrganizationsController
8
8
  # context where it is included rather than being executed in the module's context
9
9
  included do
10
10
  respond_to :json
11
+ before_filter :organization_management_enabled?, only: [:create, :update, :destroy, :update_billing,
12
+ :invite_members, :update_member, :remove_member]
11
13
  end
12
14
 
13
15
  #==================================================================
@@ -118,6 +120,7 @@ module MnoEnterprise::Concerns::Controllers::Jpi::V1::OrganizationsController
118
120
  )
119
121
 
120
122
  MnoEnterprise::SystemNotificationMailer.organization_invite(@org_invite).deliver_now
123
+ MnoEnterprise::EventLogger.info('user_invite', current_user.id, 'User invited', @org_invite)
121
124
  end
122
125
 
123
126
  # Reload users
@@ -149,9 +152,12 @@ module MnoEnterprise::Concerns::Controllers::Jpi::V1::OrganizationsController
149
152
  case member
150
153
  when MnoEnterprise::User
151
154
  organization.users.update(id: member.id, role: attributes[:role])
155
+ MnoEnterprise::EventLogger.info('user_role_update', current_user.id, 'User role update in org', organization, {email: attributes[:email], role: attributes[:role]})
152
156
  when MnoEnterprise::OrgInvite
153
157
  member.update(user_role: attributes[:role])
158
+ MnoEnterprise::EventLogger.info('user_role_update', current_user.id, 'User role update in invitation', organization, {email: attributes[:email], role: attributes[:role]})
154
159
  end
160
+
155
161
  render 'members'
156
162
  end
157
163
 
@@ -161,8 +167,10 @@ module MnoEnterprise::Concerns::Controllers::Jpi::V1::OrganizationsController
161
167
 
162
168
  if member.is_a?(MnoEnterprise::User)
163
169
  organization.remove_user(member)
170
+ MnoEnterprise::EventLogger.info('user_role_delete', current_user.id, 'User removed from org', organization, {email: member.email})
164
171
  elsif member.is_a?(MnoEnterprise::OrgInvite)
165
172
  member.cancel!
173
+ MnoEnterprise::EventLogger.info('user_role_delete', current_user.id, 'User removed from invitation', organization, {email: member.user_email})
166
174
  end
167
175
 
168
176
  render 'members'
@@ -216,4 +224,8 @@ module MnoEnterprise::Concerns::Controllers::Jpi::V1::OrganizationsController
216
224
  false
217
225
  end
218
226
  end
227
+
228
+ def organization_management_enabled?
229
+ return head :forbidden unless Settings.organization_management.enabled
230
+ end
219
231
  end
@@ -30,6 +30,8 @@ module MnoEnterprise::Concerns::Controllers::Jpi::V1::TeamsController
30
30
  authorize! :manage_teams, parent_organization
31
31
  @team = parent_organization.teams.create(team_params)
32
32
 
33
+ MnoEnterprise::EventLogger.info('team_add', current_user.id, 'Team created', @team) if @team
34
+
33
35
  render 'show'
34
36
  end
35
37
 
@@ -45,6 +47,10 @@ module MnoEnterprise::Concerns::Controllers::Jpi::V1::TeamsController
45
47
  if params[:team] && params[:team][:app_instances]
46
48
  list = params[:team][:app_instances].select { |e| e != {} }
47
49
  @team.set_access_to(list)
50
+
51
+ MnoEnterprise::EventLogger.info('team_apps_update', current_user.id, 'Team apps updated', @team,
52
+ {apps: list.map{|l| l['name']}})
53
+
48
54
  end
49
55
 
50
56
  render 'show'
@@ -64,8 +70,11 @@ module MnoEnterprise::Concerns::Controllers::Jpi::V1::TeamsController
64
70
  def destroy
65
71
  @team = MnoEnterprise::Team.find(params[:id])
66
72
  authorize! :manage_teams, @team.organization
73
+
67
74
  @team.destroy
68
75
 
76
+ MnoEnterprise::EventLogger.info('team_delete', current_user.id, 'Team deleted', @team) if @team
77
+
69
78
  head :no_content
70
79
  end
71
80
 
@@ -80,7 +89,11 @@ module MnoEnterprise::Concerns::Controllers::Jpi::V1::TeamsController
80
89
  if params[:team] && params[:team][:users]
81
90
  id_list = params[:team][:users].map { |h| h[:id] }.compact
82
91
  users = @team.organization.users.where('id.in' => id_list)
92
+
83
93
  users.each { |u| @team.send(action, u) }
94
+
95
+ MnoEnterprise::EventLogger.info('team_update', current_user.id, 'Team composition updated', @team,
96
+ {action: action.to_s, users: users.map(&:email)})
84
97
  end
85
98
 
86
99
  render 'show'
@@ -1,5 +1,6 @@
1
1
  module MnoEnterprise::Concerns::Controllers::PagesController
2
2
  extend ActiveSupport::Concern
3
+ include MnoEnterprise::ImageHelper
3
4
 
4
5
  #==================================================================
5
6
  # Included methods
@@ -9,6 +10,7 @@ module MnoEnterprise::Concerns::Controllers::PagesController
9
10
  included do
10
11
  before_filter :authenticate_user!, only: [:launch]
11
12
  before_filter :redirect_to_lounge_if_unconfirmed, only: [:launch]
13
+ helper_method :main_logo_white_bg_path # To use in the provision view
12
14
  end
13
15
 
14
16
  #==================================================================
@@ -0,0 +1,22 @@
1
+ module MnoEnterprise::Concerns::Controllers::Webhook::EventsController
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
+ skip_before_filter :verify_authenticity_token
11
+ end
12
+
13
+
14
+ #==================================================================
15
+ # Instance methods
16
+ #==================================================================
17
+ # POST /mnoe/webhook/events
18
+ def create
19
+ Rails.logger.debug("Received event #{params[:event]}")
20
+ head :ok
21
+ end
22
+ end
@@ -1,5 +1,6 @@
1
1
  module MnoEnterprise::Concerns::Controllers::Webhook::OAuthController
2
2
  extend ActiveSupport::Concern
3
+ include MnoEnterprise::ImageHelper
3
4
 
4
5
  #==================================================================
5
6
  # Included methods
@@ -12,7 +13,7 @@ module MnoEnterprise::Concerns::Controllers::Webhook::OAuthController
12
13
  before_filter :check_permissions, only: [:authorize, :disconnect, :sync]
13
14
 
14
15
  PROVIDERS_WITH_OPTIONS = ['xero','myob']
15
-
16
+ helper_method :main_logo_white_bg # To use in the provision view
16
17
  private
17
18
  def app_instance
18
19
  @app_instance ||= MnoEnterprise::AppInstance.where(uid: params[:id]).first
@@ -41,7 +42,7 @@ module MnoEnterprise::Concerns::Controllers::Webhook::OAuthController
41
42
  def error_message(error_key)
42
43
  case error_key.to_sym
43
44
  when :bad_relinking
44
- %{A different account "#{app_instance.oauth_company}" was previously linked to this application, please re-link the same account.}
45
+ %{A different account '#{app_instance.oauth_company}' was previously linked to this application, please re-link the same account.}
45
46
  when :unauthorized
46
47
  'We could not validate your credentials, please try again'
47
48
  else
@@ -73,10 +74,18 @@ module MnoEnterprise::Concerns::Controllers::Webhook::OAuthController
73
74
  path = session.delete(:redirect_path).presence || mnoe_home_path
74
75
 
75
76
  if error_key = params.fetch(:oauth, {})[:error]
76
-
77
77
  path = add_param_to_fragment(path.to_s, 'flash', [{msg: error_message(error_key), type: :error}.to_json])
78
78
  end
79
79
 
80
+ unless params.fetch(:oauth, {})[:error]
81
+ case params.fetch(:oauth, {})[:action]
82
+ when 'sync'
83
+ MnoEnterprise::EventLogger.info('app_connected', current_user.id, 'App connected', app_instance)
84
+ when 'disconnect'
85
+ MnoEnterprise::EventLogger.info('app_disconnected', current_user.id, 'App disconnected', app_instance)
86
+ end
87
+ end
88
+
80
89
  redirect_to path
81
90
  end
82
91
 
@@ -40,8 +40,8 @@ module MnoEnterprise
40
40
 
41
41
  # Get the metadata from the object if not provided
42
42
  def self.format_metadata(metadata, object)
43
- if metadata.blank? && object.respond_to?(:to_audit_event)
44
- object.to_audit_event
43
+ if object.respond_to?(:to_audit_event)
44
+ metadata.merge(object.to_audit_event)
45
45
  else
46
46
  metadata
47
47
  end
@@ -17,15 +17,9 @@ module MnoEnterprise
17
17
 
18
18
  def info(key, current_user_id, description, subject_type, subject_id, metadata)
19
19
  u = User.find(current_user_id)
20
- begin
21
- intercom.users.find(user_id: current_user_id)
22
- rescue Intercom::ResourceNotFound
23
- self.update_intercom_user(u)
24
- end
25
20
  data = {created_at: Time.now.to_i, email: u.email, user_id: u.id, event_name: key.tr('_', '-')}
26
21
  case key
27
22
  when 'user_update', 'organization_update'
28
- self.update_intercom_user(u)
29
23
  # convert values to string
30
24
  data[:metadata] = Hash[ metadata.collect {|k,v| [k, v.to_s] } ]
31
25
  when 'user_confirm'
@@ -48,6 +42,10 @@ module MnoEnterprise
48
42
  data[:event_name] = 'added-app-' + metadata[:app_nid]
49
43
  data[:metadata] = {type: 'single', app_list: metadata[:app_nid]}
50
44
  end
45
+ # Update user data in intercom
46
+ # OPTIMIZE: we could fetch the user for intercom and only update fields that have changed
47
+ self.update_intercom_user(u)
48
+ # Push the event to intercom
51
49
  self.intercom.events.create(data)
52
50
 
53
51
  rescue Intercom::IntercomError => e
@@ -55,31 +53,9 @@ module MnoEnterprise
55
53
  end
56
54
 
57
55
  def update_intercom_user(user, update_last_request_at = true)
58
- data = {
59
- user_id: user.id,
60
- name: [user.name, user.surname].join(' '),
61
- email: user.email,
62
- created_at: user.created_at.to_i,
63
- last_seen_ip: user.last_sign_in_ip,
64
- custom_attributes: {},
65
- update_last_request_at: update_last_request_at
66
- }
67
- data[:custom_attributes][:phone]= user.phone if user.phone
68
- data[:custom_attributes][:external_id]= user.external_id if user.external_id
69
-
56
+ data = user.intercom_data(update_last_request_at)
70
57
  data[:companies] = user.organizations.map do |organization|
71
- {
72
- company_id: organization.id,
73
- name: organization.name,
74
- created_at: organization.created_at.to_i,
75
- custom_attributes: {
76
- industry: organization.industry,
77
- size: organization.size,
78
- credit_card_details: organization.credit_card?,
79
- app_count: organization.app_instances.count,
80
- app_list: organization.app_instances.map { |app| app.name }.to_sentence
81
- }
82
- }
58
+ format_company(organization)
83
59
  end
84
60
  intercom.users.create(data)
85
61
  tag_user(user)
@@ -91,6 +67,25 @@ module MnoEnterprise
91
67
  intercom.tags.tag(name: user.meta_data[:source], users: [{user_id: user.id}])
92
68
  end
93
69
  end
70
+
71
+ # Formatting
72
+ # TODO: extract to a CRM service
73
+ def format_company(organization)
74
+ {
75
+ company_id: organization.id,
76
+ name: organization.name,
77
+ created_at: organization.created_at.to_i,
78
+ custom_attributes: {
79
+ industry: organization.industry,
80
+ size: organization.size,
81
+ credit_card_details: organization.has_credit_card_details?,
82
+ credit_card_expiry: organization.credit_card.expiry_date,
83
+ app_count: organization.app_instances.count,
84
+ app_list: organization.app_instances.map(&:name).sort.to_sentence,
85
+ user_count: organization.users.count
86
+ }
87
+ }
88
+ end
94
89
  end
95
90
  end
96
91
 
@@ -0,0 +1,38 @@
1
+ require 'rails_helper'
2
+
3
+ module MnoEnterprise
4
+ describe Admin::InvoicesController, type: :controller do
5
+ include MnoEnterprise::TestingSupport::SharedExamples::JpiV1Admin
6
+
7
+ render_views
8
+ routes { MnoEnterprise::Engine.routes }
9
+
10
+ #===============================================
11
+ # Assignments
12
+ #===============================================
13
+ # Stub user and user call
14
+ let(:user) { FactoryGirl.build(:user, :admin) }
15
+ before { api_stub_for(get: "/users/#{user.id}", response: from_api(user)) }
16
+ before { sign_in user }
17
+
18
+ # Stub model calls
19
+ let(:organization) { build(:organization) }
20
+ let(:invoice) { build(:invoice, organization_id: organization.id) }
21
+
22
+ # before { api_stub_for(get: "/users/#{user.id}", response: from_api(user)) }
23
+ before { api_stub_for(get: "/organizations/#{organization.id}", response: from_api(organization)) }
24
+ # before { api_stub_for(get: "/users/#{user.id}/organizations/#{organization.id}", response: from_api(organization)) }
25
+ before { api_stub_for(get: "/invoices", params: { filter: { slug: '**' } }, response: from_api([invoice])) }
26
+
27
+
28
+ describe "GET #show" do
29
+ subject { get :show, id: invoice.slug }
30
+
31
+ it_behaves_like "a jpi v1 admin action"
32
+
33
+ context 'success' do
34
+ it { subject; expect(response).to be_success }
35
+ end
36
+ end
37
+ end
38
+ end