diff --git a/src/main/java/net/sytes/kashey/sweater/controller/UserController.java b/src/main/java/net/sytes/kashey/sweater/controller/UserController.java index b721c19..c3770eb 100644 --- a/src/main/java/net/sytes/kashey/sweater/controller/UserController.java +++ b/src/main/java/net/sytes/kashey/sweater/controller/UserController.java @@ -68,4 +68,38 @@ public class UserController { customUserDetailsService.updateProfile(customUserDetails.getUser(), password, email); return "redirect:/users/profile"; } + + @GetMapping("/{type}/{user}/list") + public String getSubscribtions(@PathVariable User user, + @PathVariable String type, + Model model) { + model.addAttribute("userChannel", user); + model.addAttribute("type", type); + + if ("subscribers".equals(type)) { + model.addAttribute("users", user.getSubscribers()); + } else if ("subscriptions".equals(type)) { + model.addAttribute("users", user.getSubscribtions()); + } + + return "subscriptions"; + } + + @GetMapping("/subscribe/{user}") + public String subscribe(@AuthenticationPrincipal CustomUserDetails customUserDetails, + @PathVariable User user) { + + User currentUser = customUserDetails.getUser(); + customUserDetailsService.subscribe(currentUser, user); + return "redirect:/user-messages/" + user.getId(); + } + + @GetMapping("/unsubscribe/{user}") + public String unsubscribe(@AuthenticationPrincipal CustomUserDetails customUserDetails, + @PathVariable User user) { + + User currentUser = customUserDetails.getUser(); + customUserDetailsService.unsubscribe(currentUser, user); + return "redirect:/user-messages/" + user.getId(); + } } \ No newline at end of file diff --git a/src/main/java/net/sytes/kashey/sweater/controller/UserMessagesController.java b/src/main/java/net/sytes/kashey/sweater/controller/UserMessagesController.java index a45227b..e486b17 100644 --- a/src/main/java/net/sytes/kashey/sweater/controller/UserMessagesController.java +++ b/src/main/java/net/sytes/kashey/sweater/controller/UserMessagesController.java @@ -39,31 +39,35 @@ public class UserMessagesController { model.addAttribute("isCurrentUser", user.equals(currentUser)); model.addAttribute("messages", user.getMessages()); model.addAttribute("message", message); + model.addAttribute("userChannel", user); + model.addAttribute("subscribersCount", user.getSubscribers().size()); + model.addAttribute("subscriptionsCount", user.getSubscribtions().size()); + model.addAttribute("isSubscriber", user.getSubscribers().contains(currentUser)); + return "user_messages"; } @PostMapping("/user-messages/{userId}") - public String getUserMessages(@AuthenticationPrincipal CustomUserDetails customUserDetails, - @PathVariable(name = "userId") Long userId, - @RequestParam(required = false) Message message, - @RequestParam String text, - @RequestParam String tag, - @RequestParam("file") MultipartFile file + public String getUserMessage(@AuthenticationPrincipal CustomUserDetails customUserDetails, + @PathVariable(name = "userId") Long userId, + @ModelAttribute Message message, + @RequestParam String text, + @RequestParam String tag, + @RequestParam("file") MultipartFile file ) throws IOException { - User currentUser = customUserDetails.getUser(); - if (message.getAuthor().equals(currentUser)) { - if (!ObjectUtils.isEmpty(text)) { - message.setText(text); - } + message.setAuthor(customUserDetails.getUser()); - if (!ObjectUtils.isEmpty(tag)) { - message.setTag(tag); - } - - ControllerUtils.saveFile(message, file, uploadPath); - messageRepository.save(message); + if (!ObjectUtils.isEmpty(text)) { + message.setText(text); } + + if (!ObjectUtils.isEmpty(tag)) { + message.setTag(tag); + } + + ControllerUtils.saveFile(message, file, uploadPath); + messageRepository.save(message); return "redirect:/user-messages/" + userId; } } \ No newline at end of file diff --git a/src/main/java/net/sytes/kashey/sweater/domain/User.java b/src/main/java/net/sytes/kashey/sweater/domain/User.java index d670228..7ac6ed9 100644 --- a/src/main/java/net/sytes/kashey/sweater/domain/User.java +++ b/src/main/java/net/sytes/kashey/sweater/domain/User.java @@ -6,6 +6,7 @@ import jakarta.validation.constraints.NotBlank; import java.io.Serial; import java.io.Serializable; +import java.util.HashSet; import java.util.Objects; import java.util.Set; @@ -38,6 +39,15 @@ public class User implements Serializable { @OneToMany(mappedBy = "author", cascade = CascadeType.ALL, fetch = FetchType.LAZY) private Set messages; + @ManyToMany + @JoinTable(name = "user_subscriptions", joinColumns = { @JoinColumn(name = "channel_id")}, + inverseJoinColumns = { @JoinColumn(name = "subscriber_id")}) + private Set subscribers = new HashSet<>(); + + @ManyToMany + @JoinTable(name = "user_subscriptions", joinColumns = { @JoinColumn(name = "subscriber_id")}, + inverseJoinColumns = { @JoinColumn(name = "channel_id")}) + private Set subscribtions = new HashSet<>(); @Override public boolean equals(Object o) { if (this == o) return true; @@ -126,4 +136,20 @@ public class User implements Serializable { public void setMessages(Set messages) { this.messages = messages; } + + public Set getSubscribers() { + return subscribers; + } + + public void setSubscribers(Set subscribers) { + this.subscribers = subscribers; + } + + public Set getSubscribtions() { + return subscribtions; + } + + public void setSubscribtions(Set subscribtions) { + this.subscribtions = subscribtions; + } } diff --git a/src/main/java/net/sytes/kashey/sweater/service/CustomUserDetailsService.java b/src/main/java/net/sytes/kashey/sweater/service/CustomUserDetailsService.java index c8e02d8..eb5999d 100644 --- a/src/main/java/net/sytes/kashey/sweater/service/CustomUserDetailsService.java +++ b/src/main/java/net/sytes/kashey/sweater/service/CustomUserDetailsService.java @@ -66,6 +66,7 @@ public class CustomUserDetailsService implements UserDetailsService { } private void sendMessage(User user) { + if (!ObjectUtils.isEmpty(user.getEmail())) { String message = String.format( @@ -133,6 +134,19 @@ public class CustomUserDetailsService implements UserDetailsService { } public List findAll() { + return userRepository.findAll(); } + + public void subscribe(User currentUser, User user) { + + user.getSubscribers().add(currentUser); + userRepository.save(user); + } + + public void unsubscribe(User currentUser, User user) { + + user.getSubscribers().remove(currentUser); + userRepository.save(user); + } } diff --git a/src/main/resources/db/migration/V3__Add_user_subscriptions_table.sql b/src/main/resources/db/migration/V3__Add_user_subscriptions_table.sql new file mode 100644 index 0000000..ef103fb --- /dev/null +++ b/src/main/resources/db/migration/V3__Add_user_subscriptions_table.sql @@ -0,0 +1,8 @@ +create table if not exists user_subscriptions +( + channel_id bigint not null references usr, + subscriber_id bigint not null references usr, + primary key (channel_id, subscriber_id), + FOREIGN KEY (channel_id) REFERENCES usr(id), + FOREIGN KEY (subscriber_id) REFERENCES usr(id) +) engine = InnoDB; \ No newline at end of file diff --git a/src/main/resources/templates/parts/login.ftl b/src/main/resources/templates/parts/login.ftl index 20fdd5a..eb01e16 100644 --- a/src/main/resources/templates/parts/login.ftl +++ b/src/main/resources/templates/parts/login.ftl @@ -1,3 +1,4 @@ +<#include "security.ftl"> <#macro login path isRegistrationForm=false>
@@ -74,6 +75,6 @@ <#macro logout> - + \ No newline at end of file diff --git a/src/main/resources/templates/parts/messageEditor.ftl b/src/main/resources/templates/parts/messageEditor.ftl index 35abfd4..c3e0798 100644 --- a/src/main/resources/templates/parts/messageEditor.ftl +++ b/src/main/resources/templates/parts/messageEditor.ftl @@ -1,4 +1,6 @@ - @@ -30,7 +32,7 @@
- ${message.id}/> +
diff --git a/src/main/resources/templates/parts/navbar.ftl b/src/main/resources/templates/parts/navbar.ftl index cdfc125..89253d0 100644 --- a/src/main/resources/templates/parts/navbar.ftl +++ b/src/main/resources/templates/parts/navbar.ftl @@ -14,10 +14,10 @@ + <#if user??> - <#if user??> @@ -34,7 +34,7 @@ - -
<#if name != "unknown"> <@l.logout />
+ + <@l.logout /> \ No newline at end of file diff --git a/src/main/resources/templates/subscriptions.ftl b/src/main/resources/templates/subscriptions.ftl new file mode 100644 index 0000000..40fab53 --- /dev/null +++ b/src/main/resources/templates/subscriptions.ftl @@ -0,0 +1,12 @@ +<#import "parts/common.ftl" as com> +<@com.page> +

${userChannel.username}

+
${type}
+ + \ No newline at end of file diff --git a/src/main/resources/templates/user_messages.ftl b/src/main/resources/templates/user_messages.ftl index 7f3a366..8e0f77e 100644 --- a/src/main/resources/templates/user_messages.ftl +++ b/src/main/resources/templates/user_messages.ftl @@ -1,5 +1,39 @@ <#import "parts/common.ftl" as com> <@com.page> +

${userChannel.username}

+ <#if !isCurrentUser> +
+ <#if isSubscriber> + Unsubscibe + <#else> + Subscribe + +
+ +
+
+
+
+
+
Subscriptions
+

+ ${subscriptionsCount} +

+
+
+
+
+
+
+
Subscribers
+

+ ${subscribersCount} +

+
+
+
+
+
<#if isCurrentUser> <#include "parts/messageEditor.ftl">