Simply RESTful Controllers and Permissions

I’d like to incorporate RESTful resources in my app, and I’m having a problem figuring out how to do it easily without namespaces. I’m working in edge rails, and I am creating an app for a school for which I’d like to eventually have an API. Here’s the scenario:

  • The public can view a list of students as well as some information about each student
  • Each student can view more information than the public and edit some information about themselves
  • The teachers can view a more detailed list of all students and can edit all information, create and delete students
  • Teachers and students should be able to preview their changes on the “public” portion of the site while still logged in (meaning that the layouts have to be sensitive to whether or not they are logged in, and whether it should render in the “public” layout)

The public layout is completely different from the student layout, which is completely different from the teacher layout. In this case, a single “show” action (/students/1) would be rendered three different ways, with three different layouts:

  • Public sees about 1/3rd of the student’s info using the public layout
  • Student sees about 2/3rds of the student’s info with links to update their own record using the student layout
  • Teacher sees all the student’s information and has links to update and destroy using the teacher layout

I have roughly 25 models to which similar logic will apply, and I may be adding another role as well (like a mentor/advisor).

Initially, I had set this up with namespaced controllers and had a public_controller, student_controller and teacher_controller, each with their own actions. To DRY up and REST the app, I initially thought about creating a directory structure like:

/app/views/students list.rhtml show.rhtml edit.rhtml

list _teacher.rhtml _student.rhtml _public.rhtml

show _teacher.rhtml

_student.rhtml

_public.rhtml

edit _teacher.rhtml

_student.rhtml

I would then check the user’s roles and display the partial according to their role. To complicate things, security is a big issue and making sure that no information ‘leaks’ to the public portion is essential.

Between the authentication, the layouts and the three different displays I’ve lost the DRY principle altogether and it seems hard to test, since I can’t just check the action thats being rendered (I have to verify which partial). Any other way I’ve thought of loses the RESTfulness and makes an API more complicated. When it comes to layouts, I’m completely stumped.

Does anyone have any advice or ideas about how to build a secure 3-user-tiered app in a RESTful, DRY way? Have any of you ever done this?

I should mention that I was planning on using routes to distinguish the different perspectives, like “:mode/:resource”. So that:

  • /teacher/students #= :controller=>‘students’, :action=>‘list’, :mode=>‘admin’
  • /student/students #= :controller=>‘students’, :action=>‘list’, :mode=>‘student’
  • /students #= :controller=>‘students’, :action=>‘list’, :mode=>‘public’

Jeff,

I decided that there are cases like this one where namespaces make sense. It turns out that rails has built-in functionality to handle resource name conflicts that we can use to deal with controller namespaces.

If we have a model name Person and two controllers that operate on this resource name PeopleController and Admin::PeopleController, we can write the following routes in the routes.rb file:

map.resources :people map.resources :people, :path_prefix => 'admin', :controller => 'admin/people', :name_prefix => 'admin_'

This will create two sets of named routes, one for each controller. We just have to make sure that we use the right named route in the right place:

admin_person_url(@person) person_url(@person)

I have looked all over and I couldn't find anywhere where this was written about so I think I will make another post with more about namespaces and REST. But I think this is how I will handle the situation.

-Jake

Thanks -