diff --git a/.gitignore b/.gitignore index c2065bc..7cf595e 100644 --- a/.gitignore +++ b/.gitignore @@ -35,3 +35,6 @@ out/ ### VS Code ### .vscode/ + +application.yml +*.jar diff --git a/Dockers/Dockerfile b/Dockers/Dockerfile new file mode 100644 index 0000000..ea842b5 --- /dev/null +++ b/Dockers/Dockerfile @@ -0,0 +1,9 @@ +FROM eclipse-temurin:18 + +WORKDIR /app + +COPY java.docker.day.2-0.0.1.jar /app/java.docker.day.2-0.0.1.jar + +EXPOSE 4000 + +ENTRYPOINT ["java", "-jar", "java.docker.day.2-0.0.1.jar"] \ No newline at end of file diff --git a/Dockers/docker-compose.yml b/Dockers/docker-compose.yml new file mode 100644 index 0000000..f865b08 --- /dev/null +++ b/Dockers/docker-compose.yml @@ -0,0 +1,21 @@ +services: + app: + image: 'docker-day-2:latest' + container_name: app + depends_on: + - db + ports: + - '4000:4000' + environment: + - SPRING_DATASOURCE_URL=jdbc:postgresql://db:5432/mypostgresuser + - SPRING_DATASOURCE_USERNAME=mypostgresuser + - SPRING_DATASOURCE_PASSWORD=mypostgrespassword + - SPRING_JPA_HIBERNATE_DDL_AUTO=update + + db: + image: 'postgres:latest' + container_name: db + environment: + - POSTGRES_USER=mypostgresuser + - POSTGRES_DATABASE=mypostgresuser + - POSTGRES_PASSWORD=mypostgrespassword \ No newline at end of file diff --git a/build.gradle b/build.gradle index fb070c4..769c163 100644 --- a/build.gradle +++ b/build.gradle @@ -23,7 +23,7 @@ dependencies { implementation 'org.springframework.boot:spring-boot-starter-web' compileOnly 'org.projectlombok:lombok' developmentOnly 'org.springframework.boot:spring-boot-devtools' - implementation 'org.postgresql:postgresql:42.6.0' + implementation 'org.postgresql:postgresql:42.7.2' annotationProcessor 'org.projectlombok:lombok' testImplementation 'org.springframework.boot:spring-boot-starter-test' } diff --git a/src/main/java/com/booleanuk/api/Main.java b/src/main/java/com/booleanuk/api/Main.java new file mode 100644 index 0000000..8e749e0 --- /dev/null +++ b/src/main/java/com/booleanuk/api/Main.java @@ -0,0 +1,11 @@ +package com.booleanuk.api; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class Main { + public static void main(String[] args) { + SpringApplication.run(Main.class, args); + } +} diff --git a/src/main/java/com/booleanuk/api/controller/PostController.java b/src/main/java/com/booleanuk/api/controller/PostController.java new file mode 100644 index 0000000..97608e8 --- /dev/null +++ b/src/main/java/com/booleanuk/api/controller/PostController.java @@ -0,0 +1,96 @@ +package com.booleanuk.api.controller; + +import com.booleanuk.api.model.Post; +import com.booleanuk.api.model.User; +import com.booleanuk.api.repository.PostRepository; +import com.booleanuk.api.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 org.springframework.web.server.ResponseStatusException; + +import java.util.List; + +@RestController +@RequestMapping("posts") +public class PostController { + @Autowired + private final PostRepository repository; + + @Autowired + private UserRepository userRepository; + + public PostController(PostRepository repository){ + this.repository = repository; + } + + @GetMapping + public ResponseEntity getAll() { + return ResponseEntity.ok(this.repository.findAll()); + } + + @GetMapping("{id}") + public ResponseEntity getOne(@PathVariable("id") Integer id) { + return ResponseEntity.ok(this.repository.findById(id).orElseThrow()); + } + + @ResponseStatus(HttpStatus.CREATED) + @PostMapping + public ResponseEntity createPost(@RequestBody Post post) { + User user = this.userRepository.findById(post.getUser().getId()).orElseThrow( + ()-> new ResponseStatusException(HttpStatus.NOT_FOUND, "No user found..") + ); + post.setUser(user); + + return new ResponseEntity<>(this.repository.save(post),HttpStatus.CREATED); + } + + // Update post + @PutMapping("{id}") + public ResponseEntity updatePost(@PathVariable("id") Integer id, + @RequestBody Post post) { + Post postToUpdate = this.repository.findById(id).orElseThrow( + () -> new ResponseStatusException(HttpStatus.NOT_FOUND, + "No existing post with that ID found") + ); + postToUpdate.setContent(post.getContent()); + + return new ResponseEntity<>(this.repository.save(postToUpdate), + HttpStatus.CREATED); + } + + // User upvotes post + @PutMapping("{id}/upvote/{uId}") + public ResponseEntity upvotePost(@PathVariable("id") Integer id, + @PathVariable("uId") Integer uId) { + Post postToUpvote = this.repository.findById(id).orElseThrow( + () -> new ResponseStatusException(HttpStatus.NOT_FOUND, + "No existing post with that ID found") + ); + User user = this.userRepository.findById(uId).orElseThrow( + () -> new ResponseStatusException(HttpStatus.NOT_FOUND, + "No user with that ID found") + ); + + List currentUpvotes = postToUpvote.getUserUpvotes(); + + if(!currentUpvotes.contains(user)){ + currentUpvotes.add(user); + } + postToUpvote.setUserUpvotes(currentUpvotes); + + return new ResponseEntity<>(this.repository.save(postToUpvote), + HttpStatus.CREATED); + } + + @DeleteMapping("{id}") + public ResponseEntity deletePost(@PathVariable("id") Integer id) { + Post postToDelete = this.repository.findById(id).orElseThrow( + () -> new ResponseStatusException(HttpStatus.NOT_FOUND, + "No post with that ID were found") + ); + this.repository.delete(postToDelete); + return ResponseEntity.ok(postToDelete); + } +} diff --git a/src/main/java/com/booleanuk/api/controller/UserController.java b/src/main/java/com/booleanuk/api/controller/UserController.java new file mode 100644 index 0000000..74a31b0 --- /dev/null +++ b/src/main/java/com/booleanuk/api/controller/UserController.java @@ -0,0 +1,64 @@ +package com.booleanuk.api.controller; + +import com.booleanuk.api.model.User; +import com.booleanuk.api.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 org.springframework.web.server.ResponseStatusException; + +@RestController +@RequestMapping("users") +public class UserController { + @Autowired + private final UserRepository repository; + + public UserController(UserRepository repository){ + this.repository = repository; + } + + @GetMapping + public ResponseEntity getAll() { + return ResponseEntity.ok(this.repository.findAll()); + } + + @GetMapping("{id}") + public ResponseEntity getOne(@PathVariable("id") Integer id) { + return ResponseEntity.ok(this.repository.findById(id).orElseThrow()); + } + + @ResponseStatus(HttpStatus.CREATED) + @PostMapping + public ResponseEntity createUser(@RequestBody User user) { + /* Course course = this.courseRepository.findById(user.getCourse().getId()).orElseThrow( + ()-> new ResponseStatusException(HttpStatus.NOT_FOUND, "No course found..") + ); + user.setCourse(course);*/ + + return new ResponseEntity<>(this.repository.save(user),HttpStatus.CREATED); + } + + @PutMapping("{id}") + public ResponseEntity updateUser(@PathVariable("id") Integer id, + @RequestBody User user) { + User userToUpdate = this.repository.findById(id).orElseThrow( + () -> new ResponseStatusException(HttpStatus.NOT_FOUND, + "No existing user with that ID found") + ); + userToUpdate.setUserName(user.getUserName()); + + return new ResponseEntity<>(this.repository.save(userToUpdate), + HttpStatus.CREATED); + } + + @DeleteMapping("{id}") + public ResponseEntity deleteUser(@PathVariable("id") Integer id) { + User userToDelete = this.repository.findById(id).orElseThrow( + () -> new ResponseStatusException(HttpStatus.NOT_FOUND, + "No user with that ID were found") + ); + this.repository.delete(userToDelete); + return ResponseEntity.ok(userToDelete); + } +} diff --git a/src/main/java/com/booleanuk/api/model/Post.java b/src/main/java/com/booleanuk/api/model/Post.java new file mode 100644 index 0000000..5bdcc5d --- /dev/null +++ b/src/main/java/com/booleanuk/api/model/Post.java @@ -0,0 +1,46 @@ +package com.booleanuk.api.model; + + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonIncludeProperties; +import jakarta.persistence.*; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +import java.util.List; + +@Getter +@Setter +@AllArgsConstructor +@NoArgsConstructor +@Entity +@Table(name = "posts") +public class Post { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Integer id; + + private String content; + + @ManyToOne + @JoinColumn(name = "user_id", nullable = false) + //@JsonIncludeProperties(value = {}) + @JsonIgnoreProperties("posts") + private User user; + + @ManyToMany + @JoinColumn(name = "upvotes") + @JsonIgnoreProperties("posts") + private List userUpvotes; + + + public Post(String content) { + this.content = content; + } + + public Post(int id) { + this.id = id; + } +} diff --git a/src/main/java/com/booleanuk/api/model/User.java b/src/main/java/com/booleanuk/api/model/User.java new file mode 100644 index 0000000..90406e4 --- /dev/null +++ b/src/main/java/com/booleanuk/api/model/User.java @@ -0,0 +1,37 @@ +package com.booleanuk.api.model; + + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import jakarta.persistence.*; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +import java.util.List; + +@Getter +@Setter +@AllArgsConstructor +@NoArgsConstructor +@Entity +@Table(name = "users") +public class User { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Integer id; + + private String userName; + + @OneToMany(mappedBy = "user") + @JsonIgnoreProperties(value = {"user", "userUpvotes"}) + private List posts; + + public User(String userName) { + this.userName = userName; + } + + public User(int id) { + this.id = id; + } +} diff --git a/src/main/java/com/booleanuk/api/repository/PostRepository.java b/src/main/java/com/booleanuk/api/repository/PostRepository.java new file mode 100644 index 0000000..a80e468 --- /dev/null +++ b/src/main/java/com/booleanuk/api/repository/PostRepository.java @@ -0,0 +1,7 @@ +package com.booleanuk.api.repository; + +import com.booleanuk.api.model.Post; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface PostRepository extends JpaRepository { +} diff --git a/src/main/java/com/booleanuk/api/repository/UserRepository.java b/src/main/java/com/booleanuk/api/repository/UserRepository.java new file mode 100644 index 0000000..74858a5 --- /dev/null +++ b/src/main/java/com/booleanuk/api/repository/UserRepository.java @@ -0,0 +1,7 @@ +package com.booleanuk.api.repository; + +import com.booleanuk.api.model.User; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface UserRepository extends JpaRepository { +} diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml deleted file mode 100644 index 02c2591..0000000 --- a/src/main/resources/application.yml +++ /dev/null @@ -1,7 +0,0 @@ -server: - port: 4000 - error: - include-message: always - include-binding-errors: always - include-stacktrace: never - include-exception: false diff --git a/src/test/java/com/booleanuk/api/.gitkeep b/src/test/java/com/booleanuk/api/.gitkeep deleted file mode 100644 index e69de29..0000000