mirror of
https://github.com/Radiquum/AniX.git
synced 2025-06-04 11:09:37 +05:00
Back and Front: User Login
This commit is contained in:
parent
a03deddbc0
commit
32a4da1a31
8 changed files with 141 additions and 36 deletions
|
@ -1,20 +1,21 @@
|
||||||
from typing import Annotated
|
|
||||||
|
|
||||||
import requests
|
import requests
|
||||||
from fastapi import APIRouter
|
from fastapi import APIRouter
|
||||||
from fastapi import Form
|
|
||||||
from fastapi import Request
|
|
||||||
from modules.proxy import ENDPOINTS
|
from modules.proxy import ENDPOINTS
|
||||||
from modules.proxy import USER_AGENT
|
from modules.proxy import USER_AGENT
|
||||||
|
from pydantic import BaseModel
|
||||||
|
|
||||||
|
|
||||||
|
class User(BaseModel):
|
||||||
|
email: str
|
||||||
|
password: str
|
||||||
|
|
||||||
|
|
||||||
router = APIRouter()
|
router = APIRouter()
|
||||||
|
|
||||||
|
|
||||||
@router.post("", summary="logging in")
|
@router.post("", summary="logging in")
|
||||||
async def userSignIn(
|
async def userSignIn(
|
||||||
request: Request,
|
user: User,
|
||||||
email: Annotated[str, Form()],
|
|
||||||
password: Annotated[str, Form()],
|
|
||||||
short: bool = False,
|
short: bool = False,
|
||||||
):
|
):
|
||||||
headers = {
|
headers = {
|
||||||
|
@ -26,7 +27,7 @@ async def userSignIn(
|
||||||
# noqa: E501
|
# noqa: E501
|
||||||
f"{ENDPOINTS['auth']}",
|
f"{ENDPOINTS['auth']}",
|
||||||
headers=headers,
|
headers=headers,
|
||||||
data={"login": email, "password": password},
|
data={"login": user.email, "password": user.password},
|
||||||
)
|
)
|
||||||
if r.status_code != 200:
|
if r.status_code != 200:
|
||||||
return {"error": r.text}
|
return {"error": r.text}
|
||||||
|
|
|
@ -5,23 +5,25 @@ import "material-dynamic-colors";
|
||||||
import { NavigationRail } from "@/app/components/NavigationRail/NavigationRail";
|
import { NavigationRail } from "@/app/components/NavigationRail/NavigationRail";
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import { ColorPicker } from "@/app/components/ColorPicker/ColorPicker";
|
import { ColorPicker } from "@/app/components/ColorPicker/ColorPicker";
|
||||||
|
import { useUserStore } from "./store/user-store";
|
||||||
|
|
||||||
export function setMode(mode) {
|
function setMode(mode) {
|
||||||
localStorage.setItem("mode", mode);
|
localStorage.setItem("mode", mode);
|
||||||
}
|
}
|
||||||
export function getMode() {
|
function getMode() {
|
||||||
return localStorage.getItem("mode");
|
return localStorage.getItem("mode");
|
||||||
}
|
}
|
||||||
|
|
||||||
export function setTheme(theme) {
|
function setTheme(theme) {
|
||||||
localStorage.setItem("theme", theme);
|
localStorage.setItem("theme", theme);
|
||||||
}
|
}
|
||||||
export function getTheme() {
|
function getTheme() {
|
||||||
return localStorage.getItem("theme");
|
return localStorage.getItem("theme");
|
||||||
}
|
}
|
||||||
|
|
||||||
export const App = (props) => {
|
export const App = (props) => {
|
||||||
const [colorPicker, setColorPicker] = useState(false);
|
const [colorPicker, setColorPicker] = useState(false);
|
||||||
|
const userStore = useUserStore();
|
||||||
|
|
||||||
const theme = async (from) => {
|
const theme = async (from) => {
|
||||||
setTheme(from);
|
setTheme(from);
|
||||||
|
@ -45,6 +47,11 @@ export const App = (props) => {
|
||||||
}
|
}
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
userStore.checkAuth();
|
||||||
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
|
}, []);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<body>
|
<body>
|
||||||
<div>
|
<div>
|
||||||
|
|
|
@ -1,3 +1,7 @@
|
||||||
|
export const isResponseOk = (response) => {
|
||||||
|
return !(response instanceof Error);
|
||||||
|
};
|
||||||
|
|
||||||
export const getData = async (url) => {
|
export const getData = async (url) => {
|
||||||
try {
|
try {
|
||||||
const response = await fetch(url);
|
const response = await fetch(url);
|
||||||
|
@ -14,8 +18,8 @@ export const authorize = async (url, data) => {
|
||||||
try {
|
try {
|
||||||
const response = await fetch(url, {
|
const response = await fetch(url, {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
headers: { "Content-Type": "application/json" },
|
||||||
body: data,
|
body: JSON.stringify(data),
|
||||||
});
|
});
|
||||||
if (response.status !== 200) {
|
if (response.status !== 200) {
|
||||||
throw new Error("Ошибка получения данных");
|
throw new Error("Ошибка получения данных");
|
||||||
|
@ -28,7 +32,7 @@ export const authorize = async (url, data) => {
|
||||||
|
|
||||||
export const getMe = async (url, jwt) => {
|
export const getMe = async (url, jwt) => {
|
||||||
try {
|
try {
|
||||||
const response = await fetch(`${url}?token=${jwt}&short=True`, {
|
const response = await fetch(`${url}?token=${jwt}`, {
|
||||||
method: "GET",
|
method: "GET",
|
||||||
});
|
});
|
||||||
if (response.status !== 200) {
|
if (response.status !== 200) {
|
||||||
|
@ -40,12 +44,14 @@ export const getMe = async (url, jwt) => {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export function setJWT(jwt) {
|
export function setJWT(jwt, user_id) {
|
||||||
localStorage.setItem("jwt", jwt);
|
const data = { jwt: jwt, user_id: user_id };
|
||||||
|
localStorage.setItem("data", JSON.stringify(data));
|
||||||
}
|
}
|
||||||
export function getJWT() {
|
export function getJWT() {
|
||||||
return localStorage.getItem("jwt");
|
const data = localStorage.getItem("data");
|
||||||
|
return JSON.parse(data);
|
||||||
}
|
}
|
||||||
export function removeJWT() {
|
export function removeJWT() {
|
||||||
localStorage.removeItem("jwt");
|
localStorage.removeItem("data");
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,4 +8,8 @@ export const endpoints = {
|
||||||
finished: `${API_URL}/index/finished`,
|
finished: `${API_URL}/index/finished`,
|
||||||
},
|
},
|
||||||
search: `${API_URL}/search`,
|
search: `${API_URL}/search`,
|
||||||
|
user: {
|
||||||
|
profile: `${API_URL}/profile`,
|
||||||
|
auth: `${API_URL}/auth`,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
|
@ -3,9 +3,13 @@
|
||||||
import { usePathname } from "next/navigation";
|
import { usePathname } from "next/navigation";
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import Image from "next/image";
|
import Image from "next/image";
|
||||||
|
import { useUserStore } from "@/app/store/user-store";
|
||||||
|
import { useRouter } from "next/navigation";
|
||||||
|
|
||||||
export const NavigationRail = (props) => {
|
export const NavigationRail = (props) => {
|
||||||
const pathname = usePathname();
|
const pathname = usePathname();
|
||||||
|
const userStore = useUserStore();
|
||||||
|
const router = useRouter();
|
||||||
|
|
||||||
const items = [
|
const items = [
|
||||||
{
|
{
|
||||||
|
@ -37,15 +41,26 @@ export const NavigationRail = (props) => {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<nav className="left">
|
<nav className="left">
|
||||||
<button className="circle transparent ">
|
{userStore.isAuth && userStore.user ? (
|
||||||
<Image
|
<Link className="circle transparent " href="/profile">
|
||||||
className="responsive"
|
<Image
|
||||||
src="/favicon.ico"
|
className="responsive"
|
||||||
alt="Ваш профиль"
|
src={userStore.user.profile.avatar}
|
||||||
width="64"
|
alt="Ваш профиль"
|
||||||
height="64"
|
width="64"
|
||||||
/>
|
height="64"
|
||||||
</button>
|
/>
|
||||||
|
</Link>
|
||||||
|
) : (
|
||||||
|
<button
|
||||||
|
className="circle transparent"
|
||||||
|
onClick={() => {
|
||||||
|
router.push("/login");
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<i className="responsive">login</i>
|
||||||
|
</button>
|
||||||
|
)}
|
||||||
|
|
||||||
{items.map((item) => {
|
{items.map((item) => {
|
||||||
return (
|
return (
|
||||||
|
@ -67,6 +82,17 @@ export const NavigationRail = (props) => {
|
||||||
>
|
>
|
||||||
<i>palette</i>
|
<i>palette</i>
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
|
{userStore.isAuth ? (
|
||||||
|
<button
|
||||||
|
className="circle transparent"
|
||||||
|
onClick={() => userStore.logout()}
|
||||||
|
>
|
||||||
|
<i>logout</i>
|
||||||
|
</button>
|
||||||
|
) : (
|
||||||
|
""
|
||||||
|
)}
|
||||||
</nav>
|
</nav>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
@ -24,8 +24,8 @@ export const ReleaseCard = (props) => {
|
||||||
<h6>{`${props.title.substring(0, 30)}${
|
<h6>{`${props.title.substring(0, 30)}${
|
||||||
[...props.title].length > 30 ? "..." : ""
|
[...props.title].length > 30 ? "..." : ""
|
||||||
}`}</h6>
|
}`}</h6>
|
||||||
<p>{`${props.description}${
|
<p>{`${props.description.substring(0, 150)}${
|
||||||
[...props.description].length > 160 ? "..." : ""
|
[...props.description].length > 150 ? "..." : ""
|
||||||
}`}</p>
|
}`}</p>
|
||||||
</div>
|
</div>
|
||||||
</article>
|
</article>
|
||||||
|
|
|
@ -1,3 +1,60 @@
|
||||||
|
"use client";
|
||||||
|
|
||||||
|
import { useUserStore } from "../store/user-store";
|
||||||
|
import { endpoints } from "../api/config";
|
||||||
|
import { authorize, isResponseOk } from "../api/api-utils";
|
||||||
|
import { useRouter } from "next/navigation";
|
||||||
|
import { useState, useEffect } from "react";
|
||||||
|
|
||||||
export default function LoginPage() {
|
export default function LoginPage() {
|
||||||
return <p>login page</p>;
|
const userStore = useUserStore();
|
||||||
|
const router = useRouter();
|
||||||
|
const [authData, setAuthData] = useState({ email: "", password: "" });
|
||||||
|
|
||||||
|
const handleInput = (e) => {
|
||||||
|
setAuthData({ ...authData, [e.target.name]: e.target.value });
|
||||||
|
};
|
||||||
|
const handleSubmit = async (e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
const userData = await authorize(endpoints.user.auth, authData);
|
||||||
|
if (isResponseOk(userData)) {
|
||||||
|
userStore.login(
|
||||||
|
userData,
|
||||||
|
userData.profileToken.token,
|
||||||
|
userData.profile.id,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
let timer;
|
||||||
|
if (userStore.user) {
|
||||||
|
timer = setTimeout(() => {
|
||||||
|
router.push("/profile");
|
||||||
|
}, 1000);
|
||||||
|
}
|
||||||
|
return () => clearTimeout(timer);
|
||||||
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
|
}, [userStore.user]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="absolute padding tertiary center middle round">
|
||||||
|
<i className="extra">login</i>
|
||||||
|
<h5>Вход в аккаунт anixart.</h5>
|
||||||
|
<form onSubmit={handleSubmit}>
|
||||||
|
<div className="border field fill label large round">
|
||||||
|
<input type="email" name="email" onInput={handleInput} />
|
||||||
|
<label>логин</label>
|
||||||
|
</div>
|
||||||
|
<div className="border field fill label large round">
|
||||||
|
<input type="password" name="password" onInput={handleInput} />
|
||||||
|
<label>пароль</label>
|
||||||
|
</div>
|
||||||
|
<button className="small-round medium" type="submit">
|
||||||
|
<i>login</i>
|
||||||
|
<span>Войти</span>
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,20 +7,24 @@ export const useUserStore = create((set, get) => ({
|
||||||
isAuth: false,
|
isAuth: false,
|
||||||
user: null,
|
user: null,
|
||||||
token: null,
|
token: null,
|
||||||
login: (user, token) => {
|
|
||||||
|
login: (user, token, user_id) => {
|
||||||
set({ isAuth: true, user, token });
|
set({ isAuth: true, user, token });
|
||||||
setJWT(token);
|
setJWT(token, user_id);
|
||||||
},
|
},
|
||||||
logout: () => {
|
logout: () => {
|
||||||
set({ isAuth: false, user: null, token: null });
|
set({ isAuth: false, user: null, token: null });
|
||||||
removeJWT();
|
removeJWT();
|
||||||
},
|
},
|
||||||
checkAuth: async (user_id) => {
|
checkAuth: async () => {
|
||||||
const jwt = getJWT();
|
const jwt = getJWT();
|
||||||
if (jwt) {
|
if (jwt) {
|
||||||
const me = await getMe(`${endpoints.profile}/${user_id}`, jwt);
|
const me = await getMe(
|
||||||
|
`${endpoints.user.profile}/${jwt.user_id}`,
|
||||||
|
jwt.jwt,
|
||||||
|
);
|
||||||
if (me.is_my_profile) {
|
if (me.is_my_profile) {
|
||||||
get().login(me, jwt);
|
get().login(me, jwt.jwt, jwt.user_id);
|
||||||
} else {
|
} else {
|
||||||
get().logout();
|
get().logout();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue