spree_core 5.2.0.rc3 → 5.2.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 (59) hide show
  1. checksums.yaml +4 -4
  2. data/app/helpers/spree/integrations_helper.rb +1 -1
  3. data/app/jobs/spree/images/save_from_url_job.rb +1 -1
  4. data/app/models/concerns/spree/calculated_adjustments.rb +1 -1
  5. data/app/models/concerns/spree/user_methods.rb +1 -1
  6. data/app/models/spree/ability.rb +75 -10
  7. data/app/models/spree/address.rb +1 -1
  8. data/app/models/spree/adjustable/adjustments_updater.rb +1 -1
  9. data/app/models/spree/asset.rb +2 -2
  10. data/app/models/spree/calculator.rb +1 -1
  11. data/app/models/spree/data_feed.rb +1 -1
  12. data/app/models/spree/export.rb +1 -1
  13. data/app/models/spree/gateway/bogus.rb +1 -1
  14. data/app/models/spree/import.rb +1 -1
  15. data/app/models/spree/metafield_definition.rb +3 -3
  16. data/app/models/spree/order/payments.rb +2 -0
  17. data/app/models/spree/order.rb +1 -0
  18. data/app/models/spree/payment/processing.rb +13 -0
  19. data/app/models/spree/payment.rb +20 -0
  20. data/app/models/spree/payment_method.rb +1 -1
  21. data/app/models/spree/permission_sets/base.rb +81 -0
  22. data/app/models/spree/permission_sets/configuration_management.rb +47 -0
  23. data/app/models/spree/permission_sets/dashboard_display.rb +17 -0
  24. data/app/models/spree/permission_sets/default_customer.rb +66 -0
  25. data/app/models/spree/permission_sets/order_display.rb +27 -0
  26. data/app/models/spree/permission_sets/order_management.rb +33 -0
  27. data/app/models/spree/permission_sets/product_display.rb +27 -0
  28. data/app/models/spree/permission_sets/product_management.rb +27 -0
  29. data/app/models/spree/permission_sets/promotion_management.rb +22 -0
  30. data/app/models/spree/permission_sets/role_management.rb +21 -0
  31. data/app/models/spree/permission_sets/stock_display.rb +19 -0
  32. data/app/models/spree/permission_sets/stock_management.rb +19 -0
  33. data/app/models/spree/permission_sets/super_user.rb +28 -0
  34. data/app/models/spree/permission_sets/user_display.rb +19 -0
  35. data/app/models/spree/permission_sets/user_management.rb +20 -0
  36. data/app/models/spree/product.rb +37 -3
  37. data/app/models/spree/stock/coordinator.rb +1 -1
  38. data/app/models/spree/taxon.rb +1 -0
  39. data/app/models/spree/theme.rb +4 -4
  40. data/app/services/spree/compare_line_items.rb +1 -1
  41. data/app/views/spree/shared/_base_mailer_stylesheets.html.erb +5 -0
  42. data/config/locales/en.yml +5 -0
  43. data/lib/friendly_id/history_decorator.rb +26 -0
  44. data/lib/generators/spree/cursor_rules/templates/spree_rules.mdc +1 -1
  45. data/lib/generators/spree/install/templates/config/initializers/spree.rb +56 -24
  46. data/lib/generators/spree/model/model_generator.rb +21 -0
  47. data/lib/generators/spree/model/templates/model.rb.tt +22 -0
  48. data/lib/generators/spree/model_decorator/model_decorator_generator.rb +37 -0
  49. data/lib/generators/spree/model_decorator/templates/model_decorator.rb.tt +12 -0
  50. data/lib/spree/analytics.rb +2 -2
  51. data/lib/spree/core/engine.rb +10 -4
  52. data/lib/spree/core/partials.rb +42 -0
  53. data/lib/spree/core/permission_configuration.rb +102 -0
  54. data/lib/spree/core/token_generator.rb +1 -0
  55. data/lib/spree/core/version.rb +1 -1
  56. data/lib/spree/core.rb +208 -0
  57. data/lib/spree/testing_support/factories/order_factory.rb +7 -4
  58. data/lib/spree_core.rb +1 -0
  59. metadata +31 -12
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 531657763d76e0ce76fb2845acfeb30c110343666bc5e8e727de1f21249da4cd
4
- data.tar.gz: 2d4f33f07d6b90d61c9578575889c7c597a39b98e19597c90f902e312832af2c
3
+ metadata.gz: 77f4a7f3643f4b9263ab029e06d7870f5f45397e295f4116a485bc82a280d15f
4
+ data.tar.gz: 482208c5fd5725818a539a4daa4d566bd4c57c1c82595166e6232c91c56b876f
5
5
  SHA512:
6
- metadata.gz: 1a5aa4b5e32b63a67c2cb557a77014fe1d6cbd55d4f1df437480ff2c3502e4f9fbb533caea745e90a3cb7fd8013439d591f4247c5203e44e75dec638a62abf3e
7
- data.tar.gz: 7b66c4d564e21310dbc962eb1398886441a0a374b85f955a1e317cdbaef8fb27ea312d1987c33c611138e6ff1bf48e9f4de6a7301f0666423658bf7f831ec0ab
6
+ metadata.gz: 6424ad89c3f5a35cade4d6fc2dc67a74bbf1e0fab459727630c49582f5f94581924b16fba3ce54844d9fddac8cf2f2c2e442c4937f00db98d4276f1e5fb45649
7
+ data.tar.gz: 5dbaa89fd0648e3b35d5f4d7d48ee1066d3bf2da71cae97ee2c9769600380c95054f0aee146f845d4c92910f9b1944bc52155b98508345482ba3bb47224c689f
@@ -9,7 +9,7 @@ module Spree
9
9
  end
10
10
 
11
11
  def grouped_available_store_integrations
12
- Rails.application.config.spree.integrations.group_by(&:integration_group).sort_by { |group, _| group }
12
+ Spree.integrations.group_by(&:integration_group).sort_by { |group, _| group }
13
13
  end
14
14
  end
15
15
  end
@@ -13,7 +13,7 @@ module Spree
13
13
 
14
14
  Spree::Image.ensure_metafield_definition_exists!(Spree::Image::EXTERNAL_URL_METAFIELD_KEY)
15
15
 
16
- external_url = external_url.downcase.strip
16
+ external_url = external_url.strip
17
17
  external_id = external_id.to_s.downcase.strip if external_id.present?
18
18
 
19
19
  image = find_or_initialize_image(viewable, external_url, external_id)
@@ -30,7 +30,7 @@ module Spree
30
30
  end
31
31
 
32
32
  def self.spree_calculators
33
- Rails.application.config.spree.calculators
33
+ Spree.calculators
34
34
  end
35
35
  end
36
36
  end
@@ -160,7 +160,7 @@ module Spree
160
160
  private
161
161
 
162
162
  def check_completed_orders
163
- raise Spree::Core::DestroyWithOrdersError if !has_spree_role?(Spree::Role::ADMIN_ROLE) && orders.complete.present?
163
+ raise Spree::Core::DestroyWithOrdersError if !spree_admin? && orders.complete.present?
164
164
  end
165
165
 
166
166
  def clone_billing_address
@@ -1,6 +1,15 @@
1
1
  # Implementation class for Cancan gem. Instead of overriding this class, consider adding new permissions
2
2
  # using the special +register_ability+ method which allows extensions to add their own abilities.
3
3
  #
4
+ # The preferred way to add permissions is now through permission sets. See Spree::PermissionSets::Base
5
+ # for more details on creating custom permission sets.
6
+ #
7
+ # @example Configuring role permissions
8
+ # Spree.permissions.assign(:customer_service, [
9
+ # Spree::PermissionSets::OrderDisplay,
10
+ # Spree::PermissionSets::UserManagement
11
+ # ])
12
+ #
4
13
  # See https://github.com/CanCanCommunity/cancancan for more details.
5
14
  require 'cancan'
6
15
 
@@ -11,6 +20,12 @@ module Spree
11
20
  class_attribute :abilities
12
21
  self.abilities = Set.new
13
22
 
23
+ # @return [Object] the current user
24
+ attr_reader :user
25
+
26
+ # @return [Spree::Store, nil] the current store
27
+ attr_reader :store
28
+
14
29
  # Allows us to go beyond the standard cancan initialize method which makes it difficult for engines to
15
30
  # modify the default +Ability+ of an application. The +ability+ argument must be a class that includes
16
31
  # the +CanCan::Ability+ module. The registered ability should behave properly as a stand-alone class
@@ -26,22 +41,16 @@ module Spree
26
41
  def initialize(user, options = {})
27
42
  alias_cancan_delete_action
28
43
 
29
- user ||= Spree.user_class.new
30
- store ||= options[:store] || Spree::Current.store
44
+ @user = user || Spree.user_class.new
45
+ @store = options[:store] || Spree::Current.store
31
46
 
32
- if user.persisted? && user.is_a?(Spree.admin_user_class) && user.try(:spree_admin?, store)
33
- apply_admin_permissions(user, options)
34
- else
35
- apply_user_permissions(user, options)
36
- end
47
+ apply_permissions_from_sets
37
48
 
38
49
  # Include any abilities registered by extensions, etc.
39
50
  # this is legacy behaviour and should be removed in Spree 5.0
40
51
  Ability.abilities.merge(abilities_to_register).each do |clazz|
41
- merge clazz.new(user)
52
+ merge clazz.new(@user)
42
53
  end
43
-
44
- protect_admin_role
45
54
  end
46
55
 
47
56
  protected
@@ -57,6 +66,62 @@ module Spree
57
66
  alias_action :create, :update, :destroy, to: :modify
58
67
  end
59
68
 
69
+ # Applies permissions based on the user's roles and the configured permission sets.
70
+ def apply_permissions_from_sets
71
+ role_names = determine_role_names
72
+ permission_sets = Spree.permissions.permission_sets_for_roles(role_names)
73
+
74
+ # If no permission sets are configured for the user's roles, use legacy behavior
75
+ if permission_sets.empty?
76
+ apply_legacy_permissions
77
+ else
78
+ activate_permission_sets(permission_sets)
79
+ end
80
+ end
81
+
82
+ # Determines the role names for the current user.
83
+ #
84
+ # @return [Array<Symbol>] the role names
85
+ def determine_role_names
86
+ return [:default] unless @user.persisted?
87
+
88
+ # First, try to get roles from the spree_roles association
89
+ if @user.respond_to?(:spree_roles)
90
+ role_names = @user.spree_roles.pluck(:name).map(&:to_sym)
91
+ return role_names if role_names.any?
92
+ end
93
+
94
+ # Fall back to checking spree_admin? for backward compatibility
95
+ # This supports cases where roles are mocked or admin status is determined differently
96
+ if @user.try(:spree_admin?, @store)
97
+ [:admin]
98
+ else
99
+ [:default]
100
+ end
101
+ end
102
+
103
+ # Activates the given permission sets.
104
+ #
105
+ # @param permission_sets [Array<Class>] the permission set classes to activate
106
+ def activate_permission_sets(permission_sets)
107
+ permission_sets.each do |permission_set_class|
108
+ permission_set = permission_set_class.new(self)
109
+ permission_set.activate!
110
+ end
111
+ end
112
+
113
+ # Legacy permission application for backward compatibility.
114
+ # This is used when no permission sets are configured for the user's roles.
115
+ def apply_legacy_permissions
116
+ if @user.persisted? && @user.is_a?(Spree.admin_user_class) && @user.try(:spree_admin?, @store)
117
+ apply_admin_permissions(@user, { store: @store })
118
+ else
119
+ apply_user_permissions(@user, { store: @store })
120
+ end
121
+
122
+ protect_admin_role
123
+ end
124
+
60
125
  def apply_admin_permissions(_user, _options)
61
126
  can :manage, :all
62
127
  cannot :cancel, Spree::Order
@@ -76,7 +76,7 @@ module Spree
76
76
  allow_nil: true }
77
77
 
78
78
  def address_validators
79
- Rails.application.config.spree.validators.addresses.each do |validator|
79
+ Spree.validators.addresses.each do |validator|
80
80
  validates_with validator
81
81
  end
82
82
  end
@@ -55,7 +55,7 @@ module Spree
55
55
  end
56
56
 
57
57
  def adjusters
58
- Rails.application.config.spree.adjusters
58
+ Spree.adjusters
59
59
  end
60
60
 
61
61
  def tax_adjuster
@@ -22,7 +22,7 @@ module Spree
22
22
  scope :with_session_uploaded_assets_uuid, lambda { |uuid|
23
23
  where(session_id: uuid)
24
24
  }
25
- scope :with_external_url, ->(url) { url.present? ? with_metafield_key_value(EXTERNAL_URL_METAFIELD_KEY, url.downcase.strip) : none }
25
+ scope :with_external_url, ->(url) { url.present? ? with_metafield_key_value(EXTERNAL_URL_METAFIELD_KEY, url.strip) : none }
26
26
 
27
27
  def product
28
28
  @product ||= viewable_type == 'Spree::Variant' ? viewable&.product : nil
@@ -33,7 +33,7 @@ module Spree
33
33
  end
34
34
 
35
35
  def external_url=(url)
36
- set_metafield(EXTERNAL_URL_METAFIELD_KEY, url.downcase.strip)
36
+ set_metafield(EXTERNAL_URL_METAFIELD_KEY, url.strip)
37
37
  end
38
38
 
39
39
  def skip_import?
@@ -26,7 +26,7 @@ module Spree
26
26
 
27
27
  # Returns all calculators applicable for kind of work
28
28
  def self.calculators
29
- Rails.application.config.spree.calculators
29
+ Spree.calculators
30
30
  end
31
31
 
32
32
  def to_s
@@ -33,7 +33,7 @@ module Spree
33
33
  end
34
34
 
35
35
  def available_types
36
- Rails.application.config.spree.data_feed_types
36
+ Spree.data_feed_types
37
37
  end
38
38
  end
39
39
  end
@@ -175,7 +175,7 @@ module Spree
175
175
 
176
176
  class << self
177
177
  def available_types
178
- Rails.application.config.spree.export_types
178
+ Spree.export_types
179
179
  end
180
180
 
181
181
  def available_models
@@ -60,7 +60,7 @@ module Spree
60
60
  end
61
61
 
62
62
  def void(_response_code, _credit_card, _options = {})
63
- ActiveMerchant::Billing::Response.new(true, 'Bogus Gateway: Forced success', {}, test: true, authorization: '12345')
63
+ ActiveMerchant::Billing::Response.new(true, 'Bogus Gateway: Forced success', {}, test: true, authorization: 'void-12345')
64
64
  end
65
65
 
66
66
  def cancel(_response_code, _payment = nil)
@@ -224,7 +224,7 @@ module Spree
224
224
  # Returns the available types for the import
225
225
  # @return [Array<Class>]
226
226
  def available_types
227
- Rails.application.config.spree.import_types
227
+ Spree.import_types
228
228
  end
229
229
 
230
230
  # Returns the available models for the import
@@ -61,13 +61,13 @@ module Spree
61
61
  # Returns the available types
62
62
  # @return [Array<Class>]
63
63
  def self.available_types
64
- Rails.application.config.spree.metafield_types
64
+ Spree.metafields.types
65
65
  end
66
66
 
67
67
  # Returns the available resources
68
68
  # @return [Array<Class>]
69
69
  def self.available_resources
70
- Rails.application.config.spree.metafield_enabled_resources
70
+ Spree.metafields.enabled_resources
71
71
  end
72
72
 
73
73
  private
@@ -81,7 +81,7 @@ module Spree
81
81
  end
82
82
 
83
83
  def set_default_type
84
- self.metafield_type ||= Rails.application.config.spree.metafield_types.first.to_s
84
+ self.metafield_type ||= Spree.metafields.types.first.to_s
85
85
  end
86
86
 
87
87
  def set_name_from_key
@@ -44,6 +44,8 @@ module Spree
44
44
  def process_payments_with(method)
45
45
  # Don't run if there is nothing to pay.
46
46
  return if payment_total >= total
47
+ # Don't run if there are authorized payments
48
+ return if pending_payments.any? && unprocessed_payments.empty?
47
49
  # Prevent orders from transitioning to complete without a successfully processed payment.
48
50
  raise Core::GatewayError, Spree.t(:no_payment_found) if unprocessed_payments.empty?
49
51
 
@@ -910,6 +910,7 @@ module Spree
910
910
  payments.completed.store_credits.each(&:void!)
911
911
  else
912
912
  payments.completed.each(&:cancel!)
913
+ payments.incomplete.not_store_credits.each(&:void_transaction!)
913
914
  payments.store_credits.pending.each(&:void!)
914
915
  end
915
916
 
@@ -26,6 +26,19 @@ module Spree
26
26
  handle_payment_preconditions { process_purchase }
27
27
  end
28
28
 
29
+ # Confirms a payment by completing it or pending it depending on the payment method's auto_capture setting
30
+ # Useful for payments that are authorized/captured with SDK/Drop-in elements
31
+ def confirm!
32
+ started_processing! if checkout?
33
+
34
+ if payment_method&.auto_capture? && can_complete?
35
+ complete!
36
+ capture_events.create!(amount: amount)
37
+ elsif can_pend?
38
+ pend!
39
+ end
40
+ end
41
+
29
42
  # Takes the amount in cents to capture.
30
43
  # Can be used to capture partial amounts of a payment, and will create
31
44
  # a new pending payment record for the remaining amount to capture later.
@@ -255,6 +255,26 @@ module Spree
255
255
  payment_method&.source_required?
256
256
  end
257
257
 
258
+ def add_gateway_processing_error(error_message)
259
+ if has_metafield?('gateway.processing_errors')
260
+ errors = JSON.parse(get_metafield('gateway.processing_errors').value)
261
+ errors << { message: error_message }
262
+
263
+ set_metafield('gateway.processing_errors', errors.to_json)
264
+ else
265
+ set_metafield('gateway.processing_errors', [{ message: error_message }].to_json)
266
+ end
267
+ end
268
+
269
+ def gateway_processing_error_messages
270
+ @gateway_processing_error_messages ||= begin
271
+ errors = JSON.parse(get_metafield('gateway.processing_errors')&.value || '[]')
272
+ errors.map { |error| error['message'] }
273
+ rescue JSON::ParserError
274
+ []
275
+ end
276
+ end
277
+
258
278
  private
259
279
 
260
280
  def set_amount
@@ -29,7 +29,7 @@ module Spree
29
29
  has_many :gateway_customers, class_name: 'Spree::GatewayCustomer', dependent: :destroy
30
30
 
31
31
  def self.providers
32
- Rails.application.config.spree.payment_methods
32
+ Spree.payment_methods
33
33
  end
34
34
 
35
35
  def provider_class
@@ -0,0 +1,81 @@
1
+ # Base class for all permission sets.
2
+ #
3
+ # Permission sets are reusable groups of permissions that can be assigned to roles.
4
+ # They provide a clean abstraction over CanCanCan abilities, making it easier to
5
+ # manage permissions in a modular way.
6
+ #
7
+ # @example Creating a custom permission set
8
+ # class Spree::PermissionSets::InventoryManagement < Spree::PermissionSets::Base
9
+ # def activate!
10
+ # can :manage, Spree::StockItem
11
+ # can :manage, Spree::StockLocation
12
+ # can :manage, Spree::StockMovement
13
+ # end
14
+ # end
15
+ #
16
+ # @example Assigning the permission set to a role
17
+ # Spree.permissions.assign(:warehouse_manager, Spree::PermissionSets::InventoryManagement)
18
+ #
19
+ module Spree
20
+ module PermissionSets
21
+ class Base
22
+ # @return [CanCan::Ability] the ability instance to add permissions to
23
+ attr_reader :ability
24
+
25
+ # @param ability [CanCan::Ability] the ability instance to add permissions to
26
+ def initialize(ability)
27
+ @ability = ability
28
+ end
29
+
30
+ # Activates this permission set by adding its permissions to the ability.
31
+ # Override this method in subclasses to define the permissions.
32
+ #
33
+ # @abstract
34
+ # @return [void]
35
+ def activate!
36
+ raise NotImplementedError, "#{self.class} must implement #activate!"
37
+ end
38
+
39
+ protected
40
+
41
+ # Delegates the `can` method to the ability instance.
42
+ #
43
+ # @param args [Array] arguments to pass to CanCan::Ability#can
44
+ # @param block [Proc] optional block for conditional permissions
45
+ def can(*args, &block)
46
+ ability.can(*args, &block)
47
+ end
48
+
49
+ # Delegates the `cannot` method to the ability instance.
50
+ #
51
+ # @param args [Array] arguments to pass to CanCan::Ability#cannot
52
+ # @param block [Proc] optional block for conditional permissions
53
+ def cannot(*args, &block)
54
+ ability.cannot(*args, &block)
55
+ end
56
+
57
+ # Delegates the `can?` method to the ability instance.
58
+ #
59
+ # @param args [Array] arguments to pass to CanCan::Ability#can?
60
+ # @return [Boolean]
61
+ def can?(*args)
62
+ ability.can?(*args)
63
+ end
64
+
65
+ # Returns the user from the ability instance.
66
+ # This method assumes the ability has a user accessor.
67
+ #
68
+ # @return [Object] the current user
69
+ def user
70
+ ability.user
71
+ end
72
+
73
+ # Returns the store from the ability instance options.
74
+ #
75
+ # @return [Spree::Store, nil] the current store
76
+ def store
77
+ ability.store
78
+ end
79
+ end
80
+ end
81
+ end
@@ -0,0 +1,47 @@
1
+ # Permission set for managing store configuration and settings.
2
+ #
3
+ # This permission set provides access to manage store settings,
4
+ # payment methods, shipping methods, and other configuration.
5
+ #
6
+ # @example
7
+ # Spree.permissions.assign(:store_admin, Spree::PermissionSets::ConfigurationManagement)
8
+ #
9
+ module Spree
10
+ module PermissionSets
11
+ class ConfigurationManagement < Base
12
+ def activate!
13
+ # Store settings
14
+ can :manage, Spree::Store
15
+
16
+ # Payment configuration
17
+ can :manage, Spree::PaymentMethod
18
+ can :manage, Spree::Gateway
19
+
20
+ # Shipping configuration
21
+ can :manage, Spree::ShippingMethod
22
+ can :manage, Spree::ShippingCategory
23
+ can :manage, Spree::Zone
24
+ can :manage, Spree::ZoneMember
25
+
26
+ # Tax configuration
27
+ can :manage, Spree::TaxCategory
28
+ can :manage, Spree::TaxRate
29
+
30
+ # General configuration
31
+ can :manage, Spree::RefundReason
32
+ can :manage, Spree::ReimbursementType
33
+ can :manage, Spree::ReturnReason
34
+
35
+ # Restrictions on immutable types
36
+ cannot [:edit, :update], Spree::RefundReason, mutable: false
37
+ cannot [:edit, :update], Spree::ReimbursementType, mutable: false
38
+
39
+ # Metafield configuration
40
+ can :manage, Spree::MetafieldDefinition
41
+
42
+ # Policies
43
+ can :manage, Spree::Policy
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,17 @@
1
+ # Permission set for viewing the admin dashboard.
2
+ #
3
+ # This permission set provides access to view the admin dashboard
4
+ # and basic admin navigation.
5
+ #
6
+ # @example
7
+ # Spree.permissions.assign(:viewer, Spree::PermissionSets::DashboardDisplay)
8
+ #
9
+ module Spree
10
+ module PermissionSets
11
+ class DashboardDisplay < Base
12
+ def activate!
13
+ can [:admin, :index, :show], :dashboard
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,66 @@
1
+ # Permission set for default storefront customers (both authenticated and guests).
2
+ #
3
+ # This permission set provides the standard permissions needed for browsing
4
+ # the store and making purchases.
5
+ #
6
+ # @example
7
+ # Spree.permissions.assign(:default, Spree::PermissionSets::DefaultCustomer)
8
+ #
9
+ module Spree
10
+ module PermissionSets
11
+ class DefaultCustomer < Base
12
+ def activate!
13
+ # Read-only access to catalog
14
+ can :read, Spree::Country
15
+ can :read, Spree::OptionType
16
+ can :read, Spree::OptionValue
17
+ can :read, Spree::Product
18
+ can :read, Spree::ProductProperty
19
+ can :read, Spree::Property
20
+ can :read, Spree::State
21
+ can :read, Spree::Store
22
+ can :read, Spree::Taxon
23
+ can :read, Spree::Taxonomy
24
+ can :read, Spree::Variant
25
+ can :read, Spree::Zone
26
+
27
+ # Content pages
28
+ can :read, Spree::Policy
29
+ can :read, Spree::Page
30
+ can :read, Spree::Post
31
+ can :read, Spree::PostCategory
32
+
33
+ # Order management for the user's own orders
34
+ can :create, Spree::Order
35
+ can :show, Spree::Order do |order, token|
36
+ order.user == user || order.token && token == order.token
37
+ end
38
+ can :update, Spree::Order do |order, token|
39
+ !order.completed? && (order.user == user || order.token && token == order.token)
40
+ end
41
+
42
+ # User account management - available to all users (including guests for their own record)
43
+ can :create, Spree.user_class
44
+ can [:show, :update, :destroy], Spree.user_class, id: user.id
45
+
46
+ # Address management
47
+ can :manage, Spree::Address, user_id: user.id
48
+
49
+ # Credit card management
50
+ can [:read, :destroy], Spree::CreditCard, user_id: user.id
51
+
52
+ # Wishlist management
53
+ can :manage, Spree::Wishlist, user_id: user.id
54
+ can :show, Spree::Wishlist do |wishlist|
55
+ wishlist.user == user || wishlist.is_private == false
56
+ end
57
+ can [:create, :update, :destroy], Spree::WishedItem do |wished_item|
58
+ wished_item.wishlist.user == user
59
+ end
60
+
61
+ # Invitation acceptance
62
+ can :accept, Spree::Invitation, invitee_id: [user.id, nil], invitee_type: user.class.name, status: 'pending'
63
+ end
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,27 @@
1
+ # Permission set for viewing orders and related resources.
2
+ #
3
+ # This permission set provides read-only access to orders and associated
4
+ # models like payments, shipments, and refunds.
5
+ #
6
+ # @example
7
+ # Spree.permissions.assign(:customer_service, Spree::PermissionSets::OrderDisplay)
8
+ #
9
+ module Spree
10
+ module PermissionSets
11
+ class OrderDisplay < Base
12
+ def activate!
13
+ can [:read, :admin, :index], Spree::Order
14
+ can [:read, :admin], Spree::Payment
15
+ can [:read, :admin], Spree::Shipment
16
+ can [:read, :admin], Spree::Adjustment
17
+ can [:read, :admin], Spree::LineItem
18
+ can [:read, :admin], Spree::ReturnAuthorization
19
+ can [:read, :admin], Spree::CustomerReturn
20
+ can [:read, :admin], Spree::Reimbursement
21
+ can [:read, :admin], Spree::Refund
22
+ can [:read, :admin], Spree::StoreCredit
23
+ can [:read, :admin], Spree::GiftCard
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,33 @@
1
+ # Permission set for full order management.
2
+ #
3
+ # This permission set provides complete access to manage orders,
4
+ # including creating, updating, and processing payments and shipments.
5
+ #
6
+ # @example
7
+ # Spree.permissions.assign(:order_manager, Spree::PermissionSets::OrderManagement)
8
+ #
9
+ module Spree
10
+ module PermissionSets
11
+ class OrderManagement < Base
12
+ def activate!
13
+ can :manage, Spree::Order
14
+ can :manage, Spree::Payment
15
+ can :manage, Spree::Shipment
16
+ can :manage, Spree::Adjustment
17
+ can :manage, Spree::LineItem
18
+ can :manage, Spree::ReturnAuthorization
19
+ can :manage, Spree::CustomerReturn
20
+ can :manage, Spree::Reimbursement
21
+ can :manage, Spree::Refund
22
+ can :manage, Spree::StoreCredit
23
+ can :manage, Spree::GiftCard
24
+
25
+ # Order-specific restrictions
26
+ cannot :cancel, Spree::Order
27
+ can :cancel, Spree::Order, &:allow_cancel?
28
+ cannot :destroy, Spree::Order
29
+ can :destroy, Spree::Order, &:can_be_deleted?
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,27 @@
1
+ # Permission set for viewing products and catalog information.
2
+ #
3
+ # This permission set provides read-only access to products, variants,
4
+ # and related catalog models.
5
+ #
6
+ # @example
7
+ # Spree.permissions.assign(:content_editor, Spree::PermissionSets::ProductDisplay)
8
+ #
9
+ module Spree
10
+ module PermissionSets
11
+ class ProductDisplay < Base
12
+ def activate!
13
+ can [:read, :admin, :index], Spree::Product
14
+ can [:read, :admin], Spree::Variant
15
+ can [:read, :admin], Spree::OptionType
16
+ can [:read, :admin], Spree::OptionValue
17
+ can [:read, :admin], Spree::Property
18
+ can [:read, :admin], Spree::ProductProperty
19
+ can [:read, :admin], Spree::Metafield
20
+ can [:read, :admin], Spree::Taxon
21
+ can [:read, :admin], Spree::Taxonomy
22
+ can [:read, :admin], Spree::Classification
23
+ can [:read, :admin], Spree::Price
24
+ end
25
+ end
26
+ end
27
+ end