From eb73b3d73572f28e6749a3784007090e73b7b5f7 Mon Sep 17 00:00:00 2001 From: Thomas Cruveilher Date: Fri, 19 Nov 2021 23:32:11 +0100 Subject: [PATCH] feature(back): add ip and useragent in events --- back/flag-service/package.json | 1 + back/flag-service/src/flag/FlagController.ts | 10 +++++++--- back/flag-service/src/flag/FlagService.ts | 4 +++- .../src/flag/spec/FlagController.spec.ts | 6 +++--- .../flag/spec/FlagService.spec-integration.ts | 14 +++++++------- .../database/object/event/DatabaseEvent.ts | 2 ++ back/yarn.lock | 19 +++++++++++++++++++ 7 files changed, 42 insertions(+), 14 deletions(-) diff --git a/back/flag-service/package.json b/back/flag-service/package.json index a3604f5..6aeecb2 100644 --- a/back/flag-service/package.json +++ b/back/flag-service/package.json @@ -38,6 +38,7 @@ "jsonwebtoken": "^8.5.1", "library": "^0.0.1", "mongodb": "^3.6.10", + "nestjs-real-ip": "^2.0.0", "reflect-metadata": "^0.1.13", "rimraf": "^3.0.2", "rxjs": "^7.2.0", diff --git a/back/flag-service/src/flag/FlagController.ts b/back/flag-service/src/flag/FlagController.ts index 5f2ebb8..52d0300 100644 --- a/back/flag-service/src/flag/FlagController.ts +++ b/back/flag-service/src/flag/FlagController.ts @@ -5,8 +5,10 @@ import { InternalServerErrorException, Param, Post, - Put, + Put, Req, } from '@nestjs/common'; +import { Request } from 'express'; +import { RealIP } from 'nestjs-real-ip'; import { Public } from '../user/decorators/Public'; import { UserId } from '../user/decorators/UserId'; import { ChangePixelColorDto } from './dto/ChangePixelColorDto'; @@ -30,9 +32,11 @@ export class FlagController { @Put('pixel') async changePixelColor( @UserId() currentUserId: string, - @Body() changeColorDTO: ChangePixelColorDto + @Body() changeColorDTO: ChangePixelColorDto, + @RealIP() ip: string, + @Req() request: Request, ) { - const event = await this.flagService.changePixelColor(currentUserId, changeColorDTO.pixelId, changeColorDTO.hexColor); + const event = await this.flagService.changePixelColor(currentUserId, changeColorDTO.pixelId, changeColorDTO.hexColor, ip, request.header('user-agent')); return event; } diff --git a/back/flag-service/src/flag/FlagService.ts b/back/flag-service/src/flag/FlagService.ts index d7d13e2..cc7c679 100644 --- a/back/flag-service/src/flag/FlagService.ts +++ b/back/flag-service/src/flag/FlagService.ts @@ -34,7 +34,7 @@ export class FlagService { return createdEvent; } - async changePixelColor(performingUserId: string, pixelId: string, hexColor: string) { + async changePixelColor(performingUserId: string, pixelId: string, hexColor: string, ip: string, useragent: string) { const lastUserAction = await this.pixelRepository.findLastByDate({ author: performingUserId, }); @@ -53,6 +53,8 @@ export class FlagService { author: performingUserId, entityId: lastPixelEvent.entityId, data: { ...lastPixelEvent.data, hexColor }, + ip, + useragent, }); this.flagSnapshotService.createSnapshotIfEventIdMeetThreshold(createdEvent.eventId); return createdEvent; diff --git a/back/flag-service/src/flag/spec/FlagController.spec.ts b/back/flag-service/src/flag/spec/FlagController.spec.ts index 5d9b8f1..2bcd76b 100644 --- a/back/flag-service/src/flag/spec/FlagController.spec.ts +++ b/back/flag-service/src/flag/spec/FlagController.spec.ts @@ -67,7 +67,7 @@ describe('FlagController', () => { changePixelColorSpy = jest .spyOn(flagService, 'changePixelColor') .mockReturnValue({ modified: true } as any); - res = await flagController.changePixelColor('ownerId', data); + res = await flagController.changePixelColor('ownerId', data, 'myip', {} as any); }); it('call changePixelColor from service', () => { expect(changePixelColorSpy).toBeCalledTimes(1); @@ -90,7 +90,7 @@ describe('FlagController', () => { .mockImplementation(() => { throw new UserActionIsOnCooldownError(1000); }); - res = flagController.changePixelColor('ownerId', data); + res = flagController.changePixelColor('ownerId', data, 'myip', {} as any); }); it('call changePixelColor from service', () => { expect(changePixelColorSpy).toBeCalledTimes(1); @@ -112,7 +112,7 @@ describe('FlagController', () => { .mockImplementation(() => { throw new UserHasNoPixelError(); }); - res = flagController.changePixelColor('ownerId', data); + res = flagController.changePixelColor('ownerId', data, 'myip', { } as any); }); it('call changePixelColor from service', () => { expect(changePixelColorSpy).toBeCalledTimes(1); diff --git a/back/flag-service/src/flag/spec/FlagService.spec-integration.ts b/back/flag-service/src/flag/spec/FlagService.spec-integration.ts index aa39823..adfbaa0 100644 --- a/back/flag-service/src/flag/spec/FlagService.spec-integration.ts +++ b/back/flag-service/src/flag/spec/FlagService.spec-integration.ts @@ -245,7 +245,7 @@ describe('FlagService', () => { 'anotherUserId', '#DDDDDD', ); - await flagService.changePixelColor('currentUserId', otherPixel.entityId, '#FFFFFF'); + await flagService.changePixelColor('currentUserId', otherPixel.entityId, '#FFFFFF', 'myip', 'myuseragent'); const pixel = await flagService.getOrCreateUserPixel('currentUserId'); expect(pixel.author).toEqual('currentUserId'); expect(pixel.entityId).toEqual(myPixel.entityId); @@ -316,7 +316,7 @@ describe('FlagService', () => { await flagService.addPixel('ownerid', '#FFFFFF'); await new Promise((r) => setTimeout(r, 1)); - await flagService.changePixelColor('userid', addedPixelEvent.entityId, '#FFFFFF'); + await flagService.changePixelColor('userid', addedPixelEvent.entityId, '#FFFFFF', 'myip', 'myuseragent'); const events = await dbClientService .getDb() .collection(pixelRepository.getCollectionName()) @@ -338,7 +338,7 @@ describe('FlagService', () => { await flagService.addPixel('ownerid', '#DDDDDD'); await expect( - flagService.changePixelColor('fakeuserid','fakeId', '#FFFFFF'), + flagService.changePixelColor('fakeuserid','fakeId', '#FFFFFF', 'myip', 'myuseragent'), ).rejects.toThrow(PixelDoesNotExistError); }); it('throw error when changing color before cooldown duration ends', async () => { @@ -346,10 +346,10 @@ describe('FlagService', () => { const addedPixel = await flagService.addPixel('ownerid', '#DDDDDD'); await new Promise((r) => setTimeout(r, 1)); - await flagService.changePixelColor('userid', addedPixel.entityId,'#FFFFFF'); + await flagService.changePixelColor('userid', addedPixel.entityId,'#FFFFFF', 'myip', 'myuseragent'); await expect( - flagService.changePixelColor('userid', addedPixel.entityId,'#FFFFFF'), + flagService.changePixelColor('userid', addedPixel.entityId,'#FFFFFF', 'myip', 'myuseragent'), ).rejects.toThrow(UserActionIsOnCooldownError); }); }); @@ -366,7 +366,7 @@ describe('FlagService', () => { '#FFFFFF', ); await new Promise((r) => setTimeout(r, 1)); - await flagService.changePixelColor('fourthuser', addedPixel.entityId, '#000000'); + await flagService.changePixelColor('fourthuser', addedPixel.entityId, '#000000', 'myip', 'myuseragent'); const flag = await flagService.getFlag(); expect(flag.length).toEqual(3); @@ -390,7 +390,7 @@ describe('FlagService', () => { '#FFFFFF', ); await new Promise((r) => setTimeout(r, 1)); - await flagService.changePixelColor('fourthuser', addedPixel.entityId, '#000000'); + await flagService.changePixelColor('fourthuser', addedPixel.entityId, '#000000', 'myip', 'myuseragent'); const flag = await flagService.getFlag(); expect(flag.length).toEqual(3); diff --git a/back/library/database/object/event/DatabaseEvent.ts b/back/library/database/object/event/DatabaseEvent.ts index 2a414ae..7ff978f 100644 --- a/back/library/database/object/event/DatabaseEvent.ts +++ b/back/library/database/object/event/DatabaseEvent.ts @@ -7,4 +7,6 @@ export class DatabaseEvent extends DatabaseObject { entityId: string; eventId?: number; ignored?: boolean; + ip?: string; + useragent?: string; } diff --git a/back/yarn.lock b/back/yarn.lock index 9065a99..1ee48b9 100644 --- a/back/yarn.lock +++ b/back/yarn.lock @@ -3088,6 +3088,11 @@ is-unicode-supported@^0.1.0: resolved "https://registry.yarnpkg.com/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz#3f26c76a809593b52bfa2ecb5710ed2779b522a7" integrity sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw== +is_js@^0.9.0: + version "0.9.0" + resolved "https://registry.yarnpkg.com/is_js/-/is_js-0.9.0.tgz#0ab94540502ba7afa24c856aa985561669e9c52d" + integrity sha1-CrlFQFArp6+iTIVqqYVWFmnpxS0= + isarray@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf" @@ -4050,6 +4055,13 @@ neo-async@^2.6.2: resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f" integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw== +nestjs-real-ip@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/nestjs-real-ip/-/nestjs-real-ip-2.0.0.tgz#6e54203e7af629a045c7d8dd01df5ac67b2cdfd8" + integrity sha512-UeVauTCkxUB6Wcmk4bCiDHRzpvG+LPCWmXDhSUvcPrMzUvZAZ+KGWrp9iy3YP9vcGnY0+69K9o2AmHLmfSd1fA== + dependencies: + request-ip "^2.1.3" + node-addon-api@^3.0.2: version "3.2.1" resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-3.2.1.tgz#81325e0a2117789c0128dab65e7e38f07ceba161" @@ -4542,6 +4554,13 @@ regexpp@^3.1.0: resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-3.2.0.tgz#0425a2768d8f23bad70ca4b90461fa2f1213e1b2" integrity sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg== +request-ip@^2.1.3: + version "2.1.3" + resolved "https://registry.yarnpkg.com/request-ip/-/request-ip-2.1.3.tgz#99ab2bafdeaf2002626e28083cb10597511d9e14" + integrity sha512-J3qdE/IhVM3BXkwMIVO4yFrvhJlU3H7JH16+6yHucadT4fePnR8dyh+vEs6FIx0S2x5TCt2ptiPfHcn0sqhbYQ== + dependencies: + is_js "^0.9.0" + require-directory@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42"