Scoping to Current User
Given a
Postmodel withhiddenattribute, only allow administrators to view hiddenPosts.
Let’s start by adding a visible scope to Post, so we can easily
retrive only Posts where hidden is false:
# app/models/post.rb
scope :visible, -> { where(hidden: false) }As you know, we would typically use the base scope Post.all like so:
def index
render_jsonapi(Post.all)
endLet’s instead use the base scope Post.visible when the user is not an
administrator:
def index
scope = current_user.admin? ? Post.all : Post.visible
render_jsonapi(scope)
endThat’s it! Now only administrators can view hidden Posts.
Of course, this logic would only apply to the /posts endpoint and
would not apply when we are sideloading from /blogs?include=posts. To
ensure this logic runs all the time, add a default filter:
default_filter :visible do |scope, context|
context.current_user.admin? ? scope : scope.visible
endPrivileged Writes
Given
Posts that have aninternalattribute, only allow internal users to publish internal posts.
Our controller context is available in our resource. Let’s override
Resource#create to ensure correct privileging:
def create(attributes)
if !internal_user? && attributes[:internal] == true
raise "Hey you! YOU can't publish internal posts!"
else
super
end
end
private
def internal_user?
context.current_user.internal?
endGuarding Filters
Given
Employees with attributeunder_performance_review, do not allow clients to find all employees under performance review.
Occasionally you need to guard filters based on the current user. Use
the :if option on allow_filter. This will execute in the context of
your controller:
# app/resources/employee_resource.rb
allow_filter :under_performance_review, if: :admin?# app/controllers/employees_controller.rb
class EmployeesController < ApplicationController
jsonapi resource: EmployeeResource
def index
render_jsonapi(Employee.all)
end
private
def admin?
current_user.admin?
end
end