Lesson: Use Hydra Access Controls and CanCan to decide whether to render a page - afred/hydra-head GitHub Wiki
This Tutorial is known to work with hydra-head version 6.0.0.
Please update this wiki to reflect any other versions that have been tested.
- Use Hydra Access Controls and its built-in CanCan integration to decide whether to render a page
All of the methods described in this lesson are actually provided by a gem called CanCan. Hydra simply implements the ability for those CanCan methods to consult Hydra rightsMetadata to make decisions about access controls. The actual methods come from CanCan, so for more information you should consult the CanCan documentation.
Before starting this lesson, you need to have Controller, Views and Routes set up for Books. The easiest way to do this is by using the rails scaffold generator. See Lesson: Generate Rails Scaffolding for Creating and Editing Books in the Dive into Hydra tutorial for step-by-step instructions.
In app/controllers/books_controller.rb
find the lines that define the show
method and add authorize! :show, params[:id]
as the first thing the method does.
# GET /books/1
# GET /books/1.json
def show
authorize! :show, params[:id]
@book = Book.find(params[:id])
respond_to do |format|
format.html # show.html.erb
format.json { render json: @book }
end
end
Now when you try to view a Book's show
page in the browser, you will get an error page.
CanCan::AccessDenied in BooksController#show
You are not authorized to access this page.
If you go into the rails console
and give yourself read access, then the page renders normally.
Likewise, you can add authorize! :edit, params[:id]
to the BooksController#edit
, BooksController#update
and BooksController#destroy
methods. Then save the file and see what happens in the browser. When you try to access the edit
page for an object that you don't have edit access to, you get an error, but if you go into the rails console
and give yourself edit access, then the page renders normally.
Instead of calling authorize!
in each of your methods, there's a one-line option you can use. At the top of app/controllers/books_controller.rb add a line that simply says load_and_authorize_resource
class BooksController < ApplicationController
load_and_authorize_resource
# GET /books
# GET /books.json
def index
@books = Book.all
respond_to do |format|
format.html # index.html.erb
format.json { render json: @books }
end
end
[...]
end
This load_and_authorize_resource
method does two things for you. It loads a copy of the Book from Fedora and it runs authorize!
for you. So, if you're using this method you can also delete the lines that create @book
for you, for example:
@book = Book.find(params[:id])
If you're using load_and_authorize_resource
, it does that loading for you. This allows you to have less lines of code in your Controller.
Note: A drawback of using load_and_authorize_resource
is that it always loads a copy of the object from Fedora on every request. By contrast, calling authorize!
only reads the permissions metadata out of Solr, which is much faster than loading an object from Fedora. Either method works equally well. There is just the tradeoff: one method lets your application run faster while the other lets you have less lines of code in your Controller.
Go on to Lesson: Using Hydra Access Controls and CanCan to conditionally render part of a page or return to the Access Controls with Hydra tutorial.