From 72b8b39eb09d4dae9e6ad89be0a0619a4a81b0da Mon Sep 17 00:00:00 2001 From: Bulat Kurbanov Date: Sat, 11 Jan 2025 23:19:49 +0100 Subject: [PATCH] Add login page --- .gitignore | 2 + poetry.lock | 8 +- pyproject.toml | 2 +- src/modules/web_app/frontend/index.css | 16 ++++ src/modules/web_app/frontend/index.html | 20 +++++ src/modules/web_app/frontend/index.js | 97 +++++++++++++++++++++++++ src/modules/web_app/views/auth.py | 2 +- src/modules/web_app/views/streamer.py | 2 +- 8 files changed, 142 insertions(+), 7 deletions(-) create mode 100644 src/modules/web_app/frontend/index.css create mode 100644 src/modules/web_app/frontend/index.html create mode 100644 src/modules/web_app/frontend/index.js diff --git a/.gitignore b/.gitignore index abc591b..d2f262a 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,5 @@ venv .DS_Store + +.vscode diff --git a/poetry.lock b/poetry.lock index b21194e..df18141 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1059,13 +1059,13 @@ files = [ [[package]] name = "pydantic" -version = "2.10.4" +version = "2.10.5" description = "Data validation using Python type hints" optional = false python-versions = ">=3.8" files = [ - {file = "pydantic-2.10.4-py3-none-any.whl", hash = "sha256:597e135ea68be3a37552fb524bc7d0d66dcf93d395acd93a00682f1efcb8ee3d"}, - {file = "pydantic-2.10.4.tar.gz", hash = "sha256:82f12e9723da6de4fe2ba888b5971157b3be7ad914267dea8f05f82b28254f06"}, + {file = "pydantic-2.10.5-py3-none-any.whl", hash = "sha256:4dd4e322dbe55472cb7ca7e73f4b63574eecccf2835ffa2af9021ce113c83c53"}, + {file = "pydantic-2.10.5.tar.gz", hash = "sha256:278b38dbbaec562011d659ee05f63346951b3a248a6f3642e1bc68894ea2b4ff"}, ] [package.dependencies] @@ -1987,4 +1987,4 @@ type = ["pytest-mypy"] [metadata] lock-version = "2.0" python-versions = "^3.11" -content-hash = "54b7af11ca7015e9a96234a672549033d77151acbed7c12675b097ed498a681b" +content-hash = "bd44ab97afc7310e67c61b6a658180ed4592e01a06f95d645fb42c8e9a60b759" diff --git a/pyproject.toml b/pyproject.toml index 12eade5..f25716c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -10,7 +10,7 @@ packages = [{include = "discord_bot"}] python = "^3.11" discord-py = "^2.4.0" twitchapi = "^4.4.0" -pydantic = "^2.10.4" +pydantic = "^2.10.5" pydantic-settings = "^2.7.1" httpx = "^0.28.1" icalendar = "^6.1.0" diff --git a/src/modules/web_app/frontend/index.css b/src/modules/web_app/frontend/index.css new file mode 100644 index 0000000..b0cb12c --- /dev/null +++ b/src/modules/web_app/frontend/index.css @@ -0,0 +1,16 @@ +.authorize__container { + display: flex; + justify-content: center; + align-items: center; + height: 100%; +} + +a.authorize__twitch_btn { + display: inline-block; + background-color: #6441a5; + color: #fff; + padding: 10px 20px; + border-radius: 5px; + text-decoration: none; + font-size: 1.5rem; +} diff --git a/src/modules/web_app/frontend/index.html b/src/modules/web_app/frontend/index.html new file mode 100644 index 0000000..219606b --- /dev/null +++ b/src/modules/web_app/frontend/index.html @@ -0,0 +1,20 @@ + + + Web App + + + + + +
+ + + + diff --git a/src/modules/web_app/frontend/index.js b/src/modules/web_app/frontend/index.js new file mode 100644 index 0000000..933f4d1 --- /dev/null +++ b/src/modules/web_app/frontend/index.js @@ -0,0 +1,97 @@ +import { createApp, ref, onMounted } from 'vue'; +import { createRouter, createWebHistory, RouterView } from 'vue-router'; + + +const Authorize = { + setup() { + const loginLink = ref(null); + + onMounted(() => { + fetch('/api/auth/get_authorization_url/twitch/') + .then(response => response.json()) + .then(data => { + loginLink.value = data.authorization_url; + }) + }); + + return { + loginLink + } + }, + template: ` +
+ Login with Twitch +
Loading...
+
+ ` +} + + +const Settings = { + template: ` +
Settings
+ ` +} + + +const Main = { + components: { + Authorize, + Settings + }, + setup() { + const authorized = localStorage.getItem('token') !== null; + + return { + authorized + }; + }, + template: ` +
+ + +
+ ` +}; + + +const AuthCallbackTwitch = { + setup() { + onMounted(() => { + fetch('/api/auth/callback/twitch/' + urlParams.search) + .then(response => response.json()) + .then(data => { + localStorage.setItem('token', data.token); + + this.$router.push('/'); + }); + }); + }, + template: ` +
AuthCallbackTwitch
+ ` +}; + + +const router = createRouter({ + history: createWebHistory(), + routes: [ + { path: '', component: Main }, + { path: '/auth/callback/twitch/', component: AuthCallbackTwitch }, + ] +}); + + +const App = { + components: { + RouterView, + }, + template: ` + + `, +}; + + +createApp(App) + .use(router) + .mount('#app'); diff --git a/src/modules/web_app/views/auth.py b/src/modules/web_app/views/auth.py index 963140c..c68b3a6 100644 --- a/src/modules/web_app/views/auth.py +++ b/src/modules/web_app/views/auth.py @@ -9,7 +9,7 @@ from modules.web_app.auth.authx import auth from repositories.users import UserRepository -auth_router = APIRouter(prefix="/auth", tags=["auth"]) +auth_router = APIRouter(prefix="/api/auth", tags=["auth"]) @auth_router.get("/get_authorization_url/{provider}/") diff --git a/src/modules/web_app/views/streamer.py b/src/modules/web_app/views/streamer.py index a2c4bb7..349c132 100644 --- a/src/modules/web_app/views/streamer.py +++ b/src/modules/web_app/views/streamer.py @@ -8,7 +8,7 @@ from repositories.users import UserRepository from domain.auth import OAuthProvider -streamer_router = APIRouter(prefix="/streamers") +streamer_router = APIRouter(prefix="/api/streamers") @streamer_router.get("/")