diff --git a/.rubocop.yml b/.rubocop.yml index f6f0f20..ddbc53a 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -38,6 +38,10 @@ Style/SpaceBeforeFirstArg: Style/StringLiterals: Enabled: false +Style/StructInheritance: + Exclude: + - app/policies/**/* + Metrics/AbcSize: Exclude: - db/migrate/**/* diff --git a/Gemfile b/Gemfile index f2a509c..8a1a259 100644 --- a/Gemfile +++ b/Gemfile @@ -11,6 +11,7 @@ gem 'jquery-rails' gem 'json', '~> 2.0.2' gem 'mailjet', '~> 1.3.8' gem 'puma', '~> 3.0' +gem 'pundit' gem 'sass-rails', '~> 5.0' gem 'settingslogic', '~> 2.0.9' gem 'turbolinks', '~> 5' @@ -44,6 +45,7 @@ group :development, :test do gem 'guard-shell' gem 'listen', '~> 3.0' gem 'minitest-reporters' + gem 'policy-assertions' gem 'pry-byebug' gem 'pry-rails' gem 'rails-controller-testing' diff --git a/Gemfile.lock b/Gemfile.lock index e9e37a6..248ef2c 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -161,6 +161,9 @@ GEM parser (2.3.1.2) ast (~> 2.2) pkg-config (1.1.7) + policy-assertions (0.0.3) + activesupport (>= 3.0.0) + pundit (>= 1.0.0) powerpack (0.1.1) premailer (1.8.7) css_parser (>= 1.4.5) @@ -178,6 +181,8 @@ GEM pry-rails (0.3.4) pry (>= 0.9.10) puma (3.6.0) + pundit (1.1.0) + activesupport (>= 3.0.0) rack (2.0.1) rack-livereload (0.3.16) rack @@ -309,10 +314,12 @@ DEPENDENCIES minitest-reporters mysql2 (>= 0.3.18, < 0.5) neat + policy-assertions premailer-rails pry-byebug pry-rails puma (~> 3.0) + pundit rack-livereload rails (~> 5.0, >= 5.0.0.1) rails-controller-testing diff --git a/app/controllers/admin_controller.rb b/app/controllers/admin_controller.rb index 39b9f06..423782b 100644 --- a/app/controllers/admin_controller.rb +++ b/app/controllers/admin_controller.rb @@ -1,9 +1,13 @@ # frozen_string_literal: true class AdminController < ApplicationController + include Pundit layout 'admin' before_action :authorize_user + rescue_from Pundit::NotAuthorizedError, with: :user_not_authorized + def dashboard + authorize :admin, :dashboard? @quizzes = Quiz.includes(:questions).all @users = User.order(:role, :name) end @@ -18,4 +22,9 @@ class AdminController < ApplicationController def authorize_user redirect_to admin_login_path unless current_user end + + def user_not_authorized + flash[:error] = "You are not authorized to perform this action." + redirect_to(request.referer || root_path) + end end diff --git a/app/policies/admin_policy.rb b/app/policies/admin_policy.rb new file mode 100644 index 0000000..2644868 --- /dev/null +++ b/app/policies/admin_policy.rb @@ -0,0 +1,31 @@ +# frozen_string_literal: true +class AdminPolicy < Struct.new(:user, :dashboard) + attr_reader :user, :record + + def initialize(user, record) + raise Pundit::NotAuthorizedError, "Must be logged in." unless user + @user = user + @record = record + end + + def dashboard? + true + end + + def scope + Pundit.policy_scope!(user, record.class) + end + + class Scope + attr_reader :user, :scope + + def initialize(user, scope) + @user = user + @scope = scope + end + + def resolve + scope + end + end +end diff --git a/test/policies/admin_policy_test.rb b/test/policies/admin_policy_test.rb new file mode 100644 index 0000000..00f8494 --- /dev/null +++ b/test/policies/admin_policy_test.rb @@ -0,0 +1,10 @@ +# frozen_string_literal: true +require 'test_helper' + +# TODO: How the heck to you test a headless policy?... +# +# class AdminPolicyTest < PolicyAssertions::Test +# def test_dashboard +# assert_permit users(:recruiter), Admin +# end +# end diff --git a/test/test_helper.rb b/test/test_helper.rb index 2eca63e..01cdb2c 100644 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -13,6 +13,7 @@ require File.expand_path('../../config/environment', __FILE__) require 'rails/test_help' require "minitest/autorun" require 'minitest/reporters' +require 'policy_assertions' Dir[Rails.root.join("test/test_helpers/**/*.rb")].each { |f| require f } Minitest::Reporters.use! [Minitest::Reporters::DefaultReporter.new(color: true)]