【個人メモ】padrino-wardenとpadrino-adminを使って認証する

# Padrinoで楽に認証の仕組み作りたい...

Padrino製のアプリに、[Padrino-admin](http://www.padrinorb.com/guides/padrino-admin)を使って
ユーザ認証作ればチョー楽できるよなーとか思ってたら、
[padrino-warden](https://github.com/jondot/padrino-warden)を見つけたので使ってみた。

[OmniAuth](https://github.com/intridea/omniauth)じゃないものもあるのかと思ったので使ってみる。

# それぞれの要素

## Padrino

言わずもがな...
sinatraベースの自分が好んでいるWeb Application Framework。

## Warden

[warden](https://github.com/hassox/warden)は、
Rack Middlewareを利用しているWAFで使える認証ライブラリ。

## Padrino-warden

[padrino-warden](https://github.com/jondot/padrino-warden)は、WardenをPadrinoで利用できるように
Helperを追加がされており、楽に使える。

## [Padrino-admin](http://www.padrinorb.com/guides/padrino-admin)

Padrinoプロダクトに包含されている
admin画面を作るもの。
scaffoldにて、```padrino g admin``` と、
padrino projectに対してscaffoldを実行すればadmin画面を作成できる。

こんなの。

![Screen Shot 2014-07-12 at 18.34.14.png](https://qiita-image-store.s3.amazonaws.com/0/3985/90b559be-8f2d-1726-8373-f04b962fc2ef.png)

# padrino-adminの環境を構築するまで

## padrinoを入れる

まあ、グローバルインストールすると楽。

```
> gem install padrino -V
```

## generatorでサクッと作る

```
> padrino g project test-padrino-warden -t rspec -e haml -m mocha -s jquery -d activerecord -c sass
> cd test-padrino-warden
> bundle ins --path vendor/bundle
```

## adminアプリを作成

Padrino-adminは、別アプリとして
Padrino側でPadrino-adminをマウントする。
まあ、scaffoldを使えば良い。

```
> cd test-padrino-warden
> padrino admin
```

## DB migrate

DBのマイグレーションをする。

```
> bundle
> bundle ex db:create
> bundle ex db:marge
```

## Adminのユーザを作る

以下のRake taskで作成できる。

```
> bundle ex db:seed
```

![Screen Shot 2014-07-12 at 18.49.05.png](https://qiita-image-store.s3.amazonaws.com/0/3985/2f9ab6a7-a1f8-c7d9-43a9-f98ecfbcafba.png)

## padrino-adminの確認

アプリを立ち上げて、padrino-adminへのアクセスを確認する。

```
> bundle ex rackup
> open http://localhost:9292/admin/sessions/new
```

![Screen Shot 2014-07-12 at 18.50.53.png](https://qiita-image-store.s3.amazonaws.com/0/3985/1d1e84ae-3cb3-04bb-2bd3-cc6f3b3c1910.png)

OK。

# wardenとpadrino-adminのつなぎ込み

## wardenなどをインストール

Gemfileに、おもむろにpadrino-wardenをインストールするよう
追記しとく。

rubygemsで手に入るpadrino-wardenはバージョンが古い(0.1.0)。
githubからmaster branchを手に入れるようにする。

![Screen Shot 2014-07-14 at 9.43.38.png](https://qiita-image-store.s3.amazonaws.com/0/3985/a816254b-6d08-f64b-b366-8cc2bd878c5d.png)

```rb:Gemfile
gem 'padrino', '0.12.2'
gem 'padrino-warden', :github => 'jondot/padrino-warden'
```

```
> bundle
```

## app.rbにwarden provideの対応を行う

generatorが作成したapp.rbと
追記した結果のdiffを示す。

```diff
--- app.rbx	2014-07-12 19:07:15.000000000 +0900
+++ app.rb	2014-07-13 09:58:03.000000000 +0900
@@ -4,9 +4,36 @@
     use ActiveRecord::ConnectionAdapters::ConnectionManagement
     register Padrino::Mailer
     register Padrino::Helpers
+    register Padrino::Warden
+    register Padrino::Warden::Helper
 
     enable :sessions
 
+    set :auth_failute_path, '/sessions/login'
+    set :auth_success_path, '/'
+
+    Warden::Strategies.add(:password) do
+      def valid?
+        params['email'] || params['password']
+      end
+
+      def authenticate!
+        account = Account.authenticate(
+          params['email'], params['password']
+        )
+        account.nil? ? fail!('Invalid username of password') : success!(account)
+      end
+    end
+
+    Warden::Manager.serialize_into_session { |account| account.email }
+    Warden::Manager.serialize_from_session { |email| Account.where(email: email) }
+
+    before do
+      unless request.path == '/sessions/login'
+        return redirect '/sessions/login' unless authenticated?
+      end
+    end
+
     ##
     # Caching support.
     #
```

## layouts/application templateを作る

```${root}/app/views/layouts/application.haml``` を作る。

```haml:application.haml
%html
  %head
    %meta{:charset => "utf-8"}
    = stylesheet_link_tag '//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css'
    = javascript_include_tag '//code.jquery.com/jquery-2.1.1.min.js'
    = javascript_include_tag '//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/js/bootstrap.min.js'
    %title
      Test - Padrino Warden -
  %body
    .navbar.navbar-default{ role: 'navigation' }
      .container-fluid
        .navbar-header
          %a{ class: 'navbar-brand'}
            Test - Padrino Warden -
        .collapse.navbar-collapse
          %ul.nav.navbar-nav.navbar-right
            %li
              %a{ href: "#" }
                - if authenticated?
                  = "#{current_user.first.name} としてログイン"
                - else
                  ログインしてません...
            - if authenticated?
              %li
                %a{ href: "/sessions/logout" }
                  ログアウトする

    = yield
```

## sessions/login templateを作る

```${root}/app/views/sessions/login.haml``` を作る。

```haml:login
.container
  %h1
    login
  
  = form_tag('/sessions/login', id: 'sessions_login', method: 'post', role: 'form', role: 'form') do
    .form-group
      %label.label(for='email') Login
      = text_field_tag :email, type: 'email', class: 'form-control', value: params[:email]
    .form-group
      %label.label(for='password') Password
      = password_field_tag :password, class: 'form-control'

    = submit_tag('Sign in', class: 'btn btn-default')
```

## Top pageを作る

index controllerを作る。名前はアレだが...

```
> padrino g controller index
```

## index controllerを整える

```ruby:app/controllers/index.rb
TestPadrinoWarden::App.controllers :index do
  get :index do
    render :index
  end
end
```

## index/index.haml を作る

```haml:index.haml
.container
  %h1
    Welcome to underground...
```

# ログインの実験

Padrinoのアプリケーションを立ち上げ、テストしてみる。

## アプリケーションの立ち上げ

Rackupで立ち上げ。

```
> bundle ex rackup
```

## ブラウザでアプリにアクセスする。

```
> open http://localhost:9292/
```

ログインページが開いた。

![Screen Shot 2014-07-14 at 23.47.27.png](https://qiita-image-store.s3.amazonaws.com/0/3985/ebcfcfc8-7f9e-3d5f-329c-996f907fcf01.png)

メールアドレスとパスワードを入力して、
Sign inボタンを押すと、indexページが開く。

![Screen Shot 2014-07-14 at 23.49.05.png](https://qiita-image-store.s3.amazonaws.com/0/3985/bb1d5bf6-3431-4243-1821-15d8d6d0e52c.png)

# 使ってみて

padrino-admin、気楽にアカウントを追加できるし、
roleの追加も行える。連携できるのは楽だ。
Wardenの組み込みはpadrino-wardenで問題なく行える。

```
current_user.first.role
```

などでroleについても取得できるし、色々使えそう。

# 成果物

以下のリポジトリに追加しておいた。

https://github.com/futoase/test-padrino-warden