Compare commits
No commits in common. "048a00a4a43b35bee06754f3cb2457500af03c2c" and "aefeeeee487bf3c0c9885cebfce3e3ca7ec0fc9f" have entirely different histories.
048a00a4a4
...
aefeeeee48
BIN
data.mv.db
BIN
data.mv.db
Binary file not shown.
3828
data.trace.db
Normal file
3828
data.trace.db
Normal file
File diff suppressed because it is too large
Load Diff
@ -1,8 +1,10 @@
|
||||
package com.webproglabs.lab1;
|
||||
|
||||
import com.webproglabs.lab1.lab34.model.enums.UserRole;
|
||||
import com.webproglabs.lab1.lab34.mvc.UserSignUpMvcController;
|
||||
import com.webproglabs.lab1.lab34.services.UserService;
|
||||
import com.webproglabs.lab1.lab34.controller.ProfileController;
|
||||
import com.webproglabs.lab1.lab34.controller.mvc_controllers.UserSignupMvcController;
|
||||
import com.webproglabs.lab1.lab34.jwt.JwtFilter;
|
||||
import com.webproglabs.lab1.lab34.model.UserRole;
|
||||
import com.webproglabs.lab1.lab34.services.ProfileService;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
@ -15,10 +17,12 @@ import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||
import org.springframework.security.config.annotation.web.builders.WebSecurity;
|
||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
||||
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
|
||||
import org.springframework.security.config.http.SessionCreationPolicy;
|
||||
import org.springframework.security.web.AuthenticationEntryPoint;
|
||||
import org.springframework.security.web.authentication.DelegatingAuthenticationEntryPoint;
|
||||
import org.springframework.security.web.authentication.Http403ForbiddenEntryPoint;
|
||||
import org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint;
|
||||
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
|
||||
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
|
||||
import org.springframework.security.web.util.matcher.RequestMatcher;
|
||||
|
||||
@ -32,16 +36,18 @@ public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
|
||||
private final Logger log = LoggerFactory.getLogger(SecurityConfiguration.class);
|
||||
private static final String LOGIN_URL = "/login";
|
||||
public static final String SPA_URL_MASK = "/{path:[^\\.]*}";
|
||||
private final UserService userService;
|
||||
private final ProfileService userService;
|
||||
private final JwtFilter jwtFilter;
|
||||
|
||||
public SecurityConfiguration(UserService userService) {
|
||||
public SecurityConfiguration(ProfileService userService) {
|
||||
this.userService = userService;
|
||||
this.jwtFilter = new JwtFilter(userService);
|
||||
createAdminOnStartup();
|
||||
}
|
||||
|
||||
private void createAdminOnStartup() {
|
||||
final String admin = "admin";
|
||||
if (userService.findUserByLogin(admin) == null) {
|
||||
if (userService.findByLogin(admin) == null) {
|
||||
log.info("Admin user successfully created");
|
||||
try {
|
||||
userService.createUser(admin, admin, admin, UserRole.ADMIN);
|
||||
@ -53,12 +59,13 @@ public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
|
||||
|
||||
@Override
|
||||
protected void configure(HttpSecurity http) throws Exception {
|
||||
|
||||
http.exceptionHandling().authenticationEntryPoint(delegatingEntryPoint());
|
||||
http.headers().frameOptions().sameOrigin().and()
|
||||
.cors().and()
|
||||
.csrf().disable()
|
||||
.authorizeRequests()
|
||||
.antMatchers(UserSignUpMvcController.SIGNUP_URL).permitAll()
|
||||
.antMatchers(UserSignupMvcController.SIGNUP_URL).permitAll()
|
||||
.antMatchers(HttpMethod.GET, LOGIN_URL).permitAll()
|
||||
.anyRequest().authenticated()
|
||||
.and()
|
||||
|
105
src/main/java/com/webproglabs/lab1/SecurityConfigurationSPA.java
Normal file
105
src/main/java/com/webproglabs/lab1/SecurityConfigurationSPA.java
Normal file
@ -0,0 +1,105 @@
|
||||
package com.webproglabs.lab1;
|
||||
|
||||
import com.webproglabs.lab1.lab34.controller.ProfileController;
|
||||
import com.webproglabs.lab1.lab34.controller.mvc_controllers.UserSignupMvcController;
|
||||
import com.webproglabs.lab1.lab34.jwt.JwtFilter;
|
||||
import com.webproglabs.lab1.lab34.model.UserRole;
|
||||
import com.webproglabs.lab1.lab34.services.ProfileService;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Profile;
|
||||
import org.springframework.http.HttpMethod;
|
||||
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.builders.WebSecurity;
|
||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
||||
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
|
||||
import org.springframework.security.config.http.SessionCreationPolicy;
|
||||
import org.springframework.security.web.AuthenticationEntryPoint;
|
||||
import org.springframework.security.web.authentication.DelegatingAuthenticationEntryPoint;
|
||||
import org.springframework.security.web.authentication.Http403ForbiddenEntryPoint;
|
||||
import org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint;
|
||||
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
|
||||
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
|
||||
import org.springframework.security.web.util.matcher.RequestMatcher;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
|
||||
@Configuration
|
||||
@EnableWebSecurity
|
||||
@EnableGlobalMethodSecurity(securedEnabled = true)
|
||||
@Profile("spa")
|
||||
public class SecurityConfigurationSPA extends WebSecurityConfigurerAdapter {
|
||||
private final Logger log = LoggerFactory.getLogger(SecurityConfiguration.class);
|
||||
private static final String LOGIN_URL = "/login";
|
||||
public static final String SPA_URL_MASK = "/{path:[^\\.]*}";
|
||||
private final ProfileService userService;
|
||||
private final JwtFilter jwtFilter;
|
||||
|
||||
public SecurityConfigurationSPA(ProfileService userService) {
|
||||
this.userService = userService;
|
||||
this.jwtFilter = new JwtFilter(userService);
|
||||
createAdminOnStartup();
|
||||
}
|
||||
|
||||
private void createAdminOnStartup() {
|
||||
final String admin = "admin";
|
||||
if (userService.findByLogin(admin) == null) {
|
||||
log.info("Admin user successfully created");
|
||||
try {
|
||||
userService.createUser(admin, admin, admin, UserRole.ADMIN);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void configure(HttpSecurity http) throws Exception {
|
||||
log.info("Creating security configuration");
|
||||
http.cors()
|
||||
.and()
|
||||
.csrf().disable()
|
||||
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
|
||||
.and()
|
||||
.authorizeRequests()
|
||||
.antMatchers("/", SPA_URL_MASK).permitAll()
|
||||
.antMatchers(HttpMethod.POST, WebConfiguration.REST_API + "/profile" + ProfileController.URL_LOGIN).permitAll()
|
||||
.anyRequest()
|
||||
.authenticated()
|
||||
.and()
|
||||
.addFilterBefore(jwtFilter, UsernamePasswordAuthenticationFilter.class)
|
||||
.anonymous();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
|
||||
auth.userDetailsService(userService);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void configure(WebSecurity web) {
|
||||
web.ignoring()
|
||||
.antMatchers("/css/**")
|
||||
.antMatchers("/js/**")
|
||||
.antMatchers("/templates/**")
|
||||
.antMatchers("/webjars/**")
|
||||
.antMatchers("/swagger-resources/**")
|
||||
.antMatchers("/v3/api-docs/**");
|
||||
}
|
||||
|
||||
@Bean
|
||||
public AuthenticationEntryPoint delegatingEntryPoint() {
|
||||
final LinkedHashMap<RequestMatcher, AuthenticationEntryPoint> map = new LinkedHashMap();
|
||||
map.put(new AntPathRequestMatcher("/"), new LoginUrlAuthenticationEntryPoint("/login"));
|
||||
map.put(new AntPathRequestMatcher("/api/1.0/**"), new Http403ForbiddenEntryPoint());
|
||||
|
||||
final DelegatingAuthenticationEntryPoint entryPoint = new DelegatingAuthenticationEntryPoint(map);
|
||||
entryPoint.setDefaultEntryPoint(new LoginUrlAuthenticationEntryPoint("/login"));
|
||||
|
||||
return entryPoint;
|
||||
}
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
package com.webproglabs.lab1;
|
||||
|
||||
import com.webproglabs.lab1.lab34.OpenAPI30Configuration;
|
||||
import org.springframework.boot.web.server.ErrorPage;
|
||||
import org.springframework.boot.web.server.WebServerFactoryCustomizer;
|
||||
import org.springframework.boot.web.servlet.server.ConfigurableServletWebServerFactory;
|
||||
@ -12,7 +13,7 @@ import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
||||
|
||||
@Configuration
|
||||
public class WebConfiguration implements WebMvcConfigurer {
|
||||
public static final String REST_API = "/api";
|
||||
public static final String REST_API = OpenAPI30Configuration.API_PREFIX;
|
||||
@Override
|
||||
public void addViewControllers(ViewControllerRegistry registry) {
|
||||
WebMvcConfigurer.super.addViewControllers(registry);
|
||||
|
44
src/main/java/com/webproglabs/lab1/lab1/Lab1Controller.java
Normal file
44
src/main/java/com/webproglabs/lab1/lab1/Lab1Controller.java
Normal file
@ -0,0 +1,44 @@
|
||||
package com.webproglabs.lab1.lab1;
|
||||
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.Random;
|
||||
|
||||
@RestController
|
||||
public class Lab1Controller {
|
||||
@GetMapping("/ilove")
|
||||
public String ilove(@RequestParam(value = "thing", defaultValue = "cookies") String thing) {
|
||||
return String.format("I love %s!", thing);
|
||||
}
|
||||
|
||||
@GetMapping("/ask")
|
||||
public String question(@RequestParam(value = "question", defaultValue = "Задайте вопрос") String question) {
|
||||
if (question.contains("Задайте вопрос")) return question;
|
||||
String[] answers = new String[] {
|
||||
"Не знаю",
|
||||
"Да",
|
||||
"Нет",
|
||||
"Спросите у мамы"
|
||||
};
|
||||
Random random = new Random();
|
||||
return answers[random.nextInt(4)];
|
||||
}
|
||||
|
||||
@GetMapping("/touppercase")
|
||||
public String tuupper(@RequestParam(value = "content", defaultValue = "Введите строку") String content) {
|
||||
return content.toUpperCase();
|
||||
}
|
||||
|
||||
@GetMapping("/date")
|
||||
public String date () {
|
||||
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss");
|
||||
LocalDateTime now = LocalDateTime.now();
|
||||
return dtf.format(now);
|
||||
}
|
||||
|
||||
|
||||
}
|
27
src/main/java/com/webproglabs/lab1/lab2/Lab2Config.java
Normal file
27
src/main/java/com/webproglabs/lab1/lab2/Lab2Config.java
Normal file
@ -0,0 +1,27 @@
|
||||
package com.webproglabs.lab1.lab2.config;
|
||||
|
||||
import com.webproglabs.lab1.lab2.domain.Lab2Int;
|
||||
import com.webproglabs.lab1.lab2.domain.Lab2String;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
@Configuration
|
||||
public class Lab2Config {
|
||||
|
||||
@Bean(value="int")
|
||||
public Lab2Int createLab2Int() {
|
||||
return new Lab2Int();
|
||||
}
|
||||
|
||||
@Bean(value="String")
|
||||
public Lab2String createLab2String() {
|
||||
return new Lab2String();
|
||||
}
|
||||
}
|
||||
|
||||
//фронт на жсон сервер был когда то
|
||||
//сделать на основе старых сущностей сущности в жпа
|
||||
//делаем сущности, зависимость для жпа, сервис для круд операций,
|
||||
//тесты
|
||||
//фронт не нужно
|
||||
//двунправленная связь один ко многим
|
35
src/main/java/com/webproglabs/lab1/lab2/Lab2Controller.java
Normal file
35
src/main/java/com/webproglabs/lab1/lab2/Lab2Controller.java
Normal file
@ -0,0 +1,35 @@
|
||||
package com.webproglabs.lab1.lab2.controllers;
|
||||
|
||||
import com.webproglabs.lab1.lab2.Lab2Service;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
@RestController
|
||||
public class Lab2Controller {
|
||||
private final Lab2Service lab2Service;
|
||||
|
||||
public Lab2Controller(Lab2Service lab2Service) {this.lab2Service = lab2Service;}
|
||||
|
||||
@GetMapping("/lab2/sum")
|
||||
public Object sum(@RequestParam (value = "first", defaultValue = "hello") String first,
|
||||
@RequestParam (value = "second", defaultValue = "world") String second,
|
||||
@RequestParam (value = "type") String type) {
|
||||
return lab2Service.sum(first, second, type);
|
||||
}
|
||||
|
||||
@GetMapping("/lab2/makeitbigger")
|
||||
public Object makeItBigger(@RequestParam (value = "small") String small, @RequestParam (value = "type") String type) {
|
||||
return lab2Service.makeItBigger(small, type);
|
||||
}
|
||||
|
||||
@GetMapping("/lab2/reverse")
|
||||
public Object reverse(@RequestParam(value="value")String value, @RequestParam (value = "type") String type) {
|
||||
return lab2Service.reverse(value, type);
|
||||
}
|
||||
|
||||
@GetMapping("lab2/lenght")
|
||||
public Object lenght(@RequestParam(value = "value") String value, @RequestParam (value = "type") String type) {
|
||||
return lab2Service.lenght(value, type);
|
||||
}
|
||||
}
|
47
src/main/java/com/webproglabs/lab1/lab2/Lab2Service.java
Normal file
47
src/main/java/com/webproglabs/lab1/lab2/Lab2Service.java
Normal file
@ -0,0 +1,47 @@
|
||||
package com.webproglabs.lab1.lab2;
|
||||
|
||||
import com.webproglabs.lab1.lab2.domain.Lab2Interface;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
public class Lab2Service {
|
||||
private final ApplicationContext applicationContext;
|
||||
|
||||
public Lab2Service(ApplicationContext applicationContext) {
|
||||
this.applicationContext = applicationContext;
|
||||
}
|
||||
|
||||
public Object sum(Object first, Object second, String type) {
|
||||
if (type.equals("int")) {
|
||||
first = Integer.parseInt(first.toString());
|
||||
second = Integer.parseInt(second.toString());
|
||||
}
|
||||
final Lab2Interface summator =(Lab2Interface)applicationContext.getBean(type);
|
||||
return summator.sum(first, second);
|
||||
}
|
||||
|
||||
public Object makeItBigger(Object small, String type) {
|
||||
if (type.equals("int")) {
|
||||
small = Integer.parseInt(small.toString());
|
||||
}
|
||||
final Lab2Interface biggernator = (Lab2Interface)applicationContext.getBean(type);
|
||||
return biggernator.makeItBigger(small);
|
||||
}
|
||||
|
||||
public Object reverse (Object value, String type) {
|
||||
if (type.equals("int")) {
|
||||
value = Integer.parseInt(value.toString());
|
||||
}
|
||||
final Lab2Interface reversenator = (Lab2Interface) applicationContext.getBean(type);
|
||||
return reversenator.reverse(value);
|
||||
}
|
||||
|
||||
public Object lenght (Object value, String type) {
|
||||
if (type.equals("int")) {
|
||||
value = Integer.parseInt(value.toString());
|
||||
}
|
||||
final Lab2Interface leghtgetter = (Lab2Interface) applicationContext.getBean(type);
|
||||
return leghtgetter.lenght(value);
|
||||
}
|
||||
}
|
58
src/main/java/com/webproglabs/lab1/lab2/domain/Lab2Int.java
Normal file
58
src/main/java/com/webproglabs/lab1/lab2/domain/Lab2Int.java
Normal file
@ -0,0 +1,58 @@
|
||||
package com.webproglabs.lab1.lab2.domain;
|
||||
|
||||
public class Lab2Int implements Lab2Interface<Integer>{
|
||||
// @Override
|
||||
// public Object sum(Object first, Object second) {
|
||||
// if (!(first instanceof Integer && second instanceof Integer)) {
|
||||
// throw new IllegalArgumentException();
|
||||
// }
|
||||
// return (Integer)first + (Integer)second;
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public Object makeItBigger(Object small) {
|
||||
// if (!(small instanceof Integer)) {
|
||||
// throw new IllegalArgumentException();
|
||||
// }
|
||||
// return (Integer)small * (Integer)small;
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public Object reverse(Object value) {
|
||||
// if (!(value instanceof Integer)) {
|
||||
// throw new IllegalArgumentException();
|
||||
// }
|
||||
// return (Integer)value * (-1);
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public Object lenght(Object value) {
|
||||
// if (!(value instanceof Integer)) {
|
||||
// throw new IllegalArgumentException();
|
||||
// }
|
||||
// int newvalue = (Integer)value;
|
||||
// if (newvalue < 0) newvalue = newvalue * (-1);
|
||||
// return newvalue;
|
||||
// }
|
||||
|
||||
@Override
|
||||
public Integer sum(Integer first, Integer second) {
|
||||
return first + second;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer makeItBigger(Integer small) {
|
||||
return small*small;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer reverse(Integer value) {
|
||||
return value*(-1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer lenght(Integer value) {
|
||||
if (value < 0) return value *(-1);
|
||||
else return value;
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
package com.webproglabs.lab1.lab2.domain;
|
||||
|
||||
public interface Lab2Interface<T> {
|
||||
T sum(T first, T second);
|
||||
|
||||
T makeItBigger (T small);
|
||||
|
||||
T reverse (T value);
|
||||
|
||||
T lenght (T value);
|
||||
}
|
@ -0,0 +1,61 @@
|
||||
package com.webproglabs.lab1.lab2.domain;
|
||||
|
||||
public class Lab2String implements Lab2Interface<String>{
|
||||
// @Override
|
||||
// public Object sum(Object first, Object second) {
|
||||
// if (!(first instanceof String && second instanceof String)) {
|
||||
// throw new IllegalArgumentException();
|
||||
// }
|
||||
// return ((String) first).concat((String)second);
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public Object makeItBigger(Object small) {
|
||||
// if (!(small instanceof String)) {
|
||||
// throw new IllegalArgumentException();
|
||||
// }
|
||||
// return ((String) small).toUpperCase();
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public Object reverse(Object value) {
|
||||
// if (!(value instanceof String)) {
|
||||
// throw new IllegalArgumentException();
|
||||
// }
|
||||
// StringBuilder sb = new StringBuilder((String)value);
|
||||
// sb.reverse();
|
||||
// return sb.toString();
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public Object lenght(Object value) {
|
||||
// if (!(value instanceof String)) {
|
||||
// throw new IllegalArgumentException();
|
||||
// }
|
||||
// return ((String) value).length();
|
||||
// }
|
||||
|
||||
|
||||
@Override
|
||||
public String sum(String first, String second) {
|
||||
return first.concat(second);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String makeItBigger(String small) {
|
||||
return small.toUpperCase();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String reverse(String value) {
|
||||
StringBuilder sb = new StringBuilder(value);
|
||||
sb.reverse();
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String lenght(String value) {
|
||||
int len = value.length();
|
||||
return Integer.toString(len);
|
||||
}
|
||||
}
|
@ -0,0 +1,28 @@
|
||||
package com.webproglabs.lab1.lab34;
|
||||
|
||||
import com.webproglabs.lab1.lab34.jwt.JwtFilter;
|
||||
import io.swagger.v3.oas.models.Components;
|
||||
import io.swagger.v3.oas.models.OpenAPI;
|
||||
import io.swagger.v3.oas.models.security.SecurityRequirement;
|
||||
import io.swagger.v3.oas.models.security.SecurityScheme;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
@Configuration
|
||||
public class OpenAPI30Configuration {
|
||||
public static final String API_PREFIX = "/api/1.0";
|
||||
|
||||
@Bean
|
||||
public OpenAPI customizeOpenAPI() {
|
||||
final String securitySchemeName = JwtFilter.TOKEN_BEGIN_STR;
|
||||
return new OpenAPI()
|
||||
.addSecurityItem(new SecurityRequirement()
|
||||
.addList(securitySchemeName))
|
||||
.components(new Components()
|
||||
.addSecuritySchemes(securitySchemeName, new SecurityScheme()
|
||||
.name(securitySchemeName)
|
||||
.type(SecurityScheme.Type.HTTP)
|
||||
.scheme("bearer")
|
||||
.bearerFormat("JWT")));
|
||||
}
|
||||
}
|
@ -0,0 +1,59 @@
|
||||
package com.webproglabs.lab1.lab34.controller;
|
||||
|
||||
import com.webproglabs.lab1.WebConfiguration;
|
||||
import com.webproglabs.lab1.lab34.model.Comment;
|
||||
import com.webproglabs.lab1.lab34.model.Profile;
|
||||
import com.webproglabs.lab1.lab34.services.CommentService;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@RestController
|
||||
@RequestMapping(WebConfiguration.REST_API + "/comment")
|
||||
public class CommentController {
|
||||
private final CommentService commentService;
|
||||
|
||||
public CommentController(CommentService commentService) {
|
||||
this.commentService = commentService;
|
||||
}
|
||||
|
||||
@GetMapping("/{id}")
|
||||
public CommentDto getComment(@PathVariable Long id) {
|
||||
return new CommentDto(commentService.findComment(id));
|
||||
}
|
||||
|
||||
@GetMapping
|
||||
public List<CommentDto> getComments() {
|
||||
return commentService.findAllComments().stream()
|
||||
.map(CommentDto::new)
|
||||
.toList();
|
||||
}
|
||||
@GetMapping("/find")
|
||||
public List<PostDto> getFilteredComments(@RequestParam("text") String text) {
|
||||
return commentService.findFilteredComments(text).stream()
|
||||
.map(PostDto::new)
|
||||
.toList();
|
||||
}
|
||||
|
||||
|
||||
@PostMapping
|
||||
public CommentDto createComment(@RequestParam("text") String text, @RequestParam("ownerId") Long id, @RequestParam("postId") Long postId){
|
||||
final Comment comment = commentService.addComment(text, id, postId);
|
||||
return new CommentDto(comment);
|
||||
}
|
||||
|
||||
@PutMapping("/{id}")
|
||||
public CommentDto updateComment(@RequestParam("text") String text, @PathVariable Long id) {
|
||||
return new CommentDto(commentService.updateComment(id, text));
|
||||
}
|
||||
|
||||
@DeleteMapping("/{id}")
|
||||
public CommentDto deleteComment(@PathVariable Long id) {
|
||||
return new CommentDto(commentService.deleteComment(id));
|
||||
}
|
||||
|
||||
@DeleteMapping
|
||||
public void deleteAllComments(){
|
||||
commentService.deleteAllComments();
|
||||
}
|
||||
}
|
@ -0,0 +1,23 @@
|
||||
package com.webproglabs.lab1.lab34.controller;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import com.webproglabs.lab1.lab34.model.Comment;
|
||||
|
||||
public class CommentDto {
|
||||
private Long id;
|
||||
private String text;
|
||||
private String authorLogin;
|
||||
|
||||
public CommentDto(Comment comment) {
|
||||
this.id = comment.getId();
|
||||
this.text = comment.getText();
|
||||
this.authorLogin = comment.getOwner().getLogin();
|
||||
}
|
||||
|
||||
@JsonProperty(access = JsonProperty.Access.READ_ONLY)
|
||||
public long getId() {
|
||||
return id;
|
||||
}
|
||||
public String getText() {return text;}
|
||||
public String getAuthor() {return authorLogin;}
|
||||
}
|
@ -0,0 +1,64 @@
|
||||
package com.webproglabs.lab1.lab34.controller;
|
||||
|
||||
import com.webproglabs.lab1.WebConfiguration;
|
||||
import com.webproglabs.lab1.lab34.services.PostService;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@RestController
|
||||
@RequestMapping(WebConfiguration.REST_API + "/post")
|
||||
public class PostController {
|
||||
private final PostService postService;
|
||||
|
||||
public PostController(PostService postService) {
|
||||
this.postService = postService;
|
||||
}
|
||||
|
||||
@GetMapping("/{id}")
|
||||
public PostDto getPost(@PathVariable Long id) {
|
||||
return new PostDto(postService.findPost(id));
|
||||
}
|
||||
|
||||
@GetMapping
|
||||
public List<PostDto> getPosts() {
|
||||
return postService.findAllPosts().stream()
|
||||
.map(PostDto::new)
|
||||
.toList();
|
||||
}
|
||||
|
||||
@GetMapping("/find")
|
||||
public List<PostDto> getFilteredPosts(@RequestParam("text") String text) {
|
||||
return postService.findFilteredPosts(text).stream()
|
||||
.map(PostDto::new)
|
||||
.toList();
|
||||
}
|
||||
|
||||
@PostMapping
|
||||
public PostDto createPost(
|
||||
@RequestParam("text") String text,
|
||||
@RequestParam("authorId") Long authorId
|
||||
)
|
||||
{
|
||||
return new PostDto(postService.addPost(text, new ArrayList<>(),authorId));
|
||||
}
|
||||
|
||||
@PutMapping("/{id}")
|
||||
public PostDto updatePost(
|
||||
@PathVariable Long id,
|
||||
@RequestParam("text") String text
|
||||
)
|
||||
{
|
||||
return new PostDto(postService.updatePost(id, text));
|
||||
}
|
||||
|
||||
@DeleteMapping("/{id}")
|
||||
public PostDto deletePost (@PathVariable Long id) {
|
||||
return new PostDto(postService.deletePost(id));
|
||||
}
|
||||
@DeleteMapping
|
||||
public void deleteAllPosts() {
|
||||
postService.deleteAllPosts();
|
||||
}
|
||||
}
|
@ -0,0 +1,34 @@
|
||||
package com.webproglabs.lab1.lab34.controller;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import com.webproglabs.lab1.lab34.model.Comment;
|
||||
import com.webproglabs.lab1.lab34.model.Post;
|
||||
import com.webproglabs.lab1.lab34.model.Profile;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class PostDto {
|
||||
private Long id;
|
||||
private String text;
|
||||
private List<CommentDto> comments = new ArrayList<>();
|
||||
|
||||
private String authorLogin;
|
||||
|
||||
public PostDto(Post post){
|
||||
this.id = post.getId();
|
||||
this.text = post.getText();
|
||||
for(Comment comment: post.getComments()){
|
||||
comments.add(new CommentDto(comment));
|
||||
}
|
||||
this.authorLogin = post.getAuthor().getLogin();
|
||||
}
|
||||
|
||||
@JsonProperty(access = JsonProperty.Access.READ_ONLY)
|
||||
public long getId() {
|
||||
return id;
|
||||
}
|
||||
public String getText() {return text;}
|
||||
public List<CommentDto> getComments() {return comments;}
|
||||
public String getAuthor() {return authorLogin;}
|
||||
}
|
@ -0,0 +1,88 @@
|
||||
package com.webproglabs.lab1.lab34.controller;
|
||||
|
||||
import com.webproglabs.lab1.WebConfiguration;
|
||||
import com.webproglabs.lab1.lab34.model.Profile;
|
||||
import com.webproglabs.lab1.lab34.model.UserRole;
|
||||
import com.webproglabs.lab1.lab34.services.ProfileService;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.validation.Valid;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@RestController
|
||||
@RequestMapping(WebConfiguration.REST_API + "/profile")
|
||||
public class ProfileController {
|
||||
|
||||
public static final String URL_LOGIN = "/jwt/login";
|
||||
|
||||
private final ProfileService profileService;
|
||||
|
||||
public ProfileController(ProfileService profileService) {
|
||||
this.profileService = profileService;
|
||||
}
|
||||
|
||||
@GetMapping("/{id}")
|
||||
public ProfileDto getProfile(@PathVariable Long id) {
|
||||
return new ProfileDto(profileService.findUser(id));
|
||||
}
|
||||
|
||||
@GetMapping("/find/{login}")
|
||||
public ProfileDto getProfileByLogin(@PathVariable String login) {
|
||||
return new ProfileDto(profileService.findByLogin(login));
|
||||
}
|
||||
|
||||
@GetMapping
|
||||
public List<ProfileDto> getProfiles() {
|
||||
return profileService.findAllUsers().stream()
|
||||
.map(ProfileDto::new)
|
||||
.toList();
|
||||
}
|
||||
|
||||
@PostMapping
|
||||
public ProfileDto createProfile(
|
||||
@RequestParam("login") String login,
|
||||
@RequestParam("password") String password
|
||||
)
|
||||
{
|
||||
return new ProfileDto(profileService.addUser(login, password, new ArrayList<>(),new ArrayList<>() ));
|
||||
}
|
||||
|
||||
@PutMapping("/{id}")
|
||||
public ProfileDto updateProfile(
|
||||
@PathVariable Long id,
|
||||
@RequestParam("login") String login,
|
||||
@RequestParam("password") String password
|
||||
)
|
||||
{
|
||||
return new ProfileDto(profileService.updateUser(id, login, password));
|
||||
}
|
||||
|
||||
@DeleteMapping("/{id}")
|
||||
public ProfileDto deleteProfile (@PathVariable Long id) {
|
||||
return new ProfileDto(profileService.deleteUser(id));
|
||||
}
|
||||
@DeleteMapping
|
||||
public void deleteAllProfiles() {
|
||||
profileService.deleteAllUsers();
|
||||
}
|
||||
@PostMapping(URL_LOGIN)
|
||||
public String login(@RequestBody @Valid ProfileDto userDto) {
|
||||
return profileService.loginAndGetToken(userDto);
|
||||
}
|
||||
|
||||
|
||||
// этот метод юзать для проверки на администраторсткую роль вместо старой проверки по логину админа ЛОЛ
|
||||
//
|
||||
@GetMapping("role/{token}")
|
||||
public String getRoleByToken(@PathVariable String token) {
|
||||
var userDetails = profileService.loadUserByToken(token);
|
||||
Profile user = profileService.findByLogin(userDetails.getUsername());
|
||||
if (user != null) {
|
||||
return user.getRole().toString();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,50 @@
|
||||
package com.webproglabs.lab1.lab34.controller;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import com.webproglabs.lab1.lab34.model.Comment;
|
||||
import com.webproglabs.lab1.lab34.model.Post;
|
||||
import com.webproglabs.lab1.lab34.model.Profile;
|
||||
import com.webproglabs.lab1.lab34.model.UserRole;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class ProfileDto {
|
||||
private Long id;
|
||||
private String login;
|
||||
private String password;
|
||||
private List<CommentDto> comments = new ArrayList<>();
|
||||
|
||||
private List<PostDto> posts = new ArrayList<>();
|
||||
|
||||
private UserRole role;
|
||||
|
||||
public ProfileDto(){}
|
||||
|
||||
public ProfileDto(Profile profile){
|
||||
this.id = profile.getId();
|
||||
this.login = profile.getLogin();
|
||||
this.password = profile.getPassword();
|
||||
this.role = profile.getRole();
|
||||
for(Comment comment: profile.getComments()){
|
||||
comments.add(new CommentDto(comment));
|
||||
}
|
||||
for (Post post: profile.getPosts()) {
|
||||
posts.add(new PostDto(post));
|
||||
}
|
||||
}
|
||||
|
||||
@JsonProperty(access = JsonProperty.Access.READ_ONLY)
|
||||
public long getId() {
|
||||
return id;
|
||||
}
|
||||
public String getLogin() {return login;}
|
||||
public void setLogin(String login) {this.login = login;}
|
||||
public String getPassword() {return password;}
|
||||
|
||||
public UserRole getRole() {return role;}
|
||||
|
||||
public void setPassword(String password) {this.password = password;}
|
||||
public List<CommentDto> getComments() {return comments;}
|
||||
public List<PostDto> getPosts() {return posts;}
|
||||
}
|
@ -0,0 +1,121 @@
|
||||
package com.webproglabs.lab1.lab34.controller.mvc_controllers;
|
||||
|
||||
import com.webproglabs.lab1.lab34.controller.CommentDto;
|
||||
import com.webproglabs.lab1.lab34.controller.PostDto;
|
||||
import com.webproglabs.lab1.lab34.controller.ProfileDto;
|
||||
import com.webproglabs.lab1.lab34.model.Profile;
|
||||
import com.webproglabs.lab1.lab34.services.CommentService;
|
||||
import com.webproglabs.lab1.lab34.services.PostService;
|
||||
import com.webproglabs.lab1.lab34.services.ProfileService;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.Model;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
@Controller
|
||||
@RequestMapping("/feed")
|
||||
public class FeedMvcController {
|
||||
private final ProfileService profileService;
|
||||
private final PostService postService;
|
||||
private final CommentService commentService;
|
||||
public FeedMvcController(ProfileService profileService, PostService postService, CommentService commentService) {
|
||||
this.profileService = profileService;
|
||||
this.postService = postService;
|
||||
this.commentService = commentService;
|
||||
}
|
||||
|
||||
@GetMapping
|
||||
public String getFeedPage(Model model) {
|
||||
UserDetails principal = (UserDetails)SecurityContextHolder.getContext().getAuthentication().getPrincipal();
|
||||
var user = profileService.findByLogin(principal.getUsername());
|
||||
if (user != null) {
|
||||
return "redirect:/feed/" + user.getId().toString();
|
||||
}
|
||||
|
||||
model.addAttribute("profiles", profileService.findAllUsers().stream().map(ProfileDto::new).toList());
|
||||
return "feed";
|
||||
}
|
||||
|
||||
@GetMapping(value = {"/{id}"})
|
||||
public String getFeedPageAuthorized(@PathVariable Long id, Model model) {
|
||||
model.addAttribute("profiles", profileService.findAllUsers().stream().map(ProfileDto::new).toList());
|
||||
model.addAttribute("posts", postService.findAllPosts().stream().map(PostDto::new).toList());
|
||||
model.addAttribute("selectedProfile", new ProfileDto(profileService.findUser(id)));
|
||||
|
||||
return "feedPosts";
|
||||
}
|
||||
|
||||
@GetMapping(value= {"/filter/{id}/"})
|
||||
public String getFeedPageFiltered(@PathVariable Long id, @RequestParam(value="searchField") String searchField, Model model) {
|
||||
model.addAttribute("profiles", profileService.findAllUsers().stream().map(ProfileDto::new).toList());
|
||||
model.addAttribute("posts", postService.findFilteredPosts(searchField).stream().map(PostDto::new).toList());
|
||||
model.addAttribute("selectedProfile", new ProfileDto(profileService.findUser(id)));
|
||||
return "feedPosts";
|
||||
}
|
||||
|
||||
@PostMapping(value={"/post/{id}/"})
|
||||
public String createPost(@PathVariable Long id, @RequestParam(value="postInputField") String postInputField) {
|
||||
postService.addPost(postInputField, new ArrayList<>(), id);
|
||||
return "redirect:/feed/" + id.toString();
|
||||
}
|
||||
|
||||
@PostMapping(value = {"/deletePost/{id}/{authorId}"})
|
||||
public String deletePost(@PathVariable Long id, @PathVariable Long authorId) {
|
||||
postService.deletePost(id);
|
||||
return "redirect:/feed/" + authorId.toString();
|
||||
}
|
||||
|
||||
@GetMapping(value = {"postModal/{id}/{authorId}"})
|
||||
public String getPostEditModal(@PathVariable Long id,@PathVariable Long authorId, Model model) {
|
||||
model.addAttribute("selectedPost", new PostDto(postService.findPost(id)));
|
||||
model.addAttribute("profiles", profileService.findAllUsers().stream().map(ProfileDto::new).toList());
|
||||
model.addAttribute("posts", postService.findAllPosts().stream().map(PostDto::new).toList());
|
||||
model.addAttribute("selectedProfile", new ProfileDto(profileService.findUser(authorId)));
|
||||
return "editPostModal";
|
||||
}
|
||||
|
||||
@PostMapping(value = {"editPost/{id}/{authorId}/"})
|
||||
public String editPost(@PathVariable Long id, @PathVariable Long authorId, @RequestParam(value="postEditField") String postEditField) {
|
||||
postService.updatePost(id, postEditField);
|
||||
return "redirect:/feed/" + authorId.toString();
|
||||
}
|
||||
|
||||
@GetMapping(value = {"commentModal/{authorId}/{postId}"})
|
||||
public String getCommentModal(@PathVariable Long authorId,@PathVariable Long postId, Model model) {
|
||||
model.addAttribute("selectedPost", new PostDto(postService.findPost(postId)));
|
||||
model.addAttribute("profiles", profileService.findAllUsers().stream().map(ProfileDto::new).toList());
|
||||
model.addAttribute("posts", postService.findAllPosts().stream().map(PostDto::new).toList());
|
||||
model.addAttribute("selectedProfile", new ProfileDto(profileService.findUser(authorId)));
|
||||
return "commentModal";
|
||||
}
|
||||
|
||||
@PostMapping(value = {"comment/{authorId}/{postId}/"})
|
||||
public String createComment(@PathVariable Long authorId,@PathVariable Long postId, @RequestParam(value="commentInputField") String commentInputField) {
|
||||
commentService.addComment(commentInputField, authorId, postId);
|
||||
return "redirect:/feed/" + authorId.toString();
|
||||
}
|
||||
|
||||
@PostMapping(value = {"/deleteComment/{id}/{authorId}"})
|
||||
public String deleteComment(@PathVariable Long id, @PathVariable Long authorId) {
|
||||
commentService.deleteComment(id);
|
||||
return "redirect:/feed/" + authorId.toString();
|
||||
}
|
||||
|
||||
@GetMapping(value = {"commentEditModal/{id}/{authorId}"})
|
||||
public String getCommentEditModal(@PathVariable Long id,@PathVariable Long authorId, Model model) {
|
||||
model.addAttribute("selectedComment", new CommentDto(commentService.findComment(id)));
|
||||
model.addAttribute("profiles", profileService.findAllUsers().stream().map(ProfileDto::new).toList());
|
||||
model.addAttribute("posts", postService.findAllPosts().stream().map(PostDto::new).toList());
|
||||
model.addAttribute("selectedProfile", new ProfileDto(profileService.findUser(authorId)));
|
||||
return "editCommentModal";
|
||||
}
|
||||
|
||||
@PostMapping(value = {"editComment/{authorId}/{commentId}/"})
|
||||
public String editComment(@PathVariable Long authorId,@PathVariable Long commentId, @RequestParam(value="commentEditField") String commentEditField) {
|
||||
commentService.updateComment(commentId, commentEditField);
|
||||
return "redirect:/feed/" + authorId.toString();
|
||||
}
|
||||
}
|
@ -0,0 +1,52 @@
|
||||
package com.webproglabs.lab1.lab34.controller.mvc_controllers;
|
||||
|
||||
import com.webproglabs.lab1.lab34.controller.ProfileDto;
|
||||
import com.webproglabs.lab1.lab34.model.UserRole;
|
||||
import com.webproglabs.lab1.lab34.services.ProfileService;
|
||||
import org.springframework.security.access.annotation.Secured;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.Model;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
@Controller
|
||||
@RequestMapping("/")
|
||||
public class ProfileMvcController {
|
||||
private final ProfileService profileService;
|
||||
|
||||
public ProfileMvcController(ProfileService profileService) {
|
||||
this.profileService = profileService;
|
||||
}
|
||||
|
||||
@GetMapping
|
||||
public String index() {
|
||||
return "default";
|
||||
}
|
||||
|
||||
@GetMapping(value={"profiles"})
|
||||
@Secured({UserRole.AsString.ADMIN})
|
||||
public String getProfiles(Model model) {
|
||||
model.addAttribute("profiles", profileService.findAllUsers().stream().map(ProfileDto::new).toList());
|
||||
model.addAttribute("profileDto", new ProfileDto());
|
||||
return "profiles";
|
||||
}
|
||||
|
||||
@GetMapping(value = {"profile/{login}"})
|
||||
public String getProfile(@PathVariable String login, Model model) {
|
||||
model.addAttribute("profile", new ProfileDto(profileService.findUserByLogin(login)));
|
||||
return "profilePage";
|
||||
}
|
||||
|
||||
@PostMapping(value = {"profile/{id}"})
|
||||
public String deleteProfile(@PathVariable Long id) {
|
||||
profileService.deleteUser(id);
|
||||
return "redirect:/profiles";
|
||||
}
|
||||
|
||||
@PostMapping(value = {"profile/create/"})
|
||||
public String createProfile(@ModelAttribute ProfileDto profileDto) {
|
||||
profileService.addUser(profileDto.getLogin(), profileDto.getPassword(), new ArrayList<>(), new ArrayList<>());
|
||||
return "redirect:/profiles";
|
||||
}
|
||||
}
|
@ -1,17 +1,17 @@
|
||||
package com.webproglabs.lab1.lab34.dto;
|
||||
package com.webproglabs.lab1.lab34.controller.mvc_controllers;
|
||||
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import javax.validation.constraints.Size;
|
||||
|
||||
public class UserSignUpDto {
|
||||
public class UserSignupDto {
|
||||
@NotBlank
|
||||
@Size(min = 3, max = 64)
|
||||
private String login;
|
||||
@NotBlank
|
||||
@Size(min = 4, max = 64)
|
||||
@Size(min = 6, max = 64)
|
||||
private String password;
|
||||
@NotBlank
|
||||
@Size(min = 4, max = 64)
|
||||
@Size(min = 6, max = 64)
|
||||
private String passwordConfirm;
|
||||
|
||||
public String getLogin() {
|
@ -1,9 +1,7 @@
|
||||
package com.webproglabs.lab1.lab34.mvc;
|
||||
package com.webproglabs.lab1.lab34.controller.mvc_controllers;
|
||||
|
||||
import com.webproglabs.lab1.lab34.dto.UserSignUpDto;
|
||||
import com.webproglabs.lab1.lab34.model.User;
|
||||
import com.webproglabs.lab1.lab34.services.UserService;
|
||||
import javax.validation.Valid;
|
||||
import com.webproglabs.lab1.lab34.model.Profile;
|
||||
import com.webproglabs.lab1.lab34.services.ProfileService;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.Model;
|
||||
import org.springframework.validation.BindingResult;
|
||||
@ -12,25 +10,27 @@ import org.springframework.web.bind.annotation.ModelAttribute;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
|
||||
import javax.validation.Valid;
|
||||
|
||||
@Controller
|
||||
@RequestMapping(UserSignUpMvcController.SIGNUP_URL)
|
||||
public class UserSignUpMvcController {
|
||||
@RequestMapping(UserSignupMvcController.SIGNUP_URL)
|
||||
public class UserSignupMvcController {
|
||||
public static final String SIGNUP_URL = "/signup";
|
||||
|
||||
private final UserService UserService;
|
||||
private final ProfileService userService;
|
||||
|
||||
public UserSignUpMvcController(UserService userService) {
|
||||
UserService = userService;
|
||||
public UserSignupMvcController(ProfileService userService) {
|
||||
this.userService = userService;
|
||||
}
|
||||
|
||||
@GetMapping
|
||||
public String showSignupForm(Model model) {
|
||||
model.addAttribute("userDto", new UserSignUpDto());
|
||||
model.addAttribute("userDto", new UserSignupDto());
|
||||
return "signup";
|
||||
}
|
||||
|
||||
@PostMapping
|
||||
public String signup(@ModelAttribute("userDto") @Valid UserSignUpDto userSignupDto,
|
||||
public String signup(@ModelAttribute("userDto") @Valid UserSignupDto userSignupDto,
|
||||
BindingResult bindingResult,
|
||||
Model model) {
|
||||
if (bindingResult.hasErrors()) {
|
||||
@ -38,8 +38,9 @@ public class UserSignUpMvcController {
|
||||
return "signup";
|
||||
}
|
||||
try {
|
||||
final User NewUser = UserService.createUser(userSignupDto.getLogin(), userSignupDto.getPassword(), userSignupDto.getPasswordConfirm());
|
||||
return "redirect:/login?created=" + NewUser.getLogin();
|
||||
final Profile user = userService.createUser(
|
||||
userSignupDto.getLogin(), userSignupDto.getPassword(), userSignupDto.getPasswordConfirm());
|
||||
return "redirect:/login?created=" + user.getLogin();
|
||||
} catch (Exception e) {
|
||||
model.addAttribute("errors", e.getMessage());
|
||||
return "signup";
|
@ -1,36 +0,0 @@
|
||||
package com.webproglabs.lab1.lab34.dto;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import com.webproglabs.lab1.lab34.model.Category;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.util.List;
|
||||
|
||||
public class CategoryDto {
|
||||
private Long Id;
|
||||
@NotNull
|
||||
private String Name;
|
||||
@NotNull
|
||||
private List<ProductDto> Products;
|
||||
|
||||
public CategoryDto(Category Category) {
|
||||
this.Id = Category.getId();
|
||||
this.Name = Category.getName();
|
||||
this.Products = Category.getProducts().stream().map(ProductDto::new).toList();
|
||||
}
|
||||
|
||||
public CategoryDto(){}
|
||||
|
||||
@JsonProperty(access = JsonProperty.Access.READ_ONLY)
|
||||
public Long getId() {
|
||||
return Id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return Name;
|
||||
}
|
||||
|
||||
public List<ProductDto> getProducts() {
|
||||
return Products;
|
||||
}
|
||||
}
|
@ -1,33 +0,0 @@
|
||||
package com.webproglabs.lab1.lab34.dto;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import com.webproglabs.lab1.lab34.model.Product;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
public class ProductDto {
|
||||
private Long Id;
|
||||
|
||||
@NotNull
|
||||
private String Name;
|
||||
|
||||
@NotNull
|
||||
private Double Cost;
|
||||
|
||||
public ProductDto(Product Product) {
|
||||
this.Id = Product.getId();
|
||||
this.Name = Product.getName();
|
||||
this.Cost = Product.getCost();
|
||||
}
|
||||
|
||||
@JsonProperty(access = JsonProperty.Access.READ_ONLY)
|
||||
public Long getId() {
|
||||
return Id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return Name;
|
||||
}
|
||||
|
||||
public Double getCost() { return Cost; }
|
||||
}
|
@ -1,38 +0,0 @@
|
||||
package com.webproglabs.lab1.lab34.dto;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import com.webproglabs.lab1.lab34.model.Shop;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.util.List;
|
||||
|
||||
public class ShopDto {
|
||||
private Long Id;
|
||||
@NotNull
|
||||
private String Name;
|
||||
@NotNull
|
||||
private List<ProductDto> Products;
|
||||
|
||||
public ShopDto(Shop Shop) {
|
||||
this.Id = Shop.getId();
|
||||
this.Name = Shop.getName();
|
||||
this.Products = Shop.getProducts().stream().map(ProductDto::new).toList();
|
||||
}
|
||||
|
||||
public ShopDto() {}
|
||||
|
||||
@JsonProperty(access = JsonProperty.Access.READ_ONLY)
|
||||
public Long getId() {
|
||||
return Id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return Name;
|
||||
}
|
||||
public void setName(String name) {
|
||||
this.Name = name;
|
||||
}
|
||||
public List<ProductDto> getProducts() {
|
||||
return Products;
|
||||
}
|
||||
}
|
@ -1,52 +0,0 @@
|
||||
package com.webproglabs.lab1.lab34.dto;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import com.webproglabs.lab1.lab34.model.User;
|
||||
import com.webproglabs.lab1.lab34.model.enums.UserRole;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.util.List;
|
||||
|
||||
public class UserDto {
|
||||
private Long Id;
|
||||
|
||||
@NotNull
|
||||
private String Login;
|
||||
|
||||
@NotNull
|
||||
private String Password;
|
||||
|
||||
@NotNull
|
||||
private List<ProductDto> Products;
|
||||
|
||||
@NotNull
|
||||
private UserRole Role;
|
||||
|
||||
public UserDto(User User) {
|
||||
this.Id = User.getId();
|
||||
this.Login = User.getLogin();
|
||||
this.Password = User.getPassword();
|
||||
this.Role = User.getRole();
|
||||
this.Products = User.getProducts().stream().map(ProductDto::new).toList();
|
||||
}
|
||||
|
||||
@JsonProperty(access = JsonProperty.Access.READ_ONLY)
|
||||
public Long getId() {
|
||||
return Id;
|
||||
}
|
||||
|
||||
public String getLogin() {
|
||||
return Login;
|
||||
}
|
||||
|
||||
public String getPassword() {
|
||||
return Password;
|
||||
}
|
||||
|
||||
public List<ProductDto> getProducts() {
|
||||
return Products;
|
||||
}
|
||||
public UserRole getRole() {
|
||||
return Role;
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
package com.webproglabs.lab1.lab34.jwt;
|
||||
|
||||
public class JwtException extends RuntimeException {
|
||||
public JwtException(Throwable throwable) {
|
||||
super(throwable);
|
||||
}
|
||||
|
||||
public JwtException(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
72
src/main/java/com/webproglabs/lab1/lab34/jwt/JwtFilter.java
Normal file
72
src/main/java/com/webproglabs/lab1/lab34/jwt/JwtFilter.java
Normal file
@ -0,0 +1,72 @@
|
||||
package com.webproglabs.lab1.lab34.jwt;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.webproglabs.lab1.lab34.services.ProfileService;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.filter.GenericFilterBean;
|
||||
|
||||
import javax.servlet.FilterChain;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.ServletRequest;
|
||||
import javax.servlet.ServletResponse;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
|
||||
public class JwtFilter extends GenericFilterBean {
|
||||
private static final String AUTHORIZATION = "Authorization";
|
||||
public static final String TOKEN_BEGIN_STR = "Bearer ";
|
||||
|
||||
private final ProfileService userService;
|
||||
|
||||
public JwtFilter(ProfileService userService) {
|
||||
this.userService = userService;
|
||||
}
|
||||
|
||||
private String getTokenFromRequest(HttpServletRequest request) {
|
||||
String bearer = request.getHeader(AUTHORIZATION);
|
||||
if (StringUtils.hasText(bearer) && bearer.startsWith(TOKEN_BEGIN_STR)) {
|
||||
return bearer.substring(TOKEN_BEGIN_STR.length());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private void raiseException(ServletResponse response, int status, String message) throws IOException {
|
||||
if (response instanceof final HttpServletResponse httpResponse) {
|
||||
httpResponse.setContentType(MediaType.APPLICATION_JSON_VALUE);
|
||||
httpResponse.setStatus(status);
|
||||
final byte[] body = new ObjectMapper().writeValueAsBytes(message);
|
||||
response.getOutputStream().write(body);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doFilter(ServletRequest request,
|
||||
ServletResponse response,
|
||||
FilterChain chain) throws IOException, ServletException {
|
||||
if (request instanceof final HttpServletRequest httpRequest) {
|
||||
final String token = getTokenFromRequest(httpRequest);
|
||||
if (StringUtils.hasText(token)) {
|
||||
try {
|
||||
final UserDetails user = userService.loadUserByToken(token);
|
||||
final UsernamePasswordAuthenticationToken auth =
|
||||
new UsernamePasswordAuthenticationToken(user, null, user.getAuthorities());
|
||||
SecurityContextHolder.getContext().setAuthentication(auth);
|
||||
} catch (JwtException e) {
|
||||
raiseException(response, HttpServletResponse.SC_UNAUTHORIZED, e.getMessage());
|
||||
return;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
raiseException(response, HttpServletResponse.SC_INTERNAL_SERVER_ERROR,
|
||||
String.format("Internal error: %s", e.getMessage()));
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
chain.doFilter(request, response);
|
||||
}
|
||||
}
|
@ -0,0 +1,27 @@
|
||||
package com.webproglabs.lab1.lab34.jwt;
|
||||
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
@Configuration
|
||||
@ConfigurationProperties(prefix = "jwt", ignoreInvalidFields = true)
|
||||
public class JwtProperties {
|
||||
private String devToken = "";
|
||||
private Boolean isDev = true;
|
||||
|
||||
public String getDevToken() {
|
||||
return devToken;
|
||||
}
|
||||
|
||||
public void setDevToken(String devToken) {
|
||||
this.devToken = devToken;
|
||||
}
|
||||
|
||||
public Boolean isDev() {
|
||||
return isDev;
|
||||
}
|
||||
|
||||
public void setDev(Boolean dev) {
|
||||
isDev = dev;
|
||||
}
|
||||
}
|
107
src/main/java/com/webproglabs/lab1/lab34/jwt/JwtProvider.java
Normal file
107
src/main/java/com/webproglabs/lab1/lab34/jwt/JwtProvider.java
Normal file
@ -0,0 +1,107 @@
|
||||
package com.webproglabs.lab1.lab34.jwt;
|
||||
|
||||
import com.auth0.jwt.JWT;
|
||||
import com.auth0.jwt.algorithms.Algorithm;
|
||||
import com.auth0.jwt.exceptions.JWTVerificationException;
|
||||
import com.auth0.jwt.interfaces.DecodedJWT;
|
||||
import com.auth0.jwt.interfaces.JWTVerifier;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.time.LocalDate;
|
||||
import java.time.ZoneId;
|
||||
import java.util.Date;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
|
||||
@Component
|
||||
public class JwtProvider {
|
||||
private final static Logger LOG = LoggerFactory.getLogger(JwtProvider.class);
|
||||
|
||||
private final static byte[] HEX_ARRAY = "0123456789ABCDEF".getBytes(StandardCharsets.US_ASCII);
|
||||
private final static String ISSUER = "auth0";
|
||||
|
||||
private final Algorithm algorithm;
|
||||
private final JWTVerifier verifier;
|
||||
|
||||
public JwtProvider(JwtProperties jwtProperties) {
|
||||
if (!jwtProperties.isDev()) {
|
||||
LOG.info("Generate new JWT key for prod");
|
||||
try {
|
||||
final MessageDigest salt = MessageDigest.getInstance("SHA-256");
|
||||
salt.update(UUID.randomUUID().toString().getBytes(StandardCharsets.UTF_8));
|
||||
LOG.info("Use generated JWT key for prod \n{}", bytesToHex(salt.digest()));
|
||||
algorithm = Algorithm.HMAC256(bytesToHex(salt.digest()));
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
throw new JwtException(e);
|
||||
}
|
||||
} else {
|
||||
LOG.info("Use default JWT key for dev \n{}", jwtProperties.getDevToken());
|
||||
algorithm = Algorithm.HMAC256(jwtProperties.getDevToken());
|
||||
}
|
||||
verifier = JWT.require(algorithm)
|
||||
.withIssuer(ISSUER)
|
||||
.build();
|
||||
}
|
||||
|
||||
private static String bytesToHex(byte[] bytes) {
|
||||
byte[] hexChars = new byte[bytes.length * 2];
|
||||
for (int j = 0; j < bytes.length; j++) {
|
||||
int v = bytes[j] & 0xFF;
|
||||
hexChars[j * 2] = HEX_ARRAY[v >>> 4];
|
||||
hexChars[j * 2 + 1] = HEX_ARRAY[v & 0x0F];
|
||||
}
|
||||
return new String(hexChars, StandardCharsets.UTF_8);
|
||||
}
|
||||
|
||||
public String generateToken(String login) {
|
||||
final Date issueDate = Date.from(LocalDate.now()
|
||||
.atStartOfDay(ZoneId.systemDefault())
|
||||
.toInstant());
|
||||
final Date expireDate = Date.from(LocalDate.now()
|
||||
.plusDays(15)
|
||||
.atStartOfDay(ZoneId.systemDefault())
|
||||
.toInstant());
|
||||
return JWT.create()
|
||||
.withIssuer(ISSUER)
|
||||
.withIssuedAt(issueDate)
|
||||
.withExpiresAt(expireDate)
|
||||
.withSubject(login)
|
||||
.sign(algorithm);
|
||||
}
|
||||
|
||||
private DecodedJWT validateToken(String token) {
|
||||
try {
|
||||
return verifier.verify(token);
|
||||
} catch (JWTVerificationException e) {
|
||||
throw new JwtException(String.format("Token verification error: %s", e.getMessage()));
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isTokenValid(String token) {
|
||||
if (!StringUtils.hasText(token)) {
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
validateToken(token);
|
||||
return true;
|
||||
} catch (JwtException e) {
|
||||
LOG.error(e.getMessage());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public Optional<String> getLoginFromToken(String token) {
|
||||
try {
|
||||
return Optional.ofNullable(validateToken(token).getSubject());
|
||||
} catch (JwtException e) {
|
||||
LOG.error(e.getMessage());
|
||||
return Optional.empty();
|
||||
}
|
||||
}
|
||||
}
|
@ -1,77 +0,0 @@
|
||||
package com.webproglabs.lab1.lab34.model;
|
||||
|
||||
import javax.persistence.*;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
@Entity
|
||||
public class Category {
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.AUTO)
|
||||
private Long Id;
|
||||
|
||||
@Column(unique = true)
|
||||
private String Name;
|
||||
|
||||
@OneToMany(mappedBy = "Category")
|
||||
private List<Product> Products = new ArrayList<>();
|
||||
|
||||
public Category(String Name) {
|
||||
this.Name = Name;
|
||||
}
|
||||
|
||||
public Category(){}
|
||||
|
||||
public Long getId() {
|
||||
return Id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return Name;
|
||||
}
|
||||
|
||||
public List<Product> getProducts() {
|
||||
return Products;
|
||||
}
|
||||
|
||||
public void setName(String Name) {
|
||||
this.Name = Name;
|
||||
}
|
||||
|
||||
public void addProduct(Product Product) {
|
||||
this.Products.add(Product);
|
||||
Product.setCategory(this);
|
||||
}
|
||||
|
||||
public void removeProduct(Product Product) {
|
||||
this.Products.remove(Product);
|
||||
Product.setCategory(null);
|
||||
}
|
||||
|
||||
public void setProducts (List<Product> Products) {
|
||||
this.Products = Products;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
Category category = (Category) o;
|
||||
return Objects.equals(Id, category.Id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(Id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Category{" +
|
||||
"Id=" + Id +
|
||||
", Name='" + Name +
|
||||
'}';
|
||||
}
|
||||
}
|
81
src/main/java/com/webproglabs/lab1/lab34/model/Comment.java
Normal file
81
src/main/java/com/webproglabs/lab1/lab34/model/Comment.java
Normal file
@ -0,0 +1,81 @@
|
||||
package com.webproglabs.lab1.lab34.model;
|
||||
|
||||
import javax.persistence.*;
|
||||
import java.util.Objects;
|
||||
|
||||
@Entity
|
||||
public class Comment {
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.AUTO)
|
||||
private Long id;
|
||||
|
||||
private String text;
|
||||
|
||||
@ManyToOne()
|
||||
private Profile owner;
|
||||
|
||||
@ManyToOne()
|
||||
private Post post;
|
||||
|
||||
public Comment(){};
|
||||
public Comment(String text, Profile owner, Post post) {
|
||||
this.text = text;
|
||||
this.owner = owner;
|
||||
this.post = post;
|
||||
}
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public String getText() {
|
||||
return text;
|
||||
}
|
||||
|
||||
public void setText(String text) {
|
||||
this.text = text;
|
||||
}
|
||||
|
||||
public Profile getOwner() {
|
||||
return owner;
|
||||
}
|
||||
public void setOwner(Profile owner) {
|
||||
this.owner.getComments().remove(this);
|
||||
this.owner = owner;
|
||||
if (!owner.getComments().contains(this)) {
|
||||
owner.getComments().add(this);
|
||||
}
|
||||
}
|
||||
|
||||
public Post getPost() {return post; }
|
||||
|
||||
public void setPost(Post post) {
|
||||
this.post.getComments().remove(this);
|
||||
this.post = post;
|
||||
if (!post.getComments().contains(this)) {
|
||||
post.getComments().add(this);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
Comment comment = (Comment) o;
|
||||
return Objects.equals(id, comment.id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(id);
|
||||
}
|
||||
|
||||
public String ToString() {
|
||||
return "Comment{" +
|
||||
"id=" + id +
|
||||
", text='" + text + '\'' +
|
||||
", owner='" + owner.ToString() + '\'' +
|
||||
", post='" + post.ToString() + '\'' +
|
||||
'}';
|
||||
}
|
||||
}
|
90
src/main/java/com/webproglabs/lab1/lab34/model/Post.java
Normal file
90
src/main/java/com/webproglabs/lab1/lab34/model/Post.java
Normal file
@ -0,0 +1,90 @@
|
||||
package com.webproglabs.lab1.lab34.model;
|
||||
|
||||
import javax.persistence.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
@Entity
|
||||
public class Post {
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.AUTO)
|
||||
private Long id;
|
||||
|
||||
private String text;
|
||||
|
||||
@OneToMany(mappedBy = "post", orphanRemoval = true, fetch = FetchType.EAGER)
|
||||
private List<Comment> comments = new ArrayList<Comment>();
|
||||
|
||||
@ManyToOne()
|
||||
private Profile author;
|
||||
|
||||
public Post(){}
|
||||
public Post(String text, Profile author, List<Comment> comments) {
|
||||
this.text = text;
|
||||
this.author = author;
|
||||
for (int i = 0; i < comments.size(); i++) {
|
||||
addComment(comments.get(i));
|
||||
}
|
||||
}
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public String getText() {
|
||||
return text;
|
||||
}
|
||||
|
||||
public void setText(String text) {
|
||||
this.text = text;
|
||||
}
|
||||
|
||||
public Profile getAuthor() {
|
||||
return author;
|
||||
}
|
||||
|
||||
public void setAuthor(Profile author) {
|
||||
this.author.getPosts().remove(this);
|
||||
this.author = author;
|
||||
if (!author.getPosts().contains(this)) {
|
||||
author.getPosts().add(this);
|
||||
}
|
||||
}
|
||||
|
||||
public List<Comment> getComments() { return comments; }
|
||||
public int getCommentsSize() {
|
||||
if (comments == null) return 0;
|
||||
else return comments.size();
|
||||
}
|
||||
|
||||
public void addComment(Comment comment) {
|
||||
this.comments.add(comment);
|
||||
if (comment.getPost() != this) {
|
||||
comment.setPost(this);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
Post post = (Post) o;
|
||||
return Objects.equals(id, post.id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(id);
|
||||
}
|
||||
|
||||
public String ToString() {
|
||||
return "Post{" +
|
||||
"id=" + id +
|
||||
", text='" + text + '\'' +
|
||||
", author='" + author.ToString() + '\'' +
|
||||
", comments='" + getCommentsSize() + '\'' +
|
||||
'}';
|
||||
}
|
||||
|
||||
}
|
@ -1,103 +0,0 @@
|
||||
package com.webproglabs.lab1.lab34.model;
|
||||
|
||||
import javax.persistence.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
@Entity
|
||||
public class Product {
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.AUTO)
|
||||
private Long Id;
|
||||
|
||||
private String Name;
|
||||
|
||||
public Double Cost;
|
||||
|
||||
@ManyToOne()
|
||||
private Shop Shop;
|
||||
|
||||
@ManyToOne()
|
||||
private Category Category;
|
||||
|
||||
@ManyToMany()
|
||||
private List<User> Users = new ArrayList<>();
|
||||
|
||||
public Product (String Name, Double Cost, Shop Shop, Category Category) {
|
||||
this.Name = Name;
|
||||
this.Shop = Shop;
|
||||
this.Cost = Cost;
|
||||
this.Category = Category;
|
||||
}
|
||||
|
||||
public Product(){}
|
||||
|
||||
public Long getId() {
|
||||
return Id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return Name;
|
||||
}
|
||||
|
||||
public Double getCost(){ return Cost; }
|
||||
|
||||
public Shop getShop() {
|
||||
return Shop;
|
||||
}
|
||||
|
||||
public Category getCategory() {
|
||||
return Category;
|
||||
}
|
||||
|
||||
public List<User> getUsers() {
|
||||
return Users;
|
||||
}
|
||||
|
||||
public void setName(String Name) {
|
||||
this.Name = Name;
|
||||
}
|
||||
|
||||
public void setCost(Double Cost) { this.Cost = Cost; }
|
||||
|
||||
public void setShop(Shop Shop) {
|
||||
this.Shop.removeProduct(this);
|
||||
Shop.addProduct(this);
|
||||
}
|
||||
|
||||
public void setCategory(Category Category) {
|
||||
this.Category.removeProduct(this);
|
||||
Category.addProduct(this);
|
||||
}
|
||||
|
||||
public void addUser(User User) {
|
||||
Users.add(User);
|
||||
}
|
||||
|
||||
public void removeUser(User User) {
|
||||
Users.remove(User);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
Product product = (Product) o;
|
||||
return Objects.equals(Id, product.Id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(Id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Product{" +
|
||||
"Id=" + Id +
|
||||
", name='" + Name +
|
||||
'}';
|
||||
}
|
||||
|
||||
}
|
133
src/main/java/com/webproglabs/lab1/lab34/model/Profile.java
Normal file
133
src/main/java/com/webproglabs/lab1/lab34/model/Profile.java
Normal file
@ -0,0 +1,133 @@
|
||||
package com.webproglabs.lab1.lab34.model;
|
||||
|
||||
import javax.persistence.*;
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import javax.validation.constraints.Size;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
@Entity
|
||||
@Table(name="tab_user")
|
||||
public class Profile {
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.AUTO)
|
||||
private Long id;
|
||||
|
||||
@Column(nullable = false, unique = true, length = 64)
|
||||
@NotBlank
|
||||
@Size(min = 3, max = 64)
|
||||
private String login;
|
||||
|
||||
@Column(nullable = false, length = 64)
|
||||
@NotBlank
|
||||
@Size(min = 6, max = 64)
|
||||
private String password;
|
||||
|
||||
private UserRole role;
|
||||
|
||||
public UserRole getRole() {
|
||||
return role;
|
||||
}
|
||||
|
||||
@OneToMany(mappedBy = "owner", orphanRemoval = true, fetch = FetchType.EAGER)
|
||||
private List<Comment> comments = new ArrayList<Comment>();
|
||||
|
||||
@OneToMany(mappedBy = "author", orphanRemoval = true, fetch = FetchType.EAGER)
|
||||
private List<Post> posts = new ArrayList<Post>();
|
||||
|
||||
public Profile(){}
|
||||
public Profile(String login, String password, List<Comment> comments, List<Post> posts) {
|
||||
this.login = login;
|
||||
this.password=password;
|
||||
this.role = UserRole.USER;
|
||||
for (int i = 0; i < comments.size(); i++) {
|
||||
addComment(comments.get(i));
|
||||
}
|
||||
for (int i = 0; i < posts.size(); i++) {
|
||||
addPost(posts.get(i));
|
||||
}
|
||||
};
|
||||
public Profile(String login, String password, List<Comment> comments, List<Post> posts, UserRole role) {
|
||||
this.login = login;
|
||||
this.password=password;
|
||||
this.role = role;
|
||||
for (int i = 0; i < comments.size(); i++) {
|
||||
addComment(comments.get(i));
|
||||
}
|
||||
for (int i = 0; i < posts.size(); i++) {
|
||||
addPost(posts.get(i));
|
||||
}
|
||||
};
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
public List<Comment> getComments() { return comments; }
|
||||
|
||||
public List<Post> getPosts() {return posts; }
|
||||
|
||||
public int getCommentsSize() {
|
||||
if (comments == null) return 0;
|
||||
else return comments.size();
|
||||
}
|
||||
|
||||
public int getPostsSize() {
|
||||
if (posts == null) return 0;
|
||||
else return posts.size();
|
||||
}
|
||||
|
||||
public void addComment(Comment comment) {
|
||||
this.comments.add(comment);
|
||||
if (comment.getOwner() != this) {
|
||||
comment.setOwner(this);
|
||||
}
|
||||
}
|
||||
|
||||
public void addPost(Post post) {
|
||||
this.posts.add(post);
|
||||
if (post.getAuthor() != this) {
|
||||
post.setAuthor(this);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
Profile user = (Profile) o;
|
||||
return Objects.equals(id, user.id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(id);
|
||||
}
|
||||
|
||||
public String ToString() {
|
||||
return "User{" +
|
||||
"id=" + id +
|
||||
", login='" + login + '\'' +
|
||||
", password='" + password + '\'' +
|
||||
", comments='" + getCommentsSize() + '\'' +
|
||||
", comments='" + getPostsSize() + '\'' +
|
||||
'}';
|
||||
}
|
||||
}
|
@ -1,75 +0,0 @@
|
||||
package com.webproglabs.lab1.lab34.model;
|
||||
|
||||
import javax.persistence.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
@Entity
|
||||
public class Shop {
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.AUTO)
|
||||
private Long Id;
|
||||
@Column(unique = true)
|
||||
private String Name;
|
||||
@OneToMany(mappedBy = "Shop")
|
||||
private List<Product> Products = new ArrayList<>();
|
||||
|
||||
public Shop(String Name) {
|
||||
this.Name = Name;
|
||||
}
|
||||
|
||||
public Shop(){}
|
||||
|
||||
public Long getId() {
|
||||
return Id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return Name;
|
||||
}
|
||||
|
||||
public List<Product> getProducts() {
|
||||
return Products;
|
||||
}
|
||||
|
||||
public void setName(String Name) {
|
||||
this.Name = Name;
|
||||
}
|
||||
|
||||
public void addProduct(Product Product) {
|
||||
this.Products.add(Product);
|
||||
Product.setShop(this);
|
||||
}
|
||||
|
||||
public void removeProduct(Product Product) {
|
||||
this.Products.remove(Product);
|
||||
Product.setShop(null);
|
||||
}
|
||||
|
||||
public void setProducts (List<Product> Products) {
|
||||
this.Products = Products;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
Shop shop = (Shop) o;
|
||||
return Objects.equals(Id, shop.Id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(Id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Shop{" +
|
||||
"Id=" + Id +
|
||||
", Name='" + Name +
|
||||
'}';
|
||||
}
|
||||
|
||||
}
|
@ -1,100 +0,0 @@
|
||||
package com.webproglabs.lab1.lab34.model;
|
||||
|
||||
import com.webproglabs.lab1.lab34.model.enums.UserRole;
|
||||
|
||||
import javax.persistence.*;
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import javax.validation.constraints.Size;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
@Entity
|
||||
@Table(name = "users")
|
||||
public class User {
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.AUTO)
|
||||
private Long Id;
|
||||
|
||||
@Column(nullable = false, unique = true, length = 1024)
|
||||
@NotBlank
|
||||
@Size(min = 4, max = 64)
|
||||
private String login;
|
||||
|
||||
@Column(nullable = false, length = 1024)
|
||||
@NotBlank
|
||||
@Size(min = 4, max = 64)
|
||||
private String Password;
|
||||
|
||||
@ManyToMany(mappedBy = "Users")
|
||||
private List<Product> Products = new ArrayList<>();
|
||||
|
||||
private UserRole Role;
|
||||
|
||||
public User(String login, String password, UserRole role) {
|
||||
this.login = login;
|
||||
this.Password = password;
|
||||
this.Role = role;
|
||||
}
|
||||
|
||||
public User(String Login, String Password) {
|
||||
this(Login, Password, UserRole.USER);
|
||||
}
|
||||
|
||||
public User() {}
|
||||
|
||||
public Long getId() {
|
||||
return Id;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
public List<Product> getProducts() {
|
||||
return Products;
|
||||
}
|
||||
|
||||
public void addProduct(Product Product) {
|
||||
this.Products.add(Product);
|
||||
Product.addUser(this);
|
||||
}
|
||||
|
||||
public void removeProduct(Product Product) {
|
||||
this.Products.remove(Product);
|
||||
Product.removeUser(this);
|
||||
}
|
||||
|
||||
public UserRole getRole() {
|
||||
return Role;
|
||||
}
|
||||
|
||||
public void setRole(UserRole Role) {
|
||||
this.Role = Role;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
User user = (User) o;
|
||||
return Objects.equals(Id, user.Id) && Objects.equals(login, user.login);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(Id, login);
|
||||
}
|
||||
}
|
@ -1,11 +1,10 @@
|
||||
package com.webproglabs.lab1.lab34.model.enums;
|
||||
package com.webproglabs.lab1.lab34.model;
|
||||
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
|
||||
public enum UserRole implements GrantedAuthority {
|
||||
ADMIN,
|
||||
USER,
|
||||
;
|
||||
USER;
|
||||
|
||||
private static final String PREFIX = "ROLE_";
|
||||
|
||||
@ -19,5 +18,3 @@ public enum UserRole implements GrantedAuthority {
|
||||
public static final String USER = PREFIX + "USER";
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,57 +0,0 @@
|
||||
package com.webproglabs.lab1.lab34.mvc;
|
||||
|
||||
import com.webproglabs.lab1.lab34.dto.ShopDto;
|
||||
import com.webproglabs.lab1.lab34.model.Shop;
|
||||
import com.webproglabs.lab1.lab34.model.enums.UserRole;
|
||||
import com.webproglabs.lab1.lab34.services.ShopService;
|
||||
import org.springframework.security.access.annotation.Secured;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.Model;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
@Controller
|
||||
@RequestMapping("/shops")
|
||||
public class ShopMvcController {
|
||||
private final ShopService shopService;
|
||||
|
||||
public ShopMvcController(ShopService shopService) {
|
||||
this.shopService = shopService;
|
||||
}
|
||||
|
||||
@GetMapping
|
||||
@Secured({UserRole.AsString.ADMIN})
|
||||
public String getShops(Model model) {
|
||||
model.addAttribute("shops", shopService.findAllShops().stream().map(ShopDto::new).toList());
|
||||
model.addAttribute("shopDto", new ShopDto());
|
||||
return "shops";
|
||||
}
|
||||
|
||||
@GetMapping(value = {"/edit/{Id}"})
|
||||
@Secured({UserRole.AsString.ADMIN})
|
||||
public String getShopEdit(@PathVariable Long Id, Model model) {
|
||||
model.addAttribute("shop", shopService.findShopById(Id));
|
||||
model.addAttribute("shopDto", new ShopDto());
|
||||
return "shopEdit";
|
||||
}
|
||||
|
||||
@PostMapping(value = {"/edit/{Id}"})
|
||||
@Secured({UserRole.AsString.ADMIN})
|
||||
public String editShop(@PathVariable Long Id, @ModelAttribute ShopDto shopDto) {
|
||||
shopService.updateShop(Id, shopDto.getName());
|
||||
return "redirect:/shops";
|
||||
}
|
||||
|
||||
@PostMapping(value = {"/create"})
|
||||
@Secured({UserRole.AsString.ADMIN})
|
||||
public String createShop(@ModelAttribute ShopDto shopDto) {
|
||||
shopService.addShop(shopDto.getName());
|
||||
return "redirect:/shops";
|
||||
}
|
||||
|
||||
@PostMapping(value = {"/delete/{Id}"})
|
||||
@Secured({UserRole.AsString.ADMIN})
|
||||
public String deleteShop(@PathVariable Long Id) {
|
||||
shopService.deleteShop(Id);
|
||||
return "redirect:/shops";
|
||||
}
|
||||
}
|
@ -1,10 +0,0 @@
|
||||
package com.webproglabs.lab1.lab34.repository;
|
||||
|
||||
import com.webproglabs.lab1.lab34.model.Category;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
public interface CategoryRepository extends JpaRepository<Category, Long> {
|
||||
Optional<Category> findById(Long Id);
|
||||
}
|
@ -0,0 +1,10 @@
|
||||
package com.webproglabs.lab1.lab34.repository;
|
||||
|
||||
import com.webproglabs.lab1.lab34.model.Comment;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface CommentRepository extends JpaRepository<Comment, Long> {
|
||||
List<Comment> findByTextLike(String text);
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
package com.webproglabs.lab1.lab34.repository;
|
||||
|
||||
import com.webproglabs.lab1.lab34.model.Comment;
|
||||
import com.webproglabs.lab1.lab34.model.Post;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface PostRepository extends JpaRepository<Post, Long> {
|
||||
List<Post> findByTextLike(String text);
|
||||
}
|
@ -1,9 +0,0 @@
|
||||
package com.webproglabs.lab1.lab34.repository;
|
||||
import com.webproglabs.lab1.lab34.model.Product;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
public interface ProductRepository extends JpaRepository<Product, Long> {
|
||||
Optional<Product> findById(Long Id);
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
package com.webproglabs.lab1.lab34.repository;
|
||||
|
||||
import com.webproglabs.lab1.lab34.model.Post;
|
||||
import com.webproglabs.lab1.lab34.model.Profile;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface ProfileRepository extends JpaRepository<Profile, Long> {
|
||||
List<Profile> findByLoginLike(String login);
|
||||
Profile findOneByLoginIgnoreCase(String login);
|
||||
}
|
@ -1,9 +0,0 @@
|
||||
package com.webproglabs.lab1.lab34.repository;
|
||||
import com.webproglabs.lab1.lab34.model.Shop;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
public interface ShopRepository extends JpaRepository<Shop, Long> {
|
||||
Optional<Shop> findById(Long Id);
|
||||
}
|
@ -1,10 +0,0 @@
|
||||
package com.webproglabs.lab1.lab34.repository;
|
||||
import com.webproglabs.lab1.lab34.model.User;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
public interface UserRepository extends JpaRepository<User, Long> {
|
||||
Optional<User> findById(Long Id);
|
||||
Optional<User> findOneByLoginIgnoreCase(String Login);
|
||||
}
|
@ -1,86 +0,0 @@
|
||||
package com.webproglabs.lab1.lab34.services;
|
||||
|
||||
import javax.persistence.EntityNotFoundException;
|
||||
import javax.transaction.Transactional;
|
||||
|
||||
import com.webproglabs.lab1.lab34.model.Category;
|
||||
import com.webproglabs.lab1.lab34.model.Product;
|
||||
import com.webproglabs.lab1.lab34.repository.CategoryRepository;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Service
|
||||
public class CategoryService {
|
||||
private final CategoryRepository CategoryRepository;
|
||||
|
||||
public CategoryService(CategoryRepository CategoryRepository) {
|
||||
this.CategoryRepository = CategoryRepository;
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public Category addCategory(String Name) {
|
||||
if (!StringUtils.hasText(Name)) {
|
||||
throw new IllegalArgumentException("Name is null or empty");
|
||||
}
|
||||
final Category Category = new Category(Name);
|
||||
CategoryRepository.save(Category);
|
||||
return Category;
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public Category findCategoryById(Long Id) {
|
||||
final Category Category = CategoryRepository.findById(Id).orElse(null);
|
||||
if (Category == null) {
|
||||
throw new EntityNotFoundException(String.format(" Category with id [%s] is not found", Id));
|
||||
}
|
||||
return Category;
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public List<Category> findAllCategories(){
|
||||
return CategoryRepository.findAll();
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public Category updateCategory(Long Id, String Name) {
|
||||
if (!StringUtils.hasText(Name)) {
|
||||
throw new IllegalArgumentException("Name is null or empty");
|
||||
}
|
||||
final Category CurrentCategory = findCategoryById(Id);
|
||||
CurrentCategory.setName(Name);
|
||||
return CategoryRepository.save(CurrentCategory);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public Category deleteCategory(Long Id) {
|
||||
final Category CurrentCategory = findCategoryById(Id);
|
||||
CategoryRepository.delete(CurrentCategory);
|
||||
return CurrentCategory;
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void deleteAllCategories() {
|
||||
CategoryRepository.deleteAll();
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public Product addProductToCategory(Long Id, Product Product) {
|
||||
// TODO возможно придется подключать репозиторий продуктов и там тоже сохранять
|
||||
|
||||
final Category CurrentCategory = findCategoryById(Id);
|
||||
CurrentCategory.addProduct(Product);
|
||||
CategoryRepository.save(CurrentCategory);
|
||||
return Product;
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void removeProductFromCategory(Long Id, Product Product) {
|
||||
// TODO возможно придется подключать репозиторий продуктов и там тоже сохранять
|
||||
|
||||
final Category CurrentCategory = findCategoryById(Id);
|
||||
CurrentCategory.removeProduct(Product);
|
||||
CategoryRepository.save(CurrentCategory);
|
||||
}
|
||||
}
|
@ -0,0 +1,102 @@
|
||||
package com.webproglabs.lab1.lab34.services;
|
||||
|
||||
import com.webproglabs.lab1.lab34.model.Comment;
|
||||
import com.webproglabs.lab1.lab34.model.Post;
|
||||
import com.webproglabs.lab1.lab34.model.Profile;
|
||||
import com.webproglabs.lab1.lab34.repository.CommentRepository;
|
||||
import com.webproglabs.lab1.lab34.repository.PostRepository;
|
||||
import com.webproglabs.lab1.lab34.repository.ProfileRepository;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import javax.persistence.EntityNotFoundException;
|
||||
import javax.transaction.Transactional;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
@Service
|
||||
public class CommentService {
|
||||
|
||||
private final ProfileRepository profileRepository;
|
||||
private final CommentRepository commentRepository;
|
||||
|
||||
private final PostRepository postRepository;
|
||||
|
||||
public CommentService(ProfileRepository profileRepository, CommentRepository commentRepository, PostRepository postRepository) {
|
||||
this.profileRepository = profileRepository;
|
||||
this.commentRepository = commentRepository;
|
||||
this.postRepository = postRepository;
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public Comment findComment(Long id) {
|
||||
final Optional<Comment> comment = commentRepository.findById(id);
|
||||
return comment.orElseThrow(EntityNotFoundException::new);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public List<Comment> findAllComments() {
|
||||
return commentRepository.findAll();
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public List<Post> findFilteredComments(String filter) {
|
||||
List<Post> postList = postRepository.findByTextLike("%" + filter + "%");
|
||||
List<Comment> commentList = commentRepository.findByTextLike("%" + filter + "%");
|
||||
List<Post> allPosts = postRepository.findAll();
|
||||
for(Post post : allPosts) {
|
||||
for (Comment comm : commentList) {
|
||||
if (post.getComments().contains(comm) && !(postList.contains(post))) {
|
||||
postList.add(post);
|
||||
}
|
||||
}
|
||||
}
|
||||
return postList;
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public Comment addComment(String text, Long profileId, Long postId) {
|
||||
if (!StringUtils.hasText(text)) {
|
||||
throw new IllegalArgumentException("Comment data is null or empty");
|
||||
}
|
||||
try{
|
||||
Profile user = profileRepository.findById(profileId).get();
|
||||
Post post = postRepository.findById(postId).get();
|
||||
Comment comment = new Comment(text, user, post);
|
||||
user.addComment(comment);
|
||||
post.addComment(comment);
|
||||
profileRepository.save(user);
|
||||
postRepository.save(post);
|
||||
return commentRepository.save(comment);
|
||||
}
|
||||
catch (Exception exception) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public Comment updateComment(Long id, String text) {
|
||||
if (!StringUtils.hasText(text)) {
|
||||
throw new IllegalArgumentException("Comment data is null or empty");
|
||||
}
|
||||
Comment currentComment = findComment(id);
|
||||
currentComment.setText(text);
|
||||
final Profile owner = currentComment.getOwner();
|
||||
profileRepository.save(owner);
|
||||
final Post post = currentComment.getPost();
|
||||
postRepository.save(post);
|
||||
return commentRepository.save(currentComment);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public Comment deleteComment(Long id) {
|
||||
final Comment currentComment = findComment(id);
|
||||
commentRepository.delete(currentComment);
|
||||
return currentComment;
|
||||
}
|
||||
@Transactional
|
||||
public void deleteAllComments() {
|
||||
commentRepository.deleteAll();
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,90 @@
|
||||
package com.webproglabs.lab1.lab34.services;
|
||||
|
||||
import com.webproglabs.lab1.lab34.model.Comment;
|
||||
import com.webproglabs.lab1.lab34.model.Post;
|
||||
import com.webproglabs.lab1.lab34.model.Profile;
|
||||
import com.webproglabs.lab1.lab34.repository.CommentRepository;
|
||||
import com.webproglabs.lab1.lab34.repository.PostRepository;
|
||||
import com.webproglabs.lab1.lab34.repository.ProfileRepository;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import javax.persistence.EntityNotFoundException;
|
||||
import javax.transaction.Transactional;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
@Service
|
||||
public class PostService {
|
||||
private final PostRepository postRepository;
|
||||
private final CommentRepository commentRepository;
|
||||
private final ProfileRepository profileRepository;
|
||||
|
||||
public PostService(PostRepository postRepository, CommentRepository commentRepository, ProfileRepository profileRepository) {
|
||||
this.postRepository = postRepository;
|
||||
this.commentRepository = commentRepository;
|
||||
this.profileRepository = profileRepository;
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public Post findPost(Long id) {
|
||||
final Optional<Post> post = postRepository.findById(id);
|
||||
return post.orElseThrow(EntityNotFoundException::new);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public List<Post> findAllPosts() {
|
||||
return postRepository.findAll();
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public List<Post> findFilteredPosts(String filter) {
|
||||
List<Post> postList = postRepository.findByTextLike("%" + filter + "%");
|
||||
List<Comment> commentList = commentRepository.findByTextLike("%" + filter + "%");
|
||||
List<Post> allPosts = postRepository.findAll();
|
||||
for(Post post : allPosts) {
|
||||
for (Comment comm : commentList) {
|
||||
if (post.getComments().contains(comm) && !(postList.contains(post))) {
|
||||
postList.add(post);
|
||||
}
|
||||
}
|
||||
}
|
||||
return postList;
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public Post addPost (String text, List<Comment> comments, Long authorId) {
|
||||
if (!StringUtils.hasText(text)) {
|
||||
throw new IllegalArgumentException("Post data is null or empty");
|
||||
}
|
||||
Profile author = profileRepository.findById(authorId).get();
|
||||
Post post = new Post(text, author, comments);
|
||||
author.addPost(post);
|
||||
profileRepository.save(author);
|
||||
return postRepository.save(post);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public Post updatePost(Long id, String text) {
|
||||
if (!StringUtils.hasText(text)) {
|
||||
throw new IllegalArgumentException("Post data is null or empty");
|
||||
}
|
||||
final Post currentPost = findPost(id);
|
||||
currentPost.setText(text);
|
||||
final Profile author = currentPost.getAuthor();
|
||||
profileRepository.save(author);
|
||||
return postRepository.save(currentPost);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public Post deletePost(Long id) {
|
||||
final Post currentPost = findPost(id);
|
||||
postRepository.delete(currentPost);
|
||||
return currentPost;
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void deleteAllPosts() {
|
||||
postRepository.deleteAll();
|
||||
}
|
||||
}
|
@ -1,72 +0,0 @@
|
||||
package com.webproglabs.lab1.lab34.services;
|
||||
|
||||
|
||||
import javax.persistence.EntityNotFoundException;
|
||||
import javax.transaction.Transactional;
|
||||
|
||||
import com.webproglabs.lab1.lab34.model.Category;
|
||||
import com.webproglabs.lab1.lab34.model.Product;
|
||||
import com.webproglabs.lab1.lab34.model.Shop;
|
||||
import com.webproglabs.lab1.lab34.repository.ProductRepository;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Service
|
||||
public class ProductService {
|
||||
private final ProductRepository ProductRepository;
|
||||
|
||||
public ProductService(ProductRepository productRepository) {
|
||||
ProductRepository = productRepository;
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public Product addProduct(String Name, Double Cost, Shop Shop, Category Category) {
|
||||
if (!StringUtils.hasText(Name) || Cost == null || Cost < 0 || Shop == null || Category == null) {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
final Product NewProduct = new Product(Name, Cost, Shop, Category);
|
||||
return ProductRepository.save(NewProduct);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public Product findProductById(Long Id) {
|
||||
final Product CurrentProduct = ProductRepository.findById(Id).orElse(null);
|
||||
if (CurrentProduct == null) {
|
||||
throw new EntityNotFoundException(String.format(" Product with id [%s] is not found", Id));
|
||||
}
|
||||
return CurrentProduct;
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public List<Product> findAllProducts() {
|
||||
return ProductRepository.findAll();
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public Product updateProduct(Long Id, String Name, Double Cost, Shop Shop, Category Category) {
|
||||
final Product CurrentProduct = findProductById(Id);
|
||||
if (!StringUtils.hasText(Name) || Cost == null || Cost < 0 || Shop == null || Category == null) {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
CurrentProduct.setName(Name);
|
||||
CurrentProduct.setCost(Cost);
|
||||
CurrentProduct.setShop(Shop);
|
||||
CurrentProduct.setCategory(Category);
|
||||
return ProductRepository.save(CurrentProduct);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public Product deleteProduct(Long Id) {
|
||||
final Product CurrentProduct = findProductById(Id);
|
||||
ProductRepository.delete(CurrentProduct);
|
||||
return CurrentProduct;
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void deleteAllProducts() {
|
||||
ProductRepository.deleteAll();
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,158 @@
|
||||
package com.webproglabs.lab1.lab34.services;
|
||||
|
||||
import com.webproglabs.lab1.lab34.controller.ProfileDto;
|
||||
import com.webproglabs.lab1.lab34.jwt.JwtException;
|
||||
import com.webproglabs.lab1.lab34.jwt.JwtProvider;
|
||||
import com.webproglabs.lab1.lab34.model.Comment;
|
||||
import com.webproglabs.lab1.lab34.model.Post;
|
||||
import com.webproglabs.lab1.lab34.model.Profile;
|
||||
import com.webproglabs.lab1.lab34.model.UserRole;
|
||||
import com.webproglabs.lab1.lab34.repository.ProfileRepository;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||
import org.springframework.security.core.userdetails.UsernameNotFoundException;
|
||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import javax.persistence.EntityNotFoundException;
|
||||
import javax.transaction.Transactional;
|
||||
import java.util.*;
|
||||
|
||||
@Service
|
||||
public class ProfileService implements UserDetailsService {
|
||||
|
||||
private final ProfileRepository profileRepository;
|
||||
private final PasswordEncoder passwordEncoder;
|
||||
|
||||
private final JwtProvider jwtProvider;
|
||||
|
||||
public ProfileService(ProfileRepository profileRepository, PasswordEncoder passwordEncoder, JwtProvider jwtProvider) {
|
||||
this.profileRepository = profileRepository;
|
||||
this.passwordEncoder = passwordEncoder;
|
||||
this.jwtProvider = jwtProvider;
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public Profile findUser(Long id) {
|
||||
final Optional<Profile> profile = profileRepository.findById(id);
|
||||
return profile.orElseThrow(EntityNotFoundException::new);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public Profile findUserByLogin(String login) {
|
||||
final Optional<Profile> profile = profileRepository.findByLoginLike(login).stream().findFirst();
|
||||
return profile.orElseThrow(EntityNotFoundException::new);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public List<Profile> findAllUsers() {
|
||||
return profileRepository.findAll();
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public Profile addUser(String login, String password, List<Comment> comments, List<Post> posts) {
|
||||
if (!StringUtils.hasText(login) || !StringUtils.hasText(password)) {
|
||||
throw new IllegalArgumentException("User data is null or empty");
|
||||
}
|
||||
final Profile user = new Profile(login, password, comments, posts, UserRole.USER);
|
||||
return profileRepository.save(user);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public Profile addUser(String login, String password, List<Comment> comments, List<Post> posts, UserRole role) {
|
||||
if (!StringUtils.hasText(login) || !StringUtils.hasText(password)) {
|
||||
throw new IllegalArgumentException("User data is null or empty");
|
||||
}
|
||||
final Profile user = new Profile(login, password, comments, posts, role);
|
||||
return profileRepository.save(user);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public Profile createUser(String login, String password, String passwordConfirm) throws Exception {
|
||||
if (findByLogin(login) != null) {
|
||||
throw new Exception("User " + login + " already exists");
|
||||
}
|
||||
final Profile user = new Profile(login, passwordEncoder.encode(password), new ArrayList<>(), new ArrayList<>(), UserRole.USER);
|
||||
if (!Objects.equals(password, passwordConfirm)) {
|
||||
throw new Exception("Passwords not equals");
|
||||
}
|
||||
return profileRepository.save(user);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public Profile createUser(String login, String password, String passwordConfirm, UserRole role) throws Exception {
|
||||
if (findByLogin(login) != null) {
|
||||
throw new Exception("User " + login + " already exists");
|
||||
}
|
||||
final Profile user = new Profile(login, passwordEncoder.encode(password), new ArrayList<>(), new ArrayList<>(), role);
|
||||
if (!Objects.equals(password, passwordConfirm)) {
|
||||
throw new Exception("Passwords not equals");
|
||||
}
|
||||
return profileRepository.save(user);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public Profile updateUser(Long id, String login, String password) {
|
||||
if (!StringUtils.hasText(login) || !StringUtils.hasText(password)) {
|
||||
throw new IllegalArgumentException("User data is null or empty");
|
||||
}
|
||||
final Profile currentUser = findUser(id);
|
||||
currentUser.setLogin(login);
|
||||
currentUser.setPassword(password);
|
||||
return profileRepository.save(currentUser);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public Profile deleteUser(Long id) {
|
||||
final Profile currentUser = findUser(id);
|
||||
profileRepository.delete(currentUser);
|
||||
return currentUser;
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void deleteAllUsers() {
|
||||
profileRepository.deleteAll();
|
||||
}
|
||||
|
||||
public Profile findByLogin(String login) {
|
||||
return profileRepository.findOneByLoginIgnoreCase(login);
|
||||
}
|
||||
@Override
|
||||
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
|
||||
final Profile userEntity = findByLogin(username);
|
||||
if (userEntity == null) {
|
||||
throw new UsernameNotFoundException(username);
|
||||
}
|
||||
return new org.springframework.security.core.userdetails.User(
|
||||
userEntity.getLogin(), userEntity.getPassword(), Collections.singleton(userEntity.getRole()));
|
||||
}
|
||||
|
||||
public String loginAndGetToken(ProfileDto userDto) {
|
||||
|
||||
try {
|
||||
final Profile user = findByLogin(userDto.getLogin());
|
||||
if (user == null) {
|
||||
throw new Exception("Login not found" + userDto.getLogin());
|
||||
}
|
||||
if (!passwordEncoder.matches(userDto.getPassword(), user.getPassword())) {
|
||||
throw new Exception("User not found" + user.getLogin());
|
||||
}
|
||||
return jwtProvider.generateToken(user.getLogin());
|
||||
}
|
||||
catch (Exception e) {
|
||||
var ex = e;
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public UserDetails loadUserByToken(String token) throws UsernameNotFoundException {
|
||||
if (!jwtProvider.isTokenValid(token)) {
|
||||
throw new JwtException("Bad token");
|
||||
}
|
||||
final String userLogin = jwtProvider.getLoginFromToken(token)
|
||||
.orElseThrow(() -> new JwtException("Token is not contain Login"));
|
||||
return loadUserByUsername(userLogin);
|
||||
}
|
||||
}
|
@ -1,85 +0,0 @@
|
||||
package com.webproglabs.lab1.lab34.services;
|
||||
|
||||
import com.webproglabs.lab1.lab34.model.Product;
|
||||
import com.webproglabs.lab1.lab34.model.Shop;
|
||||
import com.webproglabs.lab1.lab34.repository.ShopRepository;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import javax.persistence.EntityNotFoundException;
|
||||
import javax.transaction.Transactional;
|
||||
import java.util.List;
|
||||
|
||||
@Service
|
||||
public class ShopService {
|
||||
private final ShopRepository ShopRepository;
|
||||
|
||||
public ShopService(ShopRepository ShopRepository) {
|
||||
this.ShopRepository = ShopRepository;
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public Shop addShop(String Name) {
|
||||
if (!StringUtils.hasText(Name)) {
|
||||
throw new IllegalArgumentException("Name is null or empty");
|
||||
}
|
||||
final Shop Shop = new Shop(Name);
|
||||
ShopRepository.save(Shop);
|
||||
return Shop;
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public Shop findShopById(Long Id) {
|
||||
final Shop Shop = ShopRepository.findById(Id).orElse(null);
|
||||
if (Shop == null) {
|
||||
throw new EntityNotFoundException(String.format(" Shop with id [%s] is not found", Id));
|
||||
}
|
||||
return Shop;
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public List<Shop> findAllShops(){
|
||||
return ShopRepository.findAll();
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public Shop updateShop(Long Id, String Name) {
|
||||
if (!StringUtils.hasText(Name)) {
|
||||
throw new IllegalArgumentException("Name is null or empty");
|
||||
}
|
||||
final Shop CurrentShop = findShopById(Id);
|
||||
CurrentShop.setName(Name);
|
||||
return ShopRepository.save(CurrentShop);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public Shop deleteShop(Long Id) {
|
||||
final Shop CurrentShop = findShopById(Id);
|
||||
ShopRepository.delete(CurrentShop);
|
||||
return CurrentShop;
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void deleteAllShops() {
|
||||
ShopRepository.deleteAll();
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public Product addProductToShop(Long Id, Product Product) {
|
||||
// TODO возможно придется подключать репозиторий продуктов и там тоже сохранять
|
||||
|
||||
final Shop CurrentShop = findShopById(Id);
|
||||
CurrentShop.addProduct(Product);
|
||||
ShopRepository.save(CurrentShop);
|
||||
return Product;
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void removeProductFromShop(Long Id, Product Product) {
|
||||
// TODO возможно придется подключать репозиторий продуктов и там тоже сохранять
|
||||
|
||||
final Shop CurrentShop = findShopById(Id);
|
||||
CurrentShop.removeProduct(Product);
|
||||
ShopRepository.save(CurrentShop);
|
||||
}
|
||||
}
|
@ -1,117 +0,0 @@
|
||||
package com.webproglabs.lab1.lab34.services;
|
||||
|
||||
import com.webproglabs.lab1.lab34.model.Product;
|
||||
import com.webproglabs.lab1.lab34.model.User;
|
||||
import com.webproglabs.lab1.lab34.model.enums.UserRole;
|
||||
import com.webproglabs.lab1.lab34.repository.UserRepository;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||
import org.springframework.security.core.userdetails.UsernameNotFoundException;
|
||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import javax.persistence.EntityNotFoundException;
|
||||
import javax.transaction.Transactional;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
@Service
|
||||
public class UserService implements UserDetailsService {
|
||||
private final UserRepository UserRepository;
|
||||
private final PasswordEncoder PasswordEncoder;
|
||||
|
||||
public UserService(UserRepository UserRepository, PasswordEncoder PasswordEncoder) {
|
||||
this.UserRepository = UserRepository;
|
||||
this.PasswordEncoder = PasswordEncoder;
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public User findUserById(Long Id) {
|
||||
User CurrentUser = UserRepository.findById(Id).orElse(null);
|
||||
if (CurrentUser == null) {
|
||||
throw new EntityNotFoundException(String.format(" User with id [%s] is not found", Id));
|
||||
}
|
||||
return CurrentUser;
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public User findUserByLogin(String Login) {
|
||||
if (!StringUtils.hasText(Login)) {
|
||||
throw new IllegalArgumentException("Login is null or empty");
|
||||
}
|
||||
User CurrentUser = UserRepository.findOneByLoginIgnoreCase(Login).orElse(null);
|
||||
return CurrentUser;
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public List<User> findAllUsers() {
|
||||
return UserRepository.findAll();
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public User createUser(String Login, String Password, String PasswordConfirm) {
|
||||
return createUser(Login, Password, PasswordConfirm, UserRole.USER);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public User createUser(String Login, String Password, String PasswordConfirm, UserRole Role) {
|
||||
if (findUserByLogin(Login) != null) {
|
||||
throw new IllegalArgumentException("User " + Login + " already exists");
|
||||
}
|
||||
if (!Objects.equals(Password, PasswordConfirm)) {
|
||||
throw new IllegalArgumentException("Passwords not equals");
|
||||
}
|
||||
final User NewUser = new User(Login, PasswordEncoder.encode(Password), Role);
|
||||
return UserRepository.save(NewUser);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public User updateUser(Long Id, String Login, String Password, UserRole Role) {
|
||||
if (!StringUtils.hasText(Login) || !StringUtils.hasText(Password)) {
|
||||
throw new IllegalArgumentException("User data is null or empty");
|
||||
}
|
||||
final User CurrentUser = findUserById(Id);
|
||||
CurrentUser.setLogin(Login);
|
||||
CurrentUser.setPassword(Password);
|
||||
CurrentUser.setRole(Role);
|
||||
return UserRepository.save(CurrentUser);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public User deleteUser(Long Id) {
|
||||
final User CurrentUser = findUserById(Id);
|
||||
UserRepository.delete(CurrentUser);
|
||||
return CurrentUser;
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void deleteAllUsers(){
|
||||
UserRepository.deleteAll();
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void addProductToUser(Long Id, Product Product) {
|
||||
// TODO возможно придется подключать репозиторий продуктов и там тоже сохранять
|
||||
|
||||
final User CurrentUser = findUserById(Id);
|
||||
CurrentUser.addProduct(Product);
|
||||
UserRepository.save(CurrentUser);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void removeProductFromUser(Long Id, Product Product) {
|
||||
// TODO возможно придется подключать репозиторий продуктов и там тоже сохранять
|
||||
|
||||
final User CurrentUser = findUserById(Id);
|
||||
CurrentUser.removeProduct(Product);
|
||||
UserRepository.save(CurrentUser);
|
||||
}
|
||||
|
||||
@Override
|
||||
public UserDetails loadUserByUsername(String Login) throws UsernameNotFoundException {
|
||||
final User UserEntity = findUserByLogin(Login);
|
||||
return new org.springframework.security.core.userdetails.User(UserEntity.getLogin(), UserEntity.getPassword(), Collections.singleton(UserEntity.getRole()));
|
||||
}
|
||||
}
|
@ -1,13 +0,0 @@
|
||||
package com.webproglabs.lab1.lab34.validation;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
public class ValidationException extends RuntimeException {
|
||||
public <T> ValidationException(Set<String> errors) {
|
||||
super(String.join("\n", errors));
|
||||
}
|
||||
|
||||
public <T> ValidationException(String error) {
|
||||
super(error);
|
||||
}
|
||||
}
|
@ -1,27 +0,0 @@
|
||||
package com.webproglabs.lab1.lab34.validation;
|
||||
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.validation.ConstraintViolation;
|
||||
import javax.validation.Validation;
|
||||
import javax.validation.Validator;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Component
|
||||
public class ValidatorUtil {
|
||||
private final Validator validator;
|
||||
|
||||
public ValidatorUtil() {
|
||||
this.validator = Validation.buildDefaultValidatorFactory().getValidator();
|
||||
}
|
||||
|
||||
public <T> void validate(T object) {
|
||||
final Set<ConstraintViolation<T>> errors = validator.validate(object);
|
||||
if (!errors.isEmpty()) {
|
||||
throw new ValidationException(errors.stream()
|
||||
.map(ConstraintViolation::getMessage)
|
||||
.collect(Collectors.toSet()));
|
||||
}
|
||||
}
|
||||
}
|
31
src/main/resources/templates/commentModal.html
Normal file
31
src/main/resources/templates/commentModal.html
Normal file
@ -0,0 +1,31 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en"
|
||||
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
|
||||
layout:decorate="~{feedPosts}" xmlns:th="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
</head>
|
||||
<body>
|
||||
<div layout:fragment="modalFeed">
|
||||
|
||||
<div class="modal fade" id="commentCreate" tabindex="-1" role="dialog" aria-labelledby="commentCreateLabel" aria-hidden="true">
|
||||
<div class="modal-dialog" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title" id="commentCreateLabel">Создать комментарий</h5>
|
||||
</div>
|
||||
<form th:action="@{/feed/comment/{id}/{postId}/{text} (id=${selectedProfile.id}, postId=${selectedPost.id}, text=${commentInputField}) }" method="post" class="modal-body text-center">
|
||||
<p>Текст комментария:</p>
|
||||
<input th:value="${commentInputField}" id="commentInputField" name="commentInputField" type="text" class="mb-2">
|
||||
<br>
|
||||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Закрыть</button>
|
||||
<button type="submit" class="btn btn-primary" >Сохранить</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
@ -3,33 +3,44 @@
|
||||
xmlns:th="http://www.thymeleaf.org"
|
||||
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
|
||||
xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity5">
|
||||
>
|
||||
<head>
|
||||
<meta charset="UTF-8"/>
|
||||
<title>Магазин</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1"/>
|
||||
<link rel="icon" href="/favicon.svg">
|
||||
<script type="text/javascript" src="/webjars/bootstrap/5.1.3/js/bootstrap.bundle.min.js"></script>
|
||||
<script src="https://code.jquery.com/jquery-3.6.0.min.js" integrity="sha256-/xUj+3OJU5yExlq6GSYGSHk7tPXikynS7ogEvDej/m4=" crossorigin="anonymous"></script>
|
||||
<meta charset="UTF-8"/>
|
||||
<title>Лабораторная работа 5</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1"/>
|
||||
<link rel="icon" href="/favicon.svg">
|
||||
<script type="text/javascript" src="/webjars/bootstrap/5.1.3/js/bootstrap.bundle.min.js"></script>
|
||||
<script src="https://code.jquery.com/jquery-3.6.0.min.js" integrity="sha256-/xUj+3OJU5yExlq6GSYGSHk7tPXikynS7ogEvDej/m4=" crossorigin="anonymous"></script>
|
||||
|
||||
<link rel="stylesheet" href="/webjars/bootstrap/5.1.3/css/bootstrap.min.css"/>
|
||||
<link rel="stylesheet" href="/webjars/font-awesome/6.1.0/css/all.min.css"/>
|
||||
<link rel="stylesheet" href="/css/style.css"/>
|
||||
<link rel="stylesheet" href="/webjars/bootstrap/5.1.3/css/bootstrap.min.css"/>
|
||||
<link rel="stylesheet" href="/webjars/font-awesome/6.1.0/css/all.min.css"/>
|
||||
<link rel="stylesheet" href="/css/style.css"/>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div>
|
||||
<p class='text-center m-3 h3'>Магазин</p>
|
||||
</div>
|
||||
<div>
|
||||
<div>
|
||||
<p class='text-center m-3 h3'> Лабораторная работа 5</p>
|
||||
</div>
|
||||
<div>
|
||||
<p class='h4 text-center'>
|
||||
<a sec:authorize="isAuthenticated()" href="/logout" class="text-decoration-none m-3">
|
||||
Выход
|
||||
</a>
|
||||
<a sec:authorize="hasRole('ROLE_ADMIN')" href="/profiles" class="text-decoration-none m-3">Профили</a>
|
||||
<a sec:authorize="isAuthenticated()" href="/feed/" class="text-decoration-none m-3">Лента</a>
|
||||
<a sec:authorize="isAuthenticated()" href="/logout" class="text-decoration-none m-3">
|
||||
Выход
|
||||
</a>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div >
|
||||
<div >
|
||||
<div layout:fragment="content"></div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
<script type="text/javascript">
|
||||
window.onload = () => {
|
||||
$('#postEdit').modal('show');
|
||||
$('#commentCreate').modal('show');
|
||||
$('#commentEdit').modal('show');
|
||||
}
|
||||
|
||||
</body>
|
||||
</script>
|
||||
</html>
|
30
src/main/resources/templates/editCommentModal.html
Normal file
30
src/main/resources/templates/editCommentModal.html
Normal file
@ -0,0 +1,30 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en"
|
||||
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
|
||||
layout:decorate="~{feedPosts}" xmlns:th="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
</head>
|
||||
<body>
|
||||
<div layout:fragment="modalFeed">
|
||||
|
||||
<div class="modal fade" id="commentEdit" tabindex="-1" role="dialog" aria-labelledby="commentEditLabel" aria-hidden="true">
|
||||
<div class="modal-dialog" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title" id="commentEditLabel">Редактировать комментарий</h5>
|
||||
</div>
|
||||
<form th:action="@{/feed/editComment/{id}/{commentId}/{text} (id=${selectedProfile.id}, commentId=${selectedComment.id}, text=${commentEditField}) }" method="post" class="modal-body text-center">
|
||||
<p>Новый текст комментария:</p>
|
||||
<input th:attr="value = ${selectedComment.text}" id="commentEditField" name="commentEditField" type="text" class="mb-2">
|
||||
<br>
|
||||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Закрыть</button>
|
||||
<button type="submit" class="btn btn-primary" >Изменить</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
32
src/main/resources/templates/editPostModal.html
Normal file
32
src/main/resources/templates/editPostModal.html
Normal file
@ -0,0 +1,32 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en"
|
||||
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
|
||||
layout:decorate="~{feedPosts}" xmlns:th="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div layout:fragment="modalFeed">
|
||||
|
||||
<div class="modal fade" id="postEdit" tabindex="-1" role="dialog" aria-labelledby="postEditLabel" aria-hidden="true">
|
||||
<div class="modal-dialog" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title" id="postEditLabel">Редактировать пост</h5>
|
||||
</div>
|
||||
<form th:action="@{/feed/editPost/{id}/{authorId}/{text} (id=${selectedPost.id}, authorId=${selectedProfile.id}, text=${postEditField} ) }" method="post" class="modal-body text-center">
|
||||
<p>Текст поста:</p>
|
||||
<input th:attr="value = ${selectedPost.text}" id="postEditField" name="postEditField" type="text" class="mb-2">
|
||||
<br>
|
||||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Закрыть</button>
|
||||
<button type="submit" class="btn btn-primary" >Сохранить</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
@ -4,10 +4,10 @@
|
||||
layout:decorate="~{default}">
|
||||
<body>
|
||||
<div class="container" layout:fragment="content">
|
||||
<div class="alert alert-danger">
|
||||
<span th:text="${error}"></span>
|
||||
</div>
|
||||
<a href="/">На главную</a>
|
||||
<div class="alert alert-danger">
|
||||
<span th:text="${error}"></span>
|
||||
</div>
|
||||
<a href="/">На главную</a>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
32
src/main/resources/templates/feed.html
Normal file
32
src/main/resources/templates/feed.html
Normal file
@ -0,0 +1,32 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en"
|
||||
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
|
||||
layout:decorate="~{default}">
|
||||
<head>
|
||||
</head>
|
||||
<body>
|
||||
<div layout:fragment="content">
|
||||
<div class="text-center">
|
||||
|
||||
<!-- <div class="dropdown text-center mx-auto w-25 ">-->
|
||||
<!-- <div class="text-end mt-3">-->
|
||||
<!-- <button class="btn btn-secondary dropdown-toggle ms-3 mb-3 " type="button" data-bs-toggle="dropdown" aria-expanded="false">-->
|
||||
<!-- Выбор пользователя-->
|
||||
<!-- </button>-->
|
||||
<!-- <ul class="dropdown-menu " >-->
|
||||
<!-- <li th:each="profile: ${profiles}">-->
|
||||
<!-- <a class="dropdown-item" th:href="@{/feed/{id}(id=${profile.id})}" th:text="${profile.login}">-->
|
||||
<!-- </a>-->
|
||||
<!-- </li>-->
|
||||
<!-- </ul>-->
|
||||
<!-- </div>-->
|
||||
<!-- </div>-->
|
||||
<div layout:fragment="contentFeed"></div>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
|
||||
|
||||
</html>
|
106
src/main/resources/templates/feedPosts.html
Normal file
106
src/main/resources/templates/feedPosts.html
Normal file
@ -0,0 +1,106 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en"
|
||||
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
|
||||
layout:decorate="~{feed}" xmlns:th="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
</head>
|
||||
<body>
|
||||
<div layout:fragment="contentFeed">
|
||||
|
||||
<div class='h3 mb-3 mx-auto w-25'>
|
||||
<p class="text-end" th:text="${selectedProfile.login}"></p>
|
||||
</div>
|
||||
<div class='h3 m-3 d-flex justify-content-between text-center mx-auto w-25'>
|
||||
|
||||
Лента
|
||||
<button type='button' class="btn btn-primary ms-5 mb-3 " data-bs-toggle="modal" data-bs-target="#postCreate">
|
||||
Добавить новый пост
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<form th:action="@{/feed/filter/{id}/{text} (id=${selectedProfile.id}, text=${searchField}) }" method="get">
|
||||
<input th:value="${searchField}" id="searchField" name="searchField" type="text" class="mb-2" style="width: 20%" placeholder="Поиск...">
|
||||
<button type='submit' class="btn btn-primary mb-2" style="width: 5%">
|
||||
Найти
|
||||
</button>
|
||||
</form>
|
||||
|
||||
|
||||
<div th:each="post: ${posts}" class="text-center mx-auto w-25 mb-3 ">
|
||||
<div class="border p-2">
|
||||
<p th:text="${post.text}" class="h4 text-start"></p>
|
||||
<div class="d-flex justify-content-between fst-italic">
|
||||
<div>
|
||||
Автор:
|
||||
<a th:text="${post.getAuthor()}" class="text-start fst-italic" th:href="@{/profile/{login}(login=${post.getAuthor()})}"></a>
|
||||
</div>
|
||||
<div th:if="${selectedProfile.getLogin() == post.getAuthor()}" class="d-flex justify-content-between fst-italic">
|
||||
<form th:action="@{/feed/deletePost/{id}/{authorId} (id=${post.id}, authorId=${selectedProfile.id})}" method="post" >
|
||||
<button type="submit" class="btn btn-danger me-1 mb-1 ms-2" >
|
||||
<i class="fa fa-trash" aria-hidden="true"></i>
|
||||
</button>
|
||||
</form>
|
||||
<form th:action="@{/feed/postModal/{id}/{authorId} (id=${post.id}, authorId=${selectedProfile.id})}" method="get">
|
||||
<button type="submit" class="btn btn-warning mb-1" data-bs-toggle="modal" data-bs-target="#postEdit" >
|
||||
<i class="fa fa-pencil" aria-hidden="true"></i>
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="border p-2" th:if="${post.comments.size() > 0}" >
|
||||
<div class="text-start">
|
||||
<p class="text-start h5">Комментарии:</p>
|
||||
<div th:each="comment: ${post.comments}" >
|
||||
<p class="fst-italic" th:text="${comment.getAuthor() + ':'}"> </p>
|
||||
<div class="d-flex justify-content-between fst-italic">
|
||||
<p class="ms-3" th:text="${comment.text}"></p>
|
||||
|
||||
<div th:if="${selectedProfile.getLogin() == comment.getAuthor()}" class="d-flex justify-content-between fst-italic">
|
||||
<form th:action="@{/feed/deleteComment/{id}/{authorId} (id=${comment.id}, authorId=${selectedProfile.id})}" method="post" >
|
||||
<button type="submit" class="btn btn-danger me-1 mb-1"> <i class="fa fa-trash" aria-hidden="true"> </i> </button>
|
||||
</form>
|
||||
<form th:action="@{/feed/commentEditModal/{id}/{authorId} (id=${comment.id}, authorId=${selectedProfile.id})}" method="get">
|
||||
<button type="submit" class="btn btn-warning mb-1" data-bs-toggle="modal" data-bs-target="#postEdit" >
|
||||
<i class="fa fa-pencil" aria-hidden="true"></i>
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<form th:action="@{/feed/commentModal/{authorId}/{postId}/ ( authorId=${selectedProfile.id}, postId=${post.id} ) }" method="get" class="text-end">
|
||||
<button type="submit" class="btn btn-info mb-3" data-bs-toggle="modal" data-bs-target="#commentCreate">Добавить комментарий</button>
|
||||
</form>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="modal fade" id="postCreate" tabindex="-1" role="dialog" aria-labelledby="postCreateLabel" aria-hidden="true">
|
||||
<div class="modal-dialog" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title" id="postCreateLabel">Создать пост</h5>
|
||||
</div>
|
||||
<form th:action="@{/feed/post/{id}/{text} (id=${selectedProfile.id}, text=${postInputField}) }" method="post" class="modal-body text-center">
|
||||
<p>Текст поста:</p>
|
||||
<input th:value="${postInputField}" id="postInputField" name="postInputField" type="text" class="mb-2">
|
||||
<br>
|
||||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Закрыть</button>
|
||||
<button type="submit" class="btn btn-primary" >Сохранить</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<div layout:fragment="modalFeed"></div>
|
||||
|
||||
|
||||
</div>
|
||||
</body>
|
||||
|
||||
</html>
|
@ -4,27 +4,27 @@
|
||||
layout:decorate="~{default}">
|
||||
<body>
|
||||
<div class="container" layout:fragment="content">
|
||||
<div th:if="${param.error}" class="alert alert-danger margin-bottom">
|
||||
Пользователь не найден или пароль указан не верно
|
||||
</div>
|
||||
<div th:if="${param.logout}" class="alert alert-success margin-bottom">
|
||||
Выход успешно произведен
|
||||
</div>
|
||||
<div th:if="${param.created}" class="alert alert-success margin-bottom">
|
||||
Пользователь '<span th:text="${param.created}"></span>' успешно создан
|
||||
</div>
|
||||
<form th:action="@{/login}" method="post" class="container-padding">
|
||||
<div class="mb-3">
|
||||
<input type="text" name="username" id="username" class="form-control"
|
||||
placeholder="Логин" required="true" autofocus="true"/>
|
||||
<div th:if="${param.error}" class="alert alert-danger margin-bottom">
|
||||
Пользователь не найден или пароль указан не верно
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<input type="password" name="password" id="password" class="form-control"
|
||||
placeholder="Пароль" required="true"/>
|
||||
<div th:if="${param.logout}" class="alert alert-success margin-bottom">
|
||||
Выход успешно произведен
|
||||
</div>
|
||||
<button type="submit" class="btn btn-success button-fixed">Войти</button>
|
||||
<a class="btn btn-primary button-fixed" href="/signup">Регистрация</a>
|
||||
</form>
|
||||
<div th:if="${param.created}" class="alert alert-success margin-bottom">
|
||||
Пользователь '<span th:text="${param.created}"></span>' успешно создан
|
||||
</div>
|
||||
<form th:action="@{/login}" method="post" class="container-padding">
|
||||
<div class="mb-3">
|
||||
<input type="text" name="username" id="username" class="form-control"
|
||||
placeholder="Логин" required="true" autofocus="true"/>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<input type="password" name="password" id="password" class="form-control"
|
||||
placeholder="Пароль" required="true"/>
|
||||
</div>
|
||||
<button type="submit" class="btn btn-success button-fixed">Войти</button>
|
||||
<a class="btn btn-primary button-fixed" href="/signup">Регистрация</a>
|
||||
</form>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
29
src/main/resources/templates/profilePage.html
Normal file
29
src/main/resources/templates/profilePage.html
Normal file
@ -0,0 +1,29 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en"
|
||||
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
|
||||
layout:decorate="~{default}">
|
||||
<head>
|
||||
</head>
|
||||
<body>
|
||||
<div layout:fragment="content">
|
||||
|
||||
<div class="text-center">
|
||||
<div class="text-start mx-auto w-25 border p-5">
|
||||
<p class='h5'>Профиль</p>
|
||||
<p th:text="${'Логин: ' + profile.login}"></p>
|
||||
<p class='h6 '>Список постов пользователя: </p>
|
||||
|
||||
<div th:if="${profile.posts.size()>0}">
|
||||
<div th:each="post: ${profile.posts}">
|
||||
<p th:text="${post.text}" class="mb-3 ms-2 border p-2"></p>
|
||||
</div>
|
||||
</div>
|
||||
<p th:unless="${profile.posts.size()>0}">
|
||||
Нет постов
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
56
src/main/resources/templates/profiles.html
Normal file
56
src/main/resources/templates/profiles.html
Normal file
@ -0,0 +1,56 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en"
|
||||
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
|
||||
layout:decorate="~{default}" xmlns:th="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
</head>
|
||||
<body>
|
||||
<div layout:fragment="content" class="text-center">
|
||||
|
||||
<div th:each="profile: ${profiles}" class="mb-2">
|
||||
<div class="text-center">
|
||||
<div class="text-start mx-auto w-25 border p-3">
|
||||
<p class='h5'>Профиль</p>
|
||||
<p th:text="${'Логин: ' + profile.login}"></p>
|
||||
<p class='h6 '>Список постов пользователя: </p>
|
||||
|
||||
<div th:if="${profile.posts.size()>0}">
|
||||
<div th:each="post: ${profile.posts}">
|
||||
<p th:text="${post.text}" class="mb-3 ms-2 border p-2"></p>
|
||||
</div>
|
||||
</div>
|
||||
<p th:unless="${profile.posts.size()>0}">
|
||||
Нет постов
|
||||
</p>
|
||||
<div class="text-end">
|
||||
<form action="#" th:action="@{/profile/{id} (id=${profile.id})}" method="post" >
|
||||
<button type="submit" class="btn btn-danger">Удалить</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="modal fade" id="profileCreate" tabindex="-1" role="dialog" aria-labelledby="profileCreateLabel" aria-hidden="true">
|
||||
<div class="modal-dialog" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title" id="profileCreateLabel">Регистрация профиля</h5>
|
||||
</div>
|
||||
<form action="#" th:action="@{/profile/create/}" th:object="${profileDto}" method="post" class="modal-body text-center">
|
||||
<p>Логин: </p>
|
||||
<input th:field="${profileDto.login}" type="text" class="mb-2 form-control" required="true" />
|
||||
<br>
|
||||
<p>Пароль: </p>
|
||||
<input th:field="${profileDto.password}" type="text" class="mb-2 form-control" required="true" />
|
||||
<br>
|
||||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Закрыть</button>
|
||||
<button type="submit" class="btn btn-primary" >Регистрация</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
@ -1,21 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en"
|
||||
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
|
||||
layout:decorate="~{default}"
|
||||
xmlns:th="http://www.w3.org/1999/xhtml">
|
||||
<body>
|
||||
<div class="container container-padding" layout:fragment="content">
|
||||
<div>Name</div>
|
||||
<div th:text="${shop.name}"></div>
|
||||
<form action="#" th:action="@{/shops/edit/{id} (id=${shop.id})}" th:object="${shopDto}" method="post">
|
||||
<p>New Name:</p>
|
||||
<input th:field="${shopDto.name}" type="text" class="mb-2 form-control" required="true" />
|
||||
<button type="submit" class="" >Edit</button>
|
||||
</form>
|
||||
<div th:each="product: ${shop.products}">
|
||||
<p th:text="${product.name}"></p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
@ -1,27 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en"
|
||||
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
|
||||
layout:decorate="~{default}"
|
||||
xmlns:th="http://www.w3.org/1999/xhtml">
|
||||
<body>
|
||||
<div class="container container-padding" layout:fragment="content">
|
||||
|
||||
<div th:each="shop: ${shops}">
|
||||
<div th:text="${'Name: ' + shop.name}" class="m-3"></div>
|
||||
<form action="#" th:action="@{/shops/delete/{id} (id=${shop.id})}" method="post">
|
||||
<button type="submit" class="" >Delete</button>
|
||||
</form>
|
||||
<form action="#" th:action="@{/shops/edit/{id} (id=${shop.id})}" method="get">
|
||||
<button type="submit" class="">Edit</button>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<form action="#" th:action="@{/shops/create}" th:object="${shopDto}" method="post">
|
||||
<p>Name:</p>
|
||||
<input th:field="${shopDto.name}" type="text" class="mb-2 form-control" required="true" />
|
||||
<button type="submit" class="" >Add</button>
|
||||
</form>
|
||||
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
@ -1,8 +1,7 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en"
|
||||
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
|
||||
layout:decorate="~{default}"
|
||||
>
|
||||
layout:decorate="~{default}">
|
||||
<body>
|
||||
<div class="container container-padding" layout:fragment="content">
|
||||
<div th:if="${errors}" th:text="${errors}" class="margin-bottom alert alert-danger"></div>
|
||||
@ -13,11 +12,11 @@
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<input type="password" class="form-control" th:field="${userDto.password}"
|
||||
placeholder="Пароль" required="true" minlength="4" maxlength="64"/>
|
||||
placeholder="Пароль" required="true" minlength="6" maxlength="64"/>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<input type="password" class="form-control" th:field="${userDto.passwordConfirm}"
|
||||
placeholder="Пароль (подтверждение)" required="true" minlength="4" maxlength="64"/>
|
||||
placeholder="Пароль (подтверждение)" required="true" minlength="6" maxlength="64"/>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<button type="submit" class="btn btn-success button-fixed">Создать</button>
|
||||
|
Loading…
Reference in New Issue
Block a user