spree_api 6.0.0.rc7 → 6.0.1

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 (73) hide show
  1. checksums.yaml +4 -4
  2. data/app/controllers/concerns/spree/api/v3/admin/maintenance_tasks_switch.rb +35 -0
  3. data/app/controllers/spree/api/v3/admin/invitation_acceptances_controller.rb +8 -4
  4. data/app/controllers/spree/api/v3/admin/maintenance_task_runs/cancellations_controller.rb +42 -0
  5. data/app/controllers/spree/api/v3/admin/maintenance_task_runs_controller.rb +92 -0
  6. data/app/controllers/spree/api/v3/admin/sellers_controller.rb +1 -1
  7. data/app/controllers/spree/api/v3/admin/store_controller.rb +23 -7
  8. data/app/controllers/spree/api/v3/admin/upgrade_steps_controller.rb +114 -0
  9. data/app/controllers/spree/api/v3/seller/invitation_acceptances_controller.rb +15 -5
  10. data/app/controllers/spree/api/v3/store/customers_controller.rb +1 -0
  11. data/app/controllers/spree/api/v3/store/store_controller.rb +25 -0
  12. data/app/serializers/spree/api/v3/address_serializer.rb +2 -0
  13. data/app/serializers/spree/api/v3/admin/address_serializer.rb +2 -0
  14. data/app/serializers/spree/api/v3/admin/category_serializer.rb +1 -3
  15. data/app/serializers/spree/api/v3/admin/claim_serializer.rb +2 -0
  16. data/app/serializers/spree/api/v3/admin/collection_serializer.rb +1 -4
  17. data/app/serializers/spree/api/v3/admin/company_serializer.rb +2 -0
  18. data/app/serializers/spree/api/v3/admin/credit_card_serializer.rb +2 -0
  19. data/app/serializers/spree/api/v3/admin/customer_serializer.rb +2 -0
  20. data/app/serializers/spree/api/v3/admin/delivery_method_serializer.rb +2 -0
  21. data/app/serializers/spree/api/v3/admin/fulfillment_serializer.rb +1 -0
  22. data/app/serializers/spree/api/v3/admin/gift_card_serializer.rb +2 -0
  23. data/app/serializers/spree/api/v3/admin/invitation_serializer.rb +1 -1
  24. data/app/serializers/spree/api/v3/admin/line_item_serializer.rb +1 -0
  25. data/app/serializers/spree/api/v3/admin/maintenance_task_run_serializer.rb +72 -0
  26. data/app/serializers/spree/api/v3/admin/media_serializer.rb +2 -0
  27. data/app/serializers/spree/api/v3/admin/newsletter_subscriber_serializer.rb +2 -0
  28. data/app/serializers/spree/api/v3/admin/option_type_serializer.rb +2 -0
  29. data/app/serializers/spree/api/v3/admin/option_value_serializer.rb +2 -0
  30. data/app/serializers/spree/api/v3/admin/order_serializer.rb +2 -0
  31. data/app/serializers/spree/api/v3/admin/payment_method_serializer.rb +2 -0
  32. data/app/serializers/spree/api/v3/admin/payment_serializer.rb +3 -1
  33. data/app/serializers/spree/api/v3/admin/payment_source_serializer.rb +2 -0
  34. data/app/serializers/spree/api/v3/admin/product_serializer.rb +1 -3
  35. data/app/serializers/spree/api/v3/admin/return_serializer.rb +2 -0
  36. data/app/serializers/spree/api/v3/admin/seller_payout_serializer.rb +2 -1
  37. data/app/serializers/spree/api/v3/admin/seller_serializer.rb +4 -0
  38. data/app/serializers/spree/api/v3/admin/store_credit_serializer.rb +2 -0
  39. data/app/serializers/spree/api/v3/admin/store_serializer.rb +3 -4
  40. data/app/serializers/spree/api/v3/admin/variant_serializer.rb +1 -3
  41. data/app/serializers/spree/api/v3/base_serializer.rb +28 -0
  42. data/app/serializers/spree/api/v3/category_serializer.rb +1 -4
  43. data/app/serializers/spree/api/v3/claim_serializer.rb +2 -0
  44. data/app/serializers/spree/api/v3/collection_serializer.rb +1 -4
  45. data/app/serializers/spree/api/v3/company_serializer.rb +2 -0
  46. data/app/serializers/spree/api/v3/credit_card_serializer.rb +2 -0
  47. data/app/serializers/spree/api/v3/customer_serializer.rb +2 -0
  48. data/app/serializers/spree/api/v3/delivery_method_serializer.rb +2 -0
  49. data/app/serializers/spree/api/v3/fulfillment_serializer.rb +2 -0
  50. data/app/serializers/spree/api/v3/gift_card_serializer.rb +1 -0
  51. data/app/serializers/spree/api/v3/line_item_serializer.rb +2 -0
  52. data/app/serializers/spree/api/v3/media_serializer.rb +2 -0
  53. data/app/serializers/spree/api/v3/newsletter_subscriber_serializer.rb +2 -0
  54. data/app/serializers/spree/api/v3/option_type_serializer.rb +2 -0
  55. data/app/serializers/spree/api/v3/option_value_serializer.rb +2 -0
  56. data/app/serializers/spree/api/v3/order_serializer.rb +2 -0
  57. data/app/serializers/spree/api/v3/payment_method_serializer.rb +2 -0
  58. data/app/serializers/spree/api/v3/payment_serializer.rb +3 -1
  59. data/app/serializers/spree/api/v3/payment_source_serializer.rb +2 -0
  60. data/app/serializers/spree/api/v3/product_serializer.rb +1 -4
  61. data/app/serializers/spree/api/v3/return_serializer.rb +2 -0
  62. data/app/serializers/spree/api/v3/seller/invitation_serializer.rb +22 -1
  63. data/app/serializers/spree/api/v3/seller/profile_serializer.rb +1 -1
  64. data/app/serializers/spree/api/v3/seller_serializer.rb +2 -0
  65. data/app/serializers/spree/api/v3/store_credit_serializer.rb +2 -0
  66. data/app/serializers/spree/api/v3/store_serializer.rb +16 -0
  67. data/app/serializers/spree/api/v3/variant_serializer.rb +1 -4
  68. data/app/services/spree/api/v3/request_schema.rb +15 -7
  69. data/config/routes.rb +14 -2
  70. data/lib/spree/api/dependencies.rb +2 -1
  71. data/lib/spree/api/enum_types.rb +2 -1
  72. data/lib/typelizer/open_enums.rb +21 -2
  73. metadata +13 -6
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 982115017cd530a3474eddb5fadd2ab6bd770236d449c9a4b93488d45c485c16
4
- data.tar.gz: c333427d0e3dc56730671eb612f44f4ced415f790f5eb4557c6cf2f7da5f6d34
3
+ metadata.gz: 88513caab1df4ae8256a450d38b98601d724763697f75cd6bbe92f20986fac7c
4
+ data.tar.gz: 87742481e6e84a33e11080d3c830ca960eb692a243fb6d1b6c926a43f7d951e0
5
5
  SHA512:
6
- metadata.gz: c5cff8de77ced4e66a5f935e7dd3fed912cb9b8141e0675ae6014fa594022d4db451ba0ae9ef4673aebb41d70b2592529ebf858fab1cdf94e476568b72ef0ab6
7
- data.tar.gz: 2c71f0f8d3667f4e9e3ab61c7024d534abfb765a8c56f23daee05430fac53b303dac6463021f7e24c5cf690eba6226ef1c2824b1eb66cd665c4ee572214505f3
6
+ metadata.gz: 10e0aa59755c08b5d83f12080be796d2a4a8cd3cbb70e77a47d369853385dc78f3583296534b0482dc76816396a285f6b476c12cc0c1863eac45defedc646f71
7
+ data.tar.gz: fd76b27f733d1acf21c0deb06341cf2cde81de862dc1d1eaaefcb91f2ffb216bafd3c2f24d4f7a09f1a6dbe39d31f66b9e37584561c26e64563099c67a3592bb
@@ -0,0 +1,35 @@
1
+ module Spree
2
+ module Api
3
+ module V3
4
+ module Admin
5
+ # Refuses every maintenance task endpoint when the installation has
6
+ # turned them off (Spree::Config.maintenance_tasks_dashboard_enabled).
7
+ # The ability already withholds them from signed-in staff; this also
8
+ # covers secret API keys, which are authorized by scope instead.
9
+ #
10
+ # Runs ahead of every other callback, so the caller learns the feature
11
+ # is off rather than a lookup or permission failure that no grant could
12
+ # fix — whether the caller is signed in does not change that answer.
13
+ module MaintenanceTasksSwitch
14
+ extend ActiveSupport::Concern
15
+
16
+ included do
17
+ before_action :ensure_maintenance_tasks_enabled, prepend: true
18
+ end
19
+
20
+ private
21
+
22
+ def ensure_maintenance_tasks_enabled
23
+ return if Spree::Config.maintenance_tasks_dashboard_enabled
24
+
25
+ render_error(
26
+ code: ErrorHandler::ERROR_CODES[:access_denied],
27
+ message: I18n.t('spree.maintenance_tasks_turned_off'),
28
+ status: :forbidden
29
+ )
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
@@ -12,7 +12,7 @@ module Spree
12
12
 
13
13
  request_params 'InvitationAcceptParams', action: :accept do |body|
14
14
  body.attribute :password, :string,
15
- description: 'Required when the invitee has no account yet: it creates one. An existing account signs in without it.'
15
+ description: 'Creates the account when the invitee has none yet. An existing account confirms it is theirs with it, unless the request is already signed in as that account.'
16
16
  body.attribute :password_confirmation, :string
17
17
  body.attribute :first_name, :string
18
18
  body.attribute :last_name, :string
@@ -74,10 +74,14 @@ module Spree
74
74
  # implicit: we look the user up by `invitation.email`, never by a
75
75
  # client-supplied email. The token is the credential.
76
76
  def resolve_or_create_invitee(invitation)
77
- existing = Spree.admin_user_class.find_by(email: invitation.email)
78
- return authenticate_existing(existing) if existing
77
+ existing = invitation.invitee_account
78
+ return create_new_invitee(invitation) unless existing
79
79
 
80
- create_new_invitee(invitation)
80
+ # Someone already signed in as the invitee has proven who they are.
81
+ authenticate_user
82
+ return existing if current_user == existing
83
+
84
+ authenticate_existing(existing)
81
85
  end
82
86
 
83
87
  def authenticate_existing(user)
@@ -0,0 +1,42 @@
1
+ module Spree
2
+ module Api
3
+ module V3
4
+ module Admin
5
+ module MaintenanceTaskRuns
6
+ # POST /api/v3/admin/maintenance_task_runs/:maintenance_task_run_id/cancellation
7
+ #
8
+ # Stops a run for good. Work already committed stays committed; the
9
+ # runner records the outcome (docs/plans/6.0-maintenance-tasks.md).
10
+ class CancellationsController < Admin::BaseController
11
+ include MaintenanceTasksSwitch
12
+
13
+ scoped_resource :maintenance_tasks
14
+
15
+ def create
16
+ run = Spree::MaintenanceTaskRun.find_by_prefix_id!(params[:maintenance_task_run_id])
17
+ authorize! :update, run
18
+
19
+ result = Spree::MaintenanceTasks::Cancel.call(run: run)
20
+
21
+ if result.success?
22
+ render json: serialize_resource(result.value)
23
+ else
24
+ render_validation_error(result.error)
25
+ end
26
+ end
27
+
28
+ protected
29
+
30
+ def serializer_class
31
+ Spree.api.admin_maintenance_task_run_serializer
32
+ end
33
+
34
+ def serializer_params
35
+ super.merge(show_backtrace: true)
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,92 @@
1
+ module Spree
2
+ module Api
3
+ module V3
4
+ module Admin
5
+ # Firing a maintenance task and steering the run it creates
6
+ # (docs/plans/6.0-maintenance-tasks.md).
7
+ #
8
+ # No destroy: a run is the audit record of work that touched merchant
9
+ # data, so it is never removed through the API. Stopping one is a
10
+ # cancellation (MaintenanceTaskRuns::CancellationsController).
11
+ class MaintenanceTaskRunsController < ResourceController
12
+ include ActiveStorage::SetCurrent
13
+
14
+ include MaintenanceTasksSwitch
15
+
16
+ scoped_resource :maintenance_tasks
17
+
18
+ request_params :maintenance_task_run do |body|
19
+ body.attribute :task_name, :string,
20
+ required: true, on: :create,
21
+ example: 'capture_methods',
22
+ description: 'The task to run, as `task_name` from `GET /upgrade_steps`.'
23
+ body.attribute :arguments, :hash,
24
+ description: "Values for the task's declared parameters, keyed by parameter name. " \
25
+ 'A key the task does not declare is rejected.'
26
+ body.attribute :dry_run, :boolean,
27
+ description: 'Report what would change without writing. Ignored by tasks that do not support a dry run, which run for real.'
28
+ end
29
+
30
+ # POST /api/v3/admin/maintenance_task_runs
31
+ def create
32
+ authorize! :create, Spree::MaintenanceTaskRun
33
+
34
+ # Not normalized: a task argument holding a prefixed id is the
35
+ # task's to resolve, and decoding it here would hand it a raw key.
36
+ body = params.permit(*declared_permitted_attributes)
37
+
38
+ result = Spree::MaintenanceTasks::Start.call(
39
+ api_type: body[:task_name].to_s,
40
+ arguments: body[:arguments]&.to_h || {},
41
+ dry_run: ActiveModel::Type::Boolean.new.cast(body[:dry_run]) || false,
42
+ admin_user: try_spree_current_user,
43
+ api_key: current_api_key,
44
+ initiated_via: initiated_via
45
+ )
46
+
47
+ if result.success?
48
+ render json: serialize_resource(result.value), status: :created
49
+ else
50
+ render_validation_error(result.error)
51
+ end
52
+ end
53
+
54
+ protected
55
+
56
+ def model_class
57
+ Spree::MaintenanceTaskRun
58
+ end
59
+
60
+ def serializer_class
61
+ Spree.api.admin_maintenance_task_run_serializer
62
+ end
63
+
64
+ # Runs are installation-wide: an upgrade step converts every store's
65
+ # data, so a run belongs to no store.
66
+ def scope
67
+ model_class.all
68
+ end
69
+
70
+ def collection_includes
71
+ [{ admin_user: [{ spree_roles: :resource }, { avatar_attachment: :blob }] }]
72
+ end
73
+
74
+ # A backtrace names internal paths and class names, so it rides with
75
+ # the permission to act on runs rather than the one to read them.
76
+ def serializer_params
77
+ super.merge(show_backtrace: holds_permission?('write_maintenance_tasks'))
78
+ end
79
+
80
+ private
81
+
82
+ # A secret key belongs to an integration rather than a person, so the
83
+ # two are recorded distinctly — "who ran this" has a different answer
84
+ # for each.
85
+ def initiated_via
86
+ try_spree_current_user ? 'dashboard' : 'api'
87
+ end
88
+ end
89
+ end
90
+ end
91
+ end
92
+ end
@@ -195,7 +195,7 @@ module Spree
195
195
  # every seller on the page, so it loads once. Applied to the scope
196
196
  # rather than the collection so a single-seller read gets it too.
197
197
  def scope_includes
198
- [:billing_address, :requirement_submissions, { stock_locations: [] },
198
+ [:billing_address, :requirement_submissions, :external_references, { stock_locations: [] },
199
199
  { store: :seller_requirements, logo_attachment: :blob, cover_photo_attachment: :blob }]
200
200
  end
201
201
 
@@ -7,8 +7,15 @@ module Spree
7
7
 
8
8
  request_params :store do |body|
9
9
  body.attribute :name, :string, example: 'My Store'
10
- body.attribute :admin_locale, :string, example: 'en'
11
- body.attribute :timezone, :string, example: 'Europe/Berlin'
10
+ body.attribute :seo_title, :string,
11
+ nullable: true,
12
+ description: "The storefront's default page title, in the store's default language. Translate it through the translations endpoints."
13
+ body.attribute :meta_description, :string,
14
+ nullable: true,
15
+ description: "The storefront's default meta description, in the store's default language."
16
+ body.attribute :admin_locale, :locale, nullable: true, example: 'en',
17
+ description: 'The language the dashboard opens in for every staff member; null lets each use their own.'
18
+ body.attribute :timezone, :time_zone, example: 'Europe/Berlin'
12
19
  body.attribute :weight_unit, :weight_unit
13
20
  body.attribute :unit_system, :string, choices: Spree::Store::UNIT_SYSTEMS
14
21
  body.attribute :storefront_access, :string,
@@ -143,17 +150,19 @@ module Spree
143
150
  # GET /api/v3/admin/store
144
151
  def show
145
152
  authorize! :show, current_store
146
- render json: serialize_store
153
+ render json: in_default_locale { serialize_store }
147
154
  end
148
155
 
149
156
  # PATCH /api/v3/admin/store
150
157
  def update
151
158
  authorize! :update, current_store
152
159
 
153
- if current_store.update(permitted_params)
154
- render json: serialize_store
155
- else
156
- render_validation_error(current_store.errors)
160
+ in_default_locale do
161
+ if current_store.update(permitted_params)
162
+ render json: serialize_store
163
+ else
164
+ render_validation_error(current_store.errors)
165
+ end
157
166
  end
158
167
  end
159
168
 
@@ -177,6 +186,13 @@ module Spree
177
186
 
178
187
  private
179
188
 
189
+ # Settings hold the store's default-language values, whatever locale
190
+ # the request resolved to. Other languages are written through the
191
+ # translations endpoints.
192
+ def in_default_locale(&)
193
+ Mobility.with_locale(current_store.default_locale, &)
194
+ end
195
+
180
196
  def describe(provider_classes)
181
197
  provider_classes.map do |provider_class|
182
198
  {
@@ -0,0 +1,114 @@
1
+ module Spree
2
+ module Api
3
+ module V3
4
+ module Admin
5
+ # The upgrade manifest as an ordered checklist, so the dashboard can
6
+ # show what a release still needs and how far an operator has got
7
+ # (docs/plans/6.0-maintenance-tasks.md).
8
+ #
9
+ # Read-only: running a step is starting the maintenance task it names,
10
+ # which is what the runs endpoint already does. This exists to supply
11
+ # the order and the operator notes, neither of which a task knows about
12
+ # itself — a step's position in the manifest is a property of the
13
+ # upgrade, not of the class.
14
+ class UpgradeStepsController < BaseController
15
+ include MaintenanceTasksSwitch
16
+
17
+ scoped_resource :maintenance_tasks
18
+
19
+ # GET /api/v3/admin/upgrade_steps
20
+ #
21
+ # Every step of every manifest this installation has reached, from
22
+ # the first release whose runs are recorded, each marked pending or
23
+ # superseded. Superseded steps are the releases it has already been
24
+ # through: shown as history rather than hidden, but never runnable,
25
+ # since re-running a completed conversion is how an upgrade does
26
+ # damage. Earlier releases are left to the command line.
27
+ def index
28
+ authorize! :read, :maintenance_task
29
+
30
+ # A store installed fresh at this release has no upgrade to show —
31
+ # not the outstanding steps, and not the history of releases it was
32
+ # never on.
33
+ return render json: { data: [], meta: meta } unless Spree::Upgrade.relevant?
34
+
35
+ render json: {
36
+ data: steps.map { |step| present(step) },
37
+ meta: meta
38
+ }
39
+ end
40
+
41
+ private
42
+
43
+ def meta
44
+ { completed_version: Spree::Upgrade.completed_boundary }
45
+ end
46
+
47
+ # Superseded first: they are the earlier releases, so listing them
48
+ # above what is outstanding keeps the whole thing in release order.
49
+ def steps
50
+ @steps ||= (superseded_steps + Spree::Upgrade.pending_steps).select { |step| Spree::Upgrade.tracked?(step) }
51
+ end
52
+
53
+ def superseded_steps
54
+ @superseded_steps ||= Spree::Upgrade.superseded_steps
55
+ end
56
+
57
+ def superseded_ids
58
+ @superseded_ids ||= superseded_steps.map { |step| step['id'] }.to_set
59
+ end
60
+
61
+ def present(step)
62
+ task_name = Spree::Upgrade.task_class_name(step)
63
+ run = latest_runs[run_key(step, task_name)]
64
+
65
+ {
66
+ # A boundary this installation has already crossed. The dashboard
67
+ # shows these as done and refuses to run them.
68
+ superseded: superseded_ids.include?(step['id']),
69
+ id: step['id'],
70
+ name: step['name'],
71
+ notes: step['notes'],
72
+ from: step['from'],
73
+ to: step['to'],
74
+ docs: step['docs'],
75
+ task_name: Spree::MaintenanceTask.api_type_for(task_name),
76
+ # A rake-backed step runs inside the shared runner, so the id it
77
+ # was invoked with is what distinguishes one run from another.
78
+ arguments: Spree::Upgrade.task_arguments(step),
79
+ last_run: run && Spree.api.admin_maintenance_task_run_serializer.new(
80
+ run, params: { show_backtrace: holds_permission?('write_maintenance_tasks') }
81
+ ).to_h
82
+ }
83
+ end
84
+
85
+ # The most recent run per step. Reduced in Ruby rather than grouped
86
+ # in SQL: rake-backed runs are told apart by the step id inside their
87
+ # `arguments` JSON, and grouping on a JSON column is not portable
88
+ # across the adapters Spree supports. Only the three columns that
89
+ # pick the latest run are read for the whole history; the runs kept
90
+ # are then loaded in full.
91
+ def latest_runs
92
+ @latest_runs ||= begin
93
+ latest_ids = Spree::MaintenanceTaskRun.where(task_name: manifest_task_names).order(:id).
94
+ pluck(:id, :task_name, :arguments).
95
+ each_with_object({}) do |(id, task_name, arguments), result|
96
+ result[[task_name, arguments&.dig('step_id')]] = id
97
+ end
98
+ runs = Spree::MaintenanceTaskRun.includes(:admin_user).where(id: latest_ids.values).index_by(&:id)
99
+ latest_ids.transform_values { |id| runs[id] }
100
+ end
101
+ end
102
+
103
+ def manifest_task_names
104
+ steps.map { |step| Spree::Upgrade.task_class_name(step) }.uniq
105
+ end
106
+
107
+ def run_key(step, task_name)
108
+ [task_name, step['task_class'] ? nil : step['id']]
109
+ end
110
+ end
111
+ end
112
+ end
113
+ end
114
+ end
@@ -24,7 +24,7 @@ module Spree
24
24
 
25
25
  request_params 'InvitationAcceptParams', action: :accept do |body|
26
26
  body.attribute :password, :string,
27
- description: 'Sets the password of a new account, or confirms the password of an existing one.'
27
+ description: 'Sets the password of a new account, or confirms the password of an existing one, unless the request is already signed in as that account.'
28
28
  body.attribute :password_confirmation, :string
29
29
  body.attribute :first_name, :string, description: 'Used only when the invitation creates a new account.'
30
30
  body.attribute :last_name, :string, description: 'Used only when the invitation creates a new account.'
@@ -35,7 +35,7 @@ module Spree
35
35
  return unless load_invitation
36
36
 
37
37
  render json: Spree.api.seller_invitation_serializer.new(
38
- @invitation, params: { store: @invitation.store }
38
+ @invitation, params: { store: @invitation.store, acceptance: true }
39
39
  ).serializable_hash
40
40
  end
41
41
 
@@ -97,10 +97,14 @@ module Spree
97
97
  # implicit: we look the user up by `invitation.email`, never by a
98
98
  # client-supplied email. The token is the credential.
99
99
  def resolve_or_create_invitee(invitation)
100
- existing = Spree.admin_user_class.find_by(email: invitation.email)
101
- return authenticate_existing(existing) if existing
100
+ existing = invitation.invitee_account
101
+ return create_new_invitee(invitation) unless existing
102
102
 
103
- create_new_invitee(invitation)
103
+ # Someone already signed in as the invitee has proven who they are.
104
+ authenticate_user
105
+ return existing if current_user == existing
106
+
107
+ authenticate_existing(existing)
104
108
  end
105
109
 
106
110
  def authenticate_existing(user)
@@ -151,6 +155,12 @@ module Spree
151
155
  user.sellers.map { |seller| { id: seller.prefixed_id, name: seller.name, status: seller.status } }
152
156
  end
153
157
 
158
+ # The plain v3 base expects a storefront token; the session this
159
+ # page may carry is a seller panel one.
160
+ def expected_audience
161
+ Spree::Api::V3::JwtAuthentication::JWT_AUDIENCE_SELLER
162
+ end
163
+
154
164
  def request_env_for_token
155
165
  { ip_address: request.remote_ip, user_agent: request.user_agent&.truncate(255) }
156
166
  end
@@ -111,6 +111,7 @@ module Spree
111
111
  currency: current_currency,
112
112
  user: current_user,
113
113
  includes: [],
114
+ expand: expand_list,
114
115
  hide_prices: hide_prices?
115
116
  }
116
117
  end
@@ -0,0 +1,25 @@
1
+ module Spree
2
+ module Api
3
+ module V3
4
+ module Store
5
+ # Exposes the store the request resolved to, so a storefront can render
6
+ # its name and default SEO metadata in the requested locale.
7
+ class StoreController < Store::BaseController
8
+ # A gated storefront still needs a page title on its sign-in wall.
9
+ allow_guest_storefront_access!
10
+
11
+ # GET /api/v3/store/store
12
+ def show
13
+ render json: serialize_resource(current_store)
14
+ end
15
+
16
+ protected
17
+
18
+ def serializer_class
19
+ Spree.api.store_serializer
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -35,6 +35,8 @@ module Spree
35
35
  # The address book the entry belongs to. Null for an address in no
36
36
  # book: one a guest typed in, or the copy a placed order keeps.
37
37
  one :owner, resource: proc { Spree.api.address_owner_serializer }
38
+
39
+ expandable_custom_fields
38
40
  end
39
41
  end
40
42
  end
@@ -28,6 +28,8 @@ module Spree
28
28
  prefixed_id_attributes customer_id: :customer_owner
29
29
 
30
30
  one :owner, resource: proc { Spree.api.admin_address_owner_serializer }
31
+
32
+ expandable_custom_fields admin: true
31
33
  end
32
34
  end
33
35
  end
@@ -28,9 +28,7 @@ module Spree
28
28
  resource: proc { Spree.api.admin_category_serializer },
29
29
  if: proc { expand?('ancestors') }
30
30
 
31
- many :custom_fields,
32
- resource: proc { Spree.api.admin_custom_field_serializer },
33
- if: proc { expand?('custom_fields') }
31
+ expandable_custom_fields admin: true
34
32
  end
35
33
  end
36
34
  end
@@ -26,6 +26,8 @@ module Spree
26
26
  one :reason, resource: proc { Spree.api.admin_claim_reason_serializer }, if: proc { expand?('reason') }
27
27
  one :order, resource: proc { Spree.api.admin_order_serializer }, if: proc { expand?('order') }
28
28
  many :refunds, resource: proc { Spree.api.admin_refund_serializer }, if: proc { expand?('refunds') }
29
+
30
+ expandable_custom_fields admin: true
29
31
  end
30
32
  end
31
33
  end
@@ -18,10 +18,7 @@ module Spree
18
18
  resource: proc { Spree.api.admin_collection_rule_serializer },
19
19
  if: proc { expand?('rules') }
20
20
 
21
- # Override inherited custom_fields to use the admin serializer.
22
- many :custom_fields,
23
- resource: proc { Spree.api.admin_custom_field_serializer },
24
- if: proc { expand?('custom_fields') }
21
+ expandable_custom_fields admin: true
25
22
  end
26
23
  end
27
24
  end
@@ -30,6 +30,8 @@ module Spree
30
30
  many :memberships,
31
31
  resource: proc { Spree.api.admin_company_membership_serializer },
32
32
  if: proc { expand?('memberships') }
33
+
34
+ expandable_custom_fields admin: true
33
35
  end
34
36
  end
35
37
  end
@@ -11,6 +11,8 @@ module Spree
11
11
 
12
12
  attributes :metadata,
13
13
  created_at: :iso8601, updated_at: :iso8601
14
+
15
+ expandable_custom_fields admin: true
14
16
  end
15
17
  end
16
18
  end
@@ -99,6 +99,8 @@ module Spree
99
99
  many :companies,
100
100
  resource: proc { Spree.api.admin_company_serializer },
101
101
  if: proc { expand?('companies') }
102
+
103
+ expandable_custom_fields admin: true
102
104
  end
103
105
  end
104
106
  end
@@ -59,6 +59,8 @@ module Spree
59
59
  calculator = record.calculator
60
60
  { type: calculator.class.api_type, preferences: calculator.serialized_preferences } if calculator
61
61
  end
62
+
63
+ expandable_custom_fields admin: true
62
64
  end
63
65
  end
64
66
  end
@@ -61,6 +61,7 @@ module Spree
61
61
  resource: proc { Spree.api.admin_order_serializer },
62
62
  if: proc { expand?('order') }
63
63
 
64
+ expandable_custom_fields admin: true
64
65
  end
65
66
  end
66
67
  end
@@ -51,6 +51,8 @@ module Spree
51
51
  many :orders,
52
52
  resource: proc { Spree.api.admin_order_serializer },
53
53
  if: proc { expand?('orders') }
54
+
55
+ expandable_custom_fields admin: true
54
56
  end
55
57
  end
56
58
  end
@@ -37,7 +37,7 @@ module Spree
37
37
  # Looked up by email so an admin who's already on another store sees
38
38
  # the password prompt, not a fresh account form.
39
39
  attribute :invitee_exists do |invitation|
40
- Spree.admin_user_class.exists?(email: invitation.email)
40
+ invitation.invitee_account.present?
41
41
  end
42
42
 
43
43
  # Minimal store identity for the unauthenticated acceptance page's
@@ -85,6 +85,7 @@ module Spree
85
85
  resource: proc { Spree.api.admin_tax_category_serializer },
86
86
  if: proc { expand?('tax_category') }
87
87
 
88
+ expandable_custom_fields admin: true
88
89
  end
89
90
  end
90
91
  end