user policies
This commit is contained in:
parent
12c7e9e77c
commit
ead9564fe8
@ -2,14 +2,16 @@
|
|||||||
module Admin
|
module Admin
|
||||||
class UserController < AdminController
|
class UserController < AdminController
|
||||||
def index
|
def index
|
||||||
@users = User.order(:name)
|
@users = policy_scope User.order(:name)
|
||||||
end
|
end
|
||||||
|
|
||||||
def new
|
def new
|
||||||
@user = User.new
|
@user = User.new
|
||||||
|
authorize @user
|
||||||
end
|
end
|
||||||
|
|
||||||
def create
|
def create
|
||||||
|
authorize User
|
||||||
default_passwd = SecureRandom.urlsafe_base64(12)
|
default_passwd = SecureRandom.urlsafe_base64(12)
|
||||||
@user = User.create({ password: default_passwd }.merge(user_params.to_h))
|
@user = User.create({ password: default_passwd }.merge(user_params.to_h))
|
||||||
|
|
||||||
@ -24,14 +26,17 @@ module Admin
|
|||||||
|
|
||||||
def view
|
def view
|
||||||
@user = User.find(params[:user_id])
|
@user = User.find(params[:user_id])
|
||||||
|
authorize @user
|
||||||
end
|
end
|
||||||
|
|
||||||
def edit
|
def edit
|
||||||
@user = User.find(params[:user_id])
|
@user = User.find(params[:user_id])
|
||||||
|
authorize @user
|
||||||
end
|
end
|
||||||
|
|
||||||
def update
|
def update
|
||||||
@user = User.find(params[:user_id])
|
@user = User.find(params[:user_id])
|
||||||
|
authorize @user
|
||||||
|
|
||||||
if @user.update_attributes(user_params)
|
if @user.update_attributes(user_params)
|
||||||
redirect_to admin_user_path(@user.to_i),
|
redirect_to admin_user_path(@user.to_i),
|
||||||
|
@ -4,8 +4,12 @@ class AdminController < ApplicationController
|
|||||||
layout 'admin'
|
layout 'admin'
|
||||||
before_action :authorize_user
|
before_action :authorize_user
|
||||||
|
|
||||||
|
# TODO: after_action :verify_authorized, except: :index
|
||||||
|
# TODO: after_action :verify_policy_scoped, only: :index
|
||||||
|
|
||||||
rescue_from Pundit::NotAuthorizedError, with: :user_not_authorized
|
rescue_from Pundit::NotAuthorizedError, with: :user_not_authorized
|
||||||
|
|
||||||
|
# TODO: move to DashboardController#index
|
||||||
def dashboard
|
def dashboard
|
||||||
authorize :admin, :dashboard?
|
authorize :admin, :dashboard?
|
||||||
@quizzes = Quiz.includes(:questions).all
|
@quizzes = Quiz.includes(:questions).all
|
||||||
@ -25,6 +29,6 @@ class AdminController < ApplicationController
|
|||||||
|
|
||||||
def user_not_authorized
|
def user_not_authorized
|
||||||
flash[:error] = "You are not authorized to perform this action."
|
flash[:error] = "You are not authorized to perform this action."
|
||||||
redirect_to(request.referer || root_path)
|
redirect_to(request.referer || admin_login_path)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -15,6 +15,12 @@ class User < ApplicationRecord
|
|||||||
save
|
save
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# TODO: move to mixin: UserRoles
|
||||||
|
# define remaining helpers
|
||||||
|
def admin?
|
||||||
|
role == 'admin'
|
||||||
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def gen_reset_token
|
def gen_reset_token
|
||||||
|
60
app/policies/application_policy.rb
Normal file
60
app/policies/application_policy.rb
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
class ApplicationPolicy
|
||||||
|
attr_reader :user, :record
|
||||||
|
|
||||||
|
def initialize(user, record)
|
||||||
|
raise Pundit::NotAuthorizedError, "Must be logged in." unless user
|
||||||
|
@user = user
|
||||||
|
@record = record
|
||||||
|
end
|
||||||
|
|
||||||
|
def index?
|
||||||
|
false
|
||||||
|
end
|
||||||
|
|
||||||
|
def show?
|
||||||
|
scope.where(id: record.id).exists?
|
||||||
|
end
|
||||||
|
|
||||||
|
def view?
|
||||||
|
show?
|
||||||
|
end
|
||||||
|
|
||||||
|
def create?
|
||||||
|
false
|
||||||
|
end
|
||||||
|
|
||||||
|
def new?
|
||||||
|
create?
|
||||||
|
end
|
||||||
|
|
||||||
|
def update?
|
||||||
|
false
|
||||||
|
end
|
||||||
|
|
||||||
|
def edit?
|
||||||
|
update?
|
||||||
|
end
|
||||||
|
|
||||||
|
def destroy?
|
||||||
|
false
|
||||||
|
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
|
||||||
|
# This is a closed system.
|
||||||
|
raise Pundit::NotAuthorizedError, "No access to resource."
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
21
app/policies/user_policy.rb
Normal file
21
app/policies/user_policy.rb
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
class UserPolicy < ApplicationPolicy
|
||||||
|
def view?
|
||||||
|
user.admin? && show?
|
||||||
|
end
|
||||||
|
|
||||||
|
def create?
|
||||||
|
user.admin?
|
||||||
|
end
|
||||||
|
|
||||||
|
def update?
|
||||||
|
user.admin?
|
||||||
|
end
|
||||||
|
|
||||||
|
class Scope < Scope
|
||||||
|
def resolve
|
||||||
|
return scope if user.admin?
|
||||||
|
raise Pundit::NotAuthorizedError, "No access to resource."
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
30
test/policies/application_policy_test.rb
Normal file
30
test/policies/application_policy_test.rb
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
require 'test_helper'
|
||||||
|
|
||||||
|
class ApplicationPolicyTest < PolicyAssertions::Test
|
||||||
|
# Verify default policies are most restrictive
|
||||||
|
|
||||||
|
test 'should require a user' do
|
||||||
|
assert_raise Pundit::NotAuthorizedError do
|
||||||
|
ApplicationPolicy.new(nil, User.new)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
test 'should not allow collections' do
|
||||||
|
assert_raise Pundit::NotAuthorizedError do
|
||||||
|
ApplicationPolicy::Scope.new(users(:admin), User).resolve
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
test 'should not permit by default' do
|
||||||
|
admin = users(:admin)
|
||||||
|
refute ApplicationPolicy.new(admin, User.new).view?
|
||||||
|
refute ApplicationPolicy.new(admin, User.new).show?
|
||||||
|
refute ApplicationPolicy.new(admin, nil).index?
|
||||||
|
refute ApplicationPolicy.new(admin, nil).create?
|
||||||
|
refute ApplicationPolicy.new(admin, nil).new?
|
||||||
|
refute ApplicationPolicy.new(admin, nil).update?
|
||||||
|
refute ApplicationPolicy.new(admin, nil).edit?
|
||||||
|
refute ApplicationPolicy.new(admin, nil).destroy?
|
||||||
|
end
|
||||||
|
end
|
31
test/policies/user_policy_test.rb
Normal file
31
test/policies/user_policy_test.rb
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
require 'test_helper'
|
||||||
|
|
||||||
|
class UserPolicyTest < PolicyAssertions::Test
|
||||||
|
test 'should allow admin to scope' do
|
||||||
|
scope = UserPolicy::Scope.new(users(:admin), User).resolve
|
||||||
|
assert_equal User.count, scope.count
|
||||||
|
end
|
||||||
|
|
||||||
|
test 'should not allow non_admin' do
|
||||||
|
assert_raise Pundit::NotAuthorizedError do
|
||||||
|
UserPolicy::Scope.new(users(:manager), User).resolve
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
test 'should require current_user' do
|
||||||
|
assert_raise Pundit::NotAuthorizedError do
|
||||||
|
UserPolicy.new(nil, User.first).view?
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_view
|
||||||
|
refute_permit users(:manager), User.first
|
||||||
|
assert_permit users(:admin), User.first
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_create_and_update
|
||||||
|
refute_permit users(:manager), User
|
||||||
|
assert_permit users(:admin), User
|
||||||
|
end
|
||||||
|
end
|
@ -7,6 +7,7 @@ SimpleCov.start 'rails' do
|
|||||||
add_group 'Models', %w(app/models app/validators)
|
add_group 'Models', %w(app/models app/validators)
|
||||||
add_group 'Services & Workers', %w(app/workers app/services)
|
add_group 'Services & Workers', %w(app/workers app/services)
|
||||||
add_group "Jobs", 'app/jobs'
|
add_group "Jobs", 'app/jobs'
|
||||||
|
add_group "Policies", 'app/policies'
|
||||||
end
|
end
|
||||||
|
|
||||||
require File.expand_path('../../config/environment', __FILE__)
|
require File.expand_path('../../config/environment', __FILE__)
|
||||||
|
Loading…
Reference in New Issue
Block a user