From a168ef8afe7aff248902f4c47f7fcd408dd0e1f8 Mon Sep 17 00:00:00 2001 From: Borja Garibotti Date: Sat, 15 Jun 2024 15:27:34 -0300 Subject: [PATCH 1/6] Add bank details --- my-app/src/lib/index.ts | 2 +- my-app/src/lib/server/api.ts | 13 ++++++- .../groups/[id=integer]/members/+page.svelte | 18 +++++++-- .../src/routes/user/profile/+page.server.ts | 27 +++++++++++++ my-app/src/routes/user/profile/+page.svelte | 38 +++++++++++++++++++ my-app/src/types.d.ts | 4 ++ 6 files changed, 96 insertions(+), 6 deletions(-) create mode 100644 my-app/src/routes/user/profile/+page.server.ts create mode 100644 my-app/src/routes/user/profile/+page.svelte diff --git a/my-app/src/lib/index.ts b/my-app/src/lib/index.ts index a947554..e67c4df 100644 --- a/my-app/src/lib/index.ts +++ b/my-app/src/lib/index.ts @@ -28,7 +28,7 @@ export const routes = { login: '/user/login', logout: '/user/logout', register: '/user/register', - recover: '/user/recover', + profile: '/user/profile', // groups groups: '/groups', groupDetails: '/groups/details', diff --git a/my-app/src/lib/server/api.ts b/my-app/src/lib/server/api.ts index 1be8473..a97f9fd 100644 --- a/my-app/src/lib/server/api.ts +++ b/my-app/src/lib/server/api.ts @@ -55,8 +55,17 @@ function put(path: string, data: object, headers?: Headers) { } export const userService = { - register: (data: { email: string; password: string }) => post('user/register', data), - login: (data: { email: string; password: string }) => post('user/login', data) + register: (data: UserRegistration) => post('user/register', data), + login: (data: UserRegistration) => post('user/login', data), + save: (data: UserProfile, cookies: Cookies) => { + { + // Remove when backend is updated + cookies.set('cbu', data.cbu, { path: '/' }); + cookies.set('alias', data.alias, { path: '/' }); + return; + } + return post('user/profile', data, getAuthHeader(cookies)); + } }; export const groupService = { save: (data: Group, cookies: Cookies) => diff --git a/my-app/src/routes/groups/[id=integer]/members/+page.svelte b/my-app/src/routes/groups/[id=integer]/members/+page.svelte index 5f31cf3..d347ebd 100644 --- a/my-app/src/routes/groups/[id=integer]/members/+page.svelte +++ b/my-app/src/routes/groups/[id=integer]/members/+page.svelte @@ -25,8 +25,20 @@ {#each data.members as user} -
- - {user.email} +
+
+ + {user.email} +
+
+
+ CBU / CVU: + {user.cbu} +
+
+ Alias: + {user.alias} +
+
{/each} diff --git a/my-app/src/routes/user/profile/+page.server.ts b/my-app/src/routes/user/profile/+page.server.ts new file mode 100644 index 0000000..6c6e90e --- /dev/null +++ b/my-app/src/routes/user/profile/+page.server.ts @@ -0,0 +1,27 @@ +import { userService } from '$lib/server/api'; +import type { Actions, PageServerLoad } from './$types'; + +export const load: PageServerLoad = async ({ cookies }) => { + const profile: UserProfile = { + cbu: cookies.get('cbu')!, + alias: cookies.get('cbu')! + }; + return { profile }; +}; + +export const actions: Actions = { + default: async ({ cookies, request }) => { + const data = await request.formData(); + const cbu = data.get('cbu')?.toString() || ''; + const alias = data.get('alias')?.toString() || ''; + + const profile: UserProfile = { cbu, alias }; + try { + await userService.save(profile, cookies); + } catch { + return { success: false }; + } + + return { success: true }; + } +}; diff --git a/my-app/src/routes/user/profile/+page.svelte b/my-app/src/routes/user/profile/+page.svelte new file mode 100644 index 0000000..326af81 --- /dev/null +++ b/my-app/src/routes/user/profile/+page.svelte @@ -0,0 +1,38 @@ + + +
+
+

Perfil

+

+ {#if form == undefined} + Actualice sus datos personales + {:else if form.success} + ¡Tus datos ya se encuentran actualizados! + {:else} + Ocurrió un error + {/if} +

+
+
+ +
+
+ + + +
+ +
diff --git a/my-app/src/types.d.ts b/my-app/src/types.d.ts index d20a206..21e75bb 100644 --- a/my-app/src/types.d.ts +++ b/my-app/src/types.d.ts @@ -4,7 +4,11 @@ declare global { type User = { id: Id; email: string; + cbu: string; + alias: string; }; + type UserRegistration = { email: string; password: string }; + type UserProfile = Omit; type Group = { id: Id; From 33719f7bedaeb7142206d690bb20a87438accd78 Mon Sep 17 00:00:00 2001 From: Borja Garibotti Date: Sun, 16 Jun 2024 02:49:49 -0300 Subject: [PATCH 2/6] SSO --- my-app/.env.example | 4 +- my-app/package-lock.json | 235 +++++++++++++++++- my-app/package.json | 1 + my-app/src/app.d.ts | 1 + my-app/src/lib/auth.ts | 6 - my-app/src/lib/client/alerts.ts | 8 + .../lib/components/google/GoogleButton.svelte | 35 +++ .../components/google/GoogleLinkButton.svelte | 24 ++ .../google/GoogleSigninButton.svelte | 32 +++ .../google/GoogleSignupButton.svelte | 27 ++ .../google/GoogleUnlinkButton.svelte | 24 ++ my-app/src/lib/index.ts | 8 +- my-app/src/lib/server/api.ts | 7 +- my-app/src/routes/+layout.svelte | 5 +- my-app/src/routes/+page.svelte | 14 +- my-app/src/routes/api/google/+server.ts | 73 ++++++ .../details/[[id=integer]]/+page.server.ts | 3 +- my-app/src/routes/user/login/+page.svelte | 37 +-- .../src/routes/user/profile/+page.server.ts | 13 +- my-app/src/routes/user/profile/+page.svelte | 46 ++-- my-app/src/routes/user/register/+page.svelte | 47 ++-- my-app/src/types.d.ts | 5 +- my-app/static/styles.css | 8 + 23 files changed, 588 insertions(+), 75 deletions(-) create mode 100644 my-app/src/lib/components/google/GoogleButton.svelte create mode 100644 my-app/src/lib/components/google/GoogleLinkButton.svelte create mode 100644 my-app/src/lib/components/google/GoogleSigninButton.svelte create mode 100644 my-app/src/lib/components/google/GoogleSignupButton.svelte create mode 100644 my-app/src/lib/components/google/GoogleUnlinkButton.svelte create mode 100644 my-app/src/routes/api/google/+server.ts diff --git a/my-app/.env.example b/my-app/.env.example index 8825d1e..de8df2f 100644 --- a/my-app/.env.example +++ b/my-app/.env.example @@ -1,2 +1,4 @@ # VITE_API_URL="http://127.0.0.1:8000" -VITE_API_URL="http://localhost:8000" \ No newline at end of file +VITE_API_URL="http://localhost:8000" + +PUBLIC_GOOGLE_CLIENT_ID="99613318645-jd627o7b5ot8p78dfpeg0duandg766p5.apps.googleusercontent.com" \ No newline at end of file diff --git a/my-app/package-lock.json b/my-app/package-lock.json index 4ac6c15..23aac23 100644 --- a/my-app/package-lock.json +++ b/my-app/package-lock.json @@ -10,6 +10,7 @@ "dependencies": { "@dicebear/collection": "^8.0.2", "@dicebear/core": "^8.0.2", + "google-auth-library": "^9.11.0", "jose": "^5.3.0" }, "devDependencies": { @@ -1883,6 +1884,17 @@ "node": ">=0.4.0" } }, + "node_modules/agent-base": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz", + "integrity": "sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==", + "dependencies": { + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, "node_modules/ajv": { "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", @@ -1984,6 +1996,33 @@ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", "dev": true }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/bignumber.js": { + "version": "9.1.2", + "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.1.2.tgz", + "integrity": "sha512-2/mKyZH9K85bzOEfhXDBFZTGd1CTs+5IHpeFQo9luiBG7hghdC851Pj2WAhb6E3R6b9tZj/XKhbg4fum+Kepug==", + "engines": { + "node": "*" + } + }, "node_modules/binary-extensions": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", @@ -2026,6 +2065,11 @@ "node": "*" } }, + "node_modules/buffer-equal-constant-time": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", + "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==" + }, "node_modules/builtin-modules": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.3.0.tgz", @@ -2251,7 +2295,6 @@ "version": "4.3.4", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dev": true, "dependencies": { "ms": "2.1.2" }, @@ -2348,6 +2391,14 @@ "node": ">=6.0.0" } }, + "node_modules/ecdsa-sig-formatter": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", + "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", + "dependencies": { + "safe-buffer": "^5.0.1" + } + }, "node_modules/es6-promise": { "version": "3.3.1", "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-3.3.1.tgz", @@ -2668,6 +2719,11 @@ "url": "https://github.com/sindresorhus/execa?sponsor=1" } }, + "node_modules/extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" + }, "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", @@ -2812,6 +2868,44 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/gaxios": { + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/gaxios/-/gaxios-6.6.0.tgz", + "integrity": "sha512-bpOZVQV5gthH/jVCSuYuokRo2bTKOcuBiVWpjmTn6C5Agl5zclGfTljuGsQZxwwDBkli+YhZhP4TdlqTnhOezQ==", + "dependencies": { + "extend": "^3.0.2", + "https-proxy-agent": "^7.0.1", + "is-stream": "^2.0.0", + "node-fetch": "^2.6.9", + "uuid": "^9.0.1" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/gaxios/node_modules/is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/gcp-metadata": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/gcp-metadata/-/gcp-metadata-6.1.0.tgz", + "integrity": "sha512-Jh/AIwwgaxan+7ZUUmRLCjtchyDiqh4KjBJ5tW3plBZb5iL/BPcso8A5DlzeD9qlw0duCamnNdpFjxwaT0KyKg==", + "dependencies": { + "gaxios": "^6.0.0", + "json-bigint": "^1.0.0" + }, + "engines": { + "node": ">=14" + } + }, "node_modules/get-func-name": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.2.tgz", @@ -2934,6 +3028,22 @@ "integrity": "sha512-uHJgbwAMwNFf5mLst7IWLNg14x1CkeqglJb/K3doi4dw6q2IvAAmM/Y81kevy83wP+Sst+nutFTYOGg3d1lsxg==", "dev": true }, + "node_modules/google-auth-library": { + "version": "9.11.0", + "resolved": "https://registry.npmjs.org/google-auth-library/-/google-auth-library-9.11.0.tgz", + "integrity": "sha512-epX3ww/mNnhl6tL45EQ/oixsY8JLEgUFoT4A5E/5iAR4esld9Kqv6IJGk7EmGuOgDvaarwF95hU2+v7Irql9lw==", + "dependencies": { + "base64-js": "^1.3.0", + "ecdsa-sig-formatter": "^1.0.11", + "gaxios": "^6.1.1", + "gcp-metadata": "^6.1.0", + "gtoken": "^7.0.0", + "jws": "^4.0.0" + }, + "engines": { + "node": ">=14" + } + }, "node_modules/graceful-fs": { "version": "4.2.11", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", @@ -2946,6 +3056,18 @@ "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", "dev": true }, + "node_modules/gtoken": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/gtoken/-/gtoken-7.1.0.tgz", + "integrity": "sha512-pCcEwRi+TKpMlxAQObHDQ56KawURgyAf6jtIY046fJ5tIv3zDe/LEIubckAO8fj6JnAxLdmWkUfNyulQ2iKdEw==", + "dependencies": { + "gaxios": "^6.0.0", + "jws": "^4.0.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, "node_modules/has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", @@ -2967,6 +3089,18 @@ "node": ">= 0.4" } }, + "node_modules/https-proxy-agent": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.4.tgz", + "integrity": "sha512-wlwpilI7YdjSkWaQ/7omYBMTliDcmCN8OLihO6I9B86g06lMyAoqgoDpV0XqoaPOKj+0DIdAvnsWfyAAhmimcg==", + "dependencies": { + "agent-base": "^7.0.2", + "debug": "4" + }, + "engines": { + "node": ">= 14" + } + }, "node_modules/human-signals": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-5.0.0.tgz", @@ -3173,6 +3307,14 @@ "js-yaml": "bin/js-yaml.js" } }, + "node_modules/json-bigint": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-bigint/-/json-bigint-1.0.0.tgz", + "integrity": "sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ==", + "dependencies": { + "bignumber.js": "^9.0.0" + } + }, "node_modules/json-buffer": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", @@ -3191,6 +3333,25 @@ "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", "dev": true }, + "node_modules/jwa": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-2.0.0.tgz", + "integrity": "sha512-jrZ2Qx916EA+fq9cEAeCROWPTfCwi1IVHqT2tapuqLEVVDKFDENFw1oL+MwrTvH6msKxsd1YTDVw6uKEcsrLEA==", + "dependencies": { + "buffer-equal-constant-time": "1.0.1", + "ecdsa-sig-formatter": "1.0.11", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/jws": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jws/-/jws-4.0.0.tgz", + "integrity": "sha512-KDncfTmOZoOMTFG4mBlG0qUIOlc03fmzH+ru6RgYVZhPkyiy/92Owlt/8UEN+a4TXR1FQetfIpJE8ApdvdVxTg==", + "dependencies": { + "jwa": "^2.0.0", + "safe-buffer": "^5.0.1" + } + }, "node_modules/keyv": { "version": "4.5.4", "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", @@ -3434,8 +3595,7 @@ "node_modules/ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, "node_modules/nanoid": { "version": "3.3.7", @@ -3461,6 +3621,25 @@ "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", "dev": true }, + "node_modules/node-fetch": { + "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==", + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, "node_modules/normalize-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", @@ -4047,6 +4226,25 @@ "node": ">=6" } }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, "node_modules/sander": { "version": "0.5.1", "resolved": "https://registry.npmjs.org/sander/-/sander-0.5.1.tgz", @@ -4499,6 +4697,11 @@ "node": ">=6" } }, + "node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" + }, "node_modules/ts-api-utils": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.3.0.tgz", @@ -4584,6 +4787,18 @@ "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", "dev": true }, + "node_modules/uuid": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", + "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "bin": { + "uuid": "dist/bin/uuid" + } + }, "node_modules/vite": { "version": "5.2.10", "resolved": "https://registry.npmjs.org/vite/-/vite-5.2.10.tgz", @@ -4754,6 +4969,20 @@ } } }, + "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==" + }, + "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==", + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", diff --git a/my-app/package.json b/my-app/package.json index c666e97..b0a08ac 100644 --- a/my-app/package.json +++ b/my-app/package.json @@ -40,6 +40,7 @@ "dependencies": { "@dicebear/collection": "^8.0.2", "@dicebear/core": "^8.0.2", + "google-auth-library": "^9.11.0", "jose": "^5.3.0" } } diff --git a/my-app/src/app.d.ts b/my-app/src/app.d.ts index e6b44f1..0089347 100644 --- a/my-app/src/app.d.ts +++ b/my-app/src/app.d.ts @@ -5,6 +5,7 @@ declare global { // interface Error {} // interface Locals {} interface PageData { + user?: string; userId?: Id; } // interface PageState {} diff --git a/my-app/src/lib/auth.ts b/my-app/src/lib/auth.ts index 9eada65..408e84b 100644 --- a/my-app/src/lib/auth.ts +++ b/my-app/src/lib/auth.ts @@ -1,11 +1,5 @@ import type { Cookies } from '@sveltejs/kit'; -type UserCredentials = { - id: number; - email: string; - jwt: string; -}; - export function saveUserCredentials(cookies: Cookies, userCredentials: UserCredentials) { cookies.set('jwt', userCredentials.jwt, { httpOnly: true, secure: true, path: '/' }); cookies.set('userId', userCredentials.id.toFixed(0), { path: '/' }); diff --git a/my-app/src/lib/client/alerts.ts b/my-app/src/lib/client/alerts.ts index 03bc43b..259b40a 100644 --- a/my-app/src/lib/client/alerts.ts +++ b/my-app/src/lib/client/alerts.ts @@ -5,3 +5,11 @@ export async function confirmArchiveGroup(group: Group) { await fetch(`/api/groups?groupId=${group.id}&archive=${!group.is_archived}`, { method: 'PUT' }); location.reload(); } + +export function alertNoGoogleUser() { + alert('Su cuenta de Google no se encuentra vinculado a ningun usuario'); +} + +export function alertUnexpectedError() { + alert('Ocurrió un error'); +} diff --git a/my-app/src/lib/components/google/GoogleButton.svelte b/my-app/src/lib/components/google/GoogleButton.svelte new file mode 100644 index 0000000..1bd526f --- /dev/null +++ b/my-app/src/lib/components/google/GoogleButton.svelte @@ -0,0 +1,35 @@ + + +
+ + diff --git a/my-app/src/lib/components/google/GoogleLinkButton.svelte b/my-app/src/lib/components/google/GoogleLinkButton.svelte new file mode 100644 index 0000000..0eca34e --- /dev/null +++ b/my-app/src/lib/components/google/GoogleLinkButton.svelte @@ -0,0 +1,24 @@ + + + { + try { + const response = await fetch(routes.google, { + method: 'PUT', + body: JSON.stringify({ credential }) + }); + + const { redirect } = await response.json(); + window.location.href = redirect; + } catch { + alertUnexpectedError(); + } + }} + text="continue_with" + prompt={false} +/> diff --git a/my-app/src/lib/components/google/GoogleSigninButton.svelte b/my-app/src/lib/components/google/GoogleSigninButton.svelte new file mode 100644 index 0000000..283e1aa --- /dev/null +++ b/my-app/src/lib/components/google/GoogleSigninButton.svelte @@ -0,0 +1,32 @@ + + + { + try { + const response = await fetch(routes.google, { + method: 'POST', + body: JSON.stringify({ + action: 'signin', + credential + }) + }); + + if (!response.ok) { + alertNoGoogleUser(); + return; + } + + const { redirect } = await response.json(); + window.location.href = redirect; + } catch { + alertUnexpectedError(); + } + }} + text="signin" + prompt={false} +/> diff --git a/my-app/src/lib/components/google/GoogleSignupButton.svelte b/my-app/src/lib/components/google/GoogleSignupButton.svelte new file mode 100644 index 0000000..152c2f2 --- /dev/null +++ b/my-app/src/lib/components/google/GoogleSignupButton.svelte @@ -0,0 +1,27 @@ + + + { + try { + const response = await fetch(routes.google, { + method: 'POST', + body: JSON.stringify({ + action: 'signup', + credential + }) + }); + + const { redirect } = await response.json(); + window.location.href = redirect; + } catch { + alertUnexpectedError(); + } + }} + text="signup_with" + prompt={false} +/> diff --git a/my-app/src/lib/components/google/GoogleUnlinkButton.svelte b/my-app/src/lib/components/google/GoogleUnlinkButton.svelte new file mode 100644 index 0000000..6c91af0 --- /dev/null +++ b/my-app/src/lib/components/google/GoogleUnlinkButton.svelte @@ -0,0 +1,24 @@ + + + diff --git a/my-app/src/lib/index.ts b/my-app/src/lib/index.ts index e67c4df..fd8e2c9 100644 --- a/my-app/src/lib/index.ts +++ b/my-app/src/lib/index.ts @@ -1,7 +1,11 @@ // place files you want to import through the `$lib` alias in this folder. +import { env } from '$env/dynamic/public'; + export const title = 'VaquitApp'; +export const GOOGLE_CLIENT_ID = env['PUBLIC_GOOGLE_CLIENT_ID']; + // icons from CSS.GG export const ICONS = [ 'sun', @@ -18,7 +22,8 @@ export const ICONS = [ 'info', 'danger', 'loadbar-doc', - 'add' + 'add', + 'google' ] as const; // app routes @@ -29,6 +34,7 @@ export const routes = { logout: '/user/logout', register: '/user/register', profile: '/user/profile', + google: '/api/google', // groups groups: '/groups', groupDetails: '/groups/details', diff --git a/my-app/src/lib/server/api.ts b/my-app/src/lib/server/api.ts index a97f9fd..24e35fa 100644 --- a/my-app/src/lib/server/api.ts +++ b/my-app/src/lib/server/api.ts @@ -65,7 +65,12 @@ export const userService = { return; } return post('user/profile', data, getAuthHeader(cookies)); - } + }, + getMe: (cookies: Cookies) => get('user', getAuthHeader(cookies)), + googleSignIn: (data: UserGoogleCredentials) => post('user/googleSignIn', data), + googleLink: (data: UserGoogleCredentials, cookies: Cookies) => + put('user/googleSignIn', data, getAuthHeader(cookies)), + googleUnlink: (cookies: Cookies) => del('user/googleSignIn', getAuthHeader(cookies)) }; export const groupService = { save: (data: Group, cookies: Cookies) => diff --git a/my-app/src/routes/+layout.svelte b/my-app/src/routes/+layout.svelte index c0be333..0b2568a 100644 --- a/my-app/src/routes/+layout.svelte +++ b/my-app/src/routes/+layout.svelte @@ -47,6 +47,8 @@ {title} + + Ver perfil Cerrar sesión {:else} - Iniciar sesión + Iniciar sesión + Registrarse {/if}
  • diff --git a/my-app/src/routes/+page.svelte b/my-app/src/routes/+page.svelte index 96b24c2..d00757f 100644 --- a/my-app/src/routes/+page.svelte +++ b/my-app/src/routes/+page.svelte @@ -1,11 +1,12 @@ -
    +
    {#if data.user}

    Bienvenido, {data.user}

    Ver mis grupos @@ -13,16 +14,15 @@ {:else}

    Gestionar tus finanzas

    ahora es muucho más fácil

    - Ingresar - Registrarme + + {/if}