Добавил регистрацию/авторизацию
This commit is contained in:
parent
74d4ba0773
commit
149b0619e0
2
go-auth/.gitignore
vendored
2
go-auth/.gitignore
vendored
@ -1,2 +1,2 @@
|
||||
.env
|
||||
go.mod
|
||||
.idea
|
@ -1,3 +1,11 @@
|
||||
# PIbd-42_Kashin_M.I_FinalQualifyingWork
|
||||
|
||||
Модуль "Авторизация"
|
||||
Модуль "Авторизация"
|
||||
|
||||
go mod init main
|
||||
|
||||
go mod tidy
|
||||
|
||||
.env
|
||||
JWT_SECRET_KEY=mysecretkey123
|
||||
DB_URL=postgres://postgres:password_db@localhost:5432/name_db
|
@ -8,7 +8,6 @@ import (
|
||||
"main/database"
|
||||
"main/models"
|
||||
"os"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/joho/godotenv"
|
||||
@ -60,44 +59,50 @@ func Register(c *fiber.Ctx) error {
|
||||
return c.JSON(user)
|
||||
}
|
||||
|
||||
// Логиним пользователя
|
||||
// Генерация JWT-токена
|
||||
func generateToken(user models.User) (string, error) {
|
||||
claims := jwt.MapClaims{
|
||||
"user_id": user.Id,
|
||||
"exp": time.Now().Add(time.Hour * 24).Unix(), // Токен на 24 часа
|
||||
}
|
||||
|
||||
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
|
||||
return token.SignedString([]byte(SecretKey))
|
||||
}
|
||||
|
||||
func Login(c *fiber.Ctx) error {
|
||||
var data map[string]string
|
||||
if err := c.BodyParser(&data); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Найти пользователя по email
|
||||
var user models.User
|
||||
database.DB.Where("email = ?", data["email"]).First(&user)
|
||||
|
||||
if user.Id == 0 {
|
||||
return c.Status(fiber.StatusNotFound).JSON(fiber.Map{"message": "User not found"})
|
||||
return c.Status(fiber.StatusUnauthorized).JSON(fiber.Map{"message": "Invalid email or password"})
|
||||
}
|
||||
|
||||
// Проверяем пароль
|
||||
if err := bcrypt.CompareHashAndPassword(user.Password, []byte(data["password"])); err != nil {
|
||||
return c.Status(fiber.StatusUnauthorized).JSON(fiber.Map{"message": "Incorrect password"})
|
||||
return c.Status(fiber.StatusUnauthorized).JSON(fiber.Map{"message": "Invalid email or password"})
|
||||
}
|
||||
|
||||
claims := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.StandardClaims{
|
||||
Issuer: strconv.Itoa(int(user.Id)),
|
||||
ExpiresAt: time.Now().Add(time.Hour * 12).Unix(),
|
||||
})
|
||||
|
||||
token, err := claims.SignedString([]byte(SecretKey))
|
||||
// Генерируем токен
|
||||
token, err := generateToken(user)
|
||||
if err != nil {
|
||||
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"message": "Token invalid"})
|
||||
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"message": "Could not generate token"})
|
||||
}
|
||||
|
||||
cookie := fiber.Cookie{
|
||||
// Сохраняем токен в cookie
|
||||
c.Cookie(&fiber.Cookie{
|
||||
Name: "jwt",
|
||||
Value: token,
|
||||
Expires: time.Now().Add(time.Hour * 12),
|
||||
Expires: time.Now().Add(time.Hour * 24),
|
||||
HTTPOnly: true,
|
||||
SameSite: "Strict",
|
||||
}
|
||||
c.Cookie(&cookie)
|
||||
})
|
||||
|
||||
return c.JSON(fiber.Map{"message": "Login success"})
|
||||
return c.JSON(fiber.Map{"message": "Login successful"})
|
||||
}
|
||||
|
||||
// Получаем пользователя по токену
|
||||
|
34
go-auth/go.mod
Normal file
34
go-auth/go.mod
Normal file
@ -0,0 +1,34 @@
|
||||
module main
|
||||
|
||||
go 1.24.0
|
||||
|
||||
require (
|
||||
github.com/gofiber/fiber/v2 v2.52.6
|
||||
github.com/golang-jwt/jwt v3.2.2+incompatible
|
||||
github.com/joho/godotenv v1.5.1
|
||||
golang.org/x/crypto v0.34.0
|
||||
gorm.io/driver/postgres v1.5.11
|
||||
gorm.io/gorm v1.25.12
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/andybalholm/brotli v1.1.0 // indirect
|
||||
github.com/google/uuid v1.6.0 // indirect
|
||||
github.com/jackc/pgpassfile v1.0.0 // indirect
|
||||
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a // indirect
|
||||
github.com/jackc/pgx/v5 v5.5.5 // indirect
|
||||
github.com/jackc/puddle/v2 v2.2.1 // indirect
|
||||
github.com/jinzhu/inflection v1.0.0 // indirect
|
||||
github.com/jinzhu/now v1.1.5 // indirect
|
||||
github.com/klauspost/compress v1.17.9 // indirect
|
||||
github.com/mattn/go-colorable v0.1.13 // indirect
|
||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||
github.com/mattn/go-runewidth v0.0.16 // indirect
|
||||
github.com/rivo/uniseg v0.2.0 // indirect
|
||||
github.com/valyala/bytebufferpool v1.0.0 // indirect
|
||||
github.com/valyala/fasthttp v1.51.0 // indirect
|
||||
github.com/valyala/tcplisten v1.0.0 // indirect
|
||||
golang.org/x/sync v0.11.0 // indirect
|
||||
golang.org/x/sys v0.30.0 // indirect
|
||||
golang.org/x/text v0.22.0 // indirect
|
||||
)
|
67
go-auth/go.sum
Normal file
67
go-auth/go.sum
Normal file
@ -0,0 +1,67 @@
|
||||
github.com/andybalholm/brotli v1.1.0 h1:eLKJA0d02Lf0mVpIDgYnqXcUn0GqVmEFny3VuID1U3M=
|
||||
github.com/andybalholm/brotli v1.1.0/go.mod h1:sms7XGricyQI9K10gOSf56VKKWS4oLer58Q+mhRPtnY=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/gofiber/fiber/v2 v2.52.6 h1:Rfp+ILPiYSvvVuIPvxrBns+HJp8qGLDnLJawAu27XVI=
|
||||
github.com/gofiber/fiber/v2 v2.52.6/go.mod h1:YEcBbO/FB+5M1IZNBP9FO3J9281zgPAreiI1oqg8nDw=
|
||||
github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY=
|
||||
github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I=
|
||||
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM=
|
||||
github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg=
|
||||
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a h1:bbPeKD0xmW/Y25WS6cokEszi5g+S0QxI/d45PkRi7Nk=
|
||||
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM=
|
||||
github.com/jackc/pgx/v5 v5.5.5 h1:amBjrZVmksIdNjxGW/IiIMzxMKZFelXbUoPNb+8sjQw=
|
||||
github.com/jackc/pgx/v5 v5.5.5/go.mod h1:ez9gk+OAat140fv9ErkZDYFWmXLfV+++K0uAOiwgm1A=
|
||||
github.com/jackc/puddle/v2 v2.2.1 h1:RhxXJtFG022u4ibrCSMSiu5aOq1i77R3OHKNJj77OAk=
|
||||
github.com/jackc/puddle/v2 v2.2.1/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4=
|
||||
github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
|
||||
github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
|
||||
github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ=
|
||||
github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
|
||||
github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0=
|
||||
github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
|
||||
github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA=
|
||||
github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw=
|
||||
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
|
||||
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
|
||||
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
|
||||
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
||||
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||
github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc=
|
||||
github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY=
|
||||
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk=
|
||||
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
|
||||
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
|
||||
github.com/valyala/fasthttp v1.51.0 h1:8b30A5JlZ6C7AS81RsWjYMQmrZG6feChmgAolCl1SqA=
|
||||
github.com/valyala/fasthttp v1.51.0/go.mod h1:oI2XroL+lI7vdXyYoQk03bXBThfFl2cVdIA3Xl7cH8g=
|
||||
github.com/valyala/tcplisten v1.0.0 h1:rBHj/Xf+E1tRGZyWIWwJDiRY0zc1Js+CV5DqwacVSA8=
|
||||
github.com/valyala/tcplisten v1.0.0/go.mod h1:T0xQ8SeCZGxckz9qRXTfG43PvQ/mcWh7FwZEA7Ioqkc=
|
||||
golang.org/x/crypto v0.34.0 h1:+/C6tk6rf/+t5DhUketUbD1aNGqiSX3j15Z6xuIDlBA=
|
||||
golang.org/x/crypto v0.34.0/go.mod h1:dy7dXNW32cAb/6/PRuTNsix8T+vJAqvuIy5Bli/x0YQ=
|
||||
golang.org/x/sync v0.11.0 h1:GGz8+XQP4FvTTrjZPzNKTMFtSXH80RAzG+5ghFPgK9w=
|
||||
golang.org/x/sync v0.11.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc=
|
||||
golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/text v0.22.0 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM=
|
||||
golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gorm.io/driver/postgres v1.5.11 h1:ubBVAfbKEUld/twyKZ0IYn9rSQh448EdelLYk9Mv314=
|
||||
gorm.io/driver/postgres v1.5.11/go.mod h1:DX3GReXH+3FPWGrrgffdvCk3DQ1dwDPdmbenSkweRGI=
|
||||
gorm.io/gorm v1.25.12 h1:I0u8i2hWQItBq1WfE0o2+WuL9+8L21K9e2HHSTE/0f8=
|
||||
gorm.io/gorm v1.25.12/go.mod h1:xh7N7RHfYlNc5EmcI/El95gXusucDrQnHXe0+CgWcLQ=
|
@ -23,7 +23,7 @@ func main() {
|
||||
|
||||
app.Use(cors.New(cors.Config{
|
||||
AllowCredentials: true,
|
||||
AllowOrigins: "http://localhost:8000",
|
||||
AllowOrigins: "http://localhost:5173/",
|
||||
}))
|
||||
|
||||
routes.Setup(app)
|
||||
|
@ -2,6 +2,7 @@ import { BrowserRouter as Router, Route, Routes } from 'react-router-dom';
|
||||
import Authorization from './component/page/Authorization';
|
||||
import Registration from './component/page/Registration';
|
||||
import Main from './component/page/Main';
|
||||
import Profile from './component/profile/Profile';
|
||||
|
||||
function App() {
|
||||
return (
|
||||
@ -10,6 +11,7 @@ function App() {
|
||||
<Route path="/" element={<Main />} />
|
||||
<Route path="/login" element={<Authorization />} />
|
||||
<Route path="/register" element={<Registration />} />
|
||||
<Route path="/profile" element={<Profile />} />
|
||||
</Routes>
|
||||
</Router>
|
||||
);
|
||||
|
@ -1,48 +1,63 @@
|
||||
import { Link } from 'react-router-dom'; // Импортируем Link
|
||||
|
||||
import React from 'react';
|
||||
import { Link, useNavigate } from 'react-router-dom';
|
||||
import React, { useState } from 'react';
|
||||
import { LockOutlined, UserOutlined } from '@ant-design/icons';
|
||||
import { Button, Checkbox, Form, Input, Flex } from 'antd';
|
||||
import { Button, Checkbox, Form, Input, Flex, message } from 'antd';
|
||||
import axios from 'axios';
|
||||
|
||||
const Authorization = () => {
|
||||
const onFinish = (values) => {
|
||||
console.log('Received values of form: ', values);
|
||||
const [loading, setLoading] = useState(false);
|
||||
const navigate = useNavigate(); // Перенаправление после успешного входа
|
||||
|
||||
const onFinish = async (values) => {
|
||||
setLoading(true);
|
||||
try {
|
||||
const response = await axios.post(
|
||||
'http://localhost:8000/api/login',
|
||||
{
|
||||
email: values.email, // Обновляем поле, так как сервер ожидает email
|
||||
password: values.password,
|
||||
},
|
||||
{ withCredentials: true } // Обязательно, чтобы браузер хранил cookie
|
||||
);
|
||||
|
||||
message.success('Login successful!');
|
||||
console.log(response.data);
|
||||
|
||||
// Перенаправление на главную страницу
|
||||
navigate('/');
|
||||
} catch (error) {
|
||||
message.error(error.response?.data?.message || 'Login failed');
|
||||
console.error(error);
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="flex justify-center items-center min-h-screen bg-gray-100">
|
||||
<Form
|
||||
name="login"
|
||||
initialValues={{
|
||||
remember: true,
|
||||
}}
|
||||
style={{
|
||||
maxWidth: 360,
|
||||
}}
|
||||
initialValues={{ remember: true }}
|
||||
style={{ maxWidth: 360 }}
|
||||
onFinish={onFinish}
|
||||
>
|
||||
<Form.Item
|
||||
name="username"
|
||||
name="email"
|
||||
rules={[
|
||||
{
|
||||
required: true,
|
||||
message: 'Please input your Username!',
|
||||
},
|
||||
{ required: true, message: 'Please input your Email!' },
|
||||
{ type: 'email', message: 'Invalid email format!' },
|
||||
]}
|
||||
>
|
||||
<Input prefix={<UserOutlined />} placeholder="Username" />
|
||||
<Input prefix={<UserOutlined />} placeholder="Email" />
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item
|
||||
name="password"
|
||||
rules={[
|
||||
{
|
||||
required: true,
|
||||
message: 'Please input your Password!',
|
||||
},
|
||||
]}
|
||||
rules={[{ required: true, message: 'Please input your Password!' }]}
|
||||
>
|
||||
<Input prefix={<LockOutlined />} type="password" placeholder="Password" />
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item>
|
||||
<Flex justify="space-between" align="center">
|
||||
<Form.Item name="remember" valuePropName="checked" noStyle>
|
||||
@ -53,10 +68,10 @@ const Authorization = () => {
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item>
|
||||
<Button block type="primary" htmlType="submit">
|
||||
<Button block type="primary" htmlType="submit" loading={loading}>
|
||||
Log in
|
||||
</Button>
|
||||
or <Link to="/register">Register now!</Link> {/* Используем Link для перехода на страницу регистрации */}
|
||||
or <Link to="/register">Register now!</Link>
|
||||
</Form.Item>
|
||||
</Form>
|
||||
</div>
|
||||
|
@ -1,48 +1,64 @@
|
||||
import { Link } from 'react-router-dom'; // Импортируем Link
|
||||
|
||||
import React from 'react';
|
||||
import { LockOutlined, UserOutlined } from '@ant-design/icons';
|
||||
import { Button, Checkbox, Form, Input, Flex } from 'antd';
|
||||
import { Link } from 'react-router-dom';
|
||||
import React, { useState } from 'react';
|
||||
import { LockOutlined, UserOutlined, MailOutlined } from '@ant-design/icons';
|
||||
import { Button, Checkbox, Form, Input, Flex, message } from 'antd';
|
||||
import axios from 'axios';
|
||||
|
||||
const Registration = () => {
|
||||
const onFinish = (values) => {
|
||||
console.log('Received values of form: ', values);
|
||||
const [loading, setLoading] = useState(false); // Для отображения загрузки
|
||||
|
||||
const onFinish = async (values) => {
|
||||
setLoading(true);
|
||||
try {
|
||||
const response = await axios.post('http://localhost:8000/api/register', {
|
||||
name: values.name,
|
||||
email: values.email,
|
||||
password: values.password,
|
||||
});
|
||||
|
||||
|
||||
message.success('Registration successful!');
|
||||
console.log(response.data); // Можно обработать ответ, например, переадресовать на login
|
||||
} catch (error) {
|
||||
message.error(error.response?.data?.message || 'Registration failed');
|
||||
console.error(error);
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="flex justify-center items-center min-h-screen bg-gray-100">
|
||||
<Form
|
||||
name="login"
|
||||
initialValues={{
|
||||
remember: true,
|
||||
}}
|
||||
style={{
|
||||
maxWidth: 360,
|
||||
}}
|
||||
name="register"
|
||||
initialValues={{ remember: true }}
|
||||
style={{ maxWidth: 360 }}
|
||||
onFinish={onFinish}
|
||||
>
|
||||
<Form.Item
|
||||
name="username"
|
||||
name="name"
|
||||
rules={[{ required: true, message: 'Please input your Name!' }]}
|
||||
>
|
||||
<Input prefix={<UserOutlined />} placeholder="Name" />
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item
|
||||
name="email"
|
||||
rules={[
|
||||
{
|
||||
required: true,
|
||||
message: 'Please input your Username!',
|
||||
},
|
||||
{ required: true, message: 'Please input your Email!' },
|
||||
{ type: 'email', message: 'Invalid email format!' },
|
||||
]}
|
||||
>
|
||||
<Input prefix={<UserOutlined />} placeholder="Username" />
|
||||
<Input prefix={<MailOutlined />} placeholder="Email" />
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item
|
||||
name="password"
|
||||
rules={[
|
||||
{
|
||||
required: true,
|
||||
message: 'Please input your Password!',
|
||||
},
|
||||
]}
|
||||
rules={[{ required: true, message: 'Please input your Password!' }]}
|
||||
>
|
||||
<Input prefix={<LockOutlined />} type="password" placeholder="Password" />
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item>
|
||||
<Flex justify="space-between" align="center">
|
||||
<Form.Item name="remember" valuePropName="checked" noStyle>
|
||||
@ -53,10 +69,10 @@ const Registration = () => {
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item>
|
||||
<Button block type="primary" htmlType="submit">
|
||||
Log in
|
||||
<Button block type="primary" htmlType="submit" loading={loading}>
|
||||
Register
|
||||
</Button>
|
||||
or <Link to="/login">Login now!</Link> {/* Используем Link для перехода на страницу авторизации */}
|
||||
or <Link to="/login">Login now!</Link>
|
||||
</Form.Item>
|
||||
</Form>
|
||||
</div>
|
||||
|
56
react-auth/src/component/profile/Profile.jsx
Normal file
56
react-auth/src/component/profile/Profile.jsx
Normal file
@ -0,0 +1,56 @@
|
||||
import React, { useEffect, useState } from "react";
|
||||
import axios from "axios";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import { Card, Spin, Alert, Button } from "antd";
|
||||
|
||||
const Profile = () => {
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [error, setError] = useState(null);
|
||||
const navigate = useNavigate();
|
||||
|
||||
useEffect(() => {
|
||||
const fetchUserData = async () => {
|
||||
try {
|
||||
const response = await axios.get("http://localhost:8000/api/user", {
|
||||
withCredentials: true, // Отправляем cookie с JWT
|
||||
});
|
||||
} catch (err) {
|
||||
setError("Вы не авторизованы. Пожалуйста, войдите в систему.");
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
fetchUserData();
|
||||
}, []);
|
||||
|
||||
if (loading) return <Spin size="large" />;
|
||||
if (error)
|
||||
return (
|
||||
<Alert
|
||||
message="Ошибка"
|
||||
description={error}
|
||||
type="error"
|
||||
showIcon
|
||||
action={
|
||||
<Button type="primary" onClick={() => navigate("/login")}>
|
||||
Войти
|
||||
</Button>
|
||||
}
|
||||
/>
|
||||
);
|
||||
|
||||
return (
|
||||
<div className="flex justify-center items-center min-h-screen bg-gray-100">
|
||||
<Card title="Профиль пользователя" style={{ width: 400 }}>
|
||||
<p><strong>Имя:</strong> имя </p>
|
||||
<p><strong>Email:</strong> почта</p>
|
||||
<Button type="primary" onClick={() => navigate("/logout")}>
|
||||
Выйти
|
||||
</Button>
|
||||
</Card>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default Profile;
|
Loading…
x
Reference in New Issue
Block a user