From e776002bec3610ee18da65a794fde4ccfdf410ec Mon Sep 17 00:00:00 2001 From: Ruslan Bakiev <572431+veikab@users.noreply.github.com> Date: Fri, 5 Jun 2026 12:07:02 +0700 Subject: [PATCH] Use Logto manager scope for access --- src/schemas/manager.ts | 21 +++++---------------- src/schemas/user.ts | 16 +++------------- 2 files changed, 8 insertions(+), 29 deletions(-) diff --git a/src/schemas/manager.ts b/src/schemas/manager.ts index 99db2ed..3f164d8 100644 --- a/src/schemas/manager.ts +++ b/src/schemas/manager.ts @@ -23,27 +23,13 @@ function displayName(firstName: string, lastName: string, phone: string): string return name.length > 0 ? name : phone } -async function isManagerUser(userId: number): Promise { - const user = await prisma.user.findUnique({ where: { id: userId } }) - if (user === null) return false - if (user.isStaff || user.isSuperuser) return true - const managerMembership = await prisma.teamMember.findFirst({ - where: { userId, role: { in: ['OWNER', 'MANAGER', 'ADMIN'] } }, - }) - return managerMembership !== null -} - async function requireManagerProfile(ctx: AuthContext) { requireScopes(ctx, 'manager') if (!ctx.userId) throw new GraphQLError('Not authenticated') - const profile = await prisma.userProfile.findUnique({ + return prisma.userProfile.findUnique({ where: { logtoId: ctx.userId }, include: { user: true, activeTeam: true }, }) - if (profile === null || !(await isManagerUser(profile.userId))) { - throw new GraphQLError('Manager access required', { extensions: { code: 'FORBIDDEN' } }) - } - return profile } export const managerResolvers = { @@ -51,7 +37,10 @@ export const managerResolvers = { managerUsers: async (_: unknown, __: unknown, ctx: AuthContext) => { const profile = await requireManagerProfile(ctx) const members = await prisma.teamMember.findMany({ - where: profile.activeTeamId === null ? {} : { teamId: profile.activeTeamId }, + where: + profile?.activeTeamId === undefined || profile.activeTeamId === null + ? {} + : { teamId: profile.activeTeamId }, include: { user: { include: { profile: { include: { activeTeam: true } } } }, team: true }, orderBy: { joinedAt: 'desc' }, }) diff --git a/src/schemas/user.ts b/src/schemas/user.ts index 00edc00..9827409 100644 --- a/src/schemas/user.ts +++ b/src/schemas/user.ts @@ -112,24 +112,14 @@ function displayName( return name.length > 0 ? name : phone; } -async function isManagerUser(userId: number): Promise { - const user = await prisma.user.findUnique({ where: { id: userId } }); - if (user === null) return false; - if (user.isStaff || user.isSuperuser) return true; - const managerMembership = await prisma.teamMember.findFirst({ - where: { userId, role: { in: ["OWNER", "MANAGER", "ADMIN"] } }, - }); - return managerMembership !== null; -} - async function mapProfileUser( profile: Awaited>, + ctx: AuthContext, ) { const memberships = await prisma.teamMember.findMany({ where: { userId: profile.userId }, include: { team: true }, }); - const isManager = await isManagerUser(profile.userId); return { id: profile.logtoId, firstName: profile.user.firstName, @@ -141,7 +131,7 @@ async function mapProfileUser( ), phone: profile.phone, avatarId: profile.avatarId, - isManager, + isManager: ctx.scopes.includes("manager"), activeTeamId: profile.activeTeam?.uuid ?? null, activeTeam: profile.activeTeam ? { @@ -167,7 +157,7 @@ export const userResolvers = { me: async (_: unknown, __: unknown, ctx: AuthContext) => { if (!ctx.userId) throw new GraphQLError("Not authenticated"); const profile = await getOrCreateProfile(ctx.userId); - return mapProfileUser(profile); + return mapProfileUser(profile, ctx); }, getTeam: async (_: unknown, args: { teamId: string }, ctx: AuthContext) => {