From 0470676c5d97ad2b7a8d1433376e1a5c0f4b14be Mon Sep 17 00:00:00 2001 From: Me Date: Thu, 5 Jan 2023 22:37:56 +0100 Subject: [PATCH 1/2] added the thing so you can see other people's avatars, fixed checks on frontend routes like game and such that other people created, need help understanding ValidationPipe() to make it so a user must have a unique username. TBH this shit is still being held together by Duct Tape and Holy Water --- .../api_back/src/users/users.controller.ts | 19 +++++-- .../api_back/src/users/users.service.ts | 47 +++++----------- .../api_front/src/pieces/DisplayAUser.svelte | 2 +- .../src/pieces/GenerateUserDisplay.svelte | 25 ++++++++- .../api_front/src/routes/primaryRoutes.js | 55 +++++++++++++++++-- 5 files changed, 102 insertions(+), 46 deletions(-) diff --git a/srcs/requirements/nestjs/api_back/src/users/users.controller.ts b/srcs/requirements/nestjs/api_back/src/users/users.controller.ts index 2b350667..d6811642 100644 --- a/srcs/requirements/nestjs/api_back/src/users/users.controller.ts +++ b/srcs/requirements/nestjs/api_back/src/users/users.controller.ts @@ -84,6 +84,7 @@ export class UsersController { @UseGuards(TwoFactorGuard) @Patch() async update(@Req() req, @Body(new ValidationPipe()) usersUpdateDto: UpdateUsersDto, @Res() response : Response) { + console.log('user.controller updating user info') const user = await this.usersService.update(req.user.id, usersUpdateDto); if (user.isEnabledTwoFactorAuth === false && user.isTwoFactorAuthenticated === true) this.usersService.setIsTwoFactorAuthenticatedWhenLogout(user.id); @@ -103,6 +104,7 @@ export class UsersController { return this.usersService.remove(req.user.id); } + // POST http://transcendance:8080/user/avatar @UseGuards(AuthenticateGuard) @UseGuards(TwoFactorGuard) @@ -118,15 +120,24 @@ export class UsersController { return res.status(HttpStatus.UNSUPPORTED_MEDIA_TYPE).json({message : "Unsupported media type. Please use a valid image file."}); } - // GET http://transcendance:8080/user/avatar + + // GET http://transcendance:8080/user/avatar?username=username @UseGuards(AuthenticateGuard) @UseGuards(TwoFactorGuard) @Get('avatar') - getAvatar(@Req() request, @Res() response) { - const promise = this.usersService.getAvatarUrl(request.user.id).then((url) => + async getAvatar(@Query('username') username: string, @Req() request, @Res() response) { + let usernameToFind; + if (username !== undefined) { + usernameToFind = username; + } else { + usernameToFind = request.user.username; + } + const promise = this.usersService.getAvatarUrl(usernameToFind).then((url) => { - if (url) + if (url) { + console.log('what is the URL: ' + url) return of(response.sendFile(process.cwd() + '/uploads/avatars/' + url)); + } else throw new NotFoundException('Avatar not found'); }); diff --git a/srcs/requirements/nestjs/api_back/src/users/users.service.ts b/srcs/requirements/nestjs/api_back/src/users/users.service.ts index 0251f2e0..fbb6156a 100644 --- a/srcs/requirements/nestjs/api_back/src/users/users.service.ts +++ b/srcs/requirements/nestjs/api_back/src/users/users.service.ts @@ -68,13 +68,13 @@ export class UsersService { let partialUsers : Partial[] = []; for (const otherUser of otherUsers) { - console.log('other user: ') - console.log({...otherUser}) - let tmp = await this.friendshipService.findIfUserIsBlockedOrHasBlocked(currentUser.id, otherUser.id); - console.log('user.services findIF Blocked... : ') - console.log(tmp) - if (tmp === false) { - // if (await this.friendshipService.findIfUserIsBlockedOrHasBlocked(currentUser.id, otherUser.id) === false) { + // console.log('other user: ') + // console.log({...otherUser}) + // let tmp = await this.friendshipService.findIfUserIsBlockedOrHasBlocked(currentUser.id, otherUser.id); + // console.log('user.services findIF Blocked... : ') + // console.log(tmp) + // if (tmp === false) { + if (await this.friendshipService.findIfUserIsBlockedOrHasBlocked(currentUser.id, otherUser.id) === false) { partialUsers.push({username: otherUser.username, image_url: otherUser.image_url, status: otherUser.status, stats: otherUser.stats}); } } @@ -83,30 +83,6 @@ export class UsersService { return partialUsers; } - // async findAbsolutelyAll() { - // // const otherUsers = await this.userRepository.find({where: {id: Not(+currentUser.id)}, order: {username: "ASC"}, skip: offset, take: limit,}); - // const otherUsers = await this.userRepository.find({order: {username: "ASC"}}); - - // let partialUsers : Partial[] = []; - - // for (const otherUser of otherUsers) { - // console.log('other user: ') - // console.log({...otherUser}) - // let tmp = await this.friendshipService.findIfUserIsBlockedOrHasBlocked(currentUser.id, otherUser.id); - // console.log('user.services findIF Blocked... : ') - // console.log(tmp) - // if (tmp === false) { - // // if (await this.friendshipService.findIfUserIsBlockedOrHasBlocked(currentUser.id, otherUser.id) === false) { - // partialUsers.push({username: otherUser.username, image_url: otherUser.image_url, status: otherUser.status, stats: otherUser.stats}); - // } - // } - // console.log('user.services findAll, partialUsers:') - // console.log({...partialUsers}) - // return partialUsers; - // } - - - async create(createUserDto: CreateUsersDto) { if (await this.userRepository.findOneBy({fortyTwoId: createUserDto.fortyTwoId})) throw new HttpException(`The user already exists.`,HttpStatus.CONFLICT); @@ -158,13 +134,16 @@ export class UsersService { return this.userRepository.update(id, {image_url: avatar}); } - async getAvatarUrl(id: number) { - const user = await this.userRepository.findOneBy({id: id}); + // doing search with username not id because userService.findOne doesn't return an Id anymore, just username... fuck this architecture is big trash... + // async getAvatarUrl(id: number) { + async getAvatarUrl(username: string) { + const user = await this.userRepository.findOneBy({username: username}); if (!user) throw new HttpException(`The user could not be found.`,HttpStatus.NOT_FOUND); + // console.log('user.service getAvatarUrl of ' + user.username) if (!user.image_url) throw new HttpException(`The user has no avatar.`,HttpStatus.NOT_FOUND); - console.log(user.image_url); + // console.log('User.service Avatar URL ' + user.image_url); return user.image_url; } diff --git a/srcs/requirements/svelte/api_front/src/pieces/DisplayAUser.svelte b/srcs/requirements/svelte/api_front/src/pieces/DisplayAUser.svelte index 75e1f1f6..65a9da14 100644 --- a/srcs/requirements/svelte/api_front/src/pieces/DisplayAUser.svelte +++ b/srcs/requirements/svelte/api_front/src/pieces/DisplayAUser.svelte @@ -39,7 +39,7 @@ {#if user !== undefined} - + {:else}

Sorry

diff --git a/srcs/requirements/svelte/api_front/src/pieces/GenerateUserDisplay.svelte b/srcs/requirements/svelte/api_front/src/pieces/GenerateUserDisplay.svelte index b0804a96..b235f64a 100644 --- a/srcs/requirements/svelte/api_front/src/pieces/GenerateUserDisplay.svelte +++ b/srcs/requirements/svelte/api_front/src/pieces/GenerateUserDisplay.svelte @@ -4,20 +4,39 @@ export let user; - export let primary; + export let primary; // kinda useless, not sure what i was going for... Might be userful after all let rank = ''; let avatar; - + // avatar needs to be updated!!! + console.log('Generate User Display, BEFORE on mount ' + avatar) onMount( async() => { + console.log('Generate User Display, on mount ' + user.username) // using this for now cuz for some reason there is yet to be a way to fet another person's avatar if (primary) { + // await fetch(`http://${process.env.WEBSITE_HOST}:${process.env.WEBSITE_PORT}/api/v2/user/avatar?username=${user.username}`, {method: "GET"}) + // .then(response => {return response.blob()}) + // .then(data => { + // const url = URL.createObjectURL(data); + // avatar = url; + // }); await fetch(`http://${process.env.WEBSITE_HOST}:${process.env.WEBSITE_PORT}/api/v2/user/avatar`, {method: "GET"}) .then(response => {return response.blob()}) .then(data => { const url = URL.createObjectURL(data); avatar = url; - }); + }) + .catch(() => errors.avatar = 'Sorry your avatar could not be loaded' ); + console.log('avatar: ') + console.log(avatar) + } else { + await fetch(`http://${process.env.WEBSITE_HOST}:${process.env.WEBSITE_PORT}/api/v2/user/avatar?username=${user.username}`, {method: "GET"}) + .then(response => {return response.blob()}) + .then(data => { + const url = URL.createObjectURL(data); + avatar = url; + }) + .catch(() => errors.avatar = 'Sorry your avatar could not be loaded' ); } }) diff --git a/srcs/requirements/svelte/api_front/src/routes/primaryRoutes.js b/srcs/requirements/svelte/api_front/src/routes/primaryRoutes.js index ab3d29e6..1360f1a4 100644 --- a/srcs/requirements/svelte/api_front/src/routes/primaryRoutes.js +++ b/srcs/requirements/svelte/api_front/src/routes/primaryRoutes.js @@ -13,9 +13,57 @@ import GameSpectator from '../pages/game/GameSpectator.svelte'; export const primaryRoutes = { '/': SplashPage, '/2fa': TwoFactorAuthentication, - '/game': Game, - '/spectator': GameSpectator, - '/ranking' : Ranking, + '/game': wrap({ + component: Game, + conditions: [ + async(detail) => { + const user = await fetch('http://' + process.env.WEBSITE_HOST + ":" + process.env.WEBSITE_PORT + '/api/v2/user') + .then((resp) => resp.json()) + + console.log('in /profile what is in user') + console.log(user) + + if (user && user.username) + return true; + else + return false; + } + ] + }), + '/spectator': wrap({ + component: GameSpectator, + conditions: [ + async(detail) => { + const user = await fetch('http://' + process.env.WEBSITE_HOST + ":" + process.env.WEBSITE_PORT + '/api/v2/user') + .then((resp) => resp.json()) + + console.log('in /profile what is in user') + console.log(user) + + if (user && user.username) + return true; + else + return false; + } + ] + }), + '/ranking': wrap({ + component: Ranking, + conditions: [ + async(detail) => { + const user = await fetch('http://' + process.env.WEBSITE_HOST + ":" + process.env.WEBSITE_PORT + '/api/v2/user') + .then((resp) => resp.json()) + + console.log('in /profile what is in user') + console.log(user) + + if (user && user.username) + return true; + else + return false; + } + ] + }), '/profile': wrap({ component: ProfilePage, conditions: [ @@ -50,7 +98,6 @@ export const primaryRoutes = { } ] }), - '/unauthorized-access': UnauthorizedAccessPage, '*': NotFound }; From f7c728a0094adc2b567e58c9ac54701a530d31e8 Mon Sep 17 00:00:00 2001 From: Me Date: Sat, 7 Jan 2023 01:41:06 +0100 Subject: [PATCH 2/2] So i added a check to make it so you can't change your username to someone else's, also turns out Cherif already has a check so that if you change your username to someone else's 42 username who isn't a user yet and then they try to become a user, their username will have a random string attached to the end so it is also unique, then fixed a few minor things, and made it so all UnauthorizedPages take you back to / as in the SplashPage rather than a special page from which you navigate to /, that said, i think feedback for the user is kinda nice, will decide with team eventually --- .../api_back/src/users/users.controller.ts | 2 +- .../api_back/src/users/users.service.ts | 15 ++++++++---- .../svelte/api_front/src/App.svelte | 3 ++- .../src/pages/profile/ProfileSettings.svelte | 6 +++-- .../src/pieces/GenerateUserDisplay.svelte | 24 +++++++++++-------- 5 files changed, 31 insertions(+), 19 deletions(-) diff --git a/srcs/requirements/nestjs/api_back/src/users/users.controller.ts b/srcs/requirements/nestjs/api_back/src/users/users.controller.ts index d6811642..bdb9f20e 100644 --- a/srcs/requirements/nestjs/api_back/src/users/users.controller.ts +++ b/srcs/requirements/nestjs/api_back/src/users/users.controller.ts @@ -120,7 +120,7 @@ export class UsersController { return res.status(HttpStatus.UNSUPPORTED_MEDIA_TYPE).json({message : "Unsupported media type. Please use a valid image file."}); } - + // don't pass your own username // GET http://transcendance:8080/user/avatar?username=username @UseGuards(AuthenticateGuard) @UseGuards(TwoFactorGuard) diff --git a/srcs/requirements/nestjs/api_back/src/users/users.service.ts b/srcs/requirements/nestjs/api_back/src/users/users.service.ts index fbb6156a..e44cd2ad 100644 --- a/srcs/requirements/nestjs/api_back/src/users/users.service.ts +++ b/srcs/requirements/nestjs/api_back/src/users/users.service.ts @@ -50,12 +50,10 @@ export class UsersService { return partialUser; } - - /***** THIS IS THE THING I REALLY NEED TO FIX!!!!!!! *****/ - - // Ok this gets called in the Authenitcation Service, but like i was still able to make a username === someone else's async isUsernameExists(usernameToSearch: string): Promise { - const user = await this.userRepository.findOneBy({username : usernameToSearch}); + console.log('searching for username: ' + usernameToSearch) + const user = await this.userRepository.findOneBy({username : usernameToSearch}); + console.log({...user}) if (!user) return false; return true; @@ -84,6 +82,8 @@ export class UsersService { } async create(createUserDto: CreateUsersDto) { + // console.log('\nuser.services create a new user, createUserDto: ') + // console.log({...createUserDto}) if (await this.userRepository.findOneBy({fortyTwoId: createUserDto.fortyTwoId})) throw new HttpException(`The user already exists.`,HttpStatus.CONFLICT); const user = this.userRepository.create(createUserDto); @@ -95,6 +95,11 @@ export class UsersService { async update(id: number, updateUserDto: UpdateUsersDto) { // console.log(`Update user ${id} with ${updateUserDto.isEnabledTwoFactorAuth}`); + // console.log({...updateUserDto}) + if (await this.isUsernameExists(updateUserDto.username) === true) { + console.log('updating username ' + updateUserDto.username + ' but it already is in use') + throw new HttpException(`The username is already in use.`,HttpStatus.CONFLICT); + } const user = await this.userRepository.preload( {id: id, ...updateUserDto}); diff --git a/srcs/requirements/svelte/api_front/src/App.svelte b/srcs/requirements/svelte/api_front/src/App.svelte index b9b7c6c2..95e04345 100644 --- a/srcs/requirements/svelte/api_front/src/App.svelte +++ b/srcs/requirements/svelte/api_front/src/App.svelte @@ -9,7 +9,8 @@ console.error('conditionsFailed event', event.detail); // i mean i guess i can just leave this in there permanently? - replace('/unauthorized-access'); + // replace('/unauthorized-access'); + replace('/'); }; diff --git a/srcs/requirements/svelte/api_front/src/pages/profile/ProfileSettings.svelte b/srcs/requirements/svelte/api_front/src/pages/profile/ProfileSettings.svelte index 7a6dbd2f..35a71898 100644 --- a/srcs/requirements/svelte/api_front/src/pages/profile/ProfileSettings.svelte +++ b/srcs/requirements/svelte/api_front/src/pages/profile/ProfileSettings.svelte @@ -78,9 +78,11 @@ if (response.status === 200) success.username = "Your changes have been saved" else if (response.status === 201) - push("/2fa") + push("/2fa"); + else if (response.status === 409) + errors.username = `${set.username} is already in use, pick a different one.`; else - errors.username = "Something went wrong" + errors.username = "Something went wrong"; } ) .catch((err) => errors.username = err) diff --git a/srcs/requirements/svelte/api_front/src/pieces/GenerateUserDisplay.svelte b/srcs/requirements/svelte/api_front/src/pieces/GenerateUserDisplay.svelte index b235f64a..4c33e9f7 100644 --- a/srcs/requirements/svelte/api_front/src/pieces/GenerateUserDisplay.svelte +++ b/srcs/requirements/svelte/api_front/src/pieces/GenerateUserDisplay.svelte @@ -9,17 +9,12 @@ let avatar; // avatar needs to be updated!!! console.log('Generate User Display, BEFORE on mount ' + avatar) + // add errors + let errors = {avatar: ''}; onMount( async() => { - console.log('Generate User Display, on mount ' + user.username) - // using this for now cuz for some reason there is yet to be a way to fet another person's avatar + // console.log('Generate User Display, on mount ' + user.username) if (primary) { - // await fetch(`http://${process.env.WEBSITE_HOST}:${process.env.WEBSITE_PORT}/api/v2/user/avatar?username=${user.username}`, {method: "GET"}) - // .then(response => {return response.blob()}) - // .then(data => { - // const url = URL.createObjectURL(data); - // avatar = url; - // }); await fetch(`http://${process.env.WEBSITE_HOST}:${process.env.WEBSITE_PORT}/api/v2/user/avatar`, {method: "GET"}) .then(response => {return response.blob()}) .then(data => { @@ -27,8 +22,8 @@ avatar = url; }) .catch(() => errors.avatar = 'Sorry your avatar could not be loaded' ); - console.log('avatar: ') - console.log(avatar) + // console.log('avatar: ') + // console.log(avatar) } else { await fetch(`http://${process.env.WEBSITE_HOST}:${process.env.WEBSITE_PORT}/api/v2/user/avatar?username=${user.username}`, {method: "GET"}) .then(response => {return response.blob()}) @@ -40,6 +35,9 @@ } }) + + /**** THIS IS BASICALLY ALL THE RANK LOGIC ERIC HAS MADE ****/ + if (user.loseGame > user.winGame) { rank = 'Bitch Ass Loser!' } else if (user.loseGame === user.winGame) { @@ -86,6 +84,7 @@ default user icon +
{errors.avatar}
{user.username}
Rank: @@ -169,6 +168,11 @@ font-weight: bold; } + .error{ + font-size: 0.8em; + font-weight: bold; + color: red; + } /* Glittery Star Stuff */