Skip to content

Friend list #230

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 91 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
91 commits
Select commit Hold shift + click to select a range
96c13d7
Update README.md
sashaparkes Jun 2, 2025
f697244
altered existing tables and created new table migrations
Shanice598 Jun 3, 2025
3834bf4
Merge pull request #1 from sashaparkes/migrations
A-Schmigiel Jun 3, 2025
41456a4
updated user model and tests
sashaparkes Jun 3, 2025
7c3199f
Merge remote-tracking branch 'origin/main' into sign_up
sashaparkes Jun 3, 2025
3ce1025
pull
A-Schmigiel Jun 3, 2025
e56e6d0
update user model again
sashaparkes Jun 3, 2025
5db70b5
yml fix
Shanice598 Jun 3, 2025
781bcac
Merge pull request #3 from sashaparkes/migrations
A-Schmigiel Jun 3, 2025
2250297
Mid workflow
A-Schmigiel Jun 3, 2025
34bbbd7
Mid workflow
A-Schmigiel Jun 3, 2025
daff4b1
Auth0 taking name details etc
sashaparkes Jun 4, 2025
61e71b2
Notifications Model/Controller/Interface/HTML-- working except for th…
A-Schmigiel Jun 4, 2025
b7101f6
basic settings page
sashaparkes Jun 4, 2025
bb6eee9
settings page
sashaparkes Jun 4, 2025
065999b
settings
sashaparkes Jun 4, 2025
0bfd2c6
Merge pull request #4 from sashaparkes/sign_up
A-Schmigiel Jun 4, 2025
ff069be
friends
HarryMcconville Jun 4, 2025
9c0648c
Merge branch 'main' into notifications
sashaparkes Jun 4, 2025
686c28e
Merge pull request #5 from sashaparkes/notifications
sashaparkes Jun 4, 2025
0855208
Merge pull request #6 from sashaparkes/friend_list
sashaparkes Jun 4, 2025
968fb0c
image uploader updates
sashaparkes Jun 4, 2025
a275311
image uploader
sashaparkes Jun 4, 2025
9563f2c
fixed friends template
HarryMcconville Jun 4, 2025
259c2ad
Updated PostController, Posts index.html, and individual post html, a…
A-Schmigiel Jun 4, 2025
9410fad
Notifications now correctly marking as read when clicked.
A-Schmigiel Jun 4, 2025
ab964d3
image uploader updated
sashaparkes Jun 4, 2025
b072ba0
updated friends page
HarryMcconville Jun 4, 2025
c83931e
Merge pull request #9 from sashaparkes/friend_list
Jordan-Gill Jun 4, 2025
8ac358c
Merge pull request #8 from sashaparkes/notifications
Jordan-Gill Jun 4, 2025
8897fef
Merge pull request #10 from sashaparkes/sign_up
HarryMcconville Jun 4, 2025
f2de4ac
Notifications now (actually) correctly marking as read when clicked.
A-Schmigiel Jun 4, 2025
7319078
adding dsstore
Shanice598 Jun 5, 2025
677bb02
users can comment on posts and like comments MVC's only
Shanice598 Jun 5, 2025
753e3b8
adding controller for comments
Shanice598 Jun 5, 2025
cf12eff
corrected errors for commentlike stuff, small change in user.java
Shanice598 Jun 5, 2025
38de3c7
settings page tests
sashaparkes Jun 5, 2025
3efaeb1
Navbar up and running
A-Schmigiel Jun 5, 2025
80b2a40
Navbar, Notifications, and Posts updates
A-Schmigiel Jun 5, 2025
ff5bbb9
Merge pull request #11 from sashaparkes/usercommentonposts
A-Schmigiel Jun 5, 2025
6a97af7
settings.html fix
A-Schmigiel Jun 5, 2025
e8c1d06
settings.html merge fix
A-Schmigiel Jun 5, 2025
93927cf
Merge pull request #13 from sashaparkes/notifications
Jordan-Gill Jun 5, 2025
eddb8b1
Temporary comment fix :(
A-Schmigiel Jun 5, 2025
bc98908
partway through testing settings page
sashaparkes Jun 5, 2025
753e8e7
Merge pull request #14 from sashaparkes/notifications
Jordan-Gill Jun 5, 2025
47a7611
completed feature tests for settings page
sashaparkes Jun 5, 2025
dd4de01
Friend requests can be accepted/rejected
HarryMcconville Jun 5, 2025
edf5d50
creating comment like functionality, and display name for comments
Shanice598 Jun 5, 2025
67191c6
added V12 migration to add friends since...
HarryMcconville Jun 5, 2025
27df91b
First commit
Jordan-Gill Jun 5, 2025
d9f1045
changed v12 to v13
HarryMcconville Jun 5, 2025
88ec736
changed name again whoops
HarryMcconville Jun 5, 2025
797a3e4
Merge pull request #15 from sashaparkes/friend_list
A-Schmigiel Jun 5, 2025
ab30d5b
Merge pull request #17 from sashaparkes/user_details_with_post
A-Schmigiel Jun 5, 2025
ccc6c9f
settings page tests without images
sashaparkes Jun 6, 2025
56d9dbb
Making some edits and adding comments to User class that I needed to …
Shanice598 Jun 6, 2025
29306a6
Html navbarfix
A-Schmigiel Jun 6, 2025
f0e9b24
removed images
sashaparkes Jun 6, 2025
a98b30c
Merge pull request #16 from sashaparkes/testing_user_controller
A-Schmigiel Jun 6, 2025
1dfdf91
ShanniCode merge
A-Schmigiel Jun 6, 2025
42f3ee3
Ordering requests and friends
HarryMcconville Jun 6, 2025
3fde400
Merge branch 'main' into friend_list
HarryMcconville Jun 6, 2025
2556ea7
ShanniCode merge
A-Schmigiel Jun 6, 2025
8feaadf
ShanniCode merge
A-Schmigiel Jun 6, 2025
1506295
added db migration V13
sashaparkes Jun 6, 2025
8e0a4e0
post upload merged with main functionality
sashaparkes Jun 6, 2025
9ab2e0f
deleted images
sashaparkes Jun 6, 2025
4240fe9
Remove friends route added and add friends route added but not tested
HarryMcconville Jun 6, 2025
e19b3f5
Comments/Likes patch completed
A-Schmigiel Jun 6, 2025
51eb61b
Merge pull request #20 from sashaparkes/image_upload_retry
Jordan-Gill Jun 6, 2025
02cc3fd
First commit
Jordan-Gill Jun 6, 2025
3d2e4ae
Merge pull request #21 from sashaparkes/friend_list
Jordan-Gill Jun 6, 2025
9d907f2
links
A-Schmigiel Jun 6, 2025
4d907ad
Comment/like merge patch
A-Schmigiel Jun 6, 2025
7407702
Comment/like merge patch
A-Schmigiel Jun 6, 2025
179098e
Merge pull request #22 from sashaparkes/temp
Jordan-Gill Jun 6, 2025
3e63ca7
Second commit
Jordan-Gill Jun 6, 2025
81a0937
merging in updates
A-Schmigiel Jun 6, 2025
b4153c2
merging in updates
A-Schmigiel Jun 6, 2025
c5afe45
added links to posts/users in html for posts and post pages
A-Schmigiel Jun 6, 2025
cfb7559
Third commit
Jordan-Gill Jun 6, 2025
37b212b
Merged main commit
Jordan-Gill Jun 6, 2025
8e09c57
Monday Commit
Jordan-Gill Jun 9, 2025
f0191f2
Merge pull request #23 from sashaparkes/notifications
sashaparkes Jun 9, 2025
a31e649
Merge branch 'main' into basic_html
sashaparkes Jun 9, 2025
0d7a3bb
Merge pull request #24 from sashaparkes/basic_html
sashaparkes Jun 9, 2025
9c343aa
bug fix for image uploading
sashaparkes Jun 9, 2025
f3c53f4
Merge pull request #25 from sashaparkes/profile_image_bug_fix
HarryMcconville Jun 9, 2025
6d84fd0
seed files stuff
HarryMcconville Jun 9, 2025
24f21f1
more like DS BORE
HarryMcconville Jun 9, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added .DS_Store
Binary file not shown.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,5 @@ dependency-reduced-pom.xml
.factorypath
.project
.settings/
application.yml
.DS_Store
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# Acebook

https://trello.com/b/VidgaAkH/acebook-engineering-project-2

The application uses:
- `maven` to build the project
- `thymeleaf` for templating
Expand Down
3 changes: 3 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.32</version>
<scope>provided</scope>
</dependency>
<dependency>
Expand Down Expand Up @@ -102,6 +103,7 @@
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>3.3.2</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
Expand All @@ -114,6 +116,7 @@
<path>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.32</version>
</path>
</annotationProcessorPaths>
</configuration>
Expand Down
Binary file added src/.DS_Store
Binary file not shown.
Binary file added src/main/.DS_Store
Binary file not shown.
Binary file added src/main/java/.DS_Store
Binary file not shown.
Binary file added src/main/java/com/.DS_Store
Binary file not shown.
Binary file added src/main/java/com/makersacademy/.DS_Store
Binary file not shown.
Binary file not shown.
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,10 @@ public SecurityFilterChain configure(HttpSecurity http) throws Exception {
http
.csrf(csrf -> csrf.disable())
.authorizeHttpRequests(authorize -> authorize
.requestMatchers("/", "/images/**").permitAll()
.requestMatchers("/",
"/main.css",
"/images/**",
"/favicon.png").permitAll()
.anyRequest().authenticated()
)
.oauth2Login(oauth2 -> oauth2
Expand Down
24 changes: 24 additions & 0 deletions src/main/java/com/makersacademy/acebook/config/WebConfig.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package com.makersacademy.acebook.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

// This class customises how the app serves static resources (e.g. images) from the file system
// Resource handlers map URL paths to filesystem directories so static files (e.g. images) can be served via HTTP
// This is required for image storage outside the classpath (src) on uploading

@Configuration
public class WebConfig implements WebMvcConfigurer {

@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
// Handler for profile images
registry.addResourceHandler("/uploads/user_profile/**")
.addResourceLocations("file:uploads/user_profile/");

// Handler for post images
registry.addResourceHandler("/uploads/post_images/**")
.addResourceLocations("file:uploads/post_images/");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package com.makersacademy.acebook.controller;

import com.makersacademy.acebook.dto.CommentRequest;
import com.makersacademy.acebook.model.Comment;
import com.makersacademy.acebook.model.Post;
import com.makersacademy.acebook.model.User;
import com.makersacademy.acebook.repository.PostRepository;
import com.makersacademy.acebook.repository.UserRepository;
import com.makersacademy.acebook.service.CommentService;
import java.util.List;

import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.view.RedirectView;

@Controller
@RequestMapping("/posts/comments")
public class CommentController {

private final CommentService commentService;
private final PostRepository postRepository;
private final UserRepository userRepository;

public CommentController(CommentService commentService, PostRepository postRepository, UserRepository userRepository) {
this.commentService = commentService;
this.postRepository = postRepository;
this.userRepository = userRepository;
}


@GetMapping("/post/{postId}")
@ResponseBody
public List<Comment> getCommentsByPost(@PathVariable Long postId) {
return commentService.getCommentsForPost(postId);
}

// This will POST to add a comment and then redirect back to the post with the updated comment for that post
@PostMapping
public RedirectView createComment(@ModelAttribute CommentRequest request,
@AuthenticationPrincipal(expression = "attributes['email']") String email) {
Post post = postRepository.findById(request.getPostId())
.orElseThrow(() -> new RuntimeException("Post not found"));

User user = userRepository.findUserByUsername(email)
.orElseThrow(() -> new RuntimeException("User not found"));

Comment comment = new Comment();
comment.setPost(post);
comment.setUser(user);
comment.setContent(request.getContent());

commentService.addComment(comment);
return new RedirectView("/posts/" + post.getId());
}


}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package com.makersacademy.acebook.controller;

import com.makersacademy.acebook.service.CommentLikeService;
import jakarta.transaction.Transactional;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.security.oauth2.core.oidc.user.DefaultOidcUser;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.view.RedirectView;

@Controller
@RequestMapping("/posts/comments")
public class CommentLikeController {
private final CommentLikeService commentLikeService;
public CommentLikeController(CommentLikeService commentLikeService) {
this.commentLikeService = commentLikeService;
}

@Transactional
@PostMapping("/{commentId}/like")
public RedirectView likeComment(@PathVariable Long commentId,
@RequestParam Long postId,
@AuthenticationPrincipal(expression = "attributes['email']") String email) {
commentLikeService.likeComment(commentId, email);
return new RedirectView("/posts/" + postId);
}

@Transactional
@PostMapping("/{commentId}/unlike")
public RedirectView unlikeComment(@PathVariable Long commentId,
@RequestParam Long postId,
@AuthenticationPrincipal(expression = "attributes['email']") String email) {
commentLikeService.unlikeComment(commentId, email);
return new RedirectView("/posts/" + postId);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,188 @@
package com.makersacademy.acebook.controller;

import com.makersacademy.acebook.model.Friend;
import com.makersacademy.acebook.model.FriendRequest;
import com.makersacademy.acebook.model.User;
import com.makersacademy.acebook.repository.FriendRepository;
import com.makersacademy.acebook.repository.FriendRequestRepository;
import com.makersacademy.acebook.repository.UserRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.view.RedirectView;

import java.sql.Timestamp;
import java.time.Instant;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Optional;

@Controller
public class FriendsController {

@Autowired
FriendRequestRepository friendRequestRepository;
@Autowired
FriendRepository friendRepository;
@Autowired
UserRepository userRepository;

@GetMapping("/friends")
public ModelAndView friendList(@AuthenticationPrincipal(expression = "attributes['email']") String email) {
ModelAndView modelAndView = new ModelAndView("friends/friends");

// User!
Optional<User> userOptional = userRepository.findUserByUsername(email);

User currentUser = userOptional.get();
Long userId = currentUser.getId();

// Friends!
List<Friend> friendsList = friendRepository.findAllByMainUserId(userId);

// Objectify!
List<User> friendUsers = new ArrayList<>();
for (Friend friend : friendsList) {
Long friendId = friend.getFriendUserId();
Optional<User> friendUser = userRepository.findById(friendId);
if (friendUser.isPresent()) {
friendUsers.add(friendUser.get());
}
}

// Sort the users into alphabetical order!
friendUsers.sort(Comparator.comparing(User::getFirstName));


// Friend Requests!
List<FriendRequest> pendingRequests = friendRequestRepository.findAllByReceiverIdAndStatusOrderByCreatedAtDesc(userId, "pending");


// Objectify!
List<User> requesterUsers = new ArrayList<>();
for (FriendRequest request : pendingRequests) {
Long requesterId = request.getRequesterId();
Optional<User> requesterUser = userRepository.findById(requesterId);
if (requesterUser.isPresent()) {
requesterUsers.add(requesterUser.get());
}
}

modelAndView.addObject("friendUsers", friendUsers);
modelAndView.addObject("requesterUsers", requesterUsers);

return modelAndView;
}


@PostMapping("/friend_request/{requesterId}")
public RedirectView respondToFriendRequest(
@PathVariable Long requesterId,
@RequestParam String decision,
@AuthenticationPrincipal(expression = "attributes['email']") String email) {

// Get User!
Optional<User> userOptional = userRepository.findUserByUsername(email);

User currentUser = userOptional.get();
Long currentUserId = currentUser.getId();

// Get Friend Request!
Optional<FriendRequest> friendRequestOptional = friendRequestRepository
.findByRequesterIdAndReceiverIdAndStatus(requesterId, currentUserId, "pending");


FriendRequest friendRequest = friendRequestOptional.get();

if (decision.equals("accept")) {
friendRequest.setStatus("accepted");
Instant instant = Instant.now();
Timestamp now = Timestamp.from(instant);
friendRequest.setRespondedAt(now);
friendRequestRepository.save(friendRequest);


Friend friendship1 = new Friend();
friendship1.setMainUserId(currentUserId);
friendship1.setFriendUserId(requesterId);
friendship1.setFriendsSince(now);
friendRepository.save(friendship1);

Friend friendship2 = new Friend();
friendship2.setMainUserId(requesterId);
friendship2.setFriendUserId(currentUserId);
friendship2.setFriendsSince(now);
friendRepository.save(friendship2);

} else if (decision.equals("decline")) {
friendRequest.setStatus("rejected");
Instant instant = Instant.now();
Timestamp now = Timestamp.from(instant);
friendRequest.setRespondedAt(now);
friendRequestRepository.save(friendRequest);
}

return new RedirectView("/friends");
}

@PostMapping("/remove_friend/{friendId}")
public RedirectView removeFriend(
@PathVariable Long friendId,
@AuthenticationPrincipal(expression = "attributes['email']") String email) {

// Get User!
Optional<User> userOptional = userRepository.findUserByUsername(email);

User currentUser = userOptional.get();
Long currentUserId = currentUser.getId();

//Find Friendships!

Optional<Friend> friendship1 = friendRepository.findByMainUserIdAndFriendUserId(currentUserId, friendId);
Optional<Friend> friendship2 = friendRepository.findByMainUserIdAndFriendUserId(friendId, currentUserId);

//Remove Friendships!
friendship1.ifPresent(friendRepository::delete);
friendship2.ifPresent(friendRepository::delete);

//Redirect to Friends!
return new RedirectView("/friends");
}

@PostMapping("/add_friend/{userId}")
public RedirectView addFriend(
@PathVariable Long userId,
@AuthenticationPrincipal(expression = "attributes['email']") String email) {

// Get User!
Optional<User> userOptional = userRepository.findUserByUsername(email);

User currentUser = userOptional.get();
Long currentUserId = currentUser.getId();

Optional<User> requestee = userRepository.findById(userId);

User requesteeUser = requestee.get();
Long requesteeId = requesteeUser.getId();

FriendRequest request = new FriendRequest();
request.setRequesterId(currentUserId);
request.setReceiverId(requesteeId);
friendRequestRepository.save(request);

return new RedirectView("/friends");
}

// @PostMapping("/friends")
// public RedirectView create(@ModelAttribute Friend friend, @AuthenticationPrincipal(expression = "attributes['email']") String email) {
// Optional<User> user = userRepository.findUserByUsername(email);
// if (user.isPresent()) {
// Long id = user.get().getId();
// }
// return new RedirectView("friends/friends");
// }
}

Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,13 @@

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.view.RedirectView;

@Controller
public class HomeController {
@RequestMapping(value = "/")
public RedirectView index() {
return new RedirectView("/posts");
public ModelAndView index() {
return new ModelAndView("/landing");
}
}
Loading