diff --git a/backend/danswer/configs/app_configs.py b/backend/danswer/configs/app_configs.py index df2151a29..1c0efb7c3 100644 --- a/backend/danswer/configs/app_configs.py +++ b/backend/danswer/configs/app_configs.py @@ -13,6 +13,16 @@ APP_PORT = 8080 BLURB_LENGTH = 200 # Characters. Blurbs will be truncated at the first punctuation after this many characters. +##### +# Web Configs +##### +# WEB_DOMAIN is used to set the redirect_uri when doing OAuth with Google +# TODO: investigate if this can be done cleaner by overwriting the redirect_uri +# on the frontend and just sending a dummy value (or completely generating the URL) +# on the frontend +WEB_DOMAIN = os.environ.get("WEB_DOMAIN", "http://localhost:3000") + + ##### # Vector DB Configs ##### diff --git a/backend/danswer/main.py b/backend/danswer/main.py index 7aa0e3973..19974f0f7 100644 --- a/backend/danswer/main.py +++ b/backend/danswer/main.py @@ -9,6 +9,7 @@ from danswer.auth.users import fastapi_users from danswer.auth.users import google_oauth_client from danswer.configs.app_configs import APP_HOST from danswer.configs.app_configs import APP_PORT +from danswer.configs.app_configs import WEB_DOMAIN from danswer.server.admin import router as admin_router from danswer.server.event_loading import router as event_processing_router from danswer.server.search_backend import router as backend_router @@ -69,7 +70,9 @@ def get_application() -> FastAPI: SECRET, associate_by_email=True, is_verified_by_default=True, - redirect_url="http://localhost:8080/test", # TODO DAN-39 set this to frontend redirect + # points the user back to the login page, where we will call the + # /auth/google/callback endpoint + redirect them to the main app + redirect_url=f"{WEB_DOMAIN}/auth/google/callback", ), prefix="/auth/google", tags=["auth"], diff --git a/backend/danswer/server/admin.py b/backend/danswer/server/admin.py index aa74425fc..d2166fb2d 100644 --- a/backend/danswer/server/admin.py +++ b/backend/danswer/server/admin.py @@ -1,7 +1,6 @@ from datetime import datetime from danswer.configs.constants import DocumentSource -from danswer.connectors.models import ConnectorDescriptor from danswer.connectors.models import InputType from danswer.connectors.slack.config import get_slack_config from danswer.connectors.slack.config import SlackConfig diff --git a/web/README.md b/web/README.md index 2845027e1..ae7903b0f 100644 --- a/web/README.md +++ b/web/README.md @@ -2,7 +2,10 @@ This is a [Next.js](https://nextjs.org/) project bootstrapped with [`create-next ## Getting Started -First, run the development server: +Install node / npm: https://docs.npmjs.com/downloading-and-installing-node-js-and-npm +Install all dependencies: `npm i` + +Then, run the development server: ```bash npm run dev @@ -13,20 +16,3 @@ pnpm dev ``` Open [http://localhost:3000](http://localhost:3000) with your browser to see the result. - -This project uses [`next/font`](https://nextjs.org/docs/basic-features/font-optimization) to automatically optimize and load Inter, a custom Google Font. - -## Learn More - -To learn more about Next.js, take a look at the following resources: - -- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API. -- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial. - -You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome! - -## Deploy on Vercel - -The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js. - -Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details. diff --git a/web/package-lock.json b/web/package-lock.json index 525340ba5..4a9e434b5 100644 --- a/web/package-lock.json +++ b/web/package-lock.json @@ -16,10 +16,10 @@ "eslint": "8.37.0", "eslint-config-next": "13.2.4", "formik": "^2.2.9", - "next": "13.2.4", + "next": "^13.2.4", "postcss": "^8.4.23", - "react": "18.2.0", - "react-dom": "18.2.0", + "react": "^18.2.0", + "react-dom": "^18.2.0", "swr": "^2.1.5", "tailwindcss": "^3.3.1", "typescript": "5.0.3", @@ -168,9 +168,9 @@ "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==" }, "node_modules/@next/env": { - "version": "13.2.4", - "resolved": "https://registry.npmjs.org/@next/env/-/env-13.2.4.tgz", - "integrity": "sha512-+Mq3TtpkeeKFZanPturjcXt+KHfKYnLlX6jMLyCrmpq6OOs4i1GqBOAauSkii9QeKCMTYzGppar21JU57b/GEA==" + "version": "13.4.1", + "resolved": "https://registry.npmjs.org/@next/env/-/env-13.4.1.tgz", + "integrity": "sha512-eD6WCBMFjLFooLM19SIhSkWBHtaFrZFfg2Cxnyl3vS3DAdFRfnx5TY2RxlkuKXdIRCC0ySbtK9JXXt8qLCqzZg==" }, "node_modules/@next/eslint-plugin-next": { "version": "13.2.4", @@ -180,40 +180,10 @@ "glob": "7.1.7" } }, - "node_modules/@next/swc-android-arm-eabi": { - "version": "13.2.4", - "resolved": "https://registry.npmjs.org/@next/swc-android-arm-eabi/-/swc-android-arm-eabi-13.2.4.tgz", - "integrity": "sha512-DWlalTSkLjDU11MY11jg17O1gGQzpRccM9Oes2yTqj2DpHndajrXHGxj9HGtJ+idq2k7ImUdJVWS2h2l/EDJOw==", - "cpu": [ - "arm" - ], - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@next/swc-android-arm64": { - "version": "13.2.4", - "resolved": "https://registry.npmjs.org/@next/swc-android-arm64/-/swc-android-arm64-13.2.4.tgz", - "integrity": "sha512-sRavmUImUCf332Gy+PjIfLkMhiRX1Ez4SI+3vFDRs1N5eXp+uNzjFUK/oLMMOzk6KFSkbiK/3Wt8+dHQR/flNg==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">= 10" - } - }, "node_modules/@next/swc-darwin-arm64": { - "version": "13.2.4", - "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-13.2.4.tgz", - "integrity": "sha512-S6vBl+OrInP47TM3LlYx65betocKUUlTZDDKzTiRDbsRESeyIkBtZ6Qi5uT2zQs4imqllJznVjFd1bXLx3Aa6A==", + "version": "13.4.1", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-13.4.1.tgz", + "integrity": "sha512-eF8ARHtYfnoYtDa6xFHriUKA/Mfj/cCbmKb3NofeKhMccs65G6/loZ15a6wYCCx4rPAd6x4t1WmVYtri7EdeBg==", "cpu": [ "arm64" ], @@ -226,9 +196,9 @@ } }, "node_modules/@next/swc-darwin-x64": { - "version": "13.2.4", - "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-13.2.4.tgz", - "integrity": "sha512-a6LBuoYGcFOPGd4o8TPo7wmv5FnMr+Prz+vYHopEDuhDoMSHOnC+v+Ab4D7F0NMZkvQjEJQdJS3rqgFhlZmKlw==", + "version": "13.4.1", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-13.4.1.tgz", + "integrity": "sha512-7cmDgF9tGWTgn5Gw+vP17miJbH4wcraMHDCOHTYWkO/VeKT73dUWG23TNRLfgtCNSPgH4V5B4uLHoZTanx9bAw==", "cpu": [ "x64" ], @@ -240,40 +210,10 @@ "node": ">= 10" } }, - "node_modules/@next/swc-freebsd-x64": { - "version": "13.2.4", - "resolved": "https://registry.npmjs.org/@next/swc-freebsd-x64/-/swc-freebsd-x64-13.2.4.tgz", - "integrity": "sha512-kkbzKVZGPaXRBPisoAQkh3xh22r+TD+5HwoC5bOkALraJ0dsOQgSMAvzMXKsN3tMzJUPS0tjtRf1cTzrQ0I5vQ==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@next/swc-linux-arm-gnueabihf": { - "version": "13.2.4", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm-gnueabihf/-/swc-linux-arm-gnueabihf-13.2.4.tgz", - "integrity": "sha512-7qA1++UY0fjprqtjBZaOA6cas/7GekpjVsZn/0uHvquuITFCdKGFCsKNBx3S0Rpxmx6WYo0GcmhNRM9ru08BGg==", - "cpu": [ - "arm" - ], - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, "node_modules/@next/swc-linux-arm64-gnu": { - "version": "13.2.4", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-13.2.4.tgz", - "integrity": "sha512-xzYZdAeq883MwXgcwc72hqo/F/dwUxCukpDOkx/j1HTq/J0wJthMGjinN9wH5bPR98Mfeh1MZJ91WWPnZOedOg==", + "version": "13.4.1", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-13.4.1.tgz", + "integrity": "sha512-qwJqmCri2ie8aTtE5gjTSr8S6O8B67KCYgVZhv9gKH44yvc/zXbAY8u23QGULsYOyh1islWE5sWfQNLOj9iryg==", "cpu": [ "arm64" ], @@ -286,9 +226,9 @@ } }, "node_modules/@next/swc-linux-arm64-musl": { - "version": "13.2.4", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-13.2.4.tgz", - "integrity": "sha512-8rXr3WfmqSiYkb71qzuDP6I6R2T2tpkmf83elDN8z783N9nvTJf2E7eLx86wu2OJCi4T05nuxCsh4IOU3LQ5xw==", + "version": "13.4.1", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-13.4.1.tgz", + "integrity": "sha512-qcC54tWNGDv/VVIFkazxhqH1Bnagjfs4enzELVRlUOoJPD2BGJTPI7z08pQPbbgxLtRiu8gl2mXvpB8WlOkMeA==", "cpu": [ "arm64" ], @@ -301,9 +241,9 @@ } }, "node_modules/@next/swc-linux-x64-gnu": { - "version": "13.2.4", - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-13.2.4.tgz", - "integrity": "sha512-Ngxh51zGSlYJ4EfpKG4LI6WfquulNdtmHg1yuOYlaAr33KyPJp4HeN/tivBnAHcZkoNy0hh/SbwDyCnz5PFJQQ==", + "version": "13.4.1", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-13.4.1.tgz", + "integrity": "sha512-9TeWFlpLsBosZ+tsm/rWBaMwt5It9tPH8m3nawZqFUUrZyGRfGcI67js774vtx0k3rL9qbyY6+3pw9BCVpaYUA==", "cpu": [ "x64" ], @@ -316,9 +256,9 @@ } }, "node_modules/@next/swc-linux-x64-musl": { - "version": "13.2.4", - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-13.2.4.tgz", - "integrity": "sha512-gOvwIYoSxd+j14LOcvJr+ekd9fwYT1RyMAHOp7znA10+l40wkFiMONPLWiZuHxfRk+Dy7YdNdDh3ImumvL6VwA==", + "version": "13.4.1", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-13.4.1.tgz", + "integrity": "sha512-sNDGaWmSqTS4QRUzw61wl4mVPeSqNIr1OOjLlQTRuyInxMxtqImRqdvzDvFTlDfdeUMU/DZhWGYoHrXLlZXe6A==", "cpu": [ "x64" ], @@ -331,9 +271,9 @@ } }, "node_modules/@next/swc-win32-arm64-msvc": { - "version": "13.2.4", - "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-13.2.4.tgz", - "integrity": "sha512-q3NJzcfClgBm4HvdcnoEncmztxrA5GXqKeiZ/hADvC56pwNALt3ngDC6t6qr1YW9V/EPDxCYeaX4zYxHciW4Dw==", + "version": "13.4.1", + "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-13.4.1.tgz", + "integrity": "sha512-+CXZC7u1iXdLRudecoUYbhbsXpglYv8KFYsFxKBPn7kg+bk7eJo738wAA4jXIl8grTF2mPdmO93JOQym+BlYGA==", "cpu": [ "arm64" ], @@ -346,9 +286,9 @@ } }, "node_modules/@next/swc-win32-ia32-msvc": { - "version": "13.2.4", - "resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-13.2.4.tgz", - "integrity": "sha512-/eZ5ncmHUYtD2fc6EUmAIZlAJnVT2YmxDsKs1Ourx0ttTtvtma/WKlMV5NoUsyOez0f9ExLyOpeCoz5aj+MPXw==", + "version": "13.4.1", + "resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-13.4.1.tgz", + "integrity": "sha512-vIoXVVc7UYO68VwVMDKwJC2+HqAZQtCYiVlApyKEeIPIQpz2gpufzGxk1z3/gwrJt/kJ5CDZjlhYDCzd3hdz+g==", "cpu": [ "ia32" ], @@ -361,9 +301,9 @@ } }, "node_modules/@next/swc-win32-x64-msvc": { - "version": "13.2.4", - "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-13.2.4.tgz", - "integrity": "sha512-0MffFmyv7tBLlji01qc0IaPP/LVExzvj7/R5x1Jph1bTAIj4Vu81yFQWHHQAP6r4ff9Ukj1mBK6MDNVXm7Tcvw==", + "version": "13.4.1", + "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-13.4.1.tgz", + "integrity": "sha512-n8V5ImLQZibKTu10UUdI3nIeTLkliEXe628qxqW9v8My3BAH2a7H0SaCqkV2OgqFnn8sG1wxKYw9/SNJ632kSA==", "cpu": [ "x64" ], @@ -444,9 +384,9 @@ "integrity": "sha512-sXo/qW2/pAcmT43VoRKOJbDOfV3cYpq3szSVfIThQXNt+E4DfKj361vaAt3c88U5tPUxzEswam7GW48PJqtKAg==" }, "node_modules/@swc/helpers": { - "version": "0.4.14", - "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.4.14.tgz", - "integrity": "sha512-4C7nX/dvpzB7za4Ql9K81xK3HPxCpHMgwTZVyf+9JQ6VUbn9jjZVN7/Nkdz/Ugzs2CSjqnL/UPXroiVBVHUWUw==", + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.1.tgz", + "integrity": "sha512-sJ902EfIzn1Fa+qYmjdQqh8tPsoxyBz+8yBKC2HKUxyezKJFwPGOn7pv4WY6QuQW//ySQi5lJjA/ZT9sNWWNTg==", "dependencies": { "tslib": "^2.4.0" } @@ -884,6 +824,17 @@ "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" } }, + "node_modules/busboy": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz", + "integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==", + "dependencies": { + "streamsearch": "^1.1.0" + }, + "engines": { + "node": ">=10.16.0" + } + }, "node_modules/call-bind": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", @@ -2755,39 +2706,37 @@ "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==" }, "node_modules/next": { - "version": "13.2.4", - "resolved": "https://registry.npmjs.org/next/-/next-13.2.4.tgz", - "integrity": "sha512-g1I30317cThkEpvzfXujf0O4wtaQHtDCLhlivwlTJ885Ld+eOgcz7r3TGQzeU+cSRoNHtD8tsJgzxVdYojFssw==", + "version": "13.4.1", + "resolved": "https://registry.npmjs.org/next/-/next-13.4.1.tgz", + "integrity": "sha512-JBw2kAIyhKDpjhEWvNVoFeIzNp9xNxg8wrthDOtMctfn3EpqGCmW0FSviNyGgOSOSn6zDaX48pmvbdf6X2W9xA==", "dependencies": { - "@next/env": "13.2.4", - "@swc/helpers": "0.4.14", + "@next/env": "13.4.1", + "@swc/helpers": "0.5.1", + "busboy": "1.6.0", "caniuse-lite": "^1.0.30001406", "postcss": "8.4.14", - "styled-jsx": "5.1.1" + "styled-jsx": "5.1.1", + "zod": "3.21.4" }, "bin": { "next": "dist/bin/next" }, "engines": { - "node": ">=14.6.0" + "node": ">=16.8.0" }, "optionalDependencies": { - "@next/swc-android-arm-eabi": "13.2.4", - "@next/swc-android-arm64": "13.2.4", - "@next/swc-darwin-arm64": "13.2.4", - "@next/swc-darwin-x64": "13.2.4", - "@next/swc-freebsd-x64": "13.2.4", - "@next/swc-linux-arm-gnueabihf": "13.2.4", - "@next/swc-linux-arm64-gnu": "13.2.4", - "@next/swc-linux-arm64-musl": "13.2.4", - "@next/swc-linux-x64-gnu": "13.2.4", - "@next/swc-linux-x64-musl": "13.2.4", - "@next/swc-win32-arm64-msvc": "13.2.4", - "@next/swc-win32-ia32-msvc": "13.2.4", - "@next/swc-win32-x64-msvc": "13.2.4" + "@next/swc-darwin-arm64": "13.4.1", + "@next/swc-darwin-x64": "13.4.1", + "@next/swc-linux-arm64-gnu": "13.4.1", + "@next/swc-linux-arm64-musl": "13.4.1", + "@next/swc-linux-x64-gnu": "13.4.1", + "@next/swc-linux-x64-musl": "13.4.1", + "@next/swc-win32-arm64-msvc": "13.4.1", + "@next/swc-win32-ia32-msvc": "13.4.1", + "@next/swc-win32-x64-msvc": "13.4.1" }, "peerDependencies": { - "@opentelemetry/api": "^1.4.0", + "@opentelemetry/api": "^1.1.0", "fibers": ">= 3.1.0", "node-sass": "^6.0.0 || ^7.0.0", "react": "^18.2.0", @@ -3515,6 +3464,14 @@ "node": ">= 0.4" } }, + "node_modules/streamsearch": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz", + "integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==", + "engines": { + "node": ">=10.0.0" + } + }, "node_modules/string.prototype.matchall": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.8.tgz", @@ -4122,6 +4079,14 @@ "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/web/package.json b/web/package.json index 699dfed03..aa6da4d05 100644 --- a/web/package.json +++ b/web/package.json @@ -17,10 +17,10 @@ "eslint": "8.37.0", "eslint-config-next": "13.2.4", "formik": "^2.2.9", - "next": "13.2.4", + "next": "^13.2.4", "postcss": "^8.4.23", - "react": "18.2.0", - "react-dom": "18.2.0", + "react": "^18.2.0", + "react-dom": "^18.2.0", "swr": "^2.1.5", "tailwindcss": "^3.3.1", "typescript": "5.0.3", diff --git a/web/src/app/auth/error/page.tsx b/web/src/app/auth/error/page.tsx new file mode 100644 index 000000000..16d33f49c --- /dev/null +++ b/web/src/app/auth/error/page.tsx @@ -0,0 +1,7 @@ +const Page = () => { + return ( +
Unable to login, please try again and/or contact an administrator
+ ); +}; + +export default Page; diff --git a/web/src/app/auth/google/callback/route.ts b/web/src/app/auth/google/callback/route.ts new file mode 100644 index 000000000..61dcc01df --- /dev/null +++ b/web/src/app/auth/google/callback/route.ts @@ -0,0 +1,20 @@ +import { buildUrl } from "@/lib/userSS"; +import { NextRequest, NextResponse } from "next/server"; + +export const GET = async (request: NextRequest) => { + // Wrapper around the FastAPI endpoint /auth/google/callback, + // which adds back a redirect to the main app. + const url = new URL(buildUrl("/auth/google/callback")); + url.search = request.nextUrl.search; + + const response = await fetch(url.toString()); + const setCookieHeader = response.headers.get("set-cookie"); + + if (!setCookieHeader) { + return NextResponse.redirect(new URL("/auth/error", request.url)); + } + + const redirectResponse = NextResponse.redirect(new URL("/", request.url)); + redirectResponse.headers.set("set-cookie", setCookieHeader); + return redirectResponse; +}; diff --git a/web/src/app/auth/login/page.tsx b/web/src/app/auth/login/page.tsx new file mode 100644 index 000000000..a9761cfc9 --- /dev/null +++ b/web/src/app/auth/login/page.tsx @@ -0,0 +1,44 @@ +import { getGoogleOAuthUrlSS, getCurrentUserSS } from "@/lib/userSS"; +import { redirect } from "next/navigation"; + +const Page = async () => { + const [currentUser, authorizationUrl] = await Promise.all([ + getCurrentUserSS(), + getGoogleOAuthUrlSS(), + ]); + + // if user is already logged in, take them to the main app page + if (currentUser && currentUser.is_active && currentUser.is_verified) { + return redirect("/"); + } + + return ( +
+
+
+
+

+ danswer 💃 +

+
+
+ + Sign in with Google + +
+
+
+
+ ); +}; + +export default Page; diff --git a/web/src/app/layout.tsx b/web/src/app/layout.tsx index 2f1fe7efe..a51401447 100644 --- a/web/src/app/layout.tsx +++ b/web/src/app/layout.tsx @@ -19,7 +19,9 @@ export default function RootLayout({ }) { return ( - {children} + + {children} + ); } diff --git a/web/src/app/page.tsx b/web/src/app/page.tsx index e2d057c29..1fec5990d 100644 --- a/web/src/app/page.tsx +++ b/web/src/app/page.tsx @@ -1,9 +1,6 @@ -import { Inter } from "next/font/google"; import { SearchSection } from "@/components/SearchBar"; import { Header } from "@/components/Header"; -const inter = Inter({ subsets: ["latin"] }); - export default function Home() { return ( <> diff --git a/web/src/components/Header.tsx b/web/src/components/Header.tsx index 73f2b7f8e..545aab275 100644 --- a/web/src/components/Header.tsx +++ b/web/src/components/Header.tsx @@ -1,11 +1,34 @@ +"use client"; + +import { logout } from "@/lib/user"; +import { UserCircle } from "@phosphor-icons/react"; +import { useRouter } from "next/navigation"; import React from "react"; import "tailwindcss/tailwind.css"; export const Header: React.FC = () => { + const router = useRouter(); + return (
-
+

danswer 💃

+ +
+ logout().then((isSuccess) => { + if (!isSuccess) { + alert("Failed to logout"); + } + router.push("/auth/login"); + }) + } + > + {/* TODO: make this a dropdown with more options */} + + Logout +
); diff --git a/web/src/lib/types.ts b/web/src/lib/types.ts new file mode 100644 index 000000000..1edec2db1 --- /dev/null +++ b/web/src/lib/types.ts @@ -0,0 +1,8 @@ +export interface User { + id: string; + email: string; + is_active: string; + is_superuser: string; + is_verified: string; + role: string; +} diff --git a/web/src/lib/user.ts b/web/src/lib/user.ts new file mode 100644 index 000000000..cccd7c72e --- /dev/null +++ b/web/src/lib/user.ts @@ -0,0 +1,21 @@ +import { User } from "./types"; + +// should be used client-side only +export const getCurrentUser = async (): Promise => { + const response = await fetch("/api/users/me", { + credentials: "include", + }); + if (!response.ok) { + return null; + } + const user = await response.json(); + return user; +}; + +export const logout = async (): Promise => { + const response = await fetch("/api/auth/database/logout", { + method: "POST", + credentials: "include", + }); + return response.ok; +}; diff --git a/web/src/lib/userSS.ts b/web/src/lib/userSS.ts new file mode 100644 index 000000000..8245cf465 --- /dev/null +++ b/web/src/lib/userSS.ts @@ -0,0 +1,40 @@ +import { cookies } from "next/headers"; +import { User } from "./types"; + +const INTERNAL_AUTH_URL = + process.env.INTERNAL_AUTH_URL || "http://127.0.0.1:8080"; + +export const buildUrl = (path: string) => { + if (path.startsWith("/")) { + return `${INTERNAL_AUTH_URL}${path}`; + } + return `${INTERNAL_AUTH_URL}/${path}`; +}; + +export const getGoogleOAuthUrlSS = async (): Promise => { + const res = await fetch(buildUrl("/auth/google/authorize")); + if (!res.ok) { + throw new Error("Failed to fetch data"); + } + + const data: { authorization_url: string } = await res.json(); + return data.authorization_url; +}; + +// should be used server-side only +export const getCurrentUserSS = async (): Promise => { + const response = await fetch(buildUrl("/users/me"), { + credentials: "include", + headers: { + cookie: cookies() + .getAll() + .map((cookie) => `${cookie.name}=${cookie.value}`) + .join("; "), + }, + }); + if (!response.ok) { + return null; + } + const user = await response.json(); + return user; +};