Skip to content

Commit

Permalink
Fix custom authentication generators and update docs
Browse files Browse the repository at this point in the history
  • Loading branch information
damianlegawiec committed May 22, 2024
1 parent 8ae3d7f commit 94dcf0a
Show file tree
Hide file tree
Showing 6 changed files with 89 additions and 72 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
module Spree
class CustomAuthenticationGenerator < Rails::Generators::Base
desc 'Set up a Spree installation with a custom authentication helpers'

def self.source_paths
paths = superclass.source_paths
paths << File.expand_path('templates', __dir__)
paths.flatten
end

def generate
template 'authentication_helpers.rb.tt', 'lib/spree/authentication_helpers.rb'

file_action = File.exist?('config/initializers/spree.rb') ? :append_file : :create_file
send(file_action, 'config/initializers/spree.rb') do
%Q{
Rails.application.config.to_prepare do
require_dependency 'spree/authentication_helpers'
end\n}
end
end
end
end
Original file line number Diff line number Diff line change
@@ -1,14 +1,4 @@
module Spree
module CurrentUserHelpers
def self.included(receiver)
receiver.send :helper_method, :spree_current_user
end

def spree_current_user
current_user
end
end

module AuthenticationHelpers
def self.included(receiver)
receiver.send :helper_method, :spree_login_path
Expand All @@ -30,7 +20,4 @@ module Spree
end
end

ApplicationController.include Spree::AuthenticationHelpers
ApplicationController.include Spree::CurrentUserHelpers

Spree::Api::BaseController.include Spree::CurrentUserHelpers
ApplicationController.include Spree::AuthenticationHelpers if defined?(ApplicationController)
11 changes: 3 additions & 8 deletions core/lib/generators/spree/custom_user/custom_user_generator.rb
Original file line number Diff line number Diff line change
Expand Up @@ -20,24 +20,19 @@ def check_for_constant

def generate
migration_template 'migration.rb.tt', 'db/migrate/add_spree_fields_to_custom_user_table.rb'
template 'authentication_helpers.rb.tt', 'lib/spree/authentication_helpers.rb'
template 'current_user_helpers.rb.tt', 'lib/spree/current_user_helpers.rb'

file_action = File.exist?('config/initializers/spree.rb') ? :append_file : :create_file
send(file_action, 'config/initializers/spree.rb') do
%Q{
Rails.application.config.to_prepare do
require_dependency 'spree/authentication_helpers'
require_dependency 'spree/current_user_helpers'
end\n}
end
end

def self.next_migration_number(dirname)
if ApplicationRecord.timestamped_migrations
sleep 1 # make sure to get a different migration every time
Time.new.utc.strftime('%Y%m%d%H%M%S')
else
format('%.3d', (current_migration_number(dirname) + 1))
end
format('%.3d', (current_migration_number(dirname) + 1))
end

def klass
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
module Spree
module CurrentUserHelpers
def self.included(receiver)
receiver.send :helper_method, :spree_current_user
end

def spree_current_user
current_user
end
end
end


ApplicationController.include Spree::CurrentUserHelpers if defined?(ApplicationController)
Spree::Api::BaseController.include Spree::CurrentUserHelpers if defined?(Spree::Api::BaseController)
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
class AddSpreeFieldsToCustomUserTable < ActiveRecord::Migration[4.2]
def up
add_column <%= table_name.inspect %>, :spree_api_key, :string, limit: 48
add_column <%= table_name.inspect %>, :ship_address_id, :integer
add_column <%= table_name.inspect %>, :bill_address_id, :integer
add_column <%= table_name.inspect %>, :ship_address_id, :bigint
add_column <%= table_name.inspect %>, :bill_address_id, :bigint
end
end
93 changes: 45 additions & 48 deletions docs/developer/customization/authentication.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@ To use your own authentication system with Spree, please follow these steps:
```
</Accordion>

<Accordion title="2. Generate Spree Authentication Helpers">
Next, you need to run the custom user generator for Spree which will create two files. The first is a migration that will add the necessary Spree fields to your users table, and the second is an extension that lives at `lib/spree/authentication_helpers.rb` to the `Spree::Core::AuthenticationHelpers` module inside of Spree.
<Accordion title="2. Update User model">
Next, you need to run the custom user generator for Spree which will create a migration that will add the necessary Spree fields to your users table.

Run this generator with this command:

Expand All @@ -43,10 +43,50 @@ To use your own authentication system with Spree, please follow these steps:
bin/rails db:migrate
```

Next you will need to define some methods to tell Spree where to find your application's authentication routes.
This generator will also create a file at `lib/spree/current_user_helpers.rb` which will be automatically included in your application's controllers allowing you to override the `spree_current_user` method to return the current user of the request.
</Accordion>
<Accordion title="3. Customize Spree Authentication Helpers">
There are some authentication helpers of Spree's that you will need to possibly override. The file at `lib/spree/authentication_helpers.rb` contains the following code to help you do that:
<Accordion title="3. Include User concerns in your User model">
In your User Model please include the following lines:

```ruby
include Spree::UserMethods
include Spree::UserAddress
include Spree::UserPaymentSource
```

The first of these methods are the ones added for the `has_and_belongs_to_many` association called `spree_roles`. This association will retrieve all the roles that a user has for Spree.

The second of these is the `spree_orders` association. This will return all orders associated with the user in Spree. There's also a `last_incomplete_spree_order` method which will return the last incomplete spree order for the user. This is used internal to Spree to persist order data across a user's login sessions.

The third and fourth associations are for address information for a user. When a user places an order, the address information for that order will be linked to that user so that it is available for subsequent orders.

The next method is one called `has_spree_role?` which can be used to check if a user has a specific role. This method is used internally to Spree to check if the user is authorized to perform specific actions, such as accessing the admin section. Admin users of your system should be assigned the Spree admin role, like this:

```ruby
user = User.find_by(email: 'master@example.com')
user.spree_roles << Spree::Role.where(name: 'admin').first_or_create
```

To test that this has worked, use the `has_spree_role?` method, like this:

```ruby
user.has_spree_role?('admin')
```

If this returns `true`, then the user has admin permissions within Spree.
</Accordion>
<Accordion title="4. Customize Spree Authentication Helpers (Optional)">
<Note>
This step is required if you're using `spree_backend` and/or `spree_frontend` gems.
</Note>

Run a generator to create a file at `lib/spree/authentication_helpers.rb` which will contain the following code to help you do that:

```bash
bin/rails g spree:custom_authentication
```

This will create a file at `lib/spree/authentication_helpers.rb` which will contain the following code to help you do that:

```ruby
module Spree
Expand Down Expand Up @@ -77,19 +117,6 @@ To use your own authentication system with Spree, please follow these steps:
end
```

In your `ApplicationController` add these lines:

```ruby
include Spree::AuthenticationHelpers
include Spree::Core::ControllerHelpers::Auth
include Spree::Core::ControllerHelpers::Order
include Spree::Core::ControllerHelpers::Store
include Spree::Core::ControllerHelpers::Currency
include Spree::Core::ControllerHelpers::Locale

helper 'spree/base', 'spree/locale', 'spree/currency', 'spree/store'
```

Each of the methods defined in this module return values that are the most common in Rails applications today, but you may need to customize them. In order, they are:

* `spree_current_user` Used to tell Spree what the current user of a request is.
Expand All @@ -116,36 +143,6 @@ To use your own authentication system with Spree, please follow these steps:

Any modifications made to `lib/spree/authentication_helpers.rb` while the server is running will require a restart, as with any other modification to other files in `lib`.
</Accordion>
<Accordion title="4. Include Spree::UserMethods in your User model">
In your User Model you have to add:

```ruby
include Spree::UserMethods
include Spree::UserAddress
include Spree::UserPaymentSource
```

The first of these methods are the ones added for the `has_and_belongs_to_many` association called `spree_roles`. This association will retrieve all the roles that a user has for Spree.

The second of these is the `spree_orders` association. This will return all orders associated with the user in Spree. There's also a `last_incomplete_spree_order` method which will return the last incomplete spree order for the user. This is used internal to Spree to persist order data across a user's login sessions.

The third and fourth associations are for address information for a user. When a user places an order, the address information for that order will be linked to that user so that it is available for subsequent orders.

The next method is one called `has_spree_role?` which can be used to check if a user has a specific role. This method is used internally to Spree to check if the user is authorized to perform specific actions, such as accessing the admin section. Admin users of your system should be assigned the Spree admin role, like this:

```ruby
user = User.find_by(email: 'master@example.com')
user.spree_roles << Spree::Role.where(name: 'admin').first_or_create
```

To test that this has worked, use the `has_spree_role?` method, like this:

```ruby
user.has_spree_role?('admin')
```

If this returns `true`, then the user has admin permissions within Spree.
</Accordion>
<Accordion title="5. Remove Auth Devise gem">
The `spree_auth_devise` gem is not needed when using an existing application authentication unless the goal is to have two separate authentication methods.

Expand Down

0 comments on commit 94dcf0a

Please sign in to comment.