bookingsync-engine 3.0.2 → 4.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (112) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +101 -5
  3. data/app/controllers/sessions_controller.rb +1 -1
  4. data/lib/bookingsync-engine.rb +24 -1
  5. data/lib/bookingsync/engine.rb +26 -17
  6. data/lib/bookingsync/engine/application_credentials.rb +15 -0
  7. data/lib/bookingsync/engine/auth_helpers.rb +5 -2
  8. data/lib/bookingsync/engine/credentials_resolver.rb +18 -0
  9. data/lib/bookingsync/engine/models.rb +11 -0
  10. data/lib/bookingsync/engine/models/account.rb +36 -0
  11. data/lib/bookingsync/engine/models/application.rb +9 -0
  12. data/lib/bookingsync/engine/{model.rb → models/base_account.rb} +15 -27
  13. data/lib/bookingsync/engine/models/multi_applications_account.rb +47 -0
  14. data/lib/bookingsync/engine/version.rb +1 -1
  15. data/spec/controllers/authenticated_controller_spec.rb +1 -1
  16. data/spec/controllers/sessions_controller_spec.rb +28 -4
  17. data/spec/dummy/app/models/account.rb +1 -1
  18. data/spec/dummy/app/models/application.rb +3 -0
  19. data/spec/dummy/app/models/application_record.rb +3 -0
  20. data/spec/dummy/app/models/multi_applications_account.rb +3 -0
  21. data/spec/dummy/config/database.yml.docker +11 -0
  22. data/spec/dummy/config/initializers/bookingsync-engine.rb +3 -0
  23. data/spec/dummy/db/migrate/20140522110326_create_accounts.rb +1 -1
  24. data/spec/dummy/db/migrate/20140522110454_add_o_auth_fields_to_accounts.rb +1 -1
  25. data/spec/dummy/db/migrate/20181130062531_create_multi_applications_accounts.rb +8 -0
  26. data/spec/dummy/db/migrate/20181130062650_add_o_auth_fields_to_multi_applications_accounts.rb +14 -0
  27. data/spec/dummy/db/migrate/20181130063056_create_applications.rb +8 -0
  28. data/spec/dummy/db/migrate/20181130063104_add_credentials_fields_to_applications.rb +10 -0
  29. data/spec/dummy/db/schema.rb +41 -10
  30. data/spec/dummy/log/development.log +7423 -16
  31. data/spec/dummy/log/test.log +62430 -617
  32. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/0A/0AkQ3CITU4KXnU7GsiDQLAWeLkJApWK8LSS1j7wEk2I.cache +0 -0
  33. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/1M/1MTKfLxlwDryDP9C4ksVeuOF5FekTW5EddfnaJ4ujrA.cache +0 -0
  34. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/2F/2FjAKNLL-jC6FeYfXsL0M8jItncHQcdDy239KNsTZQs.cache +1 -0
  35. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/2_/2_hJriYgvh3UGtv5NMhrnkrtfpJlyTuQ4F5jYdVf8sQ.cache +1 -0
  36. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/3J/3JfiofMyqvbHq3sZznFIDsFS81fHxyAWoCXJLrtrWP4.cache +0 -0
  37. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/3f/3fwING3B2z9NOnWMwdXFatlVw06vge46KkOWOII0KlU.cache +1 -0
  38. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/4i/4iLsjcOzC2_Y0hxnbPKuyayJABeUFDSyIh4Ed9OA8Xw.cache +0 -0
  39. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/50/502uMBbq2ELFXg5u1vtykxQ_whhsdgQnmTwNA96niD0.cache +0 -0
  40. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/5s/5sm0UHvqondwU5MMfjMuqvLW2WQ6S7ylUf9PNw2uCTc.cache +1 -0
  41. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/6F/6F2x1Bu3NKSTCTwUS6iCRFhKRT_ntZMzmPIMnVGabK4.cache +1 -0
  42. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/6g/6gkpMq6BGSOyooWUFJJQCs2k3-tT0WID6Vg4wknhJoM.cache +0 -0
  43. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/8K/8KNXqSB0siJpEjgLM64KpfTgX1FSbkYKxWso4jP9F6U.cache +0 -0
  44. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/Bf/BfiLjztc-8aILuCwNaYiWOika9XKeEiGNJJJK_LCEr4.cache +0 -0
  45. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/CM/CMaRV8szi0IicAXD33YjDgWpLw468X08ycoS-ndwO5o.cache +0 -0
  46. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/Cc/CcghYxY4f6VUjmyR9LJJi0rYn2LXCdBR9t8Qn4SroL8.cache +0 -0
  47. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/Cj/CjEM6wfYwxY_zG--WNzelIKjC420AU9WpvQLgolQOPM.cache +1 -0
  48. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/Cj/cJJ0QWQg4eJ37I13drpPfSy27rwN7iqiQYPswqRm_Po.cache +0 -0
  49. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/E2/E2tGPoiGjrMuq9vL-ndjkozskpSFwLcGQXxJf_dl4z0.cache +0 -0
  50. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/EN/ENHTZiiuQ1cqn16401VaQQBp7b0gwZOA7_I-W5CL5ig.cache +1 -0
  51. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/EV/EVkLQJ6idLBSbQnkUelhejMxSOql0wh2QbtfKpdJiak.cache +1 -0
  52. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/Gg/Gg6i-z0G_WiBfMUE_gmveurGXQff5_TlQi29HwQcZ-8.cache +1 -0
  53. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/Go/Gohhb2B4rJ5hYmGM-VhZxS5dB_NFtsEAdbP1kTKDUeU.cache +0 -0
  54. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/IH/IHM0sjf5lujHT6BG1cYKLB0rdqCd1KYYR5SLZkxXi1k.cache +1 -0
  55. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/NS/NSFU7p8JOb9tHDvG74s3jdRt4ONYZoCTluL3HEsrPxc.cache +0 -0
  56. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/OX/OXQFRQZ5OA2i3YtnP1fZ96aWeUC3_IIqO4fAMdR9FsM.cache +2 -0
  57. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/Oi/OiV2J0lyHQgXCDgtmFPNLE59EbztPsv9MNy05s943Yw.cache +2 -0
  58. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/Ps/PsVVU35DPe0tSyJ1zEoiPaaJiwo6NclhO2OKuFSn76A.cache +0 -0
  59. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/R-/R-onhPbfjYnU6tM9fR0wZkXDSvCLrY5G1wyNCSVmKEs.cache +1 -0
  60. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/RR/RRXzNBrpSlU0RGhaxTSE_1GoRrV4JkWqF0ZoOf9xtzQ.cache +0 -0
  61. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/Rd/Rd_ZtA5c34XyxDbTpkN8_ZfF1x78s46DbRXLu0jqMgo.cache +1 -0
  62. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/Sm/SmJRxdUchUsyyMi6zvsdwrcRR1hfQ9YeSZNKNM-n5lw.cache +0 -0
  63. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/Su/Sue46_TUXTlImzpNh2bkqDFL5cQ08rCAcaaJqlWI7qg.cache +0 -0
  64. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/T1/T1lVNy8C6VpxjRsI38DgOfG7yIh3OohPWTNZmJb8CPo.cache +0 -0
  65. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/Z-/Z-P7NJ7vzHin8mjLSAoWJW6FZfd6xwWS3xuoCX0DE40.cache +0 -0
  66. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/Z9/Z9d8_EzLy9N7tx_nHmbmBF5LzFtW_0sik4AH1IFBX0Y.cache +1 -0
  67. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/Ze/ZelUAL6jLQcQiGZUfnAbvuJbU9OAqHiXV_Ccu8lToho.cache +1 -0
  68. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/Zr/Zr7RfTTM_QNQ-7MuSD-M0rF18yH25tCSI9G4H5yYjAQ.cache +1 -0
  69. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/_S/_SxbUQwhqQU8951QbOA6ZZ41F0d9D-VhhQqUE4BCryQ.cache +0 -0
  70. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/_o/_okSFa_t7W5YJBZTW7ZitTwnmAFYgJup7tpTYum0Udo.cache +1 -0
  71. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/aJ/aJ4EkukIrCHlOkA1WpQIasGGosjGkOKvRMsfcNQx1QQ.cache +0 -0
  72. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/bk/bk_rOYlFWoHkh4HHsvbxeo8rSvDWRX6cCbVlO2VCVNA.cache +1 -0
  73. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/cO/cOGLhXoKF0BumBbtviyCY1xusm_WMEMhGSWY9qFekRU.cache +2 -0
  74. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/cq/cqMX8l9XlG5jEWd0fWjA7MTlj21d6dzcnhhOq08uFHY.cache +0 -0
  75. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/cy/cyurAtFfq8D4ORO-aDATDzTKcBumJfgafhOUCbECuMw.cache +0 -0
  76. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/eO/eOY3YH36a6yvdznpQqACMiI0e1CcTwPiEjUdhRfmm9k.cache +0 -0
  77. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/f3/f3VckKo5w8mrxeqmzwLfZr7f6sj0dA8xZrFq3GMF0ig.cache +1 -0
  78. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/fS/fSn1A2ssuKdsdJ-uwH_i8bXBaWmbJd0wHd-Ob6pTPi0.cache +1 -0
  79. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/gD/gDQJ-WkVLldqzYHKOLkamKeU-sTkDscHqOQawz7a6m4.cache +0 -0
  80. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/hj/hj8Ir9wcVSy1KYrnWu9bpD24vDhCG3tvt-nKbNxb1Wg.cache +0 -0
  81. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/jH/jHvwYeln0CEBatCDHIjJMF0vIdmuDmS_eTKNxFhOmlA.cache +1 -0
  82. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/jU/jUktWNbR4V7n34UAZe7uJpmEofhflF0bVtIO2BgxyJ8.cache +2 -0
  83. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/jb/jb46fu3q3DLQ7TFyiuaXmL_CPF7cQst2RgrF0xVyGtA.cache +1 -0
  84. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/le/lekrQ_bDFewtYzH2xoA2tovuPzYdoSwnauQ4MgDwb0U.cache +1 -0
  85. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/m8/m8I0GZ1puWB4hISNebXEGDX3G5QkoSVWHP4SiRvN-3Y.cache +0 -0
  86. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/mn/mNEeM32MBaqiZ0_N_eheQR9oimoBpmcXRXr5puTAh3o.cache +0 -0
  87. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/mn/mNaj9zqaawn26kC4FL9ECzN5lkppnwTTQ93MIeJRKZg.cache +1 -0
  88. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/mn/mnJy7Ei2tJLs8tfmmUHjtWmfk2yfl1opoYG7Deg2bWQ.cache +0 -0
  89. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/oC/oCsZTGZyV4kH8Y4OeSDUdrwfkJFPzTODZjuBKZB8oGQ.cache +0 -0
  90. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/oS/oS5JF4El36MylOD0SJtv4YV-fsqNzd89t1IqlBzwYes.cache +1 -0
  91. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/oY/oYCeXuzhz0IQEBtepScpQ7HlUp5yVleUE6BOLsnhXwA.cache +1 -0
  92. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/oZ/oZDDUJWB1xgHo4uv_iiUCtutWZ6LeJykII3cNkmd_bA.cache +1 -0
  93. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/q6/q6BYa32YJF11eGVapO4ouNl6gayPIsARgMavlzZmoi0.cache +0 -0
  94. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/u-/u-Iidm4zcU2RFkiqJFQkLTBxXuEoF5gCeJM4V5-3Qyc.cache +0 -0
  95. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/uK/uKpQUG2ys9fKuyfsrw1Payh72LhuIrYJXep13nTbIIc.cache +1 -0
  96. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/uX/uXHfYanP3WS7whlKHqs0pLBkEQwj_IGbfmktFdHfZ_A.cache +0 -0
  97. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/v9/v9HWdIdg3uuXOOqxWg8Y6aWxzqbywfxecFSDm5ilUs8.cache +1 -0
  98. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/w2/w2izaLMTzGRpPOq1R_Yl-0Ma7hm7tej5kSjV9khvFSk.cache +1 -0
  99. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/x7/x7KkTV3ibfIEysLB_ug5bfmnn2VLV_BldukPR3EoPBk.cache +0 -0
  100. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/y4/y4-jRuYEQUuCPpXrCIiCC1lgXmW4pm12ZEla-d56noA.cache +1 -0
  101. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/yW/yWlGtA8E8Li2epEGqbxtvBeb5h0e52XZQ8xKiMXgDOY.cache +1 -0
  102. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/yZ/yZRcLaNBQxCgGewY_IaXZrXG1YmOhr1iSxfZ-4MMK9Y.cache +0 -0
  103. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/zU/zUYxN3uLSvSCpp561lMJSJXPGanKNgxT32rw-w5jpPs.cache +0 -0
  104. data/spec/dummy/tmp/restart.txt +0 -0
  105. data/spec/helpers/auth_helpers_spec.rb +42 -0
  106. data/spec/lib/bookingsync/engine/application_credentials_spec.rb +41 -0
  107. data/spec/lib/bookingsync/engine/credentials_resolver_spec.rb +18 -0
  108. data/spec/models/account_spec.rb +130 -41
  109. data/spec/models/application_spec.rb +16 -0
  110. data/spec/models/multi_application_account_spec.rb +247 -0
  111. data/spec/spec_helper.rb +6 -4
  112. metadata +256 -34
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: fa68e5ba114ee9b351c0dfacaec2c0d56f2cc64a
4
- data.tar.gz: 99916f007b04601ccb170e133a1470830eab6d1e
3
+ metadata.gz: bafa080b2693177194be61b73fb8fbc32ba466d0
4
+ data.tar.gz: 4c5254207f7fd9dfadb7f843c51e6bb5181b807c
5
5
  SHA512:
6
- metadata.gz: f97b8fc8de54d27ba06dc978b9d04e109642e54217525e92572d2b37f6f12d7e328a50e948192896b47f1154ff05a12aafa2a6312aacba36491c6d9d9db7686a
7
- data.tar.gz: 748de1f1bf239b791435258e214ad704092f67bad7e5ff61d266b5961fbc35563f2c0707ff6017b842303a81d1f9650af540aa3fbca611b52b9ba13e68585936
6
+ metadata.gz: 2f823f488456547aecf91ddc065b4b0533961efea5b634516468b2d19bbb14ee2a2c16119624481676576da70411a5896575d1ecccd9cea94cb492cd4f3e6738
7
+ data.tar.gz: 715bba185b33ae77fd182af8ad5b8a0ea851766dc148eb438ffd0f8b22414c8885afdb96469fec08d2c57e8a20a144052a722e86b1e3c87e0cb39538b8c632a4
data/README.md CHANGED
@@ -5,7 +5,7 @@
5
5
 
6
6
  ## Requirements
7
7
 
8
- This engine requires Rails `>= 5.0.0` and Ruby `>= 2.2.0`.
8
+ This engine requires Rails `>= 5.0.0` and Ruby `>= 2.3.0`.
9
9
 
10
10
  ## Documentation
11
11
 
@@ -36,12 +36,15 @@ This will add the following routes:
36
36
  * `/auth/failure`
37
37
  * `/signout`
38
38
 
39
+
39
40
  BookingSync Engine uses the `Account` model to authenticate each BookingSync Account, if you do not have an `Account` model yet, create one:
40
41
 
41
42
  ```console
42
43
  rails g model Account
43
44
  ```
44
45
 
46
+ ### For single application setup
47
+
45
48
  Then, generate a migration to add OAuth fields for the `Account` class:
46
49
 
47
50
  ```console
@@ -56,15 +59,100 @@ and migrate:
56
59
  rake db:migrate
57
60
  ```
58
61
 
59
- Also include `BookingSync::Engine::Account` in your `Account` model:
62
+ Also include `BookingSync::Engine::Models::Account` in your `Account` model:
63
+
64
+ ```ruby
65
+ class Account < ActiveRecord::Base
66
+ include BookingSync::Engine::Models::Account
67
+ end
68
+ ```
69
+
70
+ ### For multi application setup
71
+
72
+ Then, generate a migration to add OAuth fields for the `Account` class:
73
+
74
+ ```console
75
+ rails g migration AddOAuthFieldsToAccounts provider:string synced_id:integer:index \
76
+ name:string oauth_access_token:string oauth_refresh_token:string \
77
+ oauth_expires_at:string host:string:uniq:index
78
+ ```
79
+
80
+ Add manually `null: false` to the `host` field on the newly created migration file, then migrate:
81
+
82
+ ```console
83
+ rake db:migrate
84
+ ```
85
+
86
+ Also include `BookingSync::Engine::Models::MultiApplicationsAccount` in your `Account` model:
60
87
 
61
88
  ```ruby
62
89
  class Account < ActiveRecord::Base
63
- include BookingSync::Engine::Model
90
+ include BookingSync::Engine::Models::MultiApplicationsAccount
91
+ end
92
+ ```
93
+
94
+ You also need to create applications
95
+
96
+ ```console
97
+ rails g model Application
98
+ ```
99
+
100
+ Then, generate a migration to add credentials fields for the `Application` class:
101
+
102
+ ```console
103
+ rails g migration AddCredentialsFieldsToApplications host:string:uniq:index client_id:text:uniq:index \
104
+ client_secret:text:uniq:index
105
+ ```
106
+
107
+ Add `null: false` to this 3 attributes, then migrate:
108
+
109
+ ```console
110
+ rake db:migrate
111
+ ```
112
+
113
+ Also include `BookingSync::Engine::Models::Application` in your `Application` model:
114
+
115
+ ```ruby
116
+ class Application < ActiveRecord::Base
117
+ include BookingSync::Engine::Models::Application
118
+ end
119
+ ```
120
+
121
+ Activate the multi app mode in an initializer:
122
+
123
+ ```ruby
124
+ BookingSyncEngine.setup do |setup|
125
+ setup.support_multi_applications = true
126
+ end
127
+ ```
128
+
129
+ #### Use different models for single app and multiple app setup
130
+
131
+ To make transition between the two modes on the fly, you can use different model name for your
132
+ accounts.
133
+
134
+ For the following example:
135
+
136
+ ```ruby
137
+ class MySingleAppAccount < ActiveRecord::Base
138
+ include BookingSync::Engine::Models::Account
139
+ end
140
+
141
+ class MyMultiAppAccount < ActiveRecord::Base
142
+ include BookingSync::Engine::Models::MultiApplicationsAccount
143
+ end
144
+ ```
145
+
146
+ You just need to define which model goes with which mode in an initializer.
147
+
148
+
149
+ ```ruby
150
+ BookingSyncEngine.setup do |setup|
151
+ setup.single_app_model = -> { ::MySingleAppAccount }
152
+ setup.multi_app_model = -> { ::MyMultiAppAccount }
64
153
  end
65
154
  ```
66
155
 
67
- When saving new token, this gem uses a separate thread with new db connection to ensure token save (in case of a rollback in the main transaction). To make room for the new connections, it is recommended to increase db `pool` size by 2-3.
68
156
 
69
157
  ## Configuration
70
158
 
@@ -77,7 +165,7 @@ The engine is configured by the following ENV variables:
77
165
  * `BOOKINGSYNC_SCOPE` - Space separated list of required scopes. Defaults to nil, which means the public scope.
78
166
 
79
167
  You might want to use [dotenv-rails](https://github.com/bkeepers/dotenv)
80
- to make ENV variables management easy.
168
+ to make ENV variables management easy. See `spec/dummy/.env.sample`.
81
169
 
82
170
  ## Embedded vs Standalone apps
83
171
 
@@ -168,3 +256,11 @@ We would love to see you contributing. Please, just follow the guidelines from [
168
256
  ### Testing
169
257
 
170
258
  By default, your tests will run against the Rails version used in the main Gemfile.lock, to test against all supported Rails version, please run the tests with Appraisals with: `appraisal rake spec`
259
+
260
+ #### Testing with docker
261
+
262
+ You can choose to run PostgreSQL in a Docker container. At the moment, you should use [Beta channel](https://docs.docker.com/docker-for-mac/) on a Mac - so you can reach the docker machine on localhost. It is possible to set it up with stable, but then you have to configure it another way.
263
+
264
+ Use `spec/dummy/config/database.yml.docker` instead of `spec/dummy/config/database.yml`.
265
+
266
+ Once intalled, setup the DB with `docker-compose create`, `docker-compose start` and `rake db:setup`
@@ -1,7 +1,7 @@
1
1
  class SessionsController < ApplicationController
2
2
  def create
3
3
  auth = request.env["omniauth.auth"]
4
- account = ::Account.from_omniauth(auth)
4
+ account = BookingSyncEngine.account_model.from_omniauth(auth, request.host)
5
5
  account_authorized(account)
6
6
  redirect_to after_bookingsync_sign_in_path
7
7
  end
@@ -1 +1,24 @@
1
- require 'bookingsync'
1
+ require "bookingsync"
2
+
3
+ module BookingSyncEngine
4
+ cattr_accessor :support_multi_applications
5
+ self.support_multi_applications = false
6
+
7
+ cattr_accessor :single_app_model
8
+ self.single_app_model = -> { ::Account }
9
+
10
+ cattr_accessor :multi_app_model
11
+ self.multi_app_model = -> { ::Account }
12
+
13
+ def self.setup
14
+ yield self
15
+ end
16
+
17
+ def self.support_multi_applications?
18
+ support_multi_applications
19
+ end
20
+
21
+ def self.account_model
22
+ support_multi_applications? ? multi_app_model.call : single_app_model.call
23
+ end
24
+ end
@@ -1,22 +1,30 @@
1
- require 'omniauth'
2
- require 'omniauth-bookingsync'
3
- require 'bookingsync-api'
1
+ require "omniauth"
2
+ require "omniauth-bookingsync"
3
+ require "bookingsync-api"
4
4
 
5
5
  module BookingSync
6
6
  class Engine < ::Rails::Engine
7
7
  initializer "bookingsync.add_omniauth" do |app|
8
8
  app.middleware.use OmniAuth::Builder do
9
9
  provider :bookingsync,
10
- ENV['BOOKINGSYNC_APP_ID'],
11
- ENV['BOOKINGSYNC_APP_SECRET'],
12
- scope: ENV['BOOKINGSYNC_SCOPE'],
10
+ BookingSyncEngine.support_multi_applications? ? nil : ENV["BOOKINGSYNC_APP_ID"],
11
+ BookingSyncEngine.support_multi_applications? ? nil : ENV["BOOKINGSYNC_APP_SECRET"],
12
+ scope: ENV["BOOKINGSYNC_SCOPE"],
13
13
  setup: -> (env) {
14
- if url = ENV['BOOKINGSYNC_URL']
15
- env['omniauth.strategy'].options[:client_options].site = url
14
+ if url = ENV["BOOKINGSYNC_URL"]
15
+ env["omniauth.strategy"].options[:client_options].site = url
16
16
  end
17
- env['omniauth.strategy'].options[:client_options].ssl = {
18
- verify: ENV['BOOKINGSYNC_VERIFY_SSL'] != 'false'
17
+ env["omniauth.strategy"].options[:client_options].ssl = {
18
+ verify: ENV["BOOKINGSYNC_VERIFY_SSL"] != "false"
19
19
  }
20
+
21
+ if BookingSyncEngine.support_multi_applications?
22
+ credentials = BookingSync::Engine::CredentialsResolver.new(env["HTTP_HOST"]).call
23
+ if credentials.valid?
24
+ env["omniauth.strategy"].options[:client_id] = credentials.client_id
25
+ env["omniauth.strategy"].options[:client_secret] = credentials.client_secret
26
+ end
27
+ end
20
28
  }
21
29
  end
22
30
  end
@@ -67,21 +75,22 @@ module BookingSync
67
75
  # The ENV variables used for configuration are described in {file:README.md}.
68
76
  #
69
77
  # @return [OAuth2::Client] configured OAuth client
70
- def self.oauth_client
78
+ def self.oauth_client(client_id: ENV["BOOKINGSYNC_APP_ID"], client_secret: ENV["BOOKINGSYNC_APP_SECRET"])
71
79
  client_options = {
72
- site: ENV['BOOKINGSYNC_URL'] || 'https://www.bookingsync.com',
80
+ site: ENV["BOOKINGSYNC_URL"] || 'https://www.bookingsync.com',
73
81
  connection_opts: { headers: { accept: "application/vnd.api+json" } }
74
82
  }
75
83
  client_options[:ssl] = { verify: ENV['BOOKINGSYNC_VERIFY_SSL'] != 'false' }
76
- OAuth2::Client.new(ENV['BOOKINGSYNC_APP_ID'], ENV['BOOKINGSYNC_APP_SECRET'],
77
- client_options)
84
+ OAuth2::Client.new(client_id, client_secret, client_options)
78
85
  end
79
86
 
80
- def self.application_token
81
- oauth_client.client_credentials.get_token
87
+ 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
82
89
  end
83
90
  end
84
91
  end
85
92
 
93
+ require "bookingsync/engine/application_credentials"
94
+ require "bookingsync/engine/credentials_resolver"
86
95
  require "bookingsync/engine/api_client"
87
- require "bookingsync/engine/model"
96
+ require "bookingsync/engine/models"
@@ -0,0 +1,15 @@
1
+ class BookingSync::Engine::ApplicationCredentials
2
+ attr_reader :client_id
3
+ attr_reader :client_secret
4
+
5
+ def initialize(application = nil)
6
+ if application.present?
7
+ @client_id = application.client_id
8
+ @client_secret = application.client_secret
9
+ end
10
+ end
11
+
12
+ def valid?
13
+ client_id.present? && client_secret.present?
14
+ end
15
+ end
@@ -11,7 +11,10 @@ module BookingSync::Engine::AuthHelpers
11
11
 
12
12
  # @return [Account, nil] currently authorized Account or nil if unauthorized
13
13
  def current_account
14
- @current_account ||= ::Account.find_by(synced_id: session[:account_id]) if session[:account_id].present?
14
+ return if session[:account_id].nil?
15
+
16
+ @current_account ||=
17
+ BookingSyncEngine.account_model.find_by_host_and_synced_id(request.host, session[:account_id])
15
18
  end
16
19
 
17
20
  # Callback after account is authorized.
@@ -130,7 +133,7 @@ module BookingSync::Engine::AuthHelpers
130
133
  store_bookingsync_account_id if BookingSync::Engine.embedded
131
134
  sign_out_if_inactive
132
135
  enforce_requested_account_authorized!
133
- request_authorization! unless current_account
136
+ request_authorization! if current_account.nil?
134
137
  end
135
138
 
136
139
  def store_bookingsync_account_id # :nodoc:
@@ -0,0 +1,18 @@
1
+ class BookingSync::Engine::CredentialsResolver
2
+ attr_reader :host
3
+ private :host
4
+
5
+ def initialize(host)
6
+ @host = host
7
+ end
8
+
9
+ def call
10
+ BookingSync::Engine::ApplicationCredentials.new(application)
11
+ end
12
+
13
+ private
14
+
15
+ def application
16
+ @application ||= ::Application.find_by_host(host)
17
+ end
18
+ end
@@ -0,0 +1,11 @@
1
+ module BookingSync
2
+ class Engine
3
+ module Models
4
+ end
5
+ end
6
+ end
7
+
8
+ require "bookingsync/engine/models/base_account"
9
+ require "bookingsync/engine/models/account"
10
+ require "bookingsync/engine/models/multi_applications_account"
11
+ require "bookingsync/engine/models/application"
@@ -0,0 +1,36 @@
1
+ module BookingSync::Engine::Models::Account
2
+ extend ActiveSupport::Concern
3
+ include BookingSync::Engine::Models::BaseAccount
4
+
5
+ included do
6
+ validates :synced_id, uniqueness: true
7
+ end
8
+
9
+ module ClassMethods
10
+ def from_omniauth(auth, _host)
11
+ account = find_or_initialize_by(synced_id: auth.uid, provider: auth.provider)
12
+
13
+ account.tap do |account|
14
+ account.name = auth.info.business_name
15
+ account.update_token(auth.credentials)
16
+ account.save!
17
+ end
18
+ end
19
+
20
+ def find_by_host_and_synced_id(_host, synced_id)
21
+ find_by(synced_id: synced_id)
22
+ end
23
+ end
24
+
25
+ def application_token
26
+ BookingSync::Engine.application_token
27
+ end
28
+
29
+ def oauth_client
30
+ BookingSync::Engine.oauth_client
31
+ end
32
+
33
+ def application
34
+ nil
35
+ end
36
+ end
@@ -0,0 +1,9 @@
1
+ module BookingSync::Engine::Models::Application
2
+ extend ActiveSupport::Concern
3
+
4
+ included do
5
+ validates :host, presence: true, uniqueness: true
6
+ validates :client_id, presence: true, uniqueness: true
7
+ validates :client_secret, presence: true, uniqueness: true
8
+ end
9
+ end
@@ -1,21 +1,10 @@
1
- module BookingSync::Engine::Model
1
+ module BookingSync::Engine::Models::BaseAccount
2
2
  extend ActiveSupport::Concern
3
3
 
4
4
  included do
5
- validates :synced_id, uniqueness: true
6
5
  scope :authorized, -> { where.not(oauth_access_token: nil) }
7
6
  end
8
7
 
9
- module ClassMethods
10
- def from_omniauth(auth)
11
- find_or_initialize_by(synced_id: auth.uid, provider: auth.provider).tap do |account|
12
- account.name = auth.info.business_name
13
- account.update_token(auth.credentials)
14
- account.save!
15
- end
16
- end
17
- end
18
-
19
8
  def token
20
9
  @token ||= begin
21
10
  token_options = {}
@@ -24,8 +13,7 @@ module BookingSync::Engine::Model
24
13
  token_options[:expires_at] = oauth_expires_at
25
14
  end
26
15
 
27
- token = OAuth2::AccessToken.new(BookingSync::Engine.oauth_client,
28
- oauth_access_token, token_options)
16
+ token = OAuth2::AccessToken.new(oauth_client, oauth_access_token, token_options)
29
17
 
30
18
  if token.expired?
31
19
  refresh_token!(token)
@@ -35,29 +23,29 @@ module BookingSync::Engine::Model
35
23
  end
36
24
  end
37
25
 
38
- def refresh_token!(current_token = token)
39
- @token = current_token.refresh!.tap { |new_token| update_token!(new_token) }
40
- end
41
-
42
26
  def api
43
27
  @api ||= BookingSync::Engine::APIClient.new(token.token, account: self)
44
28
  end
45
29
 
30
+ def clear_token!
31
+ self.oauth_access_token = nil
32
+ self.oauth_refresh_token = nil
33
+ self.oauth_expires_at = nil
34
+ save!
35
+ end
36
+
46
37
  def update_token(token)
47
38
  self.oauth_access_token = token.token
48
39
  self.oauth_refresh_token = token.refresh_token
49
40
  self.oauth_expires_at = token.expires_at
50
41
  end
51
42
 
52
- def update_token!(token)
53
- update_token(token)
54
- save!
55
- end
43
+ private
56
44
 
57
- def clear_token!
58
- self.oauth_access_token = nil
59
- self.oauth_refresh_token = nil
60
- self.oauth_expires_at = nil
61
- save!
45
+ def refresh_token!(current_token = token)
46
+ @token = current_token.refresh!.tap do |new_token|
47
+ update_token(new_token)
48
+ save!
49
+ end
62
50
  end
63
51
  end