workarea-api-storefront 4.4.6

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 (203) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +12 -0
  3. data/README.md +58 -0
  4. data/Rakefile +10 -0
  5. data/app/controllers/workarea/api/storefront/accounts_controller.rb +31 -0
  6. data/app/controllers/workarea/api/storefront/analytics_controller.rb +41 -0
  7. data/app/controllers/workarea/api/storefront/application_controller.rb +65 -0
  8. data/app/controllers/workarea/api/storefront/assets_controller.rb +11 -0
  9. data/app/controllers/workarea/api/storefront/authentication.rb +30 -0
  10. data/app/controllers/workarea/api/storefront/authentication_tokens_controller.rb +50 -0
  11. data/app/controllers/workarea/api/storefront/cart_items_controller.rb +100 -0
  12. data/app/controllers/workarea/api/storefront/carts_controller.rb +47 -0
  13. data/app/controllers/workarea/api/storefront/categories_controller.rb +25 -0
  14. data/app/controllers/workarea/api/storefront/checkouts_controller.rb +117 -0
  15. data/app/controllers/workarea/api/storefront/contacts_controller.rb +20 -0
  16. data/app/controllers/workarea/api/storefront/current_checkout.rb +60 -0
  17. data/app/controllers/workarea/api/storefront/email_signups_controller.rb +15 -0
  18. data/app/controllers/workarea/api/storefront/menus_controller.rb +19 -0
  19. data/app/controllers/workarea/api/storefront/orders_controller.rb +32 -0
  20. data/app/controllers/workarea/api/storefront/pages_controller.rb +14 -0
  21. data/app/controllers/workarea/api/storefront/password_resets_controller.rb +17 -0
  22. data/app/controllers/workarea/api/storefront/products_controller.rb +17 -0
  23. data/app/controllers/workarea/api/storefront/recent_views_controller.rb +46 -0
  24. data/app/controllers/workarea/api/storefront/recommendations_controller.rb +22 -0
  25. data/app/controllers/workarea/api/storefront/saved_addresses_controller.rb +38 -0
  26. data/app/controllers/workarea/api/storefront/saved_credit_cards_controller.rb +54 -0
  27. data/app/controllers/workarea/api/storefront/searches_controller.rb +29 -0
  28. data/app/controllers/workarea/api/storefront/system_content_controller.rb +16 -0
  29. data/app/controllers/workarea/api/storefront/taxons_controller.rb +20 -0
  30. data/app/controllers/workarea/api/storefront/user_activity.rb +36 -0
  31. data/app/controllers/workarea/storefront/application_controller.decorator +12 -0
  32. data/app/helpers/workarea/api/storefront/application_helper.rb +15 -0
  33. data/app/helpers/workarea/api/storefront/checkouts_helper.rb +11 -0
  34. data/app/helpers/workarea/api/storefront/content_blocks_helper.rb +38 -0
  35. data/app/models/workarea/catalog/category.decorator +7 -0
  36. data/app/models/workarea/user/authentication_token.rb +33 -0
  37. data/app/models/workarea/user.decorator +8 -0
  38. data/app/view_models/workarea/api/storefront/search_suggestion_view_model.rb +21 -0
  39. data/app/views/workarea/api/storefront/accounts/_account.json.jbuilder +7 -0
  40. data/app/views/workarea/api/storefront/accounts/create.json.jbuilder +7 -0
  41. data/app/views/workarea/api/storefront/accounts/show.json.jbuilder +1 -0
  42. data/app/views/workarea/api/storefront/assets/show.json.jbuilder +4 -0
  43. data/app/views/workarea/api/storefront/authentication_tokens/_authentication_token.json.jbuilder +2 -0
  44. data/app/views/workarea/api/storefront/authentication_tokens/create.json.jbuilder +1 -0
  45. data/app/views/workarea/api/storefront/authentication_tokens/update.json.jbuilder +1 -0
  46. data/app/views/workarea/api/storefront/cart_items/item.json.jbuilder +9 -0
  47. data/app/views/workarea/api/storefront/carts/index.json.jbuilder +4 -0
  48. data/app/views/workarea/api/storefront/carts/show.json.jbuilder +1 -0
  49. data/app/views/workarea/api/storefront/categories/_category.json.jbuilder +4 -0
  50. data/app/views/workarea/api/storefront/categories/index.json.jbuilder +3 -0
  51. data/app/views/workarea/api/storefront/categories/show.json.jbuilder +30 -0
  52. data/app/views/workarea/api/storefront/checkouts/_shipping_options.json.jbuilder +4 -0
  53. data/app/views/workarea/api/storefront/checkouts/show.json.jbuilder +17 -0
  54. data/app/views/workarea/api/storefront/checkouts/steps/_addresses.json.jbuilder +19 -0
  55. data/app/views/workarea/api/storefront/checkouts/steps/_payment.json.jbuilder +9 -0
  56. data/app/views/workarea/api/storefront/checkouts/steps/_shipping.json.jbuilder +9 -0
  57. data/app/views/workarea/api/storefront/content_blocks/_block.json.jbuilder +7 -0
  58. data/app/views/workarea/api/storefront/email_signups/create.json.jbuilder +2 -0
  59. data/app/views/workarea/api/storefront/email_signups/show.json.jbuilder +4 -0
  60. data/app/views/workarea/api/storefront/facets/_range.json.jbuilder +8 -0
  61. data/app/views/workarea/api/storefront/facets/_terms.json.jbuilder +8 -0
  62. data/app/views/workarea/api/storefront/fulfillments/_fulfillment.json.jbuilder +18 -0
  63. data/app/views/workarea/api/storefront/menus/_menu.json.jbuilder +11 -0
  64. data/app/views/workarea/api/storefront/menus/index.json.jbuilder +3 -0
  65. data/app/views/workarea/api/storefront/menus/show.json.jbuilder +1 -0
  66. data/app/views/workarea/api/storefront/orders/_item.json.jbuilder +26 -0
  67. data/app/views/workarea/api/storefront/orders/_order.json.jbuilder +42 -0
  68. data/app/views/workarea/api/storefront/orders/index.json.jbuilder +4 -0
  69. data/app/views/workarea/api/storefront/orders/show.json.jbuilder +7 -0
  70. data/app/views/workarea/api/storefront/orders/tenders/_credit_card.json.jbuilder +6 -0
  71. data/app/views/workarea/api/storefront/orders/tenders/_store_credit.json.jbuilder +2 -0
  72. data/app/views/workarea/api/storefront/pages/show.json.jbuilder +16 -0
  73. data/app/views/workarea/api/storefront/products/_image_urls.json.jbuilder +5 -0
  74. data/app/views/workarea/api/storefront/products/_product.json.jbuilder +41 -0
  75. data/app/views/workarea/api/storefront/products/show.json.jbuilder +9 -0
  76. data/app/views/workarea/api/storefront/recent_views/show.json.jbuilder +8 -0
  77. data/app/views/workarea/api/storefront/recommendations/show.json.jbuilder +3 -0
  78. data/app/views/workarea/api/storefront/saved_addresses/_saved_address.json.jbuilder +2 -0
  79. data/app/views/workarea/api/storefront/saved_addresses/index.json.jbuilder +4 -0
  80. data/app/views/workarea/api/storefront/saved_addresses/show.json.jbuilder +2 -0
  81. data/app/views/workarea/api/storefront/saved_credit_cards/_card.json.jbuilder +9 -0
  82. data/app/views/workarea/api/storefront/saved_credit_cards/index.json.jbuilder +4 -0
  83. data/app/views/workarea/api/storefront/saved_credit_cards/show.json.jbuilder +2 -0
  84. data/app/views/workarea/api/storefront/searches/index.json.jbuilder +1 -0
  85. data/app/views/workarea/api/storefront/searches/show.json.jbuilder +19 -0
  86. data/app/views/workarea/api/storefront/shared/_address.json.jbuilder +12 -0
  87. data/app/views/workarea/api/storefront/shared/_pagination.json.jbuilder +11 -0
  88. data/app/views/workarea/api/storefront/system_content/show.json.jbuilder +12 -0
  89. data/app/views/workarea/api/storefront/taxons/_taxon.json.jbuilder +10 -0
  90. data/app/views/workarea/api/storefront/taxons/show.json.jbuilder +7 -0
  91. data/app/workers/workarea/remove_authentication_tokens_on_password_changes.rb +19 -0
  92. data/bin/rails +18 -0
  93. data/config/initializers/config.rb +2 -0
  94. data/config/locales/en.yml +13 -0
  95. data/config/routes.rb +41 -0
  96. data/lib/workarea/api/storefront/engine.rb +10 -0
  97. data/lib/workarea/api/storefront.rb +15 -0
  98. data/test/documentation/workarea/api/storefront/accounts_documentation_test.rb +70 -0
  99. data/test/documentation/workarea/api/storefront/analytics_documentation_test.rb +51 -0
  100. data/test/documentation/workarea/api/storefront/assets_documentation_test.rb +32 -0
  101. data/test/documentation/workarea/api/storefront/authentication_documentation_test.rb +84 -0
  102. data/test/documentation/workarea/api/storefront/cart_items_documentation_test.rb +104 -0
  103. data/test/documentation/workarea/api/storefront/carts_documentation_test.rb +121 -0
  104. data/test/documentation/workarea/api/storefront/categories_documentation_test.rb +90 -0
  105. data/test/documentation/workarea/api/storefront/checkouts_documentation_test.rb +142 -0
  106. data/test/documentation/workarea/api/storefront/contacts_documentation_test.rb +39 -0
  107. data/test/documentation/workarea/api/storefront/email_signups_documentation_test.rb +53 -0
  108. data/test/documentation/workarea/api/storefront/menus_documentation_test.rb +67 -0
  109. data/test/documentation/workarea/api/storefront/orders_documentation_test.rb +127 -0
  110. data/test/documentation/workarea/api/storefront/pages_documentation_test.rb +66 -0
  111. data/test/documentation/workarea/api/storefront/password_resets_documentation_test.rb +30 -0
  112. data/test/documentation/workarea/api/storefront/products_documentation_test.rb +64 -0
  113. data/test/documentation/workarea/api/storefront/recent_views_documentation_test.rb +116 -0
  114. data/test/documentation/workarea/api/storefront/recommendations_documentation_test.rb +68 -0
  115. data/test/documentation/workarea/api/storefront/saved_addresses_documentation_test.rb +129 -0
  116. data/test/documentation/workarea/api/storefront/saved_credit_cards_documentation_test.rb +129 -0
  117. data/test/documentation/workarea/api/storefront/searches_documentation_test.rb +88 -0
  118. data/test/documentation/workarea/api/storefront/system_content_documentation_test.rb +66 -0
  119. data/test/documentation/workarea/api/storefront/taxons_documentation_test.rb +37 -0
  120. data/test/documentation/workarea/api/storefront/validation_documentation_test.rb +81 -0
  121. data/test/dummy/Rakefile +7 -0
  122. data/test/dummy/app/assets/config/manifest.js +4 -0
  123. data/test/dummy/app/assets/images/.keep +0 -0
  124. data/test/dummy/app/assets/javascripts/application.js +13 -0
  125. data/test/dummy/app/assets/stylesheets/application.css +15 -0
  126. data/test/dummy/app/controllers/application_controller.rb +3 -0
  127. data/test/dummy/app/controllers/concerns/.keep +0 -0
  128. data/test/dummy/app/helpers/application_helper.rb +2 -0
  129. data/test/dummy/app/jobs/application_job.rb +2 -0
  130. data/test/dummy/app/mailers/.keep +0 -0
  131. data/test/dummy/app/mailers/application_mailer.rb +4 -0
  132. data/test/dummy/app/models/.keep +0 -0
  133. data/test/dummy/app/models/concerns/.keep +0 -0
  134. data/test/dummy/app/views/layouts/application.html.erb +14 -0
  135. data/test/dummy/app/views/layouts/mailer.html.erb +13 -0
  136. data/test/dummy/app/views/layouts/mailer.text.erb +1 -0
  137. data/test/dummy/bin/bundle +3 -0
  138. data/test/dummy/bin/rails +4 -0
  139. data/test/dummy/bin/rake +4 -0
  140. data/test/dummy/bin/setup +34 -0
  141. data/test/dummy/bin/update +29 -0
  142. data/test/dummy/config/application.rb +25 -0
  143. data/test/dummy/config/boot.rb +5 -0
  144. data/test/dummy/config/cable.yml +9 -0
  145. data/test/dummy/config/environment.rb +5 -0
  146. data/test/dummy/config/environments/development.rb +55 -0
  147. data/test/dummy/config/environments/production.rb +86 -0
  148. data/test/dummy/config/environments/test.rb +43 -0
  149. data/test/dummy/config/initializers/application_controller_renderer.rb +6 -0
  150. data/test/dummy/config/initializers/assets.rb +11 -0
  151. data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
  152. data/test/dummy/config/initializers/cookies_serializer.rb +5 -0
  153. data/test/dummy/config/initializers/filter_parameter_logging.rb +4 -0
  154. data/test/dummy/config/initializers/inflections.rb +16 -0
  155. data/test/dummy/config/initializers/mime_types.rb +4 -0
  156. data/test/dummy/config/initializers/new_framework_defaults.rb +21 -0
  157. data/test/dummy/config/initializers/session_store.rb +3 -0
  158. data/test/dummy/config/initializers/workarea.rb +8 -0
  159. data/test/dummy/config/initializers/wrap_parameters.rb +14 -0
  160. data/test/dummy/config/locales/en.yml +23 -0
  161. data/test/dummy/config/puma.rb +47 -0
  162. data/test/dummy/config/routes.rb +6 -0
  163. data/test/dummy/config/secrets.yml +22 -0
  164. data/test/dummy/config/spring.rb +6 -0
  165. data/test/dummy/config.ru +4 -0
  166. data/test/dummy/db/seeds.rb +2 -0
  167. data/test/dummy/log/.keep +0 -0
  168. data/test/dummy/public/404.html +67 -0
  169. data/test/dummy/public/422.html +67 -0
  170. data/test/dummy/public/500.html +66 -0
  171. data/test/dummy/public/apple-touch-icon-precomposed.png +0 -0
  172. data/test/dummy/public/apple-touch-icon.png +0 -0
  173. data/test/dummy/public/favicon.ico +1 -0
  174. data/test/integration/workarea/api/storefront/accounts_integration_test.rb +49 -0
  175. data/test/integration/workarea/api/storefront/analytics_integration_test.rb +36 -0
  176. data/test/integration/workarea/api/storefront/assets_integration_test.rb +24 -0
  177. data/test/integration/workarea/api/storefront/authentication_integration_test.rb +50 -0
  178. data/test/integration/workarea/api/storefront/authentication_tokens_integration_test.rb +87 -0
  179. data/test/integration/workarea/api/storefront/cart_items_integration_test.rb +149 -0
  180. data/test/integration/workarea/api/storefront/carts_integration_test.rb +114 -0
  181. data/test/integration/workarea/api/storefront/categories_integration_test.rb +84 -0
  182. data/test/integration/workarea/api/storefront/checkouts_integration_test.rb +203 -0
  183. data/test/integration/workarea/api/storefront/contacts_integration_test.rb +28 -0
  184. data/test/integration/workarea/api/storefront/email_signups_integration_test.rb +35 -0
  185. data/test/integration/workarea/api/storefront/menus_integration_test.rb +53 -0
  186. data/test/integration/workarea/api/storefront/orders_integration_test.rb +115 -0
  187. data/test/integration/workarea/api/storefront/pages_integration_test.rb +57 -0
  188. data/test/integration/workarea/api/storefront/password_resets_integration_test.rb +20 -0
  189. data/test/integration/workarea/api/storefront/products_integration_test.rb +50 -0
  190. data/test/integration/workarea/api/storefront/recent_views_integration_test.rb +118 -0
  191. data/test/integration/workarea/api/storefront/recommendations_integration_test.rb +51 -0
  192. data/test/integration/workarea/api/storefront/saved_addresses_integration_test.rb +100 -0
  193. data/test/integration/workarea/api/storefront/saved_credit_cards_integration_test.rb +107 -0
  194. data/test/integration/workarea/api/storefront/searches_integration_test.rb +128 -0
  195. data/test/integration/workarea/api/storefront/system_content_integration_test.rb +35 -0
  196. data/test/integration/workarea/api/storefront/taxons_integration_test.rb +44 -0
  197. data/test/integration/workarea/api/storefront/user_carts_integration_test.rb +55 -0
  198. data/test/models/workarea/user/authentication_token_test.rb +30 -0
  199. data/test/support/authentication_test.rb +25 -0
  200. data/test/support/orders_test.rb +18 -0
  201. data/test/test_helper.rb +10 -0
  202. data/workarea-api-storefront.gemspec +18 -0
  203. metadata +277 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 23b35914b434546ccc6bfb92e627936a4a7a012686f2a9eb1883390f55d75add
4
+ data.tar.gz: 1c3c4c602f398f541937a4229f94039c8fce1f23153f2abe6c8257ea2487f558
5
+ SHA512:
6
+ metadata.gz: d362d53c468c1496de0be57d962177ad21bfc8f2ddcab962ffb06b5fe0f4b11cdce6574cb6119a46847e9f29ee310a6e4e1e683f3679bb345120411e79f372c9
7
+ data.tar.gz: 8fb0927dff5edcbd5cb69a842d38055d7782dab40e218512a0c96c59dd416528a92d4cca9283c29d0e8e48d8a1c4d111d08d584f5f490cffce51cc7087105d97
data/.gitignore ADDED
@@ -0,0 +1,12 @@
1
+ .bundle/
2
+ Gemfile.lock
3
+ .sass-cache/
4
+ log/*.log
5
+ pkg/
6
+ test/dummy/public/system/dragonfly
7
+ test/dummy/db/*.sqlite3
8
+ test/dummy/log/*.log
9
+ test/dummy/tmp/
10
+ test/dummy/.sass-cache
11
+ **/.DS_Store
12
+ docs/build
data/README.md ADDED
@@ -0,0 +1,58 @@
1
+ # Workarea Storefront API
2
+
3
+ Part of the [Workarea API][], the Storefront API provides programmatic
4
+ access to operations and resources to alternative user interfaces to
5
+ your Workarea application, like on-premises kiosks, mobile applications,
6
+ and client-side storefront implementations.
7
+
8
+ ## Getting Started
9
+
10
+ To use this plugin, install the **workarea-api** gem.
11
+
12
+ For more information on the API as a whole, and to learn how to set up
13
+ the API plugin, consult the [main README][Workarea API].
14
+
15
+ ## Authenticating
16
+
17
+ The Storefront API requires the use of a temporary authentication token,
18
+ analogous to the user ID in the session, which tells the backend of
19
+ Workarea whether a User is authenticated. It uses the
20
+ `Workarea::UrlToken` mixin from core to generate this token.
21
+
22
+ To obtain an authentication token, make a POST request like so:
23
+
24
+ ```bash
25
+ curl \
26
+ --request POST \
27
+ --data '{ "email": "your@email.address", "password": "Password1!" }' \
28
+ "http://yourincredibleheadlesscommercesolution.biz/api/authentication_tokens.json"
29
+ ```
30
+
31
+ You should get a response that looks like this:
32
+
33
+ ```json
34
+ {
35
+ "token": "tL6Scp6ubsufq76FZHLbhLWs",
36
+ "expires_at": "2018-12-25T11:58:43.674-05:00"
37
+ }
38
+ ```
39
+
40
+ Use the `token` in this response to make further authenticated requests
41
+ to the API:
42
+
43
+
44
+ ```bash
45
+ curl \
46
+ --request GET \
47
+ --header 'Authorization: Token token="tL6Scp6ubsufq76FZHLbhLWs"' \
48
+ "http://yourincredibleheadlesscommercesolution.biz/api/carts.json"
49
+ ```
50
+
51
+ ## Copyright & Licensing
52
+
53
+ Copyright Workarea 2017-2019. All rights reserved.
54
+
55
+ For licensing, contact [sales@workarea.com][].
56
+
57
+ [Workarea API]: https://homebase.weblinc.com/plugins/workarea-api-admin
58
+ [sales@workarea.com]: mailto:sales@workarea.com
data/Rakefile ADDED
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env rake
2
+ begin
3
+ require 'bundler/setup'
4
+ rescue LoadError
5
+ puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
6
+ end
7
+
8
+ # Load the dummy app's rake tasks
9
+ APP_RAKEFILE = File.expand_path('../test/dummy/Rakefile', __FILE__)
10
+ load 'rails/tasks/engine.rake'
@@ -0,0 +1,31 @@
1
+ module Workarea
2
+ module Api
3
+ module Storefront
4
+ class AccountsController < Api::Storefront::ApplicationController
5
+ def show
6
+ end
7
+
8
+ def create
9
+ @user = User.create!(user_params)
10
+
11
+ Workarea::Storefront::AccountMailer
12
+ .creation(@user.id.to_s)
13
+ .deliver_later
14
+
15
+ @authentication_token = @user.authentication_tokens.create!
16
+ end
17
+
18
+ def update
19
+ current_user.update_attributes!(user_params)
20
+ render :show
21
+ end
22
+
23
+ private
24
+
25
+ def user_params
26
+ params.permit(:email, :password, :first_name, :last_name)
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,41 @@
1
+ module Workarea
2
+ module Api
3
+ module Storefront
4
+ class AnalyticsController < ActionController::Metal
5
+ include ActionController::Head
6
+ include ActionController::Instrumentation
7
+
8
+ def category_view
9
+ Metrics::CategoryByDay.inc(key: { category_id: params[:category_id] }, views: 1)
10
+ head :ok
11
+ end
12
+
13
+ def product_view
14
+ Metrics::ProductByDay.inc(key: { product_id: params[:product_id] }, views: 1)
15
+ head :ok
16
+ end
17
+
18
+ def search
19
+ Metrics::SearchByDay.save_search(params[:q], params[:total_results])
20
+ head :ok
21
+ end
22
+
23
+ def search_abandonment
24
+ warn <<~eos
25
+ DEPRECATION WARNING: Search abandonment tracking is deprecated and will be removed \
26
+ in Workarea 3.5.
27
+ eos
28
+ head :ok
29
+ end
30
+
31
+ def filters
32
+ warn <<~eos
33
+ DEPRECATION WARNING: Filter analytics tracking is deprecated and will be removed \
34
+ in Workarea 3.5.
35
+ eos
36
+ head :ok
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,65 @@
1
+ module Workarea
2
+ module Api
3
+ module Storefront
4
+ class ApplicationController < Workarea::ApplicationController
5
+ include Workarea::Storefront::HttpCaching
6
+ include Api::Storefront::Authentication
7
+ include Api::Storefront::UserActivity
8
+
9
+ respond_to :json
10
+
11
+ before_action :set_json_format
12
+ before_action :skip_session
13
+ before_action { params.permit! }
14
+ after_action :disable_cors_protection
15
+
16
+ rescue_from Mongoid::Errors::DocumentNotFound, with: :handle_not_found
17
+ rescue_from Mongoid::Errors::Validations, with: :handle_invalid
18
+ rescue_from Mongoid::Errors::UnknownAttribute, with: :handle_unknown_attribute
19
+ rescue_from Authentication::InvalidError, with: :handle_invalid_auth
20
+
21
+ helper :all
22
+
23
+ def cache_page
24
+ expires_in Workarea.config.page_cache_ttl, public: true
25
+ end
26
+
27
+ def skip_session
28
+ request.session_options[:skip] = true
29
+ end
30
+
31
+ private
32
+
33
+ def set_json_format
34
+ request.format = :json
35
+ end
36
+
37
+ def handle_not_found(e)
38
+ payload = { params: e.params, problem: e.problem }
39
+ render json: payload, status: :not_found
40
+ end
41
+
42
+ def handle_invalid(e)
43
+ render(
44
+ json: { problems: e.document.errors.full_messages },
45
+ status: :unprocessable_entity
46
+ )
47
+ end
48
+
49
+ def handle_unknown_attribute(e)
50
+ render json: e.as_json.slice('problem'), status: :unprocessable_entity
51
+ end
52
+
53
+ def handle_invalid_auth
54
+ request_http_token_authentication
55
+ end
56
+
57
+ def disable_cors_protection
58
+ headers['Access-Control-Allow-Origin'] = '*'
59
+ headers['Access-Control-Allow-Headers'] = '*'
60
+ headers['Access-Control-Allow-Methods'] = 'GET, POST, PATCH, PUT, DELETE, OPTIONS'
61
+ end
62
+ end
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,11 @@
1
+ module Workarea
2
+ module Api
3
+ module Storefront
4
+ class AssetsController < Api::Storefront::ApplicationController
5
+ def show
6
+ @asset = Content::Asset.find(params[:id])
7
+ end
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,30 @@
1
+ module Workarea
2
+ module Api
3
+ module Storefront
4
+ module Authentication
5
+ extend ActiveSupport::Concern
6
+
7
+ class InvalidError < RuntimeError; end
8
+
9
+ included do
10
+ helper_method :current_user
11
+ end
12
+
13
+ def current_user
14
+ return @current_user if defined?(@current_user)
15
+
16
+ user = authenticate_with_http_token do |token, options|
17
+ User::AuthenticationToken.authenticate(token, options).try(:user)
18
+ end
19
+
20
+ @current_user = user || raise(InvalidError)
21
+ end
22
+
23
+ def authentication?
24
+ regex = ActionController::HttpAuthentication::Token::TOKEN_REGEX
25
+ request.authorization.to_s[regex].present?
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,50 @@
1
+ module Workarea
2
+ module Api
3
+ module Storefront
4
+ class AuthenticationTokensController < Api::Storefront::ApplicationController
5
+ before_action :ensure_not_locked, only: :create
6
+
7
+ def create
8
+ user = User.find_for_login(params[:email], params[:password])
9
+
10
+ if user.blank?
11
+ render(
12
+ json: { problem: t('workarea.api.storefront.authentication_tokens.error') },
13
+ status: :unprocessable_entity
14
+ )
15
+ else
16
+ @authentication_token = User::AuthenticationToken.create!(user: user)
17
+ end
18
+ end
19
+
20
+ def update
21
+ @authentication_token = authenticate_with_http_token do |token, options|
22
+ User::AuthenticationToken.refresh!(token, options)
23
+ end
24
+
25
+ if @authentication_token.blank?
26
+ render(
27
+ json: { problem: t('workarea.api.storefront.authentication_tokens.error') },
28
+ status: :unprocessable_entity
29
+ )
30
+ end
31
+ end
32
+
33
+ private
34
+
35
+ def ensure_not_locked
36
+ if User.login_locked?(params[:email])
37
+ render(
38
+ json: {
39
+ problem: t('workarea.api.storefront.authentication_tokens.login_locked')
40
+ },
41
+ status: :unprocessable_entity
42
+ )
43
+
44
+ return false
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,100 @@
1
+ module Workarea
2
+ module Api
3
+ module Storefront
4
+ class CartItemsController < Api::Storefront::ApplicationController
5
+ include CurrentCheckout
6
+
7
+ before_action :set_checkout_view_models
8
+ before_action :validate_customizations, only: [:create, :update]
9
+
10
+ def create
11
+ current_order.add_item(item_params.to_h.merge(item_details.to_h))
12
+ update_cart
13
+ render_item
14
+ end
15
+
16
+ def update
17
+ update_params = params.permit(:sku, :quantity).to_h
18
+ update_params.merge!(item_details.to_h) if params[:sku].present?
19
+
20
+ current_order.update_item(params[:id], update_params)
21
+ update_cart
22
+ render_item
23
+ end
24
+
25
+ def destroy
26
+ current_order.remove_item(params[:id])
27
+ update_cart
28
+ render_item
29
+ end
30
+
31
+ private
32
+
33
+ def update_cart
34
+ current_order.save! # trigger any validation errors to raise
35
+ remove_unpurchasable_items
36
+ check_inventory
37
+ Pricing.perform(current_order, current_checkout.shipping)
38
+ end
39
+
40
+ def item_params
41
+ @item_params ||= params
42
+ .permit(:product_id, :sku, :quantity)
43
+ .merge(customizations: customization_params)
44
+ end
45
+
46
+ def product_id
47
+ @product_id ||= if params[:product_id].present?
48
+ params[:product_id]
49
+ elsif params[:sku].present?
50
+ Catalog::Product.find_by_sku(params[:sku]).id
51
+ elsif params[:id].present?
52
+ current_order.items.find(params[:id]).product_id
53
+ end
54
+ end
55
+
56
+ def item_details
57
+ ActionController::Parameters.new(
58
+ OrderItemDetails.find!(params[:sku]).to_h
59
+ ).permit!
60
+ end
61
+
62
+ def customizations
63
+ @customizations ||= Catalog::Customizations.find(
64
+ product_id,
65
+ params.to_unsafe_h
66
+ )
67
+ end
68
+
69
+ def customization_params
70
+ ActionController::Parameters.new(
71
+ customizations.try(:to_h) || {}
72
+ ).permit!
73
+ end
74
+
75
+ def validate_customizations
76
+ if customizations.present? && !customizations.valid?
77
+ flash[:error] = customizations.errors.full_messages.join(', ')
78
+ set_flash_header
79
+ render_item
80
+ return false
81
+ end
82
+ end
83
+
84
+ def render_item
85
+ if current_order.items.any? && !request.delete?
86
+ model = if params[:id].present?
87
+ current_order.items.find(params[:id])
88
+ else
89
+ current_order.items.desc(:updated_at).first
90
+ end
91
+
92
+ @item = Workarea::Storefront::OrderItemViewModel.wrap(model)
93
+ end
94
+
95
+ render template: 'workarea/api/storefront/cart_items/item'
96
+ end
97
+ end
98
+ end
99
+ end
100
+ end
@@ -0,0 +1,47 @@
1
+ module Workarea
2
+ module Api
3
+ module Storefront
4
+ class CartsController < Api::Storefront::ApplicationController
5
+ include CurrentCheckout
6
+
7
+ before_action :set_checkout_view_models, except: [:index, :create]
8
+ before_action :remove_unpurchasable_items, except: [:index, :create]
9
+ before_action :check_inventory, except: [:index, :create]
10
+
11
+ def index
12
+ @orders = Workarea::Storefront::OrderViewModel.wrap(
13
+ Order.carts.where(user_id: current_user.id).to_a
14
+ )
15
+ end
16
+
17
+ def create
18
+ order = Order.new
19
+ order.user_id = current_user.id if authentication?
20
+ order.save!
21
+
22
+ @order = Workarea::Storefront::OrderViewModel.new(
23
+ order,
24
+ view_model_options
25
+ )
26
+
27
+ render :show
28
+ end
29
+
30
+ def show
31
+ Pricing.perform(current_order, current_checkout.shipping)
32
+ end
33
+
34
+ def add_promo_code
35
+ if Pricing.valid_promo_code?(params[:promo_code], current_checkout.email)
36
+ current_order.add_promo_code(params[:promo_code])
37
+ else
38
+ flash[:error] = t('workarea.storefront.flash_messages.promo_code_error')
39
+ end
40
+
41
+ Pricing.perform(current_order, current_checkout.shipping)
42
+ render :show
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,25 @@
1
+ module Workarea
2
+ module Api
3
+ module Storefront
4
+ class CategoriesController < Api::Storefront::ApplicationController
5
+ before_action :cache_page
6
+
7
+ def index
8
+ models = Catalog::Category.active.page(params[:page])
9
+ @categories = Workarea::Storefront::CategoryViewModel.wrap(
10
+ models,
11
+ view_model_options
12
+ )
13
+ end
14
+
15
+ def show
16
+ model = Catalog::Category.find_by(slug: params[:id])
17
+ @category = Workarea::Storefront::CategoryViewModel.wrap(
18
+ model,
19
+ view_model_options
20
+ )
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,117 @@
1
+ module Workarea
2
+ module Api
3
+ module Storefront
4
+ class CheckoutsController < Api::Storefront::ApplicationController
5
+ include CurrentCheckout
6
+
7
+ class InvalidCheckout < RuntimeError; end
8
+
9
+ before_action :set_checkout_view_models
10
+ before_action :start_checkout, only: [:show, :update]
11
+ before_action :validate_checkout, only: :show
12
+ before_action :check_inventory, only: [:show, :complete]
13
+ before_action :remove_unpurchasable_items, only: [:show, :complete]
14
+ before_action :check_lock, only: :complete
15
+ around_action :with_order_lock, only: [:update, :complete]
16
+ before_action :touch_checkout, only: [:update, :complete]
17
+ before_action { params.permit! }
18
+
19
+ rescue_from InvalidCheckout, with: :handle_checkout_error
20
+
21
+ def show
22
+ render_checkout
23
+ end
24
+
25
+ def update
26
+ success = current_checkout.update(params)
27
+ render_checkout(status: success ? :ok : :unprocessable_entity)
28
+ end
29
+
30
+ def complete
31
+ payment = Workarea::Checkout::Steps::Payment.new(current_checkout)
32
+ payment.update(params)
33
+
34
+ if payment.complete? && current_checkout.place_order
35
+ Workarea::Storefront::OrderMailer
36
+ .confirmation(current_order.id)
37
+ .deliver_later
38
+
39
+ @order = Workarea::Storefront::OrderViewModel.new(current_order)
40
+ render template: 'workarea/api/storefront/orders/show'
41
+ else
42
+ flash[:error] =
43
+ t('workarea.storefront.flash_messages.order_place_error')
44
+ render_checkout status: :unprocessable_entity
45
+ end
46
+ end
47
+
48
+ def reset
49
+ current_checkout.reset!
50
+ start_checkout
51
+ render_checkout
52
+ end
53
+
54
+ private
55
+
56
+ def render_checkout(status: :ok)
57
+ Pricing.perform(current_order, current_checkout.shipping)
58
+ render template: 'workarea/api/storefront/checkouts/show',
59
+ status: status
60
+ end
61
+
62
+ def start_checkout
63
+ return if current_order.checking_out?
64
+
65
+ if authentication?
66
+ current_checkout.start_as(current_user)
67
+ else
68
+ current_checkout.start_as(:guest)
69
+ end
70
+ end
71
+
72
+ def validate_checkout
73
+ message =
74
+ if !current_order || current_order.no_items?
75
+ t('workarea.storefront.flash_messages.items_required')
76
+ elsif current_order.started_checkout? && !current_order.checking_out?
77
+ t('workarea.storefront.flash_messages.checkout_expired')
78
+ end
79
+
80
+ raise InvalidCheckout.new(message) if message
81
+ end
82
+
83
+ def with_order_lock
84
+ current_order.lock!
85
+ yield
86
+ current_order.unlock! if current_order
87
+ end
88
+
89
+ def check_lock
90
+ raise InvalidCheckout.new(
91
+ t('workarea.storefront.flash_messages.checkout_lock_error')
92
+ ) if current_order.locked?
93
+ end
94
+
95
+ def touch_checkout
96
+ if authentication?
97
+ current_order.touch_checkout!(
98
+ ip_address: request.remote_ip,
99
+ user_activity_id: current_user.id,
100
+ checkout_by_id: current_user.id,
101
+ source: 'storefront_api'
102
+ )
103
+ else
104
+ current_order.touch_checkout!(
105
+ ip_address: request.remote_ip,
106
+ source: 'storefront_api'
107
+ )
108
+ end
109
+ end
110
+
111
+ def handle_checkout_error(e)
112
+ render json: { problem: e.message }, status: :unprocessable_entity
113
+ end
114
+ end
115
+ end
116
+ end
117
+ end
@@ -0,0 +1,20 @@
1
+ module Workarea
2
+ module Api
3
+ module Storefront
4
+ class ContactsController < Api::Storefront::ApplicationController
5
+ def create
6
+ inquiry = Inquiry.create!(inquiry_params)
7
+ Workarea::Storefront::InquiryMailer.created(inquiry.id.to_s).deliver_later
8
+
9
+ render(json: { inquiry: inquiry })
10
+ end
11
+
12
+ private
13
+
14
+ def inquiry_params
15
+ params.permit(:name, :email, :order_id, :subject, :message)
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,60 @@
1
+ module Workarea
2
+ module Api
3
+ module Storefront
4
+ module CurrentCheckout
5
+ def current_order
6
+ return @current_order if defined?(@current_order)
7
+
8
+ options = { id: params[:cart_id].presence || params[:id] }
9
+ options[:user_id] = current_user.id if authentication?
10
+ order = Order.carts.find_by(options)
11
+
12
+ if order.user_id.present? && current_user.id.to_s != order.user_id
13
+ raise Authentication::InvalidError
14
+ end
15
+
16
+ @current_order = order
17
+ end
18
+
19
+ def current_checkout
20
+ @current_checkout ||=
21
+ if authentication?
22
+ Workarea::Checkout.new(current_order, current_user)
23
+ else
24
+ Workarea::Checkout.new(current_order)
25
+ end
26
+ end
27
+
28
+ private
29
+
30
+ def set_checkout_view_models
31
+ @cart = Workarea::Storefront::CartViewModel.new(
32
+ current_order,
33
+ view_model_options
34
+ )
35
+
36
+ @summary = Workarea::Storefront::Checkout::SummaryViewModel.new(
37
+ current_checkout,
38
+ view_model_options
39
+ )
40
+
41
+ @order = Workarea::Storefront::OrderViewModel.new(
42
+ current_order,
43
+ view_model_options
44
+ )
45
+ end
46
+
47
+ def remove_unpurchasable_items
48
+ cleaner = CartCleaner.new(current_order)
49
+ cleaner.clean
50
+ flash[:info] = cleaner.messages if cleaner.message?
51
+ end
52
+
53
+ def check_inventory
54
+ reservation = InventoryAdjustment.new(current_order).tap(&:perform)
55
+ flash[:error] = reservation.errors if reservation.errors.present?
56
+ end
57
+ end
58
+ end
59
+ end
60
+ end