Browse Source

add auth protection, login and logout and fixed username update

master
nicolas-arnaud 2 years ago
parent
commit
6d7d526ec2
  1. 2
      back/volume/src/auth/auth.controller.ts
  2. 4
      back/volume/src/main.ts
  3. 18
      back/volume/src/users/users.controller.ts
  4. 11
      back/volume/src/users/users.service.ts
  5. 152
      front/volume/package-lock.json
  6. 1
      front/volume/package.json
  7. 142
      front/volume/src/App.svelte
  8. 37
      front/volume/src/Auth.ts
  9. 34
      front/volume/src/components/Friends.svelte
  10. 10
      front/volume/src/components/Profile.svelte

2
back/volume/src/auth/auth.controller.ts

@ -29,7 +29,7 @@ export class AuthController {
} }
@Get('out') @Get('out')
@Redirect('/') @Redirect('http://' + process.env.HOST + ':' + process.env.FRONT_PORT + '/')
logOut (@Req() req: Request) { logOut (@Req() req: Request) {
req.logOut(function (err) { req.logOut(function (err) {
if (err) return err if (err) return err

4
back/volume/src/main.ts

@ -33,7 +33,7 @@ async function bootstrap () {
app.use(passport.session()) app.use(passport.session())
app.enableCors(cors) app.enableCors(cors)
app.useWebSocketAdapter(new WsAdapter(app)) app.useWebSocketAdapter(new WsAdapter(app))
await app.listen(port) await app.listen(port)
logger.log(`Application listening on port ${port}`) logger.log(`Application listening on port ${port}`)
} }
bootstrap() bootstrap()

18
back/volume/src/users/users.controller.ts

@ -92,6 +92,22 @@ export class UsersController {
return await this.getAvatarById(profile.id, response); return await this.getAvatarById(profile.id, response);
} }
@Get('user/:name')
async getUserByName(
@Param('name') username: string
): Promise<User | null> {
return await this.usersService.findUserByName(username);
}
@Post('invit/:id')
@UseGuards(AuthenticatedGuard)
async invitUser (
@FtUser() profile: Profile,
@Param('id', ParseIntPipe) id: number
) {
return await this.usersService.invit(profile.id, id)
}
@Get('avatar/:id') @Get('avatar/:id')
async getAvatarById ( async getAvatarById (
@Param('id', ParseIntPipe) ftId: number, @Param('id', ParseIntPipe) ftId: number,
@ -124,7 +140,7 @@ export class UsersController {
async create (@Body() payload: UserDto, @FtUser() profile: Profile) { async create (@Body() payload: UserDto, @FtUser() profile: Profile) {
const user = await this.usersService.findUser(profile.id) const user = await this.usersService.findUser(profile.id)
if (user) { if (user) {
return await this.usersService.update(user.id, payload) return await this.usersService.update(user, payload)
} else { } else {
return await this.usersService.create(payload) return await this.usersService.create(payload)
} }

11
back/volume/src/users/users.service.ts

@ -44,11 +44,9 @@ export class UsersService {
.getMany() .getMany()
} }
async update (ftId: number, changes: UserDto):Promise < User | null> { async update (user: User, changes: UserDto):Promise < User | null> {
const updatedUser = await this.findUser(ftId) this.usersRepository.merge(user, changes)
if (!updatedUser) return null return await this.usersRepository.save(user)
this.usersRepository.merge(updatedUser, changes)
return await this.usersRepository.save(updatedUser)
} }
async addAvatar (ftId: number, filename: string) { async addAvatar (ftId: number, filename: string) {
@ -87,8 +85,7 @@ export class UsersService {
return new NotFoundException( return new NotFoundException(
`Error: user id ${targetFtId} isn't in our db.` `Error: user id ${targetFtId} isn't in our db.`
) )
} } const id = user.followers.findIndex(
const id = user.followers.findIndex(
(follower) => follower.ftId === targetFtId (follower) => follower.ftId === targetFtId
) )
if (id != -1) { if (id != -1) {

152
front/volume/package-lock.json

@ -10,6 +10,7 @@
"dependencies": { "dependencies": {
"@sveltejs/vite-plugin-svelte": "^2.0.2", "@sveltejs/vite-plugin-svelte": "^2.0.2",
"@tsconfig/svelte": "^3.0.0", "@tsconfig/svelte": "^3.0.0",
"axios": "^1.3.4",
"svelte": "^3.55.1", "svelte": "^3.55.1",
"vite": "^4.1.0" "vite": "^4.1.0"
}, },
@ -469,6 +470,21 @@
"node": ">= 8" "node": ">= 8"
} }
}, },
"node_modules/asynckit": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
"integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="
},
"node_modules/axios": {
"version": "1.3.4",
"resolved": "https://registry.npmjs.org/axios/-/axios-1.3.4.tgz",
"integrity": "sha512-toYm+Bsyl6VC5wSkfkbbNB6ROv7KY93PEBBL6xyDczaIHasAiv4wPqQ/c4RjoQzipxRD2W5g21cOqQulZ7rHwQ==",
"dependencies": {
"follow-redirects": "^1.15.0",
"form-data": "^4.0.0",
"proxy-from-env": "^1.1.0"
}
},
"node_modules/balanced-match": { "node_modules/balanced-match": {
"version": "1.0.2", "version": "1.0.2",
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
@ -551,6 +567,17 @@
"fsevents": "~2.3.2" "fsevents": "~2.3.2"
} }
}, },
"node_modules/combined-stream": {
"version": "1.0.8",
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
"integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
"dependencies": {
"delayed-stream": "~1.0.0"
},
"engines": {
"node": ">= 0.8"
}
},
"node_modules/concat-map": { "node_modules/concat-map": {
"version": "0.0.1", "version": "0.0.1",
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
@ -581,6 +608,14 @@
"node": ">=0.10.0" "node": ">=0.10.0"
} }
}, },
"node_modules/delayed-stream": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
"integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
"engines": {
"node": ">=0.4.0"
}
},
"node_modules/detect-indent": { "node_modules/detect-indent": {
"version": "6.1.0", "version": "6.1.0",
"resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-6.1.0.tgz", "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-6.1.0.tgz",
@ -669,6 +704,38 @@
"node": ">=8" "node": ">=8"
} }
}, },
"node_modules/follow-redirects": {
"version": "1.15.2",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz",
"integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==",
"funding": [
{
"type": "individual",
"url": "https://github.com/sponsors/RubenVerborgh"
}
],
"engines": {
"node": ">=4.0"
},
"peerDependenciesMeta": {
"debug": {
"optional": true
}
}
},
"node_modules/form-data": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz",
"integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==",
"dependencies": {
"asynckit": "^0.4.0",
"combined-stream": "^1.0.8",
"mime-types": "^2.1.12"
},
"engines": {
"node": ">= 6"
}
},
"node_modules/fs.realpath": { "node_modules/fs.realpath": {
"version": "1.0.0", "version": "1.0.0",
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
@ -868,6 +935,25 @@
"node": ">=8.6" "node": ">=8.6"
} }
}, },
"node_modules/mime-db": {
"version": "1.52.0",
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
"integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
"engines": {
"node": ">= 0.6"
}
},
"node_modules/mime-types": {
"version": "2.1.35",
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
"integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
"dependencies": {
"mime-db": "1.52.0"
},
"engines": {
"node": ">= 0.6"
}
},
"node_modules/min-indent": { "node_modules/min-indent": {
"version": "1.0.1", "version": "1.0.1",
"resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz",
@ -1044,6 +1130,11 @@
"svelte": "^3.2.0" "svelte": "^3.2.0"
} }
}, },
"node_modules/proxy-from-env": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
"integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg=="
},
"node_modules/queue-microtask": { "node_modules/queue-microtask": {
"version": "1.2.3", "version": "1.2.3",
"resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
@ -1682,6 +1773,21 @@
"picomatch": "^2.0.4" "picomatch": "^2.0.4"
} }
}, },
"asynckit": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
"integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="
},
"axios": {
"version": "1.3.4",
"resolved": "https://registry.npmjs.org/axios/-/axios-1.3.4.tgz",
"integrity": "sha512-toYm+Bsyl6VC5wSkfkbbNB6ROv7KY93PEBBL6xyDczaIHasAiv4wPqQ/c4RjoQzipxRD2W5g21cOqQulZ7rHwQ==",
"requires": {
"follow-redirects": "^1.15.0",
"form-data": "^4.0.0",
"proxy-from-env": "^1.1.0"
}
},
"balanced-match": { "balanced-match": {
"version": "1.0.2", "version": "1.0.2",
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
@ -1741,6 +1847,14 @@
"readdirp": "~3.6.0" "readdirp": "~3.6.0"
} }
}, },
"combined-stream": {
"version": "1.0.8",
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
"integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
"requires": {
"delayed-stream": "~1.0.0"
}
},
"concat-map": { "concat-map": {
"version": "0.0.1", "version": "0.0.1",
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
@ -1760,6 +1874,11 @@
"resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.0.tgz", "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.0.tgz",
"integrity": "sha512-z2wJZXrmeHdvYJp/Ux55wIjqo81G5Bp4c+oELTW+7ar6SogWHajt5a9gO3s3IDaGSAXjDk0vlQKN3rms8ab3og==" "integrity": "sha512-z2wJZXrmeHdvYJp/Ux55wIjqo81G5Bp4c+oELTW+7ar6SogWHajt5a9gO3s3IDaGSAXjDk0vlQKN3rms8ab3og=="
}, },
"delayed-stream": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
"integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ=="
},
"detect-indent": { "detect-indent": {
"version": "6.1.0", "version": "6.1.0",
"resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-6.1.0.tgz", "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-6.1.0.tgz",
@ -1832,6 +1951,21 @@
"to-regex-range": "^5.0.1" "to-regex-range": "^5.0.1"
} }
}, },
"follow-redirects": {
"version": "1.15.2",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz",
"integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA=="
},
"form-data": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz",
"integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==",
"requires": {
"asynckit": "^0.4.0",
"combined-stream": "^1.0.8",
"mime-types": "^2.1.12"
}
},
"fs.realpath": { "fs.realpath": {
"version": "1.0.0", "version": "1.0.0",
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
@ -1979,6 +2113,19 @@
"picomatch": "^2.3.1" "picomatch": "^2.3.1"
} }
}, },
"mime-db": {
"version": "1.52.0",
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
"integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg=="
},
"mime-types": {
"version": "2.1.35",
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
"integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
"requires": {
"mime-db": "1.52.0"
}
},
"min-indent": { "min-indent": {
"version": "1.0.1", "version": "1.0.1",
"resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz",
@ -2094,6 +2241,11 @@
"dev": true, "dev": true,
"requires": {} "requires": {}
}, },
"proxy-from-env": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
"integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg=="
},
"queue-microtask": { "queue-microtask": {
"version": "1.2.3", "version": "1.2.3",
"resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",

1
front/volume/package.json

@ -20,6 +20,7 @@
"dependencies": { "dependencies": {
"@sveltejs/vite-plugin-svelte": "^2.0.2", "@sveltejs/vite-plugin-svelte": "^2.0.2",
"@tsconfig/svelte": "^3.0.0", "@tsconfig/svelte": "^3.0.0",
"axios": "^1.3.4",
"svelte": "^3.55.1", "svelte": "^3.55.1",
"vite": "^4.1.0" "vite": "^4.1.0"
} }

142
front/volume/src/App.svelte

@ -1,4 +1,5 @@
<script lang="ts"> <script lang="ts">
import { onMount } from 'svelte'
import Navbar from "./components/NavBar.svelte"; import Navbar from "./components/NavBar.svelte";
import Profile from "./components/Profile.svelte"; import Profile from "./components/Profile.svelte";
import MatchHistory from "./components/MatchHistory.svelte"; import MatchHistory from "./components/MatchHistory.svelte";
@ -14,8 +15,15 @@
import Channels from "./components/Channels.svelte"; import Channels from "./components/Channels.svelte";
import type { ChannelsType } from "./components/Channels.svelte"; import type { ChannelsType } from "./components/Channels.svelte";
import { store, getUser, login, logout } from "./Auth";
// PROFILE // PROFILE
onMount(() => {
getUser()
})
let isProfileOpen = false; let isProfileOpen = false;
function clickProfile() { function clickProfile() {
isProfileOpen = true; isProfileOpen = true;
@ -82,69 +90,79 @@
</script> </script>
<main> <main>
<Navbar <div>
{clickProfile} {#if $store === null}
{clickHistory} <h1><button type="button" on:click={login}>Log In</button></h1>
{clickFriends} {:else}
{clickSpectate} <h1><button type="button" on:click={logout}>Log Out</button></h1>
{clickChannels} <Navbar
/> {clickProfile}
{#if isChannelsOpen} {clickHistory}
{#if selectedChannel} {clickFriends}
<div on:click={() => (selectedChannel = undefined)} on:keydown={() => (selectedChannel = undefined)}> {clickSpectate}
<Chat2 chatMessages={selectedChannel.messages} /> {clickChannels}
</div> />
{/if} {#if isChannelsOpen}
{#if !selectedChannel} {#if selectedChannel}
<div <div
on:click={() => (isChannelsOpen = false)} on:click={() => (selectedChannel = undefined)}
on:keydown={() => (isChannelsOpen = false)} on:keydown={() => (selectedChannel = undefined)}
> >
<Channels channels={channels} onSelectChannel={handleSelectChannel} /> <Chat2 chatMessages={selectedChannel.messages} />
</div> </div>
{/if}
{#if !selectedChannel}
<div
on:click={() => (isChannelsOpen = false)}
on:keydown={() => (isChannelsOpen = false)}
>
<Channels {channels} onSelectChannel={handleSelectChannel} />
</div>
{/if}
{/if}
{#if isSpectateOpen}
<div
on:click={() => (isSpectateOpen = false)}
on:keydown={() => (isSpectateOpen = false)}
>
<Spectate {spectate} />
</div>
{/if}
{#if isFriendOpen}
<div
on:click={() => (isFriendOpen = false)}
on:keydown={() => (isFriendOpen = false)}
>
<Friends {friends} />
</div>
{/if}
{#if isHistoryOpen}
<div
on:click={() => (isHistoryOpen = false)}
on:keydown={() => (isHistoryOpen = false)}
>
<MatchHistory {matches} />
</div>
{/if}
{#if isProfileOpen}
<div
on:click={() => (isProfileOpen = false)}
on:keydown={() => (isProfileOpen = false)}
>
<Profile
username="Alice"
wins={10}
losses={5}
elo={256}
rank={23}
is2faEnabled={false}
/>
</div>
{/if}
<Play />
<Pong />
{/if} {/if}
{/if} </div>
{#if isSpectateOpen}
<div
on:click={() => (isSpectateOpen = false)}
on:keydown={() => (isSpectateOpen = false)}
>
<Spectate {spectate} />
</div>
{/if}
{#if isFriendOpen}
<div
on:click={() => (isFriendOpen = false)}
on:keydown={() => (isFriendOpen = false)}
>
<Friends {friends} />
</div>
{/if}
{#if isHistoryOpen}
<div
on:click={() => (isHistoryOpen = false)}
on:keydown={() => (isHistoryOpen = false)}
>
<MatchHistory {matches} />
</div>
{/if}
{#if isProfileOpen}
<div
on:click={() => (isProfileOpen = false)}
on:keydown={() => (isProfileOpen = false)}
>
<Profile
username="Alice"
wins={10}
losses={5}
elo={256}
rank={23}
is2faEnabled={false}
/>
</div>
{/if}
<Play />
<Pong />
</main> </main>
<style> <style>

37
front/volume/src/Auth.ts

@ -0,0 +1,37 @@
import { writable } from 'svelte/store';
let _user = localStorage.getItem('user');
export const store = writable(_user ? JSON.parse(_user) : null);
store.subscribe((value) => {
if (value) localStorage.setItem('user', JSON.stringify(value));
else localStorage.removeItem('user');
});
export const API_URL =
"http://" + import.meta.env.VITE_HOST +
":" + import.meta.env.VITE_BACK_PORT;
export async function getUser() {
const res = await fetch(API_URL, {
method: "get",
mode: 'cors',
cache: "no-cache",
credentials: 'include',
redirect: "follow",
referrerPolicy: "no-referrer",
})
let user = await res.json()
if (user.username) {
console.log(user)
store.set(user)
}
}
export function login() {
window.location.replace(API_URL + "/log/in")
}
export function logout() {
window.location.replace(API_URL + "/log/out")
store.set(null)
}

34
front/volume/src/components/Friends.svelte

@ -6,7 +6,9 @@
</script> </script>
<script lang="ts"> <script lang="ts">
export let friends: Array<Friend> = []; let api = "http://" + import.meta.env.VITE_HOST + ":" + import.meta.env.VITE_BACK_PORT
export let friends: Array<Friend>
fetch(api + "/friends").then((response) => response.json()).then((ret) => {friends = ret});
async function addFriend(event: any) { async function addFriend(event: any) {
console.log(typeof event); console.log(typeof event);
@ -15,19 +17,23 @@
console.log(usernameInput); console.log(usernameInput);
const username = usernameInput.value; const username = usernameInput.value;
// const response = await fetch('', { let ftId: number
// method: 'POST', fetch(api + "/user/" + username).then((response) => response.json()).then((ret) => {ftId = ret.ftID});
// headers: {
// 'Content-Type': 'application/json' fetch(api + "/friends").then((response) => response.json()).then((ret) => {friends = JSON.parse(ret)});
// }, const response = await fetch(api + "/invit/" + ftId, {
// body: JSON.stringify({ username }) method: 'POST',
// }); headers: {
// if (response.ok) { 'Content-Type': 'application/json'
// console.log('Friend added successfully'); },
// } else { body: JSON.stringify({ username })
// console.log('Failed to add friend'); });
// } if (response.ok) {
// usernameInput.value = ''; console.log('Invitation send.');
} else {
console.log('Unknown user.');
}
usernameInput.value = '';
alert("Trying to add friend" + username); alert("Trying to add friend" + username);
} }
</script> </script>

10
front/volume/src/components/Profile.svelte

@ -5,7 +5,11 @@
</script> </script>
<script lang="ts"> <script lang="ts">
let api = "http://" + import.meta.env.VITE_HOST + ":" + import.meta.env.VITE_BACK_PORT
export const API_URL = "http://" + import.meta.env.VITE_HOST + ":" + import.meta.env.VITE_BACK_PORT
export const AUTH_SERVER_URL = API_URL + "/log/in"
export let avatar = API_URL + "/avatar"
export let username = ""; export let username = "";
export let realname = ""; export let realname = "";
export let wins = 0; export let wins = 0;
@ -13,10 +17,10 @@
export let elo = 0; export let elo = 0;
export let rank = -1; export let rank = -1;
export let is2faEnabled = false; export let is2faEnabled = false;
export let avatar = api + "/avatar";
const handleSubmit = () => { const handleSubmit = () => {
const user: User = { username : username}; const user: User = { username : username};
fetch("http://localhost:3001/", { fetch("http://localhost:3001/", {
headers: {"content-type": "application/json"},
method: "POST", method: "POST",
body: JSON.stringify(user), body: JSON.stringify(user),
credentials: 'include' credentials: 'include'
@ -40,7 +44,7 @@
<div class="profile-header"> <div class="profile-header">
<img class="profile-img" src={avatar} alt="avatar" /> <img class="profile-img" src={avatar} alt="avatar" />
<h3>{realname}</h3> <h3>{realname}</h3>
<form action="http://localhost:3001/avatar" <form action={avatar}
method="post" method="post"
enctype="multipart/form-data"> enctype="multipart/form-data">
<label for="mavatar-input">Select a file:</label> <label for="mavatar-input">Select a file:</label>

Loading…
Cancel
Save