diff --git a/src/components/user/user.edgedb.repository.ts b/src/components/user/user.edgedb.repository.ts index a96254f50a..852a339a6c 100644 --- a/src/components/user/user.edgedb.repository.ts +++ b/src/components/user/user.edgedb.repository.ts @@ -1,6 +1,6 @@ import { Injectable } from '@nestjs/common'; import { ID, NotImplementedException, PublicOf } from '~/common'; -import { e, RepoFor, ScopeOf } from '~/core/edgedb'; +import { disableAccessPolicies, e, RepoFor, ScopeOf } from '~/core/edgedb'; import { AssignOrganizationToUser, RemoveOrganizationFromUser, @@ -42,10 +42,19 @@ export class UserEdgeDBRepository const query = e.select(e.User, () => ({ filter_single: { email }, })); - const result = await this.db.run(query); + const result = await this.db.withOptions(disableAccessPolicies).run(query); return !!result; } + getUserByEmailAddress(email: string) { + const query = e.select(e.User, (user) => ({ + ...this.hydrate(user), + filter_single: { email }, + })); + + return this.db.run(query); + } + protected listFilters(user: ScopeOf, input: UserListInput) { if (!input.filter) return []; return [ diff --git a/src/components/user/user.repository.ts b/src/components/user/user.repository.ts index e1a43f6f02..1f5a0d2275 100644 --- a/src/components/user/user.repository.ts +++ b/src/components/user/user.repository.ts @@ -22,6 +22,7 @@ import { matchProps, merge, paginate, + path, property, requestingUser, sortWith, @@ -243,6 +244,26 @@ export class UserRepository extends DtoRepository( return !!result; } + async getUserByEmailAddress(email: string, session: Session) { + const query = this.db + .query() + .matchNode('node', 'User') + .where( + path([ + node('node'), + relation('out', '', 'email', ACTIVE), + node({ + value: email, + }), + ]), + ) + .apply(this.privileges.forUser(session).filterToReadable()) + .apply(this.hydrate(session)); + + const result = await query.first(); + return result?.dto ?? null; + } + async assignOrganizationToUser({ userId, orgId, diff --git a/src/components/user/user.resolver.ts b/src/components/user/user.resolver.ts index 3b755cb360..e3b202e9ba 100644 --- a/src/components/user/user.resolver.ts +++ b/src/components/user/user.resolver.ts @@ -129,6 +129,17 @@ export class UserResolver { return await this.userService.checkEmail(email); } + @Query(() => User, { + description: 'Returns a user for a given email address', + nullable: true, + }) + async userByEmail( + @LoggedInSession() session: Session, + @Args() { email }: CheckEmailArgs, + ): Promise { + return await this.userService.getUserByEmailAddress(email, session); + } + @ResolveField(() => SecuredUnavailabilityList) async unavailabilities( @AnonSession() session: Session, diff --git a/src/components/user/user.service.ts b/src/components/user/user.service.ts index 10d6f6f40a..0a5446b1eb 100644 --- a/src/components/user/user.service.ts +++ b/src/components/user/user.service.ts @@ -333,6 +333,11 @@ export class UserService { return !exists; } + async getUserByEmailAddress(email: string, session: Session) { + const user = await this.userRepo.getUserByEmailAddress(email, session); + return user ? this.secure(user, session) : null; + } + async assignOrganizationToUser(request: AssignOrganizationToUser) { await this.userRepo.assignOrganizationToUser(request); }