Skip to content

Instantly share code, notes, and snippets.

@AriefLuthfi79
Forked from mattmartini/admin_permission.rb
Created December 20, 2018 02:24
Show Gist options
  • Save AriefLuthfi79/fe8e5b9341594e1b0f3dfc7b2936023c to your computer and use it in GitHub Desktop.
Save AriefLuthfi79/fe8e5b9341594e1b0f3dfc7b2936023c to your computer and use it in GitHub Desktop.
# app/models/permissions/admin_permission.rb
module Permissions
class AdminPermission < BasePermission
def initialize(user)
allow_all
end
end
end
# app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
# Prevent CSRF attacks by raising an exception.
# For APIs, you may want to use :null_session instead.
protect_from_forgery with: :exception
# include SessionsHelper
before_filter :check_authorization
delegate :allow_action?, to: :current_permission
helper_method :allow_action?
delegate :allow_attribute?, to: :current_permission
helper_method :allow_attribute?
private
def current_permission
@current_permission ||= Permissions.permission_for(current_user)
end
def current_resource
nil
end
def check_authorization
if current_permission.allow_action?(params[:controller], params[:action], current_resource)
current_permission.permit_params! params
else
redirect_to root_url, alert: "Not Authorized."
end
end
def current_user
# @current_user ||= User.find(session[:user_id]) if session[:user_id]
@current_user ||= User.find_by_auth_token(cookies[:auth_token]) if cookies[:auth_token]
end
helper_method :current_user
end
# app/models/permissions/base_permission.rb
module Permissions
class BasePermission
def allow_action?(controller, action, resource = nil)
allowed = @allow_all || @allowed_actions[[controller.to_s, action.to_s]]
allowed && (allowed == true || resource && allowed.call(resource))
end
def allow_all
@allow_all = true
end
def allow_action(controllers, actions, &block)
@allowed_actions ||= {}
Array(controllers).each do |controller|
Array(actions).each do |action|
@allowed_actions[[controller.to_s, action.to_s]] = block || true
end
end
end
def allow_attribute(resources, attributes)
@allowed_params ||= {}
Array(resources).each do |resource|
@allowed_params[resource] ||= []
@allowed_params[resource] += Array(attributes)
end
end
def allow_attribute?(resource, attribute)
if @allow_all
true
elsif @allowed_params && @allowed_params[resource]
@allowed_params[resource].include? attribute
end
end
def permit_params!(params)
if @allow_all
params.permit!
elsif @allowed_params
@allowed_params.each do |resource, attributes|
if params[resource].respond_to? :permit
params[resource] = params[resource].permit(*attributes)
end
end
end
end
end
end
# app/models/permissions/captain_permission.rb
module Permissions
class CaptainPermission < BasePermission
def initialize(user)
allow_action :users, [:new, :create, :edit, :update]
allow_action :sessions, [:new, :create, :destroy]
allow_action :password_resets, [:new, :create, :edit, :update]
allow_action :pages, [:show]
allow_action :ranks, [:index, :show]
allow_action :precepts, [:index, :show]
allow_action :bulletins, [:index, :show, :new, :create, :edit, :update, :destroy]
end
end
end
# app/models/permissions/guest_permission.rb
module Permissions
class GuestPermission < BasePermission
def initialize(user)
allow_action :users, [:new, :create]
allow_action :sessions, [:new, :create, :destroy]
allow_action :password_resets, [:new, :create, :edit, :update]
allow_action :pages, [:show]
allow_action :ranks, [:index, :show]
allow_action :precepts, [:index, :show]
allow_action :bulletins, [:index, :show]
end
end
end
# app/models/permissions.rb
module Permissions
def self.permission_for(user)
if user.nil?
VisitorPermission.new
elsif user.roles.include? "admin"
AdminPermisson.new(user)
elsif user.roles.include? "captain"
CaptainPermission.new(user)
elsif user.roles.include? "student"
StudentPermission.new(user)
# elsif user.roles.include? "guest"
else
GuestPermission.new(user)
end
end
end
# app/controllers/ranks_controller.rb
class RanksController < ApplicationController
# before_action :set_rank, only: [:show, :edit, :update, :destroy]
# GET /ranks
# GET /ranks.json
def index
@ranks = Rank.all
end
# GET /ranks/1
# GET /ranks/1.json
def show
@rank = current_resource
end
# GET /ranks/new
def new
@rank = Rank.new
end
# GET /ranks/1/edit
def edit
@rank = current_resource
end
# POST /ranks
# POST /ranks.json
def create
@rank = Rank.new(rank_params)
respond_to do |format|
if @rank.save
format.html { redirect_to @rank, notice: 'Rank was successfully created.' }
format.json { render :show, status: :created, location: @rank }
else
format.html { render :new }
format.json { render json: @rank.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /ranks/1
# PATCH/PUT /ranks/1.json
def update
@rank = current_resource
respond_to do |format|
if @rank.update(rank_params)
format.html { redirect_to @rank, notice: 'Rank was successfully updated.' }
format.json { render :show, status: :ok, location: @rank }
else
format.html { render :edit }
format.json { render json: @rank.errors, status: :unprocessable_entity }
end
end
end
# DELETE /ranks/1
# DELETE /ranks/1.json
def destroy
@rank = current_resource
@rank.destroy
respond_to do |format|
format.html { redirect_to ranks_url, notice: 'Rank was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_rank
@rank = Rank.find(params[:id])
end
def current_resource
@current_resource ||= Rank.find(params[:id]) if params[:id]
end
# Never trust parameters from the scary internet, only allow the white list through.
def rank_params
params.require(:rank).permit(:name, :belt, :traditional)
end
end
# spec/controllers/ranks_controller_spec.rb
require 'rails_helper'
# This spec was generated by rspec-rails when you ran the scaffold generator.
# It demonstrates how one might use RSpec to specify the controller code that
# was generated by Rails when you ran the scaffold generator.
#
# It assumes that the implementation code is generated by the rails scaffold
# generator. If you are using any extension libraries to generate different
# controller code, this generated spec may or may not pass.
#
# It only uses APIs available in rails and/or rspec-rails. There are a number
# of tools you can use to make these specs even more expressive, but we're
# sticking to rails and rspec-rails APIs to keep things simple and stable.
#
# Compared to earlier versions of this generator, there is very limited use of
# stubs and message expectations in this spec. Stubs are only used when there
# is no simpler way to get a handle on the object needed for the example.
# Message expectations are only used when there is no simpler way to specify
# that an instance is receiving a specific message.
RSpec.describe RanksController, type: :controller do
it { should be_a ApplicationController }
# it "should have a current_user" do
# login_admin
# expect(subject.current_user).to_not eq(nil)
# end
#
# it "should get index" do
# login_admin
# get 'index'
# expect(response).to be_success
# end
let(:admin_user) { create(:admin) }
# let(:user) { create(:user) }
# This should return the minimal set of attributes required to create a valid
# Rank. As you add validations to Rank, be sure to
# adjust the attributes here as well.
let(:valid_attributes) {
{
:name => "aShodan",
:belt => "Black Belt",
:traditional => 'Black Belt'
}
}
let(:invalid_attributes) {
{
:name => nil,
:belt => "Black Belt",
:traditional => 'Black Belt'
}
}
# This should return the minimal set of values that should be in the session
# in order to pass any filters (e.g. authentication) defined in
# RanksController. Be sure to keep this updated too.
let(:valid_session) { { cookies[:auth_token] => admin_user.auth_token } }
describe "GET #index" do
it "assigns all ranks as @ranks" do
rank = Rank.create! valid_attributes
get :index, {}, valid_session
expect(assigns(:ranks)).to eq([rank])
end
end
describe "GET #show" do
it "assigns the requested rank as @rank" do
rank = Rank.create! valid_attributes
get :show, {:id => rank.to_param}, valid_session
expect(assigns(:rank)).to eq(rank)
end
end
describe "GET #new" do
it "assigns a new rank as @rank" do
get :new, {}
expect(assigns(:rank)).to be_a_new(Rank)
end
end
describe "GET #edit" do
it "assigns the requested rank as @rank" do
rank = Rank.create! valid_attributes
get :edit, {:id => rank.to_param}, valid_session
expect(assigns(:rank)).to eq(rank)
end
end
describe "POST #create" do
context "with valid params" do
it "creates a new Rank" do
expect {
post :create, {:rank => valid_attributes}, valid_session
}.to change(Rank, :count).by(1)
end
it "assigns a newly created rank as @rank" do
post :create, {:rank => valid_attributes}, valid_session
expect(assigns(:rank)).to be_a(Rank)
expect(assigns(:rank)).to be_persisted
end
it "redirects to the created rank" do
post :create, {:rank => valid_attributes}, valid_session
expect(response).to redirect_to(Rank.last)
end
end
context "with invalid params" do
it "assigns a newly created but unsaved rank as @rank" do
post :create, {:rank => invalid_attributes}, valid_session
expect(assigns(:rank)).to be_a_new(Rank)
end
it "re-renders the 'new' template" do
post :create, {:rank => invalid_attributes}, valid_session
expect(response).to render_template("new")
end
end
end
describe "PUT #update" do
context "with valid params" do
let(:new_attributes) {
{
:name => "aSho Kyu",
:belt => "Brown Belt II",
:traditional => 'Brown Belt III'
}
# skip("Add a hash of attributes valid for your model")
}
it "updates the requested rank" do
rank = Rank.create! valid_attributes
put :update, {:id => rank.to_param, :rank => new_attributes}, valid_session
rank.reload
expect(rank.name).to eq('aSho Kyu')
expect(rank.belt).to eq('Brown Belt II')
expect(rank.traditional).to eq('Brown Belt III')
expect(rank.full_rank).to eq('aSho Kyu - Brown Belt II')
expect(rank.traditional_rank).to eq('aSho Kyu - Brown Belt III')
# skip("Add assertions for updated state")
end
it "assigns the requested rank as @rank" do
rank = Rank.create! valid_attributes
put :update, {:id => rank.to_param, :rank => valid_attributes}, valid_session
expect(assigns(:rank)).to eq(rank)
end
it "redirects to the rank" do
rank = Rank.create! valid_attributes
put :update, {:id => rank.to_param, :rank => valid_attributes}, valid_session
expect(response).to redirect_to(rank)
end
end
context "with invalid params" do
it "assigns the rank as @rank" do
rank = Rank.create! valid_attributes
put :update, {:id => rank.to_param, :rank => invalid_attributes}, valid_session
expect(assigns(:rank)).to eq(rank)
end
it "re-renders the 'edit' template" do
rank = Rank.create! valid_attributes
put :update, {:id => rank.to_param, :rank => invalid_attributes}, valid_session
expect(response).to render_template("edit")
end
end
end
describe "DELETE #destroy" do
it "destroys the requested rank" do
rank = Rank.create! valid_attributes
expect {
delete :destroy, {:id => rank.to_param}, valid_session
}.to change(Rank, :count).by(-1)
end
it "redirects to the ranks list" do
rank = Rank.create! valid_attributes
delete :destroy, {:id => rank.to_param}, valid_session
expect(response).to redirect_to(ranks_url)
end
end
end
# app/controllers/sessions_controller.rb
class SessionsController < ApplicationController
def new
end
def create
user = User.find_by_email(params[:email])
if user && user.authenticate(params[:password])
# session[:user_id] = user.id
if params[:remember_me]
cookies.permanent[:auth_token] = user.auth_token
else
cookies[:auth_token] = user.auth_token
end
redirect_to root_url, notice: "Logged in!"
else
flash.now.alert = "Email or password is invalid"
render "new"
end
end
def destroy
# session[:user_id] = nil
cookies.delete(:auth_token)
redirect_to root_url, notice: "Logged out!"
end
end
# app/models/permissions/student_permission.rb
module Permissions
class StudentPermission < BasePermission
def initialize(user)
allow_action :users, [:new, :create]
allow_action :sessions, [:new, :create, :destroy]
allow_action :password_resets, [:new, :create, :edit, :update]
allow_action :pages, [:show]
allow_action :ranks, [:index, :show]
allow_action :precepts, [:index, :show]
allow_action :bulletins, [:index, :show]
end
end
end
# app/controllers/users_controller.rb
class UsersController < ApplicationController
def new
@user = User.new
end
def create
@user = User.new(user_params)
if @user.save
# session[:user_id] = @user.id
cookies[:auth_token] = @user.auth_token
redirect_to root_url, notice: "Thank you for signing up!"
else
render "new"
end
end
def edit
@user = current_user
end
def update
@user = current_user
if @user.update_attributes(user_params)
redirect_to root_url, notice: "Updated profile."
else
render "new"
end
end
private
def user_params
params.require(:user).permit(:first_name, :last_name, :email, :password, :password_confirmation, :roles_mask, :roles)
end
end
# app/models/permissions/visitor_permission.rb
module Permissions
class VisitorPermission < BasePermission
def initialize
allow_action :users, [:new, :create]
allow_action :sessions, [:new, :create, :destroy]
allow_action :password_resets, [:new, :create, :edit, :update]
allow_action :pages, [:show]
allow_action :ranks, [:index, :show]
allow_action :precepts, [:index, :show]
allow_action :bulletins, [:index, :show]
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment