bookingsync-engine 4.0.1 → 6.0.0

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 (96) hide show
  1. checksums.yaml +5 -5
  2. data/app/views/sessions/failure.html.erb +3 -1
  3. data/lib/bookingsync-engine.rb +11 -2
  4. data/lib/bookingsync/engine.rb +14 -5
  5. data/lib/bookingsync/engine/auth_helpers.rb +38 -16
  6. data/lib/bookingsync/engine/models/account.rb +9 -3
  7. data/lib/bookingsync/engine/models/base_account.rb +8 -6
  8. data/lib/bookingsync/engine/models/multi_applications_account.rb +9 -3
  9. data/lib/bookingsync/engine/retryable.rb +16 -0
  10. data/lib/bookingsync/engine/version.rb +1 -1
  11. data/spec/controllers/authenticated_controller_spec.rb +36 -12
  12. data/spec/dummy/app/assets/config/manifest.js +3 -0
  13. data/spec/dummy/config/initializers/bookingsync-engine.rb +8 -0
  14. data/spec/dummy/db/migrate/20190623220013_add_custom_booking_sync_key_id_to_accounts.rb +5 -0
  15. data/spec/dummy/db/migrate/20190623220132_add_custom_booking_sync_key_id_to_multi_applications_accounts.rb +5 -0
  16. data/spec/dummy/db/schema.rb +3 -1
  17. data/spec/dummy/log/development.log +2 -7427
  18. data/spec/dummy/log/test.log +9640 -62357
  19. data/spec/fixtures/accounts.yml +2 -0
  20. data/spec/lib/bookingsync/engine/retryable_spec.rb +81 -0
  21. data/spec/models/account_spec.rb +79 -0
  22. data/spec/models/multi_application_account_spec.rb +12 -0
  23. metadata +43 -153
  24. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/0A/0AkQ3CITU4KXnU7GsiDQLAWeLkJApWK8LSS1j7wEk2I.cache +0 -0
  25. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/1M/1MTKfLxlwDryDP9C4ksVeuOF5FekTW5EddfnaJ4ujrA.cache +0 -0
  26. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/2F/2FjAKNLL-jC6FeYfXsL0M8jItncHQcdDy239KNsTZQs.cache +0 -1
  27. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/2_/2_hJriYgvh3UGtv5NMhrnkrtfpJlyTuQ4F5jYdVf8sQ.cache +0 -1
  28. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/3J/3JfiofMyqvbHq3sZznFIDsFS81fHxyAWoCXJLrtrWP4.cache +0 -0
  29. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/3f/3fwING3B2z9NOnWMwdXFatlVw06vge46KkOWOII0KlU.cache +0 -1
  30. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/4i/4iLsjcOzC2_Y0hxnbPKuyayJABeUFDSyIh4Ed9OA8Xw.cache +0 -0
  31. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/50/502uMBbq2ELFXg5u1vtykxQ_whhsdgQnmTwNA96niD0.cache +0 -0
  32. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/5s/5sm0UHvqondwU5MMfjMuqvLW2WQ6S7ylUf9PNw2uCTc.cache +0 -1
  33. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/6F/6F2x1Bu3NKSTCTwUS6iCRFhKRT_ntZMzmPIMnVGabK4.cache +0 -1
  34. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/6g/6gkpMq6BGSOyooWUFJJQCs2k3-tT0WID6Vg4wknhJoM.cache +0 -0
  35. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/8K/8KNXqSB0siJpEjgLM64KpfTgX1FSbkYKxWso4jP9F6U.cache +0 -0
  36. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/Bf/BfiLjztc-8aILuCwNaYiWOika9XKeEiGNJJJK_LCEr4.cache +0 -0
  37. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/CM/CMaRV8szi0IicAXD33YjDgWpLw468X08ycoS-ndwO5o.cache +0 -0
  38. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/Cc/CcghYxY4f6VUjmyR9LJJi0rYn2LXCdBR9t8Qn4SroL8.cache +0 -0
  39. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/Cj/CjEM6wfYwxY_zG--WNzelIKjC420AU9WpvQLgolQOPM.cache +0 -1
  40. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/Cj/cJJ0QWQg4eJ37I13drpPfSy27rwN7iqiQYPswqRm_Po.cache +0 -0
  41. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/E2/E2tGPoiGjrMuq9vL-ndjkozskpSFwLcGQXxJf_dl4z0.cache +0 -0
  42. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/EN/ENHTZiiuQ1cqn16401VaQQBp7b0gwZOA7_I-W5CL5ig.cache +0 -1
  43. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/EV/EVkLQJ6idLBSbQnkUelhejMxSOql0wh2QbtfKpdJiak.cache +0 -1
  44. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/Gg/Gg6i-z0G_WiBfMUE_gmveurGXQff5_TlQi29HwQcZ-8.cache +0 -1
  45. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/Go/Gohhb2B4rJ5hYmGM-VhZxS5dB_NFtsEAdbP1kTKDUeU.cache +0 -0
  46. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/IH/IHM0sjf5lujHT6BG1cYKLB0rdqCd1KYYR5SLZkxXi1k.cache +0 -1
  47. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/NS/NSFU7p8JOb9tHDvG74s3jdRt4ONYZoCTluL3HEsrPxc.cache +0 -0
  48. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/OX/OXQFRQZ5OA2i3YtnP1fZ96aWeUC3_IIqO4fAMdR9FsM.cache +0 -2
  49. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/Oi/OiV2J0lyHQgXCDgtmFPNLE59EbztPsv9MNy05s943Yw.cache +0 -2
  50. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/Ps/PsVVU35DPe0tSyJ1zEoiPaaJiwo6NclhO2OKuFSn76A.cache +0 -0
  51. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/R-/R-onhPbfjYnU6tM9fR0wZkXDSvCLrY5G1wyNCSVmKEs.cache +0 -1
  52. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/RR/RRXzNBrpSlU0RGhaxTSE_1GoRrV4JkWqF0ZoOf9xtzQ.cache +0 -0
  53. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/Rd/Rd_ZtA5c34XyxDbTpkN8_ZfF1x78s46DbRXLu0jqMgo.cache +0 -1
  54. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/Sm/SmJRxdUchUsyyMi6zvsdwrcRR1hfQ9YeSZNKNM-n5lw.cache +0 -0
  55. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/Su/Sue46_TUXTlImzpNh2bkqDFL5cQ08rCAcaaJqlWI7qg.cache +0 -0
  56. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/T1/T1lVNy8C6VpxjRsI38DgOfG7yIh3OohPWTNZmJb8CPo.cache +0 -0
  57. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/Z-/Z-P7NJ7vzHin8mjLSAoWJW6FZfd6xwWS3xuoCX0DE40.cache +0 -0
  58. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/Z9/Z9d8_EzLy9N7tx_nHmbmBF5LzFtW_0sik4AH1IFBX0Y.cache +0 -1
  59. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/Ze/ZelUAL6jLQcQiGZUfnAbvuJbU9OAqHiXV_Ccu8lToho.cache +0 -1
  60. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/Zr/Zr7RfTTM_QNQ-7MuSD-M0rF18yH25tCSI9G4H5yYjAQ.cache +0 -1
  61. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/_S/_SxbUQwhqQU8951QbOA6ZZ41F0d9D-VhhQqUE4BCryQ.cache +0 -0
  62. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/_o/_okSFa_t7W5YJBZTW7ZitTwnmAFYgJup7tpTYum0Udo.cache +0 -1
  63. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/aJ/aJ4EkukIrCHlOkA1WpQIasGGosjGkOKvRMsfcNQx1QQ.cache +0 -0
  64. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/bk/bk_rOYlFWoHkh4HHsvbxeo8rSvDWRX6cCbVlO2VCVNA.cache +0 -1
  65. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/cO/cOGLhXoKF0BumBbtviyCY1xusm_WMEMhGSWY9qFekRU.cache +0 -2
  66. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/cq/cqMX8l9XlG5jEWd0fWjA7MTlj21d6dzcnhhOq08uFHY.cache +0 -0
  67. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/cy/cyurAtFfq8D4ORO-aDATDzTKcBumJfgafhOUCbECuMw.cache +0 -0
  68. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/eO/eOY3YH36a6yvdznpQqACMiI0e1CcTwPiEjUdhRfmm9k.cache +0 -0
  69. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/f3/f3VckKo5w8mrxeqmzwLfZr7f6sj0dA8xZrFq3GMF0ig.cache +0 -1
  70. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/fS/fSn1A2ssuKdsdJ-uwH_i8bXBaWmbJd0wHd-Ob6pTPi0.cache +0 -1
  71. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/gD/gDQJ-WkVLldqzYHKOLkamKeU-sTkDscHqOQawz7a6m4.cache +0 -0
  72. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/hj/hj8Ir9wcVSy1KYrnWu9bpD24vDhCG3tvt-nKbNxb1Wg.cache +0 -0
  73. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/jH/jHvwYeln0CEBatCDHIjJMF0vIdmuDmS_eTKNxFhOmlA.cache +0 -1
  74. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/jU/jUktWNbR4V7n34UAZe7uJpmEofhflF0bVtIO2BgxyJ8.cache +0 -2
  75. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/jb/jb46fu3q3DLQ7TFyiuaXmL_CPF7cQst2RgrF0xVyGtA.cache +0 -1
  76. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/le/lekrQ_bDFewtYzH2xoA2tovuPzYdoSwnauQ4MgDwb0U.cache +0 -1
  77. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/m8/m8I0GZ1puWB4hISNebXEGDX3G5QkoSVWHP4SiRvN-3Y.cache +0 -0
  78. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/mn/mNEeM32MBaqiZ0_N_eheQR9oimoBpmcXRXr5puTAh3o.cache +0 -0
  79. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/mn/mNaj9zqaawn26kC4FL9ECzN5lkppnwTTQ93MIeJRKZg.cache +0 -1
  80. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/mn/mnJy7Ei2tJLs8tfmmUHjtWmfk2yfl1opoYG7Deg2bWQ.cache +0 -0
  81. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/oC/oCsZTGZyV4kH8Y4OeSDUdrwfkJFPzTODZjuBKZB8oGQ.cache +0 -0
  82. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/oS/oS5JF4El36MylOD0SJtv4YV-fsqNzd89t1IqlBzwYes.cache +0 -1
  83. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/oY/oYCeXuzhz0IQEBtepScpQ7HlUp5yVleUE6BOLsnhXwA.cache +0 -1
  84. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/oZ/oZDDUJWB1xgHo4uv_iiUCtutWZ6LeJykII3cNkmd_bA.cache +0 -1
  85. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/q6/q6BYa32YJF11eGVapO4ouNl6gayPIsARgMavlzZmoi0.cache +0 -0
  86. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/u-/u-Iidm4zcU2RFkiqJFQkLTBxXuEoF5gCeJM4V5-3Qyc.cache +0 -0
  87. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/uK/uKpQUG2ys9fKuyfsrw1Payh72LhuIrYJXep13nTbIIc.cache +0 -1
  88. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/uX/uXHfYanP3WS7whlKHqs0pLBkEQwj_IGbfmktFdHfZ_A.cache +0 -0
  89. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/v9/v9HWdIdg3uuXOOqxWg8Y6aWxzqbywfxecFSDm5ilUs8.cache +0 -1
  90. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/w2/w2izaLMTzGRpPOq1R_Yl-0Ma7hm7tej5kSjV9khvFSk.cache +0 -1
  91. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/x7/x7KkTV3ibfIEysLB_ug5bfmnn2VLV_BldukPR3EoPBk.cache +0 -0
  92. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/y4/y4-jRuYEQUuCPpXrCIiCC1lgXmW4pm12ZEla-d56noA.cache +0 -1
  93. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/yW/yWlGtA8E8Li2epEGqbxtvBeb5h0e52XZQ8xKiMXgDOY.cache +0 -1
  94. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/yZ/yZRcLaNBQxCgGewY_IaXZrXG1YmOhr1iSxfZ-4MMK9Y.cache +0 -0
  95. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/zU/zUYxN3uLSvSCpp561lMJSJXPGanKNgxT32rw-w5jpPs.cache +0 -0
  96. data/spec/dummy/tmp/restart.txt +0 -0
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 1e682837dca15bd556e399c58a64744e5779aea9
4
- data.tar.gz: 8ed995c29acdda9688394ff1b74d9c7162d60b8d
2
+ SHA256:
3
+ metadata.gz: 76d677891a37b6bf242cc2ecdccac253d00e74d980c4c674f1e4e258a23c27aa
4
+ data.tar.gz: 6bbe344b51c76817b5f91e5db0196a8ff651a8ed668c15e8c24f809357fe7568
5
5
  SHA512:
6
- metadata.gz: 2011800c2f0f947f871695ed2e5c8685e6b9cf1a8086ab098fbe7b77a8aca374086a8a07481f66a39954392dba96769afe045bdd59c21801fc5604d70d18823b
7
- data.tar.gz: d9d6d2170c82c3c22e2751830af0acad3b30b347246c7ca9117506f993cbee03f37b9178010387c9b2ceff20aad070a2a39d5bfea6f6c3a3c9f1ce1f699b8276
6
+ metadata.gz: 0105eb59ada39b9121ad1aad63e72f7c8f9d1d717ef9cfa85ad5189b9aedf06aa61bc165265289ca55e783546ce2713f720fe26d900116b3cbe5f9d84a921587
7
+ data.tar.gz: 850bbffb9e6233f2c15009073a463ecfed670bb46db08a5b62afd5abdd8dcb5df0eee57f580872a1603cc84f897dcd4997d2d7e09c8361b384d63a2535b54640
@@ -2,4 +2,6 @@
2
2
 
3
3
  <p>Error: <%= @error_message %></p>
4
4
 
5
- <a href="/auth/bookingsync">Sign in again</a>
5
+ <%= form_tag("/auth/bookingsync", method: :post) do %>
6
+ <button type="submit">Sign in again</button>
7
+ <% end %>
@@ -1,5 +1,3 @@
1
- require "bookingsync"
2
-
3
1
  module BookingSyncEngine
4
2
  cattr_accessor :support_multi_applications
5
3
  self.support_multi_applications = false
@@ -10,6 +8,15 @@ module BookingSyncEngine
10
8
  cattr_accessor :multi_app_model
11
9
  self.multi_app_model = -> { ::Account }
12
10
 
11
+ cattr_accessor :oauth_client_connection_options
12
+ self.oauth_client_connection_options = { request: { timeout: 2 } }
13
+
14
+ cattr_accessor :token_refresh_timeout_retry_count
15
+ self.token_refresh_timeout_retry_count = 2
16
+
17
+ cattr_accessor :bookingsync_id_key
18
+ self.bookingsync_id_key = :synced_id
19
+
13
20
  def self.setup
14
21
  yield self
15
22
  end
@@ -22,3 +29,5 @@ module BookingSyncEngine
22
29
  support_multi_applications? ? multi_app_model.call : single_app_model.call
23
30
  end
24
31
  end
32
+
33
+ require "bookingsync"
@@ -7,8 +7,8 @@ module BookingSync
7
7
  initializer "bookingsync.add_omniauth" do |app|
8
8
  app.middleware.use OmniAuth::Builder do
9
9
  provider :bookingsync,
10
- BookingSyncEngine.support_multi_applications? ? nil : ENV["BOOKINGSYNC_APP_ID"],
11
- BookingSyncEngine.support_multi_applications? ? nil : ENV["BOOKINGSYNC_APP_SECRET"],
10
+ ::BookingSyncEngine.support_multi_applications? ? nil : ENV["BOOKINGSYNC_APP_ID"],
11
+ ::BookingSyncEngine.support_multi_applications? ? nil : ENV["BOOKINGSYNC_APP_SECRET"],
12
12
  scope: ENV["BOOKINGSYNC_SCOPE"],
13
13
  setup: -> (env) {
14
14
  if url = ENV["BOOKINGSYNC_URL"]
@@ -18,7 +18,7 @@ module BookingSync
18
18
  verify: ENV["BOOKINGSYNC_VERIFY_SSL"] != "false"
19
19
  }
20
20
 
21
- if BookingSyncEngine.support_multi_applications?
21
+ if ::BookingSyncEngine.support_multi_applications?
22
22
  credentials = BookingSync::Engine::CredentialsResolver.new(env["HTTP_HOST"]).call
23
23
  if credentials.valid?
24
24
  env["omniauth.strategy"].options[:client_id] = credentials.client_id
@@ -76,16 +76,24 @@ module BookingSync
76
76
  #
77
77
  # @return [OAuth2::Client] configured OAuth client
78
78
  def self.oauth_client(client_id: ENV["BOOKINGSYNC_APP_ID"], client_secret: ENV["BOOKINGSYNC_APP_SECRET"])
79
+ connection_options = {
80
+ headers: { accept: "application/vnd.api+json" }
81
+ }.merge(::BookingSyncEngine.oauth_client_connection_options)
82
+
79
83
  client_options = {
80
84
  site: ENV["BOOKINGSYNC_URL"] || 'https://www.bookingsync.com',
81
- connection_opts: { headers: { accept: "application/vnd.api+json" } }
85
+ connection_opts: connection_options
82
86
  }
83
87
  client_options[:ssl] = { verify: ENV['BOOKINGSYNC_VERIFY_SSL'] != 'false' }
84
88
  OAuth2::Client.new(client_id, client_secret, client_options)
85
89
  end
86
90
 
87
91
  def self.application_token(client_id: ENV["BOOKINGSYNC_APP_ID"], client_secret: ENV["BOOKINGSYNC_APP_SECRET"])
88
- oauth_client(client_id: client_id, client_secret: client_secret).client_credentials.get_token
92
+ token_refresh_timeout_attempts_allowed = ::BookingSyncEngine.token_refresh_timeout_retry_count + 1
93
+
94
+ BookingSync::Engine::Retryable.perform(times: token_refresh_timeout_attempts_allowed, errors: [Faraday::TimeoutError]) do
95
+ oauth_client(client_id: client_id, client_secret: client_secret).client_credentials.get_token
96
+ end
89
97
  end
90
98
  end
91
99
  end
@@ -94,3 +102,4 @@ require "bookingsync/engine/application_credentials"
94
102
  require "bookingsync/engine/credentials_resolver"
95
103
  require "bookingsync/engine/api_client"
96
104
  require "bookingsync/engine/models"
105
+ require "bookingsync/engine/retryable"
@@ -1,3 +1,5 @@
1
+ require "repost"
2
+
1
3
  module BookingSync::Engine::AuthHelpers
2
4
  extend ActiveSupport::Concern
3
5
 
@@ -16,7 +18,7 @@ module BookingSync::Engine::AuthHelpers
16
18
  return if session[:account_id].nil?
17
19
 
18
20
  @current_account ||=
19
- BookingSyncEngine.account_model.find_by_host_and_synced_id(request.host, session[:account_id])
21
+ ::BookingSyncEngine.account_model.find_by_host_and_bookingsync_id_key(request.host, session[:account_id])
20
22
  end
21
23
 
22
24
  # Callback after account is authorized.
@@ -25,7 +27,7 @@ module BookingSync::Engine::AuthHelpers
25
27
  #
26
28
  # @param account [Account] the just authorized account
27
29
  def account_authorized(account)
28
- session[:account_id] = account.synced_id.to_s
30
+ session[:account_id] = account.public_send(BookingSyncEngine.bookingsync_id_key).to_s
29
31
  end
30
32
 
31
33
  # Clear authorization if the account passed from the BookingSync app store
@@ -58,20 +60,32 @@ module BookingSync::Engine::AuthHelpers
58
60
 
59
61
  # Request a new authorization.
60
62
  def request_authorization!
61
- if request.xhr?
62
- request_authorization_for_xhr!
63
- elsif BookingSync::Engine.embedded
64
- request_authorization_for_embedded!
65
- else
66
- request_authorization_for_standalone!
63
+ respond_to do |format|
64
+ format.html do
65
+ if request.xhr?
66
+ request_authorization_for_xhr!
67
+ elsif BookingSync::Engine.embedded
68
+ request_authorization_for_embedded!
69
+ else
70
+ request_authorization_for_standalone!
71
+ end
72
+ end
73
+
74
+ format.json do
75
+ head :unauthorized
76
+ end
77
+
78
+ format.api_json do
79
+ head :unauthorized
80
+ end
67
81
  end
68
82
  end
69
83
 
70
84
  # Request a new authorization for Ajax requests.
71
85
  #
72
- # Renders the new authorization path with 401 Unauthorized status by default.
86
+ # Renders the new auto submit form with 401 Unauthorized status by default.
73
87
  def request_authorization_for_xhr!
74
- render plain: new_authorization_url, status: :unauthorized
88
+ render html: auto_submit_form_html, status: :unauthorized
75
89
  end
76
90
 
77
91
  # Request a new authorization for Embedded Apps.
@@ -79,23 +93,23 @@ module BookingSync::Engine::AuthHelpers
79
93
  # Load the new authorization path using Javascript by default.
80
94
  def request_authorization_for_embedded!
81
95
  allow_bookingsync_iframe
82
- render html: ("<script type='text/javascript'>top.location.href = " +
83
- "'#{new_authorization_path}';</script>").html_safe
96
+ render html: auto_submit_form_html
84
97
  end
85
98
 
86
99
  # Request a new authorization for Standalone Apps.
87
100
  #
88
101
  # Redirects to new authorization path by default.
89
102
  def request_authorization_for_standalone!
90
- redirect_to new_authorization_path
103
+ render html: auto_submit_form_html
91
104
  end
92
105
 
93
- # Path to which the user should be redirected to start a new
106
+ # Path which will be used in POST request to start a new
94
107
  # Authorization process.
95
108
  #
96
- # Default to /auth/bookingsync/?account_id=SESSION_BOOKINGSYNC_ACCOUNT_ID
109
+ # Default to /auth/bookingsync
110
+ NEW_AUTHORIZATION_URL = "/auth/bookingsync".freeze
97
111
  def new_authorization_path
98
- "/auth/bookingsync/?account_id=#{session[:_bookingsync_account_id]}"
112
+ NEW_AUTHORIZATION_URL
99
113
  end
100
114
 
101
115
  def new_authorization_url
@@ -141,4 +155,12 @@ module BookingSync::Engine::AuthHelpers
141
155
  def store_bookingsync_account_id # :nodoc:
142
156
  session[:_bookingsync_account_id] = params.delete(:_bookingsync_account_id)
143
157
  end
158
+
159
+ def auto_submit_form_html
160
+ Repost::Senpai.perform(
161
+ new_authorization_path,
162
+ params: { account_id: session[:_bookingsync_account_id] },
163
+ options: { authenticity_token: Rack::Protection::AuthenticityToken.token(session) }
164
+ ).html_safe
165
+ end
144
166
  end
@@ -3,12 +3,12 @@ module BookingSync::Engine::Models::Account
3
3
  include BookingSync::Engine::Models::BaseAccount
4
4
 
5
5
  included do
6
- validates :synced_id, uniqueness: true
6
+ validates BookingSyncEngine.bookingsync_id_key, uniqueness: true
7
7
  end
8
8
 
9
9
  module ClassMethods
10
10
  def from_omniauth(auth, _host)
11
- account = find_or_initialize_by(synced_id: auth.uid, provider: auth.provider)
11
+ account = find_or_initialize_by(BookingSyncEngine.bookingsync_id_key => auth.uid, provider: auth.provider)
12
12
 
13
13
  account.tap do |account|
14
14
  account.name = auth.info.business_name
@@ -17,8 +17,14 @@ module BookingSync::Engine::Models::Account
17
17
  end
18
18
  end
19
19
 
20
+ def find_by_host_and_bookingsync_id_key(_host, bookingsync_id)
21
+ find_by(BookingSyncEngine.bookingsync_id_key => bookingsync_id)
22
+ end
23
+
24
+ # DEPRECATED: Please use find_by_host_and_bookingsync_id_key instead.
20
25
  def find_by_host_and_synced_id(_host, synced_id)
21
- find_by(synced_id: synced_id)
26
+ warn("DEPRECATED: find_by_host_and_synced_id is deprecated, use #find_by_host_and_bookingsync_id_key instead. It will be removed with the release of version 6 of this gem. Called from #{Gem.location_of_caller.join(":")}")
27
+ find_by_host_and_bookingsync_id_key(nil, synced_id)
22
28
  end
23
29
  end
24
30
 
@@ -10,7 +10,7 @@ module BookingSync::Engine::Models::BaseAccount
10
10
  token_options = {}
11
11
  if oauth_refresh_token
12
12
  token_options[:refresh_token] = oauth_refresh_token
13
- token_options[:expires_at] = oauth_expires_at
13
+ token_options[:expires_at] = oauth_expires_at && oauth_expires_at.to_i
14
14
  end
15
15
 
16
16
  token = OAuth2::AccessToken.new(oauth_client, oauth_access_token, token_options)
@@ -40,12 +40,14 @@ module BookingSync::Engine::Models::BaseAccount
40
40
  self.oauth_expires_at = token.expires_at
41
41
  end
42
42
 
43
- private
44
-
45
43
  def refresh_token!(current_token = token)
46
- @token = current_token.refresh!.tap do |new_token|
47
- update_token(new_token)
48
- save!
44
+ token_refresh_timeout_attempts_allowed = ::BookingSyncEngine.token_refresh_timeout_retry_count + 1
45
+
46
+ BookingSync::Engine::Retryable.perform(times: token_refresh_timeout_attempts_allowed, errors: [Faraday::TimeoutError]) do
47
+ @token = current_token.refresh!.tap do |new_token|
48
+ update_token(new_token)
49
+ save!
50
+ end
49
51
  end
50
52
  end
51
53
  end
@@ -3,7 +3,7 @@ module BookingSync::Engine::Models::MultiApplicationsAccount
3
3
  include BookingSync::Engine::Models::BaseAccount
4
4
 
5
5
  included do
6
- validates :synced_id, uniqueness: { scope: :host }
6
+ validates BookingSyncEngine.bookingsync_id_key, uniqueness: { scope: :host }
7
7
  end
8
8
 
9
9
  module ClassMethods
@@ -13,7 +13,7 @@ module BookingSync::Engine::Models::MultiApplicationsAccount
13
13
  "multi application support"
14
14
  end
15
15
 
16
- account = find_or_initialize_by(host: host, synced_id: auth.uid, provider: auth.provider)
16
+ account = find_or_initialize_by(host: host, provider: auth.provider, BookingSyncEngine.bookingsync_id_key => auth.uid)
17
17
 
18
18
  account.tap do |account|
19
19
  account.name = auth.info.business_name
@@ -22,8 +22,14 @@ module BookingSync::Engine::Models::MultiApplicationsAccount
22
22
  end
23
23
  end
24
24
 
25
+ def find_by_host_and_bookingsync_id_key(host, bookingsync_id)
26
+ find_by(host: host, BookingSyncEngine.bookingsync_id_key => bookingsync_id)
27
+ end
28
+
29
+ # DEPRECATED: Please use find_by_host_and_bookingsync_id_key instead.
25
30
  def find_by_host_and_synced_id(host, synced_id)
26
- find_by(host: host, synced_id: synced_id)
31
+ warn("DEPRECATED: find_by_host_and_synced_id is deprecated, use #find_by_host_and_bookingsync_id_key instead. It will be removed with the release of version 5 of this gem. Called from #{Gem.location_of_caller.join(":")}")
32
+ find_by_host_and_bookingsync_id_key(host, synced_id)
27
33
  end
28
34
  end
29
35
 
@@ -0,0 +1,16 @@
1
+ class BookingSync::Engine::Retryable
2
+ def self.perform(times:, errors:, before_retry: ->(_error) {})
3
+ executed = 0
4
+ begin
5
+ executed += 1
6
+ yield
7
+ rescue *errors => error
8
+ if executed < times
9
+ before_retry.call(error)
10
+ retry
11
+ else
12
+ raise error
13
+ end
14
+ end
15
+ end
16
+ end
@@ -1,3 +1,3 @@
1
1
  module BookingSync
2
- ENGINE_VERSION = "4.0.1"
2
+ ENGINE_VERSION = "6.0.0"
3
3
  end
@@ -1,15 +1,19 @@
1
1
  require "spec_helper"
2
2
 
3
3
  RSpec.describe AuthenticatedController, type: :controller do
4
+ before do
5
+ Mime::Type.register "application/vnd.api+json", :api_json
6
+ end
7
+
4
8
  describe "GET index" do
5
9
  context "when engine is embedded" do
6
10
  before { BookingSync::Engine.embedded! }
7
11
 
8
- it "redirects to auth using js" do
12
+ it "renders autosubmitted form" do
9
13
  get :index
10
14
  expect(response.status).to eq(200)
11
- expect(response.body).to eq(
12
- "<script type='text/javascript'>top.location.href = '/auth/bookingsync/?account_id=';</script>")
15
+ expect(response.body).to include("action='/auth/bookingsync' method='post'")
16
+ expect(response.body).to include("<input type='hidden' name='account_id' value=''>")
13
17
  expect(response.header["Content-Type"]).to include("text/html")
14
18
  end
15
19
  end
@@ -17,12 +21,11 @@ RSpec.describe AuthenticatedController, type: :controller do
17
21
  context "when engine is standalone" do
18
22
  before { BookingSync::Engine.standalone! }
19
23
 
20
- it "redirects to auth using 302 redirect" do
24
+ it "renders autosubmitted form" do
21
25
  get :index
22
- expect(response.status).to eq(302)
23
- expect(response.redirect_url).to eq("http://test.host/auth/bookingsync/?account_id=")
24
- expect(response.body).to eq(
25
- "<html><body>You are being <a href=\"http://test.host/auth/bookingsync/?account_id=\">redirected</a>.</body></html>")
26
+ expect(response.status).to eq(200)
27
+ expect(response.body).to include("action='/auth/bookingsync' method='post'")
28
+ expect(response.body).to include("<input type='hidden' name='account_id' value=''>")
26
29
  end
27
30
  end
28
31
  end
@@ -31,20 +34,41 @@ RSpec.describe AuthenticatedController, type: :controller do
31
34
  context "when engine is embedded" do
32
35
  before { BookingSync::Engine.embedded! }
33
36
 
34
- it "renders the target url in response" do
37
+ it "renders autosubmitted form" do
35
38
  get :index, xhr: true
36
39
  expect(response.status).to eq(401)
37
- expect(response.body).to eq("http://test.host/auth/bookingsync/?account_id=")
40
+ expect(response.body).to include("action='/auth/bookingsync' method='post'")
41
+ expect(response.body).to include("<input type='hidden' name='account_id' value=''>")
38
42
  end
39
43
  end
40
44
 
41
45
  context "when engine is standalone" do
42
46
  before { BookingSync::Engine.standalone! }
43
47
 
44
- it "renders the target url in response" do
48
+ it "renders autosubmitted form" do
45
49
  get :index, xhr: true
46
50
  expect(response.status).to eq(401)
47
- expect(response.body).to eq("http://test.host/auth/bookingsync/?account_id=")
51
+ expect(response.body).to include("action='/auth/bookingsync' method='post'")
52
+ expect(response.body).to include("<input type='hidden' name='account_id' value=''>")
53
+ end
54
+ end
55
+ end
56
+
57
+ describe "API request" do
58
+ it "returns 401 without response body" do
59
+ get :index, format: :json
60
+ expect(response.status).to eq(401)
61
+ expect(response.body).to eq("")
62
+ end
63
+
64
+ context "with vnd.api+json content type" do
65
+ it "returns 401 without response body" do
66
+ request.headers["CONTENT_TYPE"] = "application/vnd.api+json"
67
+ request.headers["ACCEPT"] = "application/vnd.api+json"
68
+
69
+ get :index
70
+ expect(response.status).to eq(401)
71
+ expect(response.body).to eq("")
48
72
  end
49
73
  end
50
74
  end
@@ -0,0 +1,3 @@
1
+ //= link_tree ../images
2
+ //= link_directory ../javascripts .js
3
+ //= link_directory ../stylesheets .css
@@ -1,3 +1,11 @@
1
+ # temporarily change default to make sure initializer override works great
2
+ BookingSyncEngine.module_eval do
3
+ self.bookingsync_id_key = :customized_key
4
+ end
5
+
6
+ # and now override to fix breaking specs
1
7
  BookingSyncEngine.setup do |setup|
2
8
  setup.multi_app_model = -> { ::MultiApplicationsAccount }
9
+
10
+ setup.bookingsync_id_key = :synced_id
3
11
  end
@@ -0,0 +1,5 @@
1
+ class AddCustomBookingSyncKeyIdToAccounts < ActiveRecord::Migration[5.2]
2
+ def change
3
+ add_column :accounts, :customized_key, :integer
4
+ end
5
+ end
@@ -0,0 +1,5 @@
1
+ class AddCustomBookingSyncKeyIdToMultiApplicationsAccounts < ActiveRecord::Migration[5.2]
2
+ def change
3
+ add_column :multi_applications_accounts, :customized_key, :integer
4
+ end
5
+ end
@@ -10,7 +10,7 @@
10
10
  #
11
11
  # It's strongly recommended that you check this file into your version control system.
12
12
 
13
- ActiveRecord::Schema.define(version: 2018_11_30_063104) do
13
+ ActiveRecord::Schema.define(version: 2019_06_23_220132) do
14
14
 
15
15
  # These are extensions that must be enabled in order to support this database
16
16
  enable_extension "plpgsql"
@@ -24,6 +24,7 @@ ActiveRecord::Schema.define(version: 2018_11_30_063104) do
24
24
  t.string "oauth_access_token"
25
25
  t.string "oauth_refresh_token"
26
26
  t.string "oauth_expires_at"
27
+ t.integer "customized_key"
27
28
  t.index ["synced_id"], name: "index_accounts_on_synced_id"
28
29
  end
29
30
 
@@ -48,6 +49,7 @@ ActiveRecord::Schema.define(version: 2018_11_30_063104) do
48
49
  t.string "oauth_refresh_token"
49
50
  t.string "oauth_expires_at"
50
51
  t.string "host", null: false
52
+ t.integer "customized_key"
51
53
  t.index ["host", "synced_id"], name: "index_multi_applications_accounts_on_host_and_synced_id", unique: true
52
54
  t.index ["host"], name: "index_multi_applications_accounts_on_host"
53
55
  t.index ["synced_id"], name: "index_multi_applications_accounts_on_synced_id"