@@ -48,8 +48,8 class User < Principal | |||||
48 | has_many :issue_categories, :foreign_key => 'assigned_to_id', :dependent => :nullify |
|
48 | has_many :issue_categories, :foreign_key => 'assigned_to_id', :dependent => :nullify | |
49 | has_many :changesets, :dependent => :nullify |
|
49 | has_many :changesets, :dependent => :nullify | |
50 | has_one :preference, :dependent => :destroy, :class_name => 'UserPreference' |
|
50 | has_one :preference, :dependent => :destroy, :class_name => 'UserPreference' | |
51 |
has_one :rss_token |
|
51 | has_one :rss_token, :class_name => 'Token', :conditions => "action='feeds'" | |
52 |
has_one :api_token |
|
52 | has_one :api_token, :class_name => 'Token', :conditions => "action='api'" | |
53 | belongs_to :auth_source |
|
53 | belongs_to :auth_source | |
54 |
|
54 | |||
55 | # Active non-anonymous users scope |
|
55 | # Active non-anonymous users scope | |
@@ -74,6 +74,8 class User < Principal | |||||
74 | validates_confirmation_of :password, :allow_nil => true |
|
74 | validates_confirmation_of :password, :allow_nil => true | |
75 | validates_inclusion_of :mail_notification, :in => MAIL_NOTIFICATION_OPTIONS.collect(&:first), :allow_blank => true |
|
75 | validates_inclusion_of :mail_notification, :in => MAIL_NOTIFICATION_OPTIONS.collect(&:first), :allow_blank => true | |
76 |
|
76 | |||
|
77 | before_destroy :remove_references_before_destroy | |||
|
78 | ||||
77 | def before_create |
|
79 | def before_create | |
78 | self.mail_notification = Setting.default_notification_option if self.mail_notification.blank? |
|
80 | self.mail_notification = Setting.default_notification_option if self.mail_notification.blank? | |
79 | true |
|
81 | true | |
@@ -473,6 +475,31 class User < Principal | |||||
473 | end |
|
475 | end | |
474 |
|
476 | |||
475 | private |
|
477 | private | |
|
478 | ||||
|
479 | # Removes references that are not handled by associations | |||
|
480 | # Things that are not deleted are reassociated with the anonymous user | |||
|
481 | def remove_references_before_destroy | |||
|
482 | return if self.id.nil? | |||
|
483 | ||||
|
484 | substitute = User.anonymous | |||
|
485 | Attachment.update_all ['author_id = ?', substitute.id], ['author_id = ?', id] | |||
|
486 | Comment.update_all ['author_id = ?', substitute.id], ['author_id = ?', id] | |||
|
487 | Issue.update_all ['author_id = ?', substitute.id], ['author_id = ?', id] | |||
|
488 | Issue.update_all 'assigned_to_id = NULL', ['assigned_to_id = ?', id] | |||
|
489 | Journal.update_all ['user_id = ?', substitute.id], ['user_id = ?', id] | |||
|
490 | JournalDetail.update_all ['old_value = ?', substitute.id.to_s], ["property = 'attr' AND prop_key = 'assigned_to_id' AND old_value = ?", id.to_s] | |||
|
491 | JournalDetail.update_all ['value = ?', substitute.id.to_s], ["property = 'attr' AND prop_key = 'assigned_to_id' AND value = ?", id.to_s] | |||
|
492 | Message.update_all ['author_id = ?', substitute.id], ['author_id = ?', id] | |||
|
493 | News.update_all ['author_id = ?', substitute.id], ['author_id = ?', id] | |||
|
494 | # Remove private queries and keep public ones | |||
|
495 | Query.delete_all ['user_id = ? AND is_public = ?', id, false] | |||
|
496 | Query.update_all ['user_id = ?', substitute.id], ['user_id = ?', id] | |||
|
497 | TimeEntry.update_all ['user_id = ?', substitute.id], ['user_id = ?', id] | |||
|
498 | Token.delete_all ['user_id = ?', id] | |||
|
499 | Watcher.delete_all ['user_id = ?', id] | |||
|
500 | WikiContent.update_all ['author_id = ?', substitute.id], ['author_id = ?', id] | |||
|
501 | WikiContent::Version.update_all ['author_id = ?', substitute.id], ['author_id = ?', id] | |||
|
502 | end | |||
476 |
|
503 | |||
477 | # Return password digest |
|
504 | # Return password digest | |
478 | def self.hash_password(clear_password) |
|
505 | def self.hash_password(clear_password) | |
@@ -498,4 +525,9 class AnonymousUser < User | |||||
498 | def mail; nil end |
|
525 | def mail; nil end | |
499 | def time_zone; nil end |
|
526 | def time_zone; nil end | |
500 | def rss_key; nil end |
|
527 | def rss_key; nil end | |
|
528 | ||||
|
529 | # Anonymous user can not be destroyed | |||
|
530 | def destroy | |||
|
531 | false | |||
|
532 | end | |||
501 | end |
|
533 | end |
@@ -62,12 +62,11 class RepositoryTest < ActiveSupport::TestCase | |||||
62 |
|
62 | |||
63 | def test_should_not_create_with_disabled_scm |
|
63 | def test_should_not_create_with_disabled_scm | |
64 | # disable Subversion |
|
64 | # disable Subversion | |
65 |
|
|
65 | with_settings :enabled_scm => ['Darcs', 'Git'] do | |
66 | repository = Repository::Subversion.new(:project => Project.find(3), :url => "svn://localhost") |
|
66 | repository = Repository::Subversion.new(:project => Project.find(3), :url => "svn://localhost") | |
67 | assert !repository.save |
|
67 | assert !repository.save | |
68 | assert_equal I18n.translate('activerecord.errors.messages.invalid'), repository.errors.on(:type) |
|
68 | assert_equal I18n.translate('activerecord.errors.messages.invalid'), repository.errors.on(:type) | |
69 | # re-enable Subversion for following tests |
|
69 | end | |
70 | Setting.delete_all |
|
|||
71 | end |
|
70 | end | |
72 |
|
71 | |||
73 | def test_scan_changesets_for_issue_ids |
|
72 | def test_scan_changesets_for_issue_ids |
@@ -109,12 +109,216 class UserTest < ActiveSupport::TestCase | |||||
109 | assert_equal "john", @admin.login |
|
109 | assert_equal "john", @admin.login | |
110 | end |
|
110 | end | |
111 |
|
111 | |||
112 | def test_destroy |
|
112 | def test_destroy_should_delete_members_and_roles | |
113 | User.find(2).destroy |
|
113 | members = Member.find_all_by_user_id(2) | |
|
114 | ms = members.size | |||
|
115 | rs = members.collect(&:roles).flatten.size | |||
|
116 | ||||
|
117 | assert_difference 'Member.count', - ms do | |||
|
118 | assert_difference 'MemberRole.count', - rs do | |||
|
119 | User.find(2).destroy | |||
|
120 | end | |||
|
121 | end | |||
|
122 | ||||
114 | assert_nil User.find_by_id(2) |
|
123 | assert_nil User.find_by_id(2) | |
115 | assert Member.find_all_by_user_id(2).empty? |
|
124 | assert Member.find_all_by_user_id(2).empty? | |
116 | end |
|
125 | end | |
117 |
|
126 | |||
|
127 | def test_destroy_should_update_attachments | |||
|
128 | attachment = Attachment.create!(:container => Project.find(1), | |||
|
129 | :file => uploaded_test_file("testfile.txt", "text/plain"), | |||
|
130 | :author_id => 2) | |||
|
131 | ||||
|
132 | User.find(2).destroy | |||
|
133 | assert_nil User.find_by_id(2) | |||
|
134 | assert_equal User.anonymous, attachment.reload.author | |||
|
135 | end | |||
|
136 | ||||
|
137 | def test_destroy_should_update_comments | |||
|
138 | comment = Comment.create!( | |||
|
139 | :commented => News.create!(:project_id => 1, :author_id => 1, :title => 'foo', :description => 'foo'), | |||
|
140 | :author => User.find(2), | |||
|
141 | :comments => 'foo' | |||
|
142 | ) | |||
|
143 | ||||
|
144 | User.find(2).destroy | |||
|
145 | assert_nil User.find_by_id(2) | |||
|
146 | assert_equal User.anonymous, comment.reload.author | |||
|
147 | end | |||
|
148 | ||||
|
149 | def test_destroy_should_update_issues | |||
|
150 | issue = Issue.create!(:project_id => 1, :author_id => 2, :tracker_id => 1, :subject => 'foo') | |||
|
151 | ||||
|
152 | User.find(2).destroy | |||
|
153 | assert_nil User.find_by_id(2) | |||
|
154 | assert_equal User.anonymous, issue.reload.author | |||
|
155 | end | |||
|
156 | ||||
|
157 | def test_destroy_should_unassign_issues | |||
|
158 | issue = Issue.create!(:project_id => 1, :author_id => 1, :tracker_id => 1, :subject => 'foo', :assigned_to_id => 2) | |||
|
159 | ||||
|
160 | User.find(2).destroy | |||
|
161 | assert_nil User.find_by_id(2) | |||
|
162 | assert_nil issue.reload.assigned_to | |||
|
163 | end | |||
|
164 | ||||
|
165 | def test_destroy_should_update_journals | |||
|
166 | issue = Issue.create!(:project_id => 1, :author_id => 2, :tracker_id => 1, :subject => 'foo') | |||
|
167 | issue.init_journal(User.find(2), "update") | |||
|
168 | issue.save! | |||
|
169 | ||||
|
170 | User.find(2).destroy | |||
|
171 | assert_nil User.find_by_id(2) | |||
|
172 | assert_equal User.anonymous, issue.journals.first.reload.user | |||
|
173 | end | |||
|
174 | ||||
|
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 | ||||
|
185 | User.find(2).destroy | |||
|
186 | assert_nil User.find_by_id(2) | |||
|
187 | assert_equal User.anonymous.id.to_s, journal_detail.reload.old_value | |||
|
188 | end | |||
|
189 | ||||
|
190 | def test_destroy_should_update_journal_details_value | |||
|
191 | issue = Issue.create!(:project_id => 1, :author_id => 1, :tracker_id => 1, :subject => 'foo') | |||
|
192 | issue.init_journal(User.find(1), "update") | |||
|
193 | issue.assigned_to_id = 2 | |||
|
194 | assert_difference 'JournalDetail.count' do | |||
|
195 | issue.save! | |||
|
196 | end | |||
|
197 | journal_detail = JournalDetail.first(:order => 'id DESC') | |||
|
198 | assert_equal '2', journal_detail.value | |||
|
199 | ||||
|
200 | User.find(2).destroy | |||
|
201 | assert_nil User.find_by_id(2) | |||
|
202 | assert_equal User.anonymous.id.to_s, journal_detail.reload.value | |||
|
203 | end | |||
|
204 | ||||
|
205 | def test_destroy_should_update_messages | |||
|
206 | board = Board.create!(:project_id => 1, :name => 'Board', :description => 'Board') | |||
|
207 | message = Message.create!(:board_id => board.id, :author_id => 2, :subject => 'foo', :content => 'foo') | |||
|
208 | ||||
|
209 | User.find(2).destroy | |||
|
210 | assert_nil User.find_by_id(2) | |||
|
211 | assert_equal User.anonymous, message.reload.author | |||
|
212 | end | |||
|
213 | ||||
|
214 | def test_destroy_should_update_news | |||
|
215 | news = News.create!(:project_id => 1, :author_id => 2, :title => 'foo', :description => 'foo') | |||
|
216 | ||||
|
217 | User.find(2).destroy | |||
|
218 | assert_nil User.find_by_id(2) | |||
|
219 | assert_equal User.anonymous, news.reload.author | |||
|
220 | end | |||
|
221 | ||||
|
222 | def test_destroy_should_delete_private_queries | |||
|
223 | query = Query.new(:name => 'foo', :is_public => false) | |||
|
224 | query.project_id = 1 | |||
|
225 | query.user_id = 2 | |||
|
226 | query.save! | |||
|
227 | ||||
|
228 | User.find(2).destroy | |||
|
229 | assert_nil User.find_by_id(2) | |||
|
230 | assert_nil Query.find_by_id(query.id) | |||
|
231 | end | |||
|
232 | ||||
|
233 | def test_destroy_should_update_public_queries | |||
|
234 | query = Query.new(:name => 'foo', :is_public => true) | |||
|
235 | query.project_id = 1 | |||
|
236 | query.user_id = 2 | |||
|
237 | query.save! | |||
|
238 | ||||
|
239 | User.find(2).destroy | |||
|
240 | assert_nil User.find_by_id(2) | |||
|
241 | assert_equal User.anonymous, query.reload.user | |||
|
242 | end | |||
|
243 | ||||
|
244 | def test_destroy_should_update_time_entries | |||
|
245 | entry = TimeEntry.new(:hours => '2', :spent_on => Date.today, :activity => TimeEntryActivity.create!(:name => 'foo')) | |||
|
246 | entry.project_id = 1 | |||
|
247 | entry.user_id = 2 | |||
|
248 | entry.save! | |||
|
249 | ||||
|
250 | User.find(2).destroy | |||
|
251 | assert_nil User.find_by_id(2) | |||
|
252 | assert_equal User.anonymous, entry.reload.user | |||
|
253 | end | |||
|
254 | ||||
|
255 | def test_destroy_should_delete_tokens | |||
|
256 | token = Token.create!(:user_id => 2, :value => 'foo') | |||
|
257 | ||||
|
258 | User.find(2).destroy | |||
|
259 | assert_nil User.find_by_id(2) | |||
|
260 | assert_nil Token.find_by_id(token.id) | |||
|
261 | end | |||
|
262 | ||||
|
263 | def test_destroy_should_delete_watchers | |||
|
264 | issue = Issue.create!(:project_id => 1, :author_id => 1, :tracker_id => 1, :subject => 'foo') | |||
|
265 | watcher = Watcher.create!(:user_id => 2, :watchable => issue) | |||
|
266 | ||||
|
267 | User.find(2).destroy | |||
|
268 | assert_nil User.find_by_id(2) | |||
|
269 | assert_nil Watcher.find_by_id(watcher.id) | |||
|
270 | end | |||
|
271 | ||||
|
272 | def test_destroy_should_update_wiki_contents | |||
|
273 | wiki_content = WikiContent.create!( | |||
|
274 | :text => 'foo', | |||
|
275 | :author_id => 2, | |||
|
276 | :page => WikiPage.create!(:title => 'Foo', :wiki => Wiki.create!(:project_id => 1, :start_page => 'Start')) | |||
|
277 | ) | |||
|
278 | wiki_content.text = 'bar' | |||
|
279 | assert_difference 'WikiContent::Version.count' do | |||
|
280 | wiki_content.save! | |||
|
281 | end | |||
|
282 | ||||
|
283 | User.find(2).destroy | |||
|
284 | assert_nil User.find_by_id(2) | |||
|
285 | assert_equal User.anonymous, wiki_content.reload.author | |||
|
286 | wiki_content.versions.each do |version| | |||
|
287 | assert_equal User.anonymous, version.reload.author | |||
|
288 | end | |||
|
289 | end | |||
|
290 | ||||
|
291 | def test_destroy_should_nullify_issue_categories | |||
|
292 | category = IssueCategory.create!(:project_id => 1, :assigned_to_id => 2, :name => 'foo') | |||
|
293 | ||||
|
294 | User.find(2).destroy | |||
|
295 | assert_nil User.find_by_id(2) | |||
|
296 | assert_nil category.reload.assigned_to_id | |||
|
297 | end | |||
|
298 | ||||
|
299 | def test_destroy_should_nullify_changesets | |||
|
300 | changeset = Changeset.create!( | |||
|
301 | :repository => Repository::Subversion.create!( | |||
|
302 | :project_id => 1, | |||
|
303 | :url => 'file:///var/svn' | |||
|
304 | ), | |||
|
305 | :revision => '12', | |||
|
306 | :committed_on => Time.now, | |||
|
307 | :committer => 'jsmith' | |||
|
308 | ) | |||
|
309 | assert_equal 2, changeset.user_id | |||
|
310 | ||||
|
311 | User.find(2).destroy | |||
|
312 | assert_nil User.find_by_id(2) | |||
|
313 | assert_nil changeset.reload.user_id | |||
|
314 | end | |||
|
315 | ||||
|
316 | def test_anonymous_user_should_not_be_destroyable | |||
|
317 | assert_no_difference 'User.count' do | |||
|
318 | assert_equal false, User.anonymous.destroy | |||
|
319 | end | |||
|
320 | end | |||
|
321 | ||||
118 | def test_validate_login_presence |
|
322 | def test_validate_login_presence | |
119 | @admin.login = "" |
|
323 | @admin.login = "" | |
120 | assert !@admin.save |
|
324 | assert !@admin.save |
General Comments 0
You need to be logged in to leave comments.
Login now