Scoping to Current User
Given a
Post
model withhidden
attribute, only allow administrators to view hiddenPosts
.
Let’s start by adding a visible
scope to Post
, so we can easily
retrive only Post
s 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)
end
Let’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)
end
That’s it! Now only administrators can view hidden Post
s.
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
end
Privileged Writes
Given
Post
s that have aninternal
attribute, 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?
end
Guarding Filters
Given
Employee
s 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