mno-enterprise-api 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (208) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +1 -0
  3. data/Rakefile +12 -0
  4. data/app/assets/javascripts/mno_enterprise/angular/loading-page.app.js.coffee +156 -0
  5. data/app/assets/javascripts/mno_enterprise/application.js +13 -0
  6. data/app/controllers/devise/password_expired_controller.rb +55 -0
  7. data/app/controllers/mno_enterprise/auth/confirmations_controller.rb +5 -0
  8. data/app/controllers/mno_enterprise/auth/omniauth_callbacks_controller.rb +30 -0
  9. data/app/controllers/mno_enterprise/auth/passwords_controller.rb +5 -0
  10. data/app/controllers/mno_enterprise/auth/registrations_controller.rb +5 -0
  11. data/app/controllers/mno_enterprise/auth/sessions_controller.rb +7 -0
  12. data/app/controllers/mno_enterprise/auth/unlocks_controller.rb +5 -0
  13. data/app/controllers/mno_enterprise/deletion_requests_controller.rb +5 -0
  14. data/app/controllers/mno_enterprise/impersonate_controller.rb +48 -0
  15. data/app/controllers/mno_enterprise/jpi/v1/admin/audit_events_controller.rb +16 -0
  16. data/app/controllers/mno_enterprise/jpi/v1/admin/base_resource_controller.rb +5 -0
  17. data/app/controllers/mno_enterprise/jpi/v1/admin/cloud_apps_controller.rb +46 -0
  18. data/app/controllers/mno_enterprise/jpi/v1/admin/invoices_controller.rb +47 -0
  19. data/app/controllers/mno_enterprise/jpi/v1/admin/organizations_controller.rb +27 -0
  20. data/app/controllers/mno_enterprise/jpi/v1/admin/tenant_invoices_controller.rb +14 -0
  21. data/app/controllers/mno_enterprise/jpi/v1/admin/users_controller.rb +63 -0
  22. data/app/controllers/mno_enterprise/jpi/v1/app_instances_controller.rb +24 -0
  23. data/app/controllers/mno_enterprise/jpi/v1/app_instances_sync_controller.rb +36 -0
  24. data/app/controllers/mno_enterprise/jpi/v1/base_resource_controller.rb +32 -0
  25. data/app/controllers/mno_enterprise/jpi/v1/current_users_controller.rb +5 -0
  26. data/app/controllers/mno_enterprise/jpi/v1/deletion_requests_controller.rb +5 -0
  27. data/app/controllers/mno_enterprise/jpi/v1/impac/dashboards_controller.rb +5 -0
  28. data/app/controllers/mno_enterprise/jpi/v1/impac/kpis_controller.rb +80 -0
  29. data/app/controllers/mno_enterprise/jpi/v1/impac/widgets_controller.rb +63 -0
  30. data/app/controllers/mno_enterprise/jpi/v1/industry_bundle_controller.rb +25 -0
  31. data/app/controllers/mno_enterprise/jpi/v1/marketplace_controller.rb +22 -0
  32. data/app/controllers/mno_enterprise/jpi/v1/organizations_controller.rb +5 -0
  33. data/app/controllers/mno_enterprise/jpi/v1/shopping_cart_controller.rb +93 -0
  34. data/app/controllers/mno_enterprise/jpi/v1/teams_controller.rb +88 -0
  35. data/app/controllers/mno_enterprise/org_invites_controller.rb +5 -0
  36. data/app/controllers/mno_enterprise/pages_controller.rb +5 -0
  37. data/app/controllers/mno_enterprise/provision_controller.rb +5 -0
  38. data/app/controllers/mno_enterprise/status_controller.rb +27 -0
  39. data/app/controllers/mno_enterprise/webhook/o_auth_controller.rb +5 -0
  40. data/app/mailers/mno_enterprise/system_notification_mailer.rb +5 -0
  41. data/app/models/mno_enterprise/health_check.rb +16 -0
  42. data/app/views/devise/password_expired/show.html.haml +32 -0
  43. data/app/views/mno_enterprise/auth/confirmations/default/_form.html.haml +49 -0
  44. data/app/views/mno_enterprise/auth/confirmations/default/_lounge.html.haml +34 -0
  45. data/app/views/mno_enterprise/auth/confirmations/default/_show.html.haml +10 -0
  46. data/app/views/mno_enterprise/auth/confirmations/lounge.html.haml +4 -0
  47. data/app/views/mno_enterprise/auth/confirmations/material/_form.html.haml +44 -0
  48. data/app/views/mno_enterprise/auth/confirmations/material/_lounge.html.haml +18 -0
  49. data/app/views/mno_enterprise/auth/confirmations/material/_show.html.haml +21 -0
  50. data/app/views/mno_enterprise/auth/confirmations/new.html.haml +31 -0
  51. data/app/views/mno_enterprise/auth/confirmations/show.html.haml +4 -0
  52. data/app/views/mno_enterprise/auth/mailer/confirmation_instructions.html.haml +4 -0
  53. data/app/views/mno_enterprise/auth/mailer/reset_password_instructions.html.haml +6 -0
  54. data/app/views/mno_enterprise/auth/mailer/unlock_instructions.html.haml +5 -0
  55. data/app/views/mno_enterprise/auth/passwords/edit.html.haml +53 -0
  56. data/app/views/mno_enterprise/auth/passwords/new.html.haml +34 -0
  57. data/app/views/mno_enterprise/auth/registrations/default/_form.html.haml +35 -0
  58. data/app/views/mno_enterprise/auth/registrations/default/_new.html.haml +11 -0
  59. data/app/views/mno_enterprise/auth/registrations/material/_form.html.haml +30 -0
  60. data/app/views/mno_enterprise/auth/registrations/material/_new.html.haml +10 -0
  61. data/app/views/mno_enterprise/auth/registrations/new.html.haml +4 -0
  62. data/app/views/mno_enterprise/auth/sessions/default/_form.html.haml +17 -0
  63. data/app/views/mno_enterprise/auth/sessions/default/_new.html.haml +11 -0
  64. data/app/views/mno_enterprise/auth/sessions/material/_form.html.haml +26 -0
  65. data/app/views/mno_enterprise/auth/sessions/material/_new.html.haml +11 -0
  66. data/app/views/mno_enterprise/auth/sessions/new.html.haml +4 -0
  67. data/app/views/mno_enterprise/auth/shared/_links.html.haml +24 -0
  68. data/app/views/mno_enterprise/auth/unlocks/new.html.haml +10 -0
  69. data/app/views/mno_enterprise/deletion_requests/show.html.haml +131 -0
  70. data/app/views/mno_enterprise/jpi/v1/admin/audit_events/_audit_event.json.jbuilder +5 -0
  71. data/app/views/mno_enterprise/jpi/v1/admin/audit_events/index.json.jbuilder +4 -0
  72. data/app/views/mno_enterprise/jpi/v1/admin/cloud_apps/_cloud_app.json.jbuilder +1 -0
  73. data/app/views/mno_enterprise/jpi/v1/admin/cloud_apps/index.json.jbuilder +1 -0
  74. data/app/views/mno_enterprise/jpi/v1/admin/cloud_apps/show.json.jbuilder +1 -0
  75. data/app/views/mno_enterprise/jpi/v1/admin/invoices/_invoice.json.jbuilder +2 -0
  76. data/app/views/mno_enterprise/jpi/v1/admin/invoices/index.json.jbuilder +1 -0
  77. data/app/views/mno_enterprise/jpi/v1/admin/invoices/show.json.jbuilder +2 -0
  78. data/app/views/mno_enterprise/jpi/v1/admin/organizations/_credit_card.json.jbuilder +7 -0
  79. data/app/views/mno_enterprise/jpi/v1/admin/organizations/_invoices.json.jbuilder +8 -0
  80. data/app/views/mno_enterprise/jpi/v1/admin/organizations/_member.json.jbuilder +14 -0
  81. data/app/views/mno_enterprise/jpi/v1/admin/organizations/_organization.json.jbuilder +1 -0
  82. data/app/views/mno_enterprise/jpi/v1/admin/organizations/in_arrears.json.jbuilder +8 -0
  83. data/app/views/mno_enterprise/jpi/v1/admin/organizations/index.json.jbuilder +7 -0
  84. data/app/views/mno_enterprise/jpi/v1/admin/organizations/show.json.jbuilder +11 -0
  85. data/app/views/mno_enterprise/jpi/v1/admin/tenant_invoices/_tenant_invoice.json.jbuilder +5 -0
  86. data/app/views/mno_enterprise/jpi/v1/admin/tenant_invoices/index.json.jbuilder +1 -0
  87. data/app/views/mno_enterprise/jpi/v1/admin/tenant_invoices/show.json.jbuilder +1 -0
  88. data/app/views/mno_enterprise/jpi/v1/admin/users/_user.json.jbuilder +1 -0
  89. data/app/views/mno_enterprise/jpi/v1/admin/users/index.json.jbuilder +2 -0
  90. data/app/views/mno_enterprise/jpi/v1/admin/users/show.json.jbuilder +9 -0
  91. data/app/views/mno_enterprise/jpi/v1/app_instances/_resource.json.jbuilder +23 -0
  92. data/app/views/mno_enterprise/jpi/v1/app_instances/index.json.jbuilder +9 -0
  93. data/app/views/mno_enterprise/jpi/v1/app_instances/show.json.jbuilder +3 -0
  94. data/app/views/mno_enterprise/jpi/v1/billing/index.json.jbuilder +0 -0
  95. data/app/views/mno_enterprise/jpi/v1/current_users/show.json.jbuilder +37 -0
  96. data/app/views/mno_enterprise/jpi/v1/impac/dashboards/_dashboard.json.jbuilder +9 -0
  97. data/app/views/mno_enterprise/jpi/v1/impac/dashboards/index.json.jbuilder +1 -0
  98. data/app/views/mno_enterprise/jpi/v1/impac/dashboards/show.json.jbuilder +1 -0
  99. data/app/views/mno_enterprise/jpi/v1/impac/kpis/_kpi.json.jbuilder +1 -0
  100. data/app/views/mno_enterprise/jpi/v1/impac/kpis/show.json.jbuilder +1 -0
  101. data/app/views/mno_enterprise/jpi/v1/impac/widgets/_widget.json.jbuilder +6 -0
  102. data/app/views/mno_enterprise/jpi/v1/impac/widgets/show.json.jbuilder +1 -0
  103. data/app/views/mno_enterprise/jpi/v1/marketplace/_app.json.jbuilder +14 -0
  104. data/app/views/mno_enterprise/jpi/v1/marketplace/index.json.jbuilder +3 -0
  105. data/app/views/mno_enterprise/jpi/v1/marketplace/show.json.jbuilder +3 -0
  106. data/app/views/mno_enterprise/jpi/v1/organizations/_arrears.json.jbuilder +11 -0
  107. data/app/views/mno_enterprise/jpi/v1/organizations/_billing.json.jbuilder +4 -0
  108. data/app/views/mno_enterprise/jpi/v1/organizations/_credit_card.json.jbuilder +7 -0
  109. data/app/views/mno_enterprise/jpi/v1/organizations/_current_user.json.jbuilder +5 -0
  110. data/app/views/mno_enterprise/jpi/v1/organizations/_invoices.json.jbuilder +8 -0
  111. data/app/views/mno_enterprise/jpi/v1/organizations/_member.json.jbuilder +13 -0
  112. data/app/views/mno_enterprise/jpi/v1/organizations/_organization.json.jbuilder +13 -0
  113. data/app/views/mno_enterprise/jpi/v1/organizations/credit_card.json.jbuilder +1 -0
  114. data/app/views/mno_enterprise/jpi/v1/organizations/index.json.jbuilder +1 -0
  115. data/app/views/mno_enterprise/jpi/v1/organizations/members.json.jbuilder +3 -0
  116. data/app/views/mno_enterprise/jpi/v1/organizations/show.json.jbuilder +15 -0
  117. data/app/views/mno_enterprise/jpi/v1/organizations/show_reduced.json.jbuilder +3 -0
  118. data/app/views/mno_enterprise/jpi/v1/shopping_cart/organizations.json.jbuilder +5 -0
  119. data/app/views/mno_enterprise/jpi/v1/shopping_cart/show.json.jbuilder +59 -0
  120. data/app/views/mno_enterprise/jpi/v1/shopping_cart/show_item.json.jbuilder +34 -0
  121. data/app/views/mno_enterprise/jpi/v1/teams/_team.json.jbuilder +20 -0
  122. data/app/views/mno_enterprise/jpi/v1/teams/index.json.jbuilder +1 -0
  123. data/app/views/mno_enterprise/jpi/v1/teams/show.json.jbuilder +3 -0
  124. data/app/views/mno_enterprise/pages/app_access_unauthorized.html.haml +19 -0
  125. data/app/views/mno_enterprise/pages/app_logout.html.haml +18 -0
  126. data/app/views/mno_enterprise/pages/billing_details_required.html.haml +19 -0
  127. data/app/views/mno_enterprise/pages/loading.html.erb +69 -0
  128. data/app/views/mno_enterprise/provision/_provision_apps.html.haml +42 -0
  129. data/app/views/mno_enterprise/provision/_select_organization.html.haml +17 -0
  130. data/app/views/mno_enterprise/provision/new.html.haml +4 -0
  131. data/app/views/mno_enterprise/webhook/o_auth/authorize.html.haml +26 -0
  132. data/app/views/mno_enterprise/webhook/o_auth/providers/myob.html.haml +29 -0
  133. data/app/views/mno_enterprise/webhook/o_auth/providers/xero.html.haml +34 -0
  134. data/config/initializers/devise.rb +273 -0
  135. data/config/initializers/devise_extension.rb +9 -0
  136. data/config/initializers/devise_log.rb +12 -0
  137. data/config/initializers/health_check.rb +35 -0
  138. data/config/initializers/main_app_version.rb +6 -0
  139. data/config/routes.rb +152 -0
  140. data/lib/mno-enterprise-api.rb +1 -0
  141. data/lib/mno_enterprise/api.rb +14 -0
  142. data/lib/mno_enterprise/api/engine.rb +9 -0
  143. data/lib/mno_enterprise/concerns/controllers/deletion_requests_controller.rb +108 -0
  144. data/lib/mno_enterprise/concerns/controllers/jpi/v1/admin/base_resource_controller.rb +34 -0
  145. data/lib/mno_enterprise/concerns/controllers/jpi/v1/current_users_controller.rb +58 -0
  146. data/lib/mno_enterprise/concerns/controllers/jpi/v1/deletion_requests_controller.rb +69 -0
  147. data/lib/mno_enterprise/concerns/controllers/jpi/v1/impac/dashboards_controller.rb +76 -0
  148. data/lib/mno_enterprise/concerns/controllers/jpi/v1/organizations_controller.rb +180 -0
  149. data/lib/mno_enterprise/concerns/controllers/org_invites_controller.rb +44 -0
  150. data/lib/mno_enterprise/concerns/controllers/pages_controller.rb +78 -0
  151. data/lib/mno_enterprise/concerns/controllers/provision_controller.rb +71 -0
  152. data/lib/mno_enterprise/concerns/controllers/webhook/o_auth_controller.rb +107 -0
  153. data/lib/mno_enterprise/concerns/mailers/system_notification_mailer.rb +158 -0
  154. data/lib/mno_enterprise/event_logger.rb +32 -0
  155. data/spec/controllers/mno_enterprise/auth/confirmation_controller_spec.rb +68 -0
  156. data/spec/controllers/mno_enterprise/deletion_requests_controller_spec.rb +141 -0
  157. data/spec/controllers/mno_enterprise/impersonate_controller_spec.rb +48 -0
  158. data/spec/controllers/mno_enterprise/jpi/v1/admin/audit_events_controller_spec.rb +51 -0
  159. data/spec/controllers/mno_enterprise/jpi/v1/admin/cloud_apps_controller_spec.rb +92 -0
  160. data/spec/controllers/mno_enterprise/jpi/v1/admin/invoices_controller_spec.rb +159 -0
  161. data/spec/controllers/mno_enterprise/jpi/v1/admin/organizations_controller_spec.rb +116 -0
  162. data/spec/controllers/mno_enterprise/jpi/v1/admin/tenant_invoices_controller_spec.rb +92 -0
  163. data/spec/controllers/mno_enterprise/jpi/v1/admin/users_controller_spec.rb +136 -0
  164. data/spec/controllers/mno_enterprise/jpi/v1/app_instances_controller_spec.rb +76 -0
  165. data/spec/controllers/mno_enterprise/jpi/v1/app_instances_sync_controller_spec.rb +94 -0
  166. data/spec/controllers/mno_enterprise/jpi/v1/current_users_controller_spec.rb +128 -0
  167. data/spec/controllers/mno_enterprise/jpi/v1/deletion_requests_controller_spec.rb +72 -0
  168. data/spec/controllers/mno_enterprise/jpi/v1/impac/kpis_controller_spec.rb +80 -0
  169. data/spec/controllers/mno_enterprise/jpi/v1/marketplace_controller_spec.rb +115 -0
  170. data/spec/controllers/mno_enterprise/jpi/v1/organizations_controller_spec.rb +516 -0
  171. data/spec/controllers/mno_enterprise/jpi/v1/team_controller_spec.rb +86 -0
  172. data/spec/controllers/mno_enterprise/org_invites_controller_spec.rb +29 -0
  173. data/spec/controllers/mno_enterprise/pages_controller_spec.rb +49 -0
  174. data/spec/controllers/mno_enterprise/provision_controller_spec.rb +94 -0
  175. data/spec/controllers/mno_enterprise/status_controller_spec.rb +34 -0
  176. data/spec/controllers/mno_enterprise/webhook/o_auth_controller_spec.rb +104 -0
  177. data/spec/lib/mno_enterprise/event_logger_spec.rb +28 -0
  178. data/spec/mailer/mno_enterprise/system_notification_mailer_spec.rb +132 -0
  179. data/spec/rails_helper.rb +94 -0
  180. data/spec/requests/devise/authentication_spec.rb +43 -0
  181. data/spec/requests/devise/registration_spec.rb +64 -0
  182. data/spec/routing/devise/confirmation_routing_spec.rb +20 -0
  183. data/spec/routing/devise/passwords_routing_spec.rb +24 -0
  184. data/spec/routing/devise/registrations_routing_spec.rb +16 -0
  185. data/spec/routing/devise/sessions_routing_spec.rb +20 -0
  186. data/spec/routing/mno_enterprise/deletion_requests_controller_routing_spec.rb +20 -0
  187. data/spec/routing/mno_enterprise/impersonate_controller_routing.spec.rb +15 -0
  188. data/spec/routing/mno_enterprise/jpi/v1/admin/audit_events_controller_routing_spec.rb +11 -0
  189. data/spec/routing/mno_enterprise/jpi/v1/admin/cloud_apps_controller_routing_spec.rb +24 -0
  190. data/spec/routing/mno_enterprise/jpi/v1/admin/invoices_controller_routing_spec.rb +37 -0
  191. data/spec/routing/mno_enterprise/jpi/v1/admin/organizations_controller_routing_spec.rb +20 -0
  192. data/spec/routing/mno_enterprise/jpi/v1/admin/tenant_invoices_controller_routing_spec.rb +16 -0
  193. data/spec/routing/mno_enterprise/jpi/v1/admin/users_controller_routing_spec.rb +24 -0
  194. data/spec/routing/mno_enterprise/jpi/v1/app_instances_controller_routing_spec.rb +12 -0
  195. data/spec/routing/mno_enterprise/jpi/v1/app_instances_sync_controller_routing_spec.rb +15 -0
  196. data/spec/routing/mno_enterprise/jpi/v1/current_users_controller_routing_spec.rb +28 -0
  197. data/spec/routing/mno_enterprise/jpi/v1/deletion_requests_controller_routing_spec.rb +24 -0
  198. data/spec/routing/mno_enterprise/jpi/v1/impac/kpis_controller_routing_spec.rb +22 -0
  199. data/spec/routing/mno_enterprise/jpi/v1/marketplace_controller_routing_spec.rb +16 -0
  200. data/spec/routing/mno_enterprise/jpi/v1/organizations_controller_routing_spec.rb +44 -0
  201. data/spec/routing/mno_enterprise/jpi/v1/teams_controller_routing_spec.rb +36 -0
  202. data/spec/routing/mno_enterprise/org_invites_controller_routing_spec.rb +12 -0
  203. data/spec/routing/mno_enterprise/pages_controller_routing_spec.rb +29 -0
  204. data/spec/routing/mno_enterprise/provision_controller_routing_spec.rb +15 -0
  205. data/spec/routing/mno_enterprise/status_controller_routing_spec.rb +19 -0
  206. data/spec/routing/mno_enterprise/webhook/o_auth_controller_routing_spec.rb +27 -0
  207. data/spec/spec_helper.rb +88 -0
  208. 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