s6x_auth_scaffold_generator 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1 @@
1
+ *.gem
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright 2011 Kouji Takao <kouji.takao@gmail.com>
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.rdoc ADDED
@@ -0,0 +1,93 @@
1
+ == S6x(Six) Auth Scaffold Generator
2
+
3
+ Sorry, Japanese only.
4
+
5
+ 「S6x(Six) Auth Scaffold Generator」(以下、s6x_auth_scaffold)はRails
6
+ 3.0向けのシンプルな認証機能をフルスクラッチで記述するためのgeneratorで
7
+ す。s6x_auth_scaffoldの目的はこれからRuby on Railsで開発する方がRailsに
8
+ おける認証の概要をソースコードレベルで理解することを手助けすることです。
9
+
10
+ s6x_auth_scaffoldは以下の機能を実現するソースコードを自動生成します。
11
+
12
+ * ログイン画面(/login)でログインIDとパスワードで認証。
13
+ * ユーザのモデル名はUserやEmployeeなど自由にしてできる。
14
+ * ログイン後はWelcome画面(root_url)を表示。
15
+ * Welcome画面をURLできる。
16
+ * /logoutにアクセスするとログアウトできる。
17
+ * ログアウトするとログイン画面を表示。このときログアウトした旨を表示。
18
+
19
+ ただし、ソースコードを簡単にすることを優先しているため以下のことはでき
20
+ ません。
21
+
22
+ * ユーザの作成はWeb上ではできない。
23
+
24
+ s6x_auth_scaffoldで基本を学んだ後はRailsが提供しているscaffoldのように
25
+ 自分で認証機能をカスタマイズしてもよいですが、ぜひDeviseなどの認証ライ
26
+ ブラリの導入を検討してみてください。
27
+
28
+ == ライセンス
29
+
30
+ MITライセンス
31
+
32
+ == 必要なソフトウェア
33
+
34
+ * Ruby 1.9.2-p290以降
35
+ * Ruby on Rails 3.0.10 (3.1以降では動作確認をしていない)
36
+
37
+ == インストール方法
38
+
39
+ gem install s6x_auth_scaffold_generator
40
+
41
+ == 使用方法
42
+
43
+ 新しいRailsプロジェクトを作成してデータベースの設定などを行います。
44
+
45
+ $ rails new auth_demo
46
+ $ cd auth_demo
47
+ $ bundle install
48
+ (DBの設定など)
49
+ $ rake db:create:all
50
+
51
+ s6x_auth_scaffoldで認証まわりのソースコードを自動生成します。
52
+
53
+ $ rails generate s6x_auth_scaffold User
54
+
55
+ rake db:migrateを実行してusersテーブルを作成します。
56
+
57
+ $ rake db:migrate
58
+
59
+ ついでに単体テストも実行します。
60
+
61
+ $ rake
62
+
63
+ 動作確認をするためにユーザを作成します。ここではログインIDがadmin、パス
64
+ ワードがadminのユーザを作成しています。
65
+
66
+ $ rails console
67
+ > User.create!(login: "admin", password: "admin")
68
+ > quit
69
+
70
+ サーバを起動して動作を確認します。/loginにアクセスしてログインします。
71
+ 「Welcome aboard」が表示されればs6x_auth_scaffoldがただしく動作していま
72
+ す。
73
+
74
+ $ rails server
75
+ (Webブラウザでlocalhost:3000/loginにアクセスする)
76
+
77
+ サーバを停止させます。
78
+
79
+ == これから
80
+
81
+ 自動再生されたファイルや変更されたファイルを確認してください。認証に最
82
+ 低限必要な機能が実装されているはずです。コード量は少ないので安心してく
83
+ ださい。また、単体テストも記述してあるため、今後の開発の参考になるはず
84
+ です。
85
+
86
+ 一通り確認できたらWelcome画面(Welcome#index)を作成してみてください。
87
+ Welcome画面にはログアウトのボタンやログインIDを表示してみてください。
88
+
89
+ <p><%= current_user.login %> <%= link_to "ログアウト", logout_path %></p>
90
+
91
+ 最後に氏名(name)、ふりがな(furigana)、メールアドレス(email)などのユーザ
92
+ の情報をUserモデルに追加してアプリケーションの要件を満たすように改良し
93
+ てみてください。
data/lib/USAGE ADDED
@@ -0,0 +1,10 @@
1
+ 説明:
2
+ 認証まわりのソースコードを自動生成する。
3
+ Rubyは1.9.2-p290、Railsは3.0.10を対象とする。
4
+ メインのplatformはWindows。
5
+ 言語は日本語のみ。
6
+
7
+ 使用例:
8
+ rails generate s6x_auth_scaffold User
9
+
10
+ 「User」には認証に必要なログインIDとパスワードを格納するモデル名を指定する。
@@ -0,0 +1,79 @@
1
+ # coding: utf-8
2
+ # 認証まわりのソースコードを自動生成するscaffoldの+s6x_auth_scaffold+。
3
+ # 現状、Rubyは1.9.2-p290、Railsは3.0.10を対象とする。
4
+ # また、メインのplatformはWindows。
5
+
6
+ require 'rails/generators'
7
+ require 'rails/generators/named_base'
8
+ require 'rails/generators/active_record/migration'
9
+
10
+ class S6xAuthScaffoldGenerator < Rails::Generators::NamedBase
11
+ include Rails::Generators::Migration
12
+ extend ActiveRecord::Generators::Migration
13
+
14
+ source_root File.expand_path('../templates', __FILE__)
15
+
16
+ class_option :root_to, default: "welcome#index", desc: "「root :to =>」に指定する文字列", aliases: "r"
17
+
18
+ def parse_options
19
+ @user_model_name = file_name.camelize
20
+ @user_model_file_name = file_name.underscore
21
+ @user_instance_name = file_name.underscore
22
+ @users_table_name = file_name.underscore.pluralize
23
+ end
24
+
25
+ def create_users_migration
26
+ migration_template "db/migrate/create_users.rb", "db/migrate/create_#{@users_table_name}.rb"
27
+ rescue Rails::Generators::Error => e
28
+ if options[:skip]
29
+ puts e.message
30
+ else
31
+ raise
32
+ end
33
+ end
34
+
35
+ def create_user_model
36
+ template "app/models/user.rb", "app/models/#{@user_model_file_name}.rb"
37
+ template "test/unit/user_test.rb", "test/unit/#{@user_model_file_name}_test.rb"
38
+ template "test/fixtures/users.yml", "test/fixtures/#{@users_table_name}.yml"
39
+ end
40
+
41
+ def create_sessions_controller
42
+ template "app/controllers/sessions_controller.rb"
43
+ template "test/functional/sessions_controller_test.rb"
44
+ copy_file "app/views/sessions/login.html.erb"
45
+ template "app/helpers/sessions_helper.rb"
46
+ end
47
+
48
+ def add_routes
49
+ route('match "login" => "sessions#login"')
50
+ route('match "logout" => "sessions#logout"')
51
+ route(%Q'root :to => "#{options[:root_to]}"')
52
+ end
53
+
54
+ def edit_application_controller
55
+ method_name = "current_#{@user_instance_name}"
56
+ dest_path = "app/controllers/application_controller.rb"
57
+ if ApplicationController.public_method_defined?(method_name.to_sym)
58
+ msg = "ApplicationController is already defined #{method_name} method: #{dest_path}"
59
+ if options[:skip]
60
+ puts msg
61
+ else
62
+ raise Rails::Generators::Error, msg
63
+ end
64
+ else
65
+ inject_into_class(dest_path, ApplicationController, "
66
+ # ログイン中のユーザを返す。
67
+ def #{method_name}
68
+ if session[:#{@user_instance_name}_id]
69
+ @current_#{@user_instance_name} ||= #{@user_model_name}.find(session[:#{@user_instance_name}_id])
70
+ end
71
+ return @current_#{@user_instance_name}
72
+ end
73
+
74
+ helper_method :current_#{@user_instance_name}
75
+
76
+ ".force_encoding("ASCII-8BIT")) # NOTE: force_encoding("ASCII-8BIT")はThorのバグを回避するため。
77
+ end
78
+ end
79
+ end
@@ -0,0 +1,25 @@
1
+ # coding: utf-8
2
+ # セッションを管理するコントローラ。
3
+ class SessionsController < ApplicationController
4
+ # ログイン。
5
+ def login
6
+ if session[:<%= @user_instance_name %>_id]
7
+ redirect_to(root_url, notice: "すでにログインしています。")
8
+ end
9
+ if params[:login] && params[:password]
10
+ <%= @user_instance_name %> = <%= @user_model_name %>.find_by_login(params[:login])
11
+ if <%= @user_instance_name %> && <%= @user_instance_name %>.authenticate(params[:password])
12
+ session[:<%= @user_instance_name %>_id] = <%= @user_instance_name %>.id
13
+ redirect_to(root_url, notice: "ログインしました。")
14
+ else
15
+ flash.now.alert = "ログインID、パスワードが間違っています。"
16
+ end
17
+ end
18
+ end
19
+
20
+ # ログアウト。
21
+ def logout
22
+ reset_session
23
+ redirect_to(login_path, notice: "ログアウトしました。")
24
+ end
25
+ end
@@ -0,0 +1,2 @@
1
+ module SessionsHelper
2
+ end
@@ -0,0 +1,57 @@
1
+ # coding: utf-8
2
+ require 'securerandom'
3
+ require 'digest/sha1'
4
+
5
+ # ユーザを表現する。
6
+ class <%= @user_model_name %> < ActiveRecord::Base
7
+ attr_accessor :password
8
+
9
+ attr_accessible :login, :password
10
+
11
+ validates_presence_of :login
12
+ validates_uniqueness_of :login
13
+ # validates_length_of :login, within: 3..40
14
+
15
+ validates_presence_of :password, on: :create
16
+ # validates_length_of :password, within: 5..40
17
+
18
+ # パスワードの確認を行う場合は以下のコメントをはずす。
19
+ # attr_accessor :password_confirmation
20
+ # validates_confirmation_of :password
21
+ # validates_presence_of :password_confirmation, on: :create
22
+
23
+ before_save do
24
+ if @password
25
+ if !self.salt?
26
+ self.salt = random_string(10)
27
+ end
28
+ self.password_digest = digest(@password, self.salt)
29
+ end
30
+ end
31
+
32
+ # パスワード+password+で認証する。認証に成功した場合trueを返す。失敗した場合はfalseを返す。
33
+ # 使用例)
34
+ # <%= @user_instance_name %> = <%= @user_model_name %>.find_by_login(params[:login])
35
+ # if <%= @user_instance_name %>.authenticate(params[:password])
36
+ # # 認証に成功した場合の処理。
37
+ # else
38
+ # # 認証に失敗した場合の処理。
39
+ # end
40
+ def authenticate(password)
41
+ return digest(password, salt) == password_digest
42
+ end
43
+
44
+ private
45
+
46
+ # ランダムな文字列を生成します。
47
+ # Deviseライブラリのdevise/lib/devise.rbのDevise.friendly_tokenメソッドの実装を使っています。
48
+ # http://blog.plataformatec.com.br/tag/devise/
49
+ def random_string(length)
50
+ return SecureRandom.base64(15).tr('+/=lIO0', 'pqrsxyz')[0, length]
51
+ end
52
+
53
+ # パスワード+password+とランダムな文字列+salt+から、パスワード認証のためのハッシュ値を求める。
54
+ def digest(password, salt)
55
+ return Digest::SHA1.hexdigest(password + salt)
56
+ end
57
+ end
@@ -0,0 +1,15 @@
1
+ <h1>ログイン</h1>
2
+
3
+ <%= form_tag login_path do %>
4
+ <div class="field">
5
+ <%= label_tag "ログインID" %>
6
+ <%= text_field_tag :login, params[:login] %>
7
+ </div>
8
+ <div class="field">
9
+ <%= label_tag "パスワード" %>
10
+ <%= password_field_tag :password %>
11
+ </div>
12
+ <div class="actions">
13
+ <%= submit_tag "ログイン" %>
14
+ </div>
15
+ <% end %>
@@ -0,0 +1,22 @@
1
+ # coding: utf-8
2
+ # <%= @users_table_name %>テーブルを作成する。
3
+ # loginカラムはログインに使用するIDを格納する。
4
+ # password_digestカラムはパスワードとsaltカラムを元に生成したハッシュ値を格納する。
5
+ # saltカラムはパスワードからハッシュ値を求めるときに使うランダムな値を格納する。
6
+ class Create<%= @users_table_name.camelize %> < ActiveRecord::Migration
7
+ def self.up
8
+ create_table :<%= @users_table_name %> do |t|
9
+ t.string :login, limit: 40
10
+ t.string :password_digest
11
+ t.string :salt
12
+
13
+ # ここに名前(name)、ふりがな(furigana)、メールアドレス(email)などを追加します。
14
+
15
+ t.timestamps
16
+ end
17
+ end
18
+
19
+ def self.down
20
+ drop_table :<%= @users_table_name %>
21
+ end
22
+ end
@@ -0,0 +1,13 @@
1
+ # Read about fixtures at http://ar.rubyonrails.org/classes/Fixtures.html
2
+
3
+ admin:
4
+ id: 1
5
+ login: admin
6
+ password_digest: "30a389673b7ee019c7fc8201e4a5e83a0f0c9d62" # admin
7
+ salt: "4NsTR61PRi"
8
+
9
+ <% login = "#{@user_instance_name}001" %><%= login %>:
10
+ id: 2
11
+ login: <%= login %>
12
+ password_digest: "<%= Digest::SHA1.hexdigest(login + "r8i1tsR1jn") %>" # <%= login %>
13
+ salt: "r8i1tsR1jn"
@@ -0,0 +1,38 @@
1
+ # coding: utf-8
2
+ require 'test_helper'
3
+
4
+ class SessionsControllerTest < ActionController::TestCase
5
+ fixtures :<%= @users_table_name %>
6
+
7
+ def setup
8
+ @request.session = ActionController::TestSession.new
9
+ end
10
+
11
+ test "ログイン画面を表示" do
12
+ get :login
13
+ assert_response :success
14
+ end
15
+
16
+ test "ログイン中にログイン画面を表示しようとするとWelcome画面にリダイレクト" do
17
+ @request.session[:<%= @user_instance_name %>_id] = <%= @users_table_name %>(:admin).id
18
+ get :login
19
+ assert_redirected_to root_url
20
+ end
21
+
22
+ test "ログインに成功するとWelcome画面にリダイレクト" do
23
+ post :login, login: "admin", password: "admin"
24
+ assert_redirected_to root_url
25
+ end
26
+
27
+ test "ログインに失敗するとログイン画面を表示" do
28
+ post :login, login: "admin", password: "<%= @user_instance_name %>001"
29
+ assert_response :success
30
+ end
31
+
32
+ test "ログアウト後はログイン画面にリダイレクト" do
33
+ @request.session[:<%= @user_instance_name %>_id] = <%= @users_table_name %>(:admin).id
34
+ get :logout
35
+ assert_redirected_to login_url
36
+ assert_equal({}, @request.session)
37
+ end
38
+ end
@@ -0,0 +1,28 @@
1
+ # coding: utf-8
2
+ require 'test_helper'
3
+
4
+ class <%= @user_model_name %>Test < ActiveSupport::TestCase
5
+ fixtures :<%= @users_table_name %>
6
+
7
+ test "同じログインIDは指定できない" do
8
+ # 新規作成
9
+ assert_raise(ActiveRecord::RecordInvalid) do
10
+ <%= @user_model_name %>.create!(login: "<%= @user_instance_name %>001", password: "password")
11
+ end
12
+
13
+ # 更新
14
+ assert_raise(ActiveRecord::RecordInvalid) do
15
+ <%= @user_instance_name %> = <%= @users_table_name %>(:<%= @user_instance_name %>001)
16
+ <%= @user_instance_name %>.login = "admin"
17
+ <%= @user_instance_name %>.save!
18
+ end
19
+ end
20
+
21
+ test "authenticateを使った認証" do
22
+ assert_equal(true, <%= @users_table_name %>(:admin).authenticate("admin"))
23
+ assert_equal(false, <%= @users_table_name %>(:admin).authenticate("<%= @user_instance_name %>001"))
24
+
25
+ assert_equal(true, <%= @users_table_name %>(:<%= @user_instance_name %>001).authenticate("<%= @user_instance_name %>001"))
26
+ assert_equal(false, <%= @users_table_name %>(:<%= @user_instance_name %>001).authenticate("admin"))
27
+ end
28
+ end
@@ -0,0 +1,17 @@
1
+ Gem::Specification.new do |s|
2
+ s.name = "s6x_auth_scaffold_generator"
3
+ s.version = "0.0.1"
4
+ s.platform = Gem::Platform::RUBY
5
+ s.required_ruby_version = '>= 1.9.2'
6
+ s.summary = "Really simple authentication scaffold generator for Rails"
7
+ s.email = "kouji.takao@gmail.com"
8
+ s.homepage = "http://github.com/takaokouji/s6x_auth_scaffold"
9
+ s.description = "Really simple authentication scaffold generator for Rails"
10
+ s.authors = ["Kouji Takao (Kody)"]
11
+
12
+ s.files = `git ls-files`.split("\n")
13
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
14
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
15
+
16
+ s.add_dependency("rails", "~> 3.0.0")
17
+ end
metadata ADDED
@@ -0,0 +1,69 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: s6x_auth_scaffold_generator
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Kouji Takao (Kody)
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2011-11-20 00:00:00.000000000Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rails
16
+ requirement: &2152014740 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ~>
20
+ - !ruby/object:Gem::Version
21
+ version: 3.0.0
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: *2152014740
25
+ description: Really simple authentication scaffold generator for Rails
26
+ email: kouji.takao@gmail.com
27
+ executables: []
28
+ extensions: []
29
+ extra_rdoc_files: []
30
+ files:
31
+ - .gitignore
32
+ - MIT-LICENSE
33
+ - README.rdoc
34
+ - lib/USAGE
35
+ - lib/s6x_auth_scaffold_generator.rb
36
+ - lib/templates/app/controllers/sessions_controller.rb
37
+ - lib/templates/app/helpers/sessions_helper.rb
38
+ - lib/templates/app/models/user.rb
39
+ - lib/templates/app/views/sessions/login.html.erb
40
+ - lib/templates/db/migrate/create_users.rb
41
+ - lib/templates/test/fixtures/users.yml
42
+ - lib/templates/test/functional/sessions_controller_test.rb
43
+ - lib/templates/test/unit/user_test.rb
44
+ - s6x_auth_scaffold_generator.gemspec
45
+ homepage: http://github.com/takaokouji/s6x_auth_scaffold
46
+ licenses: []
47
+ post_install_message:
48
+ rdoc_options: []
49
+ require_paths:
50
+ - lib
51
+ required_ruby_version: !ruby/object:Gem::Requirement
52
+ none: false
53
+ requirements:
54
+ - - ! '>='
55
+ - !ruby/object:Gem::Version
56
+ version: 1.9.2
57
+ required_rubygems_version: !ruby/object:Gem::Requirement
58
+ none: false
59
+ requirements:
60
+ - - ! '>='
61
+ - !ruby/object:Gem::Version
62
+ version: '0'
63
+ requirements: []
64
+ rubyforge_project:
65
+ rubygems_version: 1.8.10
66
+ signing_key:
67
+ specification_version: 3
68
+ summary: Really simple authentication scaffold generator for Rails
69
+ test_files: []