Skip to content

Commit

Permalink
Merge pull request #5214 from solidusio/elia/admin/auth-config
Browse files Browse the repository at this point in the history
[Admin] Add an auth configuration that can be attached to the existing one
  • Loading branch information
elia authored Jul 31, 2023
2 parents 00b7aab + 7cce8ce commit 4e8c91a
Show file tree
Hide file tree
Showing 8 changed files with 158 additions and 2 deletions.
35 changes: 35 additions & 0 deletions admin/app/controllers/solidus_admin/auth.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# frozen_string_literal: true

module SolidusAdmin::Auth
extend ActiveSupport::Concern

included do
if ::SolidusAdmin::Config.authentication_adapter
include ::SolidusAdmin::Config.authentication_adapter.constantize
end

before_action :authenticate_solidus_admin_user!

helper_method :current_solidus_admin_user
helper_method :solidus_admin_logout_path
helper_method :solidus_admin_logout_method
end

private

def authenticate_solidus_admin_user!
send SolidusAdmin::Config.authentication_method if SolidusAdmin::Config.authentication_method
end

def current_solidus_admin_user
send SolidusAdmin::Config.current_user_method if SolidusAdmin::Config.current_user_method
end

def solidus_admin_logout_path
send SolidusAdmin::Config.logout_link_path
end

def solidus_admin_logout_method
SolidusAdmin::Config.logout_link_method
end
end
37 changes: 37 additions & 0 deletions admin/app/controllers/solidus_admin/auth_adapters/backend.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# frozen_string_literal: true

module SolidusAdmin::AuthAdapters::Backend
extend ActiveSupport::Concern

included do
delegate :admin_logout_path, to: :spree
helper_method :admin_logout_path
end

private

def authenticate_solidus_backend_user!
if respond_to?(:model_class, true) && model_class
record = model_class
else
record = controller_name.to_sym
end
authorize! :admin, record
authorize! action_name.to_sym, record
rescue CanCan::AccessDenied
instance_exec(&Spree::Admin::BaseController.unauthorized_redirect)
end

# Needs to be overriden so that we use Spree's Ability rather than anyone else's.
def current_ability
@current_ability ||= Spree::Ability.new(spree_current_user)
end

def store_location
Spree::UserLastUrlStorer.new(self).store_location
end

def spree_current_user
defined?(super) ? super : nil
end
end
6 changes: 5 additions & 1 deletion admin/app/controllers/solidus_admin/base_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,11 @@
require 'geared_pagination'

module SolidusAdmin
class BaseController < Spree::BaseController
class BaseController < ApplicationController
include ActiveStorage::SetCurrent
include ::SolidusAdmin::Auth
include Spree::Core::ControllerHelpers::Store

include ::GearedPagination::Controller

layout 'solidus_admin/application'
Expand Down
3 changes: 2 additions & 1 deletion admin/app/views/solidus_admin/accounts/show.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@
class="text-4xl"
><a href="#" data-action="hello#greet">Account</a></h1>

<h2 class="text-3xl underline">Your account info</h1>
<p>Logged in as <%= current_solidus_admin_user.email %></p>
<p><%= button_to "Log out", solidus_admin_logout_path, method: solidus_admin_logout_method, class: 'underline' %></p>
17 changes: 17 additions & 0 deletions admin/lib/solidus_admin/configuration.rb
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,23 @@ def main_nav
yield(_1) if block_given?
end
end

# The method used to authenticate the user in the admin interface, it's expected to redirect the user to the login method
# in case the authentication fails.
preference :authentication_method, :string, default: :authenticate_solidus_backend_user!

# The method used to retrieve the current user in the admin interface.
preference :current_user_method, :string, default: :spree_current_user

# The path used to logout the user in the admin interface.
preference :logout_link_path, :string, default: :admin_logout_path

# The HTTP method used to logout the user in the admin interface.
preference :logout_link_method, :string, default: :delete

# A module that will be included in the BaseController to add authentication support
# methods, can be `nil` if no module is needed.
preference :authentication_adapter, :string, default: 'SolidusAdmin::AuthAdapters::Backend'
end
end

Expand Down
35 changes: 35 additions & 0 deletions admin/spec/controllers/solidus_admin/base_controller_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# frozen_string_literal: true

require "spec_helper"

describe SolidusAdmin::BaseController, type: :controller do
controller(SolidusAdmin::BaseController) do
def index
authorize! :update, Spree::Order
render plain: 'test'
end
end

context "unauthorized request" do
before do
allow_any_instance_of(SolidusAdmin::BaseController).to receive(:spree_current_user).and_return(nil)
end

it "redirects to unauthorized" do
get :index
expect(response).to redirect_to '/unauthorized'
end
end

context "successful request" do
before do
user = create(:admin_user, email: '[email protected]')
allow_any_instance_of(SolidusAdmin::BaseController).to receive(:spree_current_user).and_return(user)
end

it "returns a 200 response" do
get :index
expect(response.code).to eq "200"
end
end
end
22 changes: 22 additions & 0 deletions admin/spec/features/accounts_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# frozen_string_literal: true

require 'spec_helper'

describe "Accounts", type: :feature do
let(:user) { create(:admin_user, email: '[email protected]') }

before do
allow_any_instance_of(SolidusAdmin::BaseController).to receive(:spree_current_user).and_return(user)
end

it "shows account info" do
without_partial_double_verification do
allow(Spree::Core::Engine.routes.url_helpers).to receive(:admin_logout_path).and_return('/admin/logout')
end

visit "/admin/account"

expect(page).to have_content("Logged in as #{user.email}")
expect(page).to have_content("Log out")
end
end
5 changes: 5 additions & 0 deletions admin/spec/features/products_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,11 @@
require 'spec_helper'

describe "Products", type: :feature do
before do
user = create(:admin_user, email: '[email protected]')
allow_any_instance_of(SolidusAdmin::BaseController).to receive(:spree_current_user).and_return(user)
end

it "lists products", :js do
create(:product, name: "Just a product", price: 19.99)

Expand Down

0 comments on commit 4e8c91a

Please sign in to comment.