You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

user_test.rb 37KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135
  1. # Redmine - project management software
  2. # Copyright (C) 2006-2014 Jean-Philippe Lang
  3. #
  4. # This program is free software; you can redistribute it and/or
  5. # modify it under the terms of the GNU General Public License
  6. # as published by the Free Software Foundation; either version 2
  7. # of the License, or (at your option) any later version.
  8. #
  9. # This program is distributed in the hope that it will be useful,
  10. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. # GNU General Public License for more details.
  13. #
  14. # You should have received a copy of the GNU General Public License
  15. # along with this program; if not, write to the Free Software
  16. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  17. require File.expand_path('../../test_helper', __FILE__)
  18. class UserTest < ActiveSupport::TestCase
  19. fixtures :users, :members, :projects, :roles, :member_roles, :auth_sources,
  20. :trackers, :issue_statuses,
  21. :projects_trackers,
  22. :watchers,
  23. :issue_categories, :enumerations, :issues,
  24. :journals, :journal_details,
  25. :groups_users,
  26. :enabled_modules
  27. def setup
  28. @admin = User.find(1)
  29. @jsmith = User.find(2)
  30. @dlopper = User.find(3)
  31. end
  32. def test_sorted_scope_should_sort_user_by_display_name
  33. assert_equal User.all.map(&:name).map(&:downcase).sort, User.sorted.all.map(&:name).map(&:downcase)
  34. end
  35. def test_generate
  36. User.generate!(:firstname => 'Testing connection')
  37. User.generate!(:firstname => 'Testing connection')
  38. assert_equal 2, User.where(:firstname => 'Testing connection').count
  39. end
  40. def test_truth
  41. assert_kind_of User, @jsmith
  42. end
  43. def test_mail_should_be_stripped
  44. u = User.new
  45. u.mail = " foo@bar.com "
  46. assert_equal "foo@bar.com", u.mail
  47. end
  48. def test_mail_validation
  49. u = User.new
  50. u.mail = ''
  51. assert !u.valid?
  52. assert_include I18n.translate('activerecord.errors.messages.blank'), u.errors[:mail]
  53. end
  54. def test_login_length_validation
  55. user = User.new(:firstname => "new", :lastname => "user", :mail => "newuser@somenet.foo")
  56. user.login = "x" * (User::LOGIN_LENGTH_LIMIT+1)
  57. assert !user.valid?
  58. user.login = "x" * (User::LOGIN_LENGTH_LIMIT)
  59. assert user.valid?
  60. assert user.save
  61. end
  62. def test_generate_password_should_respect_minimum_password_length
  63. with_settings :password_min_length => 15 do
  64. user = User.generate!(:generate_password => true)
  65. assert user.password.length >= 15
  66. end
  67. end
  68. def test_generate_password_should_not_generate_password_with_less_than_10_characters
  69. with_settings :password_min_length => 4 do
  70. user = User.generate!(:generate_password => true)
  71. assert user.password.length >= 10
  72. end
  73. end
  74. def test_generate_password_on_create_should_set_password
  75. user = User.new(:firstname => "new", :lastname => "user", :mail => "newuser@somenet.foo")
  76. user.login = "newuser"
  77. user.generate_password = true
  78. assert user.save
  79. password = user.password
  80. assert user.check_password?(password)
  81. end
  82. def test_generate_password_on_update_should_update_password
  83. user = User.find(2)
  84. hash = user.hashed_password
  85. user.generate_password = true
  86. assert user.save
  87. password = user.password
  88. assert user.check_password?(password)
  89. assert_not_equal hash, user.reload.hashed_password
  90. end
  91. def test_create
  92. user = User.new(:firstname => "new", :lastname => "user", :mail => "newuser@somenet.foo")
  93. user.login = "jsmith"
  94. user.password, user.password_confirmation = "password", "password"
  95. # login uniqueness
  96. assert !user.save
  97. assert_equal 1, user.errors.count
  98. user.login = "newuser"
  99. user.password, user.password_confirmation = "password", "pass"
  100. # password confirmation
  101. assert !user.save
  102. assert_equal 1, user.errors.count
  103. user.password, user.password_confirmation = "password", "password"
  104. assert user.save
  105. end
  106. def test_user_before_create_should_set_the_mail_notification_to_the_default_setting
  107. @user1 = User.generate!
  108. assert_equal 'only_my_events', @user1.mail_notification
  109. with_settings :default_notification_option => 'all' do
  110. @user2 = User.generate!
  111. assert_equal 'all', @user2.mail_notification
  112. end
  113. end
  114. def test_user_login_should_be_case_insensitive
  115. u = User.new(:firstname => "new", :lastname => "user", :mail => "newuser@somenet.foo")
  116. u.login = 'newuser'
  117. u.password, u.password_confirmation = "password", "password"
  118. assert u.save
  119. u = User.new(:firstname => "Similar", :lastname => "User", :mail => "similaruser@somenet.foo")
  120. u.login = 'NewUser'
  121. u.password, u.password_confirmation = "password", "password"
  122. assert !u.save
  123. assert_include I18n.translate('activerecord.errors.messages.taken'), u.errors[:login]
  124. end
  125. def test_mail_uniqueness_should_not_be_case_sensitive
  126. u = User.new(:firstname => "new", :lastname => "user", :mail => "newuser@somenet.foo")
  127. u.login = 'newuser1'
  128. u.password, u.password_confirmation = "password", "password"
  129. assert u.save
  130. u = User.new(:firstname => "new", :lastname => "user", :mail => "newUser@Somenet.foo")
  131. u.login = 'newuser2'
  132. u.password, u.password_confirmation = "password", "password"
  133. assert !u.save
  134. assert_include I18n.translate('activerecord.errors.messages.taken'), u.errors[:mail]
  135. end
  136. def test_update
  137. assert_equal "admin", @admin.login
  138. @admin.login = "john"
  139. assert @admin.save, @admin.errors.full_messages.join("; ")
  140. @admin.reload
  141. assert_equal "john", @admin.login
  142. end
  143. def test_update_should_not_fail_for_legacy_user_with_different_case_logins
  144. u1 = User.new(:firstname => "new", :lastname => "user", :mail => "newuser1@somenet.foo")
  145. u1.login = 'newuser1'
  146. assert u1.save
  147. u2 = User.new(:firstname => "new", :lastname => "user", :mail => "newuser2@somenet.foo")
  148. u2.login = 'newuser1'
  149. assert u2.save(:validate => false)
  150. user = User.find(u2.id)
  151. user.firstname = "firstname"
  152. assert user.save, "Save failed"
  153. end
  154. def test_destroy_should_delete_members_and_roles
  155. members = Member.find_all_by_user_id(2)
  156. ms = members.size
  157. rs = members.collect(&:roles).flatten.size
  158. assert_difference 'Member.count', - ms do
  159. assert_difference 'MemberRole.count', - rs do
  160. User.find(2).destroy
  161. end
  162. end
  163. assert_nil User.find_by_id(2)
  164. assert Member.find_all_by_user_id(2).empty?
  165. end
  166. def test_destroy_should_update_attachments
  167. attachment = Attachment.create!(:container => Project.find(1),
  168. :file => uploaded_test_file("testfile.txt", "text/plain"),
  169. :author_id => 2)
  170. User.find(2).destroy
  171. assert_nil User.find_by_id(2)
  172. assert_equal User.anonymous, attachment.reload.author
  173. end
  174. def test_destroy_should_update_comments
  175. comment = Comment.create!(
  176. :commented => News.create!(:project_id => 1, :author_id => 1, :title => 'foo', :description => 'foo'),
  177. :author => User.find(2),
  178. :comments => 'foo'
  179. )
  180. User.find(2).destroy
  181. assert_nil User.find_by_id(2)
  182. assert_equal User.anonymous, comment.reload.author
  183. end
  184. def test_destroy_should_update_issues
  185. issue = Issue.create!(:project_id => 1, :author_id => 2, :tracker_id => 1, :subject => 'foo')
  186. User.find(2).destroy
  187. assert_nil User.find_by_id(2)
  188. assert_equal User.anonymous, issue.reload.author
  189. end
  190. def test_destroy_should_unassign_issues
  191. issue = Issue.create!(:project_id => 1, :author_id => 1, :tracker_id => 1, :subject => 'foo', :assigned_to_id => 2)
  192. User.find(2).destroy
  193. assert_nil User.find_by_id(2)
  194. assert_nil issue.reload.assigned_to
  195. end
  196. def test_destroy_should_update_journals
  197. issue = Issue.create!(:project_id => 1, :author_id => 2, :tracker_id => 1, :subject => 'foo')
  198. issue.init_journal(User.find(2), "update")
  199. issue.save!
  200. User.find(2).destroy
  201. assert_nil User.find_by_id(2)
  202. assert_equal User.anonymous, issue.journals.first.reload.user
  203. end
  204. def test_destroy_should_update_journal_details_old_value
  205. issue = Issue.create!(:project_id => 1, :author_id => 1, :tracker_id => 1, :subject => 'foo', :assigned_to_id => 2)
  206. issue.init_journal(User.find(1), "update")
  207. issue.assigned_to_id = nil
  208. assert_difference 'JournalDetail.count' do
  209. issue.save!
  210. end
  211. journal_detail = JournalDetail.first(:order => 'id DESC')
  212. assert_equal '2', journal_detail.old_value
  213. User.find(2).destroy
  214. assert_nil User.find_by_id(2)
  215. assert_equal User.anonymous.id.to_s, journal_detail.reload.old_value
  216. end
  217. def test_destroy_should_update_journal_details_value
  218. issue = Issue.create!(:project_id => 1, :author_id => 1, :tracker_id => 1, :subject => 'foo')
  219. issue.init_journal(User.find(1), "update")
  220. issue.assigned_to_id = 2
  221. assert_difference 'JournalDetail.count' do
  222. issue.save!
  223. end
  224. journal_detail = JournalDetail.first(:order => 'id DESC')
  225. assert_equal '2', journal_detail.value
  226. User.find(2).destroy
  227. assert_nil User.find_by_id(2)
  228. assert_equal User.anonymous.id.to_s, journal_detail.reload.value
  229. end
  230. def test_destroy_should_update_messages
  231. board = Board.create!(:project_id => 1, :name => 'Board', :description => 'Board')
  232. message = Message.create!(:board_id => board.id, :author_id => 2, :subject => 'foo', :content => 'foo')
  233. User.find(2).destroy
  234. assert_nil User.find_by_id(2)
  235. assert_equal User.anonymous, message.reload.author
  236. end
  237. def test_destroy_should_update_news
  238. news = News.create!(:project_id => 1, :author_id => 2, :title => 'foo', :description => 'foo')
  239. User.find(2).destroy
  240. assert_nil User.find_by_id(2)
  241. assert_equal User.anonymous, news.reload.author
  242. end
  243. def test_destroy_should_delete_private_queries
  244. query = Query.new(:name => 'foo', :visibility => Query::VISIBILITY_PRIVATE)
  245. query.project_id = 1
  246. query.user_id = 2
  247. query.save!
  248. User.find(2).destroy
  249. assert_nil User.find_by_id(2)
  250. assert_nil Query.find_by_id(query.id)
  251. end
  252. def test_destroy_should_update_public_queries
  253. query = Query.new(:name => 'foo', :visibility => Query::VISIBILITY_PUBLIC)
  254. query.project_id = 1
  255. query.user_id = 2
  256. query.save!
  257. User.find(2).destroy
  258. assert_nil User.find_by_id(2)
  259. assert_equal User.anonymous, query.reload.user
  260. end
  261. def test_destroy_should_update_time_entries
  262. entry = TimeEntry.new(:hours => '2', :spent_on => Date.today, :activity => TimeEntryActivity.create!(:name => 'foo'))
  263. entry.project_id = 1
  264. entry.user_id = 2
  265. entry.save!
  266. User.find(2).destroy
  267. assert_nil User.find_by_id(2)
  268. assert_equal User.anonymous, entry.reload.user
  269. end
  270. def test_destroy_should_delete_tokens
  271. token = Token.create!(:user_id => 2, :value => 'foo')
  272. User.find(2).destroy
  273. assert_nil User.find_by_id(2)
  274. assert_nil Token.find_by_id(token.id)
  275. end
  276. def test_destroy_should_delete_watchers
  277. issue = Issue.create!(:project_id => 1, :author_id => 1, :tracker_id => 1, :subject => 'foo')
  278. watcher = Watcher.create!(:user_id => 2, :watchable => issue)
  279. User.find(2).destroy
  280. assert_nil User.find_by_id(2)
  281. assert_nil Watcher.find_by_id(watcher.id)
  282. end
  283. def test_destroy_should_update_wiki_contents
  284. wiki_content = WikiContent.create!(
  285. :text => 'foo',
  286. :author_id => 2,
  287. :page => WikiPage.create!(:title => 'Foo', :wiki => Wiki.create!(:project_id => 1, :start_page => 'Start'))
  288. )
  289. wiki_content.text = 'bar'
  290. assert_difference 'WikiContent::Version.count' do
  291. wiki_content.save!
  292. end
  293. User.find(2).destroy
  294. assert_nil User.find_by_id(2)
  295. assert_equal User.anonymous, wiki_content.reload.author
  296. wiki_content.versions.each do |version|
  297. assert_equal User.anonymous, version.reload.author
  298. end
  299. end
  300. def test_destroy_should_nullify_issue_categories
  301. category = IssueCategory.create!(:project_id => 1, :assigned_to_id => 2, :name => 'foo')
  302. User.find(2).destroy
  303. assert_nil User.find_by_id(2)
  304. assert_nil category.reload.assigned_to_id
  305. end
  306. def test_destroy_should_nullify_changesets
  307. changeset = Changeset.create!(
  308. :repository => Repository::Subversion.create!(
  309. :project_id => 1,
  310. :url => 'file:///tmp',
  311. :identifier => 'tmp'
  312. ),
  313. :revision => '12',
  314. :committed_on => Time.now,
  315. :committer => 'jsmith'
  316. )
  317. assert_equal 2, changeset.user_id
  318. User.find(2).destroy
  319. assert_nil User.find_by_id(2)
  320. assert_nil changeset.reload.user_id
  321. end
  322. def test_anonymous_user_should_not_be_destroyable
  323. assert_no_difference 'User.count' do
  324. assert_equal false, User.anonymous.destroy
  325. end
  326. end
  327. def test_validate_login_presence
  328. @admin.login = ""
  329. assert !@admin.save
  330. assert_equal 1, @admin.errors.count
  331. end
  332. def test_validate_mail_notification_inclusion
  333. u = User.new
  334. u.mail_notification = 'foo'
  335. u.save
  336. assert_not_equal [], u.errors[:mail_notification]
  337. end
  338. def test_password
  339. user = User.try_to_login("admin", "admin")
  340. assert_kind_of User, user
  341. assert_equal "admin", user.login
  342. user.password = "hello123"
  343. assert user.save
  344. user = User.try_to_login("admin", "hello123")
  345. assert_kind_of User, user
  346. assert_equal "admin", user.login
  347. end
  348. def test_validate_password_length
  349. with_settings :password_min_length => '100' do
  350. user = User.new(:firstname => "new100", :lastname => "user100", :mail => "newuser100@somenet.foo")
  351. user.login = "newuser100"
  352. user.password, user.password_confirmation = "password100", "password100"
  353. assert !user.save
  354. assert_equal 1, user.errors.count
  355. end
  356. end
  357. def test_name_format
  358. assert_equal 'John S.', @jsmith.name(:firstname_lastinitial)
  359. assert_equal 'Smith, John', @jsmith.name(:lastname_coma_firstname)
  360. with_settings :user_format => :firstname_lastname do
  361. assert_equal 'John Smith', @jsmith.reload.name
  362. end
  363. with_settings :user_format => :username do
  364. assert_equal 'jsmith', @jsmith.reload.name
  365. end
  366. with_settings :user_format => :lastname do
  367. assert_equal 'Smith', @jsmith.reload.name
  368. end
  369. end
  370. def test_today_should_return_the_day_according_to_user_time_zone
  371. preference = User.find(1).pref
  372. date = Date.new(2012, 05, 15)
  373. time = Time.gm(2012, 05, 15, 23, 30).utc # 2012-05-15 23:30 UTC
  374. Date.stubs(:today).returns(date)
  375. Time.stubs(:now).returns(time)
  376. preference.update_attribute :time_zone, 'Baku' # UTC+4
  377. assert_equal '2012-05-16', User.find(1).today.to_s
  378. preference.update_attribute :time_zone, 'La Paz' # UTC-4
  379. assert_equal '2012-05-15', User.find(1).today.to_s
  380. preference.update_attribute :time_zone, ''
  381. assert_equal '2012-05-15', User.find(1).today.to_s
  382. end
  383. def test_time_to_date_should_return_the_date_according_to_user_time_zone
  384. preference = User.find(1).pref
  385. time = Time.gm(2012, 05, 15, 23, 30).utc # 2012-05-15 23:30 UTC
  386. preference.update_attribute :time_zone, 'Baku' # UTC+4
  387. assert_equal '2012-05-16', User.find(1).time_to_date(time).to_s
  388. preference.update_attribute :time_zone, 'La Paz' # UTC-4
  389. assert_equal '2012-05-15', User.find(1).time_to_date(time).to_s
  390. preference.update_attribute :time_zone, ''
  391. assert_equal '2012-05-15', User.find(1).time_to_date(time).to_s
  392. end
  393. def test_fields_for_order_statement_should_return_fields_according_user_format_setting
  394. with_settings :user_format => 'lastname_coma_firstname' do
  395. assert_equal ['users.lastname', 'users.firstname', 'users.id'], User.fields_for_order_statement
  396. end
  397. end
  398. def test_fields_for_order_statement_width_table_name_should_prepend_table_name
  399. with_settings :user_format => 'lastname_firstname' do
  400. assert_equal ['authors.lastname', 'authors.firstname', 'authors.id'], User.fields_for_order_statement('authors')
  401. end
  402. end
  403. def test_fields_for_order_statement_with_blank_format_should_return_default
  404. with_settings :user_format => '' do
  405. assert_equal ['users.firstname', 'users.lastname', 'users.id'], User.fields_for_order_statement
  406. end
  407. end
  408. def test_fields_for_order_statement_with_invalid_format_should_return_default
  409. with_settings :user_format => 'foo' do
  410. assert_equal ['users.firstname', 'users.lastname', 'users.id'], User.fields_for_order_statement
  411. end
  412. end
  413. test ".try_to_login with good credentials should return the user" do
  414. user = User.try_to_login("admin", "admin")
  415. assert_kind_of User, user
  416. assert_equal "admin", user.login
  417. end
  418. test ".try_to_login with wrong credentials should return nil" do
  419. assert_nil User.try_to_login("admin", "foo")
  420. end
  421. def test_try_to_login_with_locked_user_should_return_nil
  422. @jsmith.status = User::STATUS_LOCKED
  423. @jsmith.save!
  424. user = User.try_to_login("jsmith", "jsmith")
  425. assert_equal nil, user
  426. end
  427. def test_try_to_login_with_locked_user_and_not_active_only_should_return_user
  428. @jsmith.status = User::STATUS_LOCKED
  429. @jsmith.save!
  430. user = User.try_to_login("jsmith", "jsmith", false)
  431. assert_equal @jsmith, user
  432. end
  433. test ".try_to_login should fall-back to case-insensitive if user login is not found as-typed" do
  434. user = User.try_to_login("AdMin", "admin")
  435. assert_kind_of User, user
  436. assert_equal "admin", user.login
  437. end
  438. test ".try_to_login should select the exact matching user first" do
  439. case_sensitive_user = User.generate! do |user|
  440. user.password = "admin123"
  441. end
  442. # bypass validations to make it appear like existing data
  443. case_sensitive_user.update_attribute(:login, 'ADMIN')
  444. user = User.try_to_login("ADMIN", "admin123")
  445. assert_kind_of User, user
  446. assert_equal "ADMIN", user.login
  447. end
  448. if ldap_configured?
  449. context "#try_to_login using LDAP" do
  450. context "with failed connection to the LDAP server" do
  451. should "return nil" do
  452. @auth_source = AuthSourceLdap.find(1)
  453. AuthSource.any_instance.stubs(:initialize_ldap_con).raises(Net::LDAP::LdapError, 'Cannot connect')
  454. assert_equal nil, User.try_to_login('edavis', 'wrong')
  455. end
  456. end
  457. context "with an unsuccessful authentication" do
  458. should "return nil" do
  459. assert_equal nil, User.try_to_login('edavis', 'wrong')
  460. end
  461. end
  462. context "binding with user's account" do
  463. setup do
  464. @auth_source = AuthSourceLdap.find(1)
  465. @auth_source.account = "uid=$login,ou=Person,dc=redmine,dc=org"
  466. @auth_source.account_password = ''
  467. @auth_source.save!
  468. @ldap_user = User.new(:mail => 'example1@redmine.org', :firstname => 'LDAP', :lastname => 'user', :auth_source_id => 1)
  469. @ldap_user.login = 'example1'
  470. @ldap_user.save!
  471. end
  472. context "with a successful authentication" do
  473. should "return the user" do
  474. assert_equal @ldap_user, User.try_to_login('example1', '123456')
  475. end
  476. end
  477. context "with an unsuccessful authentication" do
  478. should "return nil" do
  479. assert_nil User.try_to_login('example1', '11111')
  480. end
  481. end
  482. end
  483. context "on the fly registration" do
  484. setup do
  485. @auth_source = AuthSourceLdap.find(1)
  486. @auth_source.update_attribute :onthefly_register, true
  487. end
  488. context "with a successful authentication" do
  489. should "create a new user account if it doesn't exist" do
  490. assert_difference('User.count') do
  491. user = User.try_to_login('edavis', '123456')
  492. assert !user.admin?
  493. end
  494. end
  495. should "retrieve existing user" do
  496. user = User.try_to_login('edavis', '123456')
  497. user.admin = true
  498. user.save!
  499. assert_no_difference('User.count') do
  500. user = User.try_to_login('edavis', '123456')
  501. assert user.admin?
  502. end
  503. end
  504. end
  505. context "binding with user's account" do
  506. setup do
  507. @auth_source = AuthSourceLdap.find(1)
  508. @auth_source.account = "uid=$login,ou=Person,dc=redmine,dc=org"
  509. @auth_source.account_password = ''
  510. @auth_source.save!
  511. end
  512. context "with a successful authentication" do
  513. should "create a new user account if it doesn't exist" do
  514. assert_difference('User.count') do
  515. user = User.try_to_login('example1', '123456')
  516. assert_kind_of User, user
  517. end
  518. end
  519. end
  520. context "with an unsuccessful authentication" do
  521. should "return nil" do
  522. assert_nil User.try_to_login('example1', '11111')
  523. end
  524. end
  525. end
  526. end
  527. end
  528. else
  529. puts "Skipping LDAP tests."
  530. end
  531. def test_create_anonymous
  532. AnonymousUser.delete_all
  533. anon = User.anonymous
  534. assert !anon.new_record?
  535. assert_kind_of AnonymousUser, anon
  536. end
  537. def test_ensure_single_anonymous_user
  538. AnonymousUser.delete_all
  539. anon1 = User.anonymous
  540. assert !anon1.new_record?
  541. assert_kind_of AnonymousUser, anon1
  542. anon2 = AnonymousUser.create(
  543. :lastname => 'Anonymous', :firstname => '',
  544. :mail => '', :login => '', :status => 0)
  545. assert_equal 1, anon2.errors.count
  546. end
  547. def test_rss_key
  548. assert_nil @jsmith.rss_token
  549. key = @jsmith.rss_key
  550. assert_equal 40, key.length
  551. @jsmith.reload
  552. assert_equal key, @jsmith.rss_key
  553. end
  554. def test_rss_key_should_not_be_generated_twice
  555. assert_difference 'Token.count', 1 do
  556. key1 = @jsmith.rss_key
  557. key2 = @jsmith.rss_key
  558. assert_equal key1, key2
  559. end
  560. end
  561. def test_api_key_should_not_be_generated_twice
  562. assert_difference 'Token.count', 1 do
  563. key1 = @jsmith.api_key
  564. key2 = @jsmith.api_key
  565. assert_equal key1, key2
  566. end
  567. end
  568. test "#api_key should generate a new one if the user doesn't have one" do
  569. user = User.generate!(:api_token => nil)
  570. assert_nil user.api_token
  571. key = user.api_key
  572. assert_equal 40, key.length
  573. user.reload
  574. assert_equal key, user.api_key
  575. end
  576. test "#api_key should return the existing api token value" do
  577. user = User.generate!
  578. token = Token.create!(:action => 'api')
  579. user.api_token = token
  580. assert user.save
  581. assert_equal token.value, user.api_key
  582. end
  583. test "#find_by_api_key should return nil if no matching key is found" do
  584. assert_nil User.find_by_api_key('zzzzzzzzz')
  585. end
  586. test "#find_by_api_key should return nil if the key is found for an inactive user" do
  587. user = User.generate!
  588. user.status = User::STATUS_LOCKED
  589. token = Token.create!(:action => 'api')
  590. user.api_token = token
  591. user.save
  592. assert_nil User.find_by_api_key(token.value)
  593. end
  594. test "#find_by_api_key should return the user if the key is found for an active user" do
  595. user = User.generate!
  596. token = Token.create!(:action => 'api')
  597. user.api_token = token
  598. user.save
  599. assert_equal user, User.find_by_api_key(token.value)
  600. end
  601. def test_default_admin_account_changed_should_return_false_if_account_was_not_changed
  602. user = User.find_by_login("admin")
  603. user.password = "admin"
  604. assert user.save(:validate => false)
  605. assert_equal false, User.default_admin_account_changed?
  606. end
  607. def test_default_admin_account_changed_should_return_true_if_password_was_changed
  608. user = User.find_by_login("admin")
  609. user.password = "newpassword"
  610. user.save!
  611. assert_equal true, User.default_admin_account_changed?
  612. end
  613. def test_default_admin_account_changed_should_return_true_if_account_is_disabled
  614. user = User.find_by_login("admin")
  615. user.password = "admin"
  616. user.status = User::STATUS_LOCKED
  617. assert user.save(:validate => false)
  618. assert_equal true, User.default_admin_account_changed?
  619. end
  620. def test_default_admin_account_changed_should_return_true_if_account_does_not_exist
  621. user = User.find_by_login("admin")
  622. user.destroy
  623. assert_equal true, User.default_admin_account_changed?
  624. end
  625. def test_membership_with_project_should_return_membership
  626. project = Project.find(1)
  627. membership = @jsmith.membership(project)
  628. assert_kind_of Member, membership
  629. assert_equal @jsmith, membership.user
  630. assert_equal project, membership.project
  631. end
  632. def test_membership_with_project_id_should_return_membership
  633. project = Project.find(1)
  634. membership = @jsmith.membership(1)
  635. assert_kind_of Member, membership
  636. assert_equal @jsmith, membership.user
  637. assert_equal project, membership.project
  638. end
  639. def test_membership_for_non_member_should_return_nil
  640. project = Project.find(1)
  641. user = User.generate!
  642. membership = user.membership(1)
  643. assert_nil membership
  644. end
  645. def test_roles_for_project
  646. # user with a role
  647. roles = @jsmith.roles_for_project(Project.find(1))
  648. assert_kind_of Role, roles.first
  649. assert_equal "Manager", roles.first.name
  650. # user with no role
  651. assert_nil @dlopper.roles_for_project(Project.find(2)).detect {|role| role.member?}
  652. end
  653. def test_projects_by_role_for_user_with_role
  654. user = User.find(2)
  655. assert_kind_of Hash, user.projects_by_role
  656. assert_equal 2, user.projects_by_role.size
  657. assert_equal [1,5], user.projects_by_role[Role.find(1)].collect(&:id).sort
  658. assert_equal [2], user.projects_by_role[Role.find(2)].collect(&:id).sort
  659. end
  660. def test_accessing_projects_by_role_with_no_projects_should_return_an_empty_array
  661. user = User.find(2)
  662. assert_equal [], user.projects_by_role[Role.find(3)]
  663. # should not update the hash
  664. assert_nil user.projects_by_role.values.detect(&:blank?)
  665. end
  666. def test_projects_by_role_for_user_with_no_role
  667. user = User.generate!
  668. assert_equal({}, user.projects_by_role)
  669. end
  670. def test_projects_by_role_for_anonymous
  671. assert_equal({}, User.anonymous.projects_by_role)
  672. end
  673. def test_valid_notification_options
  674. # without memberships
  675. assert_equal 5, User.find(7).valid_notification_options.size
  676. # with memberships
  677. assert_equal 6, User.find(2).valid_notification_options.size
  678. end
  679. def test_valid_notification_options_class_method
  680. assert_equal 5, User.valid_notification_options.size
  681. assert_equal 5, User.valid_notification_options(User.find(7)).size
  682. assert_equal 6, User.valid_notification_options(User.find(2)).size
  683. end
  684. def test_mail_notification_all
  685. @jsmith.mail_notification = 'all'
  686. @jsmith.notified_project_ids = []
  687. @jsmith.save
  688. @jsmith.reload
  689. assert @jsmith.projects.first.recipients.include?(@jsmith.mail)
  690. end
  691. def test_mail_notification_selected
  692. @jsmith.mail_notification = 'selected'
  693. @jsmith.notified_project_ids = [1]
  694. @jsmith.save
  695. @jsmith.reload
  696. assert Project.find(1).recipients.include?(@jsmith.mail)
  697. end
  698. def test_mail_notification_only_my_events
  699. @jsmith.mail_notification = 'only_my_events'
  700. @jsmith.notified_project_ids = []
  701. @jsmith.save
  702. @jsmith.reload
  703. assert !@jsmith.projects.first.recipients.include?(@jsmith.mail)
  704. end
  705. def test_comments_sorting_preference
  706. assert !@jsmith.wants_comments_in_reverse_order?
  707. @jsmith.pref.comments_sorting = 'asc'
  708. assert !@jsmith.wants_comments_in_reverse_order?
  709. @jsmith.pref.comments_sorting = 'desc'
  710. assert @jsmith.wants_comments_in_reverse_order?
  711. end
  712. def test_find_by_mail_should_be_case_insensitive
  713. u = User.find_by_mail('JSmith@somenet.foo')
  714. assert_not_nil u
  715. assert_equal 'jsmith@somenet.foo', u.mail
  716. end
  717. def test_random_password
  718. u = User.new
  719. u.random_password
  720. assert !u.password.blank?
  721. assert !u.password_confirmation.blank?
  722. end
  723. test "#change_password_allowed? should be allowed if no auth source is set" do
  724. user = User.generate!
  725. assert user.change_password_allowed?
  726. end
  727. test "#change_password_allowed? should delegate to the auth source" do
  728. user = User.generate!
  729. allowed_auth_source = AuthSource.generate!
  730. def allowed_auth_source.allow_password_changes?; true; end
  731. denied_auth_source = AuthSource.generate!
  732. def denied_auth_source.allow_password_changes?; false; end
  733. assert user.change_password_allowed?
  734. user.auth_source = allowed_auth_source
  735. assert user.change_password_allowed?, "User not allowed to change password, though auth source does"
  736. user.auth_source = denied_auth_source
  737. assert !user.change_password_allowed?, "User allowed to change password, though auth source does not"
  738. end
  739. def test_own_account_deletable_should_be_true_with_unsubscrive_enabled
  740. with_settings :unsubscribe => '1' do
  741. assert_equal true, User.find(2).own_account_deletable?
  742. end
  743. end
  744. def test_own_account_deletable_should_be_false_with_unsubscrive_disabled
  745. with_settings :unsubscribe => '0' do
  746. assert_equal false, User.find(2).own_account_deletable?
  747. end
  748. end
  749. def test_own_account_deletable_should_be_false_for_a_single_admin
  750. User.delete_all(["admin = ? AND id <> ?", true, 1])
  751. with_settings :unsubscribe => '1' do
  752. assert_equal false, User.find(1).own_account_deletable?
  753. end
  754. end
  755. def test_own_account_deletable_should_be_true_for_an_admin_if_other_admin_exists
  756. User.generate! do |user|
  757. user.admin = true
  758. end
  759. with_settings :unsubscribe => '1' do
  760. assert_equal true, User.find(1).own_account_deletable?
  761. end
  762. end
  763. context "#allowed_to?" do
  764. context "with a unique project" do
  765. should "return false if project is archived" do
  766. project = Project.find(1)
  767. Project.any_instance.stubs(:status).returns(Project::STATUS_ARCHIVED)
  768. assert_equal false, @admin.allowed_to?(:view_issues, Project.find(1))
  769. end
  770. should "return false for write action if project is closed" do
  771. project = Project.find(1)
  772. Project.any_instance.stubs(:status).returns(Project::STATUS_CLOSED)
  773. assert_equal false, @admin.allowed_to?(:edit_project, Project.find(1))
  774. end
  775. should "return true for read action if project is closed" do
  776. project = Project.find(1)
  777. Project.any_instance.stubs(:status).returns(Project::STATUS_CLOSED)
  778. assert_equal true, @admin.allowed_to?(:view_project, Project.find(1))
  779. end
  780. should "return false if related module is disabled" do
  781. project = Project.find(1)
  782. project.enabled_module_names = ["issue_tracking"]
  783. assert_equal true, @admin.allowed_to?(:add_issues, project)
  784. assert_equal false, @admin.allowed_to?(:view_wiki_pages, project)
  785. end
  786. should "authorize nearly everything for admin users" do
  787. project = Project.find(1)
  788. assert ! @admin.member_of?(project)
  789. %w(edit_issues delete_issues manage_news add_documents manage_wiki).each do |p|
  790. assert_equal true, @admin.allowed_to?(p.to_sym, project)
  791. end
  792. end
  793. should "authorize normal users depending on their roles" do
  794. project = Project.find(1)
  795. assert_equal true, @jsmith.allowed_to?(:delete_messages, project) #Manager
  796. assert_equal false, @dlopper.allowed_to?(:delete_messages, project) #Developper
  797. end
  798. end
  799. context "with multiple projects" do
  800. should "return false if array is empty" do
  801. assert_equal false, @admin.allowed_to?(:view_project, [])
  802. end
  803. should "return true only if user has permission on all these projects" do
  804. assert_equal true, @admin.allowed_to?(:view_project, Project.all)
  805. assert_equal false, @dlopper.allowed_to?(:view_project, Project.all) #cannot see Project(2)
  806. assert_equal true, @jsmith.allowed_to?(:edit_issues, @jsmith.projects) #Manager or Developer everywhere
  807. assert_equal false, @jsmith.allowed_to?(:delete_issue_watchers, @jsmith.projects) #Dev cannot delete_issue_watchers
  808. end
  809. should "behave correctly with arrays of 1 project" do
  810. assert_equal false, User.anonymous.allowed_to?(:delete_issues, [Project.first])
  811. end
  812. end
  813. context "with options[:global]" do
  814. should "authorize if user has at least one role that has this permission" do
  815. @dlopper2 = User.find(5) #only Developper on a project, not Manager anywhere
  816. @anonymous = User.find(6)
  817. assert_equal true, @jsmith.allowed_to?(:delete_issue_watchers, nil, :global => true)
  818. assert_equal false, @dlopper2.allowed_to?(:delete_issue_watchers, nil, :global => true)
  819. assert_equal true, @dlopper2.allowed_to?(:add_issues, nil, :global => true)
  820. assert_equal false, @anonymous.allowed_to?(:add_issues, nil, :global => true)
  821. assert_equal true, @anonymous.allowed_to?(:view_issues, nil, :global => true)
  822. end
  823. end
  824. end
  825. context "User#notify_about?" do
  826. context "Issues" do
  827. setup do
  828. @project = Project.find(1)
  829. @author = User.generate!
  830. @assignee = User.generate!
  831. @issue = Issue.generate!(:project => @project, :assigned_to => @assignee, :author => @author)
  832. end
  833. should "be true for a user with :all" do
  834. @author.update_attribute(:mail_notification, 'all')
  835. assert @author.notify_about?(@issue)
  836. end
  837. should "be false for a user with :none" do
  838. @author.update_attribute(:mail_notification, 'none')
  839. assert ! @author.notify_about?(@issue)
  840. end
  841. should "be false for a user with :only_my_events and isn't an author, creator, or assignee" do
  842. @user = User.generate!(:mail_notification => 'only_my_events')
  843. Member.create!(:user => @user, :project => @project, :role_ids => [1])
  844. assert ! @user.notify_about?(@issue)
  845. end
  846. should "be true for a user with :only_my_events and is the author" do
  847. @author.update_attribute(:mail_notification, 'only_my_events')
  848. assert @author.notify_about?(@issue)
  849. end
  850. should "be true for a user with :only_my_events and is the assignee" do
  851. @assignee.update_attribute(:mail_notification, 'only_my_events')
  852. assert @assignee.notify_about?(@issue)
  853. end
  854. should "be true for a user with :only_assigned and is the assignee" do
  855. @assignee.update_attribute(:mail_notification, 'only_assigned')
  856. assert @assignee.notify_about?(@issue)
  857. end
  858. should "be false for a user with :only_assigned and is not the assignee" do
  859. @author.update_attribute(:mail_notification, 'only_assigned')
  860. assert ! @author.notify_about?(@issue)
  861. end
  862. should "be true for a user with :only_owner and is the author" do
  863. @author.update_attribute(:mail_notification, 'only_owner')
  864. assert @author.notify_about?(@issue)
  865. end
  866. should "be false for a user with :only_owner and is not the author" do
  867. @assignee.update_attribute(:mail_notification, 'only_owner')
  868. assert ! @assignee.notify_about?(@issue)
  869. end
  870. should "be true for a user with :selected and is the author" do
  871. @author.update_attribute(:mail_notification, 'selected')
  872. assert @author.notify_about?(@issue)
  873. end
  874. should "be true for a user with :selected and is the assignee" do
  875. @assignee.update_attribute(:mail_notification, 'selected')
  876. assert @assignee.notify_about?(@issue)
  877. end
  878. should "be false for a user with :selected and is not the author or assignee" do
  879. @user = User.generate!(:mail_notification => 'selected')
  880. Member.create!(:user => @user, :project => @project, :role_ids => [1])
  881. assert ! @user.notify_about?(@issue)
  882. end
  883. end
  884. end
  885. def test_notify_about_news
  886. user = User.generate!
  887. news = News.new
  888. User::MAIL_NOTIFICATION_OPTIONS.map(&:first).each do |option|
  889. user.mail_notification = option
  890. assert_equal (option != 'none'), user.notify_about?(news)
  891. end
  892. end
  893. def test_salt_unsalted_passwords
  894. # Restore a user with an unsalted password
  895. user = User.find(1)
  896. user.salt = nil
  897. user.hashed_password = User.hash_password("unsalted")
  898. user.save!
  899. User.salt_unsalted_passwords!
  900. user.reload
  901. # Salt added
  902. assert !user.salt.blank?
  903. # Password still valid
  904. assert user.check_password?("unsalted")
  905. assert_equal user, User.try_to_login(user.login, "unsalted")
  906. end
  907. if Object.const_defined?(:OpenID)
  908. def test_setting_identity_url
  909. normalized_open_id_url = 'http://example.com/'
  910. u = User.new( :identity_url => 'http://example.com/' )
  911. assert_equal normalized_open_id_url, u.identity_url
  912. end
  913. def test_setting_identity_url_without_trailing_slash
  914. normalized_open_id_url = 'http://example.com/'
  915. u = User.new( :identity_url => 'http://example.com' )
  916. assert_equal normalized_open_id_url, u.identity_url
  917. end
  918. def test_setting_identity_url_without_protocol
  919. normalized_open_id_url = 'http://example.com/'
  920. u = User.new( :identity_url => 'example.com' )
  921. assert_equal normalized_open_id_url, u.identity_url
  922. end
  923. def test_setting_blank_identity_url
  924. u = User.new( :identity_url => 'example.com' )
  925. u.identity_url = ''
  926. assert u.identity_url.blank?
  927. end
  928. def test_setting_invalid_identity_url
  929. u = User.new( :identity_url => 'this is not an openid url' )
  930. assert u.identity_url.blank?
  931. end
  932. else
  933. puts "Skipping openid tests."
  934. end
  935. end