ALWAYS use authorized_scope when querying the database, to prevent data leakage.
Use authorize! in EVERY SINGLE controller action, and create a policy for EVERY SINGLE controller action.
Policies are used to limit a current_user's access to controller methods.
Policies are defined like so:
user holds the value of current_user
record holds the value of whatever is passed in to the authorize! method.
If nothing is passed, record will hold the model class, that is based on the controller name.
In this case that class is Client
# app/policies/time_reg_policy.rbclassTimeRegPolicy < ApplicationPolicydefindex?# Allows all users to access the index actiontrueendend
# app/policies/client_policy.rbclassClientPolicy < ApplicationPolicydefindex?# As the index action fetches an entire collection, `record` is not relevant# This allows organization_admins to access the actionuser.organization_admin?enddefcreate?# Allows organization_admins in the Client's organization access to the actionuser.organization_admin? && user.current_organization == record.oragnizationendend
Scopes are used to scope out records that the current_user can access in a collection.
Define a scope like so:
# app/policies/time_reg_policy.rbclassTimeRegPolicy < ApplicationPolicyscope_for:relation,:owndo |relation|
# Scopes out the user's own TimeRegsrelation.joins(:organization,:user).where(organizations: user.current_organization,user: user).distinctendend
# app/policies/client_policy.rbclassClientPolicy < ApplicationPolicyscope_for:relationdo |relation|
# Scopes out Clients accessible for organization_adminifuser.organization_admin?relation.joins(:organization).where(organizations: user.current_organization).distinctelserelation.noneendendend
Example usage of policies and scopes
# app/controllers/clients_controller.rbclassClientsController < ApplicationControllerdefindex# Where the controller fetches an entire collection, # use the `authorize!` method without passing in a record (implicitly)authorize!@clients=authorized_scope(Client,type: :relation).allenddefshow@client=authorized_scope(Client,type: :relation).find(params[:id])# Where the controller fetches a single record,# use the `authorize!` method passing in a record (explicitly)authorize!@clientenddefcreate# Use `authorized_scope` when initializing a record@client=authorized_scope(Client,type: :relation).new(client_params)# Use `authorize!` before saving a recordauthorize!@clinet@client.save!endend