maestrano-connector-rails 0.2.16 → 0.2.17

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (37) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +3 -0
  3. data/Gemfile.lock +27 -0
  4. data/VERSION +1 -1
  5. data/app/helpers/maestrano/connector/rails/session_helper.rb +5 -1
  6. data/app/models/maestrano/connector/rails/complex_entity.rb +14 -33
  7. data/app/models/maestrano/connector/rails/concerns/entity.rb +161 -73
  8. data/app/models/maestrano/connector/rails/sub_entity_base.rb +44 -4
  9. data/lib/generators/connector/install_generator.rb +20 -24
  10. data/lib/generators/connector/templates/home_controller.rb +33 -10
  11. data/lib/generators/connector/templates/home_controller_spec.rb +141 -0
  12. data/lib/generators/connector/templates/home_index.haml +103 -0
  13. data/lib/generators/connector/templates/layouts.haml +45 -0
  14. data/lib/generators/connector/templates/oauth_controller.rb +3 -6
  15. data/lib/generators/connector/templates/shared_entities_controller.rb +7 -0
  16. data/lib/generators/connector/templates/shared_entities_controller_spec.rb +23 -0
  17. data/lib/generators/connector/templates/shared_entities_index.haml +41 -0
  18. data/lib/generators/connector/templates/stylesheets/application.sass +24 -0
  19. data/lib/generators/connector/templates/stylesheets/banners.sass +59 -0
  20. data/lib/generators/connector/templates/stylesheets/home.sass +25 -0
  21. data/lib/generators/connector/templates/stylesheets/layout.sass +125 -0
  22. data/lib/generators/connector/templates/stylesheets/spacers.sass +46 -0
  23. data/lib/generators/connector/templates/stylesheets/variables.sass +57 -0
  24. data/lib/generators/connector/templates/sychronizations_controller_spec.rb +22 -0
  25. data/lib/generators/connector/templates/synchronizations_controller.rb +7 -0
  26. data/lib/generators/connector/templates/synchronizations_index.haml +42 -0
  27. data/maestrano-connector-rails.gemspec +29 -6
  28. data/pkg/maestrano-connector-rails-0.2.16.gem +0 -0
  29. data/spec/models/complex_entity_spec.rb +46 -12
  30. data/spec/models/entity_spec.rb +212 -113
  31. data/spec/models/sub_entity_base_spec.rb +59 -0
  32. data/template/maestrano-connector-template.rb +4 -3
  33. data/template/routes.rb +14 -0
  34. metadata +61 -5
  35. data/lib/generators/connector/templates/admin_controller.rb +0 -58
  36. data/lib/generators/connector/templates/admin_index.html.erb +0 -55
  37. data/lib/generators/connector/templates/home_index.html.erb +0 -48
@@ -14,19 +14,59 @@ module Maestrano::Connector::Rails
14
14
  end
15
15
 
16
16
  def external_entity_name
17
- if self.external?
18
- self.entity_name
17
+ if external?
18
+ entity_name
19
19
  else
20
20
  raise "Forbidden call"
21
21
  end
22
22
  end
23
23
 
24
24
  def connec_entity_name
25
- if self.external?
25
+ if external?
26
26
  raise "Forbidden call"
27
27
  else
28
- self.entity_name
28
+ entity_name
29
29
  end
30
30
  end
31
+
32
+ def names_hash
33
+ if external?
34
+ {external_entity: entity_name.downcase}
35
+ else
36
+ {connec_entity: entity_name.downcase}
37
+ end
38
+ end
39
+
40
+ def create_idmap_from_external_entity(entity, connec_entity_name, organization)
41
+ if external?
42
+ h = names_hash.merge({
43
+ external_id: get_id_from_external_entity_hash(entity),
44
+ name: object_name_from_external_entity_hash(entity),
45
+ connec_entity: connec_entity_name.downcase,
46
+ organization_id: organization.id
47
+ })
48
+ Maestrano::Connector::Rails::IdMap.create(h)
49
+ else
50
+ raise 'Forbidden call'
51
+ end
52
+ end
53
+
54
+ def create_idmap_from_connec_entity(entity, external_entity_name, organization)
55
+ if external?
56
+ raise 'Forbidden call'
57
+ else
58
+ h = names_hash.merge({
59
+ connec_id: entity['id'],
60
+ name: object_name_from_connec_entity_hash(entity),
61
+ external_entity: external_entity_name.downcase,
62
+ organization_id: organization.id
63
+ })
64
+ Maestrano::Connector::Rails::IdMap.create(h)
65
+ end
66
+ end
67
+
68
+ def map_external_entity_with_idmap(external_entity, connec_entity_name, idmap, organization)
69
+ {entity: map_to(connec_entity_name, external_entity, organization), idmap: idmap}
70
+ end
31
71
  end
32
72
  end
@@ -21,25 +21,6 @@ module Connector
21
21
  end
22
22
  end
23
23
 
24
- def include_routes
25
- sentinel = 'Rails.application.routes.draw do'
26
- code_lines = [
27
- "mount Maestrano::Connector::Rails::Engine, at: '/'\n",
28
- "root 'home#index'",
29
- "get 'home/index' => 'home#index'",
30
- "get 'admin/index' => 'admin#index'",
31
- "put 'admin/update' => 'admin#update'",
32
- "post 'admin/synchronize' => 'admin#synchronize'",
33
- "put 'admin/toggle_sync' => 'admin#toggle_sync'"
34
- ]
35
-
36
- in_root do
37
- gsub_file 'config/routes.rb', /(#{Regexp.escape(sentinel)})/mi do |match|
38
- "#{match}\n #{code_lines.join("\n ")}\n"
39
- end
40
- end
41
- end
42
-
43
24
  def copy_entity
44
25
  copy_file 'entity.rb', 'app/models/maestrano/connector/rails/entity.rb'
45
26
  end
@@ -52,14 +33,29 @@ module Connector
52
33
  copy_file 'example_entity.rb', 'app/models/entities/example_entitiy.rb'
53
34
  end
54
35
 
55
- def copy_home
36
+ def copy_controllers_and_views
56
37
  copy_file 'home_controller.rb', 'app/controllers/home_controller.rb'
57
- copy_file 'home_index.html.erb', 'app/views/home/index.html.erb'
38
+ copy_file 'home_controller_spec.rb', 'spec/controllers/home_controller_spec.rb'
39
+ copy_file 'home_index.haml', 'app/views/home/index.html.haml'
40
+
41
+ copy_file 'synchronizations_controller.rb', 'app/controllers/synchronizations_controller.rb'
42
+ copy_file 'synchronizations_controller_spec.rb', 'spec/controllers/synchronizations_controller_spec.rb'
43
+ copy_file 'synchronizations_index.haml', 'app/views/synchronizations/index.html.haml'
44
+
45
+ copy_file 'shared_entities_controller.rb', 'app/controllers/shared_entities_controller.rb'
46
+ copy_file 'shared_entities_controller_spec.rb', 'spec/controllers/shared_entities_controller_spec.rb'
47
+ copy_file 'shared_entities_index.haml', 'app/views/shared_entities/index.html.haml'
48
+
49
+ copy_file 'layouts.haml', 'app/views/layouts/application.html.haml'
58
50
  end
59
51
 
60
- def copy_admin_view
61
- copy_file 'admin_controller.rb', 'app/controllers/admin_controller.rb'
62
- copy_file 'admin_index.html.erb', 'app/views/admin/index.html.erb'
52
+ def copy_stylesheets
53
+ copy_file 'stylesheets/application.sass', 'app/assets/stylesheets/application.sass'
54
+ copy_file 'stylesheets/banners.sass', 'app/assets/stylesheets/banners.sass'
55
+ copy_file 'stylesheets/home.sass', 'app/assets/stylesheets/home.sass'
56
+ copy_file 'stylesheets/layout.sass', 'app/assets/stylesheets/layout.sass'
57
+ copy_file 'stylesheets/spacers.sass', 'app/assets/stylesheets/spacers.sass'
58
+ copy_file 'stylesheets/variables.sass', 'app/assets/stylesheets/variables.sass'
63
59
  end
64
60
 
65
61
  def copy_oauth_controller
@@ -1,17 +1,40 @@
1
- # TODO
2
- # This controller is given as an example of a possible home
3
- # Home funcitons :
4
- # * Display generic information about the connector (mostly for not connected users)
5
- # * Link the connector to a Maestrano organization
6
- # * Acces the last synchronization and a synchronization history (with their status)
7
1
  class HomeController < ApplicationController
8
2
  def index
9
- if current_user
10
- @organization = current_organization
3
+ @organization = current_organization
4
+ end
5
+
6
+ def update
7
+ organization = Maestrano::Connector::Rails::Organization.find_by_id(params[:id])
11
8
 
12
- if @organization
13
- @synchronizations = Maestrano::Connector::Rails::Synchronization.where(organization_id: @organization.id).order(updated_at: :desc).limit(40)
9
+ if organization && is_admin?(current_user, organization)
10
+ organization.synchronized_entities.keys.each do |entity|
11
+ if !!params["#{entity}"]
12
+ organization.synchronized_entities[entity] = true
13
+ else
14
+ organization.synchronized_entities[entity] = false
15
+ end
14
16
  end
17
+ organization.save
18
+ end
19
+
20
+ redirect_to(:back)
21
+ end
22
+
23
+ def synchronize
24
+ if is_admin
25
+ Maestrano::Connector::Rails::SynchronizationJob.perform_later(current_organization, params['opts'] || {})
26
+ flash[:info] = 'Synchronization requested'
15
27
  end
28
+
29
+ redirect_to(:back)
30
+ end
31
+
32
+ def toggle_sync
33
+ if is_admin
34
+ current_organization.update(sync_enabled: !current_organization.sync_enabled)
35
+ flash[:info] = current_organization.sync_enabled ? 'Synchronization enabled' : 'Synchronization disabled'
36
+ end
37
+
38
+ redirect_to(:back)
16
39
  end
17
40
  end
@@ -0,0 +1,141 @@
1
+ require 'spec_helper'
2
+
3
+ describe HomeController, :type => :controller do
4
+ let(:back_path) { home_index_path }
5
+ before(:each) do
6
+ request.env["HTTP_REFERER"] = back_path
7
+ end
8
+
9
+ describe 'index' do
10
+ subject { get :index }
11
+
12
+ it { expect(subject).to be_success }
13
+ end
14
+
15
+ describe 'update' do
16
+ let(:organization) { create(:organization, synchronized_entities: {'people' => false, 'item' => true}) }
17
+ subject { put :update, id: organization.id, 'people' => true, 'item' => false, 'lala' => true }
18
+
19
+
20
+ context 'when user is not admin' do
21
+ before {
22
+ allow_any_instance_of(Maestrano::Connector::Rails::SessionHelper).to receive(:is_admin?).and_return(false)
23
+ }
24
+
25
+ it { expect(subject).to redirect_to back_path }
26
+ end
27
+
28
+ context 'when user is admin' do
29
+ before {
30
+ allow_any_instance_of(Maestrano::Connector::Rails::SessionHelper).to receive(:is_admin?).and_return(true)
31
+ }
32
+
33
+ it { expect(subject).to redirect_to back_path }
34
+
35
+ it 'updates organization' do
36
+ subject
37
+ organization.reload
38
+ expect(organization.synchronized_entities).to eq({'people' => true, 'item' => false})
39
+ end
40
+ end
41
+ end
42
+
43
+ describe 'synchronize' do
44
+ subject { post :synchronize }
45
+ let(:organization) { create(:organization) }
46
+ before {
47
+ allow_any_instance_of(Maestrano::Connector::Rails::SessionHelper).to receive(:current_organization).and_return(organization)
48
+ }
49
+
50
+ context 'when user is not admin' do
51
+ before {
52
+ allow_any_instance_of(ApplicationHelper).to receive(:is_admin).and_return(false)
53
+ }
54
+
55
+ it { expect(subject).to redirect_to back_path }
56
+
57
+ it 'does nothing' do
58
+ expect(Maestrano::Connector::Rails::SynchronizationJob).to_not receive(:perform_later)
59
+ subject
60
+ end
61
+ end
62
+
63
+ context 'when user is admin' do
64
+ before {
65
+ allow_any_instance_of(ApplicationHelper).to receive(:is_admin).and_return(true)
66
+ }
67
+
68
+ it { expect(subject).to redirect_to back_path }
69
+
70
+ context 'with opts' do
71
+ subject { post :synchronize, opts: 'opts' }
72
+
73
+ it 'calls perform_later with opts' do
74
+ expect(Maestrano::Connector::Rails::SynchronizationJob).to receive(:perform_later).with(organization, 'opts')
75
+ subject
76
+ end
77
+ end
78
+
79
+ context 'without opts' do
80
+ subject { post :synchronize}
81
+
82
+ it 'calls perform_later with empty opts hash' do
83
+ expect(Maestrano::Connector::Rails::SynchronizationJob).to receive(:perform_later).with(organization, {})
84
+ subject
85
+ end
86
+ end
87
+ end
88
+
89
+ describe 'toggle_sync' do
90
+ subject { put :toggle_sync }
91
+ let(:organization) { create(:organization, sync_enabled: true) }
92
+ before {
93
+ allow_any_instance_of(Maestrano::Connector::Rails::SessionHelper).to receive(:current_organization).and_return(organization)
94
+ }
95
+
96
+ context 'when user is not an admin' do
97
+ before {
98
+ allow_any_instance_of(ApplicationHelper).to receive(:is_admin).and_return(false)
99
+ }
100
+ it { expect(subject).to redirect_to back_path }
101
+
102
+ it 'does nothing' do
103
+ expect{ subject }.to_not change{ organization.sync_enabled }
104
+ end
105
+ end
106
+
107
+ context 'when user is admin' do
108
+ before {
109
+ allow_any_instance_of(ApplicationHelper).to receive(:is_admin).and_return(true)
110
+ }
111
+ it { expect(subject).to redirect_to back_path }
112
+
113
+ it 'change sync_enabled from true to false' do
114
+ expect{ subject }.to change{ organization.sync_enabled }.from(true).to(false)
115
+ end
116
+
117
+ it 'change sync_enabled from false to true' do
118
+ organization.update(sync_enabled: false)
119
+ expect{ subject }.to change{ organization.sync_enabled }.from(false).to(true)
120
+ end
121
+ end
122
+ end
123
+ end
124
+
125
+ describe 'redirect_to_external' do
126
+ subject { get :redirect_to_external }
127
+
128
+ context 'when organization has a redirect url' do
129
+ let(:organization) { create(:organization, instance_url: 'url') }
130
+ before {
131
+ allow_any_instance_of(Maestrano::Connector::Rails::SessionHelper).to receive(:current_organization).and_return(organization)
132
+ }
133
+
134
+ it {expect(subject).to redirect_to('url')}
135
+ end
136
+
137
+ context 'otherwise' do
138
+ it {expect(subject).to redirect_to('https://login.salesforce.com')}
139
+ end
140
+ end
141
+ end
@@ -0,0 +1,103 @@
1
+ / TODO
2
+ / Replace ApplicationName
3
+ .home
4
+ .banners
5
+ .row
6
+ .col-md-10.col-md-offset-2
7
+ %h2 ApplicationName Connector
8
+ %p
9
+ Link your Maestrano account to ApplicationName to get your business in synch. Check the status of your connection on this screen.
10
+
11
+ .container
12
+ - if current_user
13
+ - unless is_admin
14
+ .row
15
+ .col-md-12.alert.alert-warning
16
+ Only administrators can modify the application settings
17
+
18
+ .row.link-step
19
+ .col-md-1.text-center.link-step-number
20
+ %span.badge.link-step-badge
21
+ 1
22
+ .col-md-3.text-center
23
+ =image_tag "logos/default-white.png", class: 'logo'
24
+ .col-md-6.link-step-description
25
+ %h
26
+ Your Maestrano company <strong>#{@organization.name} (#{@organization.uid})</strong> is currently linked
27
+ .col-md-2.text-center.link-step-action
28
+ = link_to "Disconnect", Maestrano::Connector::Rails::Engine.routes.url_helpers.maestrano_signout_path, class: "btn btn-warning btn-lg #{is_admin ? '' : 'disabled'}"
29
+
30
+ .spacer1
31
+
32
+ .row.link-step
33
+ .col-md-1.text-center.link-step-number
34
+ %span.badge.link-step-badge
35
+ 2
36
+ .col-md-3.text-center
37
+ =image_tag "logos/external.png", class: 'logo'
38
+ .col-md-6.link-step-description
39
+ %h
40
+ - if @organization.oauth_uid
41
+ Your ApplicationName account <strong>#{@organization.oauth_name} (#{@organization.oauth_uid})</strong> is currently linked
42
+ - else
43
+ Your ApplicationName account is not linked
44
+ .col-md-2.text-center.link-step-action
45
+ - if @organization.oauth_uid
46
+ / TODO
47
+ = link_to "Disconnect", root_path, class: "btn btn-warning btn-lg #{is_admin ? '' : 'disabled'}"
48
+ - else
49
+ / TODO
50
+ = link_to "Link to ApplicationName", root_path, class: "btn btn-warning btn-lg #{is_admin ? '' : 'disabled'}"
51
+
52
+ .spacer1
53
+
54
+ .row.link-step
55
+ .col-md-1.text-center.link-step-number
56
+ %span.badge.link-step-badge
57
+ 3
58
+ .col-md-3.text-center
59
+ =image_tag "logos/sync.png", class: 'logo'
60
+ .col-md-6.link-step-description
61
+ %h
62
+ - if @organization.sync_enabled
63
+ Synchronizations are enabled
64
+ - else
65
+ Synchronizations are disabled
66
+ .col-md-2.text-center.link-step-action
67
+ = link_to "Toggle #{@organization.sync_enabled ? 'off' : 'on'}", home_toggle_sync_path, method: :put, class: "btn btn-warning btn-lg #{is_admin ? '' : 'disabled'}"
68
+
69
+ - else
70
+ .row
71
+ .col-md-4.col-md-offset-4.center
72
+ = link_to "Link your Maestrano account", Maestrano::Connector::Rails::Engine.routes.url_helpers.default_maestrano_auth_saml_index_path(tenant: :default), class: 'btn btn-warning'
73
+
74
+ - if @organization
75
+ .spacer2
76
+ .row
77
+ .col-md-12
78
+ %h1
79
+ Synchronized entities
80
+ %small You can customize which entities are synchronized by the connector
81
+
82
+ .spacer1
83
+ .row
84
+ .col-md-10.col-md-offset-1
85
+ = form_tag home_update_path(id: @organization.id), method: :put do
86
+ - @organization.synchronized_entities.each do |k, v|
87
+ .row.sync-entity
88
+ .col-md-1.link-step-action
89
+ %input{type: "checkbox", id: "#{k}", name: "#{k}", checked: v}
90
+ .col-md-7{style: 'padding-top: 5px;'}
91
+ %label{:for => "#{k}"} #{k.to_s.humanize}
92
+ -if is_admin
93
+ .col-md-4.text-right
94
+ - if v && @organization.oauth_uid
95
+ - if @organization.sync_enabled
96
+ = link_to "Force a synchronization for #{k.to_s.humanize.pluralize} only", home_synchronize_path(opts: {only_entities: [k.to_s]}), method: :post, class: "btn btn-warning btn-sm #{is_admin && @organization.sync_enabled ? '' : 'disabled'}"
97
+ - else
98
+ .btn.btn-warning.btn-sm.disabled= "Force a synchronization for #{k.to_s.humanize.pluralize} only"
99
+ -if is_admin
100
+ .spacer1
101
+ .row
102
+ .col-md-4.col-md-offset-8.text-right
103
+ =submit_tag :Save, class: "btn btn-primary"
@@ -0,0 +1,45 @@
1
+ / TODO
2
+ / Replace ApplicationName
3
+ !!!
4
+ %html
5
+ %head
6
+ %title ApplicationName Connector for Connec!™
7
+ = stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track' => true
8
+ = javascript_include_tag 'application', 'data-turbolinks-track' => true
9
+ = csrf_meta_tags
10
+ %body
11
+ .navbar.navbar-fixed-top.navbar-inverse
12
+ .container-fluid
13
+ .collapse.navbar-collapse#maestrano-navbar-collapse
14
+ %ul.nav.navbar-nav
15
+ =image_tag "logos/default.png", class: 'external-logo'
16
+
17
+ %ul.nav.navbar-nav
18
+ %li=link_to "Status", root_path
19
+ %li=link_to "History", synchronizations_index_path
20
+ -if is_admin
21
+ %li=link_to "Mapping", shared_entities_index_path
22
+
23
+ -if current_user
24
+ %ul.nav.navbar-nav.navbar-right
25
+ %li.dropdown
26
+ %a{:href=>"#", :class=>"dropdown-toggle", :'data-toggle'=>"dropdown", :role=>"button"}
27
+ Hi #{current_user.first_name} #{current_user.last_name}
28
+
29
+ .padding-navbar
30
+
31
+ .wrapper{style: 'margin-bottom: 15px; '}
32
+ - if flash.any?
33
+ - flash.each do |flash_key, message|
34
+ .alert{:class => "alert-#{flash_key}"}
35
+ %strong= flash.discard(flash_key)
36
+
37
+ = yield
38
+
39
+ .footer
40
+ .container
41
+ .row
42
+ .col-xs-12
43
+ .copyright
44
+ © Copyright #{Time.now.year} Maestrano Pty Ltd (ABN: 80 152 564 424).
45
+ All rights reserved. Various trademarks held by their respective owners.