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
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -35,3 +35,5 @@ out/

### VS Code ###
.vscode/

application.yml
21 changes: 21 additions & 0 deletions Docker-compose/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
services:
app:
image: 'wilmers-social-box: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
26 changes: 22 additions & 4 deletions build.gradle
Original file line number Diff line number Diff line change
@@ -1,12 +1,17 @@
plugins {
id 'java'
id 'org.springframework.boot' version '3.1.4'
id 'io.spring.dependency-management' version '1.1.3'
id 'org.springframework.boot' version '3.4.2'
id 'io.spring.dependency-management' version '1.1.7'
}

group = 'com.booleanuk'
version = '0.0.1'
sourceCompatibility = '17'
version = '0.0.2'

java {
toolchain {
languageVersion = JavaLanguageVersion.of(21)
}
}

configurations {
compileOnly {
Expand All @@ -20,12 +25,25 @@ repositories {

dependencies {
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'org.springframework.boot:spring-boot-starter-security'
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'io.jsonwebtoken:jjwt-api:0.12.6'
implementation 'io.jsonwebtoken:jjwt-impl:0.12.6'
runtimeOnly 'io.jsonwebtoken:jjwt-jackson:0.12.6'

compileOnly 'org.projectlombok:lombok'
developmentOnly 'org.springframework.boot:spring-boot-devtools'
runtimeOnly 'org.postgresql:postgresql'
implementation 'org.postgresql:postgresql:42.6.0'
annotationProcessor 'org.projectlombok:lombok'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
testImplementation 'org.springframework.security:spring-security-test'

implementation 'jakarta.validation:jakarta.validation-api:3.1.0'
}

tasks.named('bootBuildImage') {
builder = 'paketobuildpacks/builder-jammy-base:latest'
}

tasks.named('test') {
Expand Down
Empty file.
30 changes: 30 additions & 0 deletions src/main/java/com/booleanuk/api/Main.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package com.booleanuk.api;

import com.booleanuk.api.models.ERole;
import com.booleanuk.api.models.Role;
import com.booleanuk.api.repositories.RoleRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class Main implements CommandLineRunner {
@Autowired
private RoleRepository roleRepository;

public static void main(String[] args) {
SpringApplication.run(Main.class, args);
}

@Override
public void run(String... args) {
if (!this.roleRepository.existsByName(ERole.ROLE_USER)) {
this.roleRepository.save(new Role(ERole.ROLE_USER));
}
if (!this.roleRepository.existsByName(ERole.ROLE_ADMIN)) {
this.roleRepository.save(new Role(ERole.ROLE_ADMIN));
}
}

}
97 changes: 97 additions & 0 deletions src/main/java/com/booleanuk/api/controllers/AuthController.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
package com.booleanuk.api.controllers;

import com.booleanuk.api.models.ERole;
import com.booleanuk.api.models.Role;
import com.booleanuk.api.models.User;
import com.booleanuk.api.payload.request.LoginRequest;
import com.booleanuk.api.payload.request.SignupRequest;
import com.booleanuk.api.payload.response.JwtResponse;
import com.booleanuk.api.payload.response.MessageResponse;
import com.booleanuk.api.repositories.RoleRepository;
import com.booleanuk.api.repositories.UserRepository;
import com.booleanuk.api.security.jwt.JwtUtils;
import com.booleanuk.api.security.services.UserDetailsImpl;
import jakarta.validation.Valid;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.web.bind.annotation.*;

import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

@CrossOrigin(origins = "*", maxAge = 3600)
@RestController
@RequestMapping("auth")
public class AuthController {
@Autowired
AuthenticationManager authenticationManager;

@Autowired
UserRepository userRepository;

@Autowired
RoleRepository roleRepository;

@Autowired
PasswordEncoder encoder;

@Autowired
JwtUtils jwtUtils;

@PostMapping("/signin")
public ResponseEntity<?> authenticateUser(@Valid @RequestBody LoginRequest loginRequest) {
// If using a salt for password use it here
Authentication authentication = authenticationManager
.authenticate(new UsernamePasswordAuthenticationToken(loginRequest.getUsername(), loginRequest.getPassword()));
SecurityContextHolder.getContext().setAuthentication(authentication);
String jwt = jwtUtils.generateJwtToken(authentication);

UserDetailsImpl userDetails = (UserDetailsImpl) authentication.getPrincipal();
List<String> roles = userDetails.getAuthorities().stream().map((item) -> item.getAuthority())
.collect(Collectors.toList());
return ResponseEntity
.ok(new JwtResponse(jwt, userDetails.getId(), userDetails.getUsername(), userDetails.getEmail(), roles));
}

@PostMapping("/signup")
public ResponseEntity<?> registerUser(@Valid @RequestBody SignupRequest signupRequest) {
if (userRepository.existsByUsername(signupRequest.getUsername())) {
return ResponseEntity.badRequest().body(new MessageResponse("Error: Username is already taken"));
}
if (userRepository.existsByEmail(signupRequest.getEmail())) {
return ResponseEntity.badRequest().body(new MessageResponse("Error: Email is already in use!"));
}
// Create a new user add salt here if using one
User user = new User(signupRequest.getUsername(), signupRequest.getEmail(), encoder.encode(signupRequest.getPassword()));
Set<String> strRoles = signupRequest.getRole();
Set<Role> roles = new HashSet<>();

if (strRoles == null) {
Role userRole = roleRepository.findByName(ERole.ROLE_USER).orElseThrow(() -> new RuntimeException("Error: Role is not found"));
roles.add(userRole);
} else {
strRoles.forEach((role) -> {
switch (role) {
case "admin":
Role adminRole = roleRepository.findByName(ERole.ROLE_ADMIN).orElseThrow(() -> new RuntimeException("Error: Role is not found"));
roles.add(adminRole);
break;
default:
Role userRole = roleRepository.findByName(ERole.ROLE_USER).orElseThrow(() -> new RuntimeException("Error: Role is not found"));
roles.add(userRole);
break;
}
});
}
user.setRoles(roles);
userRepository.save(user);
return ResponseEntity.ok((new MessageResponse("User registered successfully")));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package com.booleanuk.api.controllers;

import com.booleanuk.api.models.Follower;
import com.booleanuk.api.models.User;
import com.booleanuk.api.payload.response.*;
import com.booleanuk.api.repositories.FollowerRepository;
import com.booleanuk.api.repositories.UserRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("user")
public class FollowerController {

@Autowired
private FollowerRepository followerRepository;
@Autowired
private UserRepository userRepository;



@DeleteMapping("/unfollow/{id}")
public ResponseEntity<Response<?>> unfollowUser(@PathVariable int id) {
Follower followerToDelete = this.followerRepository.findById(id).orElse(null);
if (followerToDelete == null) {
ErrorResponse error = new ErrorResponse();
error.set("not found");
return new ResponseEntity<>(error, HttpStatus.NOT_FOUND);
}
this.followerRepository.delete(followerToDelete);
FollowerResponse followerResponse = new FollowerResponse();
followerResponse.set(followerToDelete);
return ResponseEntity.ok(followerResponse);
}

@PostMapping("/follow")
public ResponseEntity<Response<?>> followUser(@RequestBody Follower follow) {
FollowerResponse followerResponse = new FollowerResponse();
User follower = this.userRepository.findById(follow.getFollower().getId()).orElse(null);
User following = this.userRepository.findById(follow.getFollowing().getId()).orElse(null);
try {
follow.setFollower(follower);
follow.setFollowing(following);
followerResponse.set(this.followerRepository.save(follow));
} catch (Exception e) {
ErrorResponse error = new ErrorResponse();
error.set("Bad request");
return new ResponseEntity<>(error, HttpStatus.BAD_REQUEST);
}
return new ResponseEntity<>(followerResponse, HttpStatus.CREATED);
}

@GetMapping("/followers/{id}")
public ResponseEntity<FollowerListRespons> listAllFollowers(@PathVariable int id) {
FollowerListRespons followerListRespons = new FollowerListRespons();
followerListRespons.set(this.followerRepository.findAllByFollowingId(id));
return ResponseEntity.ok(followerListRespons);
}


}
85 changes: 85 additions & 0 deletions src/main/java/com/booleanuk/api/controllers/PostController.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
package com.booleanuk.api.controllers;

import com.booleanuk.api.models.Post;
import com.booleanuk.api.models.User;
import com.booleanuk.api.payload.response.*;
import com.booleanuk.api.repositories.PostRepository;
import com.booleanuk.api.repositories.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.time.LocalDateTime;

@RestController
@RequestMapping("user")
public class PostController {

@Autowired
private PostRepository postRepository;
@Autowired
private UserRepository userRepository;



@PostMapping("/post")
public ResponseEntity<Response<?>> createPost(@RequestBody Post post) {
PostResponse postResponse = new PostResponse();
User user = this.userRepository.findById(post.getUser().getId()).orElse(null);

try {
post.setUser(user);
postResponse.set(this.postRepository.save(post));
} catch (Exception e) {
ErrorResponse error = new ErrorResponse();
error.set("Bad request");
return new ResponseEntity<>(error, HttpStatus.BAD_REQUEST);
}
return new ResponseEntity<>(postResponse, HttpStatus.CREATED);
}

@DeleteMapping("/deletepost/{id}")
public ResponseEntity<Response<?>> deletePost(@PathVariable int id) {
Post postToDelete = this.postRepository.findById(id).orElse(null);
if (postToDelete == null) {
ErrorResponse error = new ErrorResponse();
error.set("not found");
return new ResponseEntity<>(error, HttpStatus.NOT_FOUND);
}
this.postRepository.delete(postToDelete);
PostResponse postResponse = new PostResponse();
postResponse.set(postToDelete);
return ResponseEntity.ok(postResponse);
}

@GetMapping("/posts/{id}")
public ResponseEntity<PostListResponse> listAllPostsByUser(@PathVariable int id) {
PostListResponse postListResponse = new PostListResponse();
postListResponse.set(this.postRepository.findAllByUserId(id));
return ResponseEntity.ok(postListResponse);
}

@PutMapping("/updatepost/{id}")
public ResponseEntity<Response<?>> updatePost(@PathVariable int id, @RequestBody Post post) {
Post postToUpdate = this.postRepository.findById(id).orElse(null);
if (postToUpdate == null) {
ErrorResponse error = new ErrorResponse();
error.set("not found");
return new ResponseEntity<>(error, HttpStatus.NOT_FOUND);
}
postToUpdate.setContent(post.getContent());
postToUpdate.setUpdatedAt(LocalDateTime.now());

try {
postToUpdate = this.postRepository.save(postToUpdate);
} catch (Exception e) {
ErrorResponse error = new ErrorResponse();
error.set("Bad request");
return new ResponseEntity<>(error, HttpStatus.BAD_REQUEST);
}
PostResponse postResponse = new PostResponse();
postResponse.set(postToUpdate);
return new ResponseEntity<>(postResponse, HttpStatus.CREATED);
}
}
Loading