##// END OF EJS Templates
revert r16322 (#24970)...
Toshi MARUYAMA -
r15941:5a86f95d290a
parent child
Show More
@@ -1,116 +1,116
1 1 source 'https://rubygems.org'
2 2
3 3 if Gem::Version.new(Bundler::VERSION) < Gem::Version.new('1.5.0')
4 4 abort "Redmine requires Bundler 1.5.0 or higher (you're using #{Bundler::VERSION}).\nPlease update with 'gem update bundler'."
5 5 end
6 6
7 7 gem "rails", "4.2.7.1"
8 8 gem "addressable", "2.4.0" if RUBY_VERSION < "2.0"
9 9 gem "jquery-rails", "~> 3.1.4"
10 10 gem "coderay", "~> 1.1.1"
11 11 gem "request_store", "1.0.5"
12 12 gem "mime-types", (RUBY_VERSION >= "2.0" ? "~> 3.0" : "~> 2.99")
13 13 gem "protected_attributes"
14 14 gem "actionpack-xml_parser"
15 15 gem "roadie-rails"
16 16 gem "mimemagic"
17 17
18 18 gem "nokogiri", "~> 1.6.8"
19 19
20 20 # Request at least rails-html-sanitizer 1.0.3 because of security advisories
21 21 gem "rails-html-sanitizer", ">= 1.0.3"
22 22
23 23 # Windows does not include zoneinfo files, so bundle the tzinfo-data gem
24 24 gem 'tzinfo-data', platforms: [:mingw, :x64_mingw, :mswin, :jruby]
25 25 gem "rbpdf", "~> 1.19.0"
26 26
27 27 # Optional gem for LDAP authentication
28 28 group :ldap do
29 gem "net-ldap", "~> 0.12.1"
29 gem "net-ldap", "~> 0.12.0"
30 30 end
31 31
32 32 # Optional gem for OpenID authentication
33 33 group :openid do
34 34 gem "ruby-openid", "~> 2.3.0", :require => "openid"
35 35 gem "rack-openid"
36 36 end
37 37
38 38 platforms :mri, :mingw, :x64_mingw do
39 39 # Optional gem for exporting the gantt to a PNG file, not supported with jruby
40 40 group :rmagick do
41 41 gem "rmagick", ">= 2.14.0"
42 42 end
43 43
44 44 # Optional Markdown support, not for JRuby
45 45 group :markdown do
46 46 gem "redcarpet", "~> 3.3.2"
47 47 end
48 48 end
49 49
50 50 platforms :jruby do
51 51 # jruby-openssl is bundled with JRuby 1.7.0
52 52 gem "jruby-openssl" if Object.const_defined?(:JRUBY_VERSION) && JRUBY_VERSION < '1.7.0'
53 53 gem "activerecord-jdbc-adapter", "~> 1.3.2"
54 54 end
55 55
56 56 # Include database gems for the adapters found in the database
57 57 # configuration file
58 58 require 'erb'
59 59 require 'yaml'
60 60 database_file = File.join(File.dirname(__FILE__), "config/database.yml")
61 61 if File.exist?(database_file)
62 62 database_config = YAML::load(ERB.new(IO.read(database_file)).result)
63 63 adapters = database_config.values.map {|c| c['adapter']}.compact.uniq
64 64 if adapters.any?
65 65 adapters.each do |adapter|
66 66 case adapter
67 67 when 'mysql2'
68 68 gem "mysql2", "~> 0.3.11", :platforms => [:mri, :mingw, :x64_mingw]
69 69 gem "activerecord-jdbcmysql-adapter", :platforms => :jruby
70 70 when 'mysql'
71 71 gem "activerecord-jdbcmysql-adapter", :platforms => :jruby
72 72 when /postgresql/
73 73 gem "pg", "~> 0.18.1", :platforms => [:mri, :mingw, :x64_mingw]
74 74 gem "activerecord-jdbcpostgresql-adapter", :platforms => :jruby
75 75 when /sqlite3/
76 76 gem "sqlite3", :platforms => [:mri, :mingw, :x64_mingw]
77 77 gem "jdbc-sqlite3", ">= 3.8.10.1", :platforms => :jruby
78 78 gem "activerecord-jdbcsqlite3-adapter", :platforms => :jruby
79 79 when /sqlserver/
80 80 gem "tiny_tds", (RUBY_VERSION >= "2.0" ? "~> 1.0.5" : "~> 0.7.0"), :platforms => [:mri, :mingw, :x64_mingw]
81 81 gem "activerecord-sqlserver-adapter", :platforms => [:mri, :mingw, :x64_mingw]
82 82 else
83 83 warn("Unknown database adapter `#{adapter}` found in config/database.yml, use Gemfile.local to load your own database gems")
84 84 end
85 85 end
86 86 else
87 87 warn("No adapter found in config/database.yml, please configure it first")
88 88 end
89 89 else
90 90 warn("Please configure your config/database.yml first")
91 91 end
92 92
93 93 group :development do
94 94 gem "rdoc", "~> 4.3"
95 95 gem "yard"
96 96 end
97 97
98 98 group :test do
99 99 gem "minitest"
100 100 gem "rails-dom-testing"
101 101 gem "mocha"
102 102 gem "simplecov", "~> 0.9.1", :require => false
103 103 # For running UI tests
104 104 gem "capybara"
105 105 gem "selenium-webdriver", "~> 2.53.4"
106 106 end
107 107
108 108 local_gemfile = File.join(File.dirname(__FILE__), "Gemfile.local")
109 109 if File.exists?(local_gemfile)
110 110 eval_gemfile local_gemfile
111 111 end
112 112
113 113 # Load plugins' Gemfiles
114 114 Dir.glob File.expand_path("../plugins/*/{Gemfile,PluginGemfile}", __FILE__) do |file|
115 115 eval_gemfile file
116 116 end
@@ -1,209 +1,209
1 1 # Redmine - project management software
2 2 # Copyright (C) 2006-2016 Jean-Philippe Lang
3 3 #
4 4 # This program is free software; you can redistribute it and/or
5 5 # modify it under the terms of the GNU General Public License
6 6 # as published by the Free Software Foundation; either version 2
7 7 # of the License, or (at your option) any later version.
8 8 #
9 9 # This program is distributed in the hope that it will be useful,
10 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 # GNU General Public License for more details.
13 13 #
14 14 # You should have received a copy of the GNU General Public License
15 15 # along with this program; if not, write to the Free Software
16 16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 17
18 18 require 'net/ldap'
19 19 require 'net/ldap/dn'
20 20 require 'timeout'
21 21
22 22 class AuthSourceLdap < AuthSource
23 23 NETWORK_EXCEPTIONS = [
24 Net::LDAP::Error,
24 Net::LDAP::LdapError,
25 25 Errno::ECONNABORTED, Errno::ECONNREFUSED, Errno::ECONNRESET,
26 26 Errno::EHOSTDOWN, Errno::EHOSTUNREACH,
27 27 SocketError
28 28 ]
29 29
30 30 validates_presence_of :host, :port, :attr_login
31 31 validates_length_of :name, :host, :maximum => 60, :allow_nil => true
32 32 validates_length_of :account, :account_password, :base_dn, :maximum => 255, :allow_blank => true
33 33 validates_length_of :attr_login, :attr_firstname, :attr_lastname, :attr_mail, :maximum => 30, :allow_nil => true
34 34 validates_numericality_of :port, :only_integer => true
35 35 validates_numericality_of :timeout, :only_integer => true, :allow_blank => true
36 36 validate :validate_filter
37 37
38 38 before_validation :strip_ldap_attributes
39 39
40 40 def initialize(attributes=nil, *args)
41 41 super
42 42 self.port = 389 if self.port == 0
43 43 end
44 44
45 45 def authenticate(login, password)
46 46 return nil if login.blank? || password.blank?
47 47
48 48 with_timeout do
49 49 attrs = get_user_dn(login, password)
50 50 if attrs && attrs[:dn] && authenticate_dn(attrs[:dn], password)
51 51 logger.debug "Authentication successful for '#{login}'" if logger && logger.debug?
52 52 return attrs.except(:dn)
53 53 end
54 54 end
55 55 rescue *NETWORK_EXCEPTIONS => e
56 56 raise AuthSourceException.new(e.message)
57 57 end
58 58
59 59 # Test the connection to the LDAP
60 60 def test_connection
61 61 with_timeout do
62 62 ldap_con = initialize_ldap_con(self.account, self.account_password)
63 63 ldap_con.open { }
64 64
65 65 if self.account.present? && !self.account.include?("$login") && self.account_password.present?
66 66 ldap_auth = authenticate_dn(self.account, self.account_password)
67 67 raise AuthSourceException.new(l(:error_ldap_bind_credentials)) if !ldap_auth
68 68 end
69 69 end
70 70 rescue *NETWORK_EXCEPTIONS => e
71 71 raise AuthSourceException.new(e.message)
72 72 end
73 73
74 74 def auth_method_name
75 75 "LDAP"
76 76 end
77 77
78 78 # Returns true if this source can be searched for users
79 79 def searchable?
80 80 !account.to_s.include?("$login") && %w(login firstname lastname mail).all? {|a| send("attr_#{a}?")}
81 81 end
82 82
83 83 # Searches the source for users and returns an array of results
84 84 def search(q)
85 85 q = q.to_s.strip
86 86 return [] unless searchable? && q.present?
87 87
88 88 results = []
89 89 search_filter = base_filter & Net::LDAP::Filter.begins(self.attr_login, q)
90 90 ldap_con = initialize_ldap_con(self.account, self.account_password)
91 91 ldap_con.search(:base => self.base_dn,
92 92 :filter => search_filter,
93 93 :attributes => ['dn', self.attr_login, self.attr_firstname, self.attr_lastname, self.attr_mail],
94 94 :size => 10) do |entry|
95 95 attrs = get_user_attributes_from_ldap_entry(entry)
96 96 attrs[:login] = AuthSourceLdap.get_attr(entry, self.attr_login)
97 97 results << attrs
98 98 end
99 99 results
100 100 rescue *NETWORK_EXCEPTIONS => e
101 101 raise AuthSourceException.new(e.message)
102 102 end
103 103
104 104 private
105 105
106 106 def with_timeout(&block)
107 107 timeout = self.timeout
108 108 timeout = 20 unless timeout && timeout > 0
109 109 Timeout.timeout(timeout) do
110 110 return yield
111 111 end
112 112 rescue Timeout::Error => e
113 113 raise AuthSourceTimeoutException.new(e.message)
114 114 end
115 115
116 116 def ldap_filter
117 117 if filter.present?
118 118 Net::LDAP::Filter.construct(filter)
119 119 end
120 rescue Net::LDAP::Error, Net::LDAP::FilterSyntaxInvalidError
120 rescue Net::LDAP::LdapError, Net::LDAP::FilterSyntaxInvalidError
121 121 nil
122 122 end
123 123
124 124 def base_filter
125 125 filter = Net::LDAP::Filter.eq("objectClass", "*")
126 126 if f = ldap_filter
127 127 filter = filter & f
128 128 end
129 129 filter
130 130 end
131 131
132 132 def validate_filter
133 133 if filter.present? && ldap_filter.nil?
134 134 errors.add(:filter, :invalid)
135 135 end
136 136 end
137 137
138 138 def strip_ldap_attributes
139 139 [:attr_login, :attr_firstname, :attr_lastname, :attr_mail].each do |attr|
140 140 write_attribute(attr, read_attribute(attr).strip) unless read_attribute(attr).nil?
141 141 end
142 142 end
143 143
144 144 def initialize_ldap_con(ldap_user, ldap_password)
145 145 options = { :host => self.host,
146 146 :port => self.port,
147 147 :encryption => (self.tls ? :simple_tls : nil)
148 148 }
149 149 options.merge!(:auth => { :method => :simple, :username => ldap_user, :password => ldap_password }) unless ldap_user.blank? && ldap_password.blank?
150 150 Net::LDAP.new options
151 151 end
152 152
153 153 def get_user_attributes_from_ldap_entry(entry)
154 154 {
155 155 :dn => entry.dn,
156 156 :firstname => AuthSourceLdap.get_attr(entry, self.attr_firstname),
157 157 :lastname => AuthSourceLdap.get_attr(entry, self.attr_lastname),
158 158 :mail => AuthSourceLdap.get_attr(entry, self.attr_mail),
159 159 :auth_source_id => self.id
160 160 }
161 161 end
162 162
163 163 # Return the attributes needed for the LDAP search. It will only
164 164 # include the user attributes if on-the-fly registration is enabled
165 165 def search_attributes
166 166 if onthefly_register?
167 167 ['dn', self.attr_firstname, self.attr_lastname, self.attr_mail]
168 168 else
169 169 ['dn']
170 170 end
171 171 end
172 172
173 173 # Check if a DN (user record) authenticates with the password
174 174 def authenticate_dn(dn, password)
175 175 if dn.present? && password.present?
176 176 initialize_ldap_con(dn, password).bind
177 177 end
178 178 end
179 179
180 180 # Get the user's dn and any attributes for them, given their login
181 181 def get_user_dn(login, password)
182 182 ldap_con = nil
183 183 if self.account && self.account.include?("$login")
184 184 ldap_con = initialize_ldap_con(self.account.sub("$login", Net::LDAP::DN.escape(login)), password)
185 185 else
186 186 ldap_con = initialize_ldap_con(self.account, self.account_password)
187 187 end
188 188 attrs = {}
189 189 search_filter = base_filter & Net::LDAP::Filter.eq(self.attr_login, login)
190 190 ldap_con.search( :base => self.base_dn,
191 191 :filter => search_filter,
192 192 :attributes=> search_attributes) do |entry|
193 193 if onthefly_register?
194 194 attrs = get_user_attributes_from_ldap_entry(entry)
195 195 else
196 196 attrs = {:dn => entry.dn}
197 197 end
198 198 logger.debug "DN found for #{login}: #{attrs[:dn]}" if logger && logger.debug?
199 199 end
200 200 attrs
201 201 end
202 202
203 203 def self.get_attr(entry, attr_name)
204 204 if !attr_name.blank?
205 205 value = entry[attr_name].is_a?(Array) ? entry[attr_name].first : entry[attr_name]
206 206 value.to_s.force_encoding('UTF-8')
207 207 end
208 208 end
209 209 end
@@ -1,160 +1,160
1 1 # Redmine - project management software
2 2 # Copyright (C) 2006-2016 Jean-Philippe Lang
3 3 #
4 4 # This program is free software; you can redistribute it and/or
5 5 # modify it under the terms of the GNU General Public License
6 6 # as published by the Free Software Foundation; either version 2
7 7 # of the License, or (at your option) any later version.
8 8 #
9 9 # This program is distributed in the hope that it will be useful,
10 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 # GNU General Public License for more details.
13 13 #
14 14 # You should have received a copy of the GNU General Public License
15 15 # along with this program; if not, write to the Free Software
16 16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 17
18 18 require File.expand_path('../../test_helper', __FILE__)
19 19
20 20 class AuthSourcesControllerTest < Redmine::ControllerTest
21 21 fixtures :users, :auth_sources
22 22
23 23 def setup
24 24 @request.session[:user_id] = 1
25 25 end
26 26
27 27 def test_index
28 28 get :index
29 29 assert_response :success
30 30 end
31 31
32 32 def test_new
33 33 get :new
34 34 assert_response :success
35 35
36 36 assert_select 'form#auth_source_form' do
37 37 assert_select 'input[name=type][value=AuthSourceLdap]'
38 38 assert_select 'input[name=?]', 'auth_source[host]'
39 39 end
40 40 end
41 41
42 42 def test_new_with_invalid_type_should_respond_with_404
43 43 get :new, :type => 'foo'
44 44 assert_response 404
45 45 end
46 46
47 47 def test_create
48 48 assert_difference 'AuthSourceLdap.count' do
49 49 post :create, :type => 'AuthSourceLdap', :auth_source => {:name => 'Test', :host => '127.0.0.1', :port => '389', :attr_login => 'cn'}
50 50 assert_redirected_to '/auth_sources'
51 51 end
52 52
53 53 source = AuthSourceLdap.order('id DESC').first
54 54 assert_equal 'Test', source.name
55 55 assert_equal '127.0.0.1', source.host
56 56 assert_equal 389, source.port
57 57 assert_equal 'cn', source.attr_login
58 58 end
59 59
60 60 def test_create_with_failure
61 61 assert_no_difference 'AuthSourceLdap.count' do
62 62 post :create, :type => 'AuthSourceLdap',
63 63 :auth_source => {:name => 'Test', :host => '',
64 64 :port => '389', :attr_login => 'cn'}
65 65 assert_response :success
66 66 end
67 67 assert_select_error /host cannot be blank/i
68 68 end
69 69
70 70 def test_edit
71 71 get :edit, :id => 1
72 72 assert_response :success
73 73
74 74 assert_select 'form#auth_source_form' do
75 75 assert_select 'input[name=?]', 'auth_source[host]'
76 76 end
77 77 end
78 78
79 79 def test_edit_should_not_contain_password
80 80 AuthSource.find(1).update_column :account_password, 'secret'
81 81
82 82 get :edit, :id => 1
83 83 assert_response :success
84 84 assert_select 'input[value=secret]', 0
85 85 assert_select 'input[name=dummy_password][value^=xxxxxx]'
86 86 end
87 87
88 88 def test_edit_invalid_should_respond_with_404
89 89 get :edit, :id => 99
90 90 assert_response 404
91 91 end
92 92
93 93 def test_update
94 94 put :update, :id => 1,
95 95 :auth_source => {:name => 'Renamed', :host => '192.168.0.10',
96 96 :port => '389', :attr_login => 'uid'}
97 97 assert_redirected_to '/auth_sources'
98 98 source = AuthSourceLdap.find(1)
99 99 assert_equal 'Renamed', source.name
100 100 assert_equal '192.168.0.10', source.host
101 101 end
102 102
103 103 def test_update_with_failure
104 104 put :update, :id => 1,
105 105 :auth_source => {:name => 'Renamed', :host => '',
106 106 :port => '389', :attr_login => 'uid'}
107 107 assert_response :success
108 108 assert_select_error /host cannot be blank/i
109 109 end
110 110
111 111 def test_destroy
112 112 assert_difference 'AuthSourceLdap.count', -1 do
113 113 delete :destroy, :id => 1
114 114 assert_redirected_to '/auth_sources'
115 115 end
116 116 end
117 117
118 118 def test_destroy_auth_source_in_use
119 119 User.find(2).update_attribute :auth_source_id, 1
120 120
121 121 assert_no_difference 'AuthSourceLdap.count' do
122 122 delete :destroy, :id => 1
123 123 assert_redirected_to '/auth_sources'
124 124 end
125 125 end
126 126
127 127 def test_test_connection
128 128 AuthSourceLdap.any_instance.stubs(:test_connection).returns(true)
129 129
130 130 get :test_connection, :id => 1
131 131 assert_redirected_to '/auth_sources'
132 132 assert_not_nil flash[:notice]
133 133 assert_match /successful/i, flash[:notice]
134 134 end
135 135
136 136 def test_test_connection_with_failure
137 AuthSourceLdap.any_instance.stubs(:initialize_ldap_con).raises(Net::LDAP::Error.new("Something went wrong"))
137 AuthSourceLdap.any_instance.stubs(:initialize_ldap_con).raises(Net::LDAP::LdapError.new("Something went wrong"))
138 138
139 139 get :test_connection, :id => 1
140 140 assert_redirected_to '/auth_sources'
141 141 assert_not_nil flash[:error]
142 142 assert_include 'Something went wrong', flash[:error]
143 143 end
144 144
145 145 def test_autocomplete_for_new_user
146 146 AuthSource.expects(:search).with('foo').returns([
147 147 {:login => 'foo1', :firstname => 'John', :lastname => 'Smith', :mail => 'foo1@example.net', :auth_source_id => 1},
148 148 {:login => 'Smith', :firstname => 'John', :lastname => 'Doe', :mail => 'foo2@example.net', :auth_source_id => 1}
149 149 ])
150 150
151 151 get :autocomplete_for_new_user, :term => 'foo'
152 152 assert_response :success
153 153 assert_equal 'application/json', response.content_type
154 154 json = ActiveSupport::JSON.decode(response.body)
155 155 assert_kind_of Array, json
156 156 assert_equal 2, json.size
157 157 assert_equal 'foo1', json.first['value']
158 158 assert_equal 'foo1 (John Smith)', json.first['label']
159 159 end
160 160 end
@@ -1,234 +1,234
1 1 # Redmine - project management software
2 2 # Copyright (C) 2006-2016 Jean-Philippe Lang
3 3 #
4 4 # This program is free software; you can redistribute it and/or
5 5 # modify it under the terms of the GNU General Public License
6 6 # as published by the Free Software Foundation; either version 2
7 7 # of the License, or (at your option) any later version.
8 8 #
9 9 # This program is distributed in the hope that it will be useful,
10 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 # GNU General Public License for more details.
13 13 #
14 14 # You should have received a copy of the GNU General Public License
15 15 # along with this program; if not, write to the Free Software
16 16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 17
18 18 require File.expand_path('../../test_helper', __FILE__)
19 19
20 20 class AuthSourceLdapTest < ActiveSupport::TestCase
21 21 include Redmine::I18n
22 22 fixtures :auth_sources
23 23
24 24 def setup
25 25 end
26 26
27 27 def test_initialize
28 28 auth_source = AuthSourceLdap.new
29 29 assert_nil auth_source.id
30 30 assert_equal "AuthSourceLdap", auth_source.type
31 31 assert_equal "", auth_source.name
32 32 assert_nil auth_source.host
33 33 assert_nil auth_source.port
34 34 assert_nil auth_source.account
35 35 assert_equal "", auth_source.account_password
36 36 assert_nil auth_source.base_dn
37 37 assert_nil auth_source.attr_login
38 38 assert_nil auth_source.attr_firstname
39 39 assert_nil auth_source.attr_lastname
40 40 assert_nil auth_source.attr_mail
41 41 assert_equal false, auth_source.onthefly_register
42 42 assert_equal false, auth_source.tls
43 43 assert_nil auth_source.filter
44 44 assert_nil auth_source.timeout
45 45 end
46 46
47 47 def test_create
48 48 a = AuthSourceLdap.new(:name => 'My LDAP', :host => 'ldap.example.net', :port => 389, :base_dn => 'dc=example,dc=net', :attr_login => 'sAMAccountName')
49 49 assert a.save
50 50 end
51 51
52 52 def test_should_strip_ldap_attributes
53 53 a = AuthSourceLdap.new(:name => 'My LDAP', :host => 'ldap.example.net', :port => 389, :base_dn => 'dc=example,dc=net', :attr_login => 'sAMAccountName',
54 54 :attr_firstname => 'givenName ')
55 55 assert a.save
56 56 assert_equal 'givenName', a.reload.attr_firstname
57 57 end
58 58
59 59 def test_replace_port_zero_to_389
60 60 a = AuthSourceLdap.new(
61 61 :name => 'My LDAP', :host => 'ldap.example.net', :port => 0,
62 62 :base_dn => 'dc=example,dc=net', :attr_login => 'sAMAccountName',
63 63 :attr_firstname => 'givenName ')
64 64 assert a.save
65 65 assert_equal 389, a.port
66 66 end
67 67
68 68 def test_filter_should_be_validated
69 69 set_language_if_valid 'en'
70 70
71 71 a = AuthSourceLdap.new(:name => 'My LDAP', :host => 'ldap.example.net', :port => 389, :attr_login => 'sn')
72 72 a.filter = "(mail=*@redmine.org"
73 73 assert !a.valid?
74 74 assert_include "LDAP filter is invalid", a.errors.full_messages
75 75
76 76 a.filter = "(mail=*@redmine.org)"
77 77 assert a.valid?
78 78 end
79 79
80 80 if ldap_configured?
81 81 test '#authenticate with a valid LDAP user should return the user attributes' do
82 82 auth = AuthSourceLdap.find(1)
83 83 auth.update_attribute :onthefly_register, true
84 84
85 85 attributes = auth.authenticate('example1','123456')
86 86 assert attributes.is_a?(Hash), "An hash was not returned"
87 87 assert_equal 'Example', attributes[:firstname]
88 88 assert_equal 'One', attributes[:lastname]
89 89 assert_equal 'example1@redmine.org', attributes[:mail]
90 90 assert_equal auth.id, attributes[:auth_source_id]
91 91 attributes.keys.each do |attribute|
92 92 assert User.new.respond_to?("#{attribute}="), "Unexpected :#{attribute} attribute returned"
93 93 end
94 94 end
95 95
96 96 test '#authenticate with an invalid LDAP user should return nil' do
97 97 auth = AuthSourceLdap.find(1)
98 98 assert_nil auth.authenticate('nouser','123456')
99 99 end
100 100
101 101 test '#authenticate without a login should return nil' do
102 102 auth = AuthSourceLdap.find(1)
103 103 assert_nil auth.authenticate('','123456')
104 104 end
105 105
106 106 test '#authenticate without a password should return nil' do
107 107 auth = AuthSourceLdap.find(1)
108 108 assert_nil auth.authenticate('edavis','')
109 109 end
110 110
111 111 test '#authenticate without filter should return any user' do
112 112 auth = AuthSourceLdap.find(1)
113 113 assert auth.authenticate('example1','123456')
114 114 assert auth.authenticate('edavis', '123456')
115 115 end
116 116
117 117 test '#authenticate with filter should return user who matches the filter only' do
118 118 auth = AuthSourceLdap.find(1)
119 119 auth.filter = "(mail=*@redmine.org)"
120 120
121 121 assert auth.authenticate('example1','123456')
122 122 assert_nil auth.authenticate('edavis', '123456')
123 123 end
124 124
125 125 def test_authenticate_should_timeout
126 126 auth_source = AuthSourceLdap.find(1)
127 127 auth_source.timeout = 1
128 128 def auth_source.initialize_ldap_con(*args); sleep(5); end
129 129
130 130 assert_raise AuthSourceTimeoutException do
131 131 auth_source.authenticate 'example1', '123456'
132 132 end
133 133 end
134 134
135 135 def test_search_should_return_matching_entries
136 136 results = AuthSource.search("exa")
137 137 assert_equal 1, results.size
138 138 result = results.first
139 139 assert_kind_of Hash, result
140 140 assert_equal "example1", result[:login]
141 141 assert_equal "Example", result[:firstname]
142 142 assert_equal "One", result[:lastname]
143 143 assert_equal "example1@redmine.org", result[:mail]
144 144 assert_equal 1, result[:auth_source_id]
145 145 end
146 146
147 147 def test_search_with_no_match_should_return_an_empty_array
148 148 results = AuthSource.search("wro")
149 149 assert_equal [], results
150 150 end
151 151
152 152 def test_search_with_exception_should_return_an_empty_array
153 Net::LDAP.stubs(:new).raises(Net::LDAP::Error, 'Cannot connect')
153 Net::LDAP.stubs(:new).raises(Net::LDAP::LdapError, 'Cannot connect')
154 154
155 155 results = AuthSource.search("exa")
156 156 assert_equal [], results
157 157 end
158 158
159 159 def test_test_connection_with_correct_host_and_port
160 160 auth_source = AuthSourceLdap.find(1)
161 161
162 162 assert_nothing_raised Net::LDAP::Error do
163 163 auth_source.test_connection
164 164 end
165 165 end
166 166
167 167 def test_test_connection_with_incorrect_host
168 168 auth_source = AuthSourceLdap.find(1)
169 169 auth_source.host = "badhost"
170 170 auth_source.save!
171 171
172 172 assert_raise Net::LDAP::Error do
173 173 auth_source.test_connection
174 174 end
175 175 end
176 176
177 177 def test_test_connection_with_incorrect_port
178 178 auth_source = AuthSourceLdap.find(1)
179 179 auth_source.port = 1234
180 180 auth_source.save!
181 181
182 182 assert_raise Net::LDAP::Error do
183 183 auth_source.test_connection
184 184 end
185 185 end
186 186
187 187 def test_test_connection_bind_with_account_and_password
188 188 auth_source = AuthSourceLdap.find(1)
189 189 auth_source.account = "cn=admin,dc=redmine,dc=org"
190 190 auth_source.account_password = "secret"
191 191 auth_source.save!
192 192
193 193 assert_equal "cn=admin,dc=redmine,dc=org", auth_source.account
194 194 assert_equal "secret", auth_source.account_password
195 195 assert_nil auth_source.test_connection
196 196 end
197 197
198 198 def test_test_connection_bind_without_account_and_password
199 199 auth_source = AuthSourceLdap.find(1)
200 200
201 201 assert_nil auth_source.account
202 202 assert_equal "", auth_source.account_password
203 203 assert_nil auth_source.test_connection
204 204 end
205 205
206 206 def test_test_connection_bind_with_incorrect_account
207 207 auth_source = AuthSourceLdap.find(1)
208 208 auth_source.account = "cn=baduser,dc=redmine,dc=org"
209 209 auth_source.account_password = "secret"
210 210 auth_source.save!
211 211
212 212 assert_equal "cn=baduser,dc=redmine,dc=org", auth_source.account
213 213 assert_equal "secret", auth_source.account_password
214 214 assert_raise AuthSourceException do
215 215 auth_source.test_connection
216 216 end
217 217 end
218 218
219 219 def test_test_connection_bind_with_incorrect_password
220 220 auth_source = AuthSourceLdap.find(1)
221 221 auth_source.account = "cn=admin,dc=redmine,dc=org"
222 222 auth_source.account_password = "badpassword"
223 223 auth_source.save!
224 224
225 225 assert_equal "cn=admin,dc=redmine,dc=org", auth_source.account
226 226 assert_equal "badpassword", auth_source.account_password
227 227 assert_raise AuthSourceException do
228 228 auth_source.test_connection
229 229 end
230 230 end
231 231 else
232 232 puts '(Test LDAP server not configured)'
233 233 end
234 234 end
@@ -1,1238 +1,1238
1 1 # Redmine - project management software
2 2 # Copyright (C) 2006-2016 Jean-Philippe Lang
3 3 #
4 4 # This program is free software; you can redistribute it and/or
5 5 # modify it under the terms of the GNU General Public License
6 6 # as published by the Free Software Foundation; either version 2
7 7 # of the License, or (at your option) any later version.
8 8 #
9 9 # This program is distributed in the hope that it will be useful,
10 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 # GNU General Public License for more details.
13 13 #
14 14 # You should have received a copy of the GNU General Public License
15 15 # along with this program; if not, write to the Free Software
16 16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 17
18 18 require File.expand_path('../../test_helper', __FILE__)
19 19
20 20 class UserTest < ActiveSupport::TestCase
21 21 fixtures :users, :email_addresses, :members, :projects, :roles, :member_roles, :auth_sources,
22 22 :trackers, :issue_statuses,
23 23 :projects_trackers,
24 24 :watchers,
25 25 :issue_categories, :enumerations, :issues,
26 26 :journals, :journal_details,
27 27 :groups_users,
28 28 :enabled_modules,
29 29 :tokens
30 30
31 31 include Redmine::I18n
32 32
33 33 def setup
34 34 @admin = User.find(1)
35 35 @jsmith = User.find(2)
36 36 @dlopper = User.find(3)
37 37 end
38 38
39 39 def test_sorted_scope_should_sort_user_by_display_name
40 40 # Use .active to ignore anonymous with localized display name
41 41 assert_equal User.active.map(&:name).map(&:downcase).sort,
42 42 User.active.sorted.map(&:name).map(&:downcase)
43 43 end
44 44
45 45 def test_generate
46 46 User.generate!(:firstname => 'Testing connection')
47 47 User.generate!(:firstname => 'Testing connection')
48 48 assert_equal 2, User.where(:firstname => 'Testing connection').count
49 49 end
50 50
51 51 def test_truth
52 52 assert_kind_of User, @jsmith
53 53 end
54 54
55 55 def test_should_validate_status
56 56 user = User.new
57 57 user.status = 0
58 58
59 59 assert !user.save
60 60 assert_include I18n.translate('activerecord.errors.messages.invalid'), user.errors[:status]
61 61 end
62 62
63 63 def test_mail_should_be_stripped
64 64 u = User.new
65 65 u.mail = " foo@bar.com "
66 66 assert_equal "foo@bar.com", u.mail
67 67 end
68 68
69 69 def test_should_create_email_address
70 70 u = User.new(:firstname => "new", :lastname => "user")
71 71 u.login = "create_email_address"
72 72 u.mail = "defaultemail@somenet.foo"
73 73 assert u.save
74 74 u.reload
75 75 assert u.email_address
76 76 assert_equal "defaultemail@somenet.foo", u.email_address.address
77 77 assert_equal true, u.email_address.is_default
78 78 assert_equal true, u.email_address.notify
79 79 end
80 80
81 81 def test_should_not_create_user_without_mail
82 82 set_language_if_valid 'en'
83 83 u = User.new(:firstname => "new", :lastname => "user")
84 84 u.login = "user_without_mail"
85 85 assert !u.save
86 86 assert_equal ["Email #{I18n.translate('activerecord.errors.messages.blank')}"], u.errors.full_messages
87 87 end
88 88
89 89 def test_should_not_create_user_with_blank_mail
90 90 set_language_if_valid 'en'
91 91 u = User.new(:firstname => "new", :lastname => "user")
92 92 u.login = "user_with_blank_mail"
93 93 u.mail = ''
94 94 assert !u.save
95 95 assert_equal ["Email #{I18n.translate('activerecord.errors.messages.blank')}"], u.errors.full_messages
96 96 end
97 97
98 98 def test_should_not_update_user_with_blank_mail
99 99 set_language_if_valid 'en'
100 100 u = User.find(2)
101 101 u.mail = ''
102 102 assert !u.save
103 103 assert_equal ["Email #{I18n.translate('activerecord.errors.messages.blank')}"], u.errors.full_messages
104 104 end
105 105
106 106 def test_login_length_validation
107 107 user = User.new(:firstname => "new", :lastname => "user", :mail => "newuser@somenet.foo")
108 108 user.login = "x" * (User::LOGIN_LENGTH_LIMIT+1)
109 109 assert !user.valid?
110 110
111 111 user.login = "x" * (User::LOGIN_LENGTH_LIMIT)
112 112 assert user.valid?
113 113 assert user.save
114 114 end
115 115
116 116 def test_generate_password_should_respect_minimum_password_length
117 117 with_settings :password_min_length => 15 do
118 118 user = User.generate!(:generate_password => true)
119 119 assert user.password.length >= 15
120 120 end
121 121 end
122 122
123 123 def test_generate_password_should_not_generate_password_with_less_than_10_characters
124 124 with_settings :password_min_length => 4 do
125 125 user = User.generate!(:generate_password => true)
126 126 assert user.password.length >= 10
127 127 end
128 128 end
129 129
130 130 def test_generate_password_on_create_should_set_password
131 131 user = User.new(:firstname => "new", :lastname => "user", :mail => "newuser@somenet.foo")
132 132 user.login = "newuser"
133 133 user.generate_password = true
134 134 assert user.save
135 135
136 136 password = user.password
137 137 assert user.check_password?(password)
138 138 end
139 139
140 140 def test_generate_password_on_update_should_update_password
141 141 user = User.find(2)
142 142 hash = user.hashed_password
143 143 user.generate_password = true
144 144 assert user.save
145 145
146 146 password = user.password
147 147 assert user.check_password?(password)
148 148 assert_not_equal hash, user.reload.hashed_password
149 149 end
150 150
151 151 def test_create
152 152 user = User.new(:firstname => "new", :lastname => "user", :mail => "newuser@somenet.foo")
153 153
154 154 user.login = "jsmith"
155 155 user.password, user.password_confirmation = "password", "password"
156 156 # login uniqueness
157 157 assert !user.save
158 158 assert_equal 1, user.errors.count
159 159
160 160 user.login = "newuser"
161 161 user.password, user.password_confirmation = "password", "pass"
162 162 # password confirmation
163 163 assert !user.save
164 164 assert_equal 1, user.errors.count
165 165
166 166 user.password, user.password_confirmation = "password", "password"
167 167 assert user.save
168 168 end
169 169
170 170 def test_user_before_create_should_set_the_mail_notification_to_the_default_setting
171 171 @user1 = User.generate!
172 172 assert_equal 'only_my_events', @user1.mail_notification
173 173 with_settings :default_notification_option => 'all' do
174 174 @user2 = User.generate!
175 175 assert_equal 'all', @user2.mail_notification
176 176 end
177 177 end
178 178
179 179 def test_user_login_should_be_case_insensitive
180 180 u = User.new(:firstname => "new", :lastname => "user", :mail => "newuser@somenet.foo")
181 181 u.login = 'newuser'
182 182 u.password, u.password_confirmation = "password", "password"
183 183 assert u.save
184 184 u = User.new(:firstname => "Similar", :lastname => "User",
185 185 :mail => "similaruser@somenet.foo")
186 186 u.login = 'NewUser'
187 187 u.password, u.password_confirmation = "password", "password"
188 188 assert !u.save
189 189 assert_include I18n.translate('activerecord.errors.messages.taken'), u.errors[:login]
190 190 end
191 191
192 192 def test_mail_uniqueness_should_not_be_case_sensitive
193 193 set_language_if_valid 'en'
194 194 u = User.new(:firstname => "new", :lastname => "user", :mail => "newuser@somenet.foo")
195 195 u.login = 'newuser1'
196 196 u.password, u.password_confirmation = "password", "password"
197 197 assert u.save
198 198
199 199 u = User.new(:firstname => "new", :lastname => "user", :mail => "newUser@Somenet.foo")
200 200 u.login = 'newuser2'
201 201 u.password, u.password_confirmation = "password", "password"
202 202 assert !u.save
203 203 assert_include "Email #{I18n.translate('activerecord.errors.messages.taken')}", u.errors.full_messages
204 204 end
205 205
206 206 def test_update
207 207 assert_equal "admin", @admin.login
208 208 @admin.login = "john"
209 209 assert @admin.save, @admin.errors.full_messages.join("; ")
210 210 @admin.reload
211 211 assert_equal "john", @admin.login
212 212 end
213 213
214 214 def test_update_should_not_fail_for_legacy_user_with_different_case_logins
215 215 u1 = User.new(:firstname => "new", :lastname => "user", :mail => "newuser1@somenet.foo")
216 216 u1.login = 'newuser1'
217 217 assert u1.save
218 218
219 219 u2 = User.new(:firstname => "new", :lastname => "user", :mail => "newuser2@somenet.foo")
220 220 u2.login = 'newuser1'
221 221 assert u2.save(:validate => false)
222 222
223 223 user = User.find(u2.id)
224 224 user.firstname = "firstname"
225 225 assert user.save, "Save failed"
226 226 end
227 227
228 228 def test_destroy_should_delete_members_and_roles
229 229 members = Member.where(:user_id => 2)
230 230 ms = members.count
231 231 rs = members.collect(&:roles).flatten.size
232 232 assert ms > 0
233 233 assert rs > 0
234 234 assert_difference 'Member.count', - ms do
235 235 assert_difference 'MemberRole.count', - rs do
236 236 User.find(2).destroy
237 237 end
238 238 end
239 239 assert_nil User.find_by_id(2)
240 240 assert_equal 0, Member.where(:user_id => 2).count
241 241 end
242 242
243 243 def test_destroy_should_update_attachments
244 244 attachment = Attachment.create!(:container => Project.find(1),
245 245 :file => uploaded_test_file("testfile.txt", "text/plain"),
246 246 :author_id => 2)
247 247
248 248 User.find(2).destroy
249 249 assert_nil User.find_by_id(2)
250 250 assert_equal User.anonymous, attachment.reload.author
251 251 end
252 252
253 253 def test_destroy_should_update_comments
254 254 comment = Comment.create!(
255 255 :commented => News.create!(:project_id => 1,
256 256 :author_id => 1, :title => 'foo', :description => 'foo'),
257 257 :author => User.find(2),
258 258 :comments => 'foo'
259 259 )
260 260
261 261 User.find(2).destroy
262 262 assert_nil User.find_by_id(2)
263 263 assert_equal User.anonymous, comment.reload.author
264 264 end
265 265
266 266 def test_destroy_should_update_issues
267 267 issue = Issue.create!(:project_id => 1, :author_id => 2,
268 268 :tracker_id => 1, :subject => 'foo')
269 269
270 270 User.find(2).destroy
271 271 assert_nil User.find_by_id(2)
272 272 assert_equal User.anonymous, issue.reload.author
273 273 end
274 274
275 275 def test_destroy_should_unassign_issues
276 276 issue = Issue.create!(:project_id => 1, :author_id => 1,
277 277 :tracker_id => 1, :subject => 'foo', :assigned_to_id => 2)
278 278
279 279 User.find(2).destroy
280 280 assert_nil User.find_by_id(2)
281 281 assert_nil issue.reload.assigned_to
282 282 end
283 283
284 284 def test_destroy_should_update_journals
285 285 issue = Issue.create!(:project_id => 1, :author_id => 2,
286 286 :tracker_id => 1, :subject => 'foo')
287 287 issue.init_journal(User.find(2), "update")
288 288 issue.save!
289 289
290 290 User.find(2).destroy
291 291 assert_nil User.find_by_id(2)
292 292 assert_equal User.anonymous, issue.journals.first.reload.user
293 293 end
294 294
295 295 def test_destroy_should_update_journal_details_old_value
296 296 issue = Issue.create!(:project_id => 1, :author_id => 1,
297 297 :tracker_id => 1, :subject => 'foo', :assigned_to_id => 2)
298 298 issue.init_journal(User.find(1), "update")
299 299 issue.assigned_to_id = nil
300 300 assert_difference 'JournalDetail.count' do
301 301 issue.save!
302 302 end
303 303 journal_detail = JournalDetail.order('id DESC').first
304 304 assert_equal '2', journal_detail.old_value
305 305
306 306 User.find(2).destroy
307 307 assert_nil User.find_by_id(2)
308 308 assert_equal User.anonymous.id.to_s, journal_detail.reload.old_value
309 309 end
310 310
311 311 def test_destroy_should_update_journal_details_value
312 312 issue = Issue.create!(:project_id => 1, :author_id => 1,
313 313 :tracker_id => 1, :subject => 'foo')
314 314 issue.init_journal(User.find(1), "update")
315 315 issue.assigned_to_id = 2
316 316 assert_difference 'JournalDetail.count' do
317 317 issue.save!
318 318 end
319 319 journal_detail = JournalDetail.order('id DESC').first
320 320 assert_equal '2', journal_detail.value
321 321
322 322 User.find(2).destroy
323 323 assert_nil User.find_by_id(2)
324 324 assert_equal User.anonymous.id.to_s, journal_detail.reload.value
325 325 end
326 326
327 327 def test_destroy_should_update_messages
328 328 board = Board.create!(:project_id => 1, :name => 'Board', :description => 'Board')
329 329 message = Message.create!(:board_id => board.id, :author_id => 2,
330 330 :subject => 'foo', :content => 'foo')
331 331 User.find(2).destroy
332 332 assert_nil User.find_by_id(2)
333 333 assert_equal User.anonymous, message.reload.author
334 334 end
335 335
336 336 def test_destroy_should_update_news
337 337 news = News.create!(:project_id => 1, :author_id => 2,
338 338 :title => 'foo', :description => 'foo')
339 339 User.find(2).destroy
340 340 assert_nil User.find_by_id(2)
341 341 assert_equal User.anonymous, news.reload.author
342 342 end
343 343
344 344 def test_destroy_should_delete_private_queries
345 345 query = Query.new(:name => 'foo', :visibility => Query::VISIBILITY_PRIVATE)
346 346 query.project_id = 1
347 347 query.user_id = 2
348 348 query.save!
349 349
350 350 User.find(2).destroy
351 351 assert_nil User.find_by_id(2)
352 352 assert_nil Query.find_by_id(query.id)
353 353 end
354 354
355 355 def test_destroy_should_update_public_queries
356 356 query = Query.new(:name => 'foo', :visibility => Query::VISIBILITY_PUBLIC)
357 357 query.project_id = 1
358 358 query.user_id = 2
359 359 query.save!
360 360
361 361 User.find(2).destroy
362 362 assert_nil User.find_by_id(2)
363 363 assert_equal User.anonymous, query.reload.user
364 364 end
365 365
366 366 def test_destroy_should_update_time_entries
367 367 entry = TimeEntry.new(:hours => '2', :spent_on => Date.today,
368 368 :activity => TimeEntryActivity.create!(:name => 'foo'))
369 369 entry.project_id = 1
370 370 entry.user_id = 2
371 371 entry.save!
372 372
373 373 User.find(2).destroy
374 374 assert_nil User.find_by_id(2)
375 375 assert_equal User.anonymous, entry.reload.user
376 376 end
377 377
378 378 def test_destroy_should_delete_tokens
379 379 token = Token.create!(:user_id => 2, :value => 'foo')
380 380
381 381 User.find(2).destroy
382 382 assert_nil User.find_by_id(2)
383 383 assert_nil Token.find_by_id(token.id)
384 384 end
385 385
386 386 def test_destroy_should_delete_watchers
387 387 issue = Issue.create!(:project_id => 1, :author_id => 1,
388 388 :tracker_id => 1, :subject => 'foo')
389 389 watcher = Watcher.create!(:user_id => 2, :watchable => issue)
390 390
391 391 User.find(2).destroy
392 392 assert_nil User.find_by_id(2)
393 393 assert_nil Watcher.find_by_id(watcher.id)
394 394 end
395 395
396 396 def test_destroy_should_update_wiki_contents
397 397 wiki_content = WikiContent.create!(
398 398 :text => 'foo',
399 399 :author_id => 2,
400 400 :page => WikiPage.create!(:title => 'Foo',
401 401 :wiki => Wiki.create!(:project_id => 3,
402 402 :start_page => 'Start'))
403 403 )
404 404 wiki_content.text = 'bar'
405 405 assert_difference 'WikiContent::Version.count' do
406 406 wiki_content.save!
407 407 end
408 408
409 409 User.find(2).destroy
410 410 assert_nil User.find_by_id(2)
411 411 assert_equal User.anonymous, wiki_content.reload.author
412 412 wiki_content.versions.each do |version|
413 413 assert_equal User.anonymous, version.reload.author
414 414 end
415 415 end
416 416
417 417 def test_destroy_should_nullify_issue_categories
418 418 category = IssueCategory.create!(:project_id => 1, :assigned_to_id => 2, :name => 'foo')
419 419
420 420 User.find(2).destroy
421 421 assert_nil User.find_by_id(2)
422 422 assert_nil category.reload.assigned_to_id
423 423 end
424 424
425 425 def test_destroy_should_nullify_changesets
426 426 changeset = Changeset.create!(
427 427 :repository => Repository::Subversion.create!(
428 428 :project_id => 1,
429 429 :url => 'file:///tmp',
430 430 :identifier => 'tmp'
431 431 ),
432 432 :revision => '12',
433 433 :committed_on => Time.now,
434 434 :committer => 'jsmith'
435 435 )
436 436 assert_equal 2, changeset.user_id
437 437
438 438 User.find(2).destroy
439 439 assert_nil User.find_by_id(2)
440 440 assert_nil changeset.reload.user_id
441 441 end
442 442
443 443 def test_anonymous_user_should_not_be_destroyable
444 444 assert_no_difference 'User.count' do
445 445 assert_equal false, User.anonymous.destroy
446 446 end
447 447 end
448 448
449 449 def test_password_change_should_destroy_tokens
450 450 recovery_token = Token.create!(:user_id => 2, :action => 'recovery')
451 451 autologin_token = Token.create!(:user_id => 2, :action => 'autologin')
452 452
453 453 user = User.find(2)
454 454 user.password, user.password_confirmation = "a new password", "a new password"
455 455 assert user.save
456 456
457 457 assert_nil Token.find_by_id(recovery_token.id)
458 458 assert_nil Token.find_by_id(autologin_token.id)
459 459 end
460 460
461 461 def test_mail_change_should_destroy_tokens
462 462 recovery_token = Token.create!(:user_id => 2, :action => 'recovery')
463 463 autologin_token = Token.create!(:user_id => 2, :action => 'autologin')
464 464
465 465 user = User.find(2)
466 466 user.mail = "user@somwehere.com"
467 467 assert user.save
468 468
469 469 assert_nil Token.find_by_id(recovery_token.id)
470 470 assert_equal autologin_token, Token.find_by_id(autologin_token.id)
471 471 end
472 472
473 473 def test_change_on_other_fields_should_not_destroy_tokens
474 474 recovery_token = Token.create!(:user_id => 2, :action => 'recovery')
475 475 autologin_token = Token.create!(:user_id => 2, :action => 'autologin')
476 476
477 477 user = User.find(2)
478 478 user.firstname = "Bobby"
479 479 assert user.save
480 480
481 481 assert_equal recovery_token, Token.find_by_id(recovery_token.id)
482 482 assert_equal autologin_token, Token.find_by_id(autologin_token.id)
483 483 end
484 484
485 485 def test_validate_login_presence
486 486 @admin.login = ""
487 487 assert !@admin.save
488 488 assert_equal 1, @admin.errors.count
489 489 end
490 490
491 491 def test_validate_mail_notification_inclusion
492 492 u = User.new
493 493 u.mail_notification = 'foo'
494 494 u.save
495 495 assert_not_equal [], u.errors[:mail_notification]
496 496 end
497 497
498 498 def test_password
499 499 user = User.try_to_login("admin", "admin")
500 500 assert_kind_of User, user
501 501 assert_equal "admin", user.login
502 502 user.password = "hello123"
503 503 assert user.save
504 504
505 505 user = User.try_to_login("admin", "hello123")
506 506 assert_kind_of User, user
507 507 assert_equal "admin", user.login
508 508 end
509 509
510 510 def test_validate_password_length
511 511 with_settings :password_min_length => '100' do
512 512 user = User.new(:firstname => "new100",
513 513 :lastname => "user100", :mail => "newuser100@somenet.foo")
514 514 user.login = "newuser100"
515 515 user.password, user.password_confirmation = "password100", "password100"
516 516 assert !user.save
517 517 assert_equal 1, user.errors.count
518 518 end
519 519 end
520 520
521 521 def test_name_format
522 522 assert_equal 'John S.', @jsmith.name(:firstname_lastinitial)
523 523 assert_equal 'Smith, John', @jsmith.name(:lastname_comma_firstname)
524 524 assert_equal 'J. Smith', @jsmith.name(:firstinitial_lastname)
525 525 assert_equal 'J.-P. Lang', User.new(:firstname => 'Jean-Philippe', :lastname => 'Lang').name(:firstinitial_lastname)
526 526 end
527 527
528 528 def test_name_should_use_setting_as_default_format
529 529 with_settings :user_format => :firstname_lastname do
530 530 assert_equal 'John Smith', @jsmith.reload.name
531 531 end
532 532 with_settings :user_format => :username do
533 533 assert_equal 'jsmith', @jsmith.reload.name
534 534 end
535 535 with_settings :user_format => :lastname do
536 536 assert_equal 'Smith', @jsmith.reload.name
537 537 end
538 538 end
539 539
540 540 def test_today_should_return_the_day_according_to_user_time_zone
541 541 preference = User.find(1).pref
542 542 date = Date.new(2012, 05, 15)
543 543 time = Time.gm(2012, 05, 15, 23, 30).utc # 2012-05-15 23:30 UTC
544 544 Date.stubs(:today).returns(date)
545 545 Time.stubs(:now).returns(time)
546 546
547 547 preference.update_attribute :time_zone, 'Baku' # UTC+4
548 548 assert_equal '2012-05-16', User.find(1).today.to_s
549 549
550 550 preference.update_attribute :time_zone, 'La Paz' # UTC-4
551 551 assert_equal '2012-05-15', User.find(1).today.to_s
552 552
553 553 preference.update_attribute :time_zone, ''
554 554 assert_equal '2012-05-15', User.find(1).today.to_s
555 555 end
556 556
557 557 def test_time_to_date_should_return_the_date_according_to_user_time_zone
558 558 preference = User.find(1).pref
559 559 time = Time.gm(2012, 05, 15, 23, 30).utc # 2012-05-15 23:30 UTC
560 560
561 561 preference.update_attribute :time_zone, 'Baku' # UTC+4
562 562 assert_equal '2012-05-16', User.find(1).time_to_date(time).to_s
563 563
564 564 preference.update_attribute :time_zone, 'La Paz' # UTC-4
565 565 assert_equal '2012-05-15', User.find(1).time_to_date(time).to_s
566 566
567 567 preference.update_attribute :time_zone, ''
568 568 assert_equal '2012-05-15', User.find(1).time_to_date(time).to_s
569 569 end
570 570
571 571 def test_fields_for_order_statement_should_return_fields_according_user_format_setting
572 572 with_settings :user_format => 'lastname_comma_firstname' do
573 573 assert_equal ['users.lastname', 'users.firstname', 'users.id'],
574 574 User.fields_for_order_statement
575 575 end
576 576 end
577 577
578 578 def test_fields_for_order_statement_width_table_name_should_prepend_table_name
579 579 with_settings :user_format => 'lastname_firstname' do
580 580 assert_equal ['authors.lastname', 'authors.firstname', 'authors.id'],
581 581 User.fields_for_order_statement('authors')
582 582 end
583 583 end
584 584
585 585 def test_fields_for_order_statement_with_blank_format_should_return_default
586 586 with_settings :user_format => '' do
587 587 assert_equal ['users.firstname', 'users.lastname', 'users.id'],
588 588 User.fields_for_order_statement
589 589 end
590 590 end
591 591
592 592 def test_fields_for_order_statement_with_invalid_format_should_return_default
593 593 with_settings :user_format => 'foo' do
594 594 assert_equal ['users.firstname', 'users.lastname', 'users.id'],
595 595 User.fields_for_order_statement
596 596 end
597 597 end
598 598
599 599 test ".try_to_login with good credentials should return the user" do
600 600 user = User.try_to_login("admin", "admin")
601 601 assert_kind_of User, user
602 602 assert_equal "admin", user.login
603 603 end
604 604
605 605 test ".try_to_login with wrong credentials should return nil" do
606 606 assert_nil User.try_to_login("admin", "foo")
607 607 end
608 608
609 609 def test_try_to_login_with_locked_user_should_return_nil
610 610 @jsmith.status = User::STATUS_LOCKED
611 611 @jsmith.save!
612 612
613 613 user = User.try_to_login("jsmith", "jsmith")
614 614 assert_nil user
615 615 end
616 616
617 617 def test_try_to_login_with_locked_user_and_not_active_only_should_return_user
618 618 @jsmith.status = User::STATUS_LOCKED
619 619 @jsmith.save!
620 620
621 621 user = User.try_to_login("jsmith", "jsmith", false)
622 622 assert_equal @jsmith, user
623 623 end
624 624
625 625 test ".try_to_login should fall-back to case-insensitive if user login is not found as-typed" do
626 626 user = User.try_to_login("AdMin", "admin")
627 627 assert_kind_of User, user
628 628 assert_equal "admin", user.login
629 629 end
630 630
631 631 test ".try_to_login should select the exact matching user first" do
632 632 case_sensitive_user = User.generate! do |user|
633 633 user.password = "admin123"
634 634 end
635 635 # bypass validations to make it appear like existing data
636 636 case_sensitive_user.update_attribute(:login, 'ADMIN')
637 637
638 638 user = User.try_to_login("ADMIN", "admin123")
639 639 assert_kind_of User, user
640 640 assert_equal "ADMIN", user.login
641 641 end
642 642
643 643 if ldap_configured?
644 644 test "#try_to_login using LDAP with failed connection to the LDAP server" do
645 645 auth_source = AuthSourceLdap.find(1)
646 AuthSource.any_instance.stubs(:initialize_ldap_con).raises(Net::LDAP::Error, 'Cannot connect')
646 AuthSource.any_instance.stubs(:initialize_ldap_con).raises(Net::LDAP::LdapError, 'Cannot connect')
647 647
648 648 assert_nil User.try_to_login('edavis', 'wrong')
649 649 end
650 650
651 651 test "#try_to_login using LDAP" do
652 652 assert_nil User.try_to_login('edavis', 'wrong')
653 653 end
654 654
655 655 test "#try_to_login using LDAP binding with user's account" do
656 656 auth_source = AuthSourceLdap.find(1)
657 657 auth_source.account = "uid=$login,ou=Person,dc=redmine,dc=org"
658 658 auth_source.account_password = ''
659 659 auth_source.save!
660 660
661 661 ldap_user = User.new(:mail => 'example1@redmine.org', :firstname => 'LDAP', :lastname => 'user', :auth_source_id => 1)
662 662 ldap_user.login = 'example1'
663 663 ldap_user.save!
664 664
665 665 assert_equal ldap_user, User.try_to_login('example1', '123456')
666 666 assert_nil User.try_to_login('example1', '11111')
667 667 end
668 668
669 669 test "#try_to_login using LDAP on the fly registration" do
670 670 AuthSourceLdap.find(1).update_attribute :onthefly_register, true
671 671
672 672 assert_difference('User.count') do
673 673 assert User.try_to_login('edavis', '123456')
674 674 end
675 675
676 676 assert_no_difference('User.count') do
677 677 assert User.try_to_login('edavis', '123456')
678 678 end
679 679
680 680 assert_nil User.try_to_login('example1', '11111')
681 681 end
682 682
683 683 test "#try_to_login using LDAP on the fly registration and binding with user's account" do
684 684 auth_source = AuthSourceLdap.find(1)
685 685 auth_source.update_attribute :onthefly_register, true
686 686 auth_source = AuthSourceLdap.find(1)
687 687 auth_source.account = "uid=$login,ou=Person,dc=redmine,dc=org"
688 688 auth_source.account_password = ''
689 689 auth_source.save!
690 690
691 691 assert_difference('User.count') do
692 692 assert User.try_to_login('example1', '123456')
693 693 end
694 694
695 695 assert_no_difference('User.count') do
696 696 assert User.try_to_login('example1', '123456')
697 697 end
698 698
699 699 assert_nil User.try_to_login('example1', '11111')
700 700 end
701 701
702 702 else
703 703 puts "Skipping LDAP tests."
704 704 end
705 705
706 706 def test_create_anonymous
707 707 AnonymousUser.delete_all
708 708 anon = User.anonymous
709 709 assert !anon.new_record?
710 710 assert_kind_of AnonymousUser, anon
711 711 end
712 712
713 713 def test_ensure_single_anonymous_user
714 714 AnonymousUser.delete_all
715 715 anon1 = User.anonymous
716 716 assert !anon1.new_record?
717 717 assert_kind_of AnonymousUser, anon1
718 718 anon2 = AnonymousUser.create(
719 719 :lastname => 'Anonymous', :firstname => '',
720 720 :login => '', :status => 0)
721 721 assert_equal 1, anon2.errors.count
722 722 end
723 723
724 724 def test_rss_key
725 725 assert_nil @jsmith.rss_token
726 726 key = @jsmith.rss_key
727 727 assert_equal 40, key.length
728 728
729 729 @jsmith.reload
730 730 assert_equal key, @jsmith.rss_key
731 731 end
732 732
733 733 def test_rss_key_should_not_be_generated_twice
734 734 assert_difference 'Token.count', 1 do
735 735 key1 = @jsmith.rss_key
736 736 key2 = @jsmith.rss_key
737 737 assert_equal key1, key2
738 738 end
739 739 end
740 740
741 741 def test_api_key_should_not_be_generated_twice
742 742 assert_difference 'Token.count', 1 do
743 743 key1 = @jsmith.api_key
744 744 key2 = @jsmith.api_key
745 745 assert_equal key1, key2
746 746 end
747 747 end
748 748
749 749 test "#api_key should generate a new one if the user doesn't have one" do
750 750 user = User.generate!(:api_token => nil)
751 751 assert_nil user.api_token
752 752
753 753 key = user.api_key
754 754 assert_equal 40, key.length
755 755 user.reload
756 756 assert_equal key, user.api_key
757 757 end
758 758
759 759 test "#api_key should return the existing api token value" do
760 760 user = User.generate!
761 761 token = Token.create!(:action => 'api')
762 762 user.api_token = token
763 763 assert user.save
764 764
765 765 assert_equal token.value, user.api_key
766 766 end
767 767
768 768 test "#find_by_api_key should return nil if no matching key is found" do
769 769 assert_nil User.find_by_api_key('zzzzzzzzz')
770 770 end
771 771
772 772 test "#find_by_api_key should return nil if the key is found for an inactive user" do
773 773 user = User.generate!
774 774 user.status = User::STATUS_LOCKED
775 775 token = Token.create!(:action => 'api')
776 776 user.api_token = token
777 777 user.save
778 778
779 779 assert_nil User.find_by_api_key(token.value)
780 780 end
781 781
782 782 test "#find_by_api_key should return the user if the key is found for an active user" do
783 783 user = User.generate!
784 784 token = Token.create!(:action => 'api')
785 785 user.api_token = token
786 786 user.save
787 787
788 788 assert_equal user, User.find_by_api_key(token.value)
789 789 end
790 790
791 791 def test_default_admin_account_changed_should_return_false_if_account_was_not_changed
792 792 user = User.find_by_login("admin")
793 793 user.password = "admin"
794 794 assert user.save(:validate => false)
795 795
796 796 assert_equal false, User.default_admin_account_changed?
797 797 end
798 798
799 799 def test_default_admin_account_changed_should_return_true_if_password_was_changed
800 800 user = User.find_by_login("admin")
801 801 user.password = "newpassword"
802 802 user.save!
803 803
804 804 assert_equal true, User.default_admin_account_changed?
805 805 end
806 806
807 807 def test_default_admin_account_changed_should_return_true_if_account_is_disabled
808 808 user = User.find_by_login("admin")
809 809 user.password = "admin"
810 810 user.status = User::STATUS_LOCKED
811 811 assert user.save(:validate => false)
812 812
813 813 assert_equal true, User.default_admin_account_changed?
814 814 end
815 815
816 816 def test_default_admin_account_changed_should_return_true_if_account_does_not_exist
817 817 user = User.find_by_login("admin")
818 818 user.destroy
819 819
820 820 assert_equal true, User.default_admin_account_changed?
821 821 end
822 822
823 823 def test_membership_with_project_should_return_membership
824 824 project = Project.find(1)
825 825
826 826 membership = @jsmith.membership(project)
827 827 assert_kind_of Member, membership
828 828 assert_equal @jsmith, membership.user
829 829 assert_equal project, membership.project
830 830 end
831 831
832 832 def test_membership_with_project_id_should_return_membership
833 833 project = Project.find(1)
834 834
835 835 membership = @jsmith.membership(1)
836 836 assert_kind_of Member, membership
837 837 assert_equal @jsmith, membership.user
838 838 assert_equal project, membership.project
839 839 end
840 840
841 841 def test_membership_for_non_member_should_return_nil
842 842 project = Project.find(1)
843 843
844 844 user = User.generate!
845 845 membership = user.membership(1)
846 846 assert_nil membership
847 847 end
848 848
849 849 def test_roles_for_project_with_member_on_public_project_should_return_roles_and_non_member
850 850 roles = @jsmith.roles_for_project(Project.find(1))
851 851 assert_kind_of Role, roles.first
852 852 assert_equal ["Manager"], roles.map(&:name)
853 853 end
854 854
855 855 def test_roles_for_project_with_member_on_private_project_should_return_roles
856 856 Project.find(1).update_attribute :is_public, false
857 857
858 858 roles = @jsmith.roles_for_project(Project.find(1))
859 859 assert_kind_of Role, roles.first
860 860 assert_equal ["Manager"], roles.map(&:name)
861 861 end
862 862
863 863 def test_roles_for_project_with_non_member_with_public_project_should_return_non_member
864 864 set_language_if_valid 'en'
865 865 roles = User.find(8).roles_for_project(Project.find(1))
866 866 assert_equal ["Non member"], roles.map(&:name)
867 867 end
868 868
869 869 def test_roles_for_project_with_non_member_with_public_project_and_override_should_return_override_roles
870 870 project = Project.find(1)
871 871 Member.create!(:project => project, :principal => Group.non_member, :role_ids => [1, 2])
872 872 roles = User.find(8).roles_for_project(project)
873 873 assert_equal ["Developer", "Manager"], roles.map(&:name).sort
874 874 end
875 875
876 876 def test_roles_for_project_with_non_member_with_private_project_should_return_no_roles
877 877 Project.find(1).update_attribute :is_public, false
878 878 roles = User.find(8).roles_for_project(Project.find(1))
879 879 assert_equal [], roles.map(&:name)
880 880 end
881 881
882 882 def test_roles_for_project_with_non_member_with_private_project_and_override_should_return_no_roles
883 883 project = Project.find(1)
884 884 project.update_attribute :is_public, false
885 885 Member.create!(:project => project, :principal => Group.non_member, :role_ids => [1, 2])
886 886 roles = User.find(8).roles_for_project(project)
887 887 assert_equal [], roles.map(&:name).sort
888 888 end
889 889
890 890 def test_roles_for_project_with_anonymous_with_public_project_should_return_anonymous
891 891 set_language_if_valid 'en'
892 892 roles = User.anonymous.roles_for_project(Project.find(1))
893 893 assert_equal ["Anonymous"], roles.map(&:name)
894 894 end
895 895
896 896 def test_roles_for_project_with_anonymous_with_public_project_and_override_should_return_override_roles
897 897 project = Project.find(1)
898 898 Member.create!(:project => project, :principal => Group.anonymous, :role_ids => [1, 2])
899 899 roles = User.anonymous.roles_for_project(project)
900 900 assert_equal ["Developer", "Manager"], roles.map(&:name).sort
901 901 end
902 902
903 903 def test_roles_for_project_with_anonymous_with_private_project_should_return_no_roles
904 904 Project.find(1).update_attribute :is_public, false
905 905 roles = User.anonymous.roles_for_project(Project.find(1))
906 906 assert_equal [], roles.map(&:name)
907 907 end
908 908
909 909 def test_roles_for_project_with_anonymous_with_private_project_and_override_should_return_no_roles
910 910 project = Project.find(1)
911 911 project.update_attribute :is_public, false
912 912 Member.create!(:project => project, :principal => Group.anonymous, :role_ids => [1, 2])
913 913 roles = User.anonymous.roles_for_project(project)
914 914 assert_equal [], roles.map(&:name).sort
915 915 end
916 916
917 917 def test_roles_for_project_should_be_unique
918 918 m = Member.new(:user_id => 1, :project_id => 1)
919 919 m.member_roles.build(:role_id => 1)
920 920 m.member_roles.build(:role_id => 1)
921 921 m.save!
922 922
923 923 user = User.find(1)
924 924 project = Project.find(1)
925 925 assert_equal 1, user.roles_for_project(project).size
926 926 assert_equal [1], user.roles_for_project(project).map(&:id)
927 927 end
928 928
929 929 def test_projects_by_role_for_user_with_role
930 930 user = User.find(2)
931 931 assert_kind_of Hash, user.projects_by_role
932 932 assert_equal 2, user.projects_by_role.size
933 933 assert_equal [1,5], user.projects_by_role[Role.find(1)].collect(&:id).sort
934 934 assert_equal [2], user.projects_by_role[Role.find(2)].collect(&:id).sort
935 935 end
936 936
937 937 def test_accessing_projects_by_role_with_no_projects_should_return_an_empty_array
938 938 user = User.find(2)
939 939 assert_equal [], user.projects_by_role[Role.find(3)]
940 940 # should not update the hash
941 941 assert_nil user.projects_by_role.values.detect(&:blank?)
942 942 end
943 943
944 944 def test_projects_by_role_for_user_with_no_role
945 945 user = User.generate!
946 946 assert_equal({}, user.projects_by_role)
947 947 end
948 948
949 949 def test_projects_by_role_for_anonymous
950 950 assert_equal({}, User.anonymous.projects_by_role)
951 951 end
952 952
953 953 def test_valid_notification_options
954 954 # without memberships
955 955 assert_equal 5, User.find(7).valid_notification_options.size
956 956 # with memberships
957 957 assert_equal 6, User.find(2).valid_notification_options.size
958 958 end
959 959
960 960 def test_valid_notification_options_class_method
961 961 assert_equal 5, User.valid_notification_options.size
962 962 assert_equal 5, User.valid_notification_options(User.find(7)).size
963 963 assert_equal 6, User.valid_notification_options(User.find(2)).size
964 964 end
965 965
966 966 def test_notified_project_ids_setter_should_coerce_to_unique_integer_array
967 967 @jsmith.notified_project_ids = ["1", "123", "2u", "wrong", "12", 6, 12, -35, ""]
968 968 assert_equal [1, 123, 2, 12, 6], @jsmith.notified_projects_ids
969 969 end
970 970
971 971 def test_mail_notification_all
972 972 @jsmith.mail_notification = 'all'
973 973 @jsmith.notified_project_ids = []
974 974 @jsmith.save
975 975 @jsmith.reload
976 976 assert @jsmith.projects.first.recipients.include?(@jsmith.mail)
977 977 end
978 978
979 979 def test_mail_notification_selected
980 980 @jsmith.mail_notification = 'selected'
981 981 @jsmith.notified_project_ids = [1]
982 982 @jsmith.save
983 983 @jsmith.reload
984 984 assert Project.find(1).recipients.include?(@jsmith.mail)
985 985 end
986 986
987 987 def test_mail_notification_only_my_events
988 988 @jsmith.mail_notification = 'only_my_events'
989 989 @jsmith.notified_project_ids = []
990 990 @jsmith.save
991 991 @jsmith.reload
992 992 assert !@jsmith.projects.first.recipients.include?(@jsmith.mail)
993 993 end
994 994
995 995 def test_comments_sorting_preference
996 996 assert !@jsmith.wants_comments_in_reverse_order?
997 997 @jsmith.pref.comments_sorting = 'asc'
998 998 assert !@jsmith.wants_comments_in_reverse_order?
999 999 @jsmith.pref.comments_sorting = 'desc'
1000 1000 assert @jsmith.wants_comments_in_reverse_order?
1001 1001 end
1002 1002
1003 1003 def test_find_by_mail_should_be_case_insensitive
1004 1004 u = User.find_by_mail('JSmith@somenet.foo')
1005 1005 assert_not_nil u
1006 1006 assert_equal 'jsmith@somenet.foo', u.mail
1007 1007 end
1008 1008
1009 1009 def test_random_password
1010 1010 u = User.new
1011 1011 u.random_password
1012 1012 assert !u.password.blank?
1013 1013 assert !u.password_confirmation.blank?
1014 1014 end
1015 1015
1016 1016 test "#change_password_allowed? should be allowed if no auth source is set" do
1017 1017 user = User.generate!
1018 1018 assert user.change_password_allowed?
1019 1019 end
1020 1020
1021 1021 test "#change_password_allowed? should delegate to the auth source" do
1022 1022 user = User.generate!
1023 1023
1024 1024 allowed_auth_source = AuthSource.generate!
1025 1025 def allowed_auth_source.allow_password_changes?; true; end
1026 1026
1027 1027 denied_auth_source = AuthSource.generate!
1028 1028 def denied_auth_source.allow_password_changes?; false; end
1029 1029
1030 1030 assert user.change_password_allowed?
1031 1031
1032 1032 user.auth_source = allowed_auth_source
1033 1033 assert user.change_password_allowed?, "User not allowed to change password, though auth source does"
1034 1034
1035 1035 user.auth_source = denied_auth_source
1036 1036 assert !user.change_password_allowed?, "User allowed to change password, though auth source does not"
1037 1037 end
1038 1038
1039 1039 def test_own_account_deletable_should_be_true_with_unsubscrive_enabled
1040 1040 with_settings :unsubscribe => '1' do
1041 1041 assert_equal true, User.find(2).own_account_deletable?
1042 1042 end
1043 1043 end
1044 1044
1045 1045 def test_own_account_deletable_should_be_false_with_unsubscrive_disabled
1046 1046 with_settings :unsubscribe => '0' do
1047 1047 assert_equal false, User.find(2).own_account_deletable?
1048 1048 end
1049 1049 end
1050 1050
1051 1051 def test_own_account_deletable_should_be_false_for_a_single_admin
1052 1052 User.where(["admin = ? AND id <> ?", true, 1]).delete_all
1053 1053
1054 1054 with_settings :unsubscribe => '1' do
1055 1055 assert_equal false, User.find(1).own_account_deletable?
1056 1056 end
1057 1057 end
1058 1058
1059 1059 def test_own_account_deletable_should_be_true_for_an_admin_if_other_admin_exists
1060 1060 User.generate! do |user|
1061 1061 user.admin = true
1062 1062 end
1063 1063
1064 1064 with_settings :unsubscribe => '1' do
1065 1065 assert_equal true, User.find(1).own_account_deletable?
1066 1066 end
1067 1067 end
1068 1068
1069 1069 test "#allowed_to? for archived project should return false" do
1070 1070 project = Project.find(1)
1071 1071 project.archive
1072 1072 project.reload
1073 1073 assert_equal false, @admin.allowed_to?(:view_issues, project)
1074 1074 end
1075 1075
1076 1076 test "#allowed_to? for closed project should return true for read actions" do
1077 1077 project = Project.find(1)
1078 1078 project.close
1079 1079 project.reload
1080 1080 assert_equal false, @admin.allowed_to?(:edit_project, project)
1081 1081 assert_equal true, @admin.allowed_to?(:view_project, project)
1082 1082 end
1083 1083
1084 1084 test "#allowed_to? for project with module disabled should return false" do
1085 1085 project = Project.find(1)
1086 1086 project.enabled_module_names = ["issue_tracking"]
1087 1087 assert_equal true, @admin.allowed_to?(:add_issues, project)
1088 1088 assert_equal false, @admin.allowed_to?(:view_wiki_pages, project)
1089 1089 end
1090 1090
1091 1091 test "#allowed_to? for admin users should return true" do
1092 1092 project = Project.find(1)
1093 1093 assert ! @admin.member_of?(project)
1094 1094 %w(edit_issues delete_issues manage_news add_documents manage_wiki).each do |p|
1095 1095 assert_equal true, @admin.allowed_to?(p.to_sym, project)
1096 1096 end
1097 1097 end
1098 1098
1099 1099 test "#allowed_to? for normal users" do
1100 1100 project = Project.find(1)
1101 1101 assert_equal true, @jsmith.allowed_to?(:delete_messages, project) #Manager
1102 1102 assert_equal false, @dlopper.allowed_to?(:delete_messages, project) #Developper
1103 1103 end
1104 1104
1105 1105 test "#allowed_to? with empty array should return false" do
1106 1106 assert_equal false, @admin.allowed_to?(:view_project, [])
1107 1107 end
1108 1108
1109 1109 test "#allowed_to? with multiple projects" do
1110 1110 assert_equal true, @admin.allowed_to?(:view_project, Project.all.to_a)
1111 1111 assert_equal false, @dlopper.allowed_to?(:view_project, Project.all.to_a) #cannot see Project(2)
1112 1112 assert_equal true, @jsmith.allowed_to?(:edit_issues, @jsmith.projects.to_a) #Manager or Developer everywhere
1113 1113 assert_equal false, @jsmith.allowed_to?(:delete_issue_watchers, @jsmith.projects.to_a) #Dev cannot delete_issue_watchers
1114 1114 end
1115 1115
1116 1116 test "#allowed_to? with with options[:global] should return true if user has one role with the permission" do
1117 1117 @dlopper2 = User.find(5) #only Developper on a project, not Manager anywhere
1118 1118 @anonymous = User.find(6)
1119 1119 assert_equal true, @jsmith.allowed_to?(:delete_issue_watchers, nil, :global => true)
1120 1120 assert_equal false, @dlopper2.allowed_to?(:delete_issue_watchers, nil, :global => true)
1121 1121 assert_equal true, @dlopper2.allowed_to?(:add_issues, nil, :global => true)
1122 1122 assert_equal false, @anonymous.allowed_to?(:add_issues, nil, :global => true)
1123 1123 assert_equal true, @anonymous.allowed_to?(:view_issues, nil, :global => true)
1124 1124 end
1125 1125
1126 1126 # this is just a proxy method, the test only calls it to ensure it doesn't break trivially
1127 1127 test "#allowed_to_globally?" do
1128 1128 @dlopper2 = User.find(5) #only Developper on a project, not Manager anywhere
1129 1129 @anonymous = User.find(6)
1130 1130 assert_equal true, @jsmith.allowed_to_globally?(:delete_issue_watchers)
1131 1131 assert_equal false, @dlopper2.allowed_to_globally?(:delete_issue_watchers)
1132 1132 assert_equal true, @dlopper2.allowed_to_globally?(:add_issues)
1133 1133 assert_equal false, @anonymous.allowed_to_globally?(:add_issues)
1134 1134 assert_equal true, @anonymous.allowed_to_globally?(:view_issues)
1135 1135 end
1136 1136
1137 1137 def test_notify_about_issue
1138 1138 project = Project.find(1)
1139 1139 author = User.generate!
1140 1140 assignee = User.generate!
1141 1141 Member.create!(:user => assignee, :project => project, :role_ids => [1])
1142 1142 member = User.generate!
1143 1143 Member.create!(:user => member, :project => project, :role_ids => [1])
1144 1144 issue = Issue.generate!(:project => project, :assigned_to => assignee, :author => author)
1145 1145
1146 1146 tests = {
1147 1147 author => %w(all only_my_events only_owner selected),
1148 1148 assignee => %w(all only_my_events only_assigned selected),
1149 1149 member => %w(all)
1150 1150 }
1151 1151
1152 1152 tests.each do |user, expected|
1153 1153 User::MAIL_NOTIFICATION_OPTIONS.map(&:first).each do |option|
1154 1154 user.mail_notification = option
1155 1155 assert_equal expected.include?(option), user.notify_about?(issue)
1156 1156 end
1157 1157 end
1158 1158 end
1159 1159
1160 1160 def test_notify_about_issue_for_previous_assignee
1161 1161 assignee = User.generate!(:mail_notification => 'only_assigned')
1162 1162 Member.create!(:user => assignee, :project_id => 1, :role_ids => [1])
1163 1163 new_assignee = User.generate!(:mail_notification => 'only_assigned')
1164 1164 Member.create!(:user => new_assignee, :project_id => 1, :role_ids => [1])
1165 1165 issue = Issue.generate!(:assigned_to => assignee)
1166 1166
1167 1167 assert assignee.notify_about?(issue)
1168 1168 assert !new_assignee.notify_about?(issue)
1169 1169
1170 1170 issue.assigned_to = new_assignee
1171 1171 assert assignee.notify_about?(issue)
1172 1172 assert new_assignee.notify_about?(issue)
1173 1173
1174 1174 issue.save!
1175 1175 assert !assignee.notify_about?(issue)
1176 1176 assert new_assignee.notify_about?(issue)
1177 1177 end
1178 1178
1179 1179 def test_notify_about_news
1180 1180 user = User.generate!
1181 1181 news = News.new
1182 1182
1183 1183 User::MAIL_NOTIFICATION_OPTIONS.map(&:first).each do |option|
1184 1184 user.mail_notification = option
1185 1185 assert_equal (option != 'none'), user.notify_about?(news)
1186 1186 end
1187 1187 end
1188 1188
1189 1189 def test_salt_unsalted_passwords
1190 1190 # Restore a user with an unsalted password
1191 1191 user = User.find(1)
1192 1192 user.salt = nil
1193 1193 user.hashed_password = User.hash_password("unsalted")
1194 1194 user.save!
1195 1195
1196 1196 User.salt_unsalted_passwords!
1197 1197
1198 1198 user.reload
1199 1199 # Salt added
1200 1200 assert !user.salt.blank?
1201 1201 # Password still valid
1202 1202 assert user.check_password?("unsalted")
1203 1203 assert_equal user, User.try_to_login(user.login, "unsalted")
1204 1204 end
1205 1205
1206 1206 if Object.const_defined?(:OpenID)
1207 1207 def test_setting_identity_url
1208 1208 normalized_open_id_url = 'http://example.com/'
1209 1209 u = User.new( :identity_url => 'http://example.com/' )
1210 1210 assert_equal normalized_open_id_url, u.identity_url
1211 1211 end
1212 1212
1213 1213 def test_setting_identity_url_without_trailing_slash
1214 1214 normalized_open_id_url = 'http://example.com/'
1215 1215 u = User.new( :identity_url => 'http://example.com' )
1216 1216 assert_equal normalized_open_id_url, u.identity_url
1217 1217 end
1218 1218
1219 1219 def test_setting_identity_url_without_protocol
1220 1220 normalized_open_id_url = 'http://example.com/'
1221 1221 u = User.new( :identity_url => 'example.com' )
1222 1222 assert_equal normalized_open_id_url, u.identity_url
1223 1223 end
1224 1224
1225 1225 def test_setting_blank_identity_url
1226 1226 u = User.new( :identity_url => 'example.com' )
1227 1227 u.identity_url = ''
1228 1228 assert u.identity_url.blank?
1229 1229 end
1230 1230
1231 1231 def test_setting_invalid_identity_url
1232 1232 u = User.new( :identity_url => 'this is not an openid url' )
1233 1233 assert u.identity_url.blank?
1234 1234 end
1235 1235 else
1236 1236 puts "Skipping openid tests."
1237 1237 end
1238 1238 end
General Comments 0
You need to be logged in to leave comments. Login now