##// END OF EJS Templates
When destroying a user, remove all references to that user (#7296)....
Jean-Philippe Lang -
r4606:e809d40f4ed9
parent child
Show More
@@ -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, :dependent => :destroy, :class_name => 'Token', :conditions => "action='feeds'"
51 has_one :rss_token, :class_name => 'Token', :conditions => "action='feeds'"
52 has_one :api_token, :dependent => :destroy, :class_name => 'Token', :conditions => "action='api'"
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 Setting.enabled_scm = ['Darcs', 'Git']
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