Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Include Devise routes/controllers/views directly in the project #153

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 46 additions & 25 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
# Solidus Starter Frontend
[![Gem Version](https://badge.fury.io/rb/solidus_starter_frontend.svg)](https://badge.fury.io/rb/solidus_starter_frontend) [![CircleCI](https://circleci.com/gh/nebulab/solidus_starter_frontend.svg?style=shield)](https://circleci.com/gh/nebulab/solidus_starter_frontend)

`solidus_starter_frontend` is a new starter store for [Solidus][solidus]. This
extension aims to deliver a modern, minimal, semantic, and easy to extend
frontend codebase for a more efficient bootstrapping experience.
`solidus_starter_frontend` is a new starter storefront for [Solidus][solidus].

**DISCLAIMER**: some Solidus extensions (the ones that depend on Solidus
Frontend) will not work with our component because they rely on defacing some
views that don't exist here.
This project aims to deliver a modern, minimal, semantic, and easy to extend
codebase for a more efficient bootstrapping experience and easy maintenance.

It includes authentication using Devise.

**DISCLAIMER**: some Solidus extensions (the ones that depend on Solidus
Frontend) will not work with this project because they rely on defacing some
views items that don't exist here.

## Objectives
We aim to deliver:
Expand All @@ -18,59 +21,77 @@ We aim to deliver:
in vanilla JavaScript

All of this while keeping and improving on the functionality of the current
[Solidus][solidus] starter store.
[Solidus][solidus] frontend subcomponent.

## Installation

By default, the `solidus` gem also includes the standard frontend via
the `solidus_frontend` gem. To make this extension work, you need to
exclude it and manually include all the other Solidus components.
exclude it and manually include the rest of the Solidus components.

#### For a new store

Just run:

```bash
rails new store --skip-javascript
cd store
bundle add solidus_core solidus_backend solidus_api solidus_sample
bin/rails generate solidus:install
```

And type `y` when propted if you want to install Solidus Auth Devise

#### For existing stores

In your `Gemfile` replace:

You need to replace:
```ruby
gem 'solidus'
```

with:

```ruby
gem 'solidus_core'
gem 'solidus_api'
gem 'solidus_backend'
gem 'solidus_sample'
```

If Solidus was already installed with _solidus_frontend_ you will have to
replace all the references of the string `Spree::Frontend::Config` in your
And replace all the references of the string `Spree::Frontend::Config` in your
project with `SolidusStarterFrontend::Config`.

You have the following 2 install methods available.
Now You have the following 2 install methods available.

### (1) Copy the starter frontend files in your project
With this method, this project's views, assets, routes and controllers will be
copied over your project and you can change easily anything that we created; this
gives you a lot of freedom of customization.

### (1) Copy our components files in your project
With this method, our views, assets, and controllers will be copied over your
project and you can change easily anything that we created; this gives you a lot
of freedom of customization. On the other hand, you won't be able to auto-update
the storefront code with the next versions released since it will not be present
in your Gemfile.
On the other hand, you won't be able to auto-update the storefront code with the
next versions released since it will not be present in your Gemfile.

Installation steps:

```shell
$ cd your/project/
$ gem install solidus_starter_frontend
$ solidus_starter_frontend
```

The last command will copy all the necessary files.
These commands will install the gem globally and copy all the necessary files into your application.

### (2) Add our component as gem in your project
### (2) Add the starter frontend as gem in your project
With this method, you simply add our gem to your application and it behaves like
a Rails engine. In this case, our files remain in the gem and you will need to
override the views that you want to customize or if you need different logics to
monkey-patch the classes that we previously defined.

Installation steps:
- add to your _Gemfile_: `gem 'solidus_starter_frontend'`

**IMPORTANT**: put this line before `gem 'solidus_auth_devise'` (if you are
using this gem) because our component has conditional references to it.
```shell
bundle add solidus_starter_frontend
```

## Development
For information about contributing to this project please refer to this
Expand All @@ -79,7 +100,7 @@ For information about contributing to this project please refer to this
## About
[![Nebulab][nebulab-logo]][nebulab]

`solidus_starter_frontend` is funded and maintained by the [Nebulab][nebulab]
`solidus_starter_frontend` is funded and maintained by the [Nebulab][nebulab]
team.

We firmly believe in the power of open-source. [Contact us][contact-us] if you
Expand Down
62 changes: 61 additions & 1 deletion app/controllers/spree/checkout_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,14 @@ class CheckoutController < Spree::StoreController

before_action :setup_for_current_state, only: [:edit, :update]

before_action :check_registration, except: [:registration, :update_registration]
before_action :check_authorization

# This action builds some associations on the order, ex. addresses, which we
# don't to build or save here.
# TODO: this doesn't seem needed, see setup_for_current_state definition. Investigate if we can remove it.
skip_before_action :setup_for_current_state, only: [:registration, :update_registration]

helper 'spree/orders'

rescue_from Spree::Core::GatewayError, with: :rescue_from_spree_gateway_error
Expand Down Expand Up @@ -47,6 +55,20 @@ def update
end
end

def registration
@user = Spree::User.new
end

def update_registration
if params[:order][:email] =~ Devise.email_regexp && current_order.update(email: params[:order][:email])
redirect_to spree.checkout_path
else
flash[:registration_error] = t(:email_is_invalid, scope: [:errors, :messages])
@user = Spree::User.new
render 'registration'
end
end

private

def update_order
Expand Down Expand Up @@ -175,7 +197,9 @@ def ensure_sufficient_stock_lines

# Provides a route to redirect after order completion
def completion_route
spree.order_path(@order)
return spree.order_path(@order) if spree_current_user

spree.token_order_path(@order, @order.guest_token)
end

def setup_for_current_state
Expand Down Expand Up @@ -240,5 +264,41 @@ def insufficient_stock_error
end
end
end

def order_params
params.
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Layout/DotPosition: Place the . on the next line, together with the method name.

fetch(:order, {}).
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Layout/DotPosition: Place the . on the next line, together with the method name.

permit(:email)
end

def skip_state_validation?
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lint/DuplicateMethods: Method Spree::CheckoutController#skip_state_validation? is defined at both app/controllers/spree/checkout_controller.rb:160 and app/controllers/spree/checkout_controller.rb:274.

%w(registration update_registration).include?(params[:action])
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Style/PercentLiteralDelimiters: %w-literals should be delimited by [ and ].

end

def check_authorization
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lint/DuplicateMethods: Method Spree::CheckoutController#check_authorization is defined at both app/controllers/spree/checkout_controller.rb:247 and app/controllers/spree/checkout_controller.rb:278.

authorize!(:edit, current_order, cookies.signed[:guest_token])
end

# Introduces a registration step whenever the +registration_step+ preference is true.
def check_registration
return unless registration_required?

store_location
redirect_to spree.checkout_registration_path
end

def registration_required?
Spree::Auth::Config[:registration_step] &&
!already_registered?
end

def already_registered?
spree_current_user || guest_authenticated?
end

def guest_authenticated?
current_order&.email.present? &&
Spree::Config[:allow_guest_checkout]
end
end
end
18 changes: 18 additions & 0 deletions app/controllers/spree/user_confirmations_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# frozen_string_literal: true

class Spree::UserConfirmationsController < Devise::ConfirmationsController
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Style/ClassAndModuleChildren: Use nested module/class definitions instead of compact style.

helper 'spree/base', 'spree/store'

include Spree::Core::ControllerHelpers::Auth
include Spree::Core::ControllerHelpers::Common
include Spree::Core::ControllerHelpers::Order
include Spree::Core::ControllerHelpers::Store

include SolidusStarterFrontend::Taxonomies

protected

def after_confirmation_path_for(resource_name, resource)
signed_in?(resource_name) ? spree.signed_in_root_path(resource) : spree.login_path
end
end
55 changes: 55 additions & 0 deletions app/controllers/spree/user_passwords_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
# frozen_string_literal: true

class Spree::UserPasswordsController < Devise::PasswordsController
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Style/ClassAndModuleChildren: Use nested module/class definitions instead of compact style.

helper 'spree/base', 'spree/store'

include Spree::Core::ControllerHelpers::Auth
include Spree::Core::ControllerHelpers::Common
include Spree::Core::ControllerHelpers::Order
include Spree::Core::ControllerHelpers::Store

include SolidusStarterFrontend::Taxonomies

# Overridden due to bug in Devise.
# respond_with resource, location: new_session_path(resource_name)
# is generating bad url /session/new.user
#
# overridden to:
# respond_with resource, location: spree.login_path
#
def create
self.resource = resource_class.send_reset_password_instructions(params[resource_name])

set_flash_message(:notice, :send_instructions) if is_navigational_format?

if resource.errors.empty?
respond_with resource, location: spree.login_path
else
respond_with_navigational(resource) { render :new }
end
end

# Devise::PasswordsController allows for blank passwords.
# Silly Devise::PasswordsController!
# Fixes spree/spree#2190.
def update
if params[:spree_user][:password].blank?
self.resource = resource_class.new
resource.reset_password_token = params[:spree_user][:reset_password_token]
set_flash_message(:error, :cannot_be_blank)
render :edit
else
super
end
end

protected

def translation_scope
'devise.user_passwords'
end

def new_session_path(resource_name)
spree.send("new_#{resource_name}_session_path")
end
end
46 changes: 46 additions & 0 deletions app/controllers/spree/user_registrations_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
# frozen_string_literal: true

class Spree::UserRegistrationsController < Devise::RegistrationsController
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Style/ClassAndModuleChildren: Use nested module/class definitions instead of compact style.

helper 'spree/base', 'spree/store'

include Spree::Core::ControllerHelpers::Auth
include Spree::Core::ControllerHelpers::Common
include Spree::Core::ControllerHelpers::Order
include Spree::Core::ControllerHelpers::Store

include SolidusStarterFrontend::Taxonomies

before_action :check_permissions, only: [:edit, :update]
skip_before_action :require_no_authentication

def create
build_resource(spree_user_params)
if resource.save
set_flash_message(:notice, :signed_up)
sign_in(:spree_user, resource)
session[:spree_user_signup] = true
respond_with resource, location: after_sign_up_path_for(resource)
else
clean_up_passwords(resource)
respond_with(resource) do |format|
format.html { render :new }
end
end
end

protected

def translation_scope
'devise.user_registrations'
end

def check_permissions
authorize!(:create, resource)
end

private

def spree_user_params
params.require(:spree_user).permit(Spree::PermittedAttributes.user_attributes | [:email])
end
end
Loading