Commit 8084f86d80c2e61db4d85e079a28d815050d0189

add support for openid

Commit diff

.gitmodules

 
1[submodule "vendor/plugins/open_id_authentication"]
2 path = vendor/plugins/open_id_authentication
3 url = git://github.com/josh/open_id_authentication.git
toggle raw diff

app/controllers/sessions_controller.rb

 
1# This controller handles the login/logout function of the site.
1 require "openid"
2 require "yadis"
3# This controller handles the login/logout function of the site.
24class SessionsController < ApplicationController
35 # render new.rhtml
46 def new
57 end
68
79 def create
8 self.current_user = User.authenticate(params[:email], params[:password])
9 if logged_in?
10 if params[:remember_me] == "1"
11 self.current_user.remember_me
12 cookies[:auth_token] = { :value => self.current_user.remember_token , :expires => self.current_user.remember_token_expires_at }
13 end
14 redirect_back_or_default('/')
15 flash[:notice] = "Logged in successfully"
10 if using_open_id?
11 open_id_authentication(params[:openid_url])
1612 else
17 flash.now[:error] = "Username/password didn't match, please try again."
18 render :action => 'new'
13 password_authentication(params[:email], params[:password])
1914 end
2015 end
2116
2121 flash[:notice] = "You have been logged out."
2222 redirect_back_or_default('/')
2323 end
24
25 protected
26
27 # if user doesn't exist, it gets created and activated,
28 # else if the user already exists with same identity_url, it just logs in
29 def open_id_authentication(openid_url)
30 authenticate_with_open_id(openid_url, :required => [:nickname, :email], :optional => [:fullname]) do |result, identity_url, registration|
31 if result.successful?
32 @user = User.find_or_initialize_by_identity_url(identity_url)
33 if @user.new_record?
34 @user.login = registration['nickname']
35 @user.fullname = registration['fullname']
36 @user.email = registration['email']
37 @user.save!
38 @user.activate
39 end
40 self.current_user = @user
41 successful_login
42 else
43 failed_login result.message, 'openid'
44 end
45 end
46 rescue ActiveRecord::RecordInvalid => invalid
47 flash[:error] = "This login (<strong>#{@user.login}</strong>) already exists, please <a href="+@user.identity_url+">choose a different persona or modify the current one</a>"
48
49 redirect_to login_path(:method => 'openid')
50 end
51
52 def password_authentication(email, password)
53 ##self.current_user = User.authenticate(login, password)
54 self.current_user = User.authenticate(email, password)
55 if logged_in?
56 successful_login
57 else
58 failed_login("Username/password didn't match, please try again.")
59 end
60 end
61
62 def failed_login(message = "Authentication failed.",method="")
63 if method==''
64 flash.now[:error] = message
65 render :action => 'new'
66 else
67 redirect_to login_path(:method=>method)
68 flash[:error] = message
69 end
70 end
71
72 def successful_login
73 if params[:remember_me] == "1"
74 self.current_user.remember_me
75 cookies[:auth_token] = { :value => self.current_user.remember_token , :expires => self.current_user.remember_token_expires_at }
76 end
77 redirect_back_or_default('/')
78 flash[:notice] = "Logged in successfully"
79 end
80
2481end
toggle raw diff

app/helpers/sessions_helper.rb

 
11module SessionsHelper
2end
2
3 # determines which form to display for login
4 def login_method
5 if params[:method]=='openid'
6 "<script type=\"text/javascript\"> Event.observe(window, 'load',
7 function() {
8Element.toggle(\"regular_login_fields\");
9Element.toggle(\"openid_login_fields\");
10})
11 </script>"
12 end
13 end
14
15 def switch_login(title, action)
16 link_to_function title do |page|
17 page.toggle "regular_login_fields"
18 page.toggle "openid_login_fields"
19 end
20 end
21end
toggle raw diff

app/models/user.rb

 
66 has_many :repositories, :through => :committerships
77 has_many :ssh_keys, :order => "id desc"
88 has_many :comments
9
9
1010 # Virtual attribute for the unencrypted password
1111 attr_accessor :password, :current_password
12
12
1313 attr_protected :login
1414
15 validates_presence_of :login, :email
15 validates_presence_of :login, :email, :if => :password_required?
1616 validates_format_of :login, :with => /^[a-z0-9\-_\.]+$/i
1717 validates_format_of :email, :with => /^[^@\s]+@([\-a-z0-9]+\.)+[a-z]{2,}$/i
1818 validates_presence_of :password, :if => :password_required?
2222 validates_length_of :login, :within => 3..40
2323 validates_length_of :email, :within => 3..100
2424 validates_uniqueness_of :login, :email, :case_sensitive => false
25
25
2626 before_save :encrypt_password
27 before_create :make_activation_code
28
27 before_create :make_activation_code
28
2929 def self.find_by_login!(name)
3030 find_by_login(name) || raise(ActiveRecord::RecordNotFound )
3131 end
32
32
3333 # Authenticates a user by their login name and unencrypted password. Returns the user or nil.
3434 def self.authenticate(email, password)
3535 u = find :first, :conditions => ['email = ? and activated_at IS NOT NULL', email] # need to get the salt
4040 def self.encrypt(password, salt)
4141 Digest::SHA1.hexdigest("--#{salt}--#{password}--")
4242 end
43
43
4444 def self.generate_random_password(password_size = 12)
4545 characters = (("a".."z").to_a + ("0".."9").to_a) - %w[0 o i l 1]
4646 (0...password_size).collect do |char|
7575 end
7676
7777 def remember_token?
78 remember_token_expires_at && Time.now.utc < remember_token_expires_at
78 remember_token_expires_at && Time.now.utc < remember_token_expires_at
7979 end
8080
8181 # These create and unset the fields required for remembering users between browser closes
9898 self.remember_token = nil
9999 save(false)
100100 end
101
101
102102 def reset_password!
103103 generated = User.generate_random_password
104104 self.password = generated
106106 self.save!
107107 generated
108108 end
109
109
110110 def can_write_to?(repository)
111111 !!committerships.find_by_repository_id(repository.id)
112112 end
113
113
114114 def to_param
115115 login
116116 end
117
117
118118 def to_xml(opts = {})
119119 super({:except => [:activation_code, :crypted_password, :remember_token, :remember_token_expires_at, :salt, :ssh_key_id]}.merge(opts))
120120 end
121121
122122 protected
123 # before filter
123 # before filter
124124 def encrypt_password
125125 return if password.blank?
126126 self.salt = Digest::SHA1.hexdigest("--#{Time.now.to_s}--#{login}--") if new_record?
127127 self.crypted_password = encrypt(password)
128128 end
129
129
130130 def password_required?
131 crypted_password.blank? || !password.blank?
131 not_openid? && (crypted_password.blank? || !password.blank?)
132 end
133
134 def not_openid?
135 identity_url.blank?
132136 end
133
137
134138 def make_activation_code
135139 self.activation_code = Digest::SHA1.hexdigest( Time.now.to_s.split(//).sort_by {rand}.join )
136 end
140 end
137141end
toggle raw diff

app/views/accounts/edit.html.erb

 
1414 <%= f.label :url, "url <small>blog etc</small>" -%><br />
1515 <%= f.text_field :url, :class => "text" -%>
1616 </p>
17 <p>
18 <%= f.label :url, "OpenID" -%><br />
19 <%= f.text_field :identity_url, :class => "text" -%>
20 </p>
1721 <%= f.submit "Save" -%>
1822<% end -%>
1923
toggle raw diff

app/views/sessions/new.html.erb

 
11<h1>Login</h1>
2<%= login_method %>
23
3
4<% form_tag sessions_path do -%>
5 <p>
6 <label for="login">Email</label><br/>
4<% form_tag sessions_path do -%>
5 <div id="regular_login_fields">
6 <% # login_method %>
7 <p>
8 <label for="login">Email or <%= switch_login('switch to OpenID','to_openid')%></label><br/>
79 <%= text_field_tag 'email', params[:email], :class => "text" %>
810 </p>
911
1313 <label for="password">Password</label><br/>
1414 <%= password_field_tag 'password', '', :class => "text" %>
1515 </p>
16
16 </div>
17 <div id="openid_login_fields" style="display:none;">
18 <p>
19 <label for="openid">OpenID or <%= switch_login('switch to email login', 'to_email') -%></label><br/>
20 <%= text_field_tag 'openid_url', params[:openid_url], :class => "text" -%>
21 </p>
22 </div>
1723 <p>
1824 <label for="remember_me">Remember me:</label>
1925 <%= check_box_tag 'remember_me' %>
toggle raw diff

app/views/users/new.html.erb

 
1<h1>Create new user</h1>
1<h1>Create new user or <%= link_to "login directly with your OpenID", login_path(:method=>'openid') -%></h1>
22
33<p>
4 Creating a user account allows you to create your own project or participate
5 in the development of any project.
4 Creating a user account allows you to create your own project or participate
5 in the development of any project.
66</p>
77
88<%= error_messages_for :user %>
toggle raw diff

config/routes.rb

 
2828 :forgot_password => :get,
2929 :reset_password => :post,
3030 }
31 map.open_id_complete '/sessions', :controller => "sessions", :action=> "create",:requirements => { :method => :get }
3132 map.resource :sessions
3233 map.with_options(:controller => "projects", :action => "category") do |project_cat|
3334 project_cat.projects_category "projects/category/:id"
toggle raw diff

db/migrate/024_add_open_id_authentication_tables.rb

 
1class AddOpenIdAuthenticationTables < ActiveRecord::Migration
2 def self.up
3 create_table :open_id_authentication_associations, :force => true do |t|
4 t.integer :issued, :lifetime
5 t.string :handle, :assoc_type
6 t.binary :server_url, :secret
7 end
8
9 create_table :open_id_authentication_nonces, :force => true do |t|
10 t.integer :timestamp, :null => false
11 t.string :server_url, :null => true
12 t.string :salt, :null => false
13 end
14 end
15
16 def self.down
17 drop_table :open_id_authentication_associations
18 drop_table :open_id_authentication_nonces
19 end
20end
toggle raw diff

db/migrate/025_add_identity_url_to_users.rb

 
1class AddIdentityUrlToUsers < ActiveRecord::Migration
2 def self.up
3 add_column :users, :identity_url, :text
4 end
5
6 def self.down
7 remove_column :users, :identity_url
8 end
9end
10
toggle raw diff

public/images/login-bg.gif

 
toggle raw diff

public/stylesheets/base.css

 
343343 border: 1px solid #666;
344344}
345345
346/* embeds the openid image in the text field */
347input#openid_url {
348 background: url(/images/login-bg.gif) no-repeat;
349 background-color: #fff;
350 background-position: 0 50%;
351 color: #000;
352 padding-left: 18px;
353}
354
346355.fieldWithErrors { margin: 0; display: block;}
347356.fieldWithErrors input, .fieldWithErrors textarea,
348357.fieldWithErrors select {
toggle raw diff

vendor/plugins/open_id_authentication

 
1Subproject commit d9d6e6ac85e37eedd40b97fa1f7cf25645038a19
toggle raw diff