mno-enterprise-api 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/LICENSE +1 -0
- data/Rakefile +12 -0
- data/app/assets/javascripts/mno_enterprise/angular/loading-page.app.js.coffee +156 -0
- data/app/assets/javascripts/mno_enterprise/application.js +13 -0
- data/app/controllers/devise/password_expired_controller.rb +55 -0
- data/app/controllers/mno_enterprise/auth/confirmations_controller.rb +5 -0
- data/app/controllers/mno_enterprise/auth/omniauth_callbacks_controller.rb +30 -0
- data/app/controllers/mno_enterprise/auth/passwords_controller.rb +5 -0
- data/app/controllers/mno_enterprise/auth/registrations_controller.rb +5 -0
- data/app/controllers/mno_enterprise/auth/sessions_controller.rb +7 -0
- data/app/controllers/mno_enterprise/auth/unlocks_controller.rb +5 -0
- data/app/controllers/mno_enterprise/deletion_requests_controller.rb +5 -0
- data/app/controllers/mno_enterprise/impersonate_controller.rb +48 -0
- data/app/controllers/mno_enterprise/jpi/v1/admin/audit_events_controller.rb +16 -0
- data/app/controllers/mno_enterprise/jpi/v1/admin/base_resource_controller.rb +5 -0
- data/app/controllers/mno_enterprise/jpi/v1/admin/cloud_apps_controller.rb +46 -0
- data/app/controllers/mno_enterprise/jpi/v1/admin/invoices_controller.rb +47 -0
- data/app/controllers/mno_enterprise/jpi/v1/admin/organizations_controller.rb +27 -0
- data/app/controllers/mno_enterprise/jpi/v1/admin/tenant_invoices_controller.rb +14 -0
- data/app/controllers/mno_enterprise/jpi/v1/admin/users_controller.rb +63 -0
- data/app/controllers/mno_enterprise/jpi/v1/app_instances_controller.rb +24 -0
- data/app/controllers/mno_enterprise/jpi/v1/app_instances_sync_controller.rb +36 -0
- data/app/controllers/mno_enterprise/jpi/v1/base_resource_controller.rb +32 -0
- data/app/controllers/mno_enterprise/jpi/v1/current_users_controller.rb +5 -0
- data/app/controllers/mno_enterprise/jpi/v1/deletion_requests_controller.rb +5 -0
- data/app/controllers/mno_enterprise/jpi/v1/impac/dashboards_controller.rb +5 -0
- data/app/controllers/mno_enterprise/jpi/v1/impac/kpis_controller.rb +80 -0
- data/app/controllers/mno_enterprise/jpi/v1/impac/widgets_controller.rb +63 -0
- data/app/controllers/mno_enterprise/jpi/v1/industry_bundle_controller.rb +25 -0
- data/app/controllers/mno_enterprise/jpi/v1/marketplace_controller.rb +22 -0
- data/app/controllers/mno_enterprise/jpi/v1/organizations_controller.rb +5 -0
- data/app/controllers/mno_enterprise/jpi/v1/shopping_cart_controller.rb +93 -0
- data/app/controllers/mno_enterprise/jpi/v1/teams_controller.rb +88 -0
- data/app/controllers/mno_enterprise/org_invites_controller.rb +5 -0
- data/app/controllers/mno_enterprise/pages_controller.rb +5 -0
- data/app/controllers/mno_enterprise/provision_controller.rb +5 -0
- data/app/controllers/mno_enterprise/status_controller.rb +27 -0
- data/app/controllers/mno_enterprise/webhook/o_auth_controller.rb +5 -0
- data/app/mailers/mno_enterprise/system_notification_mailer.rb +5 -0
- data/app/models/mno_enterprise/health_check.rb +16 -0
- data/app/views/devise/password_expired/show.html.haml +32 -0
- data/app/views/mno_enterprise/auth/confirmations/default/_form.html.haml +49 -0
- data/app/views/mno_enterprise/auth/confirmations/default/_lounge.html.haml +34 -0
- data/app/views/mno_enterprise/auth/confirmations/default/_show.html.haml +10 -0
- data/app/views/mno_enterprise/auth/confirmations/lounge.html.haml +4 -0
- data/app/views/mno_enterprise/auth/confirmations/material/_form.html.haml +44 -0
- data/app/views/mno_enterprise/auth/confirmations/material/_lounge.html.haml +18 -0
- data/app/views/mno_enterprise/auth/confirmations/material/_show.html.haml +21 -0
- data/app/views/mno_enterprise/auth/confirmations/new.html.haml +31 -0
- data/app/views/mno_enterprise/auth/confirmations/show.html.haml +4 -0
- data/app/views/mno_enterprise/auth/mailer/confirmation_instructions.html.haml +4 -0
- data/app/views/mno_enterprise/auth/mailer/reset_password_instructions.html.haml +6 -0
- data/app/views/mno_enterprise/auth/mailer/unlock_instructions.html.haml +5 -0
- data/app/views/mno_enterprise/auth/passwords/edit.html.haml +53 -0
- data/app/views/mno_enterprise/auth/passwords/new.html.haml +34 -0
- data/app/views/mno_enterprise/auth/registrations/default/_form.html.haml +35 -0
- data/app/views/mno_enterprise/auth/registrations/default/_new.html.haml +11 -0
- data/app/views/mno_enterprise/auth/registrations/material/_form.html.haml +30 -0
- data/app/views/mno_enterprise/auth/registrations/material/_new.html.haml +10 -0
- data/app/views/mno_enterprise/auth/registrations/new.html.haml +4 -0
- data/app/views/mno_enterprise/auth/sessions/default/_form.html.haml +17 -0
- data/app/views/mno_enterprise/auth/sessions/default/_new.html.haml +11 -0
- data/app/views/mno_enterprise/auth/sessions/material/_form.html.haml +26 -0
- data/app/views/mno_enterprise/auth/sessions/material/_new.html.haml +11 -0
- data/app/views/mno_enterprise/auth/sessions/new.html.haml +4 -0
- data/app/views/mno_enterprise/auth/shared/_links.html.haml +24 -0
- data/app/views/mno_enterprise/auth/unlocks/new.html.haml +10 -0
- data/app/views/mno_enterprise/deletion_requests/show.html.haml +131 -0
- data/app/views/mno_enterprise/jpi/v1/admin/audit_events/_audit_event.json.jbuilder +5 -0
- data/app/views/mno_enterprise/jpi/v1/admin/audit_events/index.json.jbuilder +4 -0
- data/app/views/mno_enterprise/jpi/v1/admin/cloud_apps/_cloud_app.json.jbuilder +1 -0
- data/app/views/mno_enterprise/jpi/v1/admin/cloud_apps/index.json.jbuilder +1 -0
- data/app/views/mno_enterprise/jpi/v1/admin/cloud_apps/show.json.jbuilder +1 -0
- data/app/views/mno_enterprise/jpi/v1/admin/invoices/_invoice.json.jbuilder +2 -0
- data/app/views/mno_enterprise/jpi/v1/admin/invoices/index.json.jbuilder +1 -0
- data/app/views/mno_enterprise/jpi/v1/admin/invoices/show.json.jbuilder +2 -0
- data/app/views/mno_enterprise/jpi/v1/admin/organizations/_credit_card.json.jbuilder +7 -0
- data/app/views/mno_enterprise/jpi/v1/admin/organizations/_invoices.json.jbuilder +8 -0
- data/app/views/mno_enterprise/jpi/v1/admin/organizations/_member.json.jbuilder +14 -0
- data/app/views/mno_enterprise/jpi/v1/admin/organizations/_organization.json.jbuilder +1 -0
- data/app/views/mno_enterprise/jpi/v1/admin/organizations/in_arrears.json.jbuilder +8 -0
- data/app/views/mno_enterprise/jpi/v1/admin/organizations/index.json.jbuilder +7 -0
- data/app/views/mno_enterprise/jpi/v1/admin/organizations/show.json.jbuilder +11 -0
- data/app/views/mno_enterprise/jpi/v1/admin/tenant_invoices/_tenant_invoice.json.jbuilder +5 -0
- data/app/views/mno_enterprise/jpi/v1/admin/tenant_invoices/index.json.jbuilder +1 -0
- data/app/views/mno_enterprise/jpi/v1/admin/tenant_invoices/show.json.jbuilder +1 -0
- data/app/views/mno_enterprise/jpi/v1/admin/users/_user.json.jbuilder +1 -0
- data/app/views/mno_enterprise/jpi/v1/admin/users/index.json.jbuilder +2 -0
- data/app/views/mno_enterprise/jpi/v1/admin/users/show.json.jbuilder +9 -0
- data/app/views/mno_enterprise/jpi/v1/app_instances/_resource.json.jbuilder +23 -0
- data/app/views/mno_enterprise/jpi/v1/app_instances/index.json.jbuilder +9 -0
- data/app/views/mno_enterprise/jpi/v1/app_instances/show.json.jbuilder +3 -0
- data/app/views/mno_enterprise/jpi/v1/billing/index.json.jbuilder +0 -0
- data/app/views/mno_enterprise/jpi/v1/current_users/show.json.jbuilder +37 -0
- data/app/views/mno_enterprise/jpi/v1/impac/dashboards/_dashboard.json.jbuilder +9 -0
- data/app/views/mno_enterprise/jpi/v1/impac/dashboards/index.json.jbuilder +1 -0
- data/app/views/mno_enterprise/jpi/v1/impac/dashboards/show.json.jbuilder +1 -0
- data/app/views/mno_enterprise/jpi/v1/impac/kpis/_kpi.json.jbuilder +1 -0
- data/app/views/mno_enterprise/jpi/v1/impac/kpis/show.json.jbuilder +1 -0
- data/app/views/mno_enterprise/jpi/v1/impac/widgets/_widget.json.jbuilder +6 -0
- data/app/views/mno_enterprise/jpi/v1/impac/widgets/show.json.jbuilder +1 -0
- data/app/views/mno_enterprise/jpi/v1/marketplace/_app.json.jbuilder +14 -0
- data/app/views/mno_enterprise/jpi/v1/marketplace/index.json.jbuilder +3 -0
- data/app/views/mno_enterprise/jpi/v1/marketplace/show.json.jbuilder +3 -0
- data/app/views/mno_enterprise/jpi/v1/organizations/_arrears.json.jbuilder +11 -0
- data/app/views/mno_enterprise/jpi/v1/organizations/_billing.json.jbuilder +4 -0
- data/app/views/mno_enterprise/jpi/v1/organizations/_credit_card.json.jbuilder +7 -0
- data/app/views/mno_enterprise/jpi/v1/organizations/_current_user.json.jbuilder +5 -0
- data/app/views/mno_enterprise/jpi/v1/organizations/_invoices.json.jbuilder +8 -0
- data/app/views/mno_enterprise/jpi/v1/organizations/_member.json.jbuilder +13 -0
- data/app/views/mno_enterprise/jpi/v1/organizations/_organization.json.jbuilder +13 -0
- data/app/views/mno_enterprise/jpi/v1/organizations/credit_card.json.jbuilder +1 -0
- data/app/views/mno_enterprise/jpi/v1/organizations/index.json.jbuilder +1 -0
- data/app/views/mno_enterprise/jpi/v1/organizations/members.json.jbuilder +3 -0
- data/app/views/mno_enterprise/jpi/v1/organizations/show.json.jbuilder +15 -0
- data/app/views/mno_enterprise/jpi/v1/organizations/show_reduced.json.jbuilder +3 -0
- data/app/views/mno_enterprise/jpi/v1/shopping_cart/organizations.json.jbuilder +5 -0
- data/app/views/mno_enterprise/jpi/v1/shopping_cart/show.json.jbuilder +59 -0
- data/app/views/mno_enterprise/jpi/v1/shopping_cart/show_item.json.jbuilder +34 -0
- data/app/views/mno_enterprise/jpi/v1/teams/_team.json.jbuilder +20 -0
- data/app/views/mno_enterprise/jpi/v1/teams/index.json.jbuilder +1 -0
- data/app/views/mno_enterprise/jpi/v1/teams/show.json.jbuilder +3 -0
- data/app/views/mno_enterprise/pages/app_access_unauthorized.html.haml +19 -0
- data/app/views/mno_enterprise/pages/app_logout.html.haml +18 -0
- data/app/views/mno_enterprise/pages/billing_details_required.html.haml +19 -0
- data/app/views/mno_enterprise/pages/loading.html.erb +69 -0
- data/app/views/mno_enterprise/provision/_provision_apps.html.haml +42 -0
- data/app/views/mno_enterprise/provision/_select_organization.html.haml +17 -0
- data/app/views/mno_enterprise/provision/new.html.haml +4 -0
- data/app/views/mno_enterprise/webhook/o_auth/authorize.html.haml +26 -0
- data/app/views/mno_enterprise/webhook/o_auth/providers/myob.html.haml +29 -0
- data/app/views/mno_enterprise/webhook/o_auth/providers/xero.html.haml +34 -0
- data/config/initializers/devise.rb +273 -0
- data/config/initializers/devise_extension.rb +9 -0
- data/config/initializers/devise_log.rb +12 -0
- data/config/initializers/health_check.rb +35 -0
- data/config/initializers/main_app_version.rb +6 -0
- data/config/routes.rb +152 -0
- data/lib/mno-enterprise-api.rb +1 -0
- data/lib/mno_enterprise/api.rb +14 -0
- data/lib/mno_enterprise/api/engine.rb +9 -0
- data/lib/mno_enterprise/concerns/controllers/deletion_requests_controller.rb +108 -0
- data/lib/mno_enterprise/concerns/controllers/jpi/v1/admin/base_resource_controller.rb +34 -0
- data/lib/mno_enterprise/concerns/controllers/jpi/v1/current_users_controller.rb +58 -0
- data/lib/mno_enterprise/concerns/controllers/jpi/v1/deletion_requests_controller.rb +69 -0
- data/lib/mno_enterprise/concerns/controllers/jpi/v1/impac/dashboards_controller.rb +76 -0
- data/lib/mno_enterprise/concerns/controllers/jpi/v1/organizations_controller.rb +180 -0
- data/lib/mno_enterprise/concerns/controllers/org_invites_controller.rb +44 -0
- data/lib/mno_enterprise/concerns/controllers/pages_controller.rb +78 -0
- data/lib/mno_enterprise/concerns/controllers/provision_controller.rb +71 -0
- data/lib/mno_enterprise/concerns/controllers/webhook/o_auth_controller.rb +107 -0
- data/lib/mno_enterprise/concerns/mailers/system_notification_mailer.rb +158 -0
- data/lib/mno_enterprise/event_logger.rb +32 -0
- data/spec/controllers/mno_enterprise/auth/confirmation_controller_spec.rb +68 -0
- data/spec/controllers/mno_enterprise/deletion_requests_controller_spec.rb +141 -0
- data/spec/controllers/mno_enterprise/impersonate_controller_spec.rb +48 -0
- data/spec/controllers/mno_enterprise/jpi/v1/admin/audit_events_controller_spec.rb +51 -0
- data/spec/controllers/mno_enterprise/jpi/v1/admin/cloud_apps_controller_spec.rb +92 -0
- data/spec/controllers/mno_enterprise/jpi/v1/admin/invoices_controller_spec.rb +159 -0
- data/spec/controllers/mno_enterprise/jpi/v1/admin/organizations_controller_spec.rb +116 -0
- data/spec/controllers/mno_enterprise/jpi/v1/admin/tenant_invoices_controller_spec.rb +92 -0
- data/spec/controllers/mno_enterprise/jpi/v1/admin/users_controller_spec.rb +136 -0
- data/spec/controllers/mno_enterprise/jpi/v1/app_instances_controller_spec.rb +76 -0
- data/spec/controllers/mno_enterprise/jpi/v1/app_instances_sync_controller_spec.rb +94 -0
- data/spec/controllers/mno_enterprise/jpi/v1/current_users_controller_spec.rb +128 -0
- data/spec/controllers/mno_enterprise/jpi/v1/deletion_requests_controller_spec.rb +72 -0
- data/spec/controllers/mno_enterprise/jpi/v1/impac/kpis_controller_spec.rb +80 -0
- data/spec/controllers/mno_enterprise/jpi/v1/marketplace_controller_spec.rb +115 -0
- data/spec/controllers/mno_enterprise/jpi/v1/organizations_controller_spec.rb +516 -0
- data/spec/controllers/mno_enterprise/jpi/v1/team_controller_spec.rb +86 -0
- data/spec/controllers/mno_enterprise/org_invites_controller_spec.rb +29 -0
- data/spec/controllers/mno_enterprise/pages_controller_spec.rb +49 -0
- data/spec/controllers/mno_enterprise/provision_controller_spec.rb +94 -0
- data/spec/controllers/mno_enterprise/status_controller_spec.rb +34 -0
- data/spec/controllers/mno_enterprise/webhook/o_auth_controller_spec.rb +104 -0
- data/spec/lib/mno_enterprise/event_logger_spec.rb +28 -0
- data/spec/mailer/mno_enterprise/system_notification_mailer_spec.rb +132 -0
- data/spec/rails_helper.rb +94 -0
- data/spec/requests/devise/authentication_spec.rb +43 -0
- data/spec/requests/devise/registration_spec.rb +64 -0
- data/spec/routing/devise/confirmation_routing_spec.rb +20 -0
- data/spec/routing/devise/passwords_routing_spec.rb +24 -0
- data/spec/routing/devise/registrations_routing_spec.rb +16 -0
- data/spec/routing/devise/sessions_routing_spec.rb +20 -0
- data/spec/routing/mno_enterprise/deletion_requests_controller_routing_spec.rb +20 -0
- data/spec/routing/mno_enterprise/impersonate_controller_routing.spec.rb +15 -0
- data/spec/routing/mno_enterprise/jpi/v1/admin/audit_events_controller_routing_spec.rb +11 -0
- data/spec/routing/mno_enterprise/jpi/v1/admin/cloud_apps_controller_routing_spec.rb +24 -0
- data/spec/routing/mno_enterprise/jpi/v1/admin/invoices_controller_routing_spec.rb +37 -0
- data/spec/routing/mno_enterprise/jpi/v1/admin/organizations_controller_routing_spec.rb +20 -0
- data/spec/routing/mno_enterprise/jpi/v1/admin/tenant_invoices_controller_routing_spec.rb +16 -0
- data/spec/routing/mno_enterprise/jpi/v1/admin/users_controller_routing_spec.rb +24 -0
- data/spec/routing/mno_enterprise/jpi/v1/app_instances_controller_routing_spec.rb +12 -0
- data/spec/routing/mno_enterprise/jpi/v1/app_instances_sync_controller_routing_spec.rb +15 -0
- data/spec/routing/mno_enterprise/jpi/v1/current_users_controller_routing_spec.rb +28 -0
- data/spec/routing/mno_enterprise/jpi/v1/deletion_requests_controller_routing_spec.rb +24 -0
- data/spec/routing/mno_enterprise/jpi/v1/impac/kpis_controller_routing_spec.rb +22 -0
- data/spec/routing/mno_enterprise/jpi/v1/marketplace_controller_routing_spec.rb +16 -0
- data/spec/routing/mno_enterprise/jpi/v1/organizations_controller_routing_spec.rb +44 -0
- data/spec/routing/mno_enterprise/jpi/v1/teams_controller_routing_spec.rb +36 -0
- data/spec/routing/mno_enterprise/org_invites_controller_routing_spec.rb +12 -0
- data/spec/routing/mno_enterprise/pages_controller_routing_spec.rb +29 -0
- data/spec/routing/mno_enterprise/provision_controller_routing_spec.rb +15 -0
- data/spec/routing/mno_enterprise/status_controller_routing_spec.rb +19 -0
- data/spec/routing/mno_enterprise/webhook/o_auth_controller_routing_spec.rb +27 -0
- data/spec/spec_helper.rb +88 -0
- metadata +402 -0
@@ -0,0 +1,71 @@
|
|
1
|
+
module MnoEnterprise::Concerns::Controllers::ProvisionController
|
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
|
+
before_filter :authenticate_user_or_signup!
|
11
|
+
|
12
|
+
protected
|
13
|
+
# The path used after purchased apps have been provisionned
|
14
|
+
def after_provision_path
|
15
|
+
# MySpace only defined in frontend
|
16
|
+
# This should be overriden by the main app when not loading frontend
|
17
|
+
if mno_enterprise.respond_to?(:myspace_path)
|
18
|
+
mno_enterprise.myspace_path(anchor: '/')
|
19
|
+
else
|
20
|
+
main_app.root_path
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
helper_method :after_provision_path # To use in the provision view
|
25
|
+
end
|
26
|
+
|
27
|
+
#==================================================================
|
28
|
+
# Class methods
|
29
|
+
#==================================================================
|
30
|
+
module ClassMethods
|
31
|
+
# def some_class_method
|
32
|
+
# 'some text'
|
33
|
+
# end
|
34
|
+
end
|
35
|
+
|
36
|
+
#==================================================================
|
37
|
+
# Instance methods
|
38
|
+
#==================================================================
|
39
|
+
# GET /provision/new?apps[]=vtiger&organization_id=1
|
40
|
+
# TODO: check organization accessibility via ability
|
41
|
+
def new
|
42
|
+
@apps = params[:apps]
|
43
|
+
@organizations = current_user.organizations.to_a
|
44
|
+
@organization = @organizations.find { |o| o.id && o.id.to_s == params[:organization_id].to_s }
|
45
|
+
|
46
|
+
unless @organization
|
47
|
+
@organization = @organizations.one? ? @organizations.first : nil
|
48
|
+
end
|
49
|
+
authorize! :manage_app_instances, @organization
|
50
|
+
|
51
|
+
# Redirect to dashboard if no applications
|
52
|
+
unless @apps && @apps.any?
|
53
|
+
redirect_to after_provision_path
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
# POST /provision
|
58
|
+
# TODO: check organization accessibility via ability
|
59
|
+
def create
|
60
|
+
@organization = current_user.organizations.to_a.find { |o| o.id && o.id.to_s == params[:organization_id].to_s }
|
61
|
+
authorize! :manage_app_instances, @organization
|
62
|
+
|
63
|
+
app_instances = []
|
64
|
+
params[:apps].each do |product_name|
|
65
|
+
app_instances << @organization.app_instances.create(product: product_name)
|
66
|
+
end
|
67
|
+
|
68
|
+
render json: app_instances.map(&:attributes).to_json, status: :created
|
69
|
+
end
|
70
|
+
|
71
|
+
end
|
@@ -0,0 +1,107 @@
|
|
1
|
+
module MnoEnterprise::Concerns::Controllers::Webhook::OAuthController
|
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
|
+
before_filter :authenticate_user!, only: [:authorize, :disconnect, :sync]
|
11
|
+
before_filter :redirect_to_lounge_if_unconfirmed
|
12
|
+
before_filter :check_permissions, only: [:authorize, :disconnect, :sync]
|
13
|
+
|
14
|
+
PROVIDERS_WITH_OPTIONS = ['xero','myob']
|
15
|
+
|
16
|
+
private
|
17
|
+
def app_instance
|
18
|
+
@app_instance ||= MnoEnterprise::AppInstance.where(uid: params[:id]).first
|
19
|
+
end
|
20
|
+
|
21
|
+
# Redirect with an error if user is unauthorized
|
22
|
+
def check_permissions
|
23
|
+
unless can?(:manage_app_instances, app_instance.owner)
|
24
|
+
redirect_to mnoe_home_path, alert: "You are not authorized to perform this action"
|
25
|
+
return false
|
26
|
+
end
|
27
|
+
true
|
28
|
+
end
|
29
|
+
|
30
|
+
# Return a hash of extra parameters that were passed along with
|
31
|
+
# the request
|
32
|
+
def extra_params
|
33
|
+
params.reject { |k,v| [:controller,:action,:id, :perform].include?(k.to_sym) }
|
34
|
+
end
|
35
|
+
|
36
|
+
# Current user web token
|
37
|
+
def wtk
|
38
|
+
MnoEnterprise.jwt(user_id: current_user.uid)
|
39
|
+
end
|
40
|
+
|
41
|
+
# Append params to the fragment part of an existing url String
|
42
|
+
# add_param("/#/platform/accounts", 'foo', 'bar')
|
43
|
+
# => "/#/platform/accounts?foo=bar"
|
44
|
+
# add_param("/#/platform/dashboard/he/43?en=690", 'foo', 'bar')
|
45
|
+
# => "/#/platform/dashboard/he/43?en=690&foo=bar"
|
46
|
+
def add_param_to_fragment(url, param_name, param_value)
|
47
|
+
uri = URI(url)
|
48
|
+
fragment = URI(uri.fragment || "")
|
49
|
+
params = URI.decode_www_form(fragment.query || "") << [param_name, param_value]
|
50
|
+
fragment.query = URI.encode_www_form(params)
|
51
|
+
uri.fragment = fragment.to_s
|
52
|
+
uri.to_s
|
53
|
+
end
|
54
|
+
|
55
|
+
def error_message(error_key)
|
56
|
+
case error_key.to_sym
|
57
|
+
when :bad_relinking
|
58
|
+
%{A different account "#{app_instance.oauth_company}" was previously linked to this application, please re-link the same account.}
|
59
|
+
when :unauthorized
|
60
|
+
'We could not validate your credentials, please try again'
|
61
|
+
else
|
62
|
+
error_key
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
#==================================================================
|
68
|
+
# Instance methods
|
69
|
+
#==================================================================
|
70
|
+
# GET /mnoe/webhook/oauth/:id/authorize
|
71
|
+
def authorize
|
72
|
+
if params[:redirect_path].present?
|
73
|
+
session[:redirect_path] = params[:redirect_path]
|
74
|
+
end
|
75
|
+
|
76
|
+
# Certain providers require options to be selected
|
77
|
+
if !params[:perform] && app_instance.app && PROVIDERS_WITH_OPTIONS.include?(app_instance.app.nid.to_s)
|
78
|
+
render "mno_enterprise/webhook/o_auth/providers/#{app_instance.app.nid}"
|
79
|
+
return
|
80
|
+
end
|
81
|
+
|
82
|
+
@redirect_to = MnoEnterprise.router.authorize_oauth_url(params[:id], extra_params.merge(wtk: wtk))
|
83
|
+
end
|
84
|
+
|
85
|
+
# GET /mnoe/webhook/oauth/:id/callback
|
86
|
+
def callback
|
87
|
+
path = session.delete(:redirect_path).presence || mnoe_home_path
|
88
|
+
|
89
|
+
if error_key = params.fetch(:oauth, {})[:error]
|
90
|
+
|
91
|
+
path = add_param_to_fragment(path.to_s, 'flash', [{msg: error_message(error_key), type: :error}.to_json])
|
92
|
+
end
|
93
|
+
|
94
|
+
redirect_to path
|
95
|
+
end
|
96
|
+
|
97
|
+
# GET /mnoe/webhook/oauth/:id/disconnect
|
98
|
+
def disconnect
|
99
|
+
redirect_to MnoEnterprise.router.disconnect_oauth_url(params[:id], extra_params.merge(wtk: wtk))
|
100
|
+
end
|
101
|
+
|
102
|
+
# GET /mnoe/webhook/oauth/:id/sync
|
103
|
+
def sync
|
104
|
+
redirect_to MnoEnterprise.router.sync_oauth_url(params[:id], extra_params.merge(wtk: wtk))
|
105
|
+
end
|
106
|
+
|
107
|
+
end
|
@@ -0,0 +1,158 @@
|
|
1
|
+
module MnoEnterprise::Concerns::Mailers::SystemNotificationMailer
|
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
|
+
helper :application
|
11
|
+
DEFAULT_SENDER = { name: MnoEnterprise.default_sender_name, email: MnoEnterprise.default_sender_email }
|
12
|
+
end
|
13
|
+
|
14
|
+
#==================================================================
|
15
|
+
# Instance methods
|
16
|
+
#==================================================================
|
17
|
+
|
18
|
+
# Default email sender
|
19
|
+
# Override to allow dynamic sender
|
20
|
+
def default_sender
|
21
|
+
DEFAULT_SENDER
|
22
|
+
end
|
23
|
+
|
24
|
+
# ==> Devise Email
|
25
|
+
# Description:
|
26
|
+
# Email asking users to confirm their email
|
27
|
+
#
|
28
|
+
# Mandrill vars:
|
29
|
+
# :first_name
|
30
|
+
# :last_name
|
31
|
+
# :full_name
|
32
|
+
# :confirmation_link
|
33
|
+
#
|
34
|
+
def confirmation_instructions(record, token, opts={})
|
35
|
+
template = record.confirmed? && record.unconfirmed_email? ? 'reconfirmation-instructions' : 'confirmation-instructions'
|
36
|
+
MandrillClient.deliver(template,
|
37
|
+
default_sender,
|
38
|
+
recipient(record),
|
39
|
+
user_vars(record).merge(confirmation_link: user_confirmation_url(confirmation_token: token))
|
40
|
+
)
|
41
|
+
end
|
42
|
+
|
43
|
+
# ==> Devise Email
|
44
|
+
# Description:
|
45
|
+
# Email providing instructions + link to reset password
|
46
|
+
#
|
47
|
+
# Mandrill vars:
|
48
|
+
# :first_name
|
49
|
+
# :last_name
|
50
|
+
# :full_name
|
51
|
+
# :reset_password_link
|
52
|
+
#
|
53
|
+
def reset_password_instructions(record, token, opts={})
|
54
|
+
MandrillClient.deliver('reset-password-instructions',
|
55
|
+
default_sender,
|
56
|
+
recipient(record),
|
57
|
+
user_vars(record).merge(reset_password_link: edit_user_password_url(reset_password_token: token))
|
58
|
+
)
|
59
|
+
end
|
60
|
+
|
61
|
+
# ==> Devise Email
|
62
|
+
# Description:
|
63
|
+
# Email providing instructions + link to unlock a user account after too many failed attempts
|
64
|
+
#
|
65
|
+
# Mandrill vars:
|
66
|
+
# :first_name
|
67
|
+
# :last_name
|
68
|
+
# :full_name
|
69
|
+
# :unlock_link
|
70
|
+
#
|
71
|
+
def unlock_instructions(record, token, opts={})
|
72
|
+
MandrillClient.deliver('unlock-instructions',
|
73
|
+
default_sender,
|
74
|
+
recipient(record),
|
75
|
+
user_vars(record).merge(unlock_link: user_unlock_url(unlock_token: token))
|
76
|
+
)
|
77
|
+
end
|
78
|
+
|
79
|
+
# Description:
|
80
|
+
# Send an email inviting the user to join an existing organization. If the user
|
81
|
+
# is already confirmed it is directed to the organization invite page where he
|
82
|
+
# can accept or decline the invite
|
83
|
+
# If the user is not confirmed yet then it is considered a new user and will be directed
|
84
|
+
# to the confirmation page
|
85
|
+
#
|
86
|
+
# Mandrill vars:
|
87
|
+
# :organization
|
88
|
+
# :team
|
89
|
+
# :ref_first_name
|
90
|
+
# :ref_last_name
|
91
|
+
# :ref_full_name
|
92
|
+
# :ref_email
|
93
|
+
# :invitee_first_name
|
94
|
+
# :invitee_last_name
|
95
|
+
# :invitee_full_name
|
96
|
+
# :invitee_email
|
97
|
+
# :confirmation_link
|
98
|
+
#
|
99
|
+
def organization_invite(org_invite)
|
100
|
+
new_user = !org_invite.user.confirmed?
|
101
|
+
confirmation_link = new_user ? user_confirmation_url(confirmation_token: org_invite.user.confirmation_token) : org_invite_url(org_invite, token: org_invite.token)
|
102
|
+
email_template = new_user ? 'organization-invite-new-user' : 'organization-invite-existing-user'
|
103
|
+
|
104
|
+
MandrillClient.deliver(email_template,
|
105
|
+
default_sender,
|
106
|
+
recipient(org_invite.user,new_user),
|
107
|
+
invite_vars(org_invite,new_user).merge(confirmation_link: confirmation_link)
|
108
|
+
)
|
109
|
+
end
|
110
|
+
|
111
|
+
# Description:
|
112
|
+
# Email providing instructions + link to initiate the account termination
|
113
|
+
# process.
|
114
|
+
#
|
115
|
+
# Mandrill vars:
|
116
|
+
# :first_name
|
117
|
+
# :last_name
|
118
|
+
# :full_name
|
119
|
+
# :terminate_account_link
|
120
|
+
def deletion_request_instructions(record, deletion_request)
|
121
|
+
MandrillClient.deliver('deletion-request-instructions',
|
122
|
+
default_sender,
|
123
|
+
recipient(record),
|
124
|
+
user_vars(record).merge(terminate_account_link: deletion_request_url(deletion_request))
|
125
|
+
)
|
126
|
+
end
|
127
|
+
|
128
|
+
protected
|
129
|
+
|
130
|
+
def recipient(record, new_user = false)
|
131
|
+
hash = { email: record.email }
|
132
|
+
hash[:name] = "#{record.name} #{record.surname}".strip unless new_user
|
133
|
+
hash
|
134
|
+
end
|
135
|
+
|
136
|
+
def user_vars(record)
|
137
|
+
{
|
138
|
+
first_name: record.name,
|
139
|
+
last_name: record.surname,
|
140
|
+
full_name: "#{record.name} #{record.surname}".strip
|
141
|
+
}
|
142
|
+
end
|
143
|
+
|
144
|
+
def invite_vars(org_invite, new_user = true)
|
145
|
+
{
|
146
|
+
organization: org_invite.organization.name,
|
147
|
+
team: org_invite.team.present? ? org_invite.team.name : nil,
|
148
|
+
ref_first_name: org_invite.referrer.name,
|
149
|
+
ref_last_name: org_invite.referrer.surname,
|
150
|
+
ref_full_name: "#{org_invite.referrer.name} #{org_invite.referrer.surname}".strip,
|
151
|
+
ref_email: org_invite.referrer.email,
|
152
|
+
invitee_first_name: new_user ? nil : org_invite.user.name,
|
153
|
+
invitee_last_name: new_user ? nil : org_invite.user.surname,
|
154
|
+
invitee_full_name: new_user ? nil : "#{org_invite.user.name} #{org_invite.user.surname}".strip,
|
155
|
+
invitee_email: org_invite.user.email,
|
156
|
+
}
|
157
|
+
end
|
158
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'httparty'
|
2
|
+
|
3
|
+
module MnoEnterprise
|
4
|
+
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
|
9
|
+
|
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
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.format_metadata(metadata, object)
|
25
|
+
if metadata.blank? && object.respond_to?(:to_audit_event)
|
26
|
+
object.to_audit_event
|
27
|
+
else
|
28
|
+
metadata
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
require 'rails_helper'
|
2
|
+
|
3
|
+
module MnoEnterprise
|
4
|
+
describe Auth::ConfirmationsController, type: :controller do
|
5
|
+
routes { MnoEnterprise::Engine.routes }
|
6
|
+
|
7
|
+
before { @request.env['devise.mapping'] = Devise.mappings[:user] }
|
8
|
+
|
9
|
+
let(:unconfirmed_user) { build(:user, :unconfirmed, organizations: [])}
|
10
|
+
let(:confirmed_user) { build(:user, organizations: [])}
|
11
|
+
|
12
|
+
|
13
|
+
describe 'GET #show' do
|
14
|
+
subject { get :show, confirmation_token: user.confirmation_token }
|
15
|
+
|
16
|
+
before do
|
17
|
+
allow(MnoEnterprise::User).to receive(:find_for_confirmation) { user }
|
18
|
+
allow(user).to receive(:save)
|
19
|
+
end
|
20
|
+
|
21
|
+
context 'unconfirmed user' do
|
22
|
+
let(:user) { unconfirmed_user }
|
23
|
+
|
24
|
+
it 'does not sign in the user' do
|
25
|
+
subject
|
26
|
+
expect(controller.current_user).to be_nil
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'render the template' do
|
30
|
+
expect(subject).to render_template('show')
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
context 'confirmed user' do
|
35
|
+
let(:user) { confirmed_user }
|
36
|
+
|
37
|
+
context 'with a new email' do
|
38
|
+
let(:email) { 'unconfirmed@example.com' }
|
39
|
+
|
40
|
+
before do
|
41
|
+
user.unconfirmed_email = email
|
42
|
+
|
43
|
+
api_stub_for(get: "/users?filter[email]=#{email}&limit=1", response: from_api(nil))
|
44
|
+
api_stub_for(get: "/org_invites?filter[user_email]=#{email}", response: from_api(nil))
|
45
|
+
end
|
46
|
+
|
47
|
+
it 'sign in the user' do
|
48
|
+
subject
|
49
|
+
expect(controller.current_user).to eq(user)
|
50
|
+
end
|
51
|
+
|
52
|
+
it 'redirects to the dashboard' do
|
53
|
+
expect(subject).to redirect_to(controller.signed_in_root_path(user))
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
it 'does not sign in the user' do
|
58
|
+
subject
|
59
|
+
expect(controller.current_user).to be_nil
|
60
|
+
end
|
61
|
+
|
62
|
+
it 'returns an error' do
|
63
|
+
expect(subject).to render_template("new")
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
@@ -0,0 +1,141 @@
|
|
1
|
+
require 'rails_helper'
|
2
|
+
|
3
|
+
# TODO: DRY Specs with shared examples
|
4
|
+
module MnoEnterprise
|
5
|
+
describe DeletionRequestsController, type: :controller do
|
6
|
+
render_views
|
7
|
+
routes { MnoEnterprise::Engine.routes }
|
8
|
+
|
9
|
+
# Stub controller ability
|
10
|
+
let!(:ability) { stub_ability }
|
11
|
+
before { allow(ability).to receive(:can?).with(any_args).and_return(true) }
|
12
|
+
|
13
|
+
# Stub model calls
|
14
|
+
let(:deletion_req) { build(:deletion_request) }
|
15
|
+
let(:user) { build(:user, deletion_request: deletion_req) }
|
16
|
+
|
17
|
+
before do
|
18
|
+
api_stub_for(get: "/users/#{user.id}", response: from_api(user))
|
19
|
+
api_stub_for(get: "/users/#{user.id}/deletion_request", response: from_api(user))
|
20
|
+
end
|
21
|
+
|
22
|
+
describe "GET #show'" do
|
23
|
+
before { sign_in user }
|
24
|
+
subject { get :show, id: deletion_req.token }
|
25
|
+
|
26
|
+
# TODO: use behavior
|
27
|
+
it_behaves_like "a navigatable protected user action"
|
28
|
+
# it_behaves_like "a user protected resource"
|
29
|
+
|
30
|
+
context 'when no current_request' do
|
31
|
+
let(:user) { build(:user, deletion_request: nil) }
|
32
|
+
|
33
|
+
it 'redirects to the root_path' do
|
34
|
+
subject
|
35
|
+
expect(response).to redirect_to(main_app.root_path)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
context 'when not the current request' do
|
40
|
+
let(:new_deletion_req) { build(:deletion_request) }
|
41
|
+
let(:user) { build(:user, deletion_request: new_deletion_req) }
|
42
|
+
|
43
|
+
it 'redirects to the root_path' do
|
44
|
+
subject
|
45
|
+
expect(response).to redirect_to(main_app.root_path)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
describe "PUT #freeze_account" do
|
51
|
+
# before { api_stub_for(get: "/deletion_requests/#{deletion_req.id}", response: from_api(deletion_req)) }
|
52
|
+
before { api_stub_for(put: "/deletion_requests/#{deletion_req.id}", response: from_api(deletion_req)) }
|
53
|
+
|
54
|
+
before { sign_in user }
|
55
|
+
subject { put :freeze_account, id: deletion_req.token }
|
56
|
+
|
57
|
+
# TODO: use behavior
|
58
|
+
it_behaves_like "a navigatable protected user action"
|
59
|
+
|
60
|
+
context 'when the request is pending' do
|
61
|
+
it 'freezes the account' do
|
62
|
+
expect(controller.current_user).to receive(:deletion_request).and_return(deletion_req)
|
63
|
+
expect(deletion_req).to receive(:freeze_account!)
|
64
|
+
subject
|
65
|
+
end
|
66
|
+
|
67
|
+
it 'redirects to the deletion request' do
|
68
|
+
subject
|
69
|
+
expect(response).to redirect_to(deletion_request_url(deletion_req))
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
context 'when the request is not pending' do
|
74
|
+
let(:deletion_req) { build(:deletion_request, status: 'account_frozen') }
|
75
|
+
|
76
|
+
it 'does not freezes the account' do
|
77
|
+
expect_any_instance_of(MnoEnterprise::DeletionRequest).not_to receive(:freeze_account!)
|
78
|
+
subject
|
79
|
+
end
|
80
|
+
|
81
|
+
it 'redirects to the deletion request' do
|
82
|
+
subject
|
83
|
+
expect(response).to redirect_to(deletion_request_url(deletion_req))
|
84
|
+
end
|
85
|
+
|
86
|
+
it 'displays an error message' do
|
87
|
+
subject
|
88
|
+
expect(flash[:alert]).to eq("Invalid action")
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
context 'when no valid request' do
|
93
|
+
let(:user) { build(:user, deletion_request: nil) }
|
94
|
+
it 'redirects to the root_path' do
|
95
|
+
subject
|
96
|
+
expect(response).to redirect_to(main_app.root_path)
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
end
|
101
|
+
|
102
|
+
describe "PUT #checkout" do
|
103
|
+
before { api_stub_for(put: "/deletion_requests/#{deletion_req.id}", response: from_api(deletion_req)) }
|
104
|
+
|
105
|
+
before { sign_in user }
|
106
|
+
subject { put :checkout, id: deletion_req.token }
|
107
|
+
|
108
|
+
# TODO: use behavior
|
109
|
+
it_behaves_like "a navigatable protected user action"
|
110
|
+
|
111
|
+
context 'when the request is not account_frozen' do
|
112
|
+
let(:deletion_req) { build(:deletion_request, status: 'pending') }
|
113
|
+
|
114
|
+
# it 'does not freezes the account' do
|
115
|
+
# expect_any_instance_of(MnoEnterprise::DeletionRequest).not_to receive(:freeze_account!)
|
116
|
+
# subject
|
117
|
+
# end
|
118
|
+
|
119
|
+
it 'redirects to the deletion request' do
|
120
|
+
subject
|
121
|
+
expect(response).to redirect_to(deletion_request_url(deletion_req))
|
122
|
+
end
|
123
|
+
|
124
|
+
it 'displays an error message' do
|
125
|
+
subject
|
126
|
+
expect(flash[:alert]).to eq("Invalid action")
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
context 'when no valid request' do
|
131
|
+
let(:user) { build(:user, deletion_request: nil) }
|
132
|
+
it 'redirects to the root_path' do
|
133
|
+
subject
|
134
|
+
expect(response).to redirect_to(main_app.root_path)
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
describe "PUT #terminate"
|
140
|
+
end
|
141
|
+
end
|