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 36KB

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