git clone -b multitenancy_authorization https://github.com/turingschool-examples/storedom.git multitenancy_authorization
git checkout —track https://github.com/turingschool-examples/storedom.git multitenancy_authorization_final
rails g model Role name:string
rails g model UserRole user:references role:references
- Add UserRole relationship in Role
- Add UserRole relationship in User
- rake db:migrate
- Create three roles
- platform_admin
- store_admin
- registered_user
- Add Permission methods in user model
- platform_admin?
- store_admin?
- registered_user?
- Create services folder
- Create Permission service
- initialize the object with a user
- implement #allow? method
- Only allow users to visit the stores controller
- Add additional permissions
- Add guest_user and add conditional
- Abstract permissions into private methods
- Add Permission methods in ApplicationController
- current_permission
- authorize!
- before_action :authorize!
- private method :authorize?
- Add helpers in ApplicationHelpers
- platform_admin?
- store_admin?
- registered_user?
- Can you build the permissions for a store admin?
- The store admin will have access to the stores, sessions, items, and orders controllers.
- However, he won’t have access to the users controller.
- Can you create a helper that will hide that functionality from the navbar?
app/model/user.rb
class User < ActiveRecord::Base
has_secure_password
has_many :user_roles
has_many :roles, through: :user_roles
belongs_to :store
has_many :orders
def platform_admin?
roles.exists?(name: "platform_admin")
end
def store_admin?
roles.exists?(name: "store_admin")
end
def registered_user?
roles.exists?(name: “registered_user”)
end
end
app/model/user_role.rb
class UserRole < ActiveRecord::Base
belongs_to :user
belongs_to :role
end
app/model/role.rb
class Role < ActiveRecord::Base
validates :name, uniqueness: true
has_many :user_roles
has_many :users, through: :user_roles
end
app/services/permission.rb
class Permission
extend Forwardable
attr_reader :user, :controller, :action
def_delegators :user, :platform_admin?,
:store_admin?,
:registered_user?
def initialize(user)
@user = user || User.new
end
def allow?(controller, action)
@controller = controller
@action = action
case
when platform_admin?
platform_admin_permissions
when store_admin?
store_admin_permissions
when registered_user?
registered_user_permissions
else
guest_user_permissions
end
end
private
def platform_admin_permissions
return true if controller == "sessions"
return true if controller == "items" && action.in?(%w(index show))
return true if controller == "stores" && action.in?(%w(index show))
return true if controller == "orders" && action.in?(%w(index show))
return true if controller == "users" && action.in?(%w(index show))
end
def store_admin_permissions
return true if controller == "sessions"
return true if controller == "items" && action.in?(%w(index show))
return true if controller == "stores" && action.in?(%w(index show))
return true if controller == "orders" && action.in?(%w(index show))
end
def registered_user_permissions
return true if controller == "sessions"
return true if controller == "items" && action.in?(%w(index show))
return true if controller == "stores" && action.in?(%w(index show))
end
def guest_user_permissions
return true if controller == "sessions"
return true if controller == "items" && action.in?(%w(index show))
return true if controller == "stores" && action.in?(%w(index))
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
before_action :authorize!
add_flash_types :success,
:info,
:warning,
:danger
helper_method :current_user
def current_user
@current_user ||= User.find(session[:user_id]) if session[:user_id]
end
def current_permission
@current_permission ||= Permission.new(current_user)
end
def authorize!
unless authorized?
redirect_to root_url, danger: "You are not authorized to visit this page"
end
end
def authorized?
current_permission.allow?(params[:controller], params[:action])
end
end
app/helpers/application_helper.rb
module ApplicationHelper
def platform_admin?
current_user && current_user.platform_admin?
end
def store_admin?
current_user && current_user.store_admin?
end
def registered_user?
current_user && current_user.registered_user?
end
end