From 2b13af73042664a025878115f2f904c7d330d0db Mon Sep 17 00:00:00 2001 From: Mohamed Hamouda Date: Sat, 7 Oct 2023 22:36:07 -0700 Subject: [PATCH 1/5] Added my name to README --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 941dcea..d661a86 100644 --- a/README.md +++ b/README.md @@ -3,4 +3,5 @@ FA23: p-reset ### People Sumi Vora Vivien Song -Haram Yoon \ No newline at end of file +Haram Yoon +Mohamed Hamouda \ No newline at end of file From 4ec5a8ce5664bf752b7d68f4e91ce5f0cc95855d Mon Sep 17 00:00:00 2001 From: Mohamed Hamouda Date: Sun, 8 Oct 2023 22:37:18 -0700 Subject: [PATCH 2/5] Added google authentication using nextAuth; Gcal API is to be implemented --- client/.env | 6 + client/package-lock.json | 247 +++++++++++++++++-------- client/package.json | 13 +- client/pages/_app.js | 9 +- client/pages/account.jsx | 37 ++++ client/pages/api/auth/[...nextauth].js | 13 ++ client/pages/login.jsx | 26 +++ 7 files changed, 261 insertions(+), 90 deletions(-) create mode 100644 client/.env create mode 100644 client/pages/account.jsx create mode 100644 client/pages/api/auth/[...nextauth].js create mode 100644 client/pages/login.jsx diff --git a/client/.env b/client/.env new file mode 100644 index 0000000..19d3d35 --- /dev/null +++ b/client/.env @@ -0,0 +1,6 @@ +GOOGLE_CLIENT_ID = 757306875568-76c8a3tmj1hhousioaa6a2587rq2tjir.apps.googleusercontent.com +GOOGLE_CLIENT_SECRET = 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 + +NEXTAUTH_URL = http://localhost:3000 + +JWT_SECRET = c085ce0c5c21a4d774591a20b981013e diff --git a/client/package-lock.json b/client/package-lock.json index c955cf5..4a06333 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -8,8 +8,9 @@ "name": "client", "version": "0.1.0", "dependencies": { - "next": "latest", - "react": "latest", + "next": "^13.5.4", + "next-auth": "^4.23.2", + "react": "^18.2.0", "react-dom": "latest" }, "devDependencies": { @@ -45,7 +46,6 @@ "version": "7.23.1", "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.23.1.tgz", "integrity": "sha512-hC2v6p8ZSI/W0HUzh3V8C5g+NwSKzKPtJwSpTjwl0o297GP9+ZLQSkdvHz46CM3LqyoXxq+5G9komY+eSqSO0g==", - "dev": true, "dependencies": { "regenerator-runtime": "^0.14.0" }, @@ -191,9 +191,9 @@ } }, "node_modules/@next/env": { - "version": "13.5.3", - "resolved": "https://registry.npmjs.org/@next/env/-/env-13.5.3.tgz", - "integrity": "sha512-X4te86vsbjsB7iO4usY9jLPtZ827Mbx+WcwNBGUOIuswuTAKQtzsuoxc/6KLxCMvogKG795MhrR1LDhYgDvasg==" + "version": "13.5.4", + "resolved": "https://registry.npmjs.org/@next/env/-/env-13.5.4.tgz", + "integrity": "sha512-LGegJkMvRNw90WWphGJ3RMHMVplYcOfRWf2Be3td3sUa+1AaxmsYyANsA+znrGCBjXJNi4XAQlSoEfUxs/4kIQ==" }, "node_modules/@next/eslint-plugin-next": { "version": "13.5.3", @@ -205,9 +205,9 @@ } }, "node_modules/@next/swc-darwin-arm64": { - "version": "13.5.3", - "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-13.5.3.tgz", - "integrity": "sha512-6hiYNJxJmyYvvKGrVThzo4nTcqvqUTA/JvKim7Auaj33NexDqSNwN5YrrQu+QhZJCIpv2tULSHt+lf+rUflLSw==", + "version": "13.5.4", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-13.5.4.tgz", + "integrity": "sha512-Df8SHuXgF1p+aonBMcDPEsaahNo2TCwuie7VXED4FVyECvdXfRT9unapm54NssV9tF3OQFKBFOdlje4T43VO0w==", "cpu": [ "arm64" ], @@ -220,9 +220,9 @@ } }, "node_modules/@next/swc-darwin-x64": { - "version": "13.5.3", - "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-13.5.3.tgz", - "integrity": "sha512-UpBKxu2ob9scbpJyEq/xPgpdrgBgN3aLYlxyGqlYX5/KnwpJpFuIHU2lx8upQQ7L+MEmz+fA1XSgesoK92ppwQ==", + "version": "13.5.4", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-13.5.4.tgz", + "integrity": "sha512-siPuUwO45PnNRMeZnSa8n/Lye5ZX93IJom9wQRB5DEOdFrw0JjOMu1GINB8jAEdwa7Vdyn1oJ2xGNaQpdQQ9Pw==", "cpu": [ "x64" ], @@ -235,9 +235,9 @@ } }, "node_modules/@next/swc-linux-arm64-gnu": { - "version": "13.5.3", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-13.5.3.tgz", - "integrity": "sha512-5AzM7Yx1Ky+oLY6pHs7tjONTF22JirDPd5Jw/3/NazJ73uGB05NqhGhB4SbeCchg7SlVYVBeRMrMSZwJwq/xoA==", + "version": "13.5.4", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-13.5.4.tgz", + "integrity": "sha512-l/k/fvRP/zmB2jkFMfefmFkyZbDkYW0mRM/LB+tH5u9pB98WsHXC0WvDHlGCYp3CH/jlkJPL7gN8nkTQVrQ/2w==", "cpu": [ "arm64" ], @@ -250,9 +250,9 @@ } }, "node_modules/@next/swc-linux-arm64-musl": { - "version": "13.5.3", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-13.5.3.tgz", - "integrity": "sha512-A/C1shbyUhj7wRtokmn73eBksjTM7fFQoY2v/0rTM5wehpkjQRLOXI8WJsag2uLhnZ4ii5OzR1rFPwoD9cvOgA==", + "version": "13.5.4", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-13.5.4.tgz", + "integrity": "sha512-YYGb7SlLkI+XqfQa8VPErljb7k9nUnhhRrVaOdfJNCaQnHBcvbT7cx/UjDQLdleJcfyg1Hkn5YSSIeVfjgmkTg==", "cpu": [ "arm64" ], @@ -265,9 +265,9 @@ } }, "node_modules/@next/swc-linux-x64-gnu": { - "version": "13.5.3", - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-13.5.3.tgz", - "integrity": "sha512-FubPuw/Boz8tKkk+5eOuDHOpk36F80rbgxlx4+xty/U71e3wZZxVYHfZXmf0IRToBn1Crb8WvLM9OYj/Ur815g==", + "version": "13.5.4", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-13.5.4.tgz", + "integrity": "sha512-uE61vyUSClnCH18YHjA8tE1prr/PBFlBFhxBZis4XBRJoR+txAky5d7gGNUIbQ8sZZ7LVkSVgm/5Fc7mwXmRAg==", "cpu": [ "x64" ], @@ -280,9 +280,9 @@ } }, "node_modules/@next/swc-linux-x64-musl": { - "version": "13.5.3", - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-13.5.3.tgz", - "integrity": "sha512-DPw8nFuM1uEpbX47tM3wiXIR0Qa+atSzs9Q3peY1urkhofx44o7E1svnq+a5Q0r8lAcssLrwiM+OyJJgV/oj7g==", + "version": "13.5.4", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-13.5.4.tgz", + "integrity": "sha512-qVEKFYML/GvJSy9CfYqAdUexA6M5AklYcQCW+8JECmkQHGoPxCf04iMh7CPR7wkHyWWK+XLt4Ja7hhsPJtSnhg==", "cpu": [ "x64" ], @@ -295,9 +295,9 @@ } }, "node_modules/@next/swc-win32-arm64-msvc": { - "version": "13.5.3", - "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-13.5.3.tgz", - "integrity": "sha512-zBPSP8cHL51Gub/YV8UUePW7AVGukp2D8JU93IHbVDu2qmhFAn9LWXiOOLKplZQKxnIPUkJTQAJDCWBWU4UWUA==", + "version": "13.5.4", + "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-13.5.4.tgz", + "integrity": "sha512-mDSQfqxAlfpeZOLPxLymZkX0hYF3juN57W6vFHTvwKlnHfmh12Pt7hPIRLYIShk8uYRsKPtMTth/EzpwRI+u8w==", "cpu": [ "arm64" ], @@ -310,9 +310,9 @@ } }, "node_modules/@next/swc-win32-ia32-msvc": { - "version": "13.5.3", - "resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-13.5.3.tgz", - "integrity": "sha512-ONcL/lYyGUj4W37D4I2I450SZtSenmFAvapkJQNIJhrPMhzDU/AdfLkW98NvH1D2+7FXwe7yclf3+B7v28uzBQ==", + "version": "13.5.4", + "resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-13.5.4.tgz", + "integrity": "sha512-aoqAT2XIekIWoriwzOmGFAvTtVY5O7JjV21giozBTP5c6uZhpvTWRbmHXbmsjZqY4HnEZQRXWkSAppsIBweKqw==", "cpu": [ "ia32" ], @@ -325,9 +325,9 @@ } }, "node_modules/@next/swc-win32-x64-msvc": { - "version": "13.5.3", - "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-13.5.3.tgz", - "integrity": "sha512-2Vz2tYWaLqJvLcWbbTlJ5k9AN6JD7a5CN2pAeIzpbecK8ZF/yobA39cXtv6e+Z8c5UJuVOmaTldEAIxvsIux/Q==", + "version": "13.5.4", + "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-13.5.4.tgz", + "integrity": "sha512-cyRvlAxwlddlqeB9xtPSfNSCRy8BOa4wtMo0IuI9P7Y0XT2qpDrpFKRyZ7kUngZis59mPVla5k8X1oOJ8RxDYg==", "cpu": [ "x64" ], @@ -374,6 +374,14 @@ "node": ">= 8" } }, + "node_modules/@panva/hkdf": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@panva/hkdf/-/hkdf-1.1.1.tgz", + "integrity": "sha512-dhPeilub1NuIG0X5Kvhh9lH4iW3ZsHlnzwgwbOlgwQ2wG1IqFzsgHqmKPk3WzsdWAeaxKJxgM0+W433RmN45GA==", + "funding": { + "url": "https://github.com/sponsors/panva" + } + }, "node_modules/@rushstack/eslint-patch": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.5.1.tgz", @@ -1032,6 +1040,14 @@ "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", "dev": true }, + "node_modules/cookie": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz", + "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==", + "engines": { + "node": ">= 0.6" + } + }, "node_modules/cross-spawn": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", @@ -2590,6 +2606,14 @@ "jiti": "bin/jiti.js" } }, + "node_modules/jose": { + "version": "4.15.2", + "resolved": "https://registry.npmjs.org/jose/-/jose-4.15.2.tgz", + "integrity": "sha512-IY73F228OXRl9ar3jJagh7Vnuhj/GzBunPiZP13K0lOl7Am9SoWW3kEzq3MCllJMTtZqHTiDXQvoRd4U95aU6A==", + "funding": { + "url": "https://github.com/sponsors/panva" + } + }, "node_modules/js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -2740,7 +2764,6 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, "dependencies": { "yallist": "^4.0.0" }, @@ -2832,18 +2855,17 @@ "dev": true }, "node_modules/next": { - "version": "13.5.3", - "resolved": "https://registry.npmjs.org/next/-/next-13.5.3.tgz", - "integrity": "sha512-4Nt4HRLYDW/yRpJ/QR2t1v63UOMS55A38dnWv3UDOWGezuY0ZyFO1ABNbD7mulVzs9qVhgy2+ppjdsANpKP1mg==", + "version": "13.5.4", + "resolved": "https://registry.npmjs.org/next/-/next-13.5.4.tgz", + "integrity": "sha512-+93un5S779gho8y9ASQhb/bTkQF17FNQOtXLKAj3lsNgltEcF0C5PMLLncDmH+8X1EnJH1kbqAERa29nRXqhjA==", "dependencies": { - "@next/env": "13.5.3", + "@next/env": "13.5.4", "@swc/helpers": "0.5.2", "busboy": "1.6.0", "caniuse-lite": "^1.0.30001406", - "postcss": "8.4.14", + "postcss": "8.4.31", "styled-jsx": "5.1.1", - "watchpack": "2.4.0", - "zod": "3.21.4" + "watchpack": "2.4.0" }, "bin": { "next": "dist/bin/next" @@ -2852,15 +2874,15 @@ "node": ">=16.14.0" }, "optionalDependencies": { - "@next/swc-darwin-arm64": "13.5.3", - "@next/swc-darwin-x64": "13.5.3", - "@next/swc-linux-arm64-gnu": "13.5.3", - "@next/swc-linux-arm64-musl": "13.5.3", - "@next/swc-linux-x64-gnu": "13.5.3", - "@next/swc-linux-x64-musl": "13.5.3", - "@next/swc-win32-arm64-msvc": "13.5.3", - "@next/swc-win32-ia32-msvc": "13.5.3", - "@next/swc-win32-x64-msvc": "13.5.3" + "@next/swc-darwin-arm64": "13.5.4", + "@next/swc-darwin-x64": "13.5.4", + "@next/swc-linux-arm64-gnu": "13.5.4", + "@next/swc-linux-arm64-musl": "13.5.4", + "@next/swc-linux-x64-gnu": "13.5.4", + "@next/swc-linux-x64-musl": "13.5.4", + "@next/swc-win32-arm64-msvc": "13.5.4", + "@next/swc-win32-ia32-msvc": "13.5.4", + "@next/swc-win32-x64-msvc": "13.5.4" }, "peerDependencies": { "@opentelemetry/api": "^1.1.0", @@ -2877,27 +2899,31 @@ } } }, - "node_modules/next/node_modules/postcss": { - "version": "8.4.14", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.14.tgz", - "integrity": "sha512-E398TUmfAYFPBSdzgeieK2Y1+1cpdxJx8yXbK/m57nRhKSmk1GB2tO4lbLBtlkfPQTDKfe4Xqv1ASWPpayPEig==", - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/postcss" - } - ], + "node_modules/next-auth": { + "version": "4.23.2", + "resolved": "https://registry.npmjs.org/next-auth/-/next-auth-4.23.2.tgz", + "integrity": "sha512-VRmInu0r/yZNFQheDFeOKtiugu3bt90Po3owAQDnFQ3YLQFmUKgFjcE2+3L0ny5jsJpBXaKbm7j7W2QTc6Ye2A==", "dependencies": { - "nanoid": "^3.3.4", - "picocolors": "^1.0.0", - "source-map-js": "^1.0.2" + "@babel/runtime": "^7.20.13", + "@panva/hkdf": "^1.0.2", + "cookie": "^0.5.0", + "jose": "^4.11.4", + "oauth": "^0.9.15", + "openid-client": "^5.4.0", + "preact": "^10.6.3", + "preact-render-to-string": "^5.1.19", + "uuid": "^8.3.2" }, - "engines": { - "node": "^10 || ^12 || >=14" + "peerDependencies": { + "next": "^12.2.5 || ^13", + "nodemailer": "^6.6.5", + "react": "^17.0.2 || ^18", + "react-dom": "^17.0.2 || ^18" + }, + "peerDependenciesMeta": { + "nodemailer": { + "optional": true + } } }, "node_modules/node-releases": { @@ -2924,6 +2950,11 @@ "node": ">=0.10.0" } }, + "node_modules/oauth": { + "version": "0.9.15", + "resolved": "https://registry.npmjs.org/oauth/-/oauth-0.9.15.tgz", + "integrity": "sha512-a5ERWK1kh38ExDEfoO6qUHJb32rd7aYmPHuyCu3Fta/cnICvYmgd2uhuKXvPD+PXB+gCEYYEaQdIRAjCOwAKNA==" + }, "node_modules/object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", @@ -3051,6 +3082,14 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/oidc-token-hash": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/oidc-token-hash/-/oidc-token-hash-5.0.3.tgz", + "integrity": "sha512-IF4PcGgzAr6XXSff26Sk/+P4KZFJVuHAJZj3wgO3vX2bMdNVp/QXTP3P7CEm9V1IdG8lDLY3HhiqpsE/nOwpPw==", + "engines": { + "node": "^10.13.0 || >=12.0.0" + } + }, "node_modules/once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", @@ -3060,6 +3099,28 @@ "wrappy": "1" } }, + "node_modules/openid-client": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/openid-client/-/openid-client-5.6.0.tgz", + "integrity": "sha512-uFTkN/iqgKvSnmpVAS/T6SNThukRMBcmymTQ71Ngus1F60tdtKVap7zCrleocY+fogPtpmoxi5Q1YdrgYuTlkA==", + "dependencies": { + "jose": "^4.15.1", + "lru-cache": "^6.0.0", + "object-hash": "^2.2.0", + "oidc-token-hash": "^5.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/panva" + } + }, + "node_modules/openid-client/node_modules/object-hash": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-2.2.0.tgz", + "integrity": "sha512-gScRMn0bS5fH+IuwyIFgnh9zBdo4DV+6GhygmWM9HyNJSgS0hScp1f5vjtm7oIIOiT9trXrShAkLFSc2IqKNgw==", + "engines": { + "node": ">= 6" + } + }, "node_modules/optionator": { "version": "0.9.3", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz", @@ -3200,7 +3261,6 @@ "version": "8.4.31", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz", "integrity": "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==", - "dev": true, "funding": [ { "type": "opencollective", @@ -3327,6 +3387,26 @@ "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", "dev": true }, + "node_modules/preact": { + "version": "10.18.1", + "resolved": "https://registry.npmjs.org/preact/-/preact-10.18.1.tgz", + "integrity": "sha512-mKUD7RRkQQM6s7Rkmi7IFkoEHjuFqRQUaXamO61E6Nn7vqF/bo7EZCmSyrUnp2UWHw0O7XjZ2eeXis+m7tf4lg==", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/preact" + } + }, + "node_modules/preact-render-to-string": { + "version": "5.2.6", + "resolved": "https://registry.npmjs.org/preact-render-to-string/-/preact-render-to-string-5.2.6.tgz", + "integrity": "sha512-JyhErpYOvBV1hEPwIxc/fHWXPfnEGdRKxc8gFdAZ7XV4tlzyzG847XAyEZqoDnynP88akM4eaHcSOzNcLWFguw==", + "dependencies": { + "pretty-format": "^3.8.0" + }, + "peerDependencies": { + "preact": ">=10" + } + }, "node_modules/prelude-ls": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", @@ -3336,6 +3416,11 @@ "node": ">= 0.8.0" } }, + "node_modules/pretty-format": { + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-3.8.0.tgz", + "integrity": "sha512-WuxUnVtlWL1OfZFQFuqvnvs6MiAGk9UNsBostyBOB0Is9wb5uRESevA6rnl/rkksXaGX3GzZhPup5d6Vp1nFew==" + }, "node_modules/prop-types": { "version": "15.8.1", "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", @@ -3449,8 +3534,7 @@ "node_modules/regenerator-runtime": { "version": "0.14.0", "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.0.tgz", - "integrity": "sha512-srw17NI0TUWHuGa5CFGGmhfNIeja30WMBfbslPNhf6JrqQlLN5gcrvig1oqPxiVaXb0oW0XRKtH6Nngs5lKCIA==", - "dev": true + "integrity": "sha512-srw17NI0TUWHuGa5CFGGmhfNIeja30WMBfbslPNhf6JrqQlLN5gcrvig1oqPxiVaXb0oW0XRKtH6Nngs5lKCIA==" }, "node_modules/regexp.prototype.flags": { "version": "1.5.1", @@ -4150,6 +4234,14 @@ "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", "dev": true }, + "node_modules/uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "bin": { + "uuid": "dist/bin/uuid" + } + }, "node_modules/watchpack": { "version": "2.4.0", "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.0.tgz", @@ -4262,8 +4354,7 @@ "node_modules/yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" }, "node_modules/yaml": { "version": "2.3.2", @@ -4285,14 +4376,6 @@ "funding": { "url": "https://github.com/sponsors/sindresorhus" } - }, - "node_modules/zod": { - "version": "3.21.4", - "resolved": "https://registry.npmjs.org/zod/-/zod-3.21.4.tgz", - "integrity": "sha512-m46AKbrzKVzOzs/DZgVnG5H55N1sv1M8qZU3A8RIKbs3mrACDNeIOeilDymVb2HdmP8uwshOCF4uJ8uM9rCqJw==", - "funding": { - "url": "https://github.com/sponsors/colinhacks" - } } } } diff --git a/client/package.json b/client/package.json index eb04ea2..e1ca84c 100644 --- a/client/package.json +++ b/client/package.json @@ -9,15 +9,16 @@ "lint": "next lint" }, "dependencies": { - "react": "latest", - "react-dom": "latest", - "next": "latest" + "next": "^13.5.4", + "next-auth": "^4.23.2", + "react": "^18.2.0", + "react-dom": "latest" }, "devDependencies": { "autoprefixer": "latest", - "postcss": "latest", - "tailwindcss": "latest", "eslint": "latest", - "eslint-config-next": "latest" + "eslint-config-next": "latest", + "postcss": "latest", + "tailwindcss": "latest" } } diff --git a/client/pages/_app.js b/client/pages/_app.js index 2300201..3d7e765 100644 --- a/client/pages/_app.js +++ b/client/pages/_app.js @@ -1,5 +1,10 @@ import '@/styles/globals.css' +import {SessionProvider} from 'next-auth/react' -export default function App({ Component, pageProps }) { - return +export default function App({ Component, pageProps, session}) { + return ( + + + + ) } diff --git a/client/pages/account.jsx b/client/pages/account.jsx new file mode 100644 index 0000000..e11e662 --- /dev/null +++ b/client/pages/account.jsx @@ -0,0 +1,37 @@ +import React from 'react' +import { UseSession, getSession, signOut, useSession} from 'next-auth/react' + +const account = () => { + const {data: session, status} = useSession(); + + if (status === 'authenticated') { + return ( +
+

Welcome, {session.user.name}

+ +
+ ); + } else { + return ( +
+

You are not signed in.

+
+ ) + } +} + +export default account + +export const getServerSideProps = async (context) => { + const session = await getSession(context) + if (!session) { + return { + redirect: { + destination: '/login' + } + } + } + return { + props: {session}, + } +} \ No newline at end of file diff --git a/client/pages/api/auth/[...nextauth].js b/client/pages/api/auth/[...nextauth].js new file mode 100644 index 0000000..712f622 --- /dev/null +++ b/client/pages/api/auth/[...nextauth].js @@ -0,0 +1,13 @@ +import NextAuth from 'next-auth/next'; +import GoogleProvider from 'next-auth/providers/google'; + + +export default NextAuth({ + providers: [ + GoogleProvider({ + clientId: process.env.GOOGLE_CLIENT_ID, + clientSecret: process.env.GOOGLE_CLIENT_SECRET + }), + ], + secret: process.env.JWT_SECRET +}) \ No newline at end of file diff --git a/client/pages/login.jsx b/client/pages/login.jsx new file mode 100644 index 0000000..ab9b88f --- /dev/null +++ b/client/pages/login.jsx @@ -0,0 +1,26 @@ +import React from 'react' +import {useSession, signIn, signOut} from 'next-auth/react' + + +const login = () => { + const {data: session} = useSession(); + console.log(session); + if (session){ + return ( +
+

Welcome, {session.user.name}

+ Profile Picture + +
+ ) + } else { + return ( +
+

You are not signed in, bro

+ +
+ ) + } +} + +export default login \ No newline at end of file From 42c0e975ddada590b1179a1e610f3aa9ef09a8db Mon Sep 17 00:00:00 2001 From: Mohamed Hamouda Date: Sat, 28 Oct 2023 21:49:56 -0700 Subject: [PATCH 3/5] done with authentication, getting acces to users calendar and personal info, and displaying the next 10 events. Next, create events --- client/pages/_app.js | 11 +- client/pages/account.jsx | 37 ----- client/pages/api/auth/[...nextauth].js | 13 -- client/pages/index.js | 68 ++++++--- client/pages/login.jsx | 26 ---- client/styles/globals.css | 35 +++++ server/.env | 2 + .../2029240f6d1128be89ddc32729463129 | Bin 0 -> 9 bytes .../ceb926795b3aee31e24faffd5df9f47e | Bin 0 -> 735 bytes server/server.py | 137 ++++++++++++++++-- 10 files changed, 212 insertions(+), 117 deletions(-) delete mode 100644 client/pages/account.jsx delete mode 100644 client/pages/api/auth/[...nextauth].js delete mode 100644 client/pages/login.jsx create mode 100644 server/.env create mode 100644 server/.flask_session/2029240f6d1128be89ddc32729463129 create mode 100644 server/.flask_session/ceb926795b3aee31e24faffd5df9f47e diff --git a/client/pages/_app.js b/client/pages/_app.js index 3d7e765..19eaa91 100644 --- a/client/pages/_app.js +++ b/client/pages/_app.js @@ -1,10 +1,5 @@ import '@/styles/globals.css' -import {SessionProvider} from 'next-auth/react' -export default function App({ Component, pageProps, session}) { - return ( - - - - ) -} +export default function App({ Component, pageProps }) { + return +} \ No newline at end of file diff --git a/client/pages/account.jsx b/client/pages/account.jsx deleted file mode 100644 index e11e662..0000000 --- a/client/pages/account.jsx +++ /dev/null @@ -1,37 +0,0 @@ -import React from 'react' -import { UseSession, getSession, signOut, useSession} from 'next-auth/react' - -const account = () => { - const {data: session, status} = useSession(); - - if (status === 'authenticated') { - return ( -
-

Welcome, {session.user.name}

- -
- ); - } else { - return ( -
-

You are not signed in.

-
- ) - } -} - -export default account - -export const getServerSideProps = async (context) => { - const session = await getSession(context) - if (!session) { - return { - redirect: { - destination: '/login' - } - } - } - return { - props: {session}, - } -} \ No newline at end of file diff --git a/client/pages/api/auth/[...nextauth].js b/client/pages/api/auth/[...nextauth].js deleted file mode 100644 index 712f622..0000000 --- a/client/pages/api/auth/[...nextauth].js +++ /dev/null @@ -1,13 +0,0 @@ -import NextAuth from 'next-auth/next'; -import GoogleProvider from 'next-auth/providers/google'; - - -export default NextAuth({ - providers: [ - GoogleProvider({ - clientId: process.env.GOOGLE_CLIENT_ID, - clientSecret: process.env.GOOGLE_CLIENT_SECRET - }), - ], - secret: process.env.JWT_SECRET -}) \ No newline at end of file diff --git a/client/pages/index.js b/client/pages/index.js index 0d1c7a6..a66c9f4 100644 --- a/client/pages/index.js +++ b/client/pages/index.js @@ -2,30 +2,56 @@ import React, { useEffect, useState } from "react"; function index() { - const [message, setMessage] = useState("Loading"); // set state variable - const [people, setPeople] = useState([]); // make array for 'people' from server.py - - useEffect(() => { // allows us to create side effects in functional components - fetch("http://localhost:8080/api/home") - .then( // calls the endpoint - (response) => response.json() // get response from api, put into json - ).then( - (data) => { // retrieve data - console.log(data); // so we can check console.log and see that we - // are getting the api endpoint data - // message initially set to loading in line 5 - setMessage(data.message); // once we get data, set message state variable to data - setPeople(data.people); // accessing people variable from backend - }); - }, []); + const [userInfo, setUserInfo] = useState(null); + const [events, setEvents] = useState([]); + + + useEffect(() => { + fetch('http://localhost:8080/user_info', {credentials: 'include'}) + .then(response => response.json()) + .then(data => { + console.log(data); + setUserInfo(data); + }); + + fetch('http://localhost:8080/events', {credentials: 'include'}) + .then(response => response.json()) + .then(data => { + console.log(data); + setEvents(data); + }); +}, []); return(
-
{message}
- - {people.map((person, index) => ( // grabs person in people array by index and displays -
{person}
- ))} + + + + {userInfo && ( +
+

User Information

+

Name: {userInfo.name}

+ User profile +
+ )} + + {events.length > 0 && ( +
+

10 Upcoming Events

+
    + {events.map(event => ( +
  • + {event.summary} - {new Date(event.start.dateTime || event.start.date).toLocaleString()} +
  • + ))} +
+
+ )} +
); } diff --git a/client/pages/login.jsx b/client/pages/login.jsx deleted file mode 100644 index ab9b88f..0000000 --- a/client/pages/login.jsx +++ /dev/null @@ -1,26 +0,0 @@ -import React from 'react' -import {useSession, signIn, signOut} from 'next-auth/react' - - -const login = () => { - const {data: session} = useSession(); - console.log(session); - if (session){ - return ( -
-

Welcome, {session.user.name}

- Profile Picture - -
- ) - } else { - return ( -
-

You are not signed in, bro

- -
- ) - } -} - -export default login \ No newline at end of file diff --git a/client/styles/globals.css b/client/styles/globals.css index b5c61c9..4fd4a8a 100644 --- a/client/styles/globals.css +++ b/client/styles/globals.css @@ -1,3 +1,38 @@ @tailwind base; @tailwind components; @tailwind utilities; + +/* Base button styling */ +.button { + display: inline-block; + padding: 10px 20px; + font-size: 16px; + font-weight: 600; + border: none; + border-radius: 5px; + background-color: #007BFF; /* Default blue color */ + color: #FFFFFF; /* White text color */ + cursor: pointer; + text-align: center; + text-decoration: none; + transition: background-color 0.3s ease, transform 0.3s ease; +} + +/* Hover effect for the button */ +.button:hover { + background-color: #0056b3; /* Slightly darker blue on hover */ + transform: scale(1.05); /* Slightly enlarge the button on hover */ +} + +/* Active state (when button is clicked) */ +.button:active { + background-color: #004499; /* Even darker blue on active state */ + transform: scale(0.95); /* Slightly reduce the button size when clicked */ +} + +/* Optional: If you want a different style for a disabled button */ +.button:disabled { + background-color: #CCCCCC; /* Grayish background for disabled button */ + color: #888888; /* Grayish text color for disabled button */ + cursor: not-allowed; +} diff --git a/server/.env b/server/.env new file mode 100644 index 0000000..73d322b --- /dev/null +++ b/server/.env @@ -0,0 +1,2 @@ +CLIENT_ID=757306875568-76c8a3tmj1hhousioaa6a2587rq2tjir.apps.googleusercontent.com +CLIENT_SECRET=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 \ No newline at end of file diff --git a/server/.flask_session/2029240f6d1128be89ddc32729463129 b/server/.flask_session/2029240f6d1128be89ddc32729463129 new file mode 100644 index 0000000000000000000000000000000000000000..7f5741f13017ee705ea34021d222a06a6ee2a6c9 GIT binary patch literal 9 QcmZQzU|?uq^=8ro00XcA0RR91 literal 0 HcmV?d00001 diff --git a/server/.flask_session/ceb926795b3aee31e24faffd5df9f47e b/server/.flask_session/ceb926795b3aee31e24faffd5df9f47e new file mode 100644 index 0000000000000000000000000000000000000000..16a9f78cd68afadcd1e68cd2e4f5f0a2e3fc826d GIT binary patch literal 735 zcmaiy(TN~&^CzHkUYbkSlo9&YPGt{NH+T_9eJba^w1#D zOdn2H+j+!V;c0G8igwmf{O!tbt$K!odJAtx@_ZEI6fBg$GiQ$~8j0}&;9}G21lCp> zpL!~14WKPIM`%P#TlYq;{@iy56VnOCnK9zCM3lrQI8S_f*c~0xpSDUMs$yMzq9~+@ z#r_pG5(NP$qIZ}}lC38eItxDN&$@2vOLtrj8pF;5)mZ-}SOZOJdD5f@`ZQM{$+S&+ zN?mJn@H3#UcZ&$1$CCjpbs);AynE4$xqV!hmL6_Ht*&k_j($OLU44l;&)HW&fI&ct zjI(A$NR*&vKvIDS1QtA&glojxAi?K5`FK-TmfBWjplE8lt!NEZ2{b74bSuU&DHtXY zDo|=`D&0$bi)j<)`I~gX5DiGi&q}W@=S^H?89F}#udC0dW4KR?M(WJQuuKe3d0>a> zVLId!%bqiHF~DJ6eP98}5v#wQU+w;lqAbfR0L(GFK)ezN0ZdS~fwZo`|5{(;;VdN0 NoRSbHs76K6{0G6S1A_nn literal 0 HcmV?d00001 diff --git a/server/server.py b/server/server.py index 8ebea6a..e461613 100644 --- a/server/server.py +++ b/server/server.py @@ -1,18 +1,131 @@ # write flask code in python here -from flask import Flask, jsonify +from flask import Flask, redirect, request, jsonify, session, make_response from flask_cors import CORS +from google.oauth2.credentials import Credentials +from google_auth_oauthlib.flow import Flow +from googleapiclient.discovery import build +from flask_session import Session +from datetime import datetime +from dotenv import load_dotenv +import os +os.environ['OAUTHLIB_INSECURE_TRANSPORT'] = '1' + +load_dotenv() app = Flask(__name__) -CORS(app) - -# make api requests -@app.route("/api/home", methods=['GET']) -def return_home(): - return jsonify({ - 'message': "P-reset starter page!", - 'people': ['Sumi', 'Vivien', 'Haram', 'Tara' - 'Angie', 'Abrar', 'Mohamed', 'Grace', - 'Sadhvi', 'Erin'] - }) +CORS(app, origins=["http://localhost:3000"], supports_credentials=True) +app.config['SESSION_COOKIE_SECURE'] = False +app.config['SESSION_COOKIE_SAMESITE'] = 'None' + +# Configure session to use filesystem +app.config['SESSION_TYPE'] = 'filesystem' +app.config['SESSION_FILE_DIR'] = './.flask_session/' +app.config['SESSION_PERMANENT'] = False +app.config['SESSION_COOKIE_NAME'] = 'session' + +Session(app) + +app.secret_key = 'c085ce0c5c21a4d774591a20b981013e' + +CLIENT_ID = os.environ.get('CLIENT_ID', '00000') +CLIENT_SECRET = os.environ.get('CLIENT_SECRET', '00000') +REDIRECT_URI = 'http://localhost:8080/google/callback' + + +@app.route('/google/login', methods=['GET']) +def google_login(): + flow = Flow.from_client_config( + { + "web": { + "client_id": CLIENT_ID, + "client_secret": CLIENT_SECRET, + "redirect_uris": [REDIRECT_URI], + "auth_uri": "https://accounts.google.com/o/oauth2/auth", + "token_uri": "https://accounts.google.com/o/oauth2/token", + } + }, + scopes=["https://www.googleapis.com/auth/calendar", "https://www.googleapis.com/auth/userinfo.profile"], + ) + + flow.redirect_uri = REDIRECT_URI + authorization_url, state = flow.authorization_url(prompt='consent', access_type='offline') + session['state'] = state + return redirect(authorization_url) + +@app.route('/google/callback') +def google_callback(): + state = session['state'] + flow = Flow.from_client_config( + { + "web": { + "client_id": CLIENT_ID, + "client_secret": CLIENT_SECRET, + "redirect_uris": [REDIRECT_URI], + "auth_uri": "https://accounts.google.com/o/oauth2/auth", + "token_uri": "https://accounts.google.com/o/oauth2/token", + } + }, + state=state, + scopes=["https://www.googleapis.com/auth/calendar", "https://www.googleapis.com/auth/userinfo.profile"], + ) + flow.redirect_uri = REDIRECT_URI + authorization_response = request.url + flow.fetch_token(authorization_response=authorization_response) + credentials = flow.credentials + + session['credentials'] = { + 'token': credentials.token, + 'refresh_token': credentials.refresh_token, + 'token_uri': credentials.token_uri, + 'client_id': credentials.client_id, + 'client_secret': credentials.client_secret, + 'scopes': credentials.scopes, + } + + return redirect('http://localhost:3000') + + +@app.route('/user_info') +def get_user_info(): + print(session) + credentials = session.get("credentials") + if not credentials: + return jsonify({"error": "Not authenticated"}), 401 + + creds = Credentials(**credentials) + service = build('oauth2', 'v2', credentials=creds) + print(credentials) + user_info = service.userinfo().get().execute() + + return jsonify(user_info) + +@app.route('/events', methods=['GET']) +def get_events(): + credentials = session.get('credentials') + if not credentials: + return jsonify({"error": "Not authenticated"}), 401 + + creds = Credentials(**credentials) + service = build('calendar', 'v3', credentials=creds) + + # Get the current time in RFC3339 format + now = datetime.utcnow().isoformat() + 'Z' + + events_result = service.events().list(calendarId='primary', timeMin=now, + maxResults=10, singleEvents=True, + orderBy='startTime').execute() + + + events = events_result.get('items', []) + + return jsonify(events) + + +@app.route('/logout', methods=['GET']) +def logout(): + session.pop('credentials', None) + return redirect('http://localhost:3000') + + if __name__ == "__main__": app.run(debug=True, port=8080) \ No newline at end of file From 9e3d21202e2ed483a5b78ea92fd3021ff04b7d8f Mon Sep 17 00:00:00 2001 From: Mohamed Hamouda Date: Sun, 29 Oct 2023 16:20:24 -0700 Subject: [PATCH 4/5] Done with creating an add event page with sufficient functionality --- client/package-lock.json | 14 ++-- client/package.json | 4 +- client/pages/add_event.jsx | 71 ++++++++++++++++++ client/pages/index.js | 11 +-- client/styles/globals.css | 44 +++++++++++ .../ceb926795b3aee31e24faffd5df9f47e | Bin 735 -> 735 bytes server/server.py | 19 ++++- 7 files changed, 146 insertions(+), 17 deletions(-) create mode 100644 client/pages/add_event.jsx diff --git a/client/package-lock.json b/client/package-lock.json index 4a06333..c34fcb9 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -17,8 +17,8 @@ "autoprefixer": "latest", "eslint": "latest", "eslint-config-next": "latest", - "postcss": "latest", - "tailwindcss": "latest" + "postcss": "^8.4.31", + "tailwindcss": "^3.3.5" } }, "node_modules/@aashutoshrathi/word-wrap": { @@ -3952,9 +3952,9 @@ } }, "node_modules/tailwindcss": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.3.3.tgz", - "integrity": "sha512-A0KgSkef7eE4Mf+nKJ83i75TMyq8HqY3qmFIJSWy8bNt0v1lG7jUcpGpoTFxAwYcWOphcTBLPPJg+bDfhDf52w==", + "version": "3.3.5", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.3.5.tgz", + "integrity": "sha512-5SEZU4J7pxZgSkv7FP1zY8i2TIAOooNZ1e/OGtxIEv6GltpoiXUqWvLy89+a10qYTB1N5Ifkuw9lqQkN9sscvA==", "dev": true, "dependencies": { "@alloc/quick-lru": "^5.2.0", @@ -3962,10 +3962,10 @@ "chokidar": "^3.5.3", "didyoumean": "^1.2.2", "dlv": "^1.1.3", - "fast-glob": "^3.2.12", + "fast-glob": "^3.3.0", "glob-parent": "^6.0.2", "is-glob": "^4.0.3", - "jiti": "^1.18.2", + "jiti": "^1.19.1", "lilconfig": "^2.1.0", "micromatch": "^4.0.5", "normalize-path": "^3.0.0", diff --git a/client/package.json b/client/package.json index e1ca84c..2957ff1 100644 --- a/client/package.json +++ b/client/package.json @@ -18,7 +18,7 @@ "autoprefixer": "latest", "eslint": "latest", "eslint-config-next": "latest", - "postcss": "latest", - "tailwindcss": "latest" + "postcss": "^8.4.31", + "tailwindcss": "^3.3.5" } } diff --git a/client/pages/add_event.jsx b/client/pages/add_event.jsx new file mode 100644 index 0000000..cdfc550 --- /dev/null +++ b/client/pages/add_event.jsx @@ -0,0 +1,71 @@ +// add_event.jsx + +import React, { useState } from "react"; + +function AddEvent() { + const [title, setTitle] = useState(""); + const [description, setDescription] = useState(""); + const [startDate, setStartDate] = useState(""); + const [endDate, setEndDate] = useState(""); + + const fullStartDate = `${startDate}:00`; + const fullEndDate = `${endDate}:00`; + + const handleSubmit = async () => { + const eventBody = { + summary: title, + description: description, + start: { dateTime: fullStartDate, timeZone: "America/Los_Angeles" }, // Adjust timeZone as needed + end: { dateTime: fullEndDate, timeZone: "America/Los_Angeles" } + }; + + try { + console.log(eventBody); + const response = await fetch("http://localhost:8080/add_event", { + method: "POST", + headers: { + "Content-Type": "application/json" + }, + body: JSON.stringify(eventBody), + credentials: 'include' + }); + + if (response.ok) { + alert("Event added successfully!"); + window.location.href = "http://localhost:3000"; // Redirect to homepage + } else { + alert("Failed to add event. Please try again."); + } + } catch (error) { + console.error("Error adding event:", error); + } + }; + + return ( +
+ + +

Add Event

+
+

+ setTitle(e.target.value)} /> +
+
+

+