openskip-repim 0.1.8

Sign up to get free protection for your applications and to get access to all the features.
data/ChangeLog ADDED
@@ -0,0 +1,21 @@
1
+ == 0.1.7 / 2009-05-22
2
+ * fix up old style rspec test (generator's)
3
+ * add how to use. (patch from yhara)
4
+
5
+ == 0.1.6 / 2009-04-02
6
+ * change default after_create_url to root_url
7
+
8
+ == 0.1.5 / 2009-03-26
9
+ * add gem dependency information as plugin.
10
+ * remove unuse test from generator.
11
+
12
+ == 0.1.4 / 2009-03-25
13
+ * add dependency to open_id_authentication gems on http://github.com/moro/open_id_authentication
14
+
15
+ == 0.1.3 / 2009-03-24
16
+ * fix typo
17
+
18
+ == 0.0.1 / 2009-03-04
19
+
20
+ * initial release
21
+
data/README.rdoc ADDED
@@ -0,0 +1,43 @@
1
+
2
+ = repim
3
+
4
+ == Description
5
+
6
+ repim (RElying Party In Minutes) is a rails plugin to
7
+ create websites using OpenID authentication easily.
8
+
9
+ == Installation
10
+
11
+ === Archive Installation
12
+
13
+ rake install
14
+
15
+ === Gem Installation
16
+
17
+ gem install moro-repim
18
+
19
+
20
+ == Features/Problems
21
+
22
+
23
+ == Synopsis
24
+
25
+ Generate template files
26
+
27
+ $ ruby script/generate relying_party Sessions name:string display_name:string
28
+
29
+ Edit config/environment.rb to load repim gem
30
+
31
+ config.gem 'moro-repim', :lib => 'repim', :source => 'http://gems.github.com/'
32
+
33
+ Start server
34
+
35
+ $ ruby script/server
36
+
37
+ You will see the login form in http://localhost:3000/signin .
38
+
39
+ == Copyright
40
+
41
+ Author:: MOROHASHI Kyosuke <moronatural@gmail.com>
42
+ Copyright:: Copyright (c) 2009 MOROHASHI Kyosuke
43
+ License:: MIT
data/Rakefile ADDED
@@ -0,0 +1,184 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+ require 'rake/clean'
4
+ require 'rake/testtask'
5
+ require 'rake/packagetask'
6
+ require 'rake/gempackagetask'
7
+ require 'rake/rdoctask'
8
+ require 'fileutils'
9
+ require 'spec/rake/spectask'
10
+ require 'lib/repim'
11
+ include FileUtils
12
+
13
+ use_rubyforge = false
14
+ NAME = ENV["GEMNAME"] || "repim"
15
+ AUTHOR = "MOROHASHI Kyosuke"
16
+ EMAIL = "moronatural@gmail.com"
17
+ DESCRIPTION = "Relying Party in minutes."
18
+
19
+ if use_rubyforge
20
+ require 'rake/contrib/rubyforgepublisher'
21
+ require 'rake/contrib/sshpublisher'
22
+ RUBYFORGE_PROJECT = "repim"
23
+ HOMEPAGE = "http://#{RUBYFORGE_PROJECT}.rubyforge.org"
24
+ else
25
+ HOMEPAGE = "http://github.com/moro/#{NAME}/"
26
+ end
27
+ BIN_FILES = %w( )
28
+
29
+ VERS = Repim::Version
30
+ REV = File.read(".svn/entries")[/committed-rev="(d+)"/, 1] rescue nil
31
+ CLEAN.include ['**/.*.sw?', '*.gem', '.config']
32
+ RDOC_OPTS = [
33
+ '--title', "#{NAME} documentation",
34
+ "--charset", "utf-8",
35
+ "--opname", "index.html",
36
+ "--line-numbers",
37
+ "--main", "README.rdoc",
38
+ "--inline-source",
39
+ ]
40
+
41
+ task :default => [:spec]
42
+ task :package => [:clean]
43
+
44
+ desc "Run all specs in spec directory"
45
+ Spec::Rake::SpecTask.new(:spec) do |t|
46
+ t.spec_opts = %w[--colour --format progress --loadby --reverse]
47
+ t.spec_files = FileList['spec/**/*_spec.rb']
48
+ end
49
+
50
+ namespace :spec do
51
+ desc "Run both plugin's and sample_app's"
52
+ task :all => %w[spec spec:sample_app]
53
+
54
+ desc "Run Sample app's tests"
55
+ task :sample_app do
56
+ begin
57
+ Dir.chdir("integration/sample-app") do
58
+ unless File.directory?("./vendor/plugins/open_id_authentication")
59
+ system(*%w[script/plugin install git://github.com/rails/open_id_authentication.git])
60
+ end
61
+ system("script/generate relying_party sessions")
62
+ system($0, "db:migrate")
63
+ system($0, "spec")
64
+ end
65
+ ensure
66
+ Rake::Task["spec:sample_app:clean"].invoke
67
+ end
68
+ end
69
+
70
+ namespace :sample_app do
71
+ desc "Clean Sample app's generated datas"
72
+ task :clean do
73
+ Dir.chdir("integration/sample-app") do
74
+ system("script/destroy relying_party sessions")
75
+ FileUtils.rm_f(["db/development.sqlite3", "db/test.sqlite3"])
76
+ end
77
+ end
78
+ end
79
+ end
80
+
81
+ spec = Gem::Specification.new do |s|
82
+ s.name = NAME
83
+ s.version = VERS
84
+ s.platform = Gem::Platform::RUBY
85
+ s.has_rdoc = false
86
+ s.extra_rdoc_files = ["README.rdoc", "ChangeLog"]
87
+ s.rdoc_options += RDOC_OPTS + ['--exclude', '^(examples|extras)/']
88
+ s.summary = DESCRIPTION
89
+ s.description = DESCRIPTION
90
+ s.author = AUTHOR
91
+ s.email = EMAIL
92
+ s.homepage = HOMEPAGE
93
+ s.executables = BIN_FILES
94
+ s.rubyforge_project = RUBYFORGE_PROJECT if use_rubyforge
95
+ s.bindir = "bin"
96
+ s.require_path = "lib"
97
+ s.test_files = Dir["test/*_test.rb"]
98
+
99
+ s.add_dependency('moro-open_id_authentication')
100
+ #s.required_ruby_version = '>= 1.8.2'
101
+
102
+ s.files = %w(README.rdoc ChangeLog Rakefile) +
103
+ Dir.glob("{bin,doc,test,lib,templates,generators,extras,website,script}/**/*") +
104
+ Dir.glob("ext/**/*.{h,c,rb}") +
105
+ Dir.glob("examples/**/*.rb") +
106
+ Dir.glob("tools/*.rb") +
107
+ Dir.glob("rails/*.rb")
108
+
109
+ s.extensions = FileList["ext/**/extconf.rb"].to_a
110
+ end
111
+
112
+ Rake::GemPackageTask.new(spec) do |p|
113
+ p.need_tar = true
114
+ p.gem_spec = spec
115
+ end
116
+
117
+ task :install do
118
+ name = "#{NAME}-#{VERS}.gem"
119
+ sh %{rake package}
120
+ sh %{gem install pkg/#{name}}
121
+ end
122
+
123
+ task :uninstall => [:clean] do
124
+ sh %{gem uninstall #{NAME}}
125
+ end
126
+
127
+ desc 'Show information about the gem.'
128
+ task :debug_gem do
129
+ puts spec.to_ruby
130
+ end
131
+
132
+ desc 'Update gem spec'
133
+ task :gemspec do
134
+ open("#{NAME}.gemspec", 'w').write spec.to_ruby
135
+ end
136
+
137
+
138
+ Rake::RDocTask.new do |rdoc|
139
+ rdoc.rdoc_dir = 'html'
140
+ rdoc.options += RDOC_OPTS
141
+ rdoc.template = "resh"
142
+ #rdoc.template = "#{ENV['template']}.rb" if ENV['template']
143
+ if ENV['DOC_FILES']
144
+ rdoc.rdoc_files.include(ENV['DOC_FILES'].split(/,\s*/))
145
+ else
146
+ rdoc.rdoc_files.include('README', 'ChangeLog')
147
+ rdoc.rdoc_files.include('lib/**/*.rb')
148
+ rdoc.rdoc_files.include('ext/**/*.c')
149
+ end
150
+ end
151
+
152
+ if use_rubyforge
153
+ desc "Publish to RubyForge"
154
+ task :rubyforge => [:rdoc, :package] do
155
+ require 'rubyforge'
156
+ Rake::RubyForgePublisher.new(RUBYFORGE_PROJECT, 'moro').upload
157
+ end
158
+
159
+ desc 'Package and upload the release to rubyforge.'
160
+ task :release => [:clean, :package] do |t|
161
+ v = ENV["VERSION"] or abort "Must supply VERSION=x.y.z"
162
+ abort "Versions don't match #{v} vs #{VERS}" unless v == VERS
163
+ pkg = "pkg/#{NAME}-#{VERS}"
164
+
165
+ require 'rubyforge'
166
+ rf = RubyForge.new.configure
167
+ puts "Logging in"
168
+ rf.login
169
+
170
+ c = rf.userconfig
171
+ # c["release_notes"] = description if description
172
+ # c["release_changes"] = changes if changes
173
+ c["preformatted"] = true
174
+
175
+ files = [
176
+ "#{pkg}.tgz",
177
+ "#{pkg}.gem"
178
+ ].compact
179
+
180
+ puts "Releasing #{NAME} v. #{VERS}"
181
+ rf.add_release RUBYFORGE_PROJECT, NAME, VERS, *files
182
+ end
183
+ end
184
+
@@ -0,0 +1,115 @@
1
+ class RelyingPartyGenerator < Rails::Generator::NamedBase
2
+ def add_options!(opt)
3
+ opt.on("--skip-plugins-spec",
4
+ "Do'nt copy application_controller_spec.rb and #{plural_name}_controller_spec.rb, default is #{!using_rspec?}"){|v| options[:skip_sessions_spec] = true }
5
+ opt.on("--user-class=klass",
6
+ "Specify User class name defailt is [User]"){|v| options[:user_klass] = "User" }
7
+ opt.on("--user-management=generation_type",
8
+ "'model' for generate (rspec_)model, 'singnup' for controller using Repim::Signup. default is 'signup'"){|v| options[:user_model_only] = (v == "model") }
9
+ opt.on("--openid-migration=migration_name",
10
+ "Specify openid migration name, default is 'open_id_authentication_tables'. If value is 'none' generate nothing.") do |v|
11
+ options[:openid_migration] = v
12
+ end
13
+ end
14
+
15
+ def manifest
16
+ controller_file_name = plural_name + "_controller"
17
+ controller_class_name = controller_file_name.camelize
18
+
19
+ record do |m|
20
+ m.file "sessions_controller.rb", "app/controllers/#{controller_file_name}.rb"
21
+ assign_session_routing(singular_name, m)
22
+
23
+ m.directory "app/views/layouts"
24
+ m.file "views/layouts/sessions.html.erb", "app/views/layouts/#{plural_name}.html.erb"
25
+
26
+ m.directory "app/views/#{plural_name}"
27
+ m.file "views/sessions/new.html.erb", "app/views/#{plural_name}/new.html.erb"
28
+
29
+ %w[public/images/openid-login.gif public/stylesheets/repim.css].each do |asset|
30
+ m.directory File.dirname(asset)
31
+ m.file asset, asset
32
+ end
33
+
34
+ unless options[:skip_sessions_spec]
35
+ m.directory "spec/controllers"
36
+ m.file "spec/application_controller_spec.rb", "spec/controllers/application_controller_spec.rb"
37
+ m.file "spec/sessions_controller_spec.rb", "spec/controllers/#{controller_file_name}_spec.rb"
38
+
39
+ m.directory "spec/routing"
40
+ m.file "spec/sessions_routing_spec.rb", "spec/routing/#{plural_name}_routing_spec.rb"
41
+ end
42
+
43
+ generate_user_management(m, !options[:skip_sessions_spec]) unless options[:user_model_only]
44
+ m.dependency(care_rspec("model"), [user_klass_name, "identity_url:string", @args].flatten.compact)
45
+
46
+ # FIXME very veriy dirty
47
+ # "sleep 3" is for changing timestamp of 'create_user' or 'open_id_authentication_tables'
48
+ if options[:command] == :create
49
+ m.gsub_file(app_controller, /(^\s*helper\s.*?$)/mi) do |ms|
50
+ sleep 3
51
+ "#{ms}\n include Repim::Application"
52
+ end
53
+ else
54
+ m.gsub_file(app_controller, /(^\s*include Repim::Application\s*$)/mi){|m| "" }
55
+ end
56
+
57
+ unless options[:openid_migration] == "none"
58
+ name = options[:openid_migration] || "open_id_authentication_tables"
59
+ m.dependency("open_id_authentication_tables", [name])
60
+ end
61
+ end
62
+ end
63
+
64
+ private
65
+ def app_controller
66
+ %w[application_controller application].
67
+ map{|f| "app/controllers/#{f}.rb" }.
68
+ detect{|c| File.exists?(File.expand_path(c, RAILS_ROOT)) }
69
+ end
70
+
71
+ def care_rspec(base); using_rspec? ? "rspec_#{base}" : base end
72
+
73
+ def using_rspec?; File.directory?( File.expand_path("spec", RAILS_ROOT) ) end
74
+
75
+ def assign_session_routing(name, manifest)
76
+ sentinel = 'ActionController::Routing::Routes.draw do |map|'
77
+
78
+ logger.route "map.resource #{name}"
79
+ route = <<EOS
80
+
81
+ map.signin '/signin', :controller => 'sessions', :action => 'new'
82
+ map.signout '/signout', :controller => 'sessions', :action => 'destroy'
83
+ map.resource :session
84
+ EOS
85
+
86
+ unless options[:pretend]
87
+ if options[:command] == :create
88
+ manifest.gsub_file 'config/routes.rb', /(#{Regexp.escape(sentinel)})/mi do |match|
89
+ "#{match}#{route}"
90
+ end
91
+ else
92
+ manifest.gsub_file 'config/routes.rb', route, ''
93
+ end
94
+ end
95
+ end
96
+
97
+ def user_klass_name
98
+ options[:user_klass] || "User"
99
+ end
100
+ def generate_user_management(m, with_spec = true)
101
+ users = user_klass_name.pluralize.underscore
102
+ user_controller_name = users + "_controller"
103
+
104
+ m.route_resources users.to_sym
105
+ m.file("users_controller.rb", "app/controllers/#{user_controller_name}.rb")
106
+
107
+ m.directory "app/views/#{users}"
108
+ m.template "views/users/new.html.erb", "app/views/#{users}/new.html.erb", :assigns => {:user => user_klass_name.underscore, :users => users}
109
+
110
+ if with_spec
111
+ m.file "spec/users_controller_spec.rb", "spec/controllers/#{user_controller_name}_spec.rb"
112
+ m.file "spec/users_routing_spec.rb", "spec/routing/#{users}_routing_spec.rb"
113
+ end
114
+ end
115
+ end
@@ -0,0 +1,9 @@
1
+ div#login-or-signup input[name=openid_url] {
2
+ font-size: 16px;
3
+ width: 20em;
4
+ padding: 2px 2px 2px 20px;
5
+ background-image: url("../images/openid-login.gif");
6
+ background-repeat: no-repeat;
7
+ background-attachment: scroll;
8
+ background-position: 0 50%;
9
+ }
@@ -0,0 +1,4 @@
1
+ class SessionsController < ApplicationController
2
+ include OpenIdAuthentication
3
+ include Repim::RelyingParty
4
+ end
@@ -0,0 +1,17 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+
3
+ describe ApplicationController do
4
+ before :all do
5
+ ApplicationController.user_klass = mock("User-Klass")
6
+ end
7
+ describe "#logged in" do
8
+ before do
9
+ session[:user_id] = 12345
10
+ ApplicationController.user_klass.should_receive(:find_by_id).with(12345).and_return(@user = mock("user"))
11
+ end
12
+
13
+ it{ controller.should be_signed_in }
14
+ it{ controller.current_user.should == @user }
15
+ end
16
+ end
17
+
@@ -0,0 +1,79 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+
3
+ describe SessionsController do
4
+ before :all do
5
+ SessionsController.user_klass = mock("User-Klass")
6
+ end
7
+
8
+ #Delete this example and add some real ones
9
+ it "should use SessionsController" do
10
+ controller.should be_an_instance_of(SessionsController)
11
+ end
12
+
13
+ it "get new should be success" do
14
+ get :new
15
+ response.should be_success
16
+ end
17
+
18
+ def mock_out_authenticattion(controller, url, is_success)
19
+ result = mock("result")
20
+ result.should_receive(:successful?).and_return is_success
21
+
22
+ controller.
23
+ should_receive(:authenticate_with_open_id).
24
+ with(url, an_instance_of(Hash)).
25
+ and_return{|url, ax, block| block.call(result, url, ax) }
26
+ end
27
+
28
+ describe "authentication success" do
29
+ before do
30
+ url = "---openid-url---"
31
+
32
+ @user = mock("user", :id => 12345)
33
+ SessionsController.user_klass.should_receive(:find_by_identity_url).with(url).and_return(@user)
34
+
35
+ controller.should_receive(:root_path).and_return("/")
36
+ mock_out_authenticattion(controller, url, true)
37
+
38
+ post :create, :openid_url =>url
39
+ end
40
+
41
+ it{ response.should redirect_to("/") }
42
+ it{ session[:user_id].should == 12345 }
43
+ it{ controller.current_user.should == @user }
44
+ it{ controller.should be_signed_in }
45
+ end
46
+
47
+ describe "authentication success but user not found then render users/new" do
48
+ before do
49
+ url = "---openid-url---"
50
+ SessionsController.user_klass.should_receive(:find_by_identity_url).with(url).and_return(nil)
51
+ SessionsController.user_klass.should_receive(:new).with({}).and_return(@user = mock("user"))
52
+
53
+ mock_out_authenticattion(controller, url, true)
54
+
55
+ post :create, :openid_url =>url
56
+ end
57
+
58
+ it{ response.should render_template("users/new") }
59
+ it{ controller.current_user.should be_nil }
60
+ it{ controller.should_not be_signed_in }
61
+ it{ assigns[:user].should == @user }
62
+ end
63
+
64
+ describe "authentication failed" do
65
+ before do
66
+ url = "---openid-url---"
67
+
68
+ mock_out_authenticattion(controller, url, false)
69
+
70
+ post :create, :openid_url =>url
71
+ end
72
+
73
+ it{ response.should render_template("sessions/new") }
74
+ it{ assigns[:user].should be_nil }
75
+ it{ controller.current_user.should be_nil }
76
+ it{ session[:user_id].should be_nil }
77
+ it{ flash[:error].should_not be_blank }
78
+ end
79
+ end
@@ -0,0 +1,43 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+
3
+ describe SessionsController do
4
+ describe "route generation" do
5
+ it "should map #new -> /signin" do
6
+ route_for(:controller => "sessions", :action => "new").should == "/signin"
7
+ end
8
+
9
+ it "should map #destroy -> /signout" do
10
+ route_for(:controller => "sessions", :action => "destroy").should == {:path => "/signout", :method => "DELETE"}
11
+ end
12
+
13
+ it "should map #create" do
14
+ route_for(:controller => "sessions", :action => "create").should == {:path => "/session", :method => "POST"}
15
+ end
16
+ end
17
+
18
+ describe "route recognition" do
19
+ it "should generate params for #new" do
20
+ params_from(:get, "/signin").should == {:controller => "sessions", :action => "new"}
21
+ end
22
+
23
+ it "should generate params for #new" do
24
+ params_from(:get, "/session/new").should == {:controller => "sessions", :action => "new"}
25
+ end
26
+
27
+ it "should generate params for #create" do
28
+ params_from(:post, "/session").should == {:controller => "sessions", :action => "create"}
29
+ end
30
+
31
+ it "should generate params for #show (JS)" do
32
+ params_from(:get, "/session.js").should == {:controller => "sessions", :action => "show", :format => "js"}
33
+ end
34
+
35
+ it "should generate params for #destroy" do
36
+ params_from(:get, "/signout").should == {:controller => "sessions", :action => "destroy"}
37
+ end
38
+
39
+ it "should generate params for #destroy" do
40
+ params_from(:delete, "/session").should == {:controller => "sessions", :action => "destroy"}
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,98 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+
3
+ describe UsersController do
4
+ def mock_user(stubs={})
5
+ @mock_user ||= mock_model(User, stubs)
6
+ end
7
+
8
+ describe "responding to GET index" do
9
+ before do
10
+ controller.stub!(:authenticate).and_return true
11
+ end
12
+ it "should expose all users as @users" do
13
+ User.should_receive(:find).with(:all).and_return([mock_user])
14
+ get :index
15
+ assigns[:users].should == [mock_user]
16
+ end
17
+
18
+ describe "with mime type of xml" do
19
+ it "should render all users as xml" do
20
+ request.env["HTTP_ACCEPT"] = "application/xml"
21
+ User.should_receive(:find).with(:all).and_return(users = mock("Array of Users"))
22
+ users.should_receive(:to_xml).and_return("generated XML")
23
+ get :index
24
+ response.body.should == "generated XML"
25
+ end
26
+ end
27
+ end
28
+
29
+ describe "responding to GET show" do
30
+ before do
31
+ controller.stub!(:authenticate).and_return true
32
+ end
33
+
34
+ it "should expose the requested user as @user" do
35
+ User.should_receive(:find).with("37").and_return(mock_user)
36
+ get :show, :id => "37"
37
+ assigns[:user].should equal(mock_user)
38
+ end
39
+
40
+ describe "with mime type of xml" do
41
+ it "should render the requested user as xml" do
42
+ request.env["HTTP_ACCEPT"] = "application/xml"
43
+ User.should_receive(:find).with("37").and_return(mock_user)
44
+ mock_user.should_receive(:to_xml).and_return("generated XML")
45
+ get :show, :id => "37"
46
+ response.body.should == "generated XML"
47
+ end
48
+ end
49
+ end
50
+
51
+ describe "responding to POST create" do
52
+ describe "with valid params" do
53
+ before do
54
+ User.should_receive(:new).with({'these' => 'params'}).and_return(mock_user(:save => true))
55
+
56
+ @identity_url = session[:identity_url] = "http://moro.openid.example.com/"
57
+ mock_user.should_receive(:identity_url=).with(@identity_url)
58
+
59
+ post :create, :user => {:these => 'params'}
60
+ end
61
+
62
+ it "should expose a newly created user as @user" do
63
+ assigns(:user).should equal(mock_user)
64
+ end
65
+
66
+ it "session[:identity_url] should be removed" do
67
+ session[:identity_url].should be_blank
68
+ end
69
+
70
+ it "should redirect to the created user" do
71
+ response.should redirect_to(user_url(mock_user))
72
+ end
73
+ end
74
+
75
+ describe "with invalid params" do
76
+ before do
77
+ User.stub!(:new).with({'these' => 'params'}).and_return(mock_user(:save => false))
78
+
79
+ @identity_url = session[:identity_url] = "http://moro.openid.example.com/"
80
+ mock_user.should_receive(:identity_url=).with(@identity_url)
81
+
82
+ post :create, :user => {:these => 'params'}
83
+ end
84
+
85
+ it "should expose a newly created but unsaved user as @user" do
86
+ assigns(:user).should equal(mock_user)
87
+ end
88
+
89
+ it "should re-render the 'new' template" do
90
+ response.should render_template('new')
91
+ end
92
+
93
+ it "session[:identity_url] should == original" do
94
+ session[:identity_url].should == @identity_url
95
+ end
96
+ end
97
+ end
98
+ end
@@ -0,0 +1,59 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+
3
+ describe UsersController do
4
+ describe "route generation" do
5
+ it "should map #index" do
6
+ route_for(:controller => "users", :action => "index").should == {:path => "/users", :method => "GET"}
7
+ end
8
+
9
+ it "should map #new" do
10
+ route_for(:controller => "users", :action => "new").should == {:path => "/users/new", :method => "GET"}
11
+ end
12
+
13
+ it "should map #show" do
14
+ route_for(:controller => "users", :action => "show", :id => "1").should == {:path => "/users/1", :method => "GET"}
15
+ end
16
+
17
+ it "should map #edit" do
18
+ route_for(:controller => "users", :action => "edit", :id => "1").should == {:path => "/users/1/edit", :method => "GET"}
19
+ end
20
+
21
+ it "should map #update" do
22
+ route_for(:controller => "users", :action => "update", :id => "1").should == {:path => "/users/1", :method => "PUT"}
23
+ end
24
+
25
+ it "should map #destroy" do
26
+ route_for(:controller => "users", :action => "destroy", :id => "1").should == {:path => "/users/1", :method => "DELETE"}
27
+ end
28
+ end
29
+
30
+ describe "route recognition" do
31
+ it "should generate params for #index" do
32
+ params_from(:get, "/users").should == {:controller => "users", :action => "index"}
33
+ end
34
+
35
+ it "should generate params for #new" do
36
+ params_from(:get, "/users/new").should == {:controller => "users", :action => "new"}
37
+ end
38
+
39
+ it "should generate params for #create" do
40
+ params_from(:post, "/users").should == {:controller => "users", :action => "create"}
41
+ end
42
+
43
+ it "should generate params for #show" do
44
+ params_from(:get, "/users/1").should == {:controller => "users", :action => "show", :id => "1"}
45
+ end
46
+
47
+ it "should generate params for #edit" do
48
+ params_from(:get, "/users/1/edit").should == {:controller => "users", :action => "edit", :id => "1"}
49
+ end
50
+
51
+ it "should generate params for #update" do
52
+ params_from(:put, "/users/1").should == {:controller => "users", :action => "update", :id => "1"}
53
+ end
54
+
55
+ it "should generate params for #destroy" do
56
+ params_from(:delete, "/users/1").should == {:controller => "users", :action => "destroy", :id => "1"}
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,27 @@
1
+ class UsersController < ApplicationController
2
+ include Repim::Signup
3
+
4
+ def index
5
+ @users = User.find(:all)
6
+
7
+ respond_to do |format|
8
+ format.html
9
+ format.xml { render :xml => @users }
10
+ end
11
+ end
12
+
13
+ def show
14
+ @user = User.find(params[:id])
15
+
16
+ respond_to do |format|
17
+ format.html
18
+ format.xml { render :xml => @user }
19
+ end
20
+ end
21
+
22
+ # uncomment and edit this to change redirected url after signup.
23
+ # private
24
+ # def after_create_url
25
+ # user_url(current_user)
26
+ # end
27
+ end
@@ -0,0 +1,18 @@
1
+ <html>
2
+ <head>
3
+ <%= stylesheet_link_tag "repim" %>
4
+ <%= javascript_include_tag :defaults %>
5
+ </head>
6
+ <body>
7
+ <div id="header">
8
+ <% if signed_in? -%>
9
+ <span class="current-user"> Logged in as <%= current_user.identity_url %> </span>
10
+ <% else -%>
11
+ <span class="sign-in"><%= link_to "Sign in", new_session_path %></span>
12
+ <% end -%>
13
+ </div>
14
+ <div id="content">
15
+ <%= yield %>
16
+ </div>
17
+ </body>
18
+ </html>
@@ -0,0 +1,16 @@
1
+ <% content_for :stylesheet do -%>
2
+ <%= stylesheet_link_tag "repim" %>
3
+ <% end %>
4
+ <h1>Welcome</h1>
5
+
6
+ <div id="login-or-signup">
7
+ <p> Please login or signup using OpenID.</p>
8
+
9
+ <% form_tag session_path do -%>
10
+ <label for="openid_url">OpenID URL</label>
11
+ <%= text_field_tag "openid_url", params[:openid_url] %>
12
+
13
+ <%= submit_tag "Login or Signup" %>
14
+ <% end %>
15
+ </div>
16
+
@@ -0,0 +1,23 @@
1
+ <h1>Sign up</h1>
2
+
3
+ <%% form_for(@<%= user %>) do |f| %>
4
+ <%%= f.error_messages %>
5
+
6
+ <table>
7
+ <% for attribute in attributes -%>
8
+ <tr>
9
+ <th> <%%= f.label :<%= attribute.name %> %></th>
10
+ <td><%%= f.<%= attribute.field_type %> :<%= attribute.name %> %></td>
11
+ </tr>
12
+ <% end -%>
13
+ <tr>
14
+ <th>OpenID URL</th>
15
+ <td><%%=h session[:identity_url] %></td>
16
+ </tr>
17
+ </table>
18
+ <p>
19
+ <%%= f.submit 'Create' %>
20
+ </p>
21
+ <%% end %>
22
+
23
+ <%%= link_to 'Back', <%= users %>_path %>
@@ -0,0 +1,70 @@
1
+ require "repim/random"
2
+
3
+ module Repim
4
+ module Application
5
+ def self.included(base)
6
+ base.cattr_accessor :user_klass
7
+ base.cattr_accessor :login_template
8
+ base.cattr_accessor :with_single_access
9
+ base.user_klass = (User rescue nil) # assign nil when LoadError and/or ConstMissing
10
+ base.login_template = "sessions/new"
11
+ base.with_single_access = (base.user_klass.column_names.include?('single_access_token') rescue false)
12
+
13
+ base.before_filter :authenticate
14
+ [:current_user, :signed_in?, :logged_in?].each do |method|
15
+ base.helper_method method
16
+ base.hide_action method
17
+ end
18
+ end
19
+
20
+ def signed_in?; !!current_user ; end
21
+ alias logged_in? signed_in?
22
+
23
+ def current_user
24
+ return nil if @__current_user__ == false
25
+ return @__current_user__ if @__current_user__
26
+ @__current_user__ ||= (user_from_session || false)
27
+ current_user # call again
28
+ end
29
+
30
+ private
31
+ def authenticate
32
+ signed_in? || access_denied("Login required.")
33
+ end
34
+ alias login_required authenticate
35
+
36
+ def access_denied(message = nil)
37
+ store_location
38
+ flash[:error] = message if message
39
+ render :template => login_template, :status => :unauthorized
40
+ end
41
+
42
+ def store_location
43
+ session[:return_to] = request.request_uri if request.get?
44
+ end
45
+
46
+ def current_user=(user)
47
+ @__current_user__ = user
48
+ if self.class.with_single_access
49
+ # TODO Rails2.3以降で利用するか、もう少しセキュアなランダムを作成できるようにしたほうがよい
50
+ user.single_access_token = Repim::Random.friendly_token
51
+ session[:single_access_token] = user.single_access_token
52
+ user.save(false)
53
+ else
54
+ session[:user_id] = user.id
55
+ end
56
+ end
57
+
58
+ def user_from_session
59
+ if self.class.with_single_access
60
+ session[:single_access_token] && user_klass.find_by_single_access_token(session[:single_access_token])
61
+ else
62
+ session[:user_id] && user_klass.find_by_id(session[:user_id])
63
+ end
64
+ end
65
+
66
+ def redirect_back_or(default)
67
+ redirect_to(session[:return_to] || default)
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,32 @@
1
+ require 'active_support'
2
+
3
+ module Repim
4
+ class AxAttributeAdapter
5
+ attr_reader :rule, :necessity
6
+
7
+ # TODO refactor
8
+ def initialize(prefixes, propaties)
9
+ @rule = {}
10
+ @necessity = :optional
11
+ propaties.each do |model_attr, property|
12
+ @rule[model_attr] = prefixes.map{|px| px + property }
13
+ end
14
+ end
15
+
16
+ def keys
17
+ rule.values.flatten
18
+ end
19
+
20
+ def required!
21
+ @necessity = :required
22
+ end
23
+
24
+ def adapt(fetched)
25
+ returning({}) do |res|
26
+ rule.each do |k, vs|
27
+ fetched.each{|fk, (fv,_)| res[k] = fv if !fv.blank? && vs.include?(fk) }
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,33 @@
1
+ module Repim
2
+ # Handles generating random strings. If SecureRandom is installed it will default to this and use it instead. SecureRandom comes with ActiveSupport.
3
+ # So if you are using this in a rails app you should have this library.
4
+ module Random
5
+ extend self
6
+
7
+ SecureRandom = (defined?(::SecureRandom) && ::SecureRandom) || (defined?(::ActiveSupport::SecureRandom) && ::ActiveSupport::SecureRandom)
8
+
9
+ if SecureRandom
10
+ def hex_token
11
+ SecureRandom.hex(64)
12
+ end
13
+
14
+ def friendly_token
15
+ # use base64url as defined by RFC4648
16
+ SecureRandom.base64(15).tr('+/=', '-_ ').strip.delete("\n")
17
+ end
18
+ else
19
+ def hex_token
20
+ Authlogic::CryptoProviders::Sha512.encrypt(Time.now.to_s + (1..10).collect{ rand.to_s }.join)
21
+ end
22
+
23
+ FRIENDLY_CHARS = ("a".."z").to_a + ("A".."Z").to_a + ("0".."9").to_a
24
+
25
+ def friendly_token
26
+ newpass = ""
27
+ 1.upto(20) { |i| newpass << FRIENDLY_CHARS[rand(FRIENDLY_CHARS.size-1)] }
28
+ newpass
29
+ end
30
+ end
31
+
32
+ end
33
+ end
@@ -0,0 +1,101 @@
1
+ require 'repim/ax_attributes_adapter'
2
+
3
+ module Repim
4
+ module RelyingParty
5
+ def self.included(base)
6
+ base.cattr_accessor :attribute_adapter
7
+ base.cattr_accessor :signup_template
8
+
9
+ base.skip_before_filter :authenticate
10
+ base.signup_template = "users/new"
11
+
12
+ base.extend(ClassMethods)
13
+ end
14
+
15
+ module ClassMethods
16
+ def use_attribute_exchange(prefixes, propaties)
17
+ self.attribute_adapter = AxAttributeAdapter.new(prefixes, propaties)
18
+ end
19
+ end
20
+
21
+ # render new.rhtml
22
+ def new
23
+ end
24
+
25
+ def create
26
+ options = {}
27
+ options[attribute_adapter.necessity] = attribute_adapter.keys if attribute_adapter
28
+
29
+ begin
30
+ authenticate_with_open_id(params[:openid_url], options) do |result, identity_url, personal_data|
31
+ if result.successful?
32
+ authenticate_success(identity_url, personal_data)
33
+ else
34
+ authenticate_failure(params.merge(:openid_url=>identity_url))
35
+ end
36
+ end
37
+ rescue OpenID::OpenIDError => why
38
+ logger.debug{ [why.message, why.backtrace].flatten.join("\n\t") }
39
+ authenticate_failure(params)
40
+ end
41
+ end
42
+
43
+ def destroy
44
+ if self.class.with_single_access
45
+ current_user.single_access_token = nil
46
+ current_user.save(false)
47
+ session[:single_access_token] = nil
48
+ else
49
+ session[:user_id] = nil
50
+ end
51
+ reset_session
52
+ flash[:notice] = "You have been logged out."
53
+
54
+ redirect_back_or(after_logout_path)
55
+ end
56
+
57
+ private
58
+ def authenticate_success(identity_url, personal_data = {})
59
+ if user = user_klass.find_by_identity_url(identity_url)
60
+ login_successfully(user, personal_data)
61
+ redirect_back_or(after_login_path)
62
+ else
63
+ signup(identity_url, personal_data)
64
+ render(:template => signup_template)
65
+ end
66
+ end
67
+
68
+ def login_successfully(user, personal_data)
69
+ reset_session
70
+ self.current_user = user
71
+ flash[:notice] ||= "Logged in successfully"
72
+ end
73
+
74
+ def signup(identity_url, ax = {})
75
+ session[:identity_url] = identity_url
76
+ @user = user_klass.new( attribute_adapter ? attribute_adapter.adapt(ax) : {} )
77
+ end
78
+
79
+ # log login faulure. and re-render sessions/new
80
+ def authenticate_failure(assigns = params)
81
+ flash[:error] = "Couldn't log you in as '#{assigns[:openid_url] || assigns["openid.claimed_id"]}'"
82
+ logger.warn "Failed login for '#{assigns[:openid_url]}' from #{request.remote_ip} at #{Time.now.utc}"
83
+
84
+ @openid_url = assigns[:openid_url]
85
+
86
+ render :action => 'new'
87
+ end
88
+
89
+ def after_login_path; root_path ; end
90
+ def after_logout_path; login_path ; end
91
+
92
+ def method_missing(m, *args, &b)
93
+ return [request.protocol, request.host_with_port, "/"].join if m.to_sym == :root_url
94
+ super
95
+ end
96
+
97
+ def verify_authenticity_token
98
+ super unless ('create' == params[:action] && '1' == params[:open_id_complete])
99
+ end
100
+ end
101
+ end
@@ -0,0 +1,28 @@
1
+ module Repim
2
+ module Signup
3
+ def self.included(base)
4
+ base.before_filter :authenticate, :except => [:create]
5
+ end
6
+
7
+ def create
8
+ @user = User.new(params[:user])
9
+ @user.identity_url = session[:identity_url]
10
+
11
+ respond_to do |format|
12
+ if @user.save
13
+ flash[:notice] = 'User was successfully created.'
14
+ reset_session
15
+ self.current_user = @user
16
+ format.html { redirect_to(after_create_url(@user)) }
17
+ else
18
+ format.html { render :action => "new" }
19
+ end
20
+ end
21
+ end
22
+
23
+ private
24
+ def after_create_url(created)
25
+ respond_to?(:root_url) ? root_url : user_url(created)
26
+ end
27
+ end
28
+ end
data/lib/repim.rb ADDED
@@ -0,0 +1,3 @@
1
+ module Repim
2
+ Version = '0.1.8'
3
+ end
data/rails/init.rb ADDED
@@ -0,0 +1,8 @@
1
+ # add hook to activate in rails app.
2
+ #
3
+ # example.
4
+ # ActiveRecrod::Base.send(:include, Repim)
5
+
6
+ require 'repim/application'
7
+ config.gem 'moro-open_id_authentication', :lib => 'open_id_authentication', :source => 'http://gems.github.com/'
8
+
metadata ADDED
@@ -0,0 +1,107 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: openskip-repim
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.8
5
+ platform: ruby
6
+ authors:
7
+ - MOROHASHI Kyosuke
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-06-30 00:00:00 -07:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: moro-open_id_authentication
17
+ type: :runtime
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: "0"
24
+ version:
25
+ description: Relying Party in minutes.
26
+ email: moronatural@gmail.com
27
+ executables: []
28
+
29
+ extensions: []
30
+
31
+ extra_rdoc_files:
32
+ - README.rdoc
33
+ - ChangeLog
34
+ files:
35
+ - README.rdoc
36
+ - ChangeLog
37
+ - Rakefile
38
+ - lib/repim
39
+ - lib/repim/application.rb
40
+ - lib/repim/ax_attributes_adapter.rb
41
+ - lib/repim/random.rb
42
+ - lib/repim/relying_party.rb
43
+ - lib/repim/signup.rb
44
+ - lib/repim.rb
45
+ - generators/relying_party
46
+ - generators/relying_party/relying_party_generator.rb
47
+ - generators/relying_party/templates
48
+ - generators/relying_party/templates/public
49
+ - generators/relying_party/templates/public/images
50
+ - generators/relying_party/templates/public/images/openid-login.gif
51
+ - generators/relying_party/templates/public/stylesheets
52
+ - generators/relying_party/templates/public/stylesheets/repim.css
53
+ - generators/relying_party/templates/sessions_controller.rb
54
+ - generators/relying_party/templates/spec
55
+ - generators/relying_party/templates/spec/application_controller_spec.rb
56
+ - generators/relying_party/templates/spec/sessions_controller_spec.rb
57
+ - generators/relying_party/templates/spec/sessions_routing_spec.rb
58
+ - generators/relying_party/templates/spec/users_controller_spec.rb
59
+ - generators/relying_party/templates/spec/users_routing_spec.rb
60
+ - generators/relying_party/templates/users_controller.rb
61
+ - generators/relying_party/templates/views
62
+ - generators/relying_party/templates/views/layouts
63
+ - generators/relying_party/templates/views/layouts/sessions.html.erb
64
+ - generators/relying_party/templates/views/sessions
65
+ - generators/relying_party/templates/views/sessions/new.html.erb
66
+ - generators/relying_party/templates/views/users
67
+ - generators/relying_party/templates/views/users/new.html.erb
68
+ - rails/init.rb
69
+ has_rdoc: false
70
+ homepage: http://github.com/moro/repim/
71
+ post_install_message:
72
+ rdoc_options:
73
+ - --title
74
+ - repim documentation
75
+ - --charset
76
+ - utf-8
77
+ - --opname
78
+ - index.html
79
+ - --line-numbers
80
+ - --main
81
+ - README.rdoc
82
+ - --inline-source
83
+ - --exclude
84
+ - ^(examples|extras)/
85
+ require_paths:
86
+ - lib
87
+ required_ruby_version: !ruby/object:Gem::Requirement
88
+ requirements:
89
+ - - ">="
90
+ - !ruby/object:Gem::Version
91
+ version: "0"
92
+ version:
93
+ required_rubygems_version: !ruby/object:Gem::Requirement
94
+ requirements:
95
+ - - ">="
96
+ - !ruby/object:Gem::Version
97
+ version: "0"
98
+ version:
99
+ requirements: []
100
+
101
+ rubyforge_project:
102
+ rubygems_version: 1.2.0
103
+ signing_key:
104
+ specification_version: 3
105
+ summary: Relying Party in minutes.
106
+ test_files: []
107
+