Improved user profile endpoints and validated usernames
This commit is contained in:
@@ -1,14 +1,29 @@
|
|||||||
package net.kpuig.concord.backend.controllers;
|
package net.kpuig.concord.backend.controllers;
|
||||||
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import java.net.URI;
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.http.ResponseEntity;
|
||||||
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestBody;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestParam;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
import org.springframework.web.util.UriComponentsBuilder;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
|
import io.swagger.v3.oas.annotations.media.Content;
|
||||||
|
import io.swagger.v3.oas.annotations.responses.ApiResponse;
|
||||||
|
import io.swagger.v3.oas.annotations.responses.ApiResponses;
|
||||||
|
import jakarta.validation.Valid;
|
||||||
import net.kpuig.concord.backend.datamodels.userprofile.GetAllUserProfilesResponse;
|
import net.kpuig.concord.backend.datamodels.userprofile.GetAllUserProfilesResponse;
|
||||||
import net.kpuig.concord.backend.datamodels.userprofile.GetUserProfileResponse;
|
import net.kpuig.concord.backend.datamodels.userprofile.GetUserProfileResponse;
|
||||||
|
import net.kpuig.concord.backend.datamodels.userprofile.PostUserProfileRequest;
|
||||||
|
import net.kpuig.concord.backend.datamodels.userprofile.PostUserProfileResponse;
|
||||||
import net.kpuig.concord.backend.services.UserProfileService;
|
import net.kpuig.concord.backend.services.UserProfileService;
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
import net.kpuig.concord.backend.services.exceptions.BadRequestException;
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
|
||||||
import org.springframework.web.bind.annotation.RequestParam;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -18,14 +33,61 @@ public class UserProfileController {
|
|||||||
@Autowired
|
@Autowired
|
||||||
private UserProfileService userProfileService;
|
private UserProfileService userProfileService;
|
||||||
|
|
||||||
|
@Operation(summary = "Get all user profiles", description = "Retrieves a list of all user profiles")
|
||||||
|
@ApiResponse(responseCode = "200", description = "User profiles retrieved",
|
||||||
|
content = { @Content(mediaType = "application/json") })
|
||||||
@GetMapping("/")
|
@GetMapping("/")
|
||||||
public GetAllUserProfilesResponse getAllUserProfiles() {
|
public ResponseEntity<GetAllUserProfilesResponse> getAllUserProfiles() {
|
||||||
return userProfileService.getAllUserProfiles();
|
return ResponseEntity.ok(userProfileService.getAllUserProfiles());
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping("/{id}")
|
@Operation(summary = "Get user profile by ID or username", description = "Retrieves a user profile by its ID or username")
|
||||||
public GetUserProfileResponse getMethodName(@RequestParam String id) {
|
@ApiResponses(value = {
|
||||||
return userProfileService.getUserProfile(id);
|
@ApiResponse(responseCode = "200", description = "User profile retrieved",
|
||||||
|
content = { @Content(mediaType = "application/json") }),
|
||||||
|
@ApiResponse(responseCode = "404", description = "User profile not found")
|
||||||
|
})
|
||||||
|
@GetMapping("")
|
||||||
|
public ResponseEntity<GetUserProfileResponse> getUserProfileById(
|
||||||
|
@RequestParam(name = "id", required = false) Long id,
|
||||||
|
@RequestParam(name = "username", required = false) String username) {
|
||||||
|
if (id == null && username == null) { // Must provide at least one of them
|
||||||
|
return ResponseEntity.badRequest().build();
|
||||||
|
} else if (id != null && username != null) { // Both have been provided
|
||||||
|
return ResponseEntity.badRequest().build();
|
||||||
|
} else if (id != null) { // ID has been provided
|
||||||
|
try {
|
||||||
|
var response = userProfileService.getUserProfileById(id);
|
||||||
|
return ResponseEntity.ok(response);
|
||||||
|
} catch (NumberFormatException e) {
|
||||||
|
return ResponseEntity.notFound().build();
|
||||||
|
}
|
||||||
|
} else { // Username has been provided
|
||||||
|
try {
|
||||||
|
var response = userProfileService.getUserProfileByUsername(username);
|
||||||
|
return ResponseEntity.ok(response);
|
||||||
|
} catch (NumberFormatException e) {
|
||||||
|
return ResponseEntity.notFound().build();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Operation(summary = "Create user profile", description = "Creates a new user profile")
|
||||||
|
@ApiResponse(responseCode = "201", description = "User profile created",
|
||||||
|
content = { @Content(mediaType = "application/json") })
|
||||||
|
@PostMapping("/")
|
||||||
|
public ResponseEntity<PostUserProfileResponse> createUserProfile(@RequestBody @Valid PostUserProfileRequest request) {
|
||||||
|
try {
|
||||||
|
var response = userProfileService.createUserProfile(request.getUsername());
|
||||||
|
URI location = UriComponentsBuilder
|
||||||
|
.fromPath("/user-profile")
|
||||||
|
.queryParam("username", response.getUsername())
|
||||||
|
.build()
|
||||||
|
.encode()
|
||||||
|
.toUri();
|
||||||
|
return ResponseEntity.created(location).body(response);
|
||||||
|
} catch (BadRequestException e) {
|
||||||
|
return ResponseEntity.badRequest().build();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,10 @@
|
|||||||
|
package net.kpuig.concord.backend.datamodels.userprofile;
|
||||||
|
|
||||||
|
import jakarta.validation.constraints.NotBlank;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class PostUserProfileRequest {
|
||||||
|
@NotBlank
|
||||||
|
private String username;
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
package net.kpuig.concord.backend.datamodels.userprofile;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class PostUserProfileResponse {
|
||||||
|
private Long id;
|
||||||
|
private String username;
|
||||||
|
}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
package net.kpuig.concord.backend.repositories;
|
package net.kpuig.concord.backend.repositories;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.Optional;
|
||||||
|
|
||||||
import org.springframework.data.jpa.repository.JpaRepository;
|
import org.springframework.data.jpa.repository.JpaRepository;
|
||||||
import org.springframework.stereotype.Repository;
|
import org.springframework.stereotype.Repository;
|
||||||
@@ -9,5 +9,5 @@ import net.kpuig.concord.backend.datamodels.userprofile.UserProfile;
|
|||||||
|
|
||||||
@Repository
|
@Repository
|
||||||
public interface UserProfileRepository extends JpaRepository<UserProfile, Long> {
|
public interface UserProfileRepository extends JpaRepository<UserProfile, Long> {
|
||||||
|
Optional<UserProfile> findByUsername(String username);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,13 +1,14 @@
|
|||||||
package net.kpuig.concord.backend.services;
|
package net.kpuig.concord.backend.services;
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
import net.kpuig.concord.backend.datamodels.userprofile.GetAllUserProfilesResponse;
|
import net.kpuig.concord.backend.datamodels.userprofile.GetAllUserProfilesResponse;
|
||||||
import net.kpuig.concord.backend.datamodels.userprofile.GetUserProfileResponse;
|
import net.kpuig.concord.backend.datamodels.userprofile.GetUserProfileResponse;
|
||||||
|
import net.kpuig.concord.backend.datamodels.userprofile.PostUserProfileResponse;
|
||||||
|
import net.kpuig.concord.backend.datamodels.userprofile.UserProfile;
|
||||||
import net.kpuig.concord.backend.repositories.UserProfileRepository;
|
import net.kpuig.concord.backend.repositories.UserProfileRepository;
|
||||||
|
import net.kpuig.concord.backend.services.exceptions.BadRequestException;
|
||||||
|
|
||||||
@Service
|
@Service
|
||||||
public class UserProfileService {
|
public class UserProfileService {
|
||||||
@@ -25,12 +26,42 @@ public class UserProfileService {
|
|||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
|
||||||
public GetUserProfileResponse getUserProfile(String id) {
|
public GetUserProfileResponse getUserProfileById(Long id) {
|
||||||
GetUserProfileResponse response = new GetUserProfileResponse();
|
GetUserProfileResponse response = new GetUserProfileResponse();
|
||||||
userProfileRepository.findById(Long.parseLong(id)).ifPresent(userProfile -> {
|
userProfileRepository.findById(id).ifPresentOrElse(userProfile -> {
|
||||||
response.setId(userProfile.getId());
|
response.setId(userProfile.getId());
|
||||||
response.setUsername(userProfile.getUsername());
|
response.setUsername(userProfile.getUsername());
|
||||||
|
}, () -> {
|
||||||
|
throw new net.kpuig.concord.backend.services.exceptions.NotFoundException("User profile not found");
|
||||||
});
|
});
|
||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public GetUserProfileResponse getUserProfileByUsername(String username) {
|
||||||
|
GetUserProfileResponse response = new GetUserProfileResponse();
|
||||||
|
userProfileRepository.findByUsername(username).ifPresentOrElse(userProfile -> {
|
||||||
|
response.setId(userProfile.getId());
|
||||||
|
response.setUsername(userProfile.getUsername());
|
||||||
|
}, () -> {
|
||||||
|
throw new net.kpuig.concord.backend.services.exceptions.NotFoundException("User profile not found");
|
||||||
|
});
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PostUserProfileResponse createUserProfile(String username) {
|
||||||
|
if (userProfileRepository.findByUsername(username).isPresent()) {
|
||||||
|
throw new BadRequestException("Username is already taken");
|
||||||
|
}
|
||||||
|
|
||||||
|
UserProfile userProfile = new UserProfile();
|
||||||
|
userProfile.setUsername(username);
|
||||||
|
userProfile = userProfileRepository.save(userProfile);
|
||||||
|
|
||||||
|
PostUserProfileResponse response = new PostUserProfileResponse();
|
||||||
|
response.setId(userProfile.getId());
|
||||||
|
response.setUsername(userProfile.getUsername());
|
||||||
|
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,7 @@
|
|||||||
|
package net.kpuig.concord.backend.services.exceptions;
|
||||||
|
|
||||||
|
public class BadRequestException extends RuntimeException {
|
||||||
|
public BadRequestException(String message) {
|
||||||
|
super(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
package net.kpuig.concord.backend.services.exceptions;
|
||||||
|
|
||||||
|
public class NotFoundException extends RuntimeException {
|
||||||
|
public NotFoundException(String message) {
|
||||||
|
super(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user