openskip-repim 0.1.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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
+