@spree/docs 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +54 -0
- package/dist/api-reference/platform/authentication.md +38 -0
- package/dist/api-reference/store-api/authentication.md +188 -0
- package/dist/api-reference/store-api/errors.md +277 -0
- package/dist/api-reference/store-api/idempotency.md +129 -0
- package/dist/api-reference/store-api/introduction.md +34 -0
- package/dist/api-reference/store-api/localization.md +279 -0
- package/dist/api-reference/store-api/metadata.md +160 -0
- package/dist/api-reference/store-api/monetary-amounts.md +65 -0
- package/dist/api-reference/store-api/querying.md +399 -0
- package/dist/api-reference/store-api/rate-limitting.md +103 -0
- package/dist/api-reference/store-api/relations.md +185 -0
- package/dist/api-reference/storefront/authentication.md +88 -0
- package/dist/api-reference/tutorials/adyen-integration-guide-for-android.md +165 -0
- package/dist/api-reference/tutorials/adyen-integration-guide-for-ios.md +194 -0
- package/dist/api-reference/tutorials/quick-checkout-with-stripe.md +248 -0
- package/dist/api-reference/v2/fetching-multiple-resources.md +26 -0
- package/dist/api-reference/v2/filtering-and-sorting.md +53 -0
- package/dist/api-reference/v2/introduction.md +22 -0
- package/dist/api-reference/v2/pagination.md +37 -0
- package/dist/api-reference/webhooks-events.md +883 -0
- package/dist/developer/admin/admin.md +205 -0
- package/dist/developer/admin/authentication.md +59 -0
- package/dist/developer/admin/components.md +711 -0
- package/dist/developer/admin/custom-css.md +243 -0
- package/dist/developer/admin/custom-javascript.md +116 -0
- package/dist/developer/admin/extending-ui.md +1964 -0
- package/dist/developer/admin/form-builder.md +444 -0
- package/dist/developer/admin/helper-methods.md +531 -0
- package/dist/developer/admin/navigation.md +805 -0
- package/dist/developer/admin/tables.md +491 -0
- package/dist/developer/advanced/adding_spree_to_rails_app.md +106 -0
- package/dist/developer/cli/quickstart.md +137 -0
- package/dist/developer/contributing/creating-an-extension.md +258 -0
- package/dist/developer/contributing/developing-spree.md +339 -0
- package/dist/developer/contributing/quickstart.md +32 -0
- package/dist/developer/contributing/updating-extensions.md +67 -0
- package/dist/developer/core-concepts/addresses.md +265 -0
- package/dist/developer/core-concepts/adjustments.md +107 -0
- package/dist/developer/core-concepts/architecture.md +177 -0
- package/dist/developer/core-concepts/calculators.md +323 -0
- package/dist/developer/core-concepts/customers.md +230 -0
- package/dist/developer/core-concepts/events.md +624 -0
- package/dist/developer/core-concepts/imports-exports.md +698 -0
- package/dist/developer/core-concepts/inventory.md +191 -0
- package/dist/developer/core-concepts/markets.md +250 -0
- package/dist/developer/core-concepts/media.md +167 -0
- package/dist/developer/core-concepts/metafields.md +187 -0
- package/dist/developer/core-concepts/orders.md +328 -0
- package/dist/developer/core-concepts/payments.md +710 -0
- package/dist/developer/core-concepts/pricing.md +163 -0
- package/dist/developer/core-concepts/products.md +360 -0
- package/dist/developer/core-concepts/promotions.md +322 -0
- package/dist/developer/core-concepts/reports.md +206 -0
- package/dist/developer/core-concepts/search-filtering.md +237 -0
- package/dist/developer/core-concepts/shipments.md +212 -0
- package/dist/developer/core-concepts/slugs.md +111 -0
- package/dist/developer/core-concepts/staff-roles.md +123 -0
- package/dist/developer/core-concepts/store-credits-gift-cards.md +317 -0
- package/dist/developer/core-concepts/stores.md +117 -0
- package/dist/developer/core-concepts/taxes.md +135 -0
- package/dist/developer/core-concepts/translations.md +120 -0
- package/dist/developer/core-concepts/users.md +299 -0
- package/dist/developer/core-concepts/webhooks.md +378 -0
- package/dist/developer/create-spree-app/quickstart.md +158 -0
- package/dist/developer/customization/api.md +93 -0
- package/dist/developer/customization/authentication.md +88 -0
- package/dist/developer/customization/checkout.md +204 -0
- package/dist/developer/customization/configuration.md +55 -0
- package/dist/developer/customization/decorators.md +523 -0
- package/dist/developer/customization/dependencies.md +232 -0
- package/dist/developer/customization/emails.md +21 -0
- package/dist/developer/customization/extensions.md +92 -0
- package/dist/developer/customization/metadata.md +236 -0
- package/dist/developer/customization/model-preferences.md +130 -0
- package/dist/developer/customization/permissions.md +265 -0
- package/dist/developer/customization/quickstart.md +229 -0
- package/dist/developer/customization/routes.md +24 -0
- package/dist/developer/customization/v4/admin-panel.md +78 -0
- package/dist/developer/customization/v4/authentication.md +210 -0
- package/dist/developer/customization/v4/checkout.md +212 -0
- package/dist/developer/customization/v4/deface.md +251 -0
- package/dist/developer/customization/v4/images.md +86 -0
- package/dist/developer/customization/v4/storefront.md +450 -0
- package/dist/developer/deployment/assets.md +87 -0
- package/dist/developer/deployment/aws.md +335 -0
- package/dist/developer/deployment/caching.md +27 -0
- package/dist/developer/deployment/cdn.md +39 -0
- package/dist/developer/deployment/database.md +155 -0
- package/dist/developer/deployment/docker.md +128 -0
- package/dist/developer/deployment/emails.md +77 -0
- package/dist/developer/deployment/environment_variables.md +111 -0
- package/dist/developer/deployment/heroku.md +51 -0
- package/dist/developer/deployment/render.md +95 -0
- package/dist/developer/getting-started/quickstart.md +82 -0
- package/dist/developer/how-to/custom-payment-method.md +374 -0
- package/dist/developer/how-to/custom-promotion.md +373 -0
- package/dist/developer/how-to/custom-report.md +387 -0
- package/dist/developer/how-to/custom-search-provider.md +230 -0
- package/dist/developer/multi-store/quickstart.md +71 -0
- package/dist/developer/multi-store/setup.md +38 -0
- package/dist/developer/multi-tenant/configuration.md +41 -0
- package/dist/developer/multi-tenant/core-concepts.md +75 -0
- package/dist/developer/multi-tenant/installation.md +96 -0
- package/dist/developer/multi-tenant/quickstart.md +20 -0
- package/dist/developer/multi-vendor/installation.md +45 -0
- package/dist/developer/multi-vendor/quickstart.md +17 -0
- package/dist/developer/sdk/admin/quickstart.md +22 -0
- package/dist/developer/sdk/authentication.md +89 -0
- package/dist/developer/sdk/configuration.md +225 -0
- package/dist/developer/sdk/quickstart.md +82 -0
- package/dist/developer/sdk/store/account.md +67 -0
- package/dist/developer/sdk/store/cart-checkout.md +140 -0
- package/dist/developer/sdk/store/markets.md +151 -0
- package/dist/developer/sdk/store/payments.md +96 -0
- package/dist/developer/sdk/store/products.md +149 -0
- package/dist/developer/sdk/store/wishlists.md +52 -0
- package/dist/developer/security/pci_compliance.md +15 -0
- package/dist/developer/security/security_policy.md +68 -0
- package/dist/developer/storefront/blocks.md +285 -0
- package/dist/developer/storefront/custom-css.md +260 -0
- package/dist/developer/storefront/custom-javascript.md +166 -0
- package/dist/developer/storefront/helper-methods.md +1288 -0
- package/dist/developer/storefront/links.md +298 -0
- package/dist/developer/storefront/nextjs/architecture.md +150 -0
- package/dist/developer/storefront/nextjs/customization.md +141 -0
- package/dist/developer/storefront/nextjs/deployment.md +180 -0
- package/dist/developer/storefront/nextjs/quickstart.md +92 -0
- package/dist/developer/storefront/nextjs/spree-next-package.md +314 -0
- package/dist/developer/storefront/pages.md +163 -0
- package/dist/developer/storefront/sections.md +569 -0
- package/dist/developer/storefront/storefront.md +56 -0
- package/dist/developer/storefront/themes.md +161 -0
- package/dist/developer/tutorial/admin.md +134 -0
- package/dist/developer/tutorial/extending-models.md +380 -0
- package/dist/developer/tutorial/file-uploads.md +121 -0
- package/dist/developer/tutorial/introduction.md +33 -0
- package/dist/developer/tutorial/model.md +41 -0
- package/dist/developer/tutorial/page-builder.md +487 -0
- package/dist/developer/tutorial/rich-text.md +73 -0
- package/dist/developer/tutorial/seo.md +332 -0
- package/dist/developer/tutorial/storefront.md +352 -0
- package/dist/developer/tutorial/testing.md +558 -0
- package/dist/developer/upgrades/2.0-to-2.1.md +46 -0
- package/dist/developer/upgrades/2.1-to-2.2.md +59 -0
- package/dist/developer/upgrades/2.2-to-2.3.md +44 -0
- package/dist/developer/upgrades/2.3-to-2.4.md +42 -0
- package/dist/developer/upgrades/3.0-to-3.1.md +47 -0
- package/dist/developer/upgrades/3.1-to-3.2.md +34 -0
- package/dist/developer/upgrades/3.2-to-3.3.md +70 -0
- package/dist/developer/upgrades/3.3-to-3.4.md +36 -0
- package/dist/developer/upgrades/3.4-to-3.5.md +44 -0
- package/dist/developer/upgrades/3.5-to-3.6.md +40 -0
- package/dist/developer/upgrades/3.6-to-3.7.md +62 -0
- package/dist/developer/upgrades/3.7-to-4.0.md +152 -0
- package/dist/developer/upgrades/4.0-to-4.1.md +92 -0
- package/dist/developer/upgrades/4.1-to-4.2.md +109 -0
- package/dist/developer/upgrades/4.10-to-5.0.md +129 -0
- package/dist/developer/upgrades/4.2-to-4.3.md +100 -0
- package/dist/developer/upgrades/4.3-to-4.4.md +125 -0
- package/dist/developer/upgrades/4.4-to-4.5.md +94 -0
- package/dist/developer/upgrades/4.5-to-4.6.md +119 -0
- package/dist/developer/upgrades/4.6-to-4.7.md +39 -0
- package/dist/developer/upgrades/4.8-to-4.9.md +24 -0
- package/dist/developer/upgrades/4.9-to-4.10.md +24 -0
- package/dist/developer/upgrades/4.x-to-4.8.md +52 -0
- package/dist/developer/upgrades/5.0-to-5.1.md +28 -0
- package/dist/developer/upgrades/5.1-to-5.2.md +127 -0
- package/dist/developer/upgrades/5.2-to-5.3.md +338 -0
- package/dist/developer/upgrades/5.3-to-5.4.md +248 -0
- package/dist/developer/upgrades/quickstart.md +36 -0
- package/dist/integrations/analytics/google-analytics.md +64 -0
- package/dist/integrations/analytics/google-tag-manager.md +78 -0
- package/dist/integrations/integrations.md +39 -0
- package/dist/integrations/marketing/klaviyo.md +99 -0
- package/dist/integrations/payments/adyen.md +90 -0
- package/dist/integrations/payments/paypal.md +41 -0
- package/dist/integrations/payments/razorpay.md +45 -0
- package/dist/integrations/payments/stripe.md +109 -0
- package/dist/integrations/search/meilisearch.md +236 -0
- package/dist/integrations/sso-mfa-social-login/admin-dashboard.md +57 -0
- package/dist/integrations/sso-mfa-social-login/storefront.md +56 -0
- package/package.json +27 -0
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Model Preferences
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
Model preferences allow you to easily extend Spree models with configuration options. Thanks to this you can store useful information on Spree models, eg.
|
|
6
|
+
|
|
7
|
+
```ruby
|
|
8
|
+
user.preferred_language = "English"
|
|
9
|
+
user.save
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
## Defining Model Preferences
|
|
13
|
+
|
|
14
|
+
To define a model preference, you need to add them to your model class.
|
|
15
|
+
|
|
16
|
+
Make sure to generate a migration to add the `preferences` column to the table. This column will store the preferences in a serialized format.
|
|
17
|
+
|
|
18
|
+
```ruby
|
|
19
|
+
rails g migration AddPreferencesToSpreeUsers preferences:text
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
Run the migration.
|
|
23
|
+
|
|
24
|
+
```ruby
|
|
25
|
+
rails db:migrate
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
```ruby
|
|
29
|
+
class Spree::User < ApplicationRecord
|
|
30
|
+
# ... you existing code ...
|
|
31
|
+
|
|
32
|
+
# include the preferable module
|
|
33
|
+
include Spree::Preferences::Preferable
|
|
34
|
+
# define the preferences
|
|
35
|
+
preference :language, :string, default: "English"
|
|
36
|
+
preference :sms_marketing, :boolean, default: false
|
|
37
|
+
end
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
This will add a `language` preference to the `User` model. The preference will be stored in the newly created `preferences` column of the `spree_users` table. You can add more preferences to the model in the same way.
|
|
41
|
+
|
|
42
|
+
## Accessing Model Preferences
|
|
43
|
+
|
|
44
|
+
Once preferences have been defined for a model, they can be accessed either using the shortcut methods that are generated for each preference or the generic methods that are not specific to a particular preference.
|
|
45
|
+
|
|
46
|
+
### Shortcut Methods
|
|
47
|
+
|
|
48
|
+
There are several shortcut methods that are generated. They are shown below.
|
|
49
|
+
|
|
50
|
+
Query methods:
|
|
51
|
+
|
|
52
|
+
```ruby
|
|
53
|
+
user.prefers_sms_marketing? # => false
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
Reader methods:
|
|
57
|
+
|
|
58
|
+
```ruby
|
|
59
|
+
user.preferred_sms_marketing # => false
|
|
60
|
+
user.preferred_language # => "English"
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
Writer methods:
|
|
64
|
+
|
|
65
|
+
```ruby
|
|
66
|
+
user.prefers_sms_marketing = false # => false
|
|
67
|
+
user.preferred_language = "English" # => "English"
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
> **NOTE:** Remember to run `user.save` after setting the preference value to save the changes to the database.
|
|
71
|
+
|
|
72
|
+
Check if a preference is available:
|
|
73
|
+
|
|
74
|
+
```ruby
|
|
75
|
+
user.has_preference? :sms_marketing
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
### Generic Methods
|
|
79
|
+
|
|
80
|
+
Each shortcut method is essentially a wrapper for the various generic methods shown below:
|
|
81
|
+
|
|
82
|
+
Query method:
|
|
83
|
+
|
|
84
|
+
```ruby
|
|
85
|
+
user.prefers?(:sms_marketing) # => false
|
|
86
|
+
user.prefers?(:language) # => false
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
Reader methods:
|
|
90
|
+
|
|
91
|
+
```ruby
|
|
92
|
+
user.preferred(:sms_marketing) # => false
|
|
93
|
+
user.preferred(:language) # => "English"
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
```ruby
|
|
97
|
+
user.get_preference :sms_marketing
|
|
98
|
+
user.get_preference :language
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
Writer method:
|
|
102
|
+
|
|
103
|
+
```ruby
|
|
104
|
+
user.set_preference(:sms_marketing, false) # => false
|
|
105
|
+
user.set_preference(:language, "English") # => "English"
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
### Accessing All Preferences
|
|
109
|
+
|
|
110
|
+
You can get a hash of all stored preferences by accessing the `preferences` helper:
|
|
111
|
+
|
|
112
|
+
```ruby
|
|
113
|
+
user.preferences # => {"language"=>"English", "sms_marketing"=>false}
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
This hash will contain the value for every preference that has been defined for the model instance, whether the value is the default or one that has been previously stored.
|
|
117
|
+
|
|
118
|
+
## Models with preferences
|
|
119
|
+
|
|
120
|
+
The following Spree models already have preferences defined:
|
|
121
|
+
|
|
122
|
+
* `Spree::Calculator`
|
|
123
|
+
* `Spree::Gateway`
|
|
124
|
+
* `Spree::PageBlock`
|
|
125
|
+
* `Spree::PageSection`
|
|
126
|
+
* `Spree::Page`
|
|
127
|
+
* `Spree::PaymentMethod`
|
|
128
|
+
* `Spree::PromotionRule`
|
|
129
|
+
* `Spree::Store`
|
|
130
|
+
* `Spree::Theme`
|
|
@@ -0,0 +1,265 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Permissions
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
Spree uses [CanCanCan](https://github.com/CanCanCommunity/cancancan) for authorization. The permission system allows you to define granular access control for different user roles.
|
|
6
|
+
|
|
7
|
+
## Permission Sets (Recommended)
|
|
8
|
+
|
|
9
|
+
Permission Sets provide a clean, modular way to manage permissions. Each permission set is a reusable group of permissions that can be assigned to roles.
|
|
10
|
+
|
|
11
|
+
### How It Works
|
|
12
|
+
|
|
13
|
+
1. **Roles** - Determine which permission sets govern a user's access (e.g., `admin`, `customer_service`)
|
|
14
|
+
2. **Permission Sets** - Contain the logic defining what actions users can perform on resources
|
|
15
|
+
3. **Role Configuration** - Associates roles with their corresponding permission sets
|
|
16
|
+
|
|
17
|
+
### Configuring Roles
|
|
18
|
+
|
|
19
|
+
In your `config/initializers/spree.rb`, configure which permission sets are assigned to each role:
|
|
20
|
+
|
|
21
|
+
```ruby
|
|
22
|
+
Rails.application.config.after_initialize do
|
|
23
|
+
# Default permissions for all users (guests and logged-in customers)
|
|
24
|
+
Spree.permissions.assign(:default, [Spree::PermissionSets::DefaultCustomer])
|
|
25
|
+
|
|
26
|
+
# Full admin access
|
|
27
|
+
Spree.permissions.assign(:admin, [Spree::PermissionSets::SuperUser])
|
|
28
|
+
|
|
29
|
+
# Custom role with specific permissions
|
|
30
|
+
Spree.permissions.assign(:customer_service, [
|
|
31
|
+
Spree::PermissionSets::DashboardDisplay,
|
|
32
|
+
Spree::PermissionSets::OrderManagement,
|
|
33
|
+
Spree::PermissionSets::UserDisplay
|
|
34
|
+
])
|
|
35
|
+
|
|
36
|
+
# Merchandiser role for product management
|
|
37
|
+
Spree.permissions.assign(:merchandiser, [
|
|
38
|
+
Spree::PermissionSets::DashboardDisplay,
|
|
39
|
+
Spree::PermissionSets::ProductManagement,
|
|
40
|
+
Spree::PermissionSets::StockManagement
|
|
41
|
+
])
|
|
42
|
+
end
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
### Built-in Permission Sets
|
|
46
|
+
|
|
47
|
+
| Permission Set | Description |
|
|
48
|
+
|---------------|-------------|
|
|
49
|
+
| `SuperUser` | Full admin access with safety restrictions |
|
|
50
|
+
| `DefaultCustomer` | Basic storefront permissions (browse, checkout, manage own account) |
|
|
51
|
+
| `DashboardDisplay` | View admin dashboard |
|
|
52
|
+
| `OrderDisplay` | Read-only access to orders |
|
|
53
|
+
| `OrderManagement` | Full order management (view, edit, refund, etc.) |
|
|
54
|
+
| `ProductDisplay` | Read-only access to products and catalog |
|
|
55
|
+
| `ProductManagement` | Full catalog management (products, variants, taxonomies) |
|
|
56
|
+
| `UserDisplay` | Read-only access to users |
|
|
57
|
+
| `UserManagement` | Full user management |
|
|
58
|
+
| `StockDisplay` | Read-only access to inventory |
|
|
59
|
+
| `StockManagement` | Full inventory management |
|
|
60
|
+
| `PromotionManagement` | Manage promotions and coupon codes |
|
|
61
|
+
| `ConfigurationManagement` | Manage store settings, shipping, taxes, etc. |
|
|
62
|
+
| `RoleManagement` | Manage roles (except the protected admin role) |
|
|
63
|
+
|
|
64
|
+
### Creating Custom Permission Sets
|
|
65
|
+
|
|
66
|
+
Create a new permission set in `app/models/spree/permission_sets/`:
|
|
67
|
+
|
|
68
|
+
```ruby
|
|
69
|
+
# app/models/spree/permission_sets/warehouse_management.rb
|
|
70
|
+
module Spree
|
|
71
|
+
module PermissionSets
|
|
72
|
+
class WarehouseManagement < Base
|
|
73
|
+
def activate!
|
|
74
|
+
can :manage, Spree::StockItem
|
|
75
|
+
can :manage, Spree::StockLocation
|
|
76
|
+
can :manage, Spree::StockMovement
|
|
77
|
+
can :manage, Spree::Shipment
|
|
78
|
+
can [:read, :admin], Spree::Order
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
Then assign it to a role:
|
|
86
|
+
|
|
87
|
+
```ruby
|
|
88
|
+
Spree.permissions.assign(:warehouse_staff, [
|
|
89
|
+
Spree::PermissionSets::DashboardDisplay,
|
|
90
|
+
Spree::PermissionSets::WarehouseManagement
|
|
91
|
+
])
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
### Permission Set API
|
|
95
|
+
|
|
96
|
+
Within a permission set, you have access to:
|
|
97
|
+
|
|
98
|
+
- `can(action, subject, conditions = {})` - Grant permission
|
|
99
|
+
- `cannot(action, subject, conditions = {})` - Deny permission
|
|
100
|
+
- `can?(action, subject)` - Check if permission exists
|
|
101
|
+
- `user` - The current user
|
|
102
|
+
- `store` - The current store (for multi-store setups)
|
|
103
|
+
|
|
104
|
+
```ruby
|
|
105
|
+
module Spree
|
|
106
|
+
module PermissionSets
|
|
107
|
+
class OrderManagementForOwnOrders < Base
|
|
108
|
+
def activate!
|
|
109
|
+
# Users can only manage orders they created
|
|
110
|
+
can :manage, Spree::Order, created_by_id: user.id
|
|
111
|
+
|
|
112
|
+
# But cannot cancel any order
|
|
113
|
+
cannot :cancel, Spree::Order
|
|
114
|
+
|
|
115
|
+
# Unless it's cancellable
|
|
116
|
+
can :cancel, Spree::Order, &:allow_cancel?
|
|
117
|
+
end
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
### Managing Permission Configuration
|
|
124
|
+
|
|
125
|
+
```ruby
|
|
126
|
+
# Assign permission sets to a role
|
|
127
|
+
Spree.permissions.assign(:customer_service, [
|
|
128
|
+
Spree::PermissionSets::OrderDisplay,
|
|
129
|
+
Spree::PermissionSets::UserManagement
|
|
130
|
+
])
|
|
131
|
+
|
|
132
|
+
# Add more permission sets to an existing role
|
|
133
|
+
Spree.permissions.assign(:customer_service, [
|
|
134
|
+
Spree::PermissionSets::StockDisplay
|
|
135
|
+
])
|
|
136
|
+
|
|
137
|
+
# Clear all permission sets from a role
|
|
138
|
+
Spree.permissions.clear(:customer_service)
|
|
139
|
+
|
|
140
|
+
# Check what permission sets a role has
|
|
141
|
+
Spree.permissions.permission_sets_for(:customer_service)
|
|
142
|
+
# => [Spree::PermissionSets::OrderDisplay, ...]
|
|
143
|
+
|
|
144
|
+
# Check if a role is configured
|
|
145
|
+
Spree.permissions.role_configured?(:customer_service)
|
|
146
|
+
# => true
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
## Users and Roles
|
|
150
|
+
|
|
151
|
+
Spree comes with an `admin` role by default. You can create more roles in the Admin Panel or via Rails console:
|
|
152
|
+
|
|
153
|
+
```ruby
|
|
154
|
+
Spree::Role.find_or_create_by(name: 'customer_service')
|
|
155
|
+
Spree::Role.find_or_create_by(name: 'merchandiser')
|
|
156
|
+
Spree::Role.find_or_create_by(name: 'warehouse_staff')
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
Assign a role to a user:
|
|
160
|
+
|
|
161
|
+
```ruby
|
|
162
|
+
user = Spree.user_class.find_by(email: 'john@example.com')
|
|
163
|
+
role = Spree::Role.find_by(name: 'customer_service')
|
|
164
|
+
user.spree_roles << role
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
### Default Role Behavior
|
|
168
|
+
|
|
169
|
+
- Users with **no roles assigned** automatically get the `:default` role permissions
|
|
170
|
+
- No `RoleUser` records are created for regular customers
|
|
171
|
+
- Only users with special permissions need explicit role assignments
|
|
172
|
+
|
|
173
|
+
## Legacy Approach: Custom Ability Classes
|
|
174
|
+
|
|
175
|
+
> **NOTE:** The permission sets approach above is recommended for new projects. The legacy approach below is supported for backward compatibility.
|
|
176
|
+
|
|
177
|
+
### Adding Custom Permissions via Decorator
|
|
178
|
+
|
|
179
|
+
Create a new ability class in `app/models/customer_service_ability.rb`:
|
|
180
|
+
|
|
181
|
+
```ruby
|
|
182
|
+
class CustomerServiceAbility
|
|
183
|
+
include CanCan::Ability
|
|
184
|
+
|
|
185
|
+
def initialize(user)
|
|
186
|
+
if user.respond_to?(:has_spree_role?) && user.has_spree_role?('customer_service')
|
|
187
|
+
can :manage, Spree::Order
|
|
188
|
+
end
|
|
189
|
+
end
|
|
190
|
+
end
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
Register it via a decorator in `app/models/spree/ability_decorator.rb`:
|
|
194
|
+
|
|
195
|
+
```ruby
|
|
196
|
+
module Spree
|
|
197
|
+
module AbilityDecorator
|
|
198
|
+
def abilities_to_register
|
|
199
|
+
[CustomerServiceAbility]
|
|
200
|
+
end
|
|
201
|
+
end
|
|
202
|
+
|
|
203
|
+
Ability.prepend(AbilityDecorator)
|
|
204
|
+
end
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
### Replacing the Ability Class
|
|
208
|
+
|
|
209
|
+
You can replace the entire ability class via [Dependencies](/developer/customization/dependencies):
|
|
210
|
+
|
|
211
|
+
```ruby
|
|
212
|
+
# config/initializers/spree.rb
|
|
213
|
+
Spree::Dependencies.ability_class = 'CustomAbility'
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
```ruby
|
|
217
|
+
# app/models/custom_ability.rb
|
|
218
|
+
class CustomAbility < Spree::Ability
|
|
219
|
+
def initialize(user, options = {})
|
|
220
|
+
alias_cancan_delete_action
|
|
221
|
+
|
|
222
|
+
@user = user || Spree.user_class.new
|
|
223
|
+
@store = options[:store] || Spree::Current.store
|
|
224
|
+
|
|
225
|
+
if @user.respond_to?(:has_spree_role?) && @user.has_spree_role?('admin')
|
|
226
|
+
apply_admin_permissions(@user, options)
|
|
227
|
+
elsif @user.respond_to?(:has_spree_role?) && @user.has_spree_role?(:customer_service)
|
|
228
|
+
apply_customer_service_permissions(@user)
|
|
229
|
+
else
|
|
230
|
+
apply_user_permissions(@user, options)
|
|
231
|
+
end
|
|
232
|
+
|
|
233
|
+
protect_admin_role
|
|
234
|
+
end
|
|
235
|
+
|
|
236
|
+
protected
|
|
237
|
+
|
|
238
|
+
def apply_customer_service_permissions(user)
|
|
239
|
+
can :manage, Spree::Order
|
|
240
|
+
can [:read, :admin], Spree.user_class
|
|
241
|
+
end
|
|
242
|
+
end
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
## CanCanCan Reference
|
|
246
|
+
|
|
247
|
+
Spree's permission system is built on CanCanCan. Key concepts:
|
|
248
|
+
|
|
249
|
+
- `can :action, Subject` - Grant permission
|
|
250
|
+
- `can :manage, Subject` - Grant all actions (create, read, update, destroy)
|
|
251
|
+
- `cannot :action, Subject` - Explicitly deny permission
|
|
252
|
+
- `can :action, Subject, conditions` - Conditional permission
|
|
253
|
+
|
|
254
|
+
```ruby
|
|
255
|
+
# Examples
|
|
256
|
+
can :read, Spree::Product # Can read any product
|
|
257
|
+
can :manage, Spree::Order, user_id: user.id # Can manage own orders
|
|
258
|
+
can :update, Spree::Order do |order| # Block conditions
|
|
259
|
+
order.user == user && !order.completed?
|
|
260
|
+
end
|
|
261
|
+
cannot :destroy, Spree::Order # Cannot destroy any order
|
|
262
|
+
can :destroy, Spree::Order, &:can_be_deleted? # Unless it's deletable
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
See the [CanCanCan documentation](https://github.com/CanCanCommunity/cancancan) for more details.
|
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Quickstart
|
|
3
|
+
og:title: Spree Customization Quickstart
|
|
4
|
+
description: Learn how to customize every part of the Spree stack
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
Spree is a flexible platform allowing you to customize every part of it to suit your business needs. This guide presents customization options **in order of recommendation** - start from the top and only move down if simpler options don't meet your needs.
|
|
8
|
+
|
|
9
|
+
## Quick Reference
|
|
10
|
+
|
|
11
|
+
| What you want to do | Recommended approach |
|
|
12
|
+
|---------------------|---------------------|
|
|
13
|
+
| Change store settings (currency, zones, languages) | [Store Settings](#store-settings) |
|
|
14
|
+
| Tweak Spree behavior globally | [Configuration](#configuration) |
|
|
15
|
+
| React to model changes (sync, notifications) | [Events & Subscribers](#events-and-subscribers) |
|
|
16
|
+
| Notify external services | [Webhooks](#webhooks) |
|
|
17
|
+
| Swap core services (cart, checkout, etc.) | [Dependencies](#dependencies) |
|
|
18
|
+
| Add admin menu items | [Admin Navigation](#admin-extensions) |
|
|
19
|
+
| Add sections to admin forms | [Admin Partials](#admin-extensions) |
|
|
20
|
+
| Add searchable/filterable fields | [Ransack Configuration](#search-and-filtering) |
|
|
21
|
+
| Add associations/validations to models | [Decorators](#decorators) (last resort) |
|
|
22
|
+
|
|
23
|
+
**Best for:** Changing currency, shipping zones, languages, and other business settings.
|
|
24
|
+
|
|
25
|
+
There's a lot of Store settings you can change in the admin panel without touching the code.
|
|
26
|
+
|
|
27
|
+
Go to **Admin > Settings**
|
|
28
|
+
|
|
29
|
+
<img src="/images/spree_admin_store_settings.png" alt="Spree Admin Store Settings" />
|
|
30
|
+
|
|
31
|
+
<details>
|
|
32
|
+
<summary>Configuration</summary>
|
|
33
|
+
|
|
34
|
+
**Best for:** Tweaking Spree's behavior globally without modifying source code.
|
|
35
|
+
|
|
36
|
+
Global application configuration allows you to customize various aspects of Spree:
|
|
37
|
+
|
|
38
|
+
```ruby config/initializers/spree.rb
|
|
39
|
+
Spree.config do |config|
|
|
40
|
+
config.allow_guest_checkout = false
|
|
41
|
+
config.products_per_page = 20
|
|
42
|
+
end
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
Please see [Configuration](/developer/customization/configuration) section for more information.
|
|
46
|
+
|
|
47
|
+
</details>
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
<details>
|
|
51
|
+
<summary>Events and Subscribers</summary>
|
|
52
|
+
|
|
53
|
+
**Best for:** Reacting to model changes, syncing with external services, sending notifications, audit logging.
|
|
54
|
+
|
|
55
|
+
> **INFO:** Events are the **recommended way** to add behavior when something happens in Spree, replacing the need for decorator callbacks.
|
|
56
|
+
|
|
57
|
+
Spree's event system lets you subscribe to events like `order.completed`, `product.updated`, `payment.paid`, etc.:
|
|
58
|
+
|
|
59
|
+
```ruby app/subscribers/my_app/order_completed_subscriber.rb
|
|
60
|
+
module MyApp
|
|
61
|
+
class OrderCompletedSubscriber < Spree::Subscriber
|
|
62
|
+
subscribes_to 'order.completed'
|
|
63
|
+
|
|
64
|
+
def handle(event)
|
|
65
|
+
order = Spree::Order.find_by(id: event.payload['id'])
|
|
66
|
+
return unless order
|
|
67
|
+
|
|
68
|
+
# Sync to external service, send notification, etc.
|
|
69
|
+
ExternalService.notify_order_placed(order)
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
**Key benefits:**
|
|
76
|
+
- Loose coupling - your code doesn't depend on Spree internals
|
|
77
|
+
- Async by default - keeps requests fast
|
|
78
|
+
- Easier testing and upgrades
|
|
79
|
+
|
|
80
|
+
Please see [Events](/developer/core-concepts/events) section for more information.
|
|
81
|
+
|
|
82
|
+
</details>
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
<details>
|
|
86
|
+
<summary>Webhooks</summary>
|
|
87
|
+
|
|
88
|
+
**Best for:** Notifying external services (ERPs, CRMs, fulfillment systems) when events occur.
|
|
89
|
+
|
|
90
|
+
Webhooks send HTTP POST requests to external URLs when Spree events happen:
|
|
91
|
+
|
|
92
|
+
- Order completed → Notify fulfillment system
|
|
93
|
+
- Product updated → Sync with PIM
|
|
94
|
+
- Customer created → Add to CRM
|
|
95
|
+
|
|
96
|
+
Configure webhooks in **Admin > Developers > Webhooks** or via the API.
|
|
97
|
+
|
|
98
|
+
Please see [Webhooks](/developer/core-concepts/webhooks) section for more information.
|
|
99
|
+
|
|
100
|
+
</details>
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
<details>
|
|
104
|
+
<summary>Dependencies</summary>
|
|
105
|
+
|
|
106
|
+
**Best for:** Swapping core services, serializers, and abilities with your own implementations.
|
|
107
|
+
|
|
108
|
+
Spree allows you to replace core classes without modifying them:
|
|
109
|
+
|
|
110
|
+
```ruby config/initializers/spree.rb
|
|
111
|
+
Spree::Dependencies.cart_add_item_service = "MyCartAddItemService"
|
|
112
|
+
Spree::Dependencies.cart_remove_item_service = "MyCartRemoveItemService"
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
This is cleaner than decorating services because you provide a complete replacement rather than patching behavior.
|
|
116
|
+
|
|
117
|
+
Please see [Dependencies](dependencies) section for more information.
|
|
118
|
+
|
|
119
|
+
</details>
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
<details>
|
|
123
|
+
<summary>Admin Extensions</summary>
|
|
124
|
+
|
|
125
|
+
**Best for:** Adding menu items, form sections, dashboard widgets, and other UI elements to the admin panel.
|
|
126
|
+
|
|
127
|
+
Spree provides declarative APIs for extending the admin without decorators or view overrides:
|
|
128
|
+
|
|
129
|
+
**Navigation API** - Add menu items:
|
|
130
|
+
```ruby config/initializers/spree.rb
|
|
131
|
+
Rails.application.config.after_initialize do
|
|
132
|
+
Spree.admin.navigation.sidebar.add :brands,
|
|
133
|
+
label: :brands,
|
|
134
|
+
url: :admin_brands_path,
|
|
135
|
+
icon: 'award',
|
|
136
|
+
position: 35
|
|
137
|
+
end
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
**Partials API** - Add sections to forms:
|
|
141
|
+
```ruby config/initializers/spree.rb
|
|
142
|
+
Spree.admin.partials.product_form << 'spree/admin/products/erp_section'
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
Please see:
|
|
146
|
+
- [Admin Navigation](/developer/admin/navigation) - For adding menu items
|
|
147
|
+
- [Admin Partials](/developer/admin/extending-ui) - For extending UI
|
|
148
|
+
- [Admin Tables](/developer/admin/tables) - For customizing list views
|
|
149
|
+
|
|
150
|
+
</details>
|
|
151
|
+
|
|
152
|
+
|
|
153
|
+
<details>
|
|
154
|
+
<summary>Search and Filtering</summary>
|
|
155
|
+
|
|
156
|
+
**Best for:** Making custom fields searchable/sortable in the admin and API.
|
|
157
|
+
|
|
158
|
+
Instead of decorating models to add `ransackable_attributes`, use the Ransack configuration API:
|
|
159
|
+
|
|
160
|
+
```ruby config/initializers/spree.rb
|
|
161
|
+
Spree.ransack.add_attribute :product, :erp_id
|
|
162
|
+
Spree.ransack.add_association :product, :brand
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
Please see [Search & Filtering](/developer/core-concepts/search-filtering#extending-ransackable-configuration) section for more information.
|
|
166
|
+
|
|
167
|
+
</details>
|
|
168
|
+
|
|
169
|
+
|
|
170
|
+
<details>
|
|
171
|
+
<summary>Authentication</summary>
|
|
172
|
+
|
|
173
|
+
**Best for:** Using your own user model or authentication system.
|
|
174
|
+
|
|
175
|
+
Spree allows you to use your own authentication system instead of the default Devise-based one.
|
|
176
|
+
|
|
177
|
+
You can find more information in the [Authentication](authentication) section.
|
|
178
|
+
|
|
179
|
+
</details>
|
|
180
|
+
|
|
181
|
+
|
|
182
|
+
<details>
|
|
183
|
+
<summary>Checkout flow</summary>
|
|
184
|
+
|
|
185
|
+
**Best for:** Customizing checkout steps and flow.
|
|
186
|
+
|
|
187
|
+
With Spree you can change the checkout flow to fit your business needs - add steps, remove steps, or change the order.
|
|
188
|
+
|
|
189
|
+
Please see [Checkout flow customization section](checkout) for more information.
|
|
190
|
+
|
|
191
|
+
</details>
|
|
192
|
+
|
|
193
|
+
|
|
194
|
+
<details>
|
|
195
|
+
<summary>Decorators</summary>
|
|
196
|
+
|
|
197
|
+
**Best for:** Adding associations, validations, scopes, and methods to Spree models. Use as a last resort.
|
|
198
|
+
|
|
199
|
+
> **WARNING:** Decorators should be used **only when no other option works**. They tightly couple your code to Spree internals and can break during upgrades.
|
|
200
|
+
>
|
|
201
|
+
> **Do NOT use decorators for:**
|
|
202
|
+
> - After-save callbacks → Use [Events](/developer/core-concepts/events) instead
|
|
203
|
+
> - External service sync → Use [Webhooks](/developer/core-concepts/webhooks) instead
|
|
204
|
+
> - Custom service logic → Use [Dependencies](dependencies) instead
|
|
205
|
+
> - Admin UI changes → Use [Admin Extensions](#admin-extensions) instead
|
|
206
|
+
|
|
207
|
+
Decorators are still appropriate for structural changes:
|
|
208
|
+
|
|
209
|
+
```ruby app/models/spree/product_decorator.rb
|
|
210
|
+
module Spree
|
|
211
|
+
module ProductDecorator
|
|
212
|
+
def self.prepended(base)
|
|
213
|
+
base.belongs_to :brand, class_name: 'MyApp::Brand', optional: true
|
|
214
|
+
base.validates :external_id, presence: true
|
|
215
|
+
base.scope :featured, -> { where(featured: true) }
|
|
216
|
+
end
|
|
217
|
+
|
|
218
|
+
def full_title
|
|
219
|
+
"#{brand&.name} #{name}"
|
|
220
|
+
end
|
|
221
|
+
end
|
|
222
|
+
|
|
223
|
+
Product.prepend(ProductDecorator)
|
|
224
|
+
end
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
Please see [Decorators](decorators) section for more information.
|
|
228
|
+
|
|
229
|
+
</details>
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Routes
|
|
3
|
+
description: Learn how to customize the routes in Spree
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
## Default configuration
|
|
7
|
+
|
|
8
|
+
By default Spree is mounted at the root of your domain, this code will be inserted into `config/routes.rb`:
|
|
9
|
+
|
|
10
|
+
```ruby
|
|
11
|
+
mount Spree::Core::Engine, at: '/'
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
This means that Spree will be available at the root of your domain, for example `http://localhost:3000`.
|
|
15
|
+
|
|
16
|
+
## Customizing the mount point
|
|
17
|
+
|
|
18
|
+
You can customize this simply by changing the `:at` specification in `config/routes.rb` to be something else. For example, if you would like Spree to be mounted at `/shop`, you can write this:
|
|
19
|
+
|
|
20
|
+
```ruby
|
|
21
|
+
mount Spree::Core::Engine, at: `/shop`
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
The different parts of Spree (API, Admin) will be mounted there as well, eg. `http://localhost:3000/shop/products`.
|