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.
- checksums.yaml +4 -4
- data/app/assets/javascripts/mno_enterprise/config.js.coffee.erb +7 -1
- data/app/controllers/mno_enterprise/auth/omniauth_callbacks_controller.rb +3 -27
- data/app/controllers/mno_enterprise/auth/sessions_controller.rb +1 -3
- data/app/controllers/mno_enterprise/jpi/v1/admin/app_answers_controller.rb +26 -0
- data/app/controllers/mno_enterprise/jpi/v1/admin/app_comments_controller.rb +28 -0
- data/app/controllers/mno_enterprise/jpi/v1/admin/app_instances_controller.rb +16 -0
- data/app/controllers/mno_enterprise/jpi/v1/admin/app_reviews_controller.rb +30 -0
- data/app/controllers/mno_enterprise/jpi/v1/admin/invites_controller.rb +1 -1
- data/app/controllers/mno_enterprise/jpi/v1/admin/organizations_controller.rb +55 -37
- data/app/controllers/mno_enterprise/jpi/v1/app_answers_controller.rb +22 -0
- data/app/controllers/mno_enterprise/jpi/v1/app_comments_controller.rb +22 -0
- data/app/controllers/mno_enterprise/jpi/v1/app_feedbacks_controller.rb +14 -0
- data/app/controllers/mno_enterprise/jpi/v1/app_instances_controller.rb +1 -20
- data/app/controllers/mno_enterprise/jpi/v1/app_questions_controller.rb +25 -0
- data/app/controllers/mno_enterprise/jpi/v1/app_reviews_controller.rb +94 -0
- data/app/controllers/mno_enterprise/jpi/v1/base_resource_controller.rb +12 -0
- data/app/controllers/mno_enterprise/jpi/v1/impac/alerts_controller.rb +5 -0
- data/app/controllers/mno_enterprise/jpi/v1/impac/kpis_controller.rb +1 -76
- data/app/controllers/mno_enterprise/jpi/v1/marketplace_controller.rb +1 -18
- data/app/controllers/mno_enterprise/jpi/v1/teams_controller.rb +1 -83
- data/app/jobs/mno_enterprise/event_logger_job.rb +10 -0
- data/app/views/mno_enterprise/auth/confirmations/new.html.haml +6 -6
- data/app/views/mno_enterprise/auth/passwords/new.html.haml +8 -8
- data/app/views/mno_enterprise/auth/registrations/new.html.haml +1 -0
- data/app/views/mno_enterprise/auth/sessions/new.html.haml +1 -0
- data/app/views/mno_enterprise/auth/shared/_links.html.haml +0 -5
- data/app/views/mno_enterprise/auth/shared/_omniauth.html.haml +10 -0
- data/app/views/mno_enterprise/jpi/v1/admin/app_answers/show.json.jbuilder +15 -0
- data/app/views/mno_enterprise/jpi/v1/admin/app_comments/show.json.jbuilder +15 -0
- data/app/views/mno_enterprise/jpi/v1/admin/app_reviews/_app_review.json.jbuilder +13 -0
- data/app/views/mno_enterprise/jpi/v1/admin/app_reviews/index.json.jbuilder +1 -0
- data/app/views/mno_enterprise/jpi/v1/admin/app_reviews/show.json.jbuilder +3 -0
- data/app/views/mno_enterprise/jpi/v1/admin/organizations/show.json.jbuilder +1 -0
- data/app/views/mno_enterprise/jpi/v1/admin/users/_user.json.jbuilder +1 -1
- data/app/views/mno_enterprise/jpi/v1/app_answers/_resource.json.jbuilder +4 -0
- data/app/views/mno_enterprise/jpi/v1/app_answers/index.json.jbuilder +5 -0
- data/app/views/mno_enterprise/jpi/v1/app_answers/show.json.jbuilder +3 -0
- data/app/views/mno_enterprise/jpi/v1/app_comments/_resource.json.jbuilder +3 -0
- data/app/views/mno_enterprise/jpi/v1/app_comments/index.json.jbuilder +5 -0
- data/app/views/mno_enterprise/jpi/v1/app_comments/show.json.jbuilder +3 -0
- data/app/views/mno_enterprise/jpi/v1/app_feedbacks/_comment.json.jbuilder +10 -0
- data/app/views/mno_enterprise/jpi/v1/app_feedbacks/_resource.json.jbuilder +7 -0
- data/app/views/mno_enterprise/jpi/v1/app_feedbacks/index.json.jbuilder +5 -0
- data/app/views/mno_enterprise/jpi/v1/app_feedbacks/show.json.jbuilder +4 -0
- data/app/views/mno_enterprise/jpi/v1/app_instances/_resource.json.jbuilder +9 -0
- data/app/views/mno_enterprise/jpi/v1/app_questions/_answer.json.jbuilder +3 -0
- data/app/views/mno_enterprise/jpi/v1/app_questions/_resource.json.jbuilder +8 -0
- data/app/views/mno_enterprise/jpi/v1/app_questions/index.json.jbuilder +5 -0
- data/app/views/mno_enterprise/jpi/v1/app_questions/show.json.jbuilder +3 -0
- data/app/views/mno_enterprise/jpi/v1/app_reviews/_resource.json.jbuilder +13 -0
- data/app/views/mno_enterprise/jpi/v1/app_reviews/index.json.jbuilder +5 -0
- data/app/views/mno_enterprise/jpi/v1/app_reviews/show.json.jbuilder +4 -0
- data/app/views/mno_enterprise/jpi/v1/base_resource/_app_review.json.jbuilder +17 -0
- data/app/views/mno_enterprise/jpi/v1/current_users/show.json.jbuilder +9 -1
- data/app/views/mno_enterprise/jpi/v1/impac/alerts/_alert.json.jbuilder +7 -0
- data/app/views/mno_enterprise/jpi/v1/impac/alerts/index.json.jbuilder +1 -0
- data/app/views/mno_enterprise/jpi/v1/impac/alerts/show.json.jbuilder +1 -0
- data/app/views/mno_enterprise/jpi/v1/impac/dashboards/_dashboard.json.jbuilder +8 -3
- data/app/views/mno_enterprise/jpi/v1/impac/kpis/_kpi.json.jbuilder +4 -1
- data/app/views/mno_enterprise/jpi/v1/impac/widgets/_widget.json.jbuilder +1 -1
- data/app/views/mno_enterprise/jpi/v1/impac/widgets/index.json.jbuilder +3 -0
- data/app/views/mno_enterprise/jpi/v1/marketplace/_app.json.jbuilder +4 -0
- data/app/views/mno_enterprise/jpi/v1/marketplace/index.json.jbuilder +1 -2
- data/app/views/mno_enterprise/jpi/v1/marketplace/show.json.jbuilder +1 -1
- data/app/views/mno_enterprise/jpi/v1/organizations/_current_user.json.jbuilder +1 -1
- data/app/views/mno_enterprise/jpi/v1/organizations/_invoices.json.jbuilder +3 -2
- data/app/views/mno_enterprise/jpi/v1/organizations/_member.json.jbuilder +2 -2
- data/app/views/mno_enterprise/jpi/v1/organizations/_organization.json.jbuilder +2 -2
- data/app/views/mno_enterprise/jpi/v1/teams/_team.json.jbuilder +11 -5
- data/app/views/mno_enterprise/pages/terms.html.haml +219 -0
- data/app/views/mno_enterprise/provision/_select_organization.html.haml +6 -2
- data/config/initializers/devise.rb +31 -9
- data/config/initializers/devise_log.rb +4 -4
- data/config/routes.rb +41 -6
- data/lib/mno_enterprise/api.rb +1 -0
- data/lib/mno_enterprise/audit_events_listener.rb +28 -0
- data/lib/mno_enterprise/concerns/controllers/jpi/v1/app_instances_controller.rb +45 -0
- data/lib/mno_enterprise/concerns/controllers/jpi/v1/current_users_controller.rb +14 -4
- data/lib/mno_enterprise/concerns/controllers/jpi/v1/impac/alerts_controller.rb +76 -0
- data/lib/mno_enterprise/concerns/controllers/jpi/v1/impac/dashboards_controller.rb +49 -23
- data/lib/mno_enterprise/concerns/controllers/jpi/v1/impac/kpis_controller.rb +167 -0
- data/lib/mno_enterprise/concerns/controllers/jpi/v1/impac/widgets_controller.rb +33 -17
- data/lib/mno_enterprise/concerns/controllers/jpi/v1/marketplace_controller.rb +32 -0
- data/lib/mno_enterprise/concerns/controllers/jpi/v1/organizations_controller.rb +68 -28
- data/lib/mno_enterprise/concerns/controllers/jpi/v1/teams_controller.rb +92 -0
- data/lib/mno_enterprise/concerns/controllers/pages_controller.rb +17 -3
- data/lib/mno_enterprise/concerns/controllers/provision_controller.rb +17 -2
- data/lib/mno_enterprise/concerns/mailers/system_notification_mailer.rb +27 -3
- data/lib/mno_enterprise/event_logger.rb +34 -16
- data/lib/mno_enterprise/intercom_events_listener.rb +96 -0
- data/spec/controllers/mno_enterprise/auth/confirmation_controller_spec.rb +28 -0
- data/spec/controllers/mno_enterprise/auth/omniauth_callback_controller_spec.rb +34 -0
- data/spec/controllers/mno_enterprise/jpi/v1/admin/app_answers_controller_spec.rb +45 -0
- data/spec/controllers/mno_enterprise/jpi/v1/admin/app_comments_controller_spec.rb +45 -0
- data/spec/controllers/mno_enterprise/jpi/v1/admin/app_instances_controller_spec.rb +31 -0
- data/spec/controllers/mno_enterprise/jpi/v1/admin/app_reviews_controller_spec.rb +103 -0
- data/spec/controllers/mno_enterprise/jpi/v1/admin/audit_events_controller_spec.rb +4 -15
- data/spec/controllers/mno_enterprise/jpi/v1/admin/cloud_apps_controller_spec.rb +12 -3
- data/spec/controllers/mno_enterprise/jpi/v1/admin/invites_controller_spec.rb +4 -0
- data/spec/controllers/mno_enterprise/jpi/v1/admin/invoices_controller_spec.rb +15 -0
- data/spec/controllers/mno_enterprise/jpi/v1/admin/organizations_controller_spec.rb +17 -1
- data/spec/controllers/mno_enterprise/jpi/v1/admin/tenant_invoices_controller_spec.rb +5 -0
- data/spec/controllers/mno_enterprise/jpi/v1/admin/users_controller_spec.rb +30 -16
- data/spec/controllers/mno_enterprise/jpi/v1/app_answers_controller_spec.rb +74 -0
- data/spec/controllers/mno_enterprise/jpi/v1/app_comments_controller_spec.rb +74 -0
- data/spec/controllers/mno_enterprise/jpi/v1/app_feedbacks_controller_spec.rb +84 -0
- data/spec/controllers/mno_enterprise/jpi/v1/app_instances_controller_spec.rb +36 -22
- data/spec/controllers/mno_enterprise/jpi/v1/app_questions_controller_spec.rb +80 -0
- data/spec/controllers/mno_enterprise/jpi/v1/app_reviews_controller_spec.rb +107 -0
- data/spec/controllers/mno_enterprise/jpi/v1/current_users_controller_spec.rb +16 -1
- data/spec/controllers/mno_enterprise/jpi/v1/impac/alerts_controller_spec.rb +82 -0
- data/spec/controllers/mno_enterprise/jpi/v1/impac/kpis_controller_spec.rb +147 -10
- data/spec/controllers/mno_enterprise/jpi/v1/impac/widgets_controller_spec.rb +39 -0
- data/spec/controllers/mno_enterprise/jpi/v1/marketplace_controller_spec.rb +19 -26
- data/spec/controllers/mno_enterprise/jpi/v1/organizations_controller_spec.rb +248 -303
- data/spec/controllers/mno_enterprise/jpi/v1/team_controller_spec.rb +4 -1
- data/spec/controllers/mno_enterprise/pages_controller_spec.rb +21 -0
- data/spec/controllers/mno_enterprise/provision_controller_spec.rb +65 -22
- data/spec/controllers/mno_enterprise/webhook/o_auth_controller_spec.rb +1 -1
- data/spec/jobs/mno_enterprise/event_logger_job_spec.rb +11 -0
- data/spec/lib/mno_enterprise/audit_events_listener_spec.rb +28 -0
- data/spec/lib/mno_enterprise/intercom_events_listener_spec.rb +110 -0
- data/spec/mailer/mno_enterprise/system_notification_mailer_spec.rb +81 -46
- data/spec/routing/mno_enterprise/jpi/v1/admin/app_instances_controller_routing_spec.rb +11 -0
- data/spec/routing/mno_enterprise/jpi/v1/admin/app_reviews_controller_routing_spec.rb +19 -0
- data/spec/routing/mno_enterprise/jpi/v1/app_instances_controller_routing_spec.rb +9 -2
- data/spec/routing/mno_enterprise/jpi/v1/app_reviews_controller_routing_spec.rb +15 -0
- data/spec/routing/mno_enterprise/jpi/v1/current_users_controller_routing_spec.rb +5 -0
- data/spec/routing/mno_enterprise/jpi/v1/impac/alerts_controller_routing_spec.rb +24 -0
- data/spec/routing/mno_enterprise/jpi/v1/impac/dashboards_controller_routing_spec.rb +28 -0
- data/spec/routing/mno_enterprise/jpi/v1/impac/kpis_controller_routing_spec.rb +17 -11
- data/spec/routing/mno_enterprise/jpi/v1/impac/widgets_controller_routing_spec.rb +24 -0
- data/spec/routing/mno_enterprise/jpi/v1/marketplace_controller_routing_spec.rb +2 -2
- data/spec/routing/mno_enterprise/pages_controller_routing_spec.rb +4 -0
- metadata +178 -9
- data/app/controllers/mno_enterprise/jpi/v1/industry_bundle_controller.rb +0 -25
- data/app/controllers/mno_enterprise/jpi/v1/shopping_cart_controller.rb +0 -93
- 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
|
-
|
27
|
-
MnoEnterprise::EventLogger.info('app_launch', current_user.id,
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
6
|
-
|
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
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
#
|
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
|