From 7e49d2dc92e326c3e4c80668799952cee387a0ea Mon Sep 17 00:00:00 2001 From: not-nullptr Date: Mon, 18 Mar 2024 02:15:05 +0000 Subject: [PATCH] feat: new dropdown, friendship stuffz, passwords :3c Co-authored-by: Evan Song --- package-lock.json | 208 ++++++++++++++++-- package.json | 3 + src/app.html | 2 +- src/components/AccountButton.svelte | 78 +++++++ src/components/Dropdown.svelte | 101 +++++++++ src/components/Room.svelte | 19 +- src/hooks.server.ts | 4 - src/lib/client/api/index.ts | 12 +- src/lib/server/repo/index.ts | 3 +- src/lib/server/schema/index.ts | 21 +- src/lib/server/util/index.ts | 20 ++ src/routes/+layout.server.ts | 6 +- src/routes/+layout.svelte | 16 +- src/routes/+page.svelte | 4 +- src/routes/account/+layout.svelte | 35 ++- src/routes/account/+page.svelte | 7 + src/routes/account/lobbies/+page.svelte | 74 ------- .../{lobbies => lobby}/+page.server.ts | 0 src/routes/account/lobby/+page.svelte | 162 ++++++++++++++ src/routes/api/user/+server.ts | 37 +++- src/routes/api/user/login/+server.ts | 48 ++++ src/routes/coming-soon/+page.svelte | 2 +- src/routes/login/+page.server.ts | 12 + src/routes/login/+page.svelte | 73 ++++++ src/routes/signup/+page.server.ts | 2 - src/routes/signup/+page.svelte | 69 +++--- src/types/api.d.ts | 13 ++ 27 files changed, 878 insertions(+), 153 deletions(-) create mode 100644 src/components/AccountButton.svelte create mode 100644 src/components/Dropdown.svelte delete mode 100644 src/routes/account/lobbies/+page.svelte rename src/routes/account/{lobbies => lobby}/+page.server.ts (100%) create mode 100644 src/routes/account/lobby/+page.svelte create mode 100644 src/routes/api/user/login/+server.ts create mode 100644 src/routes/login/+page.server.ts create mode 100644 src/routes/login/+page.svelte diff --git a/package-lock.json b/package-lock.json index ff4d5cb..23bec58 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,6 +11,7 @@ "@benzara/svelte-animated-counter": "^0.0.3", "@sveltejs/adapter-static": "^3.0.1", "@sveltejs/enhanced-img": "^0.1.8", + "bcrypt": "^5.1.1", "better-sqlite3": "^9.4.3", "carbon-components-svelte": "^0.84.0", "cookie": "^0.6.0", @@ -39,6 +40,7 @@ "@sveltejs/kit": "^2.0.0", "@sveltejs/vite-plugin-svelte": "^3.0.0", "@tailwindcss/typography": "^0.5.10", + "@types/bcrypt": "^5.0.2", "@types/cookie": "^0.6.0", "@types/jsonwebtoken": "^9.0.6", "@types/prismjs": "^1.26.3", @@ -58,6 +60,7 @@ "sharp": "^0.33.2", "svelte": "^4.2.7", "svelte-check": "^3.6.0", + "sveltekit-rate-limiter": "^0.5.0", "svgo": "^3.2.0", "tailwindcss": "^3.3.6", "tslib": "^2.4.1", @@ -946,6 +949,15 @@ "node": ">=12" } }, + "node_modules/@isaacs/ttlcache": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/@isaacs/ttlcache/-/ttlcache-1.4.1.tgz", + "integrity": "sha512-RQgQ4uQ+pLbqXfOmieB91ejmLwvSgv9nLx6sT6sD83s7umBypgg+OIBOBbEUiJXrfpnp9j0mRhYYdzp9uqq3lA==", + "dev": true, + "engines": { + "node": ">=12" + } + }, "node_modules/@jridgewell/gen-mapping": { "version": "0.3.5", "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", @@ -989,6 +1001,145 @@ "@jridgewell/sourcemap-codec": "^1.4.14" } }, + "node_modules/@mapbox/node-pre-gyp": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.11.tgz", + "integrity": "sha512-Yhlar6v9WQgUp/He7BdgzOz8lqMQ8sU+jkCq7Wx8Myc5YFJLbEe7lgui/V7G1qB1DJykHSGwreceSaD60Y0PUQ==", + "dependencies": { + "detect-libc": "^2.0.0", + "https-proxy-agent": "^5.0.0", + "make-dir": "^3.1.0", + "node-fetch": "^2.6.7", + "nopt": "^5.0.0", + "npmlog": "^5.0.1", + "rimraf": "^3.0.2", + "semver": "^7.3.5", + "tar": "^6.1.11" + }, + "bin": { + "node-pre-gyp": "bin/node-pre-gyp" + } + }, + "node_modules/@mapbox/node-pre-gyp/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/@mapbox/node-pre-gyp/node_modules/are-we-there-yet": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-2.0.0.tgz", + "integrity": "sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==", + "dependencies": { + "delegates": "^1.0.0", + "readable-stream": "^3.6.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@mapbox/node-pre-gyp/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, + "node_modules/@mapbox/node-pre-gyp/node_modules/gauge": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-3.0.2.tgz", + "integrity": "sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==", + "dependencies": { + "aproba": "^1.0.3 || ^2.0.0", + "color-support": "^1.1.2", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.1", + "object-assign": "^4.1.1", + "signal-exit": "^3.0.0", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1", + "wide-align": "^1.1.2" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@mapbox/node-pre-gyp/node_modules/make-dir": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "dependencies": { + "semver": "^6.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@mapbox/node-pre-gyp/node_modules/make-dir/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@mapbox/node-pre-gyp/node_modules/npmlog": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-5.0.1.tgz", + "integrity": "sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==", + "dependencies": { + "are-we-there-yet": "^2.0.0", + "console-control-strings": "^1.1.0", + "gauge": "^3.0.0", + "set-blocking": "^2.0.0" + } + }, + "node_modules/@mapbox/node-pre-gyp/node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@mapbox/node-pre-gyp/node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" + }, + "node_modules/@mapbox/node-pre-gyp/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@mapbox/node-pre-gyp/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -1602,6 +1753,15 @@ "node": ">=10.13.0" } }, + "node_modules/@types/bcrypt": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/@types/bcrypt/-/bcrypt-5.0.2.tgz", + "integrity": "sha512-6atioO8Y75fNcbmj0G7UjI9lXN2pQ/IGJ2FWT4a/btd0Lk9lQalHLKhkgKVZ3r+spnmWUKfbMi1GEe9wyHQfNQ==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@types/cookie": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.6.0.tgz", @@ -1700,8 +1860,7 @@ "node_modules/abbrev": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", - "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", - "optional": true + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" }, "node_modules/accepts": { "version": "1.3.8", @@ -1731,7 +1890,6 @@ "version": "6.0.2", "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", - "optional": true, "dependencies": { "debug": "4" }, @@ -1890,8 +2048,7 @@ "node_modules/aproba": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz", - "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==", - "optional": true + "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==" }, "node_modules/arch": { "version": "2.2.0", @@ -2359,6 +2516,19 @@ } ] }, + "node_modules/bcrypt": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/bcrypt/-/bcrypt-5.1.1.tgz", + "integrity": "sha512-AGBHOG5hPYZ5Xl9KXzU5iKq9516yEmvCKDg3ecP5kX2aB6UqTeXZxk2ELnDgDm6BQSMlLt9rDB4LoSMx0rYwww==", + "hasInstallScript": true, + "dependencies": { + "@mapbox/node-pre-gyp": "^1.0.11", + "node-addon-api": "^5.0.0" + }, + "engines": { + "node": ">= 10.0.0" + } + }, "node_modules/bcrypt-pbkdf": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", @@ -2367,6 +2537,11 @@ "tweetnacl": "^0.14.3" } }, + "node_modules/bcrypt/node_modules/node-addon-api": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-5.1.0.tgz", + "integrity": "sha512-eh0GgfEkpnoWDq+VY8OyvYhFEzBk6jIYbRKdIlyTiAXIVJ8PyBaKb0rp7oDtoddbdoHWhq8wwr+XZ81F1rpNdA==" + }, "node_modules/better-sqlite3": { "version": "9.4.3", "resolved": "https://registry.npmjs.org/better-sqlite3/-/better-sqlite3-9.4.3.tgz", @@ -3643,7 +3818,6 @@ "version": "1.1.3", "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", - "devOptional": true, "bin": { "color-support": "bin.js" } @@ -7143,7 +7317,6 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", - "optional": true, "dependencies": { "agent-base": "6", "debug": "4" @@ -8845,7 +9018,6 @@ "version": "2.7.0", "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", - "dev": true, "dependencies": { "whatwg-url": "^5.0.0" }, @@ -8910,7 +9082,6 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==", - "optional": true, "dependencies": { "abbrev": "1" }, @@ -12278,6 +12449,18 @@ } } }, + "node_modules/sveltekit-rate-limiter": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/sveltekit-rate-limiter/-/sveltekit-rate-limiter-0.5.0.tgz", + "integrity": "sha512-q5RnqgAWP3fhDR+InWdOvsmYZ/x27Qojrk00scy+ob3Q+hawzHmLjQSL6XmSJrx82ceGZlw3G/hKyb/952oGWA==", + "dev": true, + "dependencies": { + "@isaacs/ttlcache": "^1.4.1" + }, + "peerDependencies": { + "@sveltejs/kit": "1.x || 2.x" + } + }, "node_modules/sver-compat": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/sver-compat/-/sver-compat-1.5.0.tgz", @@ -12890,8 +13073,7 @@ "node_modules/tr46": { "version": "0.0.3", "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", - "dev": true + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" }, "node_modules/trim-repeated": { "version": "1.0.0", @@ -14072,14 +14254,12 @@ "node_modules/webidl-conversions": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", - "dev": true + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" }, "node_modules/whatwg-url": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", - "dev": true, "dependencies": { "tr46": "~0.0.3", "webidl-conversions": "^3.0.0" diff --git a/package.json b/package.json index 9b6763a..1335738 100644 --- a/package.json +++ b/package.json @@ -18,6 +18,7 @@ "@sveltejs/kit": "^2.0.0", "@sveltejs/vite-plugin-svelte": "^3.0.0", "@tailwindcss/typography": "^0.5.10", + "@types/bcrypt": "^5.0.2", "@types/cookie": "^0.6.0", "@types/jsonwebtoken": "^9.0.6", "@types/prismjs": "^1.26.3", @@ -37,6 +38,7 @@ "sharp": "^0.33.2", "svelte": "^4.2.7", "svelte-check": "^3.6.0", + "sveltekit-rate-limiter": "^0.5.0", "svgo": "^3.2.0", "tailwindcss": "^3.3.6", "tslib": "^2.4.1", @@ -51,6 +53,7 @@ "@benzara/svelte-animated-counter": "^0.0.3", "@sveltejs/adapter-static": "^3.0.1", "@sveltejs/enhanced-img": "^0.1.8", + "bcrypt": "^5.1.1", "better-sqlite3": "^9.4.3", "carbon-components-svelte": "^0.84.0", "cookie": "^0.6.0", diff --git a/src/app.html b/src/app.html index 2edde36..2ce5a3c 100644 --- a/src/app.html +++ b/src/app.html @@ -23,6 +23,6 @@ %sveltekit.head% - %sveltekit.body% +
%sveltekit.body%
diff --git a/src/components/AccountButton.svelte b/src/components/AccountButton.svelte new file mode 100644 index 0000000..1bcb9c8 --- /dev/null +++ b/src/components/AccountButton.svelte @@ -0,0 +1,78 @@ + + + + + + + + diff --git a/src/components/Dropdown.svelte b/src/components/Dropdown.svelte new file mode 100644 index 0000000..8d18b91 --- /dev/null +++ b/src/components/Dropdown.svelte @@ -0,0 +1,101 @@ + + +
+ + +
+ + diff --git a/src/components/Room.svelte b/src/components/Room.svelte index f6e3570..470b907 100644 --- a/src/components/Room.svelte +++ b/src/components/Room.svelte @@ -18,21 +18,26 @@ ); mask-image: var(--mask-image); -webkit-mask-image: var(--mask-image); " /> -
+
{#if room.game?.iconUrl} Icon for '{room.preferredGameName}' {/if} -
-

- {room.name} - +
+

+ {room.name} +

+ ({room.game?.name || "No preferred game"}) -

+

{room.description}

{room.players.length} / {room.maxPlayers} | {#if room.players.length > 4} diff --git a/src/hooks.server.ts b/src/hooks.server.ts index 5d61ec1..9ad4359 100644 --- a/src/hooks.server.ts +++ b/src/hooks.server.ts @@ -39,10 +39,6 @@ async function setupGames() { const runAllTheInitFunctions = async () => { if (!db.isInitialized) await db.initialize(); - // sigh. - const user = await userRepo.findOne({ where: { username: "nullptr" } }); - user!.roles = ["moderator"]; - await userRepo.save(user!); if (!server) try { initServer(); diff --git a/src/lib/client/api/index.ts b/src/lib/client/api/index.ts index 31ab47a..da54412 100644 --- a/src/lib/client/api/index.ts +++ b/src/lib/client/api/index.ts @@ -1,10 +1,20 @@ -import type { CreateAccountRequest, CreateAccountResponse, GetUserResponse } from "$types/api"; +import type { + CreateAccountRequest, + CreateAccountResponse, + GetUserResponse, + LoginRequest, + LoginResponse, +} from "$types/api"; const apiUsers = { async createAccount(body: CreateAccountRequest): Promise { return await SuyuAPI.req("POST", "/api/user", body); }, + async login(body: LoginRequest): Promise { + return await SuyuAPI.req("POST", "/api/user/login", body); + }, + async deleteAccount() { return await SuyuAPI.req("DELETE", "/api/user"); }, diff --git a/src/lib/server/repo/index.ts b/src/lib/server/repo/index.ts index 2aefad5..5fe0260 100644 --- a/src/lib/server/repo/index.ts +++ b/src/lib/server/repo/index.ts @@ -1,4 +1,5 @@ import { db } from "../db"; -import { SuyuUser } from "../schema"; +import { FriendshipRequest, SuyuUser } from "../schema"; export const userRepo = db.getRepository(SuyuUser); +export const friendshipRepo = db.getRepository(FriendshipRequest); diff --git a/src/lib/server/schema/index.ts b/src/lib/server/schema/index.ts index a938c1c..118b318 100644 --- a/src/lib/server/schema/index.ts +++ b/src/lib/server/schema/index.ts @@ -1,5 +1,5 @@ import type { Role } from "$types/db"; -import { BaseEntity, Column, Entity, PrimaryGeneratedColumn } from "typeorm"; +import { BaseEntity, Column, Entity, ManyToMany, OneToOne, PrimaryGeneratedColumn } from "typeorm"; @Entity() export class SuyuUser extends BaseEntity { @@ -27,4 +27,23 @@ export class SuyuUser extends BaseEntity { select: false, }) email: string; + + @Column("text", { + select: false, + }) + password: string; + + @ManyToMany(() => SuyuUser) + friends: SuyuUser[]; +} + +export class FriendshipRequest extends BaseEntity { + @PrimaryGeneratedColumn("uuid") + id: string; + + @OneToOne(() => SuyuUser) + from: SuyuUser; + + @OneToOne(() => SuyuUser) + to: SuyuUser; } diff --git a/src/lib/server/util/index.ts b/src/lib/server/util/index.ts index c93238b..fc395cc 100644 --- a/src/lib/server/util/index.ts +++ b/src/lib/server/util/index.ts @@ -19,3 +19,23 @@ export async function getJwtData(token: string): Promise { }); }); } + +export class RateLimiter { + // allow 5 requests per minute + + cache = new Map(); + + constructor() {} + + isLimited(ip: string): boolean { + // if the last request was in the last minute, return true + if (this.cache.has(ip)) { + if (Date.now() - this.cache.get(ip)! < 5000) { + return true; + } + } + // set the last request to now + this.cache.set(ip, Date.now()); + return false; + } +} diff --git a/src/routes/+layout.server.ts b/src/routes/+layout.server.ts index 37a4758..1a59ced 100644 --- a/src/routes/+layout.server.ts +++ b/src/routes/+layout.server.ts @@ -1,7 +1,11 @@ -export function load({ cookies, url }) { +import { useAuth } from "$lib/util/api/index.js"; + +export async function load({ cookies, url }) { const token = cookies.get("token"); + const user = await useAuth(token || ""); return { tokenCookie: token, url: url.pathname, + user: { ...user }, }; } diff --git a/src/routes/+layout.svelte b/src/routes/+layout.svelte index 6ff716a..307ec3d 100644 --- a/src/routes/+layout.svelte +++ b/src/routes/+layout.svelte @@ -12,6 +12,7 @@ import { generateTransition, transition } from "$lib/util/animation"; import { reducedMotion } from "$lib/accessibility"; import BackgroundProvider from "$components/BackgroundProvider.svelte"; + import AccountButton from "$components/AccountButton.svelte"; export let data: PageData; @@ -146,7 +147,7 @@ }, { name: "GitLab", - href: "https://gitlab.com/suyu-emu/", + href: "https://gitlab.com/suyu-emu/suyu", }, { name: $token || data.tokenCookie ? "Account" : "Sign up", @@ -286,9 +287,16 @@ > - {$token ? "Account" : "Sign up"} + > --> + + + {:else} + Log in + Sign up + {/if}