Files
teams/teams_app/schemas/user_schema.py
2026-01-07 09:17:34 +07:00

288 lines
9.2 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import graphene
from graphene_django import DjangoObjectType
from django.contrib.auth import get_user_model
from ..models import Team as TeamModel, TeamMember as TeamMemberModel, TeamInvitation as TeamInvitationModel, UserProfile
from .team_schema import SelectedLocation
UserModel = get_user_model()
def _get_or_create_user_with_profile(logto_id: str):
user, _ = UserModel.objects.get_or_create(
username=logto_id,
defaults={'email': ''}
)
profile, _ = UserProfile.objects.get_or_create(
logto_id=logto_id,
defaults={'user': user}
)
if profile.user_id != user.id:
profile.user = user
profile.save(update_fields=['user'])
# Attach profile to user for resolvers
user.profile = profile
return user
class Team(DjangoObjectType):
id = graphene.String()
logtoOrgId = graphene.String()
teamType = graphene.String()
selectedLocation = graphene.Field(SelectedLocation)
class Meta:
model = TeamModel
fields = ('uuid', 'name', 'logto_org_id', 'team_type', 'created_at')
def resolve_id(self, info):
return self.uuid
def resolve_logtoOrgId(self, info):
return self.logto_org_id
def resolve_teamType(self, info):
return self.team_type
def resolve_selectedLocation(self, info):
loc_type = getattr(self, 'selected_location_type', None)
loc_uuid = getattr(self, 'selected_location_uuid', None)
if loc_type and loc_uuid:
return SelectedLocation(
type=loc_type,
uuid=loc_uuid,
name=getattr(self, 'selected_location_name', None),
latitude=getattr(self, 'selected_location_latitude', None),
longitude=getattr(self, 'selected_location_longitude', None)
)
return None
class User(DjangoObjectType):
id = graphene.String()
firstName = graphene.String()
lastName = graphene.String()
phone = graphene.String()
avatarId = graphene.String()
activeTeamId = graphene.String()
activeTeam = graphene.Field(Team)
teams = graphene.List(Team)
class Meta:
model = UserModel
fields = ('username', 'first_name', 'last_name', 'email')
def resolve_id(self, info):
if hasattr(self, 'profile') and self.profile:
return self.profile.logto_id
return self.username
def resolve_firstName(self, info):
return self.first_name
def resolve_lastName(self, info):
return self.last_name
def resolve_phone(self, info):
return getattr(self.profile, 'phone', None)
def resolve_avatarId(self, info):
return getattr(self.profile, 'avatar_id', None)
def resolve_activeTeamId(self, info):
return self.profile.active_team.uuid if getattr(self, 'profile', None) and self.profile.active_team else None
def resolve_activeTeam(self, info):
return self.profile.active_team if getattr(self, 'profile', None) else None
def resolve_teams(self, info):
# Возвращаем Team объекты через TeamMember отношения
from ..models import TeamMember as TeamMemberModel
team_members = TeamMemberModel.objects.filter(user=self)
return [member.team for member in team_members]
class TeamMember(DjangoObjectType):
user = graphene.Field(User)
role = graphene.String()
joinedAt = graphene.String()
class Meta:
from ..models import TeamMember as TeamMemberModel
model = TeamMemberModel
fields = ('uuid', 'role')
def resolve_joinedAt(self, info):
return self.joined_at.isoformat() if self.joined_at else None
class TeamInvitation(DjangoObjectType):
email = graphene.String()
role = graphene.String()
status = graphene.String()
invitedBy = graphene.String()
expiresAt = graphene.String()
createdAt = graphene.String()
class Meta:
model = TeamInvitationModel
fields = ('uuid', 'email', 'role', 'status')
def resolve_invitedBy(self, info):
return self.invited_by
def resolve_expiresAt(self, info):
return self.expires_at.isoformat() if self.expires_at else None
def resolve_createdAt(self, info):
return self.created_at.isoformat() if self.created_at else None
class TeamWithMembers(DjangoObjectType):
id = graphene.String()
members = graphene.List(TeamMember)
invitations = graphene.List(TeamInvitation)
class Meta:
model = TeamModel
fields = ('uuid', 'name', 'created_at')
def resolve_id(self, info):
return self.uuid
def resolve_members(self, info):
return self.members.all()
def resolve_invitations(self, info):
return self.invitations.filter(status='PENDING')
class UserQuery(graphene.ObjectType):
me = graphene.Field(User)
get_team = graphene.Field(TeamWithMembers, team_id=graphene.String(required=True))
def resolve_me(self, info):
# Получаем user_id из ID Token
user_id = getattr(info.context, 'user_id', None)
if not user_id:
return None
try:
return _get_or_create_user_with_profile(user_id)
except Exception:
return None
def resolve_get_team(self, info, team_id):
try:
return TeamModel.objects.get(uuid=team_id)
except TeamModel.DoesNotExist:
return None
class CreateTeamInput(graphene.InputObjectType):
name = graphene.String(required=True)
teamType = graphene.String() # BUYER или SELLER
class UpdateUserInput(graphene.InputObjectType):
firstName = graphene.String()
lastName = graphene.String()
phone = graphene.String()
avatarId = graphene.String()
class CreateTeamMutation(graphene.Mutation):
class Arguments:
input = CreateTeamInput(required=True)
team = graphene.Field(Team)
def mutate(self, info, input):
# Получаем user_id из контекста (ID Token)
user_id = getattr(info.context, 'user_id', None)
if not user_id:
raise Exception("User not authenticated")
try:
owner = _get_or_create_user_with_profile(user_id)
team = TeamModel.objects.create(
name=input.name,
owner=owner,
team_type=input.teamType or 'BUYER'
)
# Добавляем owner как участника команды с ролью OWNER
TeamMemberModel.objects.create(
team=team,
user=owner,
role='OWNER'
)
# Устанавливаем как активную команду, если у пользователя её нет
if hasattr(owner, 'profile') and not owner.profile.active_team:
owner.profile.active_team = team
owner.profile.save(update_fields=['active_team'])
return CreateTeamMutation(team=team)
except Exception as e:
raise Exception(f"Failed to create team: {str(e)}")
class UpdateUserMutation(graphene.Mutation):
class Arguments:
userId = graphene.String(required=True)
input = UpdateUserInput(required=True)
user = graphene.Field(User)
def mutate(self, info, userId, input):
# Проверяем права - пользователь может редактировать только себя
context_user_id = getattr(info.context, 'user_id', None)
if context_user_id != userId:
return UpdateUserMutation(user=None)
try:
user = _get_or_create_user_with_profile(userId)
if input.firstName is not None:
user.first_name = input.firstName
if input.lastName is not None:
user.last_name = input.lastName
user.save()
if hasattr(user, 'profile'):
if input.phone is not None:
user.profile.phone = input.phone
if input.avatarId is not None:
user.profile.avatar_id = input.avatarId
user.profile.save()
return UpdateUserMutation(user=user)
except Exception:
return UpdateUserMutation(user=None)
class SwitchTeamMutation(graphene.Mutation):
class Arguments:
teamId = graphene.String(required=True)
user = graphene.Field(User)
def mutate(self, info, teamId):
user_id = getattr(info.context, 'user_id', None)
if not user_id:
raise Exception("User not authenticated")
try:
team = TeamModel.objects.get(uuid=teamId)
user = _get_or_create_user_with_profile(user_id)
if hasattr(user, 'profile'):
user.profile.active_team = team
user.profile.save(update_fields=['active_team'])
return SwitchTeamMutation(user=user)
except TeamModel.DoesNotExist:
raise Exception("Team not found")
class UserMutation(graphene.ObjectType):
create_team = CreateTeamMutation.Field()
update_user = UpdateUserMutation.Field()
switch_team = SwitchTeamMutation.Field()
user_schema = graphene.Schema(query=UserQuery, mutation=UserMutation)