├── .rspec ├── .rubocop.yml ├── lib ├── solidus_user_roles.rb ├── solidus_user_roles │ ├── factories.rb │ └── engine.rb ├── tasks │ └── load_seeds.rake └── generators │ └── solidus_user_roles │ └── install │ └── install_generator.rb ├── config ├── routes.rb └── locales │ └── en.yml ├── app ├── controllers │ └── spree │ │ └── admin │ │ └── roles_controller.rb ├── models │ └── spree │ │ ├── role_permission.rb │ │ ├── permission_set.rb │ │ └── permission_sets │ │ └── role_management.rb ├── assets │ ├── javascripts │ │ └── spree │ │ │ ├── backend │ │ │ └── solidus_user_roles.js │ │ │ └── frontend │ │ │ └── solidus_user_roles.js │ └── stylesheets │ │ └── spree │ │ ├── backend │ │ └── solidus_user_roles.css │ │ └── frontend │ │ └── solidus_user_roles.css ├── overrides │ └── user_sub_menu.rb ├── views │ └── spree │ │ └── admin │ │ └── roles │ │ ├── edit.html.erb │ │ ├── new.html.erb │ │ ├── _form.html.erb │ │ └── index.html.erb └── decorators │ └── models │ └── solidus_user_roles │ └── spree │ └── role_decorator.rb ├── bin ├── setup ├── rails └── console ├── db ├── seeds.rb └── migrate │ ├── 20160406142441_create_spree_permission_sets.rb │ └── 20160406142933_create_spree_roles_permissions.rb ├── Rakefile ├── spec ├── support │ ├── factories.rb │ ├── shoulda.rb │ └── factories │ │ └── factories.rb ├── models │ └── spree │ │ ├── role_permission_spec.rb │ │ ├── permission_set_spec.rb │ │ └── role_spec.rb ├── spec_helper.rb └── controllers │ └── spree │ └── admin │ └── roles_controller_spec.rb ├── .gitignore ├── Gemfile ├── solidus_user_roles.gemspec ├── .circleci └── config.yml ├── LICENSE └── README.md /.rspec: -------------------------------------------------------------------------------- 1 | --color -------------------------------------------------------------------------------- /.rubocop.yml: -------------------------------------------------------------------------------- 1 | require: 2 | - solidus_dev_support/rubocop 3 | -------------------------------------------------------------------------------- /lib/solidus_user_roles.rb: -------------------------------------------------------------------------------- 1 | require 'solidus_core' 2 | require 'solidus_support' 3 | require 'solidus_user_roles/engine' 4 | -------------------------------------------------------------------------------- /config/routes.rb: -------------------------------------------------------------------------------- 1 | Spree::Core::Engine.routes.draw do 2 | namespace :admin do 3 | resources :roles 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /app/controllers/spree/admin/roles_controller.rb: -------------------------------------------------------------------------------- 1 | module Spree 2 | module Admin 3 | class RolesController < ResourceController 4 | end 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /app/models/spree/role_permission.rb: -------------------------------------------------------------------------------- 1 | module Spree 2 | class RolePermission < Spree::Base 3 | belongs_to :role 4 | belongs_to :permission_set 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /bin/setup: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -euo pipefail 3 | IFS=$'\n\t' 4 | set -vx 5 | 6 | gem install bundler --conservative 7 | bundle update 8 | bundle exec rake extension:test_app 9 | -------------------------------------------------------------------------------- /db/seeds.rb: -------------------------------------------------------------------------------- 1 | 2 | Spree::PermissionSets::Base.subclasses.each do |permission| 3 | Spree::PermissionSet.create(name: permission.to_s.split('PermissionSets::').last, set: permission.to_s) 4 | end 5 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | 2 | # frozen_string_literal: true 3 | 4 | require 'solidus_dev_support/rake_tasks' 5 | SolidusDevSupport::RakeTasks.install 6 | 7 | task default: %w[extension:test_app extension:specs] 8 | -------------------------------------------------------------------------------- /spec/support/factories.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require "factory_bot" 4 | 5 | Dir["#{File.dirname(__FILE__)}/factories/**"].each do |f| 6 | require File.expand_path(f) 7 | end 8 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | \#* 2 | *~ 3 | .#* 4 | .DS_Store 5 | .idea 6 | .project 7 | .sass-cache 8 | coverage 9 | Gemfile.lock 10 | tmp 11 | nbproject 12 | pkg 13 | *.swp 14 | spec/dummy 15 | spec/examples.txt 16 | -------------------------------------------------------------------------------- /app/assets/javascripts/spree/backend/solidus_user_roles.js: -------------------------------------------------------------------------------- 1 | // Placeholder manifest file. 2 | // the installer will append this file to the app vendored assets here: vendor/assets/javascripts/spree/backend/all.js' -------------------------------------------------------------------------------- /app/assets/javascripts/spree/frontend/solidus_user_roles.js: -------------------------------------------------------------------------------- 1 | // Placeholder manifest file. 2 | // the installer will append this file to the app vendored assets here: vendor/assets/javascripts/spree/frontend/all.js' -------------------------------------------------------------------------------- /spec/models/spree/role_permission_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe Spree::RolePermission, type: :model do 4 | it { should belong_to :role } 5 | it { should belong_to :permission_set } 6 | end 7 | -------------------------------------------------------------------------------- /spec/support/shoulda.rb: -------------------------------------------------------------------------------- 1 | require 'shoulda/matchers' 2 | 3 | Shoulda::Matchers.configure do |config| 4 | config.integrate do |with| 5 | with.test_framework :rspec 6 | with.library :rails 7 | end 8 | end 9 | -------------------------------------------------------------------------------- /app/assets/stylesheets/spree/backend/solidus_user_roles.css: -------------------------------------------------------------------------------- 1 | /* 2 | Placeholder manifest file. 3 | the installer will append this file to the app vendored assets here: 'vendor/assets/stylesheets/spree/backend/all.css' 4 | */ 5 | -------------------------------------------------------------------------------- /app/assets/stylesheets/spree/frontend/solidus_user_roles.css: -------------------------------------------------------------------------------- 1 | /* 2 | Placeholder manifest file. 3 | the installer will append this file to the app vendored assets here: 'vendor/assets/stylesheets/spree/frontend/all.css' 4 | */ 5 | -------------------------------------------------------------------------------- /spec/support/factories/factories.rb: -------------------------------------------------------------------------------- 1 | FactoryBot.define do 2 | factory :permission_set, class: Spree::PermissionSet do 3 | name { 'ProductManagement' } 4 | set { 'Spree::PermissionSets::ProductManagement' } 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /spec/models/spree/permission_set_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe Spree::PermissionSet, type: :model do 4 | it { should have_many :role_permissions } 5 | it { should have_many(:roles).through(:role_permissions) } 6 | it { should validate_presence_of :name } 7 | end 8 | -------------------------------------------------------------------------------- /db/migrate/20160406142441_create_spree_permission_sets.rb: -------------------------------------------------------------------------------- 1 | class CreateSpreePermissionSets < SolidusSupport::Migration[4.2] 2 | def change 3 | create_table :spree_permission_sets do |t| 4 | t.string :name 5 | t.string :set 6 | t.timestamps null: false 7 | end 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /db/migrate/20160406142933_create_spree_roles_permissions.rb: -------------------------------------------------------------------------------- 1 | class CreateSpreeRolesPermissions < SolidusSupport::Migration[4.2] 2 | def change 3 | create_table :spree_role_permissions do |t| 4 | t.references :role 5 | t.references :permission_set 6 | t.timestamps null: false 7 | end 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /lib/solidus_user_roles/factories.rb: -------------------------------------------------------------------------------- 1 | FactoryBot.define do 2 | # Define your Spree extensions Factories within this file to enable applications, and other extensions to use and override them. 3 | # 4 | # Example adding this to your spec_helper will load these Factories for use: 5 | # require 'solidus_user_roles/factories' 6 | end 7 | -------------------------------------------------------------------------------- /lib/tasks/load_seeds.rake: -------------------------------------------------------------------------------- 1 | namespace :solidus_user_roles do 2 | desc "Loads seed data." 3 | task load_seeds: :environment do 4 | Spree::PermissionSets::Base.subclasses.each do |permission| 5 | Spree::PermissionSet.find_or_create_by(name: permission.to_s.split('PermissionSets::').last, set: permission.to_s) 6 | end 7 | end 8 | end 9 | -------------------------------------------------------------------------------- /app/overrides/user_sub_menu.rb: -------------------------------------------------------------------------------- 1 | Deface::Override.new( 2 | virtual_path: 'spree/admin/shared/_menu', 3 | name: 'add_user_roles_menu_links', 4 | insert_bottom: "[data-hook='admin_tabs']" 5 | ) do 6 | <<-HTML 7 | <% if can? :admin, Spree::Role %> 8 | <%= tab(:roles, icon: 'users') %> 9 | <% end %> 10 | HTML 11 | end 12 | -------------------------------------------------------------------------------- /bin/rails: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | # frozen_string_literal: true 4 | 5 | app_root = 'spec/dummy' 6 | 7 | unless File.exist? "#{app_root}/bin/rails" 8 | system "bin/rake", app_root or begin # rubocop:disable Style/AndOr 9 | warn "Automatic creation of the dummy app failed" 10 | exit 1 11 | end 12 | end 13 | 14 | Dir.chdir app_root 15 | exec 'bin/rails', *ARGV 16 | -------------------------------------------------------------------------------- /app/models/spree/permission_set.rb: -------------------------------------------------------------------------------- 1 | module Spree 2 | class PermissionSet < Spree::Base 3 | has_many :role_permissions 4 | has_many :roles, through: :role_permissions 5 | validates :name, :set, presence: true 6 | scope :display_permissions, -> { where('name LIKE ?', '%Display') } 7 | scope :management_permissions, -> { where('name LIKE ?', '%Management') } 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /bin/console: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | # frozen_string_literal: true 4 | 5 | require "bundler/setup" 6 | require "solidus_editor" 7 | 8 | # You can add fixtures and/or initialization code here to make experimenting 9 | # with your gem easier. You can also use a different console, if you like. 10 | $LOAD_PATH.unshift(*Dir["#{__dir__}/../app/*"]) 11 | 12 | # (If you use this, don't forget to add pry to your Gemfile!) 13 | # require "pry" 14 | # Pry.start 15 | 16 | require "irb" 17 | IRB.start(__FILE__) 18 | -------------------------------------------------------------------------------- /config/locales/en.yml: -------------------------------------------------------------------------------- 1 | # Sample localization file for English. Add more files in this directory for other locales. 2 | # See https://github.com/svenfuchs/rails-i18n/tree/master/rails%2Flocale for starting points. 3 | 4 | en: 5 | hello: "Hello world" 6 | spree: 7 | new_user_role: New User Role 8 | back_to_roles_list: Back to Roles List 9 | permissions: Permissions 10 | user_roles: User Roles 11 | editing_user_role: Editing User Role 12 | display_permissions: Display Permissions 13 | management_permissions: Management Permissions 14 | admin: 15 | tab: 16 | roles: Roles 17 | -------------------------------------------------------------------------------- /app/views/spree/admin/roles/edit.html.erb: -------------------------------------------------------------------------------- 1 | <% content_for :page_title do %> 2 | <%= Spree.t(:editing_user_role) %> 3 | <% end %> 4 | 5 | <% content_for :page_actions do %> 6 |
  • 7 | <%= button_link_to Spree.t(:back_to_roles_list), spree.admin_roles_path, :icon => 'arrow-left' %> 8 |
  • 9 | <% end %> 10 | 11 | <%= render :partial => 'spree/shared/error_messages', :locals => { :target => @role } %> 12 | 13 | <%= form_for [:admin, @role] do |f| %> 14 |
    15 | <%= render :partial => 'form', :locals => { :f => f } %> 16 |
    17 | <%= render :partial => 'spree/admin/shared/edit_resource_links' %> 18 |
    19 | <% end %> 20 | -------------------------------------------------------------------------------- /app/views/spree/admin/roles/new.html.erb: -------------------------------------------------------------------------------- 1 | <% content_for :page_title do %> 2 | <%= Spree.t(:new_user_role) %> 3 | <% end %> 4 | 5 | <% content_for :page_actions do %> 6 |
  • 7 | <%= button_link_to Spree.t(:back_to_roles_list), spree.admin_roles_path, :icon => 'arrow-left' %> 8 |
  • 9 | <% end %> 10 | 11 | <%= render :partial => 'spree/shared/error_messages', :locals => { :target => @role } %> 12 | 13 | <%= form_for [:admin, @role] do |f| %> 14 |
    15 | 16 | <%= render :partial => 'form', :locals => { :f => f } %> 17 | 18 |
    19 | 20 | <%= render :partial => 'spree/admin/shared/new_resource_links' %> 21 | 22 |
    23 | <% end %> 24 | -------------------------------------------------------------------------------- /spec/spec_helper.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Configure Rails Environment 4 | ENV['RAILS_ENV'] = 'test' 5 | 6 | # Run Coverage report 7 | require 'solidus_dev_support/rspec/coverage' 8 | 9 | require File.expand_path('dummy/config/environment.rb', __dir__) 10 | 11 | # Requires factories and other useful helpers defined in spree_core. 12 | require 'solidus_dev_support/rspec/feature_helper' 13 | 14 | # Requires supporting ruby files with custom matchers and macros, etc, 15 | # in spec/support/ and its subdirectories. 16 | Dir[File.join(File.dirname(__FILE__), 'support/**/*.rb')].each { |f| require f } 17 | 18 | RSpec.configure do |config| 19 | config.infer_spec_type_from_file_location! 20 | config.use_transactional_fixtures = false 21 | end 22 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | source 'https://rubygems.org' 4 | git_source(:github) { |repo| "https://github.com/#{repo}.git" } 5 | 6 | branch = ENV.fetch('SOLIDUS_BRANCH', 'master') 7 | gem 'solidus', github: 'solidusio/solidus', branch: branch 8 | 9 | # Needed to help Bundler figure out how to resolve dependencies, 10 | # otherwise it takes forever to resolve them. 11 | # See https://github.com/bundler/bundler/issues/6677 12 | gem 'rails', '>0.a' 13 | 14 | # Provides basic authentication functionality for testing parts of your engine 15 | gem 'solidus_auth_devise' 16 | 17 | case ENV['DB'] 18 | when 'mysql' 19 | gem 'mysql2' 20 | when 'postgresql' 21 | gem 'pg' 22 | else 23 | gem 'sqlite3' 24 | end 25 | 26 | gem 'rails-controller-testing', group: :test 27 | 28 | gemspec 29 | -------------------------------------------------------------------------------- /solidus_user_roles.gemspec: -------------------------------------------------------------------------------- 1 | # encoding: UTF-8 2 | Gem::Specification.new do |s| 3 | s.platform = Gem::Platform::RUBY 4 | s.name = 'solidus_user_roles' 5 | s.version = '1.2.2' 6 | s.summary = 'Advanced user roles for Solidus.' 7 | s.description = 'Advanced user roles for Solidus.' 8 | s.required_ruby_version = '>= 2.1.0' 9 | 10 | s.author = 'Allison Reilly' 11 | s.email = 'acreilly3@gmail.com' 12 | s.homepage = 'http://boomer.digital' 13 | 14 | #s.files = `git ls-files`.split("\n") 15 | #s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n") 16 | s.require_path = 'lib' 17 | s.requirements << 'none' 18 | 19 | s.add_dependency "solidus_core", [">= 1.0.0", "< 3"] 20 | s.add_dependency 'solidus_support', '~> 0.5' 21 | 22 | 23 | s.add_development_dependency 'solidus_dev_support' 24 | s.add_development_dependency 'shoulda-matchers' 25 | end 26 | -------------------------------------------------------------------------------- /app/models/spree/permission_sets/role_management.rb: -------------------------------------------------------------------------------- 1 | # A Role Manager has all the access of a UserManager and the ability to manage Roles 2 | module Spree 3 | module PermissionSets 4 | class RoleManagement < PermissionSets::Base 5 | def activate! 6 | can [:admin, :display, :create, :update, :save_in_address_book, :remove_from_address_book, :addresses, :orders, :items], Spree.user_class 7 | 8 | # due to how cancancan filters by associations, 9 | # we have to define this twice, once for `accessible_by` 10 | can :update_email, Spree.user_class, spree_roles: { id: nil } 11 | # and once for `can?` 12 | can :update_email, Spree.user_class do |user| 13 | user.spree_roles.none? 14 | end 15 | 16 | cannot [:delete, :destroy], Spree.user_class 17 | can :manage, Spree::StoreCredit 18 | can :manage, Spree::Role 19 | end 20 | end 21 | end 22 | end 23 | -------------------------------------------------------------------------------- /.circleci/config.yml: -------------------------------------------------------------------------------- 1 | version: 2.1 2 | 3 | orbs: 4 | # Always take the latest version of the orb, this allows us to 5 | # run specs against Solidus supported versions only without the need 6 | # to change this configuration every time a Solidus version is released 7 | # or goes EOL. 8 | solidusio_extensions: solidusio/extensions@volatile 9 | 10 | jobs: 11 | run-specs-with-postgres: 12 | executor: solidusio_extensions/postgres 13 | steps: 14 | - solidusio_extensions/run-tests 15 | run-specs-with-mysql: 16 | executor: solidusio_extensions/mysql 17 | steps: 18 | - solidusio_extensions/run-tests 19 | 20 | workflows: 21 | "Run specs on supported Solidus versions": 22 | jobs: 23 | - run-specs-with-postgres 24 | - run-specs-with-mysql 25 | "Weekly run specs against master": 26 | triggers: 27 | - schedule: 28 | cron: "0 0 * * 4" # every Thursday 29 | filters: 30 | branches: 31 | only: 32 | - master 33 | jobs: 34 | - run-specs-with-postgres 35 | - run-specs-with-mysql 36 | -------------------------------------------------------------------------------- /app/decorators/models/solidus_user_roles/spree/role_decorator.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | 4 | module SolidusUserRoles 5 | module Spree 6 | module RoleDecorator 7 | def self.prepended(base) 8 | base.has_many :role_permissions, dependent: :destroy 9 | base.has_many :permission_sets, through: :role_permissions 10 | 11 | base.scope :non_base_roles, -> { where.not(name: ['admin', 'user']) } 12 | base.validates :name, uniqueness: true 13 | base.after_save :assign_permissions 14 | end 15 | 16 | def permission_sets_constantized 17 | permission_sets.map(&:set).map(&:constantize) 18 | end 19 | 20 | def assign_permissions 21 | if ::Spree.solidus_gem_version < Gem::Version.new('2.5.x') 22 | ::Spree::RoleConfiguration.configure do |config| 23 | config.assign_permissions name, permission_sets_constantized 24 | end 25 | else 26 | ::Spree::Config.roles.assign_permissions name, permission_sets_constantized 27 | end 28 | end 29 | 30 | ::Spree::Role.prepend self 31 | end 32 | end 33 | end 34 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2016 [name of plugin creator] 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without modification, 5 | are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright notice, 8 | this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above copyright notice, 10 | this list of conditions and the following disclaimer in the documentation 11 | and/or other materials provided with the distribution. 12 | * Neither the name Spree nor the names of its contributors may be used to 13 | endorse or promote products derived from this software without specific 14 | prior written permission. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 20 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 21 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 22 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 23 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 24 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 25 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 26 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 | -------------------------------------------------------------------------------- /lib/solidus_user_roles/engine.rb: -------------------------------------------------------------------------------- 1 | module SolidusUserRoles 2 | class Engine < Rails::Engine 3 | include SolidusSupport::EngineExtensions 4 | 5 | engine_name 'solidus_user_roles' 6 | config.autoload_paths += %W(#{config.root}/lib) 7 | 8 | config.generators do |g| 9 | g.test_framework :rspec 10 | end 11 | 12 | def self.load_custom_permissions 13 | if (ActiveRecord::Base.connection.tables & ['spree_roles','spree_permission_sets']).to_a.length == 2 # makes sure both table exist 14 | ::Spree::Role.non_base_roles.each do |role| 15 | if ::Spree.solidus_gem_version < Gem::Version.new('2.5.x') 16 | ::Spree::RoleConfiguration.configure do |config| 17 | config.assign_permissions role.name, role.permission_sets_constantized 18 | end 19 | else 20 | ::Spree::Config.roles.assign_permissions role.name, role.permission_sets_constantized 21 | end 22 | end 23 | end 24 | rescue ActiveRecord::NoDatabaseError 25 | warn "No database available, skipping role configuration" 26 | rescue ActiveRecord::StatementInvalid => e 27 | warn "Skipping role configuration: #{e.message}" 28 | end 29 | 30 | 31 | def self.activate 32 | Dir.glob(File.join(File.dirname(__FILE__), '../../app/**/*_decorator*.rb')) do |c| 33 | Rails.configuration.cache_classes ? require(c) : load(c) 34 | end 35 | unless Rails.env == 'test' 36 | SolidusUserRoles::Engine.load_custom_permissions 37 | end 38 | end 39 | 40 | config.to_prepare &method(:activate).to_proc 41 | end 42 | end 43 | -------------------------------------------------------------------------------- /lib/generators/solidus_user_roles/install/install_generator.rb: -------------------------------------------------------------------------------- 1 | module SolidusUserRoles 2 | module Generators 3 | class InstallGenerator < Rails::Generators::Base 4 | 5 | class_option :auto_run_migrations, :type => :boolean, :default => false 6 | 7 | def add_javascripts 8 | append_file 'vendor/assets/javascripts/spree/frontend/all.js', "//= require spree/frontend/solidus_user_roles\n" 9 | append_file 'vendor/assets/javascripts/spree/backend/all.js', "//= require spree/backend/solidus_user_roles\n" 10 | end 11 | 12 | def add_stylesheets 13 | inject_into_file 'vendor/assets/stylesheets/spree/frontend/all.css', " *= require spree/frontend/solidus_user_roles\n", :before => /\*\//, :verbose => true 14 | inject_into_file 'vendor/assets/stylesheets/spree/backend/all.css', " *= require spree/backend/solidus_user_roles\n", :before => /\*\//, :verbose => true 15 | end 16 | 17 | def add_migrations 18 | run 'bundle exec rake railties:install:migrations FROM=solidus_user_roles' 19 | end 20 | 21 | def run_migrations 22 | run_migrations = options[:auto_run_migrations] || ['', 'y', 'Y'].include?(ask 'Would you like to run the migrations now? [Y/n]') 23 | if run_migrations 24 | run 'bundle exec rake db:migrate' 25 | else 26 | puts 'Skipping rake db:migrate, don\'t forget to run it!' 27 | end 28 | end 29 | 30 | def include_seed_data 31 | append_file "db/seeds.rb", <<-SEEDS 32 | \n 33 | SolidusUserRoles::Engine.load_seed if defined?(SolidusUserRoles::Engine) 34 | SEEDS 35 | end 36 | end 37 | end 38 | end 39 | -------------------------------------------------------------------------------- /app/views/spree/admin/roles/_form.html.erb: -------------------------------------------------------------------------------- 1 | 12 |
    13 |
    14 |
    15 | 16 |
    17 |
    18 | <%= f.label :name, Spree.t(:name) %> 19 | <%= f.text_field :name, :class => 'fullwidth' %> 20 |
    21 |
    22 |
    23 | <%= label_tag nil, Spree.t(:display_permissions) %> 24 |
      25 | <% Spree::PermissionSet.display_permissions.each do |permission| %> 26 |
    • 27 | <%= check_box_tag 'role[permission_set_ids][]', permission.id, f.object.try(:permission_sets).include?(permission) %> 28 | <%= permission.name %> 29 |
    • 30 | <% end %> 31 |
    32 |
    33 |
    34 | <%= label_tag nil, Spree.t(:management_permissions) %> 35 |
      36 | <% Spree::PermissionSet.management_permissions.each do |permission| %> 37 |
    • 38 | <%= check_box_tag 'role[permission_set_ids][]', permission.id, f.object.try(:permission_sets).include?(permission) %> 39 | <%= permission.name %> 40 |
    • 41 | <% end %> 42 |
    43 |
    44 |
    45 |
    46 | 47 |
    48 | 49 |
    50 | -------------------------------------------------------------------------------- /app/views/spree/admin/roles/index.html.erb: -------------------------------------------------------------------------------- 1 | <% content_for :page_title do %> 2 | <%= Spree.t(:user_roles) %> 3 | <% end %> 4 | 5 | <% content_for :page_actions do %> 6 | <% if can?(:admin, Spree::Role) && can?(:create, Spree::Role) %> 7 |
  • 8 | <%= button_link_to Spree.t(:new_user_role), new_admin_role_url, :icon => 'plus', :id => 'admin_new_role_link' %> 9 |
  • 10 | <% end %> 11 | <% end %> 12 | 13 | 14 | <% if @roles.any? %> 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | <% @roles.non_base_roles.each do |role|%> 29 | 30 | 31 | 32 | 40 | 41 | <% end %> 42 | 43 |
    <%= Spree.t(:name) %><%= Spree.t(:permissions) %>
    <%=role.try(:name) || Spree.t(:not_available) %><%= role.permission_sets.map(&:name).to_sentence %> 33 | <% if can?(:update, role) %> 34 | <%= link_to_edit role, :no_text => true %> 35 | <% end %> 36 | <% if can?(:destroy, role) %> 37 | <%= link_to_delete role, :no_text => true %> 38 | <% end %> 39 |
    44 | <% else %> 45 |
    46 | <%= Spree.t(:no_resource_found, resource: I18n.t(:other, scope: 'activerecord.models.spree/role')) %> 47 | <% if can?(:create, Spree::TaxRate) %> 48 | <%= link_to Spree.t(:add_one), spree.new_admin_role_path %>! 49 | <% end %> 50 |
    51 | <% end %> 52 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | SolidusUserRoles 2 | ===================== 3 | 4 | [![CircleCI](https://circleci.com/gh/boomerdigital/solidus_user_roles.svg?style=svg)](https://circleci.com/gh/boomerdigital/solidus_user_roles) 5 | 6 | 7 | SolidusUserRoles gives an admin the ability to create custom roles for their employees to restrict or allow access to certain sections in the admin panel. 8 | 9 | Installation 10 | ------------ 11 | 12 | Add solidus_user_roles to your Gemfile: 13 | 14 | ```ruby 15 | gem 'solidus_user_roles', github: 'boomerdigital/solidus_user_roles' 16 | ``` 17 | 18 | Bundle your dependencies and run the installation generator: 19 | 20 | ```shell 21 | bundle 22 | bundle exec rails g solidus_user_roles:install 23 | ``` 24 | 25 | Remember to seed or run: 26 | ```shell 27 | rake solidus_user_roles:load_seeds 28 | ``` 29 | 30 | Admin Panel 31 | ----------- 32 | An admin is the only user who has the ability to add or remove roles from other users. 33 | ![image](https://cloud.githubusercontent.com/assets/6445334/14432566/b90ae0b4-ffd8-11e5-832c-8692dbb437bb.png) 34 | ![image](https://cloud.githubusercontent.com/assets/6445334/14432655/0c5c7a84-ffd9-11e5-8463-366fa88b774f.png) 35 | ![image](https://cloud.githubusercontent.com/assets/6445334/14432674/22dadc60-ffd9-11e5-97c2-3e9719427140.png) 36 | 37 | 38 | Testing 39 | ------- 40 | 41 | First bundle your dependencies, then run `rake`. `rake` will default to building the dummy app if it does not exist, then it will run specs. The dummy app can be regenerated by using `rake test_app`. 42 | 43 | ```shell 44 | bundle 45 | bundle exec rake 46 | ``` 47 | 48 | When testing your applications integration with this extension you may use it's factories. 49 | Simply add this require statement to your spec_helper: 50 | 51 | ```ruby 52 | require 'solidus_user_roles/factories' 53 | ``` 54 | 55 | Copyright (c) 2016 [name of extension creator], released under the New BSD License 56 | -------------------------------------------------------------------------------- /spec/models/spree/role_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe Spree::Role, type: :model do 4 | it { should have_many :role_permissions } 5 | it { should have_many(:permission_sets).through(:role_permissions) } 6 | it { should validate_uniqueness_of :name } 7 | let(:role) { 8 | role = build(:role) 9 | role.permission_sets << create(:permission_set) 10 | role 11 | } 12 | 13 | context "#assign_permissions" do 14 | it 'creates new Spree::RoleConfiguration::Role' do 15 | if Spree.solidus_gem_version < Gem::Version.new('2.5.x') 16 | expect { role.save }.to change { Spree::RoleConfiguration.instance.roles.count }.by(1) 17 | else 18 | expect { role.save }.to change { Spree::Config.roles.roles.count }.by(1) 19 | end 20 | end 21 | it 'updates the existing Spree::RoleConfiguration::Role' do 22 | role.save 23 | role.permission_sets << create(:permission_set, name: 'test', set: 'Spree::PermissionSets::ProductDisplay') 24 | 25 | if Spree.solidus_gem_version < Gem::Version.new('2.5.x') 26 | expect { role.save }.to change { Spree::RoleConfiguration.instance.roles[role.name].permission_sets.count }.from(1).to(2) 27 | else 28 | expect { role.save }.to change { Spree::Config.roles.roles[role.name].permission_sets.count }.from(1).to(2) 29 | end 30 | end 31 | end 32 | 33 | context "#destroy" do 34 | before do 35 | @role = create(:role) 36 | @role.permission_sets << create(:permission_set) 37 | @role.save 38 | @role_permission = @role.role_permissions.first 39 | end 40 | 41 | it "should destroy all associated role permissions" do 42 | @role.destroy 43 | expect{ Spree::Role.find(@role.id) }.to raise_error(ActiveRecord::RecordNotFound) 44 | expect{ Spree::RolePermission.find(@role_permission.id) }.to raise_error(ActiveRecord::RecordNotFound) 45 | end 46 | end 47 | end 48 | -------------------------------------------------------------------------------- /spec/controllers/spree/admin/roles_controller_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe Spree::Admin::RolesController do 4 | stub_authorization! 5 | let(:role) { create(:role) } 6 | let(:permission_set) { create(:permission_set) } 7 | 8 | describe "#index" do 9 | subject { get :index } 10 | 11 | it { is_expected.to be_successful } 12 | end 13 | 14 | describe "#new" do 15 | subject { get :new } 16 | 17 | it { is_expected.to be_successful } 18 | end 19 | 20 | describe "#edit" do 21 | subject { get :edit, params: { id: role.id } } 22 | 23 | it { is_expected.to be_successful } 24 | end 25 | 26 | describe "#create" do 27 | let(:params) do 28 | { 29 | role: { 30 | name: "TEST #{rand(10000)}", 31 | permission_set_ids: [permission_set.id] 32 | } 33 | } 34 | end 35 | 36 | subject { post :create, params: params } 37 | it { is_expected.to redirect_to(spree.admin_roles_path) } 38 | 39 | it "expect @role to eq the role being updated" do 40 | expect(assigns(:role)).to eq(@role) 41 | end 42 | 43 | it "should update the permission sets" do 44 | expect{subject}.to change { Spree::Role.count }.by(1) 45 | end 46 | it "should update the RoleConfiguration" do 47 | if Spree.solidus_gem_version < Gem::Version.new('2.5.x') 48 | expect{subject}.to change {Spree::RoleConfiguration.instance.roles.count}.by(1) 49 | else 50 | expect{subject}.to change {Spree::Config.roles.roles.count}.by(1) 51 | end 52 | end 53 | end 54 | 55 | describe "#update" do 56 | let(:params) do 57 | { 58 | id: role.to_param, 59 | role: { 60 | name: role.name, 61 | permission_set_ids: [permission_set.id] 62 | } 63 | } 64 | end 65 | 66 | subject { put :update, params: params } 67 | it { is_expected.to redirect_to(spree.admin_roles_path) } 68 | 69 | it "expect @role to eq the role being updated" do 70 | expect(assigns(:role)).to eq(@role) 71 | end 72 | 73 | it "should update the permission sets" do 74 | expect{subject}.to change { role.reload.permission_sets.count }.by(1) 75 | end 76 | end 77 | 78 | describe "#destroy" do 79 | subject { put :destroy, params: { :id => role.to_param } } 80 | it { is_expected.to have_http_status(302) } 81 | end 82 | end 83 | --------------------------------------------------------------------------------