---
title: Did You Order The Code Red?!
teaser:
tags: web,ruby,rails
author: Dan Croak
published_on: 2007-10-05
---

On Fridays, we enjoy getting together for lunch and reviewing code. This week,
our liveliest discussion surrounded responsibility for authorization logic.

## The problem ~ where does the authorization logic go

You've come across it before: you have a `User` model and a second model for
which users must be authorized to perform certain tasks:

```ruby
def show
  @event = Event.find(params[:id])
  unless(
    logged_in? &&
    (
      @event.members.include?(current_user) ||
      @event.organizer.include?(current_user)
    ) ||
    current_user.admin?
  )
    flash[:failure] = "You are not authorized to view this event."
    redirect_to home_url and return
  end
end
```

In discussion, we decided there is too much logic in the controller. We want to
move the authorization into the correct place in our domain model. Butwhere?

    unless current_user.authorized_for_event?(@event)`

That reads nicely in English as "Unless the current user is authorized for the
event" but logically, a `User` should not be responsible for its own
authorization.

## Solution: non-User model authorizes User

The authorization logic should be on `Event`, not `User`.

![Yawkey Way](http://images.thoughtbot.com/ui/2007-10-5-yawkey_way.jpg)

For example, I have a ticket to a [Red Sox](http://redsox.com) game. When I
arrive on Yawkey Way, the ticket-taker will authorize me to enter the event. He
or she is the Controller in our <abbr title="Model View Controller">MVC</abbr>
pattern. The ticket-taker doesn't need to know that I paid with a MasterCard on
September 20th or that my seat is in right field or any other details. All that
matters is: is this guy authorized?

```ruby
def attend
  @game = RedSoxGame.find_by_id params[:id]

  unless @game.authorized?(current_user)
    flash[:failure] = "You have no ticket for this game.
       Watch it over a pint of Sam Adams at the Cask n' Flagon."
    redirect_to home_url and return
  end
end

class RedSoxGame < ActiveRecord::Base
  def authorized?(user)
    return false if user.nil?
    doors_open? && not_rained_out? && user.ticket?(self) && user.not_drunk?
  end
end
```

The `authorized` method is noteworthy for two reasons. First, it uses the
[Composed
Method](http://c2.com/ppr/wiki/WikiPagesAboutRefactoring/ComposedMethod.html):

> Divide your program into methods that perform one identifiable task. Keep all
> of the operations in a method at the same level of abstraction. This will
> naturally result in programs with many small methods, each a few lines long.

The `authorized?` method is very easy to read because it focuses on simply
authorizing the user for the game. It relies on a number of other methods whose
purpose is clear and are similarly of narrow focus.

The second thing to note is that `authorized?` actually calls methods on the
`User` model. It may seem contradictory to call `User` after saying that
authorization logic does not belongs there. However, it isn't authorization
logic; it's another level of abstraction.

Most importantly, the ticket-taker will let me into the Sox game.
