mno-enterprise-api 3.2.1 → 3.3.0

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 (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