|
@@ -27,7 +27,9 @@ from sentry.models.authenticator import Authenticator
|
|
|
from sentry.models.avatars import UserAvatar
|
|
|
from sentry.models.lostpasswordhash import LostPasswordHash
|
|
|
from sentry.models.outbox import ControlOutbox, OutboxCategory, OutboxScope
|
|
|
+from sentry.services.hybrid_cloud.organization import organization_service
|
|
|
from sentry.services.hybrid_cloud.user import RpcUser
|
|
|
+from sentry.silo import SiloMode
|
|
|
from sentry.types.integrations import EXTERNAL_PROVIDERS, ExternalProviders
|
|
|
from sentry.types.region import find_regions_for_user
|
|
|
from sentry.utils.http import absolute_uri
|
|
@@ -291,20 +293,13 @@ class User(BaseModel, AbstractBaseUser):
|
|
|
|
|
|
def merge_to(from_user, to_user):
|
|
|
# TODO: we could discover relations automatically and make this useful
|
|
|
- from sentry import roles
|
|
|
from sentry.models import (
|
|
|
- Activity,
|
|
|
AuditLogEntry,
|
|
|
Authenticator,
|
|
|
AuthIdentity,
|
|
|
- GroupAssignee,
|
|
|
- GroupBookmark,
|
|
|
- GroupSeen,
|
|
|
- GroupShare,
|
|
|
- GroupSubscription,
|
|
|
Identity,
|
|
|
OrganizationMember,
|
|
|
- OrganizationMemberTeam,
|
|
|
+ OrganizationMemberMapping,
|
|
|
UserAvatar,
|
|
|
UserEmail,
|
|
|
UserOption,
|
|
@@ -314,33 +309,20 @@ class User(BaseModel, AbstractBaseUser):
|
|
|
"user.merge", extra={"from_user_id": from_user.id, "to_user_id": to_user.id}
|
|
|
)
|
|
|
|
|
|
- for obj in OrganizationMember.objects.filter(user_id=from_user.id):
|
|
|
- try:
|
|
|
- with transaction.atomic():
|
|
|
- obj.update(user_id=to_user.id)
|
|
|
- # this will error if both users are members of obj.org
|
|
|
- except IntegrityError:
|
|
|
- pass
|
|
|
-
|
|
|
- # identify the highest priority membership
|
|
|
- # only applies if both users are members of obj.org
|
|
|
- # if roles are different, grants combined user the higher of the two
|
|
|
- to_member = OrganizationMember.objects.get(
|
|
|
- organization=obj.organization_id, user_id=to_user.id
|
|
|
+ organization_ids: List[int]
|
|
|
+ if SiloMode.get_current_mode() == SiloMode.MONOLITH:
|
|
|
+ organization_ids = OrganizationMember.objects.filter(user_id=from_user.id).values_list(
|
|
|
+ "organization_id", flat=True
|
|
|
+ )
|
|
|
+ else:
|
|
|
+ organization_ids = OrganizationMemberMapping.objects.filter(
|
|
|
+ user_id=from_user.id
|
|
|
+ ).values_list("organization_id", flat=True)
|
|
|
+
|
|
|
+ for organization_id in organization_ids:
|
|
|
+ organization_service.merge_users(
|
|
|
+ organization_id=organization_id, from_user_id=from_user.id, to_user_id=to_user.id
|
|
|
)
|
|
|
- if roles.get(obj.role).priority > roles.get(to_member.role).priority:
|
|
|
- to_member.update(role=obj.role)
|
|
|
-
|
|
|
- for team in obj.teams.all():
|
|
|
- try:
|
|
|
- with transaction.atomic():
|
|
|
- OrganizationMemberTeam.objects.create(
|
|
|
- organizationmember=to_member, team=team
|
|
|
- )
|
|
|
- # this will error if both users are on the same team in obj.org,
|
|
|
- # in which case, no need to update anything
|
|
|
- except IntegrityError:
|
|
|
- pass
|
|
|
|
|
|
model_list = (
|
|
|
Authenticator,
|
|
@@ -348,11 +330,6 @@ class User(BaseModel, AbstractBaseUser):
|
|
|
UserAvatar,
|
|
|
UserEmail,
|
|
|
UserOption,
|
|
|
- GroupAssignee,
|
|
|
- GroupBookmark,
|
|
|
- GroupSeen,
|
|
|
- GroupShare,
|
|
|
- GroupSubscription,
|
|
|
)
|
|
|
|
|
|
for model in model_list:
|
|
@@ -363,7 +340,6 @@ class User(BaseModel, AbstractBaseUser):
|
|
|
except IntegrityError:
|
|
|
pass
|
|
|
|
|
|
- Activity.objects.filter(user_id=from_user.id).update(user_id=to_user.id)
|
|
|
# users can be either the subject or the object of actions which get logged
|
|
|
AuditLogEntry.objects.filter(actor=from_user).update(actor=to_user)
|
|
|
AuditLogEntry.objects.filter(target_user=from_user).update(target_user=to_user)
|