/
Migration Guides
Migration Guides
Marco Bagnasco (Unlicensed)
Bruno Chauvet (Unlicensed)
Owned by Marco Bagnasco (Unlicensed)
Step to step guide when migrating to a different version of the Maestrano Connector Framework
Migrating to version 2.1
Step-by-step guide
- In addition to the framework version, add the following gems to your
Gemfile
:webmock
group :test do gem 'webmock' end
- Download these 2 png files (used in the front-end) and add them to app/assets/images/logos
- to_external.png
- to_connec.png Replace your
app/assets/javascripts/home.js
:home.js Expand sourcefunction historicalDataDisplay() { if (document.getElementById('historical-data').checked) { $('#myModal').modal('show'); document.getElementById('historical-data-display-checked').style.display = 'block'; document.getElementById('historical-data-display-unchecked').style.display = 'none'; } else { document.getElementById('historical-data-display-unchecked').style.display = 'block'; document.getElementById('historical-data-display-checked').style.display = 'none'; } } var checkHistorical function closeModal(sender) { checkHistorical = sender.id == 'confirm' $('#myModal').modal('hide'); } $(function () { $('[data-toggle="tooltip"]').tooltip() }) $(document).ready(function(){ $("#myModal").on('hidden.bs.modal', function (e) { if (!checkHistorical) { document.getElementById('historical-data').checked = false historicalDataDisplay() } checkHistorical = false }); });
Append these lines to
app/assets/stylesheets/layout.sass
layout.sass Expand source.image height: 30 margin-left: -25px .small-image height: 20px
Your
home_controller.rb
should look like this:home_controller.rb Expand source# frozen_string_literal: true class HomeController < ApplicationController def update return redirect_to(:back) unless is_admin # Update list of entities to synchronize current_organization.synchronized_entities.keys.each do |entity| current_organization.synchronized_entities[entity][:can_push_to_connec] = params[entity.to_s]["to_connec"] == "1" current_organization.synchronized_entities[entity][:can_push_to_external] = params[entity.to_s]["to_external"] == "1" end full_sync = params['historical-data'].present? && !current_organization.historical_data opts = {full_sync: full_sync} current_organization.sync_enabled = current_organization.synchronized_entities.values.any? { |settings| settings.values.any? { |v| v } } current_organization.enable_historical_data(params['historical-data'].present?) trigger_sync = current_organization.sync_enabled current_organization.save # Trigger sync only if the sync has been enabled start_synchronization(opts) if trigger_sync redirect_to(:back) end def synchronize return redirect_to(:back) unless is_admin Maestrano::Connector::Rails::SynchronizationJob.perform_later(current_organization.id, (params['opts'] || {}).merge(forced: true)) flash[:info] = 'Synchronization requested' redirect_to(:back) end def redirect_to_external redirect_to 'https://your_application.com' end private def start_synchronization(opts) Maestrano::Connector::Rails::SynchronizationJob.perform_later(current_organization.id, opts) flash[:info] = 'Congrats, you\'re all set up! Your data are now being synced' if current_organization.sync_enabled_changed? end end
Refer to this
html.haml
file for the modal and layout:Front End Customization
Based on the specific requirements of the connector, this file might have to be changed. (i.e. Authentication form)
index.html.haml Expand source!!! .home .banners .row .col-md-10.col-md-offset-2 %h2 YourApp Connector %p -if current_organization Link your company <strong>#{current_organization.name} (#{current_organization.uid})</strong> to YourApp to get your business in synch. Check the status of your connection on this screen. -else Link your account to YourApp to get your business in synch. Check the status of your connection on this screen. .container - if current_user - unless is_admin .row .col-md-12.alert.alert-warning Only administrators can modify the application settings .row.link-step{class: "#{current_organization.oauth_uid ? 'done' : 'todo'}"} .col-md-1.text-center.link-step-number %span.badge.link-step-badge 1 .col-md-6.link-step-description %h - if current_organization.oauth_uid Your YourApp account <strong>#{current_organization.oauth_name} (#{current_organization.oauth_uid})</strong> is currently linked - else Your YourApp account is not linked %br .col-md-4.col-md-offset-8.text-center.link-step-action - if current_organization.oauth_uid = link_to "Disconnect", signout_omniauth_path(organization_id: current_organization.id), class: "btn btn-warning btn-lg #{is_admin ? '' : 'disabled'}" - else - if is_admin .col-md-12.col-md-offset-1.text-center %small Your YourApp email and password are not stored by Maestrano = render 'authentication_form' %br %small If you don’t have an account #{link_to 'create yours here', Maestrano::Connector::Rails::External.create_account_link(current_organization || nil)} .spacer1 .row.link-step{class: "#{(current_organization.sync_enabled && current_organization.synchronized_entities.values.any?) ? 'done' : 'todo'}"} = form_tag home_update_path(id: current_organization.id), method: :put do .col-md-1.text-center.link-step-number %span.badge.link-step-badge 2 .col-md-9.link-step-description %p You can customize which entities are synchronized by the connector: %p (#{image_tag "logos/to_connec.png", class: "small-image"} : from YourApp to Connec! and #{image_tag "logos/to_external.png", class: "small-image"} : from Connec! to YourApp) .spacer1 .row .col-md-11.col-md-offset-1.center .row .col-md-1 =image_tag "logos/to_connec.png", class: "image" .col-md-1 =image_tag "logos/to_external.png", class: "image" .col-md-4 YourApp wording .col-md-3 Universal wording .spacer1 .row .col-md-11.col-md-offset-1 - current_organization.displayable_synchronized_entities.each do |k, v| .row.sync-entity .col-md-1.link-step-action #{check_box("#{k}", "to_connec", {checked: (v[:can_push_to_connec] || v[:can_push_to_external]) && !current_organization.pull_disabled, onclick: "return !#{k}_to_external.checked;", disabled: current_organization.pull_disabled})} .col-md-1.link-step-action #{check_box("#{k}", "to_external", {checked: v[:can_push_to_external] && !current_organization.push_disabled, onchange: "#{k}_to_connec.checked = #{!current_organization.pull_disabled};", disabled: current_organization.push_disabled})} %label.col-md-8{:for => "#{k}", style: 'padding-top: 5px;'} .col-md-6 #{v[:external_name]} .col-md-6 #{v[:connec_name]} -if is_admin .col-md-2.text-right - if v && current_organization.oauth_uid && current_organization.sync_enabled = link_to 'Force a synchronization', home_synchronize_path(opts: {only_entities: [k.to_s]}), method: :post, class: 'btn btn-warning btn-sm', title: "Force a synchronization for #{v[:external_name]} only", 'data-toggle' => 'tooltip', 'data-placement' => 'right' .spacer2 .row %h Chose whether to synchronize your historical data: .spacer1 .row .col-md-4.col-md-offset-1 %label{:for => 'historical-data'} Synchronize my historical data .col-md-1 #myModal.modal.fade{:role => "dialog"} .modal-dialog .modal-content .modal-header %button.close{"data-dismiss" => "modal", :type => "button"} × %h4.modal-title Warning! .modal-body %p %b All data created prior to the date you linked YourApp %b will be synchronised both ways. %p It means that: %br \- all data from applications you already have linked to the platform will be sent to your YourApp account %br \- all exisiting data from YourApp will be sent to your other applications %br %p If you have been manually copying records in multiple applications, %b you risk seeing duplicates arising! %p %b This action cannot be undone at any time! .modal-footer %button.btn.btn-primary{id: 'confirm', :type => "button", onclick: "closeModal(confirm);"} Confirm %button.btn.btn-secondary{id: 'close', :type => "button", onclick: "closeModal(close);"} Close %input{type: 'checkbox', id: 'historical-data', name: 'historical-data', checked: current_organization.historical_data, onchange: 'historicalDataDisplay();', disabled: current_organization.historical_data} .col-md-6 %small#historical-data-display-unchecked{style: "display: #{current_organization.historical_data ? 'none' : 'block'}"} Only data created after #{(current_organization.date_filtering_limit && current_organization.date_filtering_limit.utc || Time.now.utc).to_formatted_s(:long_ordinal)} will be synchronized %small#historical-data-display-checked{style: "display: #{!current_organization.historical_data ? 'none' : 'block'}"} Synchronizing your historical data will share all data in YourApp. This action is not reversible. Want to know more? Check #{link_to 'here', 'https://maestrano.atlassian.net/wiki/display/UKB/How+Connec%21+manages+Historical+Data+Sharing'} .spacer1 .row .col-md-2.col-md-offset-10.text-center.link-step-action =submit_tag "#{current_organization.sync_enabled ? 'Synchronize' : 'Start synchronizing!'}", class: "btn btn-lg btn-warning #{current_organization.oauth_uid ? '' : 'disabled'} text-sm" -if current_organization.oauth_uid && current_organization.sync_enabled .spacer2 .row .col-md-4.col-md-offset-4.text-center = link_to 'Go to YourApp', home_redirect_to_external_path, class: 'btn btn-lg btn-primary' - else .row .col-md-4.col-md-offset-4.center = 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'
Add these 2 migrations:
UpdateOrganizationMetadata Expand sourceclass UpdateOrganizationMetadata < ActiveRecord::Migration def change add_column :organizations, :push_disabled, :boolean add_column :organizations, :pull_disabled, :boolean change_column :organizations, :synchronized_entities, :text # Migration to update the way we handle synchronized_entities for data sharing. # Before : synchronized_entities = {company: true} # After: synchronized_entities = {company: {can_push_to_connec: true, can_push_to_external: true}} #We also add metadata from MnoHub Maestrano::Connector::Rails::Organization.all.each do |o| o.reset_synchronized_entities o.enable_historical_data(true) if o.push_disabled end end end
AddMetadataToIdMap Expand sourceclass AddMetadataToIdMap < ActiveRecord::Migration def change add_column :id_maps, :metadata, :text end end
Add these to
spec_helper.rb
:spec_helper Expand sourcerequire 'webmock/rspec' ... config.before(:each) do stub_request(:get, %r(https://maestrano.com/api/v1/account/groups/\w+)) .with(:headers => {'Accept'=>'*/*', 'Accept-Encoding'=>'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', 'Authorization'=>'Basic Og==', 'User-Agent'=>'Ruby'}) .to_return({status: 200, body: "{}", headers: {}}) end
Refer to this file to fix
home_controller_spec
:home_controller_spec Expand sourcerequire 'spec_helper' describe HomeController, type: :controller do let(:back_path) { home_index_path } before(:each) do request.env["HTTP_REFERER"] = back_path end describe 'index' do subject { get :index } it { expect(subject).to be_success } end describe 'update' do let(:user) { create(:user) } let(:organization) { create(:organization, synchronized_entities: {'people' => {can_push_to_connec: false, can_push_to_external: false}, 'item' => {can_push_to_connec: true, can_push_to_external: true}}) } before { allow_any_instance_of(Maestrano::Connector::Rails::SessionHelper).to receive(:current_user).and_return(user) } before { allow_any_instance_of(Maestrano::Connector::Rails::SessionHelper).to receive(:current_organization).and_return(organization) } subject { put :update, id: organization.id, 'people' => {to_connec: '1', to_external: '1'}, 'item' => {}, 'lala' => {} } context 'when user is not admin' do before { allow_any_instance_of(Maestrano::Connector::Rails::SessionHelper).to receive(:is_admin).and_return(false) } it { expect(subject).to redirect_to back_path } end context 'when user is admin' do before { allow_any_instance_of(Maestrano::Connector::Rails::SessionHelper).to receive(:is_admin).and_return(true) } it { expect(subject).to redirect_to back_path } it 'updates organization synchronized_entities' do subject organization.reload expect(organization.synchronized_entities).to eq('people' => {can_push_to_connec: true, can_push_to_external: true}, 'item' => {can_push_to_connec: false, can_push_to_external: false}) end it 'updates organization sync_enabled' do subject organization.reload expect(organization.sync_enabled).to eq true end context 'when removing all entities' do subject { put :update, id: organization.id, 'people' => {}, 'item' => {} } before { organization.update(sync_enabled: true) } it 'set sync_enabled to false' do subject organization.reload expect(organization.sync_enabled).to eq false end end end end describe 'synchronize' do let(:user) { create(:user) } let(:organization) { create(:organization, synchronized_entities: {'people' => {can_push_to_connec: false, can_push_to_external: false}, 'item' => {can_push_to_connec: true, can_push_to_external: true}}) } before { allow_any_instance_of(Maestrano::Connector::Rails::SessionHelper).to receive(:current_user).and_return(user) } before { allow_any_instance_of(Maestrano::Connector::Rails::SessionHelper).to receive(:current_organization).and_return(organization) } subject { post :synchronize } context 'when user is not admin' do before { allow_any_instance_of(Maestrano::Connector::Rails::SessionHelper).to receive(:is_admin).and_return(false) } it { expect(subject).to redirect_to back_path } it 'does nothing' do expect(Maestrano::Connector::Rails::SynchronizationJob).to_not receive(:perform_later) subject end end context 'when user is admin' do before { allow_any_instance_of(Maestrano::Connector::Rails::SessionHelper).to receive(:is_admin).and_return(true) } it { expect(subject).to redirect_to back_path } context 'with opts' do subject { post :synchronize, opts: {'opts' => 'some_opts'} } it 'calls perform_later with opts' do expect(Maestrano::Connector::Rails::SynchronizationJob).to receive(:perform_later).with(organization.id, 'opts' => 'some_opts', forced: true) subject end end context 'without opts' do subject { post :synchronize} it 'calls perform_later with empty opts hash' do expect(Maestrano::Connector::Rails::SynchronizationJob).to receive(:perform_later).with(organization.id, forced: true) subject end end end end describe 'redirect_to_external' do subject { get :redirect_to_external } context 'otherwise' do it {expect(subject).to redirect_to('https://your_application.com')} end end end
- Download these 2 png files (used in the front-end) and add them to app/assets/images/logos
, multiple selections available,
Related content
Getting started
Getting started
More like this
How to disconnect applications on your Maestrano dashboard
How to disconnect applications on your Maestrano dashboard
More like this
[Deprecated] How to link my application to maestrano.com
[Deprecated] How to link my application to maestrano.com
More like this
Deployment of a Connector Rails Application
Deployment of a Connector Rails Application
More like this
How to connect applications on your Maestrano dashboard
How to connect applications on your Maestrano dashboard
More like this
Deploying a Connector
Deploying a Connector
More like this