Initial commit from monorepo
This commit is contained in:
287
teams_app/schemas/user_schema.py
Normal file
287
teams_app/schemas/user_schema.py
Normal file
@@ -0,0 +1,287 @@
|
||||
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)
|
||||
Reference in New Issue
Block a user