Commit 7bac7ef7dcdee879741ea74da7f334be2e5bc8ca

Authored by Leandro Nunes dos Santos
Committed by Daniela Feitosa
1 parent 54151a76

adding some hotspots to make the openid plugin works.

app/controllers/public/account_controller.rb
... ... @@ -25,11 +25,13 @@ class AccountController < ApplicationController
25 25  
26 26 # action to perform login to the application
27 27 def login
28   - @user = User.new
29   - @person = @user.build_person
30 28 store_location(request.referer) unless session[:return_to]
31 29 return unless request.post?
32   - self.current_user = User.authenticate(params[:user][:login], params[:user][:password], environment) if params[:user]
  30 +
  31 + self.current_user = plugins_alternative_authentication
  32 +
  33 + self.current_user ||= User.authenticate(params[:user][:login], params[:user][:password], environment) if params[:user]
  34 +
33 35 if logged_in?
34 36 if params[:remember_me] == "1"
35 37 self.current_user.remember_me
... ... @@ -41,7 +43,6 @@ class AccountController < ApplicationController
41 43 end
42 44 else
43 45 session[:notice] = _('Incorrect username or password') if redirect?
44   - redirect_to :back if redirect?
45 46 end
46 47 end
47 48  
... ... @@ -56,6 +57,10 @@ class AccountController < ApplicationController
56 57  
57 58 # action to register an user to the application
58 59 def signup
  60 + if @plugins.dispatch(:allow_user_registration).include?(false)
  61 + redirect_back_or_default(:controller => 'home')
  62 + end
  63 +
59 64 @invitation_code = params[:invitation_code]
60 65 begin
61 66 if params[:user]
... ... @@ -125,6 +130,9 @@ class AccountController < ApplicationController
125 130 #
126 131 # Posts back.
127 132 def forgot_password
  133 + if @plugins.dispatch(:allow_password_recovery).include?(false)
  134 + redirect_back_or_default(:controller => 'home')
  135 + end
128 136 @change_password = ChangePassword.new(params[:change_password])
129 137  
130 138 if request.post?
... ... @@ -316,4 +324,13 @@ class AccountController < ApplicationController
316 324 end
317 325 end
318 326  
  327 + def plugins_alternative_authentication
  328 + user = nil
  329 + @plugins.each do |plugin|
  330 + user = plugin.alternative_authentication
  331 + break unless user.nil?
  332 + end
  333 + user
  334 + end
  335 +
319 336 end
... ...
app/models/person.rb
... ... @@ -71,10 +71,7 @@ class Person < Profile
71 71 Friendship.find(:all, :conditions => { :friend_id => person.id}).each { |friendship| friendship.destroy }
72 72 end
73 73  
74   - after_destroy :destroy_user
75   - def destroy_user
76   - self.user.destroy if self.user
77   - end
  74 + belongs_to :user, :dependent => :delete
78 75  
79 76 def can_control_scrap?(scrap)
80 77 begin
... ...
app/models/user.rb
... ... @@ -30,7 +30,7 @@ class User < ActiveRecord::Base
30 30  
31 31 after_create do |user|
32 32 user.person ||= Person.new
33   - user.person.attributes = user.person_data.merge(:identifier => user.login, :user_id => user.id, :environment_id => user.environment_id)
  33 + user.person.attributes = user.person_data.merge(:identifier => user.login, :user => user, :environment_id => user.environment_id)
34 34 user.person.name ||= user.login
35 35 user.person.visible = false unless user.activated?
36 36 user.person.save!
... ... @@ -88,13 +88,13 @@ class User < ActiveRecord::Base
88 88 attr_protected :activated_at
89 89  
90 90 # Virtual attribute for the unencrypted password
91   - attr_accessor :password
  91 + attr_accessor :password, :name
92 92  
93 93 validates_presence_of :login, :email
94 94 validates_format_of :login, :with => Profile::IDENTIFIER_FORMAT, :if => (lambda {|user| !user.login.blank?})
95 95 validates_presence_of :password, :if => :password_required?
96   - validates_presence_of :password_confirmation, :if => :password_required?, :if => (lambda {|user| !user.password.blank?})
97   - validates_length_of :password, :within => 4..40, :if => :password_required?, :if => (lambda {|user| !user.password.blank?})
  96 + validates_presence_of :password_confirmation, :if => :password_required?
  97 + validates_length_of :password, :within => 4..40, :if => :password_required?
98 98 validates_confirmation_of :password, :if => :password_required?
99 99 validates_length_of :login, :within => 2..40, :if => (lambda {|user| !user.login.blank?})
100 100 validates_length_of :email, :within => 3..100, :if => (lambda {|user| !user.email.blank?})
... ... @@ -228,7 +228,12 @@ class User < ActiveRecord::Base
228 228 end
229 229  
230 230 def name
231   - person ? person.name : login
  231 + name = (self[:name] || login)
  232 + person.nil? ? name : (person.name || name)
  233 + end
  234 +
  235 + def name= name
  236 + self[:name] = name
232 237 end
233 238  
234 239 def enable_email!
... ... @@ -274,6 +279,11 @@ class User < ActiveRecord::Base
274 279 15 # in minutes
275 280 end
276 281  
  282 +
  283 + def not_require_password!
  284 + @is_password_required = false
  285 + end
  286 +
277 287 protected
278 288 # before filter
279 289 def encrypt_password
... ... @@ -282,9 +292,13 @@ class User < ActiveRecord::Base
282 292 self.password_type ||= User.system_encryption_method.to_s
283 293 self.crypted_password = encrypt(password)
284 294 end
285   -
  295 +
286 296 def password_required?
287   - crypted_password.blank? || !password.blank?
  297 + (crypted_password.blank? || !password.blank?) && is_password_required?
  298 + end
  299 +
  300 + def is_password_required?
  301 + @is_password_required.nil? ? true : @is_password_required
288 302 end
289 303  
290 304 def make_activation_code
... ...
app/views/account/login.rhtml
... ... @@ -13,6 +13,8 @@
13 13  
14 14 <%= f.password_field :password %>
15 15  
  16 + <%= @plugins.dispatch(:login_extra_contents).collect { |content| instance_eval(&content) }.join("") %>
  17 +
16 18 <% button_bar do %>
17 19 <%= submit_button( 'login', _('Log in') )%>
18 20 <% if is_thickbox %>
... ... @@ -23,8 +25,13 @@
23 25 <% end %>
24 26  
25 27 <% button_bar do %>
26   - <%= button :add, _("New user"), :controller => 'account', :action => 'signup' %>
27   - <%= button :help, _("I forgot my password!"), :controller => 'account', :action => 'forgot_password' %>
  28 + <% unless @plugins.dispatch(:allow_user_registration).include?(false) %>
  29 + <%= button :add, _("New user"), :controller => 'account', :action => 'signup' %>
  30 + <% end %>
  31 +
  32 + <% unless @plugins.dispatch(:allow_password_recovery).include?(false) %>
  33 + <%= button :help, _("I forgot my password!"), :controller => 'account', :action => 'forgot_password' %>
  34 + <% end %>
28 35 <% end %>
29 36  
30 37 </div><!-- end class="login-box" -->
... ...
app/views/layouts/application-ng.rhtml
... ... @@ -56,10 +56,18 @@
56 56 <%= usermenu_logged_in %>
57 57 </span>
58 58 <span class='not-logged-in' style='display: none'>
59   - <%= _("<span class='login'>%s</span> <span class='or'>or</span> <span class='signup'>%s</span>") % [thickbox_inline_popup_link('<i class="icon-menu-login"></i><strong>' + _('Login') + '</strong>', login_url, 'inlineLoginBox', :id => 'link_login'), link_to('<strong>' + _('Sign up') + '</strong>', :controller => 'account', :action => 'signup') ] %>
  59 +
  60 + <%= _("<span class='login'>%s</span>") % thickbox_inline_popup_link('<i class="icon-menu-login"></i><strong>' + _('Login') + '</strong>', login_url, 'inlineLoginBox', :id => 'link_login') %>
  61 + <%= @plugins.dispatch(:alternative_authentication_link).collect { |content| instance_eval(&content) }.join("") %>
  62 +
60 63 <div id='inlineLoginBox' style='display: none;'>
61 64 <%= render :file => 'account/login', :locals => { :is_thickbox => true } %>
62 65 </div>
  66 +
  67 + <% unless @plugins.dispatch(:allow_user_registration).include?(false) %>
  68 + <%= _("<span class='or'>or</span> <span class='signup'>%s</span>") % link_to('<strong>' + _('Sign up') + '</strong>', :controller => 'account', :action => 'signup')%>
  69 + <% end %>
  70 +
63 71 </span>
64 72 <form action="/search" class="search_form" method="get" class="clean">
65 73 <input name="query" size="15" title="<%=_('Search...')%>" onfocus="this.form.className='focused';" onblur="this.form.className=''" />
... ...
config/routes.rb
... ... @@ -19,6 +19,7 @@ ActionController::Routing::Routes.draw do |map|
19 19  
20 20 # -- just remember to delete public/index.html.
21 21 # You can have the root of your site routed by hooking up ''
  22 + map.root :controller => "home", :conditions => { :if => lambda { |env| !Domain.hosting_profile_at(env[:host]) } }
22 23 map.connect '', :controller => "home", :conditions => { :if => lambda { |env| !Domain.hosting_profile_at(env[:host]) } }
23 24 map.home 'site/:action', :controller => 'home'
24 25  
... ...
lib/noosfero/plugin.rb
... ... @@ -320,6 +320,37 @@ class Noosfero::Plugin
320 320 nil
321 321 end
322 322  
  323 + # -> Add an alternative authentication method.
  324 + # Your plugin have to make the access control and return the logged user.
  325 + # returns = User
  326 + def alternative_authentication
  327 + nil
  328 + end
  329 +
  330 + # -> Adds adicional link to make the user authentication
  331 + # returns = lambda block that creates html code
  332 + def alternative_authentication_link
  333 + nil
  334 + end
  335 +
  336 + # -> Allow or not user registration
  337 + # returns = boolean
  338 + def allow_user_registration
  339 + true
  340 + end
  341 +
  342 + # -> Allow or not password recovery by users
  343 + # returns = boolean
  344 + def allow_password_recovery
  345 + true
  346 + end
  347 +
  348 + # -> Adds fields to the login form
  349 + # returns = lambda block that creates html code
  350 + def login_extra_contents
  351 + nil
  352 + end
  353 +
323 354 def method_missing(method, *args, &block)
324 355 # This is a generic hotspot for all controllers on Noosfero.
325 356 # If any plugin wants to define filters to run on any controller, the name of
... ...
test/functional/account_controller_test.rb
... ... @@ -11,6 +11,10 @@ class AccountControllerTest &lt; ActionController::TestCase
11 11  
12 12 all_fixtures
13 13  
  14 + def teardown
  15 + Thread.current[:enabled_plugins] = nil
  16 + end
  17 +
14 18 def setup
15 19 @controller = AccountController.new
16 20 @request = ActionController::TestRequest.new
... ... @@ -31,13 +35,11 @@ class AccountControllerTest &lt; ActionController::TestCase
31 35 assert_response :redirect
32 36 end
33 37  
34   - should 'redirect to where user was on login' do
35   - @request.env["HTTP_REFERER"] = '/bli'
36   - u = new_user
  38 + should 'display notice message if the login fail' do
37 39 @controller.stubs(:logged_in?).returns(false)
38 40 post :login, :user => {:login => 'quire', :password => 'quire'}
39 41  
40   - assert_redirected_to '/bli'
  42 + assert session[:notice].include?('Incorrect')
41 43 end
42 44  
43 45 should 'authenticate on the current environment' do
... ... @@ -46,23 +48,11 @@ class AccountControllerTest &lt; ActionController::TestCase
46 48 post :login, :user => { :login => 'fake', :password => 'fake' }
47 49 end
48 50  
49   - should 'redirect to where was when login on other environment' do
50   - e = fast_create(Environment, :name => 'other_environment')
51   - e.domains << Domain.new(:name => 'other.environment')
52   - e.save!
53   - u = create_user('test_user', :environment => e).person
54   -
55   - @request.env["HTTP_REFERER"] = '/bli'
56   - post :login, :user => {:login => 'test_user', :password => 'test_user'}
57   -
58   - assert_redirected_to '/bli'
59   - end
60   -
61 51 def test_should_fail_login_and_not_redirect
62 52 @request.env["HTTP_REFERER"] = 'bli'
63 53 post :login, :user => {:login => 'johndoe', :password => 'bad password'}
64 54 assert_nil session[:user]
65   - assert_response :redirect
  55 + assert_response :success
66 56 end
67 57  
68 58 def test_should_allow_signup
... ... @@ -697,7 +687,6 @@ class AccountControllerTest &lt; ActionController::TestCase
697 687 assert_nil assigns(:message)
698 688 post :login, :user => {:login => 'testuser', :password => 'test123'}
699 689 assert_nil session[:user]
700   - assert_redirected_to '/bli'
701 690 end
702 691  
703 692 should 'not activate user when activation code is incorrect' do
... ... @@ -707,7 +696,6 @@ class AccountControllerTest &lt; ActionController::TestCase
707 696 assert_nil assigns(:message)
708 697 post :login, :user => {:login => 'testuser', :password => 'test123'}
709 698 assert_nil session[:user]
710   - assert_redirected_to '/bli'
711 699 end
712 700  
713 701 should 'be able to upload an image' do
... ... @@ -777,6 +765,122 @@ class AccountControllerTest &lt; ActionController::TestCase
777 765 assert_tag :tag => 'strong', :content => 'Plugin2 text'
778 766 end
779 767  
  768 + should 'login with an alternative authentication defined by plugin' do
  769 + class Plugin1 < Noosfero::Plugin
  770 + def alternative_authentication
  771 + User.new(:login => 'testuser')
  772 + end
  773 + end
  774 + Environment.default.enable_plugin(Plugin1.name)
  775 +
  776 + post :login, :user => {:login => "testuser"}
  777 +
  778 + assert_equal 'testuser', assigns(:current_user).login
  779 + assert_response :redirect
  780 + end
  781 +
  782 + should "login with the default autentication if the alternative authentication method doesn't login the user" do
  783 + class Plugin1 < Noosfero::Plugin
  784 + def alternative_authentication
  785 + nil
  786 + end
  787 + end
  788 + Environment.default.enable_plugin(Plugin1.name)
  789 + post :login, :user => {:login => 'johndoe', :password => 'test'}
  790 + assert session[:user]
  791 + assert_equal 'johndoe', assigns(:current_user).login
  792 + assert_response :redirect
  793 + end
  794 +
  795 + should "redirect user on signup if a plugin doesn't allow user registration" do
  796 + class TestRegistrationPlugin < Noosfero::Plugin
  797 + def allow_user_registration
  798 + false
  799 + end
  800 + end
  801 + Noosfero::Plugin::Manager.any_instance.stubs(:enabled_plugins).returns([TestRegistrationPlugin.new])
  802 +
  803 + post :signup, :user => { :login => 'testuser', :password => '123456', :password_confirmation => '123456', :email => 'testuser@example.com' }
  804 + assert_response :redirect
  805 + end
  806 +
  807 + should "not display the new user button on login page if not allowed by any plugin" do
  808 + class Plugin1 < Noosfero::Plugin
  809 + def allow_user_registration
  810 + false
  811 + end
  812 + end
  813 +
  814 + class Plugin2 < Noosfero::Plugin
  815 + def allow_user_registration
  816 + true
  817 + end
  818 + end
  819 + Noosfero::Plugin::Manager.any_instance.stubs(:enabled_plugins).returns([Plugin1.new, Plugin2.new])
  820 +
  821 + get :login
  822 +
  823 + assert_no_tag :tag => 'a', :attributes => {:href => '/account/signup'}
  824 + end
  825 +
  826 + should "redirect user on forgot_password action if a plugin doesn't allow user to recover its password" do
  827 + class TestRegistrationPlugin < Noosfero::Plugin
  828 + def allow_password_recovery
  829 + false
  830 + end
  831 + end
  832 + Noosfero::Plugin::Manager.any_instance.stubs(:enabled_plugins).returns([TestRegistrationPlugin.new])
  833 +
  834 + #Redirect on get action
  835 + get :forgot_password
  836 + assert_response :redirect
  837 +
  838 + #Redirect on post action
  839 + post :forgot_password, :change_password => { :login => 'test', :email => 'test@localhost.localdomain' }
  840 + assert_response :redirect
  841 + end
  842 +
  843 + should "not display the forgot password button on login page if not allowed by any plugin" do
  844 + class Plugin1 < Noosfero::Plugin
  845 + def allow_password_recovery
  846 + false
  847 + end
  848 + end
  849 +
  850 + class Plugin2 < Noosfero::Plugin
  851 + def allow_password_recovery
  852 + true
  853 + end
  854 + end
  855 + Noosfero::Plugin::Manager.any_instance.stubs(:enabled_plugins).returns([Plugin1.new, Plugin2.new])
  856 +
  857 + get :login
  858 +
  859 + assert_no_tag :tag => 'a', :attributes => {:href => '/account/forgot_password'}
  860 + end
  861 +
  862 + should 'add extra content on login form from plugins' do
  863 + class Plugin1 < Noosfero::Plugin
  864 + def login_extra_contents
  865 + lambda {"<strong>Plugin1 text</strong>"}
  866 + end
  867 + end
  868 + class Plugin2 < Noosfero::Plugin
  869 + def login_extra_contents
  870 + lambda {"<strong>Plugin2 text</strong>"}
  871 + end
  872 + end
  873 +
  874 + Environment.default.enable_plugin(Plugin1.name)
  875 + Environment.default.enable_plugin(Plugin2.name)
  876 +
  877 + get :login
  878 +
  879 + assert_tag :tag => 'strong', :content => 'Plugin1 text'
  880 + assert_tag :tag => 'strong', :content => 'Plugin2 text'
  881 + end
  882 +
  883 +
780 884 protected
781 885 def new_user(options = {}, extra_options ={})
782 886 data = {:profile_data => person_data}
... ...
test/functional/home_controller_test.rb
... ... @@ -6,8 +6,11 @@ class HomeController; def rescue_action(e) raise e end; end
6 6  
7 7 class HomeControllerTest < ActionController::TestCase
8 8  
9   -# all_fixtures:profiles, :environments, :domains
10   -all_fixtures
  9 + def teardown
  10 + Thread.current[:enabled_plugins] = nil
  11 + end
  12 +
  13 + all_fixtures
11 14 def setup
12 15 @controller = HomeController.new
13 16 @request = ActionController::TestRequest.new
... ... @@ -93,4 +96,44 @@ all_fixtures
93 96 assert_tag :content => /Noosfero terms of use/
94 97 end
95 98  
  99 + should 'provide a link to make the user authentication' do
  100 + class Plugin1 < Noosfero::Plugin
  101 + def alternative_authentication_link
  102 + lambda {"<a href='plugin1'>Plugin1 link</a>"}
  103 + end
  104 + end
  105 + class Plugin2 < Noosfero::Plugin
  106 + def alternative_authentication_link
  107 + lambda {"<a href='plugin2'>Plugin2 link</a>"}
  108 + end
  109 + end
  110 +
  111 + Environment.default.enable_plugin(Plugin1)
  112 + Environment.default.enable_plugin(Plugin2)
  113 +
  114 + get :index
  115 +
  116 + assert_tag :tag => 'a', :content => 'Plugin1 link'
  117 + assert_tag :tag => 'a', :content => 'Plugin2 link'
  118 + end
  119 +
  120 + should "not display the new user button on login page if now allowed by any plugin" do
  121 + class Plugin1 < Noosfero::Plugin
  122 + def allow_user_registration
  123 + false
  124 + end
  125 + end
  126 +
  127 + class Plugin2 < Noosfero::Plugin
  128 + def allow_user_registration
  129 + true
  130 + end
  131 + end
  132 + Noosfero::Plugin::Manager.any_instance.stubs(:enabled_plugins).returns([Plugin1.new, Plugin2.new])
  133 +
  134 + get :index
  135 +
  136 + assert_no_tag :tag => 'a', :attributes => {:href => '/account/signup'}
  137 + end
  138 +
96 139 end
... ...
test/unit/user_test.rb
... ... @@ -403,12 +403,29 @@ class UserTest &lt; ActiveSupport::TestCase
403 403 assert_equal 'Test User', user.name
404 404 end
405 405  
406   - should 'respond name with login, if there is no person related' do
  406 + should 'respond name with login, if there is no person related and name defined' do
407 407 user = create_user('testuser')
408 408 user.person = nil
  409 + user.name = nil
409 410 assert_equal 'testuser', user.name
410 411 end
411 412  
  413 + should 'respond name with user name attribute' do
  414 + user = create_user('testuser')
  415 + user.person = nil
  416 + user.name = 'Another User'
  417 + user.login = 'Login User'
  418 + assert_equal 'Another User', user.name
  419 + end
  420 +
  421 + should 'respond name with related person name although user name attribute is defined' do
  422 + user = create_user('testuser')
  423 + user.person.name = 'Person Name'
  424 + user.name = 'Another User'
  425 + user.login = 'Login User'
  426 + assert_equal 'Person Name', user.name
  427 + end
  428 +
412 429 should 'have activation code' do
413 430 user = create_user('testuser')
414 431 assert_respond_to user, :activation_code
... ... @@ -499,6 +516,12 @@ class UserTest &lt; ActiveSupport::TestCase
499 516 assert !user.activate
500 517 end
501 518  
  519 + should 'be able to skip the password requirement' do
  520 + user = User.new(:login => 'quire', :email => 'quire@example.com')
  521 + user.not_require_password!
  522 + assert user.save!
  523 + end
  524 +
502 525 protected
503 526 def new_user(options = {})
504 527 user = User.new({ :login => 'quire', :email => 'quire@example.com', :password => 'quire', :password_confirmation => 'quire' }.merge(options))
... ...