From ade7a2537037cd7a8af9a82a8b33ed19f0c32820 Mon Sep 17 00:00:00 2001 From: Mahdi Date: Sun, 30 Jun 2024 13:42:24 +0330 Subject: [PATCH] Combine store badge & identity insertion methods --- .../migrations/20240630094629_/migration.sql | 2 + prisma/schema.prisma | 3 +- src/flow/flow.controller.ts | 20 ++--- src/user/dto/ConnectFlowDTOs.ts | 12 +++ src/user/users.controller.ts | 81 ++++++++++++++++--- 5 files changed, 98 insertions(+), 20 deletions(-) create mode 100644 prisma/migrations/20240630094629_/migration.sql diff --git a/prisma/migrations/20240630094629_/migration.sql b/prisma/migrations/20240630094629_/migration.sql new file mode 100644 index 0000000..38e1e1b --- /dev/null +++ b/prisma/migrations/20240630094629_/migration.sql @@ -0,0 +1,2 @@ +-- DropIndex +DROP INDEX "User_identity_key"; diff --git a/prisma/schema.prisma b/prisma/schema.prisma index 18409fa..4522438 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -15,7 +15,8 @@ model User { isBadgeHolder Int @map("is_badgeholder") createdAt DateTime @default(now()) @map("created_at") updatedAt DateTime @default(now()) @updatedAt @map("updated_at") - identity Json? @unique() + identity Json? // Ideally should be unique except {} and null values but Prisma doesn't support partial + // unique constraints badges Json? projectVotes Vote[] nonce Nonce? diff --git a/src/flow/flow.controller.ts b/src/flow/flow.controller.ts index 3278408..b669a0f 100644 --- a/src/flow/flow.controller.ts +++ b/src/flow/flow.controller.ts @@ -682,7 +682,7 @@ export class FlowController { // for (let i = 2; i < 9; i++) { const user = await this.prismaService.user.findFirst({ select: { id: true }, - where: { address: '0xcb73a971e3643f756E0Ce8c81cccA3D7B6AB2b9d' }, + where: { address: '0x9cb5129b4c710dB85F1dcd4071CB5f777e5B7612' }, }); // console.log(user?.id); @@ -690,7 +690,7 @@ export class FlowController { if (user && !userId) { userId = user?.id; console.log(user.id); - } else return; + } else if (!user && !userId) return; // userId = 448; @@ -726,17 +726,17 @@ export class FlowController { where: { userId: userId }, }); - await this.prismaService.user.update({ - where: { id: userId }, - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-ignore - data: { identity: null, badges: null }, - }); - - // await this.prismaService.user.deleteMany({ + // await this.prismaService.user.update({ // where: { id: userId }, + // // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // // @ts-ignore + // data: { identity: null, badges: null }, // }); + await this.prismaService.user.deleteMany({ + where: { id: userId }, + }); + // } } } diff --git a/src/user/dto/ConnectFlowDTOs.ts b/src/user/dto/ConnectFlowDTOs.ts index 2bfd59d..a406cdb 100644 --- a/src/user/dto/ConnectFlowDTOs.ts +++ b/src/user/dto/ConnectFlowDTOs.ts @@ -1,5 +1,17 @@ import { IsDefined, IsEthereumAddress } from 'class-validator'; +export class StoreBadgesAndIdentityDTO { + @IsEthereumAddress() + @IsDefined() + mainAddress: string; + + @IsDefined() + signature: string; + + @IsDefined() + identity: string; +} + export class StoreBadgesDTO { @IsEthereumAddress() @IsDefined() diff --git a/src/user/users.controller.ts b/src/user/users.controller.ts index 35ae287..1e0c3a8 100644 --- a/src/user/users.controller.ts +++ b/src/user/users.controller.ts @@ -18,6 +18,7 @@ import { import { AuthedReq } from 'src/utils/types/AuthedReq.type'; import { GetBadgesDTO, + StoreBadgesAndIdentityDTO, StoreBadgesDTO, StoreIdentityDTO, } from './dto/ConnectFlowDTOs'; @@ -33,6 +34,59 @@ export class UsersController { private readonly logger = new Logger(UsersController.name); constructor(private readonly prismaService: PrismaService) {} + @UseGuards(AuthGuard) + @Post('/store-badges-identity') + async storeBadgesAndIdentity( + @Req() { userId }: AuthedReq, + @Body() { mainAddress, signature, identity }: StoreBadgesAndIdentityDTO, + ) { + if ( + !(await verifySignature( + 'Sign this message to generate your Semaphore identity.', + signature, + mainAddress, + )) + ) + throw new UnauthorizedException('Signature invalid'); + + // if (!verifyIdentity(identity)) + // throw new UnauthorizedException('Invalid identity format'); + + const user = await this.prismaService.user.findUnique({ + select: { badges: true, identity: true, opAddress: true }, + where: { id: userId }, + }); + + if (!user) throw new InternalServerErrorException("User doesn't exist"); + + if (user.identity?.valueOf() || user.badges?.valueOf() || user.opAddress) + throw new ForbiddenException('User has already connected'); + + const badges = await getBadges(snapshotPoints, mainAddress); + + try { + await this.prismaService.user.update({ + where: { + id: userId, + }, + data: { + identity, + badges: badges || {}, + opAddress: mainAddress, + }, + }); + } catch (e: unknown) { + if ( + e instanceof Prisma.PrismaClientKnownRequestError && + e.code === 'P2002' + ) { + throw new ConflictException('This eth address is already connected'); + } + } + + return 'success'; + } + @UseGuards(AuthGuard) @Post('/store-badges') async storeBadges( @@ -63,15 +117,24 @@ export class UsersController { if (!user.identity?.valueOf) throw new BadRequestException('You need to insert your identity first'); - await this.prismaService.user.update({ - where: { - id: userId, - }, - data: { - badges: badges || {}, - opAddress: mainAddress, - }, - }); + try { + await this.prismaService.user.update({ + where: { + id: userId, + }, + data: { + badges: badges || {}, + opAddress: mainAddress, + }, + }); + } catch (e: unknown) { + if ( + e instanceof Prisma.PrismaClientKnownRequestError && + e.code === 'P2002' + ) { + throw new ConflictException('This eth address is already connected'); + } + } return badges; }