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
3 changes: 2 additions & 1 deletion backend/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,7 @@
<artifactId>spotless-maven-plugin</artifactId>
<version>3.5.1</version>
<configuration>
<lineEndings>UNIX</lineEndings>
<java>
<googleJavaFormat>
<version>1.28.0</version>
Expand All @@ -175,4 +176,4 @@
</plugin>
</plugins>
</build>
</project>
</project>
14 changes: 2 additions & 12 deletions backend/src/main/java/vaultWeb/controllers/ChatController.java
Original file line number Diff line number Diff line change
Expand Up @@ -37,12 +37,7 @@ public class ChatController {
public void sendMessage(@Valid @Payload ChatMessageDto messageDto) {
ChatMessage savedMessage = chatService.saveMessage(messageDto);

ChatMessageDto responseDto = new ChatMessageDto();
responseDto.setE2eePayload(savedMessage.getE2eePayload());
responseDto.setTimestamp(savedMessage.getTimestamp().toString());
responseDto.setSenderUsername(savedMessage.getSender().getUsername());
responseDto.setGroupId(savedMessage.getGroup().getId());
responseDto.setSenderDeviceId(savedMessage.getSenderDeviceId());
ChatMessageDto responseDto = chatService.toDto(savedMessage);

messagingTemplate.convertAndSend(
"/topic/group/" + savedMessage.getGroup().getId(), responseDto);
Expand All @@ -58,12 +53,7 @@ public void sendMessage(@Valid @Payload ChatMessageDto messageDto) {
public void sendPrivateMessage(@Valid @Payload ChatMessageDto messageDto) {
ChatMessage savedMessage = chatService.saveMessage(messageDto);

ChatMessageDto responseDto = new ChatMessageDto();
responseDto.setE2eePayload(savedMessage.getE2eePayload());
responseDto.setTimestamp(savedMessage.getTimestamp().toString());
responseDto.setSenderUsername(savedMessage.getSender().getUsername());
responseDto.setPrivateChatId(savedMessage.getPrivateChat().getId());
responseDto.setSenderDeviceId(savedMessage.getSenderDeviceId());
ChatMessageDto responseDto = chatService.toDto(savedMessage);

String user1 = savedMessage.getPrivateChat().getUser1().getUsername();
String user2 = savedMessage.getPrivateChat().getUser2().getUsername();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
import vaultWeb.exceptions.notfound.GroupNotFoundException;
import vaultWeb.models.Group;
import vaultWeb.models.Poll;
import vaultWeb.models.PollContext;
import vaultWeb.models.User;
import vaultWeb.services.GroupService;
import vaultWeb.services.PollService;
Expand All @@ -25,7 +26,7 @@
@RestController
@RequestMapping("/groups/{groupId}/polls")
@RequiredArgsConstructor
public class PollController {
public class GroupChatPollController {

private final GroupService groupService;
private final PollService pollService;
Expand Down Expand Up @@ -59,7 +60,9 @@ public ResponseEntity<PollResponseDto> createPoll(
.getGroupById(groupId)
.orElseThrow(
() -> new GroupNotFoundException("Group with id " + groupId + " not found"));
Poll poll = pollService.createPoll(group, currentUser, pollDto);

PollContext pollContext = new PollContext(group, null);
Poll poll = pollService.createPoll(pollContext, currentUser, pollDto);

// Convert to response DTO and return
PollResponseDto responseDto = pollService.toResponseDto(poll);
Expand Down Expand Up @@ -96,7 +99,6 @@ public ResponseEntity<List<PollResponseDto>> getPolls(@PathVariable Long groupId
/**
* Casts a vote for a specific poll option.
*
* @param groupId the ID of the group
* @param pollId the ID of the poll
* @param optionId the ID of the option being voted for
* @return HTTP 204 No Content
Expand All @@ -107,25 +109,22 @@ public ResponseEntity<List<PollResponseDto>> getPolls(@PathVariable Long groupId
description =
"""
This endpoint casts a vote for some poll conducted within a specific group.
- 'groupId': the ID of the group
- 'pollId': the ID of the poll
- 'optionId': the ID of the option being voted for
""")
@ApiResponse(responseCode = "204", description = "Vote cast successfully.")
@ApiResponse(
responseCode = "401",
description = "Unauthorized request. You must provide an authentication token.")
public ResponseEntity<Void> vote(
@PathVariable Long groupId, @PathVariable Long pollId, @PathVariable Long optionId) {
public ResponseEntity<Void> vote(@PathVariable Long pollId, @PathVariable Long optionId) {
User currentUser = authService.getCurrentUser();
pollService.vote(groupId, pollId, optionId, currentUser);
pollService.vote(pollId, optionId, currentUser);
return ResponseEntity.status(HttpStatus.NO_CONTENT).build();
}

/**
* Updates an existing poll.
*
* @param groupId the ID of the group
* @param pollId the ID of the poll to update
* @param pollDto the new poll data
* @return updated PollResponseDto
Expand All @@ -136,26 +135,22 @@ public ResponseEntity<Void> vote(
description =
"""
This endpoint updates the state of a poll within a specific group.
- 'groupId': the ID of the group the poll belongs to
- 'pollId': the ID of the poll to update
""")
@ApiResponse(responseCode = "200", description = "Poll data updated successfully.")
@ApiResponse(
responseCode = "401",
description = "Unauthorized request. You must provide an authentication token.")
public ResponseEntity<PollResponseDto> updatePoll(
@PathVariable Long groupId,
@PathVariable Long pollId,
@RequestBody @Valid PollRequestDto pollDto) {
@PathVariable Long pollId, @RequestBody @Valid PollRequestDto pollDto) {
User currentUser = authService.getCurrentUser();
Poll updatedPoll = pollService.updatePoll(groupId, pollId, currentUser, pollDto);
Poll updatedPoll = pollService.updatePoll(pollId, currentUser, pollDto);
return ResponseEntity.ok(pollService.toResponseDto(updatedPoll));
}

/**
* Deletes a poll from a group.
*
* @param groupId the ID of the group
* @param pollId the ID of the poll to delete
* @return HTTP 204 No Content
*/
Expand All @@ -165,16 +160,15 @@ public ResponseEntity<PollResponseDto> updatePoll(
description =
"""
This endpoint deletes a poll conducted within a specific group.
- 'groupId': the ID of the group
- 'pollId': the ID of the poll
""")
@ApiResponse(responseCode = "204", description = "Poll deleted successfully")
@ApiResponse(
responseCode = "401",
description = "Unauthorized request. You must provide an authentication token.")
public ResponseEntity<Void> deletePoll(@PathVariable Long groupId, @PathVariable Long pollId) {
public ResponseEntity<Void> deletePoll(@PathVariable Long pollId) {
User currentUser = authService.getCurrentUser();
pollService.deletePoll(groupId, pollId, currentUser);
pollService.deletePoll(pollId, currentUser);
return ResponseEntity.noContent().build();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import vaultWeb.repositories.ChatMessageRepository;
import vaultWeb.repositories.DeviceRepository;
import vaultWeb.repositories.PrivateChatRepository;
import vaultWeb.services.ChatService;
import vaultWeb.services.PrivateChatService;

@RestController
Expand All @@ -38,6 +39,7 @@ public class PrivateChatController {
private final ChatMessageRepository chatMessageRepository;
private final DeviceRepository deviceRepository;
private final PrivateChatRepository privateChatRepository;
private final ChatService chatService;

@GetMapping("/between")
@Operation(
Expand Down Expand Up @@ -87,14 +89,7 @@ public List<ChatMessageDto> getPrivateChatMessages(
return messages.stream()
.map(
message -> {
ChatMessageDto dto = new ChatMessageDto();
dto.setE2eePayload(message.getE2eePayload());
dto.setTimestamp(message.getTimestamp().toString());
dto.setGroupId(null);
dto.setPrivateChatId(chat.getId());
dto.setSenderId(message.getSender().getId());
dto.setSenderUsername(message.getSender().getUsername());
dto.setSenderDeviceId(message.getSenderDeviceId());
ChatMessageDto dto = chatService.toDto(message);
return dto;
})
.toList();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
package vaultWeb.controllers;

import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import jakarta.validation.Valid;
import java.util.List;
import lombok.RequiredArgsConstructor;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import vaultWeb.dtos.PollRequestDto;
import vaultWeb.dtos.PollResponseDto;
import vaultWeb.exceptions.notfound.PrivateChatNotFoundException;
import vaultWeb.models.*;
import vaultWeb.repositories.PrivateChatRepository;
import vaultWeb.services.PollService;
import vaultWeb.services.auth.AuthService;

@RestController
@RequestMapping("/private-chats/{privateChatId}/polls")
@RequiredArgsConstructor
public class PrivateChatPollController {

private final PrivateChatRepository privateChatRepository;
private final PollService pollService;
private final AuthService authService;

/**
* Creates a new poll in the specified private chat.
*
* @param privateChatId the ID of the private chat where the poll will be created
* @param pollDto the poll data sent in the request body
* @return the created poll as a PollResponseDto
*/
@PostMapping("")
@Operation(
summary = "Creates a new poll in the specified private chat",
description =
"""
This endpoint creates a poll within a specific private chat.
- 'privatechatId': the ID of the privatechat Id where the poll will be created
- 'pollDTO': the poll data to be sent in the request body
""")
@ApiResponse(responseCode = "201", description = "Poll created successfully.")
@ApiResponse(
responseCode = "401",
description = "Unauthorized request. You must provide an authentication token.")
public ResponseEntity<PollResponseDto> createPoll(
@PathVariable Long privateChatId, @RequestBody @Valid PollRequestDto pollDto) {
User currentUser = authService.getCurrentUser();
PrivateChat privateChat =
privateChatRepository
.findById(privateChatId)
.orElseThrow(() -> new PrivateChatNotFoundException("Chat not found"));

PollContext pollContext = new PollContext(null, privateChat);
Poll poll = pollService.createPoll(pollContext, currentUser, pollDto);

// Convert to response DTO and return
PollResponseDto responseDto = pollService.toResponseDto(poll);
return ResponseEntity.status(HttpStatus.CREATED).body(responseDto);
}

/**
* Casts a vote for a specific poll option.
*
* @param pollId the ID of the poll
* @param optionId the ID of the option being voted for
* @return HTTP 204 No Content
*/
@PostMapping("/{pollId}/options/{optionId}/vote")
@Operation(
summary = "Casts a vote for a specific poll option",
description =
"""
This endpoint casts a vote for some poll conducted within a specific private chat.
- 'pollId': the ID of the poll
- 'optionId': the ID of the option being voted for
""")
@ApiResponse(responseCode = "204", description = "Vote cast successfully.")
@ApiResponse(
responseCode = "401",
description = "Unauthorized request. You must provide an authentication token.")
public ResponseEntity<Void> vote(@PathVariable Long pollId, @PathVariable Long optionId) {
User currentUser = authService.getCurrentUser();
pollService.vote(pollId, optionId, currentUser);
return ResponseEntity.status(HttpStatus.NO_CONTENT).build();
}

/**
* Updates an existing poll.
*
* @param pollId the ID of the poll to update
* @param pollDto the new poll data
* @return updated PollResponseDto
*/
@PutMapping("/{pollId}")
@Operation(
summary = "Updates an existing poll",
description =
"""
This endpoint updates the state of a poll within a specific private chat.
- 'pollId': the ID of the poll to update
""")
@ApiResponse(responseCode = "200", description = "Poll data updated successfully.")
@ApiResponse(
responseCode = "401",
description = "Unauthorized request. You must provide an authentication token.")
public ResponseEntity<PollResponseDto> updatePoll(
@PathVariable Long pollId, @RequestBody @Valid PollRequestDto pollDto) {
User currentUser = authService.getCurrentUser();
Poll updatedPoll = pollService.updatePoll(pollId, currentUser, pollDto);
return ResponseEntity.ok(pollService.toResponseDto(updatedPoll));
}

/**
* Deletes a poll from a private chat.
*
* @param pollId the ID of the poll to delete
* @return HTTP 204 No Content
*/
@DeleteMapping("/{pollId}")
@Operation(
summary = "Deletes a poll from a private chat",
description =
"""
This endpoint deletes a poll conducted within a specific private chat.
- 'pollId': the ID of the poll
""")
@ApiResponse(responseCode = "204", description = "Poll deleted successfully")
@ApiResponse(
responseCode = "401",
description = "Unauthorized request. You must provide an authentication token.")
public ResponseEntity<Void> deletePoll(@PathVariable Long pollId) {
User currentUser = authService.getCurrentUser();
pollService.deletePoll(pollId, currentUser);
return ResponseEntity.noContent().build();
}

/**
* Retrieves all polls of a given private chat.
*
* @param privateChatId the ID of the private chat
* @return list of PollResponseDto objects
*/
@GetMapping("")
@Operation(
summary = "Retrieves all polls of a given private chat",
description =
"""
This endpoint returns every poll within a specific private chat.
- 'privateChatId': the ID of the private chat to retrieve all polls from
""")
@ApiResponse(responseCode = "200", description = "Polls retrieved successfully.")
@ApiResponse(
responseCode = "401",
description = "Unauthorized request. You must provide an authentication token.")
public ResponseEntity<List<PollResponseDto>> getPolls(@PathVariable Long privateChatId) {
User currentUser = authService.getCurrentUser();
List<PollResponseDto> polls =
pollService.getPollsByPrivateChat(privateChatId, currentUser).stream()
.map(pollService::toResponseDto)
.toList();
return ResponseEntity.ok(polls);
}
}
6 changes: 5 additions & 1 deletion backend/src/main/java/vaultWeb/dtos/ChatMessageDto.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import vaultWeb.models.enums.MessageType;

@Data
@NoArgsConstructor
Expand All @@ -16,5 +17,8 @@ public class ChatMessageDto {
private Long senderId;
private String senderUsername;
@NotBlank private String senderDeviceId;
@NotBlank private String e2eePayload;

private String e2eePayload;
private MessageType messageType;
private PollResponseDto poll;
}
8 changes: 8 additions & 0 deletions backend/src/main/java/vaultWeb/models/ChatMessage.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import jakarta.persistence.*;
import java.time.Instant;
import lombok.*;
import vaultWeb.models.enums.MessageType;

@Entity
@Getter
Expand Down Expand Up @@ -35,4 +36,11 @@ public class ChatMessage {
private PrivateChat privateChat;

private Instant timestamp;

@Enumerated(EnumType.STRING)
private MessageType messageType;

@OneToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "poll_id")
private Poll poll;
}
Loading
Loading