Compare commits
No commits in common. "socialnetwork" and "master" have entirely different histories.
socialnetw
...
master
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.models.UserRole;
|
||||
import com.webproglabs.lab1.mvc.UserSignupMvcController;
|
||||
import com.webproglabs.lab1.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);
|
||||
|
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);
|
||||
|
@ -1,18 +0,0 @@
|
||||
package com.webproglabs.lab1.dao;
|
||||
|
||||
import com.webproglabs.lab1.models.Post;
|
||||
import com.webproglabs.lab1.models.Topic;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.Query;
|
||||
import org.springframework.data.repository.query.Param;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
public interface PostRepository extends JpaRepository<Post, Long> {
|
||||
List<Post> findByTextLike(String text);
|
||||
Optional<Post> findById(Long Id);
|
||||
|
||||
@Query("SELECT p FROM Post p WHERE p.topic = :topic AND p.text LIKE %:text%")
|
||||
List<Post> findPostsByTextInTopic(@Param("text") String text, @Param("topic") Topic topic);
|
||||
}
|
@ -1,15 +0,0 @@
|
||||
package com.webproglabs.lab1.dao;
|
||||
|
||||
import com.webproglabs.lab1.models.Post;
|
||||
import com.webproglabs.lab1.models.Topic;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.Query;
|
||||
import org.springframework.data.repository.query.Param;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
public interface TopicRepository extends JpaRepository<Topic, Long> {
|
||||
Optional<Topic> findById(Long Id);
|
||||
|
||||
}
|
@ -1,12 +0,0 @@
|
||||
package com.webproglabs.lab1.dao;
|
||||
|
||||
import com.webproglabs.lab1.models.User;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
public interface UserRepository extends JpaRepository<User, Long> {
|
||||
Optional<User> findOneByLoginIgnoreCase(String login);
|
||||
Optional<User> findById(Long Id);
|
||||
}
|
@ -1,54 +0,0 @@
|
||||
package com.webproglabs.lab1.dto;
|
||||
|
||||
import com.webproglabs.lab1.models.Comment;
|
||||
import com.webproglabs.lab1.models.Post;
|
||||
import com.webproglabs.lab1.models.Topic;
|
||||
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class TopicDto {
|
||||
private Long id;
|
||||
@NotBlank
|
||||
private String name;
|
||||
@NotBlank
|
||||
private String description;
|
||||
@NotNull
|
||||
private List<PostDto> posts = new ArrayList<>();
|
||||
|
||||
public TopicDto(Topic topic) {
|
||||
this.id = topic.getId();
|
||||
this.name = topic.getName();
|
||||
this.description = topic.getDescription();
|
||||
for(Post post: topic.getPosts()){
|
||||
posts.add(new PostDto(post));
|
||||
}
|
||||
}
|
||||
public TopicDto(){}
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
public List<PostDto> getPosts() {
|
||||
return posts;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public void setDescription(String description) {
|
||||
this.description = description;
|
||||
}
|
||||
}
|
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();
|
||||
}
|
||||
}
|
@ -1,15 +1,11 @@
|
||||
package com.webproglabs.lab1.dto;
|
||||
package com.webproglabs.lab1.lab34.controller;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import com.webproglabs.lab1.models.Comment;
|
||||
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import com.webproglabs.lab1.lab34.model.Comment;
|
||||
|
||||
public class CommentDto {
|
||||
private Long id;
|
||||
@NotBlank
|
||||
private String text;
|
||||
@NotBlank
|
||||
private String authorLogin;
|
||||
|
||||
public CommentDto(Comment comment) {
|
||||
@ -23,8 +19,5 @@ public class CommentDto {
|
||||
return id;
|
||||
}
|
||||
public String getText() {return text;}
|
||||
public void setText(String text) {
|
||||
this.text = 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();
|
||||
}
|
||||
}
|
@ -1,21 +1,18 @@
|
||||
package com.webproglabs.lab1.dto;
|
||||
package com.webproglabs.lab1.lab34.controller;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import com.webproglabs.lab1.models.Comment;
|
||||
import com.webproglabs.lab1.models.Post;
|
||||
import com.webproglabs.lab1.lab34.model.Comment;
|
||||
import com.webproglabs.lab1.lab34.model.Post;
|
||||
import com.webproglabs.lab1.lab34.model.Profile;
|
||||
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class PostDto {
|
||||
private Long id;
|
||||
@NotBlank
|
||||
private String text;
|
||||
@NotNull
|
||||
private List<CommentDto> comments = new ArrayList<>();
|
||||
@NotBlank
|
||||
|
||||
private String authorLogin;
|
||||
|
||||
public PostDto(Post post){
|
||||
@ -26,16 +23,12 @@ public class PostDto {
|
||||
}
|
||||
this.authorLogin = post.getAuthor().getLogin();
|
||||
}
|
||||
public PostDto(){}
|
||||
|
||||
@JsonProperty(access = JsonProperty.Access.READ_ONLY)
|
||||
public long getId() {
|
||||
return id;
|
||||
}
|
||||
public String getText() {return text;}
|
||||
public void setText(String text) {
|
||||
this.text = 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;
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -1,41 +1,35 @@
|
||||
package com.webproglabs.lab1.dto;
|
||||
package com.webproglabs.lab1.lab34.controller;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import com.webproglabs.lab1.models.Comment;
|
||||
import com.webproglabs.lab1.models.Post;
|
||||
import com.webproglabs.lab1.models.User;
|
||||
import com.webproglabs.lab1.models.UserRole;
|
||||
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 javax.validation.constraints.NotBlank;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class UserDto {
|
||||
public class ProfileDto {
|
||||
private Long id;
|
||||
@NotBlank
|
||||
private String login;
|
||||
@NotBlank
|
||||
private String password;
|
||||
@NotNull
|
||||
private List<CommentDto> comments = new ArrayList<>();
|
||||
@NotNull
|
||||
|
||||
private List<PostDto> posts = new ArrayList<>();
|
||||
@NotNull
|
||||
|
||||
private UserRole role;
|
||||
|
||||
public ProfileDto(){}
|
||||
|
||||
public UserDto(){}
|
||||
|
||||
public UserDto(User user){
|
||||
this.id = user.getId();
|
||||
this.login = user.getLogin();
|
||||
this.password = user.getPassword();
|
||||
this.role = user.getRole();
|
||||
for(Comment comment: user.getComments()){
|
||||
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: user.getPosts()) {
|
||||
for (Post post: profile.getPosts()) {
|
||||
posts.add(new PostDto(post));
|
||||
}
|
||||
}
|
||||
@ -47,9 +41,10 @@ public class UserDto {
|
||||
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 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.dto;
|
||||
package com.webproglabs.lab1.lab34.controller.mvc_controllers;
|
||||
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import javax.validation.constraints.Size;
|
||||
|
||||
public class UserSignupDto {
|
||||
@NotBlank
|
||||
@Size(min = 4, max = 64)
|
||||
@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,8 +1,7 @@
|
||||
package com.webproglabs.lab1.mvc;
|
||||
package com.webproglabs.lab1.lab34.controller.mvc_controllers;
|
||||
|
||||
import com.webproglabs.lab1.dto.UserSignupDto;
|
||||
import com.webproglabs.lab1.models.User;
|
||||
import com.webproglabs.lab1.services.UserService;
|
||||
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;
|
||||
@ -14,28 +13,23 @@ import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import javax.validation.Valid;
|
||||
|
||||
@Controller
|
||||
@RequestMapping()
|
||||
@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) {
|
||||
public UserSignupMvcController(ProfileService userService) {
|
||||
this.userService = userService;
|
||||
}
|
||||
|
||||
@GetMapping
|
||||
public String toFeed() {
|
||||
return "redirect:/feed";
|
||||
}
|
||||
|
||||
@GetMapping(SIGNUP_URL)
|
||||
public String showSignupForm(Model model) {
|
||||
model.addAttribute("userDto", new UserSignupDto());
|
||||
return "signup";
|
||||
}
|
||||
|
||||
@PostMapping(SIGNUP_URL)
|
||||
@PostMapping
|
||||
public String signup(@ModelAttribute("userDto") @Valid UserSignupDto userSignupDto,
|
||||
BindingResult bindingResult,
|
||||
Model model) {
|
||||
@ -44,12 +38,12 @@ public class UserSignupMvcController {
|
||||
return "signup";
|
||||
}
|
||||
try {
|
||||
final User user = userService.createUser(userSignupDto.getLogin(), userSignupDto.getPassword(), userSignupDto.getPasswordConfirm());
|
||||
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";
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -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,4 +1,4 @@
|
||||
package com.webproglabs.lab1.models;
|
||||
package com.webproglabs.lab1.lab34.model;
|
||||
|
||||
import javax.persistence.*;
|
||||
import java.util.Objects;
|
||||
@ -12,13 +12,13 @@ public class Comment {
|
||||
private String text;
|
||||
|
||||
@ManyToOne()
|
||||
private User owner;
|
||||
private Profile owner;
|
||||
|
||||
@ManyToOne()
|
||||
private Post post;
|
||||
|
||||
public Comment(){};
|
||||
public Comment(String text, User owner, Post post) {
|
||||
public Comment(String text, Profile owner, Post post) {
|
||||
this.text = text;
|
||||
this.owner = owner;
|
||||
this.post = post;
|
||||
@ -36,11 +36,10 @@ public class Comment {
|
||||
this.text = text;
|
||||
}
|
||||
|
||||
public User getOwner() {
|
||||
public Profile getOwner() {
|
||||
return owner;
|
||||
}
|
||||
|
||||
public void setOwner(User owner) {
|
||||
public void setOwner(Profile owner) {
|
||||
this.owner.getComments().remove(this);
|
||||
this.owner = owner;
|
||||
if (!owner.getComments().contains(this)) {
|
@ -1,4 +1,4 @@
|
||||
package com.webproglabs.lab1.models;
|
||||
package com.webproglabs.lab1.lab34.model;
|
||||
|
||||
import javax.persistence.*;
|
||||
import java.util.ArrayList;
|
||||
@ -17,16 +17,15 @@ public class Post {
|
||||
private List<Comment> comments = new ArrayList<Comment>();
|
||||
|
||||
@ManyToOne()
|
||||
private User author;
|
||||
|
||||
@ManyToOne()
|
||||
private Topic topic;
|
||||
private Profile author;
|
||||
|
||||
public Post(){}
|
||||
public Post(String text, User author, Topic topic) {
|
||||
public Post(String text, Profile author, List<Comment> comments) {
|
||||
this.text = text;
|
||||
this.author = author;
|
||||
this.topic = topic;
|
||||
for (int i = 0; i < comments.size(); i++) {
|
||||
addComment(comments.get(i));
|
||||
}
|
||||
}
|
||||
|
||||
public Long getId() {
|
||||
@ -41,11 +40,11 @@ public class Post {
|
||||
this.text = text;
|
||||
}
|
||||
|
||||
public User getAuthor() {
|
||||
public Profile getAuthor() {
|
||||
return author;
|
||||
}
|
||||
|
||||
public void setAuthor(User author) {
|
||||
public void setAuthor(Profile author) {
|
||||
this.author.getPosts().remove(this);
|
||||
this.author = author;
|
||||
if (!author.getPosts().contains(this)) {
|
||||
@ -53,19 +52,11 @@ public class Post {
|
||||
}
|
||||
}
|
||||
|
||||
public Topic getTopic() {
|
||||
return topic;
|
||||
}
|
||||
|
||||
public void setTopic(Topic topic) {
|
||||
this.topic.getPosts().remove(this);
|
||||
this.topic = topic;
|
||||
if (!topic.getPosts().contains(this)) {
|
||||
topic.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);
|
||||
@ -92,6 +83,8 @@ public class Post {
|
||||
"id=" + id +
|
||||
", text='" + text + '\'' +
|
||||
", author='" + author.ToString() + '\'' +
|
||||
", comments='" + getCommentsSize() + '\'' +
|
||||
'}';
|
||||
}
|
||||
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
package com.webproglabs.lab1.models;
|
||||
package com.webproglabs.lab1.lab34.model;
|
||||
|
||||
import javax.persistence.*;
|
||||
import javax.validation.constraints.NotBlank;
|
||||
@ -8,8 +8,8 @@ import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
@Entity
|
||||
@Table(name="users")
|
||||
public class User {
|
||||
@Table(name="tab_user")
|
||||
public class Profile {
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.AUTO)
|
||||
private Long id;
|
||||
@ -21,28 +21,43 @@ public class User {
|
||||
|
||||
@Column(nullable = false, length = 64)
|
||||
@NotBlank
|
||||
@Size(min = 4, max = 64)
|
||||
@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 User(){}
|
||||
public User(String login, String password) {
|
||||
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 User(String login, String password, UserRole role) {
|
||||
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() {
|
||||
@ -53,10 +68,6 @@ public class User {
|
||||
return login;
|
||||
}
|
||||
|
||||
public UserRole getRole() {
|
||||
return role;
|
||||
}
|
||||
|
||||
public void setLogin(String login) {
|
||||
this.login = login;
|
||||
}
|
||||
@ -73,6 +84,16 @@ public class User {
|
||||
|
||||
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) {
|
||||
@ -91,7 +112,7 @@ public class User {
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
User user = (User) o;
|
||||
Profile user = (Profile) o;
|
||||
return Objects.equals(id, user.id);
|
||||
}
|
||||
|
||||
@ -105,6 +126,8 @@ public class User {
|
||||
"id=" + id +
|
||||
", login='" + login + '\'' +
|
||||
", password='" + password + '\'' +
|
||||
", comments='" + getCommentsSize() + '\'' +
|
||||
", comments='" + getPostsSize() + '\'' +
|
||||
'}';
|
||||
}
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
package com.webproglabs.lab1.models;
|
||||
package com.webproglabs.lab1.lab34.model;
|
||||
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
|
@ -1,12 +1,10 @@
|
||||
package com.webproglabs.lab1.dao;
|
||||
package com.webproglabs.lab1.lab34.repository;
|
||||
|
||||
import com.webproglabs.lab1.models.Comment;
|
||||
import com.webproglabs.lab1.lab34.model.Comment;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
public interface CommentRepository extends JpaRepository<Comment, Long> {
|
||||
List<Comment> findByTextLike(String text);
|
||||
Optional<Comment> findById(Long Id);
|
||||
}
|
@ -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);
|
||||
}
|
@ -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,11 +1,11 @@
|
||||
package com.webproglabs.lab1.services;
|
||||
package com.webproglabs.lab1.lab34.services;
|
||||
|
||||
import com.webproglabs.lab1.dao.CommentRepository;
|
||||
import com.webproglabs.lab1.dao.PostRepository;
|
||||
import com.webproglabs.lab1.dao.UserRepository;
|
||||
import com.webproglabs.lab1.models.Comment;
|
||||
import com.webproglabs.lab1.models.Post;
|
||||
import com.webproglabs.lab1.models.User;
|
||||
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;
|
||||
|
||||
@ -16,18 +16,20 @@ import java.util.Optional;
|
||||
|
||||
@Service
|
||||
public class CommentService {
|
||||
private final UserRepository userRepository;
|
||||
private final CommentRepository commentRepository;
|
||||
private final PostRepository postRepository;
|
||||
|
||||
public CommentService(UserRepository profileRepository, CommentRepository commentRepository, PostRepository postRepository) {
|
||||
this.userRepository = profileRepository;
|
||||
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 findCommentById(Long id) {
|
||||
public Comment findComment(Long id) {
|
||||
final Optional<Comment> comment = commentRepository.findById(id);
|
||||
return comment.orElseThrow(EntityNotFoundException::new);
|
||||
}
|
||||
@ -38,17 +40,32 @@ public class CommentService {
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public Comment addComment(String text, Long userId, Long postId) {
|
||||
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{
|
||||
User user = userRepository.findById(userId).get();
|
||||
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);
|
||||
userRepository.save(user);
|
||||
profileRepository.save(user);
|
||||
postRepository.save(post);
|
||||
return commentRepository.save(comment);
|
||||
}
|
||||
@ -62,10 +79,10 @@ public class CommentService {
|
||||
if (!StringUtils.hasText(text)) {
|
||||
throw new IllegalArgumentException("Comment data is null or empty");
|
||||
}
|
||||
Comment currentComment = findCommentById(id);
|
||||
Comment currentComment = findComment(id);
|
||||
currentComment.setText(text);
|
||||
final User owner = currentComment.getOwner();
|
||||
userRepository.save(owner);
|
||||
final Profile owner = currentComment.getOwner();
|
||||
profileRepository.save(owner);
|
||||
final Post post = currentComment.getPost();
|
||||
postRepository.save(post);
|
||||
return commentRepository.save(currentComment);
|
||||
@ -73,8 +90,13 @@ public class CommentService {
|
||||
|
||||
@Transactional
|
||||
public Comment deleteComment(Long id) {
|
||||
final Comment currentComment = findCommentById(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();
|
||||
}
|
||||
}
|
@ -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,78 +0,0 @@
|
||||
package com.webproglabs.lab1.models;
|
||||
|
||||
import javax.persistence.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
@Entity
|
||||
public class Topic {
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
private Long id;
|
||||
|
||||
private String name;
|
||||
private String description;
|
||||
|
||||
@OneToMany(mappedBy = "topic", orphanRemoval = true, fetch = FetchType.EAGER)
|
||||
private List<Post> posts;
|
||||
|
||||
public Topic(String name, String description) {
|
||||
this.name = name;
|
||||
this.description = description;
|
||||
this.posts = new ArrayList<Post>();
|
||||
}
|
||||
public Topic(){}
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
public List<Post> getPosts() {
|
||||
return posts;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public void setDescription(String description) {
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
public void addPost(Post post) {
|
||||
this.posts.add(post);
|
||||
if (post.getTopic() != this) {
|
||||
post.setTopic(this);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
Topic topic = (Topic) o;
|
||||
return Objects.equals(id, topic.id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(id);
|
||||
}
|
||||
|
||||
public String ToString() {
|
||||
return "Topic{" +
|
||||
"id=" + id +
|
||||
", name='" + name + '\'' +
|
||||
", description='" + description + '\'' +
|
||||
'}';
|
||||
}
|
||||
}
|
@ -1,142 +0,0 @@
|
||||
package com.webproglabs.lab1.mvc;
|
||||
|
||||
import com.webproglabs.lab1.dto.CommentDto;
|
||||
import com.webproglabs.lab1.dto.PostDto;
|
||||
import com.webproglabs.lab1.dto.TopicDto;
|
||||
import com.webproglabs.lab1.dto.UserDto;
|
||||
import com.webproglabs.lab1.services.CommentService;
|
||||
import com.webproglabs.lab1.services.PostService;
|
||||
import com.webproglabs.lab1.services.TopicService;
|
||||
import com.webproglabs.lab1.services.UserService;
|
||||
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.*;
|
||||
|
||||
@Controller
|
||||
@RequestMapping("/feed")
|
||||
public class FeedMvcController {
|
||||
private final UserService userService;
|
||||
private final PostService postService;
|
||||
private final CommentService commentService;
|
||||
private final TopicService topicService;
|
||||
|
||||
public FeedMvcController(UserService userService, PostService postService, CommentService commentService, TopicService topicService) {
|
||||
this.userService = userService;
|
||||
this.postService = postService;
|
||||
this.commentService = commentService;
|
||||
this.topicService = topicService;
|
||||
}
|
||||
|
||||
@GetMapping
|
||||
public String getFeedPage(Model model) {
|
||||
model.addAttribute("topics", topicService.findAllTopics().stream().map(TopicDto::new).toList());
|
||||
return "feed";
|
||||
}
|
||||
|
||||
@GetMapping(value = {"/{id}"})
|
||||
public String getFeedPageWithTopic(@PathVariable Long id, Model model) {
|
||||
model.addAttribute("profiles", userService.findAllUsers().stream().map(UserDto::new).toList());
|
||||
model.addAttribute("posts", topicService.findTopicById(id).getPosts().stream().map(PostDto::new).toList());
|
||||
model.addAttribute("topics", topicService.findAllTopics().stream().map(TopicDto::new).toList());
|
||||
|
||||
UserDetails principal = (UserDetails)SecurityContextHolder.getContext().getAuthentication().getPrincipal();
|
||||
var user = userService.findUserByLogin(principal.getUsername());
|
||||
model.addAttribute("selectedProfile", new UserDto(userService.findUserById(user.getId())));
|
||||
|
||||
model.addAttribute("selectedTopic", new TopicDto(topicService.findTopicById(id)));
|
||||
|
||||
return "feedPosts";
|
||||
}
|
||||
|
||||
@GetMapping(value= {"/filter/{id}/"})
|
||||
public String getFeedPageFiltered(@PathVariable Long id, @RequestParam(value="searchField") String searchField, Model model) {
|
||||
model.addAttribute("profiles", userService.findAllUsers().stream().map(UserDto::new).toList());
|
||||
model.addAttribute("topics", topicService.findAllTopics().stream().map(TopicDto::new).toList());
|
||||
UserDetails principal = (UserDetails)SecurityContextHolder.getContext().getAuthentication().getPrincipal();
|
||||
var user = userService.findUserByLogin(principal.getUsername());
|
||||
model.addAttribute("selectedProfile", new UserDto(userService.findUserById(user.getId())));
|
||||
model.addAttribute("selectedTopic", new TopicDto(topicService.findTopicById(id)));
|
||||
|
||||
model.addAttribute("posts", postService.findPostsInTopicByText(searchField, id).stream().map(PostDto::new).toList());
|
||||
|
||||
return "feedPosts";
|
||||
}
|
||||
|
||||
@PostMapping(value={"/{topicId}/post/{id}/"})
|
||||
public String createPost(@PathVariable Long topicId, @PathVariable Long id, @RequestParam(value="postInputField") String postInputField) {
|
||||
postService.addPost(postInputField, id, topicId);
|
||||
return "redirect:/feed/" + topicId.toString();
|
||||
}
|
||||
|
||||
@PostMapping(value = {"/deletePost/{id}/{topicId}"})
|
||||
public String deletePost(@PathVariable Long id, @PathVariable Long topicId) {
|
||||
postService.deletePost(id);
|
||||
return "redirect:/feed/" + topicId.toString();
|
||||
}
|
||||
|
||||
@GetMapping(value = {"postModal/{id}/{topicId}"})
|
||||
public String getPostEditModal(@PathVariable Long id,@PathVariable Long topicId, Model model) {
|
||||
model.addAttribute("selectedPost", new PostDto(postService.findPostById(id)));
|
||||
model.addAttribute("profiles", userService.findAllUsers().stream().map(UserDto::new).toList());
|
||||
model.addAttribute("posts", topicService.findTopicById(topicId).getPosts().stream().map(PostDto::new).toList());
|
||||
|
||||
UserDetails principal = (UserDetails)SecurityContextHolder.getContext().getAuthentication().getPrincipal();
|
||||
var user = userService.findUserByLogin(principal.getUsername());
|
||||
model.addAttribute("selectedProfile", new UserDto(userService.findUserById(user.getId())));
|
||||
model.addAttribute("selectedTopic", new TopicDto(topicService.findTopicById(topicId)));
|
||||
return "editPostModal";
|
||||
}
|
||||
|
||||
@PostMapping(value = {"editPost/{id}/{topicId}/"})
|
||||
public String editPost(@PathVariable Long id, @PathVariable Long topicId, @RequestParam(value="postEditField") String postEditField) {
|
||||
postService.updatePost(id, postEditField);
|
||||
return "redirect:/feed/" + topicId.toString();
|
||||
}
|
||||
|
||||
@GetMapping(value = {"commentModal/{topicId}/{postId}"})
|
||||
public String getCommentModal(@PathVariable Long topicId,@PathVariable Long postId, Model model) {
|
||||
model.addAttribute("selectedPost", new PostDto(postService.findPostById(postId)));
|
||||
model.addAttribute("profiles", userService.findAllUsers().stream().map(UserDto::new).toList());
|
||||
model.addAttribute("posts", topicService.findTopicById(topicId).getPosts().stream().map(PostDto::new).toList());
|
||||
|
||||
UserDetails principal = (UserDetails)SecurityContextHolder.getContext().getAuthentication().getPrincipal();
|
||||
var user = userService.findUserByLogin(principal.getUsername());
|
||||
model.addAttribute("selectedProfile", new UserDto(userService.findUserById(user.getId())));
|
||||
model.addAttribute("selectedTopic", new TopicDto(topicService.findTopicById(topicId)));
|
||||
return "commentModal";
|
||||
}
|
||||
|
||||
@PostMapping(value = {"comment/{authorId}/{topicId}/{postId}/"})
|
||||
public String createComment(@PathVariable Long authorId, @PathVariable Long topicId, @PathVariable Long postId, @RequestParam(value="commentInputField") String commentInputField) {
|
||||
commentService.addComment(commentInputField, authorId, postId);
|
||||
return "redirect:/feed/" + topicId.toString();
|
||||
}
|
||||
|
||||
@PostMapping(value = {"/deleteComment/{id}/{topicId}"})
|
||||
public String deleteComment(@PathVariable Long id, @PathVariable Long topicId) {
|
||||
commentService.deleteComment(id);
|
||||
return "redirect:/feed/" + topicId.toString();
|
||||
}
|
||||
|
||||
@GetMapping(value = {"commentEditModal/{id}/{topicId}"})
|
||||
public String getCommentEditModal(@PathVariable Long id,@PathVariable Long topicId, Model model) {
|
||||
model.addAttribute("selectedComment", new CommentDto(commentService.findCommentById(id)));
|
||||
model.addAttribute("profiles", userService.findAllUsers().stream().map(UserDto::new).toList());
|
||||
model.addAttribute("posts", topicService.findTopicById(topicId).getPosts().stream().map(PostDto::new).toList());
|
||||
|
||||
UserDetails principal = (UserDetails)SecurityContextHolder.getContext().getAuthentication().getPrincipal();
|
||||
var user = userService.findUserByLogin(principal.getUsername());
|
||||
model.addAttribute("selectedProfile", new UserDto(userService.findUserById(user.getId())));
|
||||
model.addAttribute("selectedTopic", new TopicDto(topicService.findTopicById(topicId)));
|
||||
return "editCommentModal";
|
||||
}
|
||||
|
||||
@PostMapping(value = {"editComment/{topicId}/{commentId}/"})
|
||||
public String editComment(@PathVariable Long topicId,@PathVariable Long commentId, @RequestParam(value="commentEditField") String commentEditField) {
|
||||
commentService.updateComment(commentId, commentEditField);
|
||||
return "redirect:/feed/" + topicId.toString();
|
||||
}
|
||||
|
||||
}
|
@ -1,58 +0,0 @@
|
||||
package com.webproglabs.lab1.mvc;
|
||||
|
||||
import com.webproglabs.lab1.dto.TopicDto;
|
||||
import com.webproglabs.lab1.dto.UserSignupDto;
|
||||
import com.webproglabs.lab1.models.UserRole;
|
||||
import com.webproglabs.lab1.services.TopicService;
|
||||
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("/topic")
|
||||
public class TopicMvcController {
|
||||
private final TopicService topicService;
|
||||
|
||||
public TopicMvcController(TopicService topicService) {
|
||||
this.topicService = topicService;
|
||||
}
|
||||
|
||||
@GetMapping
|
||||
@Secured({UserRole.AsString.ADMIN})
|
||||
public String getTopics(Model model) {
|
||||
model.addAttribute("topics", topicService.findAllTopics().stream().map(TopicDto::new).toList());
|
||||
model.addAttribute("topicDto", new TopicDto());
|
||||
return "topics";
|
||||
}
|
||||
|
||||
@PostMapping(value = {"/create"})
|
||||
@Secured({UserRole.AsString.ADMIN})
|
||||
public String createTopic(@ModelAttribute TopicDto topicDto) {
|
||||
topicService.addTopic(topicDto.getName(), topicDto.getDescription());
|
||||
return "redirect:/topic";
|
||||
}
|
||||
|
||||
@PostMapping(value = {"/delete/{Id}"})
|
||||
@Secured({UserRole.AsString.ADMIN})
|
||||
public String deleteTopic(@PathVariable Long Id) {
|
||||
topicService.deleteTopic(Id);
|
||||
return "redirect:/topic";
|
||||
}
|
||||
|
||||
@GetMapping(value = {"/edit/{Id}"})
|
||||
@Secured({UserRole.AsString.ADMIN})
|
||||
public String getTopicEdit(@PathVariable Long Id, Model model) {
|
||||
model.addAttribute("topic", new TopicDto(topicService.findTopicById(Id)));
|
||||
model.addAttribute("topicDto", new TopicDto(topicService.findTopicById(Id)));
|
||||
return "topicEdit";
|
||||
}
|
||||
|
||||
@PostMapping(value = {"/edit/{Id}"})
|
||||
@Secured({UserRole.AsString.ADMIN})
|
||||
public String editTopic(@PathVariable Long Id, @ModelAttribute TopicDto topicDto) {
|
||||
topicService.updateTopic(Id, topicDto.getName(), topicDto.getDescription());
|
||||
return "redirect:/topic";
|
||||
}
|
||||
|
||||
}
|
@ -1,79 +0,0 @@
|
||||
package com.webproglabs.lab1.mvc;
|
||||
|
||||
import com.webproglabs.lab1.dto.UserDto;
|
||||
import com.webproglabs.lab1.dto.UserSignupDto;
|
||||
import com.webproglabs.lab1.models.User;
|
||||
import com.webproglabs.lab1.models.UserRole;
|
||||
import com.webproglabs.lab1.services.UserService;
|
||||
import org.springframework.security.access.annotation.Secured;
|
||||
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.validation.BindingResult;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.validation.Valid;
|
||||
|
||||
@Controller
|
||||
@RequestMapping("/users")
|
||||
public class UserMvcController {
|
||||
private final UserService userService;
|
||||
|
||||
public UserMvcController(UserService userService) {
|
||||
this.userService = userService;
|
||||
}
|
||||
|
||||
@GetMapping
|
||||
@Secured({UserRole.AsString.ADMIN})
|
||||
public String getUsersPage(Model model){
|
||||
model.addAttribute("profiles", userService.findAllUsers().stream().map(UserDto::new).toList());
|
||||
return "users";
|
||||
}
|
||||
|
||||
@PostMapping(value = {"/{id}"})
|
||||
@Secured({UserRole.AsString.ADMIN})
|
||||
public String deleteUser(@PathVariable Long id) {
|
||||
userService.deleteUser(id);
|
||||
return "redirect:/users";
|
||||
}
|
||||
|
||||
@GetMapping(value = {"/{login}"})
|
||||
public String getUserPage(@PathVariable String login, Model model) {
|
||||
model.addAttribute("user", new UserDto(userService.findUserByLogin(login)));
|
||||
return "userPage";
|
||||
}
|
||||
|
||||
@GetMapping(value = {"/settings"})
|
||||
public String getUserEditPage(Model model) {
|
||||
UserDetails principal = (UserDetails) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
|
||||
var currentUser = userService.findUserByLogin(principal.getUsername());
|
||||
model.addAttribute("user", new UserDto(userService.findUserById(currentUser.getId())));
|
||||
model.addAttribute("userDto", new UserSignupDto());
|
||||
|
||||
return "userEditPage";
|
||||
}
|
||||
|
||||
@PostMapping(value = {"/edit/{id}"})
|
||||
public String editUserData(@PathVariable Long id, @ModelAttribute("userDto") @Valid UserSignupDto userSignupDto,
|
||||
BindingResult bindingResult,
|
||||
Model model) {
|
||||
UserDetails principal = (UserDetails) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
|
||||
var currentUser = userService.findUserByLogin(principal.getUsername());
|
||||
model.addAttribute("user", new UserDto(userService.findUserById(currentUser.getId())));
|
||||
model.addAttribute("userDto", new UserSignupDto());
|
||||
|
||||
if (bindingResult.hasErrors()) {
|
||||
model.addAttribute("errors", bindingResult.getAllErrors());
|
||||
return "userEditPage";
|
||||
}
|
||||
try {
|
||||
final User user = userService.updateUser(id, userSignupDto.getLogin(), userSignupDto.getPassword(), userSignupDto.getPasswordConfirm());
|
||||
model.addAttribute("success", "Данные успешно изменены");
|
||||
return "userEditPage";
|
||||
} catch (Exception e) {
|
||||
model.addAttribute("errors", e.getMessage());
|
||||
return "userEditPage";
|
||||
}
|
||||
}
|
||||
}
|
@ -1,86 +0,0 @@
|
||||
package com.webproglabs.lab1.services;
|
||||
|
||||
import com.webproglabs.lab1.dao.CommentRepository;
|
||||
import com.webproglabs.lab1.dao.PostRepository;
|
||||
import com.webproglabs.lab1.dao.TopicRepository;
|
||||
import com.webproglabs.lab1.dao.UserRepository;
|
||||
import com.webproglabs.lab1.models.Comment;
|
||||
import com.webproglabs.lab1.models.Post;
|
||||
import com.webproglabs.lab1.models.Topic;
|
||||
import com.webproglabs.lab1.models.User;
|
||||
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 UserRepository userRepository;
|
||||
|
||||
private final TopicRepository topicRepository;
|
||||
|
||||
public PostService(PostRepository postRepository, CommentRepository commentRepository, UserRepository userRepository, TopicRepository topicRepository) {
|
||||
this.postRepository = postRepository;
|
||||
this.commentRepository = commentRepository;
|
||||
this.userRepository = userRepository;
|
||||
this.topicRepository = topicRepository;
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public Post findPostById(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> findPostsInTopicByText(String text, Long topicId) {
|
||||
Topic topic = topicRepository.findById(topicId).get();
|
||||
return postRepository.findPostsByTextInTopic(text, topic);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public Post addPost (String text, Long authorId, Long topicId) {
|
||||
if (!StringUtils.hasText(text)) {
|
||||
throw new IllegalArgumentException("Post data is null or empty");
|
||||
}
|
||||
User author = userRepository.findById(authorId).get();
|
||||
Topic topic = topicRepository.findById(topicId).get();
|
||||
Post post = new Post(text, author, topic);
|
||||
author.addPost(post);
|
||||
topic.addPost(post);
|
||||
userRepository.save(author);
|
||||
topicRepository.save(topic);
|
||||
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 = findPostById(id);
|
||||
currentPost.setText(text);
|
||||
final User author = currentPost.getAuthor();
|
||||
userRepository.save(author);
|
||||
final Topic topic = currentPost.getTopic();
|
||||
topicRepository.save(topic);
|
||||
return postRepository.save(currentPost);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public Post deletePost(Long id) {
|
||||
final Post currentPost = findPostById(id);
|
||||
postRepository.delete(currentPost);
|
||||
return currentPost;
|
||||
}
|
||||
}
|
@ -1,62 +0,0 @@
|
||||
package com.webproglabs.lab1.services;
|
||||
|
||||
import com.webproglabs.lab1.dao.TopicRepository;
|
||||
import com.webproglabs.lab1.models.Post;
|
||||
import com.webproglabs.lab1.models.Topic;
|
||||
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 TopicService {
|
||||
private final TopicRepository topicRepository;
|
||||
|
||||
public TopicService(TopicRepository topicRepository) {
|
||||
this.topicRepository = topicRepository;
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public Topic addTopic(String name, String description) {
|
||||
if (!StringUtils.hasText(name) || !StringUtils.hasText(description)) {
|
||||
throw new IllegalArgumentException("Name is null or empty");
|
||||
}
|
||||
final Topic topic = new Topic(name, description);
|
||||
return topicRepository.save(topic);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public Topic findTopicById(Long id) {
|
||||
final Topic topic = topicRepository.findById(id).orElse(null);
|
||||
if (topic == null) {
|
||||
throw new EntityNotFoundException(String.format(" topic with id [%s] is not found", id));
|
||||
}
|
||||
return topic;
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public List<Topic> findAllTopics() {
|
||||
return topicRepository.findAll();
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public Topic updateTopic(Long id, String name, String description) {
|
||||
if (!StringUtils.hasText(name) || !StringUtils.hasText(description)) {
|
||||
throw new IllegalArgumentException("Name is null or empty");
|
||||
}
|
||||
final Topic topic = findTopicById(id);
|
||||
topic.setName(name);
|
||||
topic.setDescription(description);
|
||||
return topicRepository.save(topic);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public Topic deleteTopic(Long id) {
|
||||
final Topic topic = findTopicById(id);
|
||||
topicRepository.delete(topic);
|
||||
return topic;
|
||||
}
|
||||
|
||||
}
|
@ -1,102 +0,0 @@
|
||||
package com.webproglabs.lab1.services;
|
||||
|
||||
import com.webproglabs.lab1.dao.UserRepository;
|
||||
import com.webproglabs.lab1.models.User;
|
||||
import com.webproglabs.lab1.models.UserRole;
|
||||
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;
|
||||
import java.util.Optional;
|
||||
|
||||
@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) {
|
||||
final Optional<User> user = userRepository.findById(id);
|
||||
return user.orElseThrow(EntityNotFoundException::new);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public User findUserByLogin(String login) {
|
||||
final User user = userRepository.findOneByLoginIgnoreCase(login).orElse(null);
|
||||
return user;
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public List<User> findAllUsers() {
|
||||
return userRepository.findAll();
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public User createUser(String login, String password, String passwordConfirm, UserRole role) {
|
||||
if (findUserByLogin(login) != null) {
|
||||
throw new IllegalArgumentException("User " + login + " already exists");
|
||||
}
|
||||
final User user = new User(login, passwordEncoder.encode(password), role);
|
||||
if (!Objects.equals(password, passwordConfirm)) {
|
||||
throw new IllegalArgumentException("Passwords not equals");
|
||||
}
|
||||
return userRepository.save(user);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public User createUser(String login, String password, String passwordConfirm) {
|
||||
return createUser(login, password, passwordConfirm, UserRole.USER);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public User updateUser(Long id, String login, String password, String passwordConfirm) {
|
||||
if (!StringUtils.hasText(login) || !StringUtils.hasText(password)) {
|
||||
throw new IllegalArgumentException("User data is null or empty");
|
||||
}
|
||||
|
||||
final User currentUser = findUserById(id);
|
||||
|
||||
if (Objects.equals(password, currentUser.getPassword())) {
|
||||
throw new IllegalArgumentException("New password is the same as old");
|
||||
}
|
||||
|
||||
if (!Objects.equals(password, passwordConfirm)) {
|
||||
throw new IllegalArgumentException("Password mismatch");
|
||||
}
|
||||
|
||||
currentUser.setLogin(login);
|
||||
currentUser.setPassword(passwordEncoder.encode(password));
|
||||
return userRepository.save(currentUser);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public User deleteUser(Long id) {
|
||||
final User currentUser = findUserById(id);
|
||||
userRepository.delete(currentUser);
|
||||
return currentUser;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
|
||||
final User userEntity = findUserByLogin(username);
|
||||
if (userEntity == null) {
|
||||
throw new UsernameNotFoundException(username);
|
||||
}
|
||||
return new org.springframework.security.core.userdetails.User(
|
||||
userEntity.getLogin(), userEntity.getPassword(), Collections.singleton(userEntity.getRole()));
|
||||
}
|
||||
}
|
@ -1,4 +1,3 @@
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html lang="en"
|
||||
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
|
||||
@ -14,7 +13,7 @@
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title" id="commentCreateLabel">Создать комментарий</h5>
|
||||
</div>
|
||||
<form th:action="@{/feed/comment/{id}/{topicId}/{postId}/{text} (id=${selectedProfile.id}, topicId=${selectedTopic.id}, postId=${selectedPost.id}, text=${commentInputField}) }" method="post" class="modal-body text-center">
|
||||
<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>
|
||||
|
@ -1,13 +1,12 @@
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html lang="ru"
|
||||
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>
|
||||
<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>
|
||||
@ -19,16 +18,14 @@
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div class="bg-light w-75 rounded-pill text-center pt-4 pb-4 mt-3 mx-auto">
|
||||
<p class='text-center h3'> СоцСеточка</p>
|
||||
<div>
|
||||
<p class='text-center m-3 h3'> Лабораторная работа 5</p>
|
||||
</div>
|
||||
<div>
|
||||
<p class='h4 mt-2 text-center'>
|
||||
<a sec:authorize="hasRole('ROLE_ADMIN')" href="/topic" class="text-decoration-none m-3 text-secondary ">Темы</a>
|
||||
<a sec:authorize="hasRole('ROLE_ADMIN')" href="/users" class="text-decoration-none m-3 text-secondary ">Пользователи</a>
|
||||
<a sec:authorize="isAuthenticated()" href="/feed" class="text-decoration-none m-3 text-secondary ">Лента</a>
|
||||
<a sec:authorize="isAuthenticated()" href="/users/settings" class="text-decoration-none m-3 text-secondary ">Настройки</a>
|
||||
<a sec:authorize="isAuthenticated()" href="/logout" class="text-decoration-none m-3 text-secondary ">
|
||||
<p class='h4 text-center'>
|
||||
<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>
|
||||
|
@ -13,7 +13,7 @@
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title" id="commentEditLabel">Редактировать комментарий</h5>
|
||||
</div>
|
||||
<form th:action="@{/feed/editComment/{id}/{commentId}/{text} (id=${selectedTopic.id}, commentId=${selectedComment.id}, text=${commentEditField}) }" method="post" class="modal-body text-center">
|
||||
<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>
|
||||
|
@ -14,7 +14,7 @@
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title" id="postEditLabel">Редактировать пост</h5>
|
||||
</div>
|
||||
<form th:action="@{/feed/editPost/{id}/{topicId}/{text} (id=${selectedPost.id}, topicId=${selectedTopic.id}, text=${postEditField} ) }" method="post" class="modal-body text-center">
|
||||
<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>
|
||||
|
@ -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>
|
@ -1,4 +1,3 @@
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html lang="en"
|
||||
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
|
||||
@ -6,26 +5,27 @@
|
||||
<head>
|
||||
</head>
|
||||
<body>
|
||||
<div layout:fragment="content">
|
||||
<div class="text-center">
|
||||
<div class="dropdown text-center mx-auto w-75">
|
||||
<div class="text-center mt-3">
|
||||
<button class="btn btn-secondary dropdown-toggle mb-3 w-100" type="button" data-bs-toggle="dropdown" aria-expanded="false">
|
||||
Выбор темы
|
||||
</button>
|
||||
<ul class="dropdown-menu w-100" >
|
||||
<li th:each="topic: ${topics}">
|
||||
<a class="dropdown-item" th:href="@{/feed/{id}(id=${topic.id})}" th:text="${topic.name + '. ' + topic.description}">
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div layout:fragment="contentFeed"></div>
|
||||
<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>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
|
||||
|
||||
|
@ -5,106 +5,102 @@
|
||||
<head>
|
||||
</head>
|
||||
<body>
|
||||
<div layout:fragment="contentFeed">
|
||||
<div layout:fragment="contentFeed">
|
||||
|
||||
<div class='mb-3 mx-auto w-75'>
|
||||
<div class="text-center w-100 border border-2 bg-light">
|
||||
<p class="text-center h3" th:text="${selectedTopic.name}"></p>
|
||||
<p class="text-center fw-light" th:text="${selectedTopic.description}"></p>
|
||||
</div>
|
||||
<p class="text-end h3 " th:text="${selectedProfile.login}"></p>
|
||||
</div>
|
||||
<div class='h3 m-3 d-flex justify-content-between text-center mx-auto w-75'>
|
||||
|
||||
Лента
|
||||
<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=${selectedTopic.id}, text=${searchField}) }" method="get">
|
||||
<input th:value="${searchField}" id="searchField" name="searchField" type="text" class="mb-2" style="width: 70%" 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-75 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="@{/users/{login}(login=${post.getAuthor()})}"></a>
|
||||
<div class='h3 mb-3 mx-auto w-25'>
|
||||
<p class="text-end" th:text="${selectedProfile.login}"></p>
|
||||
</div>
|
||||
<div th:if="${selectedProfile.getLogin() == post.getAuthor()}" class="d-flex justify-content-between fst-italic">
|
||||
<form th:action="@{/feed/deletePost/{id}/{topicId} (id=${post.id}, topicId=${selectedTopic.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>
|
||||
<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>
|
||||
</form>
|
||||
<form th:action="@{/feed/postModal/{id}/{topicId} (id=${post.id}, topicId=${selectedTopic.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>
|
||||
<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:if="${selectedProfile.getLogin() == comment.getAuthor()}" class="d-flex justify-content-between fst-italic">
|
||||
<form th:action="@{/feed/deleteComment/{id}/{topicId} (id=${comment.id}, topicId=${selectedTopic.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}/{topicId} (id=${comment.id}, topicId=${selectedTopic.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 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>
|
||||
<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>
|
||||
</div>
|
||||
<form th:action="@{/feed/commentModal/{topicId}/{postId}/ ( topicId=${selectedTopic.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 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>
|
||||
<form th:action="@{/feed/{topicId}/post/{id}/{text} (topicId=${selectedTopic.id}, 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 layout:fragment="modalFeed"></div>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<div layout:fragment="modalFeed"></div>
|
||||
|
||||
|
||||
</div>
|
||||
</body>
|
||||
|
||||
</html>
|
@ -1,31 +1,30 @@
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html lang="en"
|
||||
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
|
||||
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>
|
@ -8,17 +8,17 @@
|
||||
<div layout:fragment="content">
|
||||
|
||||
<div class="text-center">
|
||||
<div class="text-start mx-auto w-50 border p-5">
|
||||
<div class="text-start mx-auto w-25 border p-5">
|
||||
<p class='h5'>Профиль</p>
|
||||
<p th:text="${'Логин: ' + user.login}"></p>
|
||||
<p th:text="${'Логин: ' + profile.login}"></p>
|
||||
<p class='h6 '>Список постов пользователя: </p>
|
||||
|
||||
<div th:if="${user.posts.size()>0}">
|
||||
<div th:each="post: ${user.posts}">
|
||||
<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="${user.posts.size()>0}">
|
||||
<p th:unless="${profile.posts.size()>0}">
|
||||
Нет постов
|
||||
</p>
|
||||
</div>
|
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>
|
@ -4,25 +4,25 @@
|
||||
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>
|
||||
<form action="#" th:action="@{/signup}" th:object="${userDto}" method="post">
|
||||
<div class="mb-3">
|
||||
<input type="text" class="form-control" th:field="${userDto.login}"
|
||||
placeholder="Логин" required="true" autofocus="true" maxlength="64"/>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<input type="password" class="form-control" th:field="${userDto.password}"
|
||||
placeholder="Пароль" required="true" minlength="4" maxlength="64"/>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<input type="password" class="form-control" th:field="${userDto.passwordConfirm}"
|
||||
placeholder="Пароль (подтверждение)" required="true" minlength="4" maxlength="64"/>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<button type="submit" class="btn btn-success button-fixed">Создать</button>
|
||||
<a class="btn btn-primary button-fixed" href="/login">Назад</a>
|
||||
</div>
|
||||
</form>
|
||||
<div th:if="${errors}" th:text="${errors}" class="margin-bottom alert alert-danger"></div>
|
||||
<form action="#" th:action="@{/signup}" th:object="${userDto}" method="post">
|
||||
<div class="mb-3">
|
||||
<input type="text" class="form-control" th:field="${userDto.login}"
|
||||
placeholder="Логин" required="true" autofocus="true" maxlength="64"/>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<input type="password" class="form-control" th:field="${userDto.password}"
|
||||
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="6" maxlength="64"/>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<button type="submit" class="btn btn-success button-fixed">Создать</button>
|
||||
<a class="btn btn-primary button-fixed" href="/login">Назад</a>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
@ -1,19 +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 class="h4 text-center">Изменить топик</div>
|
||||
<form action="#" th:action="@{/topic/edit/{id} (id=${topic.id})}" th:object="${topicDto}" method="post">
|
||||
<p>Новое название:</p>
|
||||
<input th:field="${topicDto.name}" type="text" class="mb-2 form-control" required="true" />
|
||||
<p>Новое описание:</p>
|
||||
<input th:field="${topicDto.description}" type="text" class="mb-2 form-control" required="true" />
|
||||
<button type="submit" class="btn btn-success" >Сохранить изменения</button>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
@ -1,32 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en"
|
||||
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
|
||||
layout:decorate="~{default}">
|
||||
<body>
|
||||
<div class="container container-padding" layout:fragment="content">
|
||||
|
||||
<form action="#" th:action="@{/topic/create}" th:object="${topicDto}" method="post">
|
||||
<p>Название:</p>
|
||||
<input th:field="${topicDto.name}" type="text" class="mb-2 form-control" required="true" />
|
||||
<p>Описание:</p>
|
||||
<input th:field="${topicDto.description}" type="text" class="mb-2 form-control" required="true" />
|
||||
<button type="submit" class="btn btn-success">Добавить</button>
|
||||
</form>
|
||||
|
||||
<div th:each="topic: ${topics}" class="border p-3 m-3 shadow-lg bg-body rounded">
|
||||
<div th:text="${'Топик: ' + topic.name}"></div>
|
||||
<div th:text="${'Описание: ' + topic.description}"></div>
|
||||
<form action="#" th:action="@{/topic/edit/{id} (id=${topic.id})}" method="get" class="text-end m-1">
|
||||
<button type="submit" class="btn btn-warning">Изменить</button>
|
||||
</form>
|
||||
<form action="#" th:action="@{/topic/delete/{id} (id=${topic.id})}" method="post" class="text-end m-1">
|
||||
<button type="submit" class="btn btn-danger" >Удалить</button>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
@ -1,31 +0,0 @@
|
||||
<!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 th:if="${errors}" th:text="${errors}" class="margin-bottom alert alert-danger"></div>
|
||||
<div th:if="${success}" th:text="${success}" class="margin-bottom text-success"></div>
|
||||
<div class="text-start mx-auto w-50 border p-5">
|
||||
<p class='h5'>Изменение данных пользователя</p>
|
||||
<p th:text="${'Логин: ' + user.login}"></p>
|
||||
|
||||
<form action="#" th:action="@{/users/edit/{id} (id=${user.id})}" th:object="${userDto}" method="post">
|
||||
<p>Новый логин:</p>
|
||||
<input th:field="${userDto.login}" type="text" class="mb-2 form-control" required="true" autofocus="true" maxlength="64"/>
|
||||
<p>Новый пароль:</p>
|
||||
<input th:field="${userDto.password}" type="password" class="mb-2 form-control" required="true" minlength="4" maxlength="64"/>
|
||||
<p>Повторите пароль:</p>
|
||||
<input th:field="${userDto.passwordConfirm}" type="password" class="mb-2 form-control" required="true" minlength="4" maxlength="64"/>
|
||||
<button type="submit" class="btn btn-success" >Сохранить изменения</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
@ -1,36 +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">
|
||||
<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-50 border shadow 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" th:if="${profile.login!='admin'}">
|
||||
<form action="#" th:action="@{/users/{id} (id=${profile.id})}" method="post" >
|
||||
<button type="submit" class="btn btn-danger">Удалить</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
Loading…
Reference in New Issue
Block a user