Compare commits
10 Commits
master
...
socialnetw
Author | SHA1 | Date | |
---|---|---|---|
794388d0f6 | |||
e42408413a | |||
71dd9b4fde | |||
263182db1d | |||
89c76406ea | |||
a038eba691 | |||
072a9514b6 | |||
db18f20ff6 | |||
e656fe0664 | |||
8ae10007bb |
BIN
data.mv.db
BIN
data.mv.db
Binary file not shown.
3828
data.trace.db
3828
data.trace.db
File diff suppressed because it is too large
Load Diff
@ -1,10 +1,8 @@
|
||||
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 com.webproglabs.lab1.models.UserRole;
|
||||
import com.webproglabs.lab1.mvc.UserSignupMvcController;
|
||||
import com.webproglabs.lab1.services.UserService;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
@ -17,12 +15,10 @@ 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;
|
||||
|
||||
@ -36,18 +32,16 @@ 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 ProfileService userService;
|
||||
private final JwtFilter jwtFilter;
|
||||
private final UserService userService;
|
||||
|
||||
public SecurityConfiguration(ProfileService userService) {
|
||||
public SecurityConfiguration(UserService userService) {
|
||||
this.userService = userService;
|
||||
this.jwtFilter = new JwtFilter(userService);
|
||||
createAdminOnStartup();
|
||||
}
|
||||
|
||||
private void createAdminOnStartup() {
|
||||
final String admin = "admin";
|
||||
if (userService.findByLogin(admin) == null) {
|
||||
if (userService.findUserByLogin(admin) == null) {
|
||||
log.info("Admin user successfully created");
|
||||
try {
|
||||
userService.createUser(admin, admin, admin, UserRole.ADMIN);
|
||||
|
@ -1,105 +0,0 @@
|
||||
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,6 +1,5 @@
|
||||
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;
|
||||
@ -13,7 +12,7 @@ import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
||||
|
||||
@Configuration
|
||||
public class WebConfiguration implements WebMvcConfigurer {
|
||||
public static final String REST_API = OpenAPI30Configuration.API_PREFIX;
|
||||
public static final String REST_API = "/api";
|
||||
@Override
|
||||
public void addViewControllers(ViewControllerRegistry registry) {
|
||||
WebMvcConfigurer.super.addViewControllers(registry);
|
||||
|
@ -1,10 +1,12 @@
|
||||
package com.webproglabs.lab1.lab34.repository;
|
||||
package com.webproglabs.lab1.dao;
|
||||
|
||||
import com.webproglabs.lab1.lab34.model.Comment;
|
||||
import com.webproglabs.lab1.models.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);
|
||||
}
|
18
src/main/java/com/webproglabs/lab1/dao/PostRepository.java
Normal file
18
src/main/java/com/webproglabs/lab1/dao/PostRepository.java
Normal file
@ -0,0 +1,18 @@
|
||||
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);
|
||||
}
|
15
src/main/java/com/webproglabs/lab1/dao/TopicRepository.java
Normal file
15
src/main/java/com/webproglabs/lab1/dao/TopicRepository.java
Normal file
@ -0,0 +1,15 @@
|
||||
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);
|
||||
|
||||
}
|
12
src/main/java/com/webproglabs/lab1/dao/UserRepository.java
Normal file
12
src/main/java/com/webproglabs/lab1/dao/UserRepository.java
Normal file
@ -0,0 +1,12 @@
|
||||
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,11 +1,15 @@
|
||||
package com.webproglabs.lab1.lab34.controller;
|
||||
package com.webproglabs.lab1.dto;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import com.webproglabs.lab1.lab34.model.Comment;
|
||||
import com.webproglabs.lab1.models.Comment;
|
||||
|
||||
import javax.validation.constraints.NotBlank;
|
||||
|
||||
public class CommentDto {
|
||||
private Long id;
|
||||
@NotBlank
|
||||
private String text;
|
||||
@NotBlank
|
||||
private String authorLogin;
|
||||
|
||||
public CommentDto(Comment comment) {
|
||||
@ -19,5 +23,8 @@ public class CommentDto {
|
||||
return id;
|
||||
}
|
||||
public String getText() {return text;}
|
||||
public void setText(String text) {
|
||||
this.text = text;
|
||||
}
|
||||
public String getAuthor() {return authorLogin;}
|
||||
}
|
@ -1,18 +1,21 @@
|
||||
package com.webproglabs.lab1.lab34.controller;
|
||||
package com.webproglabs.lab1.dto;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import com.webproglabs.lab1.lab34.model.Comment;
|
||||
import com.webproglabs.lab1.lab34.model.Post;
|
||||
import com.webproglabs.lab1.lab34.model.Profile;
|
||||
import com.webproglabs.lab1.models.Comment;
|
||||
import com.webproglabs.lab1.models.Post;
|
||||
|
||||
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){
|
||||
@ -23,12 +26,16 @@ 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;}
|
||||
}
|
54
src/main/java/com/webproglabs/lab1/dto/TopicDto.java
Normal file
54
src/main/java/com/webproglabs/lab1/dto/TopicDto.java
Normal file
@ -0,0 +1,54 @@
|
||||
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;
|
||||
}
|
||||
}
|
@ -1,35 +1,41 @@
|
||||
package com.webproglabs.lab1.lab34.controller;
|
||||
package com.webproglabs.lab1.dto;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import com.webproglabs.lab1.lab34.model.Comment;
|
||||
import com.webproglabs.lab1.lab34.model.Post;
|
||||
import com.webproglabs.lab1.lab34.model.Profile;
|
||||
import com.webproglabs.lab1.lab34.model.UserRole;
|
||||
import com.webproglabs.lab1.models.Comment;
|
||||
import com.webproglabs.lab1.models.Post;
|
||||
import com.webproglabs.lab1.models.User;
|
||||
import com.webproglabs.lab1.models.UserRole;
|
||||
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class ProfileDto {
|
||||
public class UserDto {
|
||||
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 ProfileDto(Profile profile){
|
||||
this.id = profile.getId();
|
||||
this.login = profile.getLogin();
|
||||
this.password = profile.getPassword();
|
||||
this.role = profile.getRole();
|
||||
for(Comment comment: profile.getComments()){
|
||||
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()){
|
||||
comments.add(new CommentDto(comment));
|
||||
}
|
||||
for (Post post: profile.getPosts()) {
|
||||
for (Post post: user.getPosts()) {
|
||||
posts.add(new PostDto(post));
|
||||
}
|
||||
}
|
||||
@ -41,10 +47,9 @@ public class ProfileDto {
|
||||
public String getLogin() {return login;}
|
||||
public void setLogin(String login) {this.login = login;}
|
||||
public String getPassword() {return password;}
|
||||
|
||||
public UserRole getRole() {return role;}
|
||||
|
||||
public void setPassword(String password) {this.password = password;}
|
||||
|
||||
public List<CommentDto> getComments() {return comments;}
|
||||
public List<PostDto> getPosts() {return posts;}
|
||||
}
|
@ -1,17 +1,17 @@
|
||||
package com.webproglabs.lab1.lab34.controller.mvc_controllers;
|
||||
package com.webproglabs.lab1.dto;
|
||||
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import javax.validation.constraints.Size;
|
||||
|
||||
public class UserSignupDto {
|
||||
@NotBlank
|
||||
@Size(min = 3, max = 64)
|
||||
@Size(min = 4, max = 64)
|
||||
private String login;
|
||||
@NotBlank
|
||||
@Size(min = 6, max = 64)
|
||||
@Size(min = 4, max = 64)
|
||||
private String password;
|
||||
@NotBlank
|
||||
@Size(min = 6, max = 64)
|
||||
@Size(min = 4, max = 64)
|
||||
private String passwordConfirm;
|
||||
|
||||
public String getLogin() {
|
@ -1,44 +0,0 @@
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -1,27 +0,0 @@
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
//фронт на жсон сервер был когда то
|
||||
//сделать на основе старых сущностей сущности в жпа
|
||||
//делаем сущности, зависимость для жпа, сервис для круд операций,
|
||||
//тесты
|
||||
//фронт не нужно
|
||||
//двунправленная связь один ко многим
|
@ -1,35 +0,0 @@
|
||||
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);
|
||||
}
|
||||
}
|
@ -1,47 +0,0 @@
|
||||
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);
|
||||
}
|
||||
}
|
@ -1,58 +0,0 @@
|
||||
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;
|
||||
}
|
||||
}
|
@ -1,11 +0,0 @@
|
||||
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);
|
||||
}
|
@ -1,61 +0,0 @@
|
||||
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);
|
||||
}
|
||||
}
|
@ -1,28 +0,0 @@
|
||||
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")));
|
||||
}
|
||||
}
|
@ -1,59 +0,0 @@
|
||||
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,64 +0,0 @@
|
||||
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,88 +0,0 @@
|
||||
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,121 +0,0 @@
|
||||
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();
|
||||
}
|
||||
}
|
@ -1,52 +0,0 @@
|
||||
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,11 +0,0 @@
|
||||
package com.webproglabs.lab1.lab34.jwt;
|
||||
|
||||
public class JwtException extends RuntimeException {
|
||||
public JwtException(Throwable throwable) {
|
||||
super(throwable);
|
||||
}
|
||||
|
||||
public JwtException(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
@ -1,72 +0,0 @@
|
||||
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);
|
||||
}
|
||||
}
|
@ -1,27 +0,0 @@
|
||||
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;
|
||||
}
|
||||
}
|
@ -1,107 +0,0 @@
|
||||
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,11 +0,0 @@
|
||||
package com.webproglabs.lab1.lab34.repository;
|
||||
|
||||
import com.webproglabs.lab1.lab34.model.Comment;
|
||||
import com.webproglabs.lab1.lab34.model.Post;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface PostRepository extends JpaRepository<Post, Long> {
|
||||
List<Post> findByTextLike(String text);
|
||||
}
|
@ -1,12 +0,0 @@
|
||||
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,90 +0,0 @@
|
||||
package com.webproglabs.lab1.lab34.services;
|
||||
|
||||
import com.webproglabs.lab1.lab34.model.Comment;
|
||||
import com.webproglabs.lab1.lab34.model.Post;
|
||||
import com.webproglabs.lab1.lab34.model.Profile;
|
||||
import com.webproglabs.lab1.lab34.repository.CommentRepository;
|
||||
import com.webproglabs.lab1.lab34.repository.PostRepository;
|
||||
import com.webproglabs.lab1.lab34.repository.ProfileRepository;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import javax.persistence.EntityNotFoundException;
|
||||
import javax.transaction.Transactional;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
@Service
|
||||
public class PostService {
|
||||
private final PostRepository postRepository;
|
||||
private final CommentRepository commentRepository;
|
||||
private final ProfileRepository profileRepository;
|
||||
|
||||
public PostService(PostRepository postRepository, CommentRepository commentRepository, ProfileRepository profileRepository) {
|
||||
this.postRepository = postRepository;
|
||||
this.commentRepository = commentRepository;
|
||||
this.profileRepository = profileRepository;
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public Post findPost(Long id) {
|
||||
final Optional<Post> post = postRepository.findById(id);
|
||||
return post.orElseThrow(EntityNotFoundException::new);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public List<Post> findAllPosts() {
|
||||
return postRepository.findAll();
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public List<Post> findFilteredPosts(String filter) {
|
||||
List<Post> postList = postRepository.findByTextLike("%" + filter + "%");
|
||||
List<Comment> commentList = commentRepository.findByTextLike("%" + filter + "%");
|
||||
List<Post> allPosts = postRepository.findAll();
|
||||
for(Post post : allPosts) {
|
||||
for (Comment comm : commentList) {
|
||||
if (post.getComments().contains(comm) && !(postList.contains(post))) {
|
||||
postList.add(post);
|
||||
}
|
||||
}
|
||||
}
|
||||
return postList;
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public Post addPost (String text, List<Comment> comments, Long authorId) {
|
||||
if (!StringUtils.hasText(text)) {
|
||||
throw new IllegalArgumentException("Post data is null or empty");
|
||||
}
|
||||
Profile author = profileRepository.findById(authorId).get();
|
||||
Post post = new Post(text, author, comments);
|
||||
author.addPost(post);
|
||||
profileRepository.save(author);
|
||||
return postRepository.save(post);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public Post updatePost(Long id, String text) {
|
||||
if (!StringUtils.hasText(text)) {
|
||||
throw new IllegalArgumentException("Post data is null or empty");
|
||||
}
|
||||
final Post currentPost = findPost(id);
|
||||
currentPost.setText(text);
|
||||
final Profile author = currentPost.getAuthor();
|
||||
profileRepository.save(author);
|
||||
return postRepository.save(currentPost);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public Post deletePost(Long id) {
|
||||
final Post currentPost = findPost(id);
|
||||
postRepository.delete(currentPost);
|
||||
return currentPost;
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void deleteAllPosts() {
|
||||
postRepository.deleteAll();
|
||||
}
|
||||
}
|
@ -1,158 +0,0 @@
|
||||
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,4 +1,4 @@
|
||||
package com.webproglabs.lab1.lab34.model;
|
||||
package com.webproglabs.lab1.models;
|
||||
|
||||
import javax.persistence.*;
|
||||
import java.util.Objects;
|
||||
@ -12,13 +12,13 @@ public class Comment {
|
||||
private String text;
|
||||
|
||||
@ManyToOne()
|
||||
private Profile owner;
|
||||
private User owner;
|
||||
|
||||
@ManyToOne()
|
||||
private Post post;
|
||||
|
||||
public Comment(){};
|
||||
public Comment(String text, Profile owner, Post post) {
|
||||
public Comment(String text, User owner, Post post) {
|
||||
this.text = text;
|
||||
this.owner = owner;
|
||||
this.post = post;
|
||||
@ -36,10 +36,11 @@ public class Comment {
|
||||
this.text = text;
|
||||
}
|
||||
|
||||
public Profile getOwner() {
|
||||
public User getOwner() {
|
||||
return owner;
|
||||
}
|
||||
public void setOwner(Profile owner) {
|
||||
|
||||
public void setOwner(User owner) {
|
||||
this.owner.getComments().remove(this);
|
||||
this.owner = owner;
|
||||
if (!owner.getComments().contains(this)) {
|
@ -1,4 +1,4 @@
|
||||
package com.webproglabs.lab1.lab34.model;
|
||||
package com.webproglabs.lab1.models;
|
||||
|
||||
import javax.persistence.*;
|
||||
import java.util.ArrayList;
|
||||
@ -17,15 +17,16 @@ public class Post {
|
||||
private List<Comment> comments = new ArrayList<Comment>();
|
||||
|
||||
@ManyToOne()
|
||||
private Profile author;
|
||||
private User author;
|
||||
|
||||
@ManyToOne()
|
||||
private Topic topic;
|
||||
|
||||
public Post(){}
|
||||
public Post(String text, Profile author, List<Comment> comments) {
|
||||
public Post(String text, User author, Topic topic) {
|
||||
this.text = text;
|
||||
this.author = author;
|
||||
for (int i = 0; i < comments.size(); i++) {
|
||||
addComment(comments.get(i));
|
||||
}
|
||||
this.topic = topic;
|
||||
}
|
||||
|
||||
public Long getId() {
|
||||
@ -40,11 +41,11 @@ public class Post {
|
||||
this.text = text;
|
||||
}
|
||||
|
||||
public Profile getAuthor() {
|
||||
public User getAuthor() {
|
||||
return author;
|
||||
}
|
||||
|
||||
public void setAuthor(Profile author) {
|
||||
public void setAuthor(User author) {
|
||||
this.author.getPosts().remove(this);
|
||||
this.author = author;
|
||||
if (!author.getPosts().contains(this)) {
|
||||
@ -52,12 +53,20 @@ public class Post {
|
||||
}
|
||||
}
|
||||
|
||||
public List<Comment> getComments() { return comments; }
|
||||
public int getCommentsSize() {
|
||||
if (comments == null) return 0;
|
||||
else return comments.size();
|
||||
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 void addComment(Comment comment) {
|
||||
this.comments.add(comment);
|
||||
if (comment.getPost() != this) {
|
||||
@ -83,8 +92,6 @@ public class Post {
|
||||
"id=" + id +
|
||||
", text='" + text + '\'' +
|
||||
", author='" + author.ToString() + '\'' +
|
||||
", comments='" + getCommentsSize() + '\'' +
|
||||
'}';
|
||||
}
|
||||
|
||||
}
|
78
src/main/java/com/webproglabs/lab1/models/Topic.java
Normal file
78
src/main/java/com/webproglabs/lab1/models/Topic.java
Normal file
@ -0,0 +1,78 @@
|
||||
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,4 +1,4 @@
|
||||
package com.webproglabs.lab1.lab34.model;
|
||||
package com.webproglabs.lab1.models;
|
||||
|
||||
import javax.persistence.*;
|
||||
import javax.validation.constraints.NotBlank;
|
||||
@ -8,8 +8,8 @@ import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
@Entity
|
||||
@Table(name="tab_user")
|
||||
public class Profile {
|
||||
@Table(name="users")
|
||||
public class User {
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.AUTO)
|
||||
private Long id;
|
||||
@ -21,43 +21,28 @@ public class Profile {
|
||||
|
||||
@Column(nullable = false, length = 64)
|
||||
@NotBlank
|
||||
@Size(min = 6, max = 64)
|
||||
@Size(min = 4, max = 64)
|
||||
private String password;
|
||||
|
||||
private UserRole role;
|
||||
|
||||
public UserRole getRole() {
|
||||
return role;
|
||||
}
|
||||
|
||||
@OneToMany(mappedBy = "owner", orphanRemoval = true, fetch = FetchType.EAGER)
|
||||
private List<Comment> comments = new ArrayList<Comment>();
|
||||
|
||||
@OneToMany(mappedBy = "author", orphanRemoval = true, fetch = FetchType.EAGER)
|
||||
private List<Post> posts = new ArrayList<Post>();
|
||||
|
||||
public Profile(){}
|
||||
public Profile(String login, String password, List<Comment> comments, List<Post> posts) {
|
||||
public User(){}
|
||||
public User(String login, String password) {
|
||||
this.login = login;
|
||||
this.password=password;
|
||||
this.role = UserRole.USER;
|
||||
for (int i = 0; i < comments.size(); i++) {
|
||||
addComment(comments.get(i));
|
||||
}
|
||||
for (int i = 0; i < posts.size(); i++) {
|
||||
addPost(posts.get(i));
|
||||
}
|
||||
};
|
||||
public Profile(String login, String password, List<Comment> comments, List<Post> posts, UserRole role) {
|
||||
|
||||
public User(String login, String password, 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() {
|
||||
@ -68,6 +53,10 @@ public class Profile {
|
||||
return login;
|
||||
}
|
||||
|
||||
public UserRole getRole() {
|
||||
return role;
|
||||
}
|
||||
|
||||
public void setLogin(String login) {
|
||||
this.login = login;
|
||||
}
|
||||
@ -84,16 +73,6 @@ public class Profile {
|
||||
|
||||
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) {
|
||||
@ -112,7 +91,7 @@ public class Profile {
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
Profile user = (Profile) o;
|
||||
User user = (User) o;
|
||||
return Objects.equals(id, user.id);
|
||||
}
|
||||
|
||||
@ -126,8 +105,6 @@ public class Profile {
|
||||
"id=" + id +
|
||||
", login='" + login + '\'' +
|
||||
", password='" + password + '\'' +
|
||||
", comments='" + getCommentsSize() + '\'' +
|
||||
", comments='" + getPostsSize() + '\'' +
|
||||
'}';
|
||||
}
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
package com.webproglabs.lab1.lab34.model;
|
||||
package com.webproglabs.lab1.models;
|
||||
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
|
142
src/main/java/com/webproglabs/lab1/mvc/FeedMvcController.java
Normal file
142
src/main/java/com/webproglabs/lab1/mvc/FeedMvcController.java
Normal file
@ -0,0 +1,142 @@
|
||||
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();
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,58 @@
|
||||
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";
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,79 @@
|
||||
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,7 +1,8 @@
|
||||
package com.webproglabs.lab1.lab34.controller.mvc_controllers;
|
||||
package com.webproglabs.lab1.mvc;
|
||||
|
||||
import com.webproglabs.lab1.lab34.model.Profile;
|
||||
import com.webproglabs.lab1.lab34.services.ProfileService;
|
||||
import com.webproglabs.lab1.dto.UserSignupDto;
|
||||
import com.webproglabs.lab1.models.User;
|
||||
import com.webproglabs.lab1.services.UserService;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.Model;
|
||||
import org.springframework.validation.BindingResult;
|
||||
@ -13,23 +14,28 @@ import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import javax.validation.Valid;
|
||||
|
||||
@Controller
|
||||
@RequestMapping(UserSignupMvcController.SIGNUP_URL)
|
||||
@RequestMapping()
|
||||
public class UserSignupMvcController {
|
||||
public static final String SIGNUP_URL = "/signup";
|
||||
|
||||
private final ProfileService userService;
|
||||
private final UserService userService;
|
||||
|
||||
public UserSignupMvcController(ProfileService userService) {
|
||||
public UserSignupMvcController(UserService 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
|
||||
@PostMapping(SIGNUP_URL)
|
||||
public String signup(@ModelAttribute("userDto") @Valid UserSignupDto userSignupDto,
|
||||
BindingResult bindingResult,
|
||||
Model model) {
|
||||
@ -38,12 +44,12 @@ public class UserSignupMvcController {
|
||||
return "signup";
|
||||
}
|
||||
try {
|
||||
final Profile user = userService.createUser(
|
||||
userSignupDto.getLogin(), userSignupDto.getPassword(), userSignupDto.getPasswordConfirm());
|
||||
final User user = userService.createUser(userSignupDto.getLogin(), userSignupDto.getPassword(), userSignupDto.getPasswordConfirm());
|
||||
return "redirect:/login?created=" + user.getLogin();
|
||||
} catch (Exception e) {
|
||||
model.addAttribute("errors", e.getMessage());
|
||||
return "signup";
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -1,11 +1,11 @@
|
||||
package com.webproglabs.lab1.lab34.services;
|
||||
package com.webproglabs.lab1.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 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 org.springframework.stereotype.Service;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
@ -16,20 +16,18 @@ import java.util.Optional;
|
||||
|
||||
@Service
|
||||
public class CommentService {
|
||||
|
||||
private final ProfileRepository profileRepository;
|
||||
private final UserRepository userRepository;
|
||||
private final CommentRepository commentRepository;
|
||||
private final PostRepository postRepository;
|
||||
|
||||
private final PostRepository postRepository;
|
||||
|
||||
public CommentService(ProfileRepository profileRepository, CommentRepository commentRepository, PostRepository postRepository) {
|
||||
this.profileRepository = profileRepository;
|
||||
public CommentService(UserRepository profileRepository, CommentRepository commentRepository, PostRepository postRepository) {
|
||||
this.userRepository = profileRepository;
|
||||
this.commentRepository = commentRepository;
|
||||
this.postRepository = postRepository;
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public Comment findComment(Long id) {
|
||||
public Comment findCommentById(Long id) {
|
||||
final Optional<Comment> comment = commentRepository.findById(id);
|
||||
return comment.orElseThrow(EntityNotFoundException::new);
|
||||
}
|
||||
@ -40,32 +38,17 @@ public class CommentService {
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public List<Post> findFilteredComments(String filter) {
|
||||
List<Post> postList = postRepository.findByTextLike("%" + filter + "%");
|
||||
List<Comment> commentList = commentRepository.findByTextLike("%" + filter + "%");
|
||||
List<Post> allPosts = postRepository.findAll();
|
||||
for(Post post : allPosts) {
|
||||
for (Comment comm : commentList) {
|
||||
if (post.getComments().contains(comm) && !(postList.contains(post))) {
|
||||
postList.add(post);
|
||||
}
|
||||
}
|
||||
}
|
||||
return postList;
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public Comment addComment(String text, Long profileId, Long postId) {
|
||||
public Comment addComment(String text, Long userId, Long postId) {
|
||||
if (!StringUtils.hasText(text)) {
|
||||
throw new IllegalArgumentException("Comment data is null or empty");
|
||||
}
|
||||
try{
|
||||
Profile user = profileRepository.findById(profileId).get();
|
||||
User user = userRepository.findById(userId).get();
|
||||
Post post = postRepository.findById(postId).get();
|
||||
Comment comment = new Comment(text, user, post);
|
||||
user.addComment(comment);
|
||||
post.addComment(comment);
|
||||
profileRepository.save(user);
|
||||
userRepository.save(user);
|
||||
postRepository.save(post);
|
||||
return commentRepository.save(comment);
|
||||
}
|
||||
@ -79,10 +62,10 @@ public class CommentService {
|
||||
if (!StringUtils.hasText(text)) {
|
||||
throw new IllegalArgumentException("Comment data is null or empty");
|
||||
}
|
||||
Comment currentComment = findComment(id);
|
||||
Comment currentComment = findCommentById(id);
|
||||
currentComment.setText(text);
|
||||
final Profile owner = currentComment.getOwner();
|
||||
profileRepository.save(owner);
|
||||
final User owner = currentComment.getOwner();
|
||||
userRepository.save(owner);
|
||||
final Post post = currentComment.getPost();
|
||||
postRepository.save(post);
|
||||
return commentRepository.save(currentComment);
|
||||
@ -90,13 +73,8 @@ public class CommentService {
|
||||
|
||||
@Transactional
|
||||
public Comment deleteComment(Long id) {
|
||||
final Comment currentComment = findComment(id);
|
||||
final Comment currentComment = findCommentById(id);
|
||||
commentRepository.delete(currentComment);
|
||||
return currentComment;
|
||||
}
|
||||
@Transactional
|
||||
public void deleteAllComments() {
|
||||
commentRepository.deleteAll();
|
||||
}
|
||||
|
||||
}
|
86
src/main/java/com/webproglabs/lab1/services/PostService.java
Normal file
86
src/main/java/com/webproglabs/lab1/services/PostService.java
Normal file
@ -0,0 +1,86 @@
|
||||
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;
|
||||
}
|
||||
}
|
@ -0,0 +1,62 @@
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
102
src/main/java/com/webproglabs/lab1/services/UserService.java
Normal file
102
src/main/java/com/webproglabs/lab1/services/UserService.java
Normal file
@ -0,0 +1,102 @@
|
||||
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,3 +1,4 @@
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html lang="en"
|
||||
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
|
||||
@ -13,7 +14,7 @@
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title" id="commentCreateLabel">Создать комментарий</h5>
|
||||
</div>
|
||||
<form th:action="@{/feed/comment/{id}/{postId}/{text} (id=${selectedProfile.id}, postId=${selectedPost.id}, text=${commentInputField}) }" method="post" class="modal-body text-center">
|
||||
<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">
|
||||
<p>Текст комментария:</p>
|
||||
<input th:value="${commentInputField}" id="commentInputField" name="commentInputField" type="text" class="mb-2">
|
||||
<br>
|
||||
|
@ -1,12 +1,13 @@
|
||||
|
||||
<!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>Лабораторная работа 5</title>
|
||||
<title>СоцСеточка</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1"/>
|
||||
<link rel="icon" href="/favicon.svg">
|
||||
<script type="text/javascript" src="/webjars/bootstrap/5.1.3/js/bootstrap.bundle.min.js"></script>
|
||||
@ -18,14 +19,16 @@
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div>
|
||||
<p class='text-center m-3 h3'> Лабораторная работа 5</p>
|
||||
<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>
|
||||
<div>
|
||||
<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">
|
||||
<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 ">
|
||||
Выход
|
||||
</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=${selectedProfile.id}, commentId=${selectedComment.id}, text=${commentEditField}) }" method="post" class="modal-body text-center">
|
||||
<form th:action="@{/feed/editComment/{id}/{commentId}/{text} (id=${selectedTopic.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}/{authorId}/{text} (id=${selectedPost.id}, authorId=${selectedProfile.id}, text=${postEditField} ) }" method="post" class="modal-body text-center">
|
||||
<form th:action="@{/feed/editPost/{id}/{topicId}/{text} (id=${selectedPost.id}, topicId=${selectedTopic.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,3 +1,4 @@
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html lang="en"
|
||||
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
|
||||
@ -5,27 +6,26 @@
|
||||
<head>
|
||||
</head>
|
||||
<body>
|
||||
<div layout:fragment="content">
|
||||
<div class="text-center">
|
||||
|
||||
<!-- <div class="dropdown text-center mx-auto w-25 ">-->
|
||||
<!-- <div class="text-end mt-3">-->
|
||||
<!-- <button class="btn btn-secondary dropdown-toggle ms-3 mb-3 " type="button" data-bs-toggle="dropdown" aria-expanded="false">-->
|
||||
<!-- Выбор пользователя-->
|
||||
<!-- </button>-->
|
||||
<!-- <ul class="dropdown-menu " >-->
|
||||
<!-- <li th:each="profile: ${profiles}">-->
|
||||
<!-- <a class="dropdown-item" th:href="@{/feed/{id}(id=${profile.id})}" th:text="${profile.login}">-->
|
||||
<!-- </a>-->
|
||||
<!-- </li>-->
|
||||
<!-- </ul>-->
|
||||
<!-- </div>-->
|
||||
<!-- </div>-->
|
||||
<div layout:fragment="contentFeed"></div>
|
||||
<div 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>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
|
||||
|
||||
|
@ -5,102 +5,106 @@
|
||||
<head>
|
||||
</head>
|
||||
<body>
|
||||
<div layout:fragment="contentFeed">
|
||||
|
||||
<div class='h3 mb-3 mx-auto w-25'>
|
||||
<p class="text-end" th:text="${selectedProfile.login}"></p>
|
||||
</div>
|
||||
<div class='h3 m-3 d-flex justify-content-between text-center mx-auto w-25'>
|
||||
|
||||
Лента
|
||||
<button type='button' class="btn btn-primary ms-5 mb-3 " data-bs-toggle="modal" data-bs-target="#postCreate">
|
||||
Добавить новый пост
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<form th:action="@{/feed/filter/{id}/{text} (id=${selectedProfile.id}, text=${searchField}) }" method="get">
|
||||
<input th:value="${searchField}" id="searchField" name="searchField" type="text" class="mb-2" style="width: 20%" placeholder="Поиск...">
|
||||
<button type='submit' class="btn btn-primary mb-2" style="width: 5%">
|
||||
Найти
|
||||
</button>
|
||||
</form>
|
||||
|
||||
|
||||
<div th:each="post: ${posts}" class="text-center mx-auto w-25 mb-3 ">
|
||||
<div class="border p-2">
|
||||
<p th:text="${post.text}" class="h4 text-start"></p>
|
||||
<div class="d-flex justify-content-between fst-italic">
|
||||
<div>
|
||||
Автор:
|
||||
<a th:text="${post.getAuthor()}" class="text-start fst-italic" th:href="@{/profile/{login}(login=${post.getAuthor()})}"></a>
|
||||
</div>
|
||||
<div th:if="${selectedProfile.getLogin() == post.getAuthor()}" class="d-flex justify-content-between fst-italic">
|
||||
<form th:action="@{/feed/deletePost/{id}/{authorId} (id=${post.id}, authorId=${selectedProfile.id})}" method="post" >
|
||||
<button type="submit" class="btn btn-danger me-1 mb-1 ms-2" >
|
||||
<i class="fa fa-trash" aria-hidden="true"></i>
|
||||
</button>
|
||||
</form>
|
||||
<form th:action="@{/feed/postModal/{id}/{authorId} (id=${post.id}, authorId=${selectedProfile.id})}" method="get">
|
||||
<button type="submit" class="btn btn-warning mb-1" data-bs-toggle="modal" data-bs-target="#postEdit" >
|
||||
<i class="fa fa-pencil" aria-hidden="true"></i>
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="border p-2" th:if="${post.comments.size() > 0}" >
|
||||
<div class="text-start">
|
||||
<p class="text-start h5">Комментарии:</p>
|
||||
<div th:each="comment: ${post.comments}" >
|
||||
<p class="fst-italic" th:text="${comment.getAuthor() + ':'}"> </p>
|
||||
<div class="d-flex justify-content-between fst-italic">
|
||||
<p class="ms-3" th:text="${comment.text}"></p>
|
||||
|
||||
<div th:if="${selectedProfile.getLogin() == comment.getAuthor()}" class="d-flex justify-content-between fst-italic">
|
||||
<form th:action="@{/feed/deleteComment/{id}/{authorId} (id=${comment.id}, authorId=${selectedProfile.id})}" method="post" >
|
||||
<button type="submit" class="btn btn-danger me-1 mb-1"> <i class="fa fa-trash" aria-hidden="true"> </i> </button>
|
||||
</form>
|
||||
<form th:action="@{/feed/commentEditModal/{id}/{authorId} (id=${comment.id}, authorId=${selectedProfile.id})}" method="get">
|
||||
<button type="submit" class="btn btn-warning mb-1" data-bs-toggle="modal" data-bs-target="#postEdit" >
|
||||
<i class="fa fa-pencil" aria-hidden="true"></i>
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<form th:action="@{/feed/commentModal/{authorId}/{postId}/ ( authorId=${selectedProfile.id}, postId=${post.id} ) }" method="get" class="text-end">
|
||||
<button type="submit" class="btn btn-info mb-3" data-bs-toggle="modal" data-bs-target="#commentCreate">Добавить комментарий</button>
|
||||
</form>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="modal fade" id="postCreate" tabindex="-1" role="dialog" aria-labelledby="postCreateLabel" aria-hidden="true">
|
||||
<div class="modal-dialog" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title" id="postCreateLabel">Создать пост</h5>
|
||||
</div>
|
||||
<form th:action="@{/feed/post/{id}/{text} (id=${selectedProfile.id}, text=${postInputField}) }" method="post" class="modal-body text-center">
|
||||
<p>Текст поста:</p>
|
||||
<input th:value="${postInputField}" id="postInputField" name="postInputField" type="text" class="mb-2">
|
||||
<br>
|
||||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Закрыть</button>
|
||||
<button type="submit" class="btn btn-primary" >Сохранить</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<div layout:fragment="modalFeed"></div>
|
||||
|
||||
<div 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>
|
||||
<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>
|
||||
</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>
|
||||
|
||||
<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>
|
||||
|
||||
</div>
|
||||
</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>
|
||||
<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>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<div layout:fragment="modalFeed"></div>
|
||||
|
||||
|
||||
</div>
|
||||
</body>
|
||||
|
||||
</html>
|
@ -1,30 +1,31 @@
|
||||
|
||||
<!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 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>
|
||||
<div th:if="${param.logout}" class="alert alert-success margin-bottom">
|
||||
Выход успешно произведен
|
||||
<div class="mb-3">
|
||||
<input type="password" name="password" id="password" class="form-control"
|
||||
placeholder="Пароль" required="true"/>
|
||||
</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>
|
||||
<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>
|
||||
<button type="submit" class="btn btn-success button-fixed">Войти</button>
|
||||
<a class="btn btn-primary button-fixed" href="/signup">Регистрация</a>
|
||||
</form>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
@ -1,56 +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-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="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 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>
|
||||
</body>
|
||||
</html>
|
19
src/main/resources/templates/topicEdit.html
Normal file
19
src/main/resources/templates/topicEdit.html
Normal file
@ -0,0 +1,19 @@
|
||||
<!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>
|
32
src/main/resources/templates/topics.html
Normal file
32
src/main/resources/templates/topics.html
Normal file
@ -0,0 +1,32 @@
|
||||
<!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>
|
31
src/main/resources/templates/userEditPage.html
Normal file
31
src/main/resources/templates/userEditPage.html
Normal file
@ -0,0 +1,31 @@
|
||||
<!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>
|
@ -8,17 +8,17 @@
|
||||
<div layout:fragment="content">
|
||||
|
||||
<div class="text-center">
|
||||
<div class="text-start mx-auto w-25 border p-5">
|
||||
<div class="text-start mx-auto w-50 border p-5">
|
||||
<p class='h5'>Профиль</p>
|
||||
<p th:text="${'Логин: ' + profile.login}"></p>
|
||||
<p th:text="${'Логин: ' + user.login}"></p>
|
||||
<p class='h6 '>Список постов пользователя: </p>
|
||||
|
||||
<div th:if="${profile.posts.size()>0}">
|
||||
<div th:each="post: ${profile.posts}">
|
||||
<div th:if="${user.posts.size()>0}">
|
||||
<div th:each="post: ${user.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 th:unless="${user.posts.size()>0}">
|
||||
Нет постов
|
||||
</p>
|
||||
</div>
|
36
src/main/resources/templates/users.html
Normal file
36
src/main/resources/templates/users.html
Normal file
@ -0,0 +1,36 @@
|
||||
<!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