Промежуточный коммит

This commit is contained in:
Danil_Malin 2023-05-06 16:10:35 +04:00
parent 3b2bd8cf85
commit 3df60c757f
22 changed files with 384 additions and 99 deletions

View File

@ -1,5 +1,5 @@
import './App.css';
import { useRoutes, Outlet, BrowserRouter } from 'react-router-dom';
import { useRoutes, Outlet, BrowserRouter, Routes, Route } from 'react-router-dom';
import Header from './components/common/Header';
import MainPage from './components/pages/MainPage';
import Footer from './components/common/Footer';
@ -10,42 +10,38 @@ import { useState } from 'react';
import AuthorsPage from './components/pages/dev/AuthorsPage';
import GenresPage from './components/pages/dev/GenresPage';
import ForumPage from './components/pages/ForumPage'
function Router(props) {
return useRoutes(props.rootRoute);
}
import SignUpPage from './components/pages/SignUpPage';
import PrivateRoutes from './utils/PrivateRoutes';
export default function AppDev() {
const[searchValue, setSearchValue] = useState();
const routes = [
{ index: true, element: <MainPage />},
{ path: '', element: <MainPage/>, label: 'Главная' },
{ path: 'Books', element: <BooksPage searchValue={searchValue} setSearchValue={setSearchValue}/>, label: 'Книги' },
{ path: 'Authors', element: <AuthorsPage/>, label: 'Авторы' },
{ path: 'Genres', element: <GenresPage/>, label: 'Жанры' },
{ path: 'Forum', element:<ForumPage/>, label: 'Форум'},
{ path: 'Login', element: <LoginPage/>},
{ path: 'Contacts', element: <Contacts/>}
{ path: '/', label: "Главная" },
{ path: '/Books', label: "Книги" },
{ path: '/Authors', label: "Авторы" },
{ path: '/Genres', label: "Жанры" },
{ path: '/Forum', label: 'Форум'}
];
const links = routes.filter(route => route.hasOwnProperty('label'));
const rootRoute = [
{ path: '/', element: render(links), children: routes }
];
function render(links) {
return (
<>
<Header links={links} single={routes[routes.length-2]} setSearchValue={setSearchValue} />
<div className="container-fluid">
<Outlet />
<BrowserRouter>
<Header links={routes} setSearchValue={setSearchValue} />
<div>
<Routes>
<Route element={<PrivateRoutes/>}>
<Route element={<MainPage/>} path="/" exact />
<Route element={<MainPage />} path="*" />
<Route element={<BooksPage searchValue={searchValue} setSearchValue={setSearchValue}/>} path="/Books"/>
<Route element={<AuthorsPage/>} path="/Authors"/>
<Route element={<GenresPage/>} path="/Genres"/>
<Route element={<ForumPage/>} path="/Forum"/>
<Route element={<Contacts/>} path="/Contacts"/>
</Route>
<Route element={<LoginPage/>} path="/Login"/>
<Route element={<SignUpPage/>} path="/Signup"/>
</Routes>
</div>
<Footer link={routes[routes.length-1]}/>
<Footer link={{path: '/Contacts'}}/>
</BrowserRouter>
</>
);
}
return (
<BrowserRouter>
<Router rootRoute={ rootRoute } />
</BrowserRouter>
);
}

View File

@ -8,6 +8,7 @@ import ForumPage from './components/pages/ForumPage';
import Contacts from './components/pages/Contacts';
import LoginPage from './components/pages/LoginPage';
import { useState } from 'react';
import SignUpPage from './components/pages/SignUpPage';
function Router(props) {
return useRoutes(props.rootRoute);
}
@ -21,6 +22,7 @@ function Router(props) {
{ path: 'authors', element: null, label: 'Авторы' },
{ path: 'forum', element: <ForumPage/>, label: 'Форум' },
{ path: 'login', element: <LoginPage/>},
{ path: 'signup', element: <SignUpPage/>},
{ path: 'contacts', element: <Contacts/>}
];
const links = routes.filter(route => route.hasOwnProperty('label'));

View File

@ -1,4 +1,4 @@
import { NavLink } from "react-router-dom";
import { Link } from "react-router-dom";
export default function Footer(props) {
return (
<footer className="mt-auto" style={{ backgroundColor: "rgb(235,185,185)" }}>
@ -6,9 +6,9 @@ export default function Footer(props) {
<div className="col-lg-3 col-md-6 mb-4 mb-md-0">
<ul className="list-unstyled mb-0">
<li>
<NavLink className="nav-link" to={props.link.path}>
<Link className="nav-link" to={props.link.path}>
Контакты
</NavLink>
</Link>
</li>
<li>
<a className="nav-link" href="#">

View File

@ -1,13 +1,21 @@
import { useState } from "react";
import { NavLink } from "react-router-dom";
import { Link } from "react-router-dom";
import { useNavigate } from "react-router-dom";
import AuthService from "../../services/AuthService";
export default function Header(props) {
const navigate = useNavigate();
const[state, setState] = useState({
text:""
});
const handleChange = (event) => {
setState({ ...state, [event.target.id]: event.target.value });
};
const handleLogout = () =>{
AuthService.logout();
navigate("/Login");
window.location.reload();
};
const handleSubmit = (event) => {
event.preventDefault();
props.setSearchValue(state.text)
@ -42,9 +50,9 @@ export default function Header(props) {
<ul className="nav nav-tabs justify-content-center border-bottom-0">
{props.links.map((route) => (
<li key={route.path} className="nav-item">
<NavLink className="nav-link" to={route.path}>
<Link className="nav-link" to={route.path}>
{route.label}
</NavLink>
</Link>
</li>
))}
</ul>
@ -63,9 +71,9 @@ export default function Header(props) {
</nav>
</div>
<span className="col text-end">
<NavLink className="nav-link" to={props.single.path}>
Вход/Регистрация
</NavLink>
<Link className="nav-link" onClick={handleLogout} to={""}>
Выход
</Link>
</span>
</div>
</div>

View File

@ -1,8 +1,11 @@
import React, { useEffect } from "react";
import { useNavigate } from "react-router-dom";
import { useState } from "react";
import AuthService from "../../services/AuthService"
export default function LoginPage(props) {
const formRef = React.createRef();
const [error, setError] = useState(false)
const navigate = useNavigate();
const [message, setMessage] = useState("");
const [state, setState] = useState({
login: "",
password: ""
@ -10,37 +13,33 @@ export default function LoginPage(props) {
const handleChange = (event) => {
setState({ ...state, [event.target.name]: event.target.value});
};
const validateEmail = (email) => {
return String(email)
.toLowerCase()
.match(
/^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/
);
};
const handleSubmit = (event) =>{
if (!validateEmail(state.login) || state.password.length <=0) {
event.preventDefault();
setError(true)
event.stopPropagation();
}
else{
setError(false)
setMessage("");
AuthService.login(state.login, state.password).then(
() => {
navigate("/");
window.location.reload();
},
(error) => {
const resMessage =
(error.response &&
error.response.data &&
error.response.data.message) ||
error.message ||
error.toString();
setMessage(resMessage);
}
);
}
return (
<div className="flex-shrink-0" style={{backgroundColor : 'rgb(255,255,255)'}}>
<div className="d-flex justify-content-center">
<form ref={formRef} noValidate className="w-50 ms-2 needs-validation" onSubmit={(e)=>handleSubmit(e)}>
<form ref={formRef} className="w-50 ms-2" onSubmit={(e)=>handleSubmit(e)}>
<h2 className="py-3">Вход</h2>
<h4>Логин</h4>
<input className="form-control my-2" name="login" value={state.login} onChange={(e)=>handleChange(e)} type="email" required />
{
error && !validateEmail(state.login)
?<div>
Пожалуйста введите электронную почту вида: "*****@**.**"
</div>
:<div></div>
}
<input className="form-control my-2" name="login" value={state.login} onChange={(e)=>handleChange(e)} type="text" required />
<h4>Пароль</h4>
<input
className="form-control my-2"
@ -50,22 +49,22 @@ export default function LoginPage(props) {
onChange={(e)=>handleChange(e)}
required
/>
{
error && state.password.length <=0
?<div>
Пожалуйста введите пароль
</div>
:<div></div>
}
<div>
<button className="btn btn-primary m-2" type="submit">
Войти
</button>
<a href="" style={{marginTop: 1, marginLeft: 1}}>
<a href="/Signup" style={{marginTop: 1, marginLeft: 1}}>
Зарегистрируйтесь, если нет аккаунта, здесь
</a>
</div>
</form>
{message && (
<div className="form-group">
<div className="alert alert-danger" role="alert">
{message}
</div>
</div>
)}
</div>
</div>
);

View File

@ -0,0 +1,82 @@
import React, { useEffect } from "react";
import { Link } from "react-router-dom";
import { useState } from "react";
import { useNavigate } from "react-router-dom";
import AuthService from "../../services/AuthService"
export default function SignUpPage(props) {
const formRef = React.createRef();
const navigate = useNavigate();
const [message, setMessage] = useState("");
const [state, setState] = useState({
login: "",
password: "",
passwordConfirm: ""
});
const handleChange = (event) => {
setState({ ...state, [event.target.name]: event.target.value});
};
const handleSubmit = (event) =>{
event.preventDefault();
setMessage("");
AuthService.register(state.login, state.password, state.passwordConfirm).then(
() => {
navigate("/Login");
window.location.reload();
},
(error) => {
const resMessage =
(error.response &&
error.response.data &&
error.response.data.message) ||
error.message ||
error.toString();
setMessage(resMessage);
}
);
}
return (
<div className="flex-shrink-0" style={{backgroundColor : 'rgb(255,255,255)'}}>
<div className="d-flex justify-content-center">
<form ref={formRef} className="w-50 ms-2" onSubmit={(e)=>handleSubmit(e)}>
<h2 className="py-3">Вход</h2>
<h4>Логин</h4>
<input className="form-control my-2" name="login" value={state.login} onChange={(e)=>handleChange(e)} type="text" required />
<h4>Пароль</h4>
<input
className="form-control my-2"
type="password"
name="password"
value={state.password}
onChange={(e)=>handleChange(e)}
required
/>
<h4>Подтверждение пароля</h4>
<input
className="form-control my-2"
type="password"
name="passwordConfirm"
value={state.passwordConfirm}
onChange={(e)=>handleChange(e)}
required
/>
<div>
<button className="btn btn-primary m-2" type="submit">
Создать аккаунт
</button>
<Link className="nav-link" to={"/Login"}>
Назад
</Link>
</div>
</form>
{message && (
<div className="form-group">
<div className="alert alert-danger" role="alert">
{message}
</div>
</div>
)}
</div>
</div>
);
}

View File

@ -0,0 +1,6 @@
export default class UserLoginDto {
constructor(data) {
this.login = data?.login;
this.password = data?.password;
}
}

View File

@ -0,0 +1,7 @@
export default class UserSignUpDto {
constructor(data) {
this.login = data?.login;
this.password = data?.password;
this.passwordConfirm = data?.passwordConfirm;
}
}

View File

@ -0,0 +1,32 @@
import axios from "axios";
import UserSignUpDto from "../modelsDTO/UserSignUpDto";
import UserLoginDto from "../modelsDTO/UserLoginDto";
const API_URL = "http://localhost:8080";
const register = (username, password, passwordConfirm) => {
return axios.post(API_URL + "/signup", new UserSignUpDto({login: username,
password: password,
passwordConfirm: passwordConfirm}));
};
const login = (username, password) => {
return axios
.post(API_URL + "/jwt/login", new UserLoginDto({login: username, password: password}))
.then((response) => {
if(response.status === 200){
localStorage.setItem("token", response.data)
}
});
};
const logout = () => {
localStorage.removeItem("token");
};
const AuthService = {
register,
login,
logout,
};
export default AuthService;

View File

@ -0,0 +1,14 @@
import { Outlet, Navigate } from 'react-router-dom'
const PrivateRoutes = () => {
let getPermission = false;
let userToken = localStorage.getItem("token");
if(userToken){
getPermission = true;
}
return(
getPermission ? <Outlet/> : <Navigate to="/Login"/>
)
}
export default PrivateRoutes

View File

@ -1,6 +1,7 @@
package com.labwork01.app.author.model;
import com.labwork01.app.book.model.Book;
import com.labwork01.app.user.model.User;
import jakarta.persistence.*;
import java.util.ArrayList;
@ -19,6 +20,9 @@ public class Author {
private String patronymic;
@OneToMany(cascade = CascadeType.REMOVE, mappedBy = "author", fetch = FetchType.EAGER)
private List<Book> books =new ArrayList<>();
@ManyToOne
@JoinColumn(name= "user_id", nullable = false)
private User user;
public List<Book> getBooks() {
return books;
@ -71,6 +75,12 @@ public class Author {
public void setPatronymic(String patronymic) {
this.patronymic = patronymic;
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
@ -88,6 +98,7 @@ public class Author {
"id=" + id +
", name='" + name + '\'' + '}' +
", surname='" + surname + '\'' + '}' +
", patronymic='" + patronymic + '\'' + '}';
", patronymic='" + patronymic + '\'' +
", user='" + user.toString() + '\'' + '}' +'}';
}
}

View File

@ -2,7 +2,12 @@ package com.labwork01.app.author.service;
import com.labwork01.app.author.model.Author;
import com.labwork01.app.author.repository.AuthorRepository;
import com.labwork01.app.user.model.User;
import com.labwork01.app.user.model.UserRole;
import com.labwork01.app.user.service.UserService;
import com.labwork01.app.util.validation.ValidatorUtil;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@ -12,15 +17,25 @@ import java.util.Optional;
@Service
public class AuthorService {
private final AuthorRepository authorRepository;
private final UserService userService;
private final ValidatorUtil validatorUtil;
public AuthorService(AuthorRepository authorRepository, ValidatorUtil validatorUtil){
public AuthorService(AuthorRepository authorRepository, UserService userService, ValidatorUtil validatorUtil){
this.authorRepository = authorRepository;
this.userService = userService;
this.validatorUtil = validatorUtil;
}
@Transactional
public Author addAuthor(String name, String surname, String patronymic) {
final Author author = new Author(name,surname,patronymic);
Object currentUser = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
if(currentUser instanceof UserDetails){
String username = ((UserDetails)currentUser).getUsername();
User user = userService.findByLogin(username);
if(user.getRole() == UserRole.ADMIN){
author.setUser(user);
}
}
validatorUtil.validate(author);
return authorRepository.save(author);
}

View File

@ -2,6 +2,7 @@ package com.labwork01.app.book.model;
import com.labwork01.app.author.model.Author;
import com.labwork01.app.genre.model.Genre;
import com.labwork01.app.user.model.User;
import jakarta.persistence.*;
import java.util.ArrayList;
@ -25,6 +26,9 @@ public class Book {
@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "author_id", nullable = false)
private Author author;
@ManyToOne
@JoinColumn(name= "user_id", nullable = false)
private User user;
public Book() {
}
@ -89,6 +93,12 @@ public class Book {
public void setDescription(String description) {
this.description = description;
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
@Override
public boolean equals(Object o) {
@ -111,6 +121,7 @@ public class Book {
", description='" + description + '\'' +
", author='" + author.toString() + '\'' +
", genres='" + String.join(", ",getGenresName()) + '\'' +
", user='" + user.toString() + '\'' +
'}';
}
}

View File

@ -6,7 +6,12 @@ import com.labwork01.app.book.model.Book;
import com.labwork01.app.book.repository.BookRepository;
import com.labwork01.app.genre.model.Genre;
import com.labwork01.app.genre.service.GenreService;
import com.labwork01.app.user.model.User;
import com.labwork01.app.user.model.UserRole;
import com.labwork01.app.user.service.UserService;
import com.labwork01.app.util.validation.ValidatorUtil;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@ -18,11 +23,13 @@ public class BookService {
private final BookRepository bookRepository;
private final GenreService genreService;
private final AuthorService authorService;
private final UserService userService;
private final ValidatorUtil validatorUtil;
public BookService(BookRepository bookRepository,GenreService genreService, AuthorService authorService, ValidatorUtil validatorUtil){
public BookService(BookRepository bookRepository,GenreService genreService, AuthorService authorService, UserService userService, ValidatorUtil validatorUtil){
this.bookRepository = bookRepository;
this.genreService = genreService;
this.authorService = authorService;
this.userService = userService;
this.validatorUtil = validatorUtil;
}
@ -33,6 +40,14 @@ public class BookService {
for (Genre genre: genres) {
book.addGenre(genre);
}
Object currentUser = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
if(currentUser instanceof UserDetails){
String username = ((UserDetails)currentUser).getUsername();
User user = userService.findByLogin(username);
if(user.getRole() == UserRole.ADMIN){
book.setUser(user);
}
}
validatorUtil.validate(book);
return bookRepository.save(book);
}

View File

@ -11,13 +11,17 @@ import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityCustomizer;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(securedEnabled = true)
public class SecurityConfiguration {
private final Logger log = LoggerFactory.getLogger(SecurityConfiguration.class);
@ -48,6 +52,7 @@ public class SecurityConfiguration {
.authorizeHttpRequests()
.requestMatchers("/", SPA_URL_MASK).permitAll()
.requestMatchers(HttpMethod.POST, UserController.URL_LOGIN).permitAll()
.requestMatchers(HttpMethod.POST, UserController.URL_SIGNUP).permitAll()
.anyRequest().authenticated()
.and()
.addFilterBefore(jwtFilter, UsernamePasswordAuthenticationFilter.class)
@ -65,7 +70,12 @@ public class SecurityConfiguration {
public WebSecurityCustomizer webSecurityCustomizer() {
return (web) -> web.ignoring()
.requestMatchers(HttpMethod.OPTIONS, "/**")
.requestMatchers("/**/*.{js,html,css,png}")
.requestMatchers("/*.js")
.requestMatchers("/*.html")
.requestMatchers("/*.css")
.requestMatchers("/assets/**")
.requestMatchers("/favicon.ico")
.requestMatchers("/.js", "/.css")
.requestMatchers("/swagger-ui/index.html")
.requestMatchers("/webjars/**")
.requestMatchers("/swagger-resources/**")

View File

@ -6,10 +6,7 @@ import org.springframework.boot.web.servlet.server.ConfigurableServletWebServerF
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpStatus;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistration;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.config.annotation.*;
@Configuration
class WebConfiguration implements WebMvcConfigurer {
@ -21,7 +18,7 @@ class WebConfiguration implements WebMvcConfigurer {
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController(SecurityConfiguration.SPA_URL_MASK).setViewName("forward:/");
ViewControllerRegistration registration = registry.addViewController("/notFound");
registration.setViewName("forward:/index.html");
registration.setViewName("forward:/");
registration.setStatusCode(HttpStatus.OK);
// Alternative way (404 error hits the console):
@ -34,4 +31,16 @@ class WebConfiguration implements WebMvcConfigurer {
container.addErrorPages(new ErrorPage(HttpStatus.NOT_FOUND, "/notFound"));
};
}
@Override
public void addResourceHandlers(
ResourceHandlerRegistry registry) {
registry.addResourceHandler("/static/**")
.addResourceLocations("/WEB-INF/view/react/build/static/");
registry.addResourceHandler("/*.js")
.addResourceLocations("/WEB-INF/view/react/build/");
registry.addResourceHandler("/*.json")
.addResourceLocations("/WEB-INF/view/react/build/");
registry.addResourceHandler("/*.ico")
.addResourceLocations("/WEB-INF/view/react/build/");
}
}

View File

@ -1,5 +1,6 @@
package com.labwork01.app.genre.model;
import com.labwork01.app.user.model.User;
import jakarta.persistence.*;
import java.util.Objects;
@ -11,6 +12,9 @@ public class Genre {
private Long id;
@Column(nullable = false)
private String name;
@ManyToOne
@JoinColumn(name= "user_id", nullable = false)
private User user;
public Long getId() {
return id;
}
@ -23,6 +27,12 @@ public class Genre {
public void setName(String name) {
this.name = name;
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
public Genre() {
}
public Genre(String name) {
@ -44,6 +54,7 @@ public class Genre {
public String toString() {
return "Genre{" +
"id=" + id +
", name='" + name + '\'' + '}';
", name='" + name + '\'' +
", user='" + user.toString() + '\'' +'}';
}
}

View File

@ -3,7 +3,12 @@ package com.labwork01.app.genre.service;
import com.labwork01.app.book.model.Book;
import com.labwork01.app.genre.model.Genre;
import com.labwork01.app.genre.repository.GenreRepository;
import com.labwork01.app.user.model.User;
import com.labwork01.app.user.model.UserRole;
import com.labwork01.app.user.service.UserService;
import com.labwork01.app.util.validation.ValidatorUtil;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@ -13,15 +18,25 @@ import java.util.Optional;
@Service
public class GenreService {
private final GenreRepository genreRepository;
private final UserService userService;
private final ValidatorUtil validatorUtil;
public GenreService(GenreRepository genreRepository, ValidatorUtil validatorUtil){
public GenreService(GenreRepository genreRepository, UserService userService, ValidatorUtil validatorUtil){
this.genreRepository = genreRepository;
this.userService = userService;
this.validatorUtil = validatorUtil;
}
@Transactional
public Genre addGenre(String name) {
final Genre genre = new Genre(name);
Object currentUser = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
if(currentUser instanceof UserDetails){
String username = ((UserDetails)currentUser).getUsername();
User user = userService.findByLogin(username);
if(user.getRole() == UserRole.ADMIN){
genre.setUser(user);
}
}
validatorUtil.validate(genre);
return genreRepository.save(genre);
}

View File

@ -1,23 +1,45 @@
package com.labwork01.app.user.controller;
import com.labwork01.app.configuration.OpenAPI30Configuration;
import com.labwork01.app.user.model.User;
import com.labwork01.app.user.model.UserRole;
import com.labwork01.app.user.service.UserService;
import com.labwork01.app.util.validation.ValidationException;
import jakarta.validation.Valid;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.data.domain.Page;
import org.springframework.security.access.annotation.Secured;
import org.springframework.web.bind.annotation.*;
@RestController
public class UserController {
public static final String URL_LOGIN = "/jwt/login";
public static final String URL_SIGNUP = "/signup";
public static final String URL_MAIN = "/users";
private final UserService userService;
public UserController(UserService userService) {
this.userService = userService;
}
@GetMapping(OpenAPI30Configuration.API_PREFIX + URL_MAIN)
@Secured({UserRole.AsString.ADMIN})
public Page<UserDto> getUsers(@RequestParam(defaultValue = "1") int page,
@RequestParam(defaultValue = "5") int size){
return userService.findAllPages(page, size).map(UserDto::new);
}
@PostMapping(URL_LOGIN)
public String login(@RequestBody @Valid UserDto userDto) {
return userService.loginAndGetToken(userDto);
public String login(@RequestBody @Valid UserLoginDto userLoginDto) {
return userService.loginAndGetToken(userLoginDto);
}
@PostMapping(URL_SIGNUP)
public String signup(@RequestBody @Valid UserSignupDto userSignupDto){
try {
User user = userService.createUser(userSignupDto.getLogin(), userSignupDto.getPassword(), userSignupDto.getPasswordConfirm());
return user.getLogin() + "was created";
}
catch(ValidationException e){
return e.getMessage();
}
}
}

View File

@ -6,13 +6,11 @@ import com.labwork01.app.user.model.UserRole;
public class UserDto {
private final long id;
private final String login;
private final String password;
private final UserRole role;
public UserDto(User user) {
this.id = user.getId();
this.login = user.getLogin();
this.password = user.getPassword();
this.role = user.getRole();
}
@ -27,7 +25,4 @@ public class UserDto {
public UserRole getRole() {
return role;
}
public String getPassword(){
return password;
}
}

View File

@ -0,0 +1,25 @@
package com.labwork01.app.user.controller;
import jakarta.validation.constraints.NotBlank;
public class UserLoginDto {
@NotBlank
private String login;
@NotBlank
private String password;
public String getLogin() {
return login;
}
public void setLogin(String login) {
this.login = login;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}

View File

@ -2,7 +2,7 @@ package com.labwork01.app.user.service;
import com.labwork01.app.configuration.jwt.JwtException;
import com.labwork01.app.configuration.jwt.JwtProvider;
import com.labwork01.app.user.controller.UserDto;
import com.labwork01.app.user.controller.UserLoginDto;
import com.labwork01.app.user.model.User;
import com.labwork01.app.user.model.UserRole;
import com.labwork01.app.user.repository.UserRepository;
@ -61,7 +61,7 @@ public class UserService implements UserDetailsService {
return userRepository.save(user);
}
public String loginAndGetToken(UserDto userDto) {
public String loginAndGetToken(UserLoginDto userDto) {
final User user = findByLogin(userDto.getLogin());
if (user == null) {
throw new UserNotFoundException(userDto.getLogin());