Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -36,4 +36,5 @@ out/
### VS Code ###
.vscode/

### Project specific
application.yml
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,4 +24,6 @@ Once you are fully up to speed and working on the project it is perfectly accept

Once you have your teams set up, enjoy working on the code.

We look forward to seeing what you manage to produce from it!
We look forward to seeing what you manage to produce from it!

----Test access Magnus-----
23 changes: 21 additions & 2 deletions src/main/java/com/booleanuk/Main.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.security.crypto.password.PasswordEncoder;

import java.time.LocalDate;
import java.util.HashSet;
import java.util.Set;

Expand Down Expand Up @@ -69,7 +70,16 @@ public void run(String... args) {
}
Profile studentProfile;
if (!this.profileRepository.existsById(1)) {
studentProfile = this.profileRepository.save(new Profile(studentUser, "Joe", "Bloggs", "Hello world!", "student1"));
studentProfile = this.profileRepository.save(new Profile(studentUser,
"Joe",
"Bloggs",
"Hello world!",
"student1",
"11111111",
"Backend Development",
LocalDate.of(2025, 9, 8
), LocalDate.of(2026, 9, 8)
));
} else {
studentProfile = this.profileRepository.findById(1).orElse(null);
}
Expand All @@ -84,7 +94,16 @@ public void run(String... args) {
}
Profile teacherProfile;
if (!this.profileRepository.existsById(2)) {
teacherProfile = this.profileRepository.save(new Profile(teacherUser, "Rick", "Sanchez", "Hello there!", "teacher1"));
teacherProfile = this.profileRepository.save(new Profile(teacherUser,
"Rick",
"Sanchez",
"Hello there!",
"teacher1",
"88888888",
"Everything",
LocalDate.of(1962, 9, 8),
LocalDate.of(2062, 9, 8)
));
} else {
teacherProfile = this.profileRepository.findById(2).orElse(null);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import java.util.Set;
import java.util.stream.Collectors;

//fixed issue with login.
@CrossOrigin(origins = "*", maxAge = 3600)
@RestController
@RequestMapping
Expand Down Expand Up @@ -69,6 +70,17 @@ public ResponseEntity<?> registerUser(@Valid @RequestBody SignupRequest signupRe
if (userRepository.existsByEmail(signupRequest.getEmail())) {
return ResponseEntity.badRequest().body(new MessageResponse("Error: Email is already in use!"));
}


String emailRegex = "^\\w+([.-]?\\w+)*@\\w+([.-]?\\w+)*(\\.\\w{2,3})+$";
String passwordRegex = "^(?=.*[A-Z])(?=.*[0-9])(?=.*[#?!@$%^&-]).{8,}$";

if(!signupRequest.getEmail().matches(emailRegex))
return ResponseEntity.badRequest().body(new MessageResponse("Email is incorrectly formatted"));

if(!signupRequest.getPassword().matches(passwordRegex))
return ResponseEntity.badRequest().body(new MessageResponse("Password is incorrectly formatted"));

// Create a new user add salt here if using one
User user = new User(signupRequest.getEmail(), encoder.encode(signupRequest.getPassword()));
if (signupRequest.getCohort() != null) {
Expand Down
261 changes: 218 additions & 43 deletions src/main/java/com/booleanuk/cohorts/controllers/PostController.java
Original file line number Diff line number Diff line change
@@ -1,23 +1,39 @@
package com.booleanuk.cohorts.controllers;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.booleanuk.cohorts.models.Author;
import com.booleanuk.cohorts.models.Comment;
import com.booleanuk.cohorts.models.Post;
import com.booleanuk.cohorts.models.Profile;
import com.booleanuk.cohorts.models.User;
import com.booleanuk.cohorts.payload.request.CommentRequest;
import com.booleanuk.cohorts.payload.request.PostRequest;
import com.booleanuk.cohorts.payload.response.CommentResponse;
import com.booleanuk.cohorts.payload.response.ErrorResponse;
import com.booleanuk.cohorts.payload.response.PostListResponse;
import com.booleanuk.cohorts.payload.response.PostResponse;
import com.booleanuk.cohorts.payload.response.Response;
import com.booleanuk.cohorts.repository.CommentRepository;
import com.booleanuk.cohorts.repository.PostRepository;
import com.booleanuk.cohorts.repository.ProfileRepository;
import com.booleanuk.cohorts.repository.UserRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.util.ArrayList;
import java.util.List;
import com.booleanuk.cohorts.security.services.UserDetailsImpl;

@CrossOrigin(origins = "*", maxAge = 3600)
@RestController
Expand All @@ -29,51 +45,210 @@ public class PostController {
private UserRepository userRepository;
@Autowired
private ProfileRepository profileRepository;
@Autowired
private CommentRepository commentRepository;

private User getCurrentAuthenticatedUser() {
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
if (authentication != null && authentication.getPrincipal() instanceof UserDetailsImpl) {
UserDetailsImpl userDetails = (UserDetailsImpl) authentication.getPrincipal();
return this.userRepository.findByEmail(userDetails.getEmail()).orElse(null);
}
return null;
}

private ResponseEntity<Response> unauthorizedResponse() {
ErrorResponse error = new ErrorResponse();
error.set("Authentication required");
return new ResponseEntity<>(error, HttpStatus.UNAUTHORIZED);
}

private ResponseEntity<Response> notFoundResponse(String message) {
ErrorResponse error = new ErrorResponse();
error.set(message);
return new ResponseEntity<>(error, HttpStatus.NOT_FOUND);
}

private ResponseEntity<Response> badRequestResponse(String message) {
ErrorResponse error = new ErrorResponse();
error.set(message);
return new ResponseEntity<>(error, HttpStatus.BAD_REQUEST);
}

private ResponseEntity<Response> forbiddenResponse(String message) {
ErrorResponse error = new ErrorResponse();
error.set(message);
return new ResponseEntity<>(error, HttpStatus.FORBIDDEN);
}

private void setAuthorInfo(Post post) {
User user = post.getUser();
if (user != null && user.getCohort() != null) {
Profile profile = this.profileRepository.findById(user.getId()).orElse(null);
if (profile != null) {
Author author = new Author(user.getId(), user.getCohort().getId(),
profile.getFirstName(), profile.getLastName(), user.getEmail(),
profile.getBio(), profile.getGithubUrl());
post.setAuthor(author);
}
}
}

@GetMapping
public ResponseEntity<?> getAllPosts() {
List<Post> posts = this.postRepository.findAll();
posts.forEach(this::setAuthorInfo);

PostListResponse postListResponse = new PostListResponse();
User user = this.userRepository.findById(1).orElse(null);
if (user == null) {
ErrorResponse error = new ErrorResponse();
error.set("not found");
return new ResponseEntity<>(error, HttpStatus.NOT_FOUND);
}
Profile profile = this.profileRepository.findById(user.getId()).orElse(null);
if (profile == null) {
ErrorResponse error = new ErrorResponse();
error.set("not found");
return new ResponseEntity<>(error, HttpStatus.NOT_FOUND);
}
Author author = new Author(user.getId(), user.getCohort().getId(), profile.getFirstName(),
profile.getLastName(), user.getEmail(), profile.getBio(), profile.getGithubUrl());
List<Post> posts = new ArrayList<>();
Post post1 = this.postRepository.findById(1).orElse(null);
if (post1 == null){
ErrorResponse error = new ErrorResponse();
error.set("not found");
return new ResponseEntity<>(error, HttpStatus.NOT_FOUND);
}
post1.setAuthor(author);
post1.setContent("Hello world!!");
posts.add(post1);
Post post2 = this.postRepository.findById(2).orElse(null);
if (post2 == null){
ErrorResponse error = new ErrorResponse();
error.set("not found");
return new ResponseEntity<>(error, HttpStatus.NOT_FOUND);
}
post2.setAuthor(author);
post2.setContent("Hello from the void!!");
posts.add(post2);
postListResponse.set(posts);
return ResponseEntity.ok(postListResponse);
}

@PostMapping
public ResponseEntity<Response> createPost(@RequestBody PostRequest postRequest) {
User currentUser = getCurrentAuthenticatedUser();
if (currentUser == null) return unauthorizedResponse();

Post post = new Post(postRequest.getContent(), currentUser, 0);
Post savedPost = this.postRepository.save(post);
setAuthorInfo(savedPost);

PostResponse postResponse = new PostResponse();
postResponse.set(savedPost);
return new ResponseEntity<>(postResponse, HttpStatus.CREATED);
}

@GetMapping("/{id}")
public ResponseEntity<Response> getPostById(@PathVariable int id) {
ErrorResponse error = new ErrorResponse();
error.set("not found");
return new ResponseEntity<>(error, HttpStatus.NOT_FOUND);
Post post = this.postRepository.findById(id).orElse(null);
if (post == null) return notFoundResponse("Post not found");

setAuthorInfo(post);
PostResponse postResponse = new PostResponse();
postResponse.set(post);
return ResponseEntity.ok(postResponse);
} @PostMapping("/{postId}/comments")
public ResponseEntity<Response> addCommentToPost(@PathVariable int postId, @RequestBody CommentRequest commentRequest) {
Post post = this.postRepository.findById(postId).orElse(null);
if (post == null) return notFoundResponse("Post not found");

User user = this.userRepository.findById(commentRequest.getUserId()).orElse(null);
if (user == null) return notFoundResponse("User not found");

Comment comment = new Comment(commentRequest.getBody(), user, post);
Comment savedComment = this.commentRepository.save(comment);

CommentResponse commentResponse = new CommentResponse();
commentResponse.set(savedComment);
return new ResponseEntity<>(commentResponse, HttpStatus.CREATED);
}

@GetMapping("/{postId}/comments")
public ResponseEntity<Response> getCommentsForPost(@PathVariable int postId) {
Post post = this.postRepository.findById(postId).orElse(null);
if (post == null) return notFoundResponse("Post not found");

PostResponse postResponse = new PostResponse();
postResponse.set(post);
return ResponseEntity.ok(postResponse);
}

@GetMapping("/{postId}/comments/{commentId}")
public ResponseEntity<Response> getCommentById(@PathVariable int postId, @PathVariable int commentId) {
Post post = this.postRepository.findById(postId).orElse(null);
if (post == null) return notFoundResponse("Post not found");

Comment comment = this.commentRepository.findById(commentId).orElse(null);
if (comment == null) return notFoundResponse("Comment not found");

if (comment.getPost().getId() != postId)
return badRequestResponse("Comment does not belong to the specified post");

CommentResponse commentResponse = new CommentResponse();
commentResponse.set(comment);
return ResponseEntity.ok(commentResponse);
}

@PutMapping("/{postId}/comments/{commentId}")
public ResponseEntity<Response> updateComment(@PathVariable int postId, @PathVariable int commentId, @RequestBody CommentRequest commentRequest) {
User currentUser = getCurrentAuthenticatedUser();
if (currentUser == null) return unauthorizedResponse();

Post post = this.postRepository.findById(postId).orElse(null);
if (post == null) return notFoundResponse("Post not found");

Comment comment = this.commentRepository.findById(commentId).orElse(null);
if (comment == null) return notFoundResponse("Comment not found");

if (comment.getPost().getId() != postId)
return badRequestResponse("Comment does not belong to the specified post");

if (comment.getUser().getId() != currentUser.getId())
return forbiddenResponse("You can only edit your own comments");

comment.setBody(commentRequest.getBody());
Comment updatedComment = this.commentRepository.save(comment);

CommentResponse commentResponse = new CommentResponse();
commentResponse.set(updatedComment);
return ResponseEntity.ok(commentResponse);
}

@DeleteMapping("/{postId}/comments/{commentId}")
public ResponseEntity<Response> deleteComment(@PathVariable int postId, @PathVariable int commentId) {
User currentUser = getCurrentAuthenticatedUser();
if (currentUser == null) return unauthorizedResponse();

Post post = this.postRepository.findById(postId).orElse(null);
if (post == null) return notFoundResponse("Post not found");

Comment comment = this.commentRepository.findById(commentId).orElse(null);
if (comment == null) return notFoundResponse("Comment not found");

if (comment.getPost().getId() != postId)
return badRequestResponse("Comment does not belong to the specified post");

if (comment.getUser().getId() != currentUser.getId())
return forbiddenResponse("You can only delete your own comments");

this.commentRepository.delete(comment);

ErrorResponse success = new ErrorResponse();
success.set("Comment deleted successfully");
return ResponseEntity.ok(success);
}

@PostMapping("/{postId}/like")
public ResponseEntity<Response> likePost(@PathVariable int postId) {
User currentUser = getCurrentAuthenticatedUser();
if (currentUser == null) return unauthorizedResponse();

Post post = this.postRepository.findById(postId).orElse(null);
if (post == null) return notFoundResponse("Post not found");

post.setLikes(post.getLikes() + 1);
Post updatedPost = this.postRepository.save(post);
setAuthorInfo(updatedPost);

PostResponse postResponse = new PostResponse();
postResponse.set(updatedPost);
return ResponseEntity.ok(postResponse);
}

@DeleteMapping("/{postId}/like")
public ResponseEntity<Response> unlikePost(@PathVariable int postId) {
User currentUser = getCurrentAuthenticatedUser();
if (currentUser == null) return unauthorizedResponse();

Post post = this.postRepository.findById(postId).orElse(null);
if (post == null) return notFoundResponse("Post not found");

post.setLikes(Math.max(0, post.getLikes() - 1));
Post updatedPost = this.postRepository.save(post);
setAuthorInfo(updatedPost);

PostResponse postResponse = new PostResponse();
postResponse.set(updatedPost);
return ResponseEntity.ok(postResponse);
}
}
Loading