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,92 @@
1
+ module MnoEnterprise::Concerns::Controllers::Jpi::V1::TeamsController
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/jpi/v1/organizations/:organization_id/teams
17
+ def index
18
+ authorize! :read, parent_organization
19
+ @teams = parent_organization.teams
20
+ end
21
+
22
+ # GET /mnoe/jpi/v1/teams/:id
23
+ def show
24
+ @team = MnoEnterprise::Team.find(params[:id])
25
+ authorize! :read, @team.organization
26
+ end
27
+
28
+ # POST /mnoe/jpi/v1/organizations/:organization_id/teams
29
+ def create
30
+ authorize! :manage_teams, parent_organization
31
+ @team = parent_organization.teams.create(team_params)
32
+
33
+ render 'show'
34
+ end
35
+
36
+ # PUT /mnoe/jpi/v1/teams/:id
37
+ def update
38
+ @team = MnoEnterprise::Team.find(params[:id])
39
+ authorize! :manage_teams, @team.organization
40
+
41
+ # Update regular attributes
42
+ @team.update_attributes(team_params)
43
+
44
+ # # Update permissions
45
+ if params[:team] && params[:team][:app_instances]
46
+ list = params[:team][:app_instances].select { |e| e != {} }
47
+ @team.set_access_to(list)
48
+ end
49
+
50
+ render 'show'
51
+ end
52
+
53
+ # PUT /mnoe/jpi/v1/teams/:id/add_users
54
+ def add_users
55
+ update_members(:add_user)
56
+ end
57
+
58
+ # PUT /mnoe/jpi/v1/teams/:id/remove_users
59
+ def remove_users
60
+ update_members(:remove_user)
61
+ end
62
+
63
+ # DELETE /mnoe/jpi/v1/teams/:id
64
+ def destroy
65
+ @team = MnoEnterprise::Team.find(params[:id])
66
+ authorize! :manage_teams, @team.organization
67
+ @team.destroy
68
+
69
+ head :no_content
70
+ end
71
+
72
+ private
73
+
74
+ # Update the members of a team
75
+ # Reduce duplication between add and remove
76
+ def update_members(action)
77
+ @team = MnoEnterprise::Team.find(params[:id])
78
+ authorize! :manage_teams, @team.organization
79
+
80
+ if params[:team] && params[:team][:users]
81
+ id_list = params[:team][:users].map { |h| h[:id] }.compact
82
+ users = @team.organization.users.where('id.in' => id_list)
83
+ users.each { |u| @team.send(action, u) }
84
+ end
85
+
86
+ render 'show'
87
+ end
88
+
89
+ def team_params
90
+ params.require(:team).permit(:name)
91
+ end
92
+ end
@@ -23,9 +23,9 @@ module MnoEnterprise::Concerns::Controllers::PagesController
23
23
  # TODO: Access + existence checks could be added in the future. This is not
24
24
  # mandatory as Mno Enterprise will do it anyway
25
25
  def launch
26
- app = MnoEnterprise::AppInstance.find_by(uid: params[:id])
27
- MnoEnterprise::EventLogger.info('app_launch', current_user.id, "App launched", app.name, app)
28
- redirect_to MnoEnterprise.router.launch_url(params[:id], wtk: MnoEnterprise.jwt(user_id: current_user.uid))
26
+ app_instance = MnoEnterprise::AppInstance.find_by(uid: params[:id])
27
+ MnoEnterprise::EventLogger.info('app_launch', current_user.id, 'App launched', app_instance)
28
+ redirect_to MnoEnterprise.router.launch_url(params[:id], {wtk: MnoEnterprise.jwt(user_id: current_user.uid)}.reverse_merge(request.query_parameters))
29
29
  end
30
30
 
31
31
  # GET /loading/:id
@@ -56,6 +56,20 @@ module MnoEnterprise::Concerns::Controllers::PagesController
56
56
  @meta[:description] = "Logged out from application"
57
57
  end
58
58
 
59
+ def terms
60
+ @meta[:title] = 'Terms of Use'
61
+ @meta[:description] = 'Terms of Use'
62
+
63
+ ts = MnoEnterprise::App.order_by("updated_at.desc").first.try(:updated_at)
64
+ @apps = if ts
65
+ Rails.cache.fetch(['pages/terms/app-list', ts]) do
66
+ MnoEnterprise::App.order_by("name.ac").reject{|i| i.terms_url.blank?}
67
+ end
68
+ else
69
+ []
70
+ end
71
+ end
72
+
59
73
  private
60
74
  def app_instance_hash(app_instance)
61
75
  return {} unless app_instance
@@ -40,7 +40,17 @@ module MnoEnterprise::Concerns::Controllers::ProvisionController
40
40
  unless @organization
41
41
  @organization = @organizations.one? ? @organizations.first : nil
42
42
  end
43
- authorize! :manage_app_instances, @organization
43
+
44
+ if @organization && cannot?(:manage_app_instances, @organization)
45
+ msg = 'Unfortunately you do not have permission to purchase products for this organization'
46
+ if @organizations.one?
47
+ redirect_path = add_param_to_fragment(after_provision_path.to_s, 'flash', [{msg: msg, type: :error}.to_json])
48
+ redirect_to redirect_path
49
+ else
50
+ @organization = nil
51
+ flash.now.alert = msg
52
+ end
53
+ end
44
54
 
45
55
  # Redirect to dashboard if no applications
46
56
  unless @apps && @apps.any?
@@ -51,12 +61,17 @@ module MnoEnterprise::Concerns::Controllers::ProvisionController
51
61
  # POST /provision
52
62
  # TODO: check organization accessibility via ability
53
63
  def create
64
+ # Avoid double provisioning: previous url would be "/provision/new?apps[]=vtiger&organization_id=1"
65
+ session.delete('previous_url')
66
+
54
67
  @organization = current_user.organizations.to_a.find { |o| o.id && o.id.to_s == params[:organization_id].to_s }
55
68
  authorize! :manage_app_instances, @organization
56
69
 
57
70
  app_instances = []
58
71
  params[:apps].each do |product_name|
59
- app_instances << @organization.app_instances.create(product: product_name)
72
+ app_instance = @organization.app_instances.create(product: product_name)
73
+ app_instances << app_instance
74
+ MnoEnterprise::EventLogger.info('app_add', current_user.id, 'App added', app_instance)
60
75
  end
61
76
 
62
77
  render json: app_instances.map(&:attributes).to_json, status: :created
@@ -23,7 +23,11 @@ module MnoEnterprise::Concerns::Mailers::SystemNotificationMailer
23
23
 
24
24
  # ==> Devise Email
25
25
  # Description:
26
- # Email asking users to confirm their email
26
+ # New user: Email asking users to confirm their email
27
+ # OR
28
+ # Existing user:
29
+ # - Email asking users (on their new email) to confirm their email change
30
+ # - Email notifying users (on their old email) of an email change
27
31
  #
28
32
  # Mandrill vars:
29
33
  # :first_name
@@ -32,12 +36,21 @@ module MnoEnterprise::Concerns::Mailers::SystemNotificationMailer
32
36
  # :confirmation_link
33
37
  #
34
38
  def confirmation_instructions(record, token, opts={})
35
- template = record.confirmed? && record.unconfirmed_email? ? 'reconfirmation-instructions' : 'confirmation-instructions'
39
+ update_email = record.confirmed? && record.unconfirmed_email?
40
+ template = update_email ? 'reconfirmation-instructions' : 'confirmation-instructions'
41
+ email = update_email ? record.unconfirmed_email : record.email
36
42
  MnoEnterprise::MailClient.deliver(template,
37
43
  default_sender,
38
- recipient(record),
44
+ recipient(record).merge(email: email),
39
45
  user_vars(record).merge(confirmation_link: user_confirmation_url(confirmation_token: token))
40
46
  )
47
+ if update_email
48
+ MnoEnterprise::MailClient.deliver('email-change',
49
+ default_sender,
50
+ recipient(record),
51
+ user_vars(record).merge(unconfirmed_email: record.unconfirmed_email)
52
+ )
53
+ end
41
54
  end
42
55
 
43
56
  # ==> Devise Email
@@ -76,6 +89,17 @@ module MnoEnterprise::Concerns::Mailers::SystemNotificationMailer
76
89
  )
77
90
  end
78
91
 
92
+ # Description:
93
+ # Email notifying a change of password
94
+ #
95
+ def password_change(record, opts={})
96
+ MnoEnterprise::MailClient.deliver('password-change',
97
+ default_sender,
98
+ recipient(record),
99
+ user_vars(record)
100
+ )
101
+ end
102
+
79
103
  # Description:
80
104
  # Send an email inviting the user to join an existing organization. If the user
81
105
  # is already confirmed it is directed to the organization invite page where he
@@ -1,26 +1,44 @@
1
1
  require 'httparty'
2
2
 
3
3
  module MnoEnterprise
4
+ # EventLogger to log various action performed by the end users (eg: sign in, add an app, ...)
5
+ # The EventLogger will enqueue notifications and dispatch them to the various listeners.
6
+ # The listeners can then process these event in any way they see fit (Audit Log, Analytics, ...)
4
7
  class EventLogger
5
- include HTTParty
6
- base_uri "#{MnoEnterprise.mno_api_private_host || MnoEnterprise.mno_api_host}/api/mnoe/v1/audit_events"
7
- read_timeout 0.1
8
- basic_auth MnoEnterprise.tenant_id, MnoEnterprise.tenant_key
8
+ @@listeners = [AuditEventsListener.new]
9
+ @@listeners << IntercomEventsListener.new if MnoEnterprise.intercom_enabled?
9
10
 
10
- def self.info(key, current_user_id, description, metadata, object)
11
- post('', body: {
12
- data: {
13
- key: key,
14
- user_id: current_user_id,
15
- description: description,
16
- metadata: format_metadata(metadata, object),
17
- subject_type: object.class.name,
18
- subject_id: object.id
19
- }})
20
- rescue Net::ReadTimeout
21
- # Meant to fail
11
+ # Enqueue a logging job to be performed later
12
+ #
13
+ # @param [String] key unique key identifying the event type
14
+ # @param [Integer] current_user_id user_id of the user triggering the event
15
+ # @param [String] description humanised description
16
+ # @param [Object] metadata
17
+ # @param [Object] object
18
+ def self.info(key, current_user_id, description, object, metadata = {})
19
+ formatted_metadata = format_metadata(metadata, object)
20
+ subject_type = object.class.name
21
+ subject_id = object.id
22
+ # TODO: improve
23
+ # Bypass Job queuing in specs or we'd have to stub lots of Her call for the deserialization
24
+ if Rails.env.test?
25
+ self.send_info(key, current_user_id, description, subject_type, subject_id, formatted_metadata)
26
+ else
27
+ MnoEnterprise::EventLoggerJob.perform_later('info', key, current_user_id, description, subject_type, subject_id, formatted_metadata)
28
+ end
29
+ rescue ActiveJob::SerializationError
30
+ Rails.logger.warn "[MnoEnterprise::EventLogger] Serialization error, skipping #{key} event"
31
+ end
32
+
33
+ # Send the event to the listeners
34
+ # @see .info for the params description
35
+ def self.send_info(key, current_user_id, description, subject_type, subject_id, metadata)
36
+ @@listeners.each do |listener|
37
+ listener.info(key, current_user_id, description, subject_type, subject_id, metadata)
38
+ end
22
39
  end
23
40
 
41
+ # Get the metadata from the object if not provided
24
42
  def self.format_metadata(metadata, object)
25
43
  if metadata.blank? && object.respond_to?(:to_audit_event)
26
44
  object.to_audit_event
@@ -0,0 +1,96 @@
1
+ require 'intercom'
2
+
3
+ module MnoEnterprise
4
+
5
+ class IntercomEventsListener
6
+
7
+ attr_accessor :intercom
8
+
9
+ def initialize
10
+ args = if MnoEnterprise.intercom_token
11
+ {token: MnoEnterprise.intercom_token}
12
+ else
13
+ {app_id: MnoEnterprise.intercom_app_id, api_key: MnoEnterprise.intercom_api_key}
14
+ end
15
+ self.intercom = ::Intercom::Client.new(args)
16
+ end
17
+
18
+ def info(key, current_user_id, description, subject_type, subject_id, metadata)
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
+ data = {created_at: Time.now.to_i, email: u.email, user_id: u.id, event_name: key.tr('_', '-')}
26
+ case key
27
+ when 'user_update', 'organization_update'
28
+ self.update_intercom_user(u)
29
+ # convert values to string
30
+ data[:metadata] = Hash[ metadata.collect {|k,v| [k, v.to_s] } ]
31
+ when 'user_confirm'
32
+ data[:event_name] = 'finished-sign-up'
33
+ when 'dashboard_create'
34
+ data[:event_name] = 'added-dashboard'
35
+ when 'dashboard_delete'
36
+ data[:event_name] = 'removed-dashboard'
37
+ when 'widget_delete'
38
+ data[:event_name] = 'removed-widget'
39
+ when 'widget_create'
40
+ data[:event_name] = 'added-widget'
41
+ data[:metadata] = {widget: metadata[:name]}
42
+ when 'app_launch'
43
+ data[:event_name] = 'launched-app-' + metadata[:app_nid]
44
+ when 'app_destroy'
45
+ data[:event_name] = 'deleted-app-' + metadata[:app_nid]
46
+ data[:metadata] = {type: 'single', app_list: metadata[:app_nid]}
47
+ when 'app_add'
48
+ data[:event_name] = 'added-app-' + metadata[:app_nid]
49
+ data[:metadata] = {type: 'single', app_list: metadata[:app_nid]}
50
+ end
51
+ self.intercom.events.create(data)
52
+
53
+ rescue Intercom::IntercomError => e
54
+ Rails.logger.tagged('Intercom') { Rails.logger.warn 'Error while calling intercom ' + e.message}
55
+ end
56
+
57
+ 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
+
70
+ 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
+ }
83
+ end
84
+ intercom.users.create(data)
85
+ tag_user(user)
86
+ end
87
+
88
+ # If a source is set, tag the user with it
89
+ def tag_user(user)
90
+ if user.meta_data && user.meta_data[:source].present?
91
+ intercom.tags.tag(name: user.meta_data[:source], users: [{user_id: user.id}])
92
+ end
93
+ end
94
+ end
95
+ end
96
+
@@ -64,5 +64,33 @@ module MnoEnterprise
64
64
  end
65
65
  end
66
66
  end
67
+
68
+ describe 'PATCH #finalize' do
69
+ let(:user_params) { {confirmation_token: user.confirmation_token, password: 'test', name: 'test'} }
70
+ subject { post :finalize, user: user_params }
71
+
72
+ before do
73
+ allow(MnoEnterprise::User).to receive(:find_for_confirmation) { user }
74
+ api_stub_for(get: "/org_invites?filter[user_email]=#{user.email}", response: from_api(nil))
75
+ api_stub_for(put: "/users/#{user.id}", response: from_api(user))
76
+ end
77
+
78
+ context 'unconfirmed user' do
79
+ let(:user) { unconfirmed_user }
80
+
81
+ it 'redirects the user to the dashboard' do
82
+ expect(subject).to redirect_to('/dashboard/')
83
+ end
84
+
85
+ context 'when password change notifications are enabled' do
86
+ before { user.class.send_password_change_notification = true }
87
+
88
+ it 'does not send an email' do
89
+ expect(user).not_to receive(:send_devise_notification)
90
+ subject
91
+ end
92
+ end
93
+ end
94
+ end
67
95
  end
68
96
  end
@@ -0,0 +1,34 @@
1
+ require 'rails_helper'
2
+
3
+ module MnoEnterprise
4
+ describe Auth::OmniauthCallbacksController, type: :controller do
5
+ routes { MnoEnterprise::Engine.routes }
6
+
7
+
8
+ supported_providers = %i(linkedin google facebook)
9
+
10
+
11
+ describe 'provides callbacks for the providers' do
12
+ before do
13
+ Devise.omniauth :facebook, 'key', 'secret', secure_image_url: true
14
+ MnoEnterprise::Auth.send(:remove_const, :OmniauthCallbacksController)
15
+ load 'app/controllers/mno_enterprise/auth/omniauth_callbacks_controller.rb'
16
+ end
17
+
18
+
19
+ # No described_class as it doesn't take into account the reloading above
20
+ let(:controller) { MnoEnterprise::Auth::OmniauthCallbacksController.new }
21
+
22
+ it { expect(controller).to respond_to(:intuit) }
23
+ it { expect(controller).to respond_to(:facebook) }
24
+
25
+ end
26
+
27
+ # it creates an org?
28
+ # no if no email
29
+ # no if user already exists
30
+ # no if accepting an org invite
31
+
32
+
33
+ end
34
+ end