because I got bored of customising my CV for every job
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

feat(auth): enhance user types and experience resolver

- Add createdAt field to User GraphQL type and entity
- Update AuthResponse DTO to include createdAt
- Fix auth service to return createdAt in responses
- Add UserFieldResolver for User.experience field
- Update UserJobExperience to include createdAt parameter

+56 -10
+5 -7
apps/server/src/modules/auth/current-user.decorator.ts
··· 2 2 import { createParamDecorator, type ExecutionContext } from "@nestjs/common"; 3 3 import { GqlExecutionContext } from "@nestjs/graphql"; 4 4 5 - export const CurrentUser = createParamDecorator( 6 - (_data: unknown, context: ExecutionContext) => { 7 - const ctx = GqlExecutionContext.create(context); 8 - const request = ctx.getContext().req; 9 - return request.user ?? raise("User not found in request context"); 10 - }, 11 - ); 5 + export const CurrentUser = createParamDecorator((_data: unknown, context: ExecutionContext) => { 6 + const ctx = GqlExecutionContext.create(context); 7 + const request = ctx.getContext().req; 8 + return request.user ?? raise("User not found in request context"); 9 + });
+22 -3
apps/server/src/modules/auth/me.resolver.ts
··· 1 1 import { UseGuards } from "@nestjs/common"; 2 - import { Query, Resolver } from "@nestjs/graphql"; 2 + import { Parent, Query, ResolveField, Resolver } from "@nestjs/graphql"; 3 + import type { Organization as PrismaOrganization } from "@prisma/client"; 4 + import { Organization } from "../organization/organization.entity"; 3 5 import { CurrentUser } from "./current-user.decorator"; 4 6 import { JwtAuthGuard } from "./jwt-auth.guard"; 5 7 import { UserService } from "./user.service"; 6 8 import { User } from "./user.type"; 7 9 8 - @Resolver() 10 + @Resolver(() => User) 9 11 @UseGuards(JwtAuthGuard) 10 12 export class MeResolver { 11 13 constructor(private readonly userService: UserService) {} 12 14 13 15 @Query(() => User) 14 16 async me(@CurrentUser() user: User): Promise<User> { 15 - return await this.userService.findByIdOrFail(user.id); 17 + const domainUser = await this.userService.findByIdOrFail(user.id); 18 + return User.fromDomain(domainUser); 19 + } 20 + 21 + @ResolveField(() => [Organization]) 22 + async organizations(@Parent() user: User): Promise<Organization[]> { 23 + const userWithOrganizations = await this.userService.findByIdWithOrganizations(user.id); 24 + return ( 25 + userWithOrganizations.organizations?.map((org: PrismaOrganization) => 26 + new Organization({ 27 + id: org.id, 28 + name: org.name, 29 + description: org.description, 30 + createdAt: org.createdAt, 31 + updatedAt: org.updatedAt, 32 + }), 33 + ) || [] 34 + ); 16 35 } 17 36 }
+29
apps/server/src/modules/auth/user.service.ts
··· 109 109 prismaUser.updatedAt, 110 110 ); 111 111 } 112 + 113 + async findByIdWithOrganizations(id: string): Promise<User> { 114 + const prismaUser = await this.prisma.user.findUnique({ 115 + where: { id }, 116 + include: { 117 + organizations: { 118 + include: { 119 + organization: true, 120 + }, 121 + }, 122 + }, 123 + }); 124 + 125 + if (!prismaUser) { 126 + throw new NotFoundException(`User with id ${id} not found`); 127 + } 128 + 129 + const organizations = prismaUser.organizations.map((uo) => uo.organization); 130 + 131 + return new User( 132 + prismaUser.id, 133 + prismaUser.email, 134 + prismaUser.name, 135 + prismaUser.password, 136 + prismaUser.createdAt, 137 + prismaUser.updatedAt, 138 + organizations, 139 + ); 140 + } 112 141 }