понеділок, 1 серпня 2011 р.

OmniAuth для Sinatra

Про швидкий запуск Sinatra додатку, використовуючи OmniAuth, як протокол автентифікація я писав у OmniAuth: Зовнішня, проста автентифікація для Rack на прикладі Sinatra і ВКонтакте. Код цієї статті відрізняється від попередньої тим, що включає в себе роботу з сесіями і модель для користувачів у базі даних. Це означає, що користувач може залишатися в системі, поки ваш сервер залишається живим.

Для прикладу використовуватимемо ВКонтакте. Але ви можете використовувати будь-якого іншого постачальника аутентифікації, що підтримується бібліотекою OmniAuth.

Підключаємо необхідні бібліотеки:
require 'sinatra'
require 'haml'
require 'omniauth'

require 'dm-core'
require 'dm-migrations'
require 'dm-timestamps'

ВКонтакте, як провайдер для автентифікації:
enable :sessions

VKONTAKTE_API_ID     = '***'
VKONTAKTE_SECRET_KEY = '***'

use OmniAuth::Builder do
  provider :vkontakte, VKONTAKTE_API_ID, VKONTAKTE_SECRET_KEY
end

Модель Account для збереження інформації про користувачів у базі даних:
DataMapper.setup(:default, "sqlite3://#{Dir.pwd}/database.sqlite3")

class Account
  include DataMapper::Resource
  property :id,         Serial
  property :uid,        String
  property :name,       String
  property :provider,   String
  property :image,      String
  property :created_at, DateTime
end

DataMapper.auto_upgrade!

Помічник для отримання поточного користувача:
helpers do
  def current_user
    @current_user ||= Account.get(session[:user_id]) if session[:user_id]
  end
end

Якщо користувач не авторизований на сайті, перенаправимо його на сторінку для автентифікації:
get '/' do
  if current_user
    haml :index
  else
    haml :signin
  end
end

Тут відбувається найцікавіше. Якщо аутентифікація завершена успішно, створюємо у таблиці accounts нового користувача з заданими полями, або використовуємо вже існуючого. Для подальшого використання додаємо інформацію про користувача у сесію.
get '/auth/:name/callback' do
  auth = request.env['omniauth.auth']
  user = Account.first_or_create({ :uid => auth['uid']}, {
    :uid      => auth['uid'],
    :name     => auth['user_info']['name'],
    :provider => auth['provider'],
    :image    => auth['user_info']['image']
  })
  session[:user_id] = user.id
  redirect '/'
end

Закінчити сесію і вийти:
get '/logout' do
  session[:user_id] = nil
  redirect '/'
end

Представлення на Haml:
__END__

@@ signin
%a{:href => '/auth/vkontakte'} Sign in with Vkontakte

@@ index
%p= "Welcome #{current_user.name}!"
%a{:href => '/logout'} [Sign out]

Немає коментарів: