2010-09-26 1 views
6

Существует ли наилучший подход к внедрению пользовательских ролей при использовании маршрутов ресурсов RESTful?Структура приложения для ресурсов RESTful на основе ролей

Скажет, у меня есть следующие ресурсы:

User has_many Tickets 
Event has_many Tickets 
Ticket belongs_to Person, Event 

А затем еще у меня есть два типа пользователей: клиенты и агенты. Оба входа будут входить в систему, но с различным доступом к ресурсам и функциональностью, основанной на их ролях. Например:

Клиентов могут получить доступ:

  • индекса событий, показать
  • индекса билетов (область действия пользователя), шоу, купить/создать, возврат/удалить
  • Людей создания, шоу, обновление

Агенты могут получить доступ к:

  • Индекс события, шоу, создание, обновление, удаление
  • индекса билетов, шоу, продажа/создание, обновление, возврат/удалить
  • индекс Person, шоу, создавать, обновлять, удалять

Какие из 4-х общие подходы ниже будут более чистыми и более гибкими?

Отдельные контроллеры в роли папок и ресурсов в пространствах имен, например:

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

Отдельные контроллеры по роли, например:

AgentController 
    def sell_ticket, etc 

CustomerController 
    def buy_ticket, etc 

Общие контроллеры с отдельными действиями в случае необходимости, например:

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 

Общие действия с условными операторами, например:

TicketController 
    def create 
    if @role == :customer 
     #buy ticket 
    elsif @role == :customer 
     #sell ticket 
    end 
    end 

ответ

-1

Если вы используете ту же модель для билетов на клиентов и агентов, не должно быть существенной разницы между тем, как они обрабатываются в контроллере. Таким образом, создать действие всегда будет так:

@ticket = Ticket.new(params[:ticket]) 

if @ticket.save 
    redirect_to @ticket 
else 
    render :action => "new" 
end 

Но ваши взгляды могут быть просто настроены:

<% if customer? %> 
    Customer area. 
<% else %> 
    Agent area. 
<% end %> 
+0

Модель не знает о пользователе, который прошел аутентификацию. Обычно это управляется контроллером. Кроме того, ОП задает вопрос о наилучшем способе защиты. Это невозможно настроить в представлениях. Как насчет соединений API? Как вы обеспечиваете безопасность для разных ролей пользователя там? Вы не хотите повторять код, поэтому он должен находиться в центральном месте, т.е. контроллере. Итак, вопрос в том, как вы можете разумно управлять своим контроллером, чтобы добавить такой тонкий контроль над ролями и разрешениями пользователей. –

6

Я хотел бы предложить использовать комбинацию последних двух предложенных реализаций. Они придерживаются представления RESTful, они устанавливают авторизацию на соответствующем уровне (контроллеры), и это масштабируемая реализация.

REST есть, в высшей степени, примерно accessing nouns with verbs. Таким образом, вы хотите, чтобы агенты и клиенты выполняли действия (глаголы) в отношении Билетов, Пользователей и Событий (существительных). Чтобы точно представлять эти существительные, у вас должен быть контроллер для каждого. Затем клиенты могут идентифицировать ресурс, который они ищут по URL-адресу, http://example.com/events/22.Отсюда вы можете использовать маршрутизацию Rails, чтобы представить контекст для различных ресурсов, т.е. http://example.com/events/22/tickets делать что-то вроде:

resource :events do 
    resource :tickets 
end 

Присоединившись к RESTful архитектуры, вы покупаете в end to end principle. Парадигма для представления объектов должна отвечать только за это. Он не должен пытаться аутентифицироваться. Это не его работа. Авторизация должна выполняться в контроллерах. Я бы настоятельно рекомендовал заглянуть в драгоценные камни, например, CanCan или Declarative Authorization, которые задают все это для вас.

И наконец, эта модель масштабируется. Сохраняя авторизацию отдельно от представления ваших ресурсов, вам нужно использовать ее, только если это необходимо. Это упрощает ваше приложение, его гибкость и простоту.

0

Хотя они оба имеют дело с созданием билетов, продажа агента/билета по сравнению с покупкой Клиента/Билета выглядит для меня настолько различной, что их нужно разделить. В конце концов, они могут расходиться, так как они используются по-разному с самого начала.

Можно иметь общую функциональность контроллера либо с модулями или путем наследования от общего родительского контроллера:

module TicketsControllersCommom 
    # common helper methods 
end 

class TicketsController < ApplicationController 
    include TicketsControllersCommom 
    # actions 
end 

class AgentTicketsController < ApplicationController 
    include TicketsControllersCommom 
    # actions 
end 

я мог бы относиться к части агента в качестве своего рода раздел администрирования, с частями клиента являются по умолчанию:

/events/xx/tickets # collection 
/events/xx/tickets/xx # member 
# etc. 
/events/xx/agent/tickets # collection 
/events/xx/agent/tickets/xx # member 
# etc. 

Или, если у вас есть много админ типа материала, как если агенты управлять событиями, а также, вы можете пространства имен целый раздел:

/agent/events/xx/tickets 
/agent/events/xx/edit 
# etc.