Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

App structure for roles-based RESTful resources

Is there a consensus best approach to implementing user roles when using RESTful resource routes?

Say I have the following resources:

User has_many Tickets
Event has_many Tickets
Ticket belongs_to Person, Event

And then further say I have two types of Users: customers and agents. Both will log into the system, but with different resource access and functionality based on their roles. For example:

Customers can access:

  • Event index, show
  • Ticket index (scoped by user), show, buy/create, return/delete
  • Person create, show, update

Agents can access:

  • Event index, show, create, update, delete
  • Ticket index, show, sell/create, update, refund/delete
  • Person index, show, create, update, delete

Which of the 4 general approaches below will be cleaner and more flexible?

Separate controllers within role folders and resources in namespaces, eg:

namespace "agent" do
  resources :events, :tickets, :people
end
namespace "customer" do
  resources :events, :tickets, :people
end

Separate controllers by role, eg:

AgentController
  def sell_ticket, etc

CustomerController
  def buy_ticket, etc

Shared controllers with separate actions where needed, eg:

TicketController
  before_filter :customer_access, :only => :buy
  before_filter :agent_access, :except => :buy

  def buy  #accessed by customer to create ticket

  def sell   #accessed by agent to create ticket

Shared actions with conditional statements, eg:

TicketController
  def create
    if @role == :customer
      #buy ticket
    elsif @role == :customer
      #sell ticket
    end
  end
like image 674
Ed Haywood Avatar asked Sep 26 '10 03:09

Ed Haywood


People also ask

What are the 4 most common REST API operations?

These operations stand for four possible actions, known as CRUD: Create, Read, Update and Delete. The server sends the data to the client in one of the following formats: HTML. JSON (which is the most common one thanks to its independence of computer languages and accessibility by humans and machines)


1 Answers

I would suggest using a combination of the last two proposed implementations. They adhere to RESTful representation, they put authorization at the appropriate level (controllers), and it is a scalable implementation.

REST is, essentially, about accessing nouns with verbs. So you want Agents and Customers to perform actions (verbs) in relation to Tickets, Users, and Events (nouns). In order to accurately represent these nouns you should have a controller for each. Customers can then identify the resource they are looking for by the URL, http://example.com/events/22. From here you can use Rails' routing to represent context for various resources, ie http://example.com/events/22/tickets by doing something like:

resource :events do
  resource :tickets
end

By adhering to a RESTful architecture, you are buying into the end to end principle. The paradigm for representing objects needs to be only responsible for that. It shouldn't try to authenticate. That isn't its job. Authorization should happen in the controllers. I would highly recommend looking into gems like CanCan or Declarative Authorization that set all of this up for you.

Finally, this model scalable. By keeping authorization separate from the representation of your resources you only have to use it if you need it. This keeps your application light, flexible, and simple.

like image 131
vrish88 Avatar answered Sep 27 '22 22:09

vrish88