diff --git a/backend/src/main/java/net/kpuig/shoebill/backend/controllers/ChannelController.java b/backend/src/main/java/net/kpuig/shoebill/backend/controllers/ChannelController.java new file mode 100644 index 0000000..8ee6cb5 --- /dev/null +++ b/backend/src/main/java/net/kpuig/shoebill/backend/controllers/ChannelController.java @@ -0,0 +1,82 @@ +package net.kpuig.shoebill.backend.controllers; + +import org.springframework.web.bind.annotation.RequestMapping; +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.responses.ApiResponse; +import io.swagger.v3.oas.annotations.responses.ApiResponses; +import net.kpuig.shoebill.backend.datamodels.channel.GetAllChannelsFromServerResponse; +import net.kpuig.shoebill.backend.datamodels.channel.GetChannelResponse; +import net.kpuig.shoebill.backend.datamodels.channel.PostChannelRequest; +import net.kpuig.shoebill.backend.datamodels.channel.PostChannelResponse; +import net.kpuig.shoebill.backend.services.ChannelService; +import net.kpuig.shoebill.backend.services.exceptions.NotFoundException; + +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.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; + + +@RestController +@RequestMapping("/api") +public class ChannelController { + @Autowired private ChannelService channelService; + + @Operation(summary = "Get all channels from a server", description = "Retrieves a list of all channels from a server by the server's ID") + @ApiResponses({ + @ApiResponse(responseCode = "200", description = "Channels retrieved"), + @ApiResponse(responseCode = "404", description = "Server not found") + }) + @GetMapping("/server/{serverId}/channel/") + public ResponseEntity getAllChannelsFromServer(@PathVariable(name = "serverId") Long serverId) { + try { + var response = channelService.getAllChannelsFromServer(serverId); + return ResponseEntity.ok(response); + } catch (NotFoundException notFoundException) { + return ResponseEntity.notFound().build(); + } + } + + @Operation(summary = "Get a channel by ID", description = "Retrieves a channel by its ID") + @ApiResponses({ + @ApiResponse(responseCode = "200", description = "Channel retrieved"), + @ApiResponse(responseCode = "404", description = "Channel not found") + }) + @GetMapping("/channel/{channelId}") + public ResponseEntity getChannelById(@PathVariable(name = "channelId") Long channelId) { + try { + var response = channelService.getChannelById(channelId); + return ResponseEntity.ok(response); + } catch (NotFoundException notFoundException) { + return ResponseEntity.notFound().build(); + } + } + + @Operation(summary = "Create a new channel", description = "Creates a new channel with the provided name, position, type, and server ID") + @ApiResponses({ + @ApiResponse(responseCode = "201", description = "Channel created"), + @ApiResponse(responseCode = "400", description = "Invalid request") + }) + @PostMapping("/server/{serverId}/channel") + public ResponseEntity createChannel( + @PathVariable(name = "serverId") Long serverId, + @RequestBody PostChannelRequest request) { + + try { + var response = channelService.createChannel(serverId, request); + return ResponseEntity + .created(UriComponentsBuilder.fromPath("/api/channel/{id}") + .buildAndExpand(response.getId()) + .toUri()) + .body(response); + } catch (RuntimeException e) { + return ResponseEntity.badRequest().build(); + } + } + +} diff --git a/backend/src/main/java/net/kpuig/shoebill/backend/controllers/ServerController.java b/backend/src/main/java/net/kpuig/shoebill/backend/controllers/ServerController.java index 7c26914..d7b3556 100644 --- a/backend/src/main/java/net/kpuig/shoebill/backend/controllers/ServerController.java +++ b/backend/src/main/java/net/kpuig/shoebill/backend/controllers/ServerController.java @@ -14,23 +14,25 @@ import net.kpuig.shoebill.backend.datamodels.server.PostServerRequest; import net.kpuig.shoebill.backend.datamodels.server.PostServerResponse; import net.kpuig.shoebill.backend.services.ServerService; import net.kpuig.shoebill.backend.services.exceptions.BadRequestException; +import net.kpuig.shoebill.backend.services.exceptions.NotFoundException; 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.PathVariable; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; @RestController -@RequestMapping("/api/server") +@RequestMapping("/api") public class ServerController { @Autowired private ServerService serverService; @Operation(summary = "Get all servers", description = "Retrieves a list of all servers") @ApiResponse(responseCode = "200", description = "Servers retrieved") - @GetMapping("/") + @GetMapping("/server") public ResponseEntity getAllServers() { return ResponseEntity.ok(serverService.getAllServers()); } @@ -40,11 +42,11 @@ public class ServerController { @ApiResponse(responseCode = "200", description = "Server retrieved"), @ApiResponse(responseCode = "404", description = "Server not found") }) - @GetMapping("") - public ResponseEntity getServerById(@RequestParam(name = "id", required = false) Long id) { + @GetMapping("/server/{id}") + public ResponseEntity getServerById(@PathVariable(name = "id") Long id) { try { return ResponseEntity.ok(serverService.getServerById(id)); - } catch (Exception e) { + } catch (NotFoundException e) { return ResponseEntity.notFound().build(); } } @@ -54,7 +56,7 @@ public class ServerController { @ApiResponse(responseCode = "201", description = "Server created"), @ApiResponse(responseCode = "400", description = "Invalid request") }) - @PostMapping("/") + @PostMapping("/server") public ResponseEntity createNewServer(@Valid @RequestBody PostServerRequest request) { try { var response = serverService.createServer(request); diff --git a/backend/src/main/java/net/kpuig/shoebill/backend/controllers/UserProfileController.java b/backend/src/main/java/net/kpuig/shoebill/backend/controllers/UserProfileController.java index 99d7880..1d9e698 100644 --- a/backend/src/main/java/net/kpuig/shoebill/backend/controllers/UserProfileController.java +++ b/backend/src/main/java/net/kpuig/shoebill/backend/controllers/UserProfileController.java @@ -5,6 +5,7 @@ import java.net.URI; 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.PathVariable; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; @@ -23,9 +24,10 @@ import net.kpuig.shoebill.backend.datamodels.userprofile.PostUserProfileRequest; import net.kpuig.shoebill.backend.datamodels.userprofile.PostUserProfileResponse; import net.kpuig.shoebill.backend.services.UserProfileService; import net.kpuig.shoebill.backend.services.exceptions.BadRequestException; +import net.kpuig.shoebill.backend.services.exceptions.NotFoundException; @RestController -@RequestMapping("/api/user-profile") +@RequestMapping("/api") public class UserProfileController { @Autowired private UserProfileService userProfileService; @@ -33,46 +35,45 @@ public class UserProfileController { @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("/user-profile") public ResponseEntity getAllUserProfiles() { return ResponseEntity.ok(userProfileService.getAllUserProfiles()); } - @Operation(summary = "Get user profile by ID or username", description = "Retrieves a user profile by its ID or username") + @Operation(summary = "Get user profile by ID", description = "Retrieves a user profile by its ID") @ApiResponses(value = { @ApiResponse(responseCode = "200", description = "User profile retrieved", content = { @Content(mediaType = "application/json") }), @ApiResponse(responseCode = "404", description = "User profile not found") }) - @GetMapping("") - public ResponseEntity 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(); - } + @GetMapping("/user-profile/{id}") + public ResponseEntity getUserProfileById(@PathVariable(name = "id") Long id) { + try { + return ResponseEntity.ok(userProfileService.getUserProfileById(id)); + } catch (NotFoundException e) { + return ResponseEntity.notFound().build(); + } + } + + @Operation(summary = "Get user profile by username", description = "Retrieves a user profile by its username") + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "User profile retrieved", + content = { @Content(mediaType = "application/json") }), + @ApiResponse(responseCode = "404", description = "User profile not found") + }) + @GetMapping("/user-profile/") + public ResponseEntity getUserProfileByUsername(@RequestParam(name = "username") String username) { + try { + return ResponseEntity.ok(userProfileService.getUserProfileByUsername(username)); + } catch (NotFoundException 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("/") + @PostMapping("/user-profile") public ResponseEntity createUserProfile(@RequestBody @Valid PostUserProfileRequest request) { try { var response = userProfileService.createUserProfile(request.getUsername()); diff --git a/backend/src/main/java/net/kpuig/shoebill/backend/datamodels/channel/GetAllChannelsFromServerResponse.java b/backend/src/main/java/net/kpuig/shoebill/backend/datamodels/channel/GetAllChannelsFromServerResponse.java new file mode 100644 index 0000000..b624523 --- /dev/null +++ b/backend/src/main/java/net/kpuig/shoebill/backend/datamodels/channel/GetAllChannelsFromServerResponse.java @@ -0,0 +1,10 @@ +package net.kpuig.shoebill.backend.datamodels.channel; + +import java.util.List; + +import lombok.Data; + +@Data +public class GetAllChannelsFromServerResponse { + private List channels; +} diff --git a/backend/src/main/java/net/kpuig/shoebill/backend/datamodels/channel/GetChannelResponse.java b/backend/src/main/java/net/kpuig/shoebill/backend/datamodels/channel/GetChannelResponse.java new file mode 100644 index 0000000..4a0e8fb --- /dev/null +++ b/backend/src/main/java/net/kpuig/shoebill/backend/datamodels/channel/GetChannelResponse.java @@ -0,0 +1,11 @@ +package net.kpuig.shoebill.backend.datamodels.channel; + +import lombok.Data; + +@Data +public class GetChannelResponse { + private Long id; + private Long position; + private ChannelType type; + private String name; +} diff --git a/backend/src/main/java/net/kpuig/shoebill/backend/datamodels/channel/PostChannelRequest.java b/backend/src/main/java/net/kpuig/shoebill/backend/datamodels/channel/PostChannelRequest.java new file mode 100644 index 0000000..eeb0387 --- /dev/null +++ b/backend/src/main/java/net/kpuig/shoebill/backend/datamodels/channel/PostChannelRequest.java @@ -0,0 +1,17 @@ +package net.kpuig.shoebill.backend.datamodels.channel; + +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +@Data +public class PostChannelRequest { + @NotNull + private Long position; + + @NotNull + private ChannelType type; + + @NotBlank + private String name; +} diff --git a/backend/src/main/java/net/kpuig/shoebill/backend/datamodels/channel/PostChannelResponse.java b/backend/src/main/java/net/kpuig/shoebill/backend/datamodels/channel/PostChannelResponse.java new file mode 100644 index 0000000..4bae950 --- /dev/null +++ b/backend/src/main/java/net/kpuig/shoebill/backend/datamodels/channel/PostChannelResponse.java @@ -0,0 +1,11 @@ +package net.kpuig.shoebill.backend.datamodels.channel; + +import lombok.Data; + +@Data +public class PostChannelResponse { + private Long id; + private Long position; + private ChannelType type; + private String name; +} diff --git a/backend/src/main/java/net/kpuig/shoebill/backend/repositories/ChannelRepository.java b/backend/src/main/java/net/kpuig/shoebill/backend/repositories/ChannelRepository.java index ae66385..cb651c7 100644 --- a/backend/src/main/java/net/kpuig/shoebill/backend/repositories/ChannelRepository.java +++ b/backend/src/main/java/net/kpuig/shoebill/backend/repositories/ChannelRepository.java @@ -1,5 +1,7 @@ package net.kpuig.shoebill.backend.repositories; +import java.util.List; + import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; @@ -7,5 +9,7 @@ import net.kpuig.shoebill.backend.datamodels.channel.Channel; @Repository public interface ChannelRepository extends JpaRepository { + + List findAllByServerId(Long serverId); } diff --git a/backend/src/main/java/net/kpuig/shoebill/backend/services/ChannelService.java b/backend/src/main/java/net/kpuig/shoebill/backend/services/ChannelService.java new file mode 100644 index 0000000..c165865 --- /dev/null +++ b/backend/src/main/java/net/kpuig/shoebill/backend/services/ChannelService.java @@ -0,0 +1,70 @@ +package net.kpuig.shoebill.backend.services; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import net.kpuig.shoebill.backend.datamodels.channel.Channel; +import net.kpuig.shoebill.backend.datamodels.channel.GetAllChannelsFromServerResponse; +import net.kpuig.shoebill.backend.datamodels.channel.GetChannelResponse; +import net.kpuig.shoebill.backend.datamodels.channel.PostChannelRequest; +import net.kpuig.shoebill.backend.datamodels.channel.PostChannelResponse; +import net.kpuig.shoebill.backend.datamodels.server.Server; +import net.kpuig.shoebill.backend.repositories.ChannelRepository; +import net.kpuig.shoebill.backend.repositories.ServerRepository; +import net.kpuig.shoebill.backend.services.exceptions.NotFoundException; + +@Service +public class ChannelService { + @Autowired private ChannelRepository channelRepository; + @Autowired private ServerRepository serverRepository; + + public GetAllChannelsFromServerResponse getAllChannelsFromServer(Long serverId) { + if (!serverRepository.existsById(serverId)) { + throw new NotFoundException("Server not found"); + } + var channels = channelRepository.findAllByServerId(serverId); + var response = new GetAllChannelsFromServerResponse(); + response.setChannels(channels.stream().map(channel -> { + var channelResponse = new GetChannelResponse(); + channelResponse.setId(channel.getId()); + channelResponse.setName(channel.getName()); + channelResponse.setPosition(channel.getPosition()); + channelResponse.setType(channel.getType()); + return channelResponse; + }).toList()); + return response; + } + + public GetChannelResponse getChannelById(Long channelId) { + var channel = channelRepository.findById(channelId).orElseThrow(); + var response = new GetChannelResponse(); + response.setId(channel.getId()); + response.setName(channel.getName()); + response.setPosition(channel.getPosition()); + response.setType(channel.getType()); + return response; + } + + public PostChannelResponse createChannel(Long serverId, PostChannelRequest request) { + Server server; + try { + server = serverRepository.findById(serverId).orElseThrow(); + } catch (Exception e) { + throw new RuntimeException("Server not found"); + } + + var channel = new Channel(); + channel.setName(request.getName()); + channel.setPosition(request.getPosition()); + channel.setType(request.getType()); + channel.setServer(server); + channel = channelRepository.save(channel); + + var response = new PostChannelResponse(); + response.setId(channel.getId()); + response.setName(channel.getName()); + response.setPosition(channel.getPosition()); + response.setType(channel.getType()); + return response; + } +} diff --git a/backend/src/main/java/net/kpuig/shoebill/backend/services/UserProfileService.java b/backend/src/main/java/net/kpuig/shoebill/backend/services/UserProfileService.java index 394dd6a..5ba11b7 100644 --- a/backend/src/main/java/net/kpuig/shoebill/backend/services/UserProfileService.java +++ b/backend/src/main/java/net/kpuig/shoebill/backend/services/UserProfileService.java @@ -9,6 +9,7 @@ import net.kpuig.shoebill.backend.datamodels.userprofile.PostUserProfileResponse import net.kpuig.shoebill.backend.datamodels.userprofile.UserProfile; import net.kpuig.shoebill.backend.repositories.UserProfileRepository; import net.kpuig.shoebill.backend.services.exceptions.BadRequestException; +import net.kpuig.shoebill.backend.services.exceptions.NotFoundException; @Service public class UserProfileService { @@ -32,7 +33,7 @@ public class UserProfileService { response.setId(userProfile.getId()); response.setUsername(userProfile.getUsername()); }, () -> { - throw new net.kpuig.shoebill.backend.services.exceptions.NotFoundException("User profile not found"); + throw new NotFoundException("User profile not found"); }); return response; } @@ -43,7 +44,7 @@ public class UserProfileService { response.setId(userProfile.getId()); response.setUsername(userProfile.getUsername()); }, () -> { - throw new net.kpuig.shoebill.backend.services.exceptions.NotFoundException("User profile not found"); + throw new NotFoundException("User profile not found"); }); return response; }