18
18
from zope.component import getUtility
19
19
from zope.security.proxy import removeSecurityProxy
21
from canonical.database.sqlbase import flush_database_updates
22
21
from canonical.launchpad import _
23
22
from canonical.launchpad.interfaces.authtoken import LoginTokenType
24
23
from canonical.launchpad.interfaces.emailaddress import (
48
47
IRequestPeopleMerge,
50
from lp.registry.interfaces.teammembership import ITeamMembershipSet
51
49
from lp.services.propertycache import cachedproperty
52
50
from lp.soyuz.enums import ArchiveStatus
53
51
from lp.soyuz.interfaces.archive import IArchiveSet
143
141
Before merging this moves each email address of the duplicate person
144
142
to the target person, and resets them to `NEW`.
146
for email in self.dupe_person_emails:
147
email = IMasterObject(email)
148
# EmailAddress.person and EmailAddress.account are readonly
149
# fields, so we need to remove the security proxy here.
150
naked_email = removeSecurityProxy(email)
151
naked_email.personID = self.target_person.id
152
naked_email.accountID = self.target_person.accountID
153
# XXX: Guilherme Salgado 2007-10-15: Maybe this status change
154
# should be done only when merging people but not when merging
156
naked_email.status = EmailAddressStatus.NEW
157
flush_database_updates()
158
getUtility(IPersonSet).merge(self.dupe_person, self.target_person)
144
if not self.dupe_person.is_team:
145
# Transfer user email addresses. Team addresses will be deleted.
146
for email in self.dupe_person_emails:
147
email = IMasterObject(email)
148
# EmailAddress.person and EmailAddress.account are readonly
149
# fields, so we need to remove the security proxy here.
150
naked_email = removeSecurityProxy(email)
151
naked_email.personID = self.target_person.id
152
naked_email.accountID = self.target_person.accountID
153
naked_email.status = EmailAddressStatus.NEW
154
getUtility(IPersonSet).merge(
155
self.dupe_person, self.target_person, reviewer=self.user)
159
156
self.request.response.addInfoNotification(self.merge_message)
160
157
self.next_url = self.success_url
219
216
def registry_experts(self):
220
217
return getUtility(ILaunchpadCelebrities).registry_experts
222
def doMerge(self, data):
223
"""Purge the non-transferable team data and merge.
225
For the duplicate team:
227
- If a mailing list exists, and is REGISTERED, DECLINED, FAILED or
228
INACTIVE, it is purged.
230
- Unsets the contact address.
232
If the target team is the Registry Experts:
234
- The duplicate team is withdrawn from all teams that it is itself a
238
# A team cannot have more than one mailing list. The old list will
239
# remain in the archive.
240
purge_list = (self.dupe_person.mailing_list is not None
241
and self.dupe_person.mailing_list.status in PURGE_STATES)
243
self.dupe_person.mailing_list.purge()
244
# Team email addresses are not transferable.
245
self.dupe_person.setContactAddress(None)
246
# The registry experts does not want to acquire super teams from a
247
# merge. This operation requires unrestricted access to ensure
248
# the user who has permission to delete a team can remove the
249
# team from other teams.
250
if self.target_person == self.registry_experts:
251
all_super_teams = set(self.dupe_person.teams_participated_in)
252
indirect_super_teams = set(
253
self.dupe_person.teams_indirectly_participated_in)
254
super_teams = all_super_teams - indirect_super_teams
255
naked_dupe_person = removeSecurityProxy(self.dupe_person)
256
for team in super_teams:
257
naked_dupe_person.retractTeamMembership(team, self.user)
258
del naked_dupe_person
259
# We have sent another series of calls to the db, potentially a long
260
# sequence depending on the merge. We want everything synced up
262
flush_database_updates()
263
super(AdminTeamMergeView, self).doMerge(data)
265
219
def validate(self, data):
266
220
"""Check there are no mailing lists associated with the dupe team."""
267
221
# If errors have already been discovered there is no need to continue,
273
227
super(AdminTeamMergeView, self).validate(data)
274
228
dupe_team = data['dupe_person']
275
229
target_team = data['target_person']
276
# Merge cannot reconcile cyclic membership in super teams.
277
# Super team memberships are automatically removed when merging into
278
# the registry experts team. When merging into any other team, an
279
# error must be raised to explain that the user must remove the teams
281
super_teams_count = dupe_team.super_teams.count()
282
if target_team != self.registry_experts and super_teams_count > 0:
284
"${name} has super teams, so it can't be merged.",
285
mapping=dict(name=dupe_team.name)))
286
230
# We cannot merge the teams if there is a mailing list on the
287
231
# duplicate person, unless that mailing list is purged.
288
232
if self.hasMailingList(dupe_team):
306
250
self.should_confirm_member_deactivation = True
252
super(AdminTeamMergeView, self).doMerge(data)
310
254
@action('Deactivate Members and Merge',
311
255
name='deactivate_members_and_merge')
312
256
def deactivate_members_and_merge_action(self, action, data):
313
257
"""Deactivate all members of the team to be merged and merge them."""
314
258
self.setUpPeople(data)
316
'Deactivating all members as this team is being merged into %s. '
317
'Please contact the administrators of <%s> if you have any '
318
'issues with this change.'
319
% (self.target_person.unique_displayname,
320
canonical_url(self.target_person)))
321
membershipset = getUtility(ITeamMembershipSet)
322
membershipset.deactivateActiveMemberships(
323
self.dupe_person, comment, self.user)
324
flush_database_updates()
259
super(AdminTeamMergeView, self).doMerge(data)
328
262
class DeleteTeamView(AdminTeamMergeView):
545
479
token = logintokenset.new(
546
480
self.user, login, removeSecurityProxy(email).email,
547
481
LoginTokenType.ACCOUNTMERGE)
549
# XXX: SteveAlexander 2006-03-07: An experiment to see if this
550
# improves problems with merge people tests.
551
import canonical.database.sqlbase
552
canonical.database.sqlbase.flush_database_updates()
553
482
token.sendMergeRequestEmail()
554
483
self.next_url = './+mergerequest-sent?dupe=%d' % dupeaccount.id