From 423d9c90439b57537df095f06bce5e7b5d30760d Mon Sep 17 00:00:00 2001 From: akastijn Date: Sun, 9 Aug 2026 15:41:34 +0200 Subject: [PATCH] Add admin chat endpoint and request schemas for private messages, party messages, and punishments --- .../altitudeweb/config/SecurityConfig.java | 2 + .../chat/ServerMessageController.java | 58 +++++++++++++++---- .../chat/to_server/data/PartyChatFromWeb.java | 16 +++++ .../to_server/data/PrivateChatFromWeb.java | 16 +++++ .../chat/to_server/data/PunishFromWeb.java | 18 ++++++ .../to_server/mappers/ChatFromWebMapper.java | 18 ++++++ .../mappers/PartyChatFromWebMapper.java | 18 ++++++ .../mappers/PrivateChatFromWebMapper.java | 18 ++++++ .../mappers/PunishFromWebMapper.java | 20 +++++++ open_api/src/main/resources/api.yml | 8 +++ .../schemas/server-message/server-message.yml | 57 +++++++++++++++++- 11 files changed, 237 insertions(+), 12 deletions(-) create mode 100644 backend/src/main/java/com/alttd/altitudeweb/services/chat/to_server/data/PartyChatFromWeb.java create mode 100644 backend/src/main/java/com/alttd/altitudeweb/services/chat/to_server/data/PrivateChatFromWeb.java create mode 100644 backend/src/main/java/com/alttd/altitudeweb/services/chat/to_server/data/PunishFromWeb.java create mode 100644 backend/src/main/java/com/alttd/altitudeweb/services/chat/to_server/mappers/ChatFromWebMapper.java create mode 100644 backend/src/main/java/com/alttd/altitudeweb/services/chat/to_server/mappers/PartyChatFromWebMapper.java create mode 100644 backend/src/main/java/com/alttd/altitudeweb/services/chat/to_server/mappers/PrivateChatFromWebMapper.java create mode 100644 backend/src/main/java/com/alttd/altitudeweb/services/chat/to_server/mappers/PunishFromWebMapper.java diff --git a/backend/src/main/java/com/alttd/altitudeweb/config/SecurityConfig.java b/backend/src/main/java/com/alttd/altitudeweb/config/SecurityConfig.java index ae66826..bd79c45 100644 --- a/backend/src/main/java/com/alttd/altitudeweb/config/SecurityConfig.java +++ b/backend/src/main/java/com/alttd/altitudeweb/config/SecurityConfig.java @@ -72,6 +72,8 @@ public class SecurityConfig { .requestMatchers("/api/history/admin/**").hasAuthority(PermissionClaimDto.HEAD_MOD.getValue()) .requestMatchers("/api/login/userLogin/**").permitAll() .requestMatchers("/api/site/chat/**").authenticated() + .requestMatchers("/api/site/chat/send-admin-chat/**").hasAnyAuthority(PermissionClaimDto.HEAD_MOD.getValue(), PermissionClaimDto.MOD.getValue()) + .requestMatchers("/api/site/chat/punish/**").hasAnyAuthority(PermissionClaimDto.HEAD_MOD.getValue(), PermissionClaimDto.MOD.getValue()) .requestMatchers("/api/chat/server/send/**").permitAll() .anyRequest().permitAll() ) diff --git a/backend/src/main/java/com/alttd/altitudeweb/controllers/chat/ServerMessageController.java b/backend/src/main/java/com/alttd/altitudeweb/controllers/chat/ServerMessageController.java index 2c278ba..5617b35 100644 --- a/backend/src/main/java/com/alttd/altitudeweb/controllers/chat/ServerMessageController.java +++ b/backend/src/main/java/com/alttd/altitudeweb/controllers/chat/ServerMessageController.java @@ -2,9 +2,19 @@ package com.alttd.altitudeweb.controllers.chat; import com.alttd.altitudeweb.api.ServerMessageApi; import com.alttd.altitudeweb.controllers.data_from_auth.AuthenticatedUuid; +import com.alttd.altitudeweb.model.PartyMessageRequestDto; +import com.alttd.altitudeweb.model.PrivateMessageRequestDto; +import com.alttd.altitudeweb.model.PunishRequestDto; import com.alttd.altitudeweb.model.ServerMessageRequestDto; import com.alttd.altitudeweb.services.chat.to_server.ServerMessageService; import com.alttd.altitudeweb.services.chat.to_server.data.ChatFromWeb; +import com.alttd.altitudeweb.services.chat.to_server.data.PartyChatFromWeb; +import com.alttd.altitudeweb.services.chat.to_server.data.PrivateChatFromWeb; +import com.alttd.altitudeweb.services.chat.to_server.data.PunishFromWeb; +import com.alttd.altitudeweb.services.chat.to_server.mappers.ChatFromWebMapper; +import com.alttd.altitudeweb.services.chat.to_server.mappers.PartyChatFromWebMapper; +import com.alttd.altitudeweb.services.chat.to_server.mappers.PrivateChatFromWebMapper; +import com.alttd.altitudeweb.services.chat.to_server.mappers.PunishFromWebMapper; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import lombok.RequiredArgsConstructor; @@ -34,21 +44,47 @@ public class ServerMessageController implements ServerMessageApi { } @Override - public ResponseEntity sendServerMessage(String server, ServerMessageRequestDto serverMessageRequestDto) { - UUID authenticatedUserUuid = authenticatedUuid.getAuthenticatedUserUuid(); + public ResponseEntity punishPlayer(String server, PunishRequestDto punishRequestDto) throws Exception { + validateUser(punishRequestDto.getExecutor()); + return send(server, "web_punish", PunishFromWebMapper.fromDto(punishRequestDto)); + } - if (!authenticatedUserUuid.equals(serverMessageRequestDto.getUuid())) { + @Override + public ResponseEntity sendAdminChat(String server, ServerMessageRequestDto serverMessageRequestDto) { + validateUser(serverMessageRequestDto.getUuid()); + return send(server, "web_admin_chat", ChatFromWebMapper.fromDto(serverMessageRequestDto)); + } + + @Override + public ResponseEntity sendPartyMessage(PartyMessageRequestDto partyMessageRequestDto) { + validateUser(partyMessageRequestDto.getFrom()); + return send("proxy", "web_party_chat", PartyChatFromWebMapper.fromDto(partyMessageRequestDto)); + } + + @Override + public ResponseEntity sendPrivateMessage(PrivateMessageRequestDto privateMessageRequestDto) { + validateUser(privateMessageRequestDto.getFrom()); + return send("proxy", "web_private_chat", PrivateChatFromWebMapper.fromDto(privateMessageRequestDto)); + } + + @Override + public ResponseEntity sendServerMessage(String server, ServerMessageRequestDto serverMessageRequestDto) { + validateUser(serverMessageRequestDto.getUuid()); + + //TODO [Stijn] [2026-08-02]: Validate the user can send a message in this server (or do that in chat) + return send(server, "web_chat", ChatFromWebMapper.fromDto(serverMessageRequestDto)); + } + + private void validateUser(UUID uuid) { + UUID authenticatedUserUuid = authenticatedUuid.getAuthenticatedUserUuid(); + if (!authenticatedUserUuid.equals(uuid)) { throw new ResponseStatusException(HttpStatus.FORBIDDEN, "Cannot send message as another user"); } + } - ChatFromWeb chatFromWeb = ChatFromWeb.builder() - .sender(serverMessageRequestDto.getUuid()) - .message(serverMessageRequestDto.getMessage()) - .build(); - - String json = toJson(chatFromWeb); - //TODO [Stijn] [2026-08-02]: Validate the user can send a message in this server (or do that in chat) - if (serverMessageService.sendMessage(server, "web_chat", json)) { + private ResponseEntity send(String server, String channel, Object data) { + String json = toJson(data); + if (serverMessageService.sendMessage(server, channel, json)) { return new ResponseEntity<>(HttpStatus.ACCEPTED); } else { return new ResponseEntity<>(HttpStatus.NOT_FOUND); diff --git a/backend/src/main/java/com/alttd/altitudeweb/services/chat/to_server/data/PartyChatFromWeb.java b/backend/src/main/java/com/alttd/altitudeweb/services/chat/to_server/data/PartyChatFromWeb.java new file mode 100644 index 0000000..bddf688 --- /dev/null +++ b/backend/src/main/java/com/alttd/altitudeweb/services/chat/to_server/data/PartyChatFromWeb.java @@ -0,0 +1,16 @@ +package com.alttd.altitudeweb.services.chat.to_server.data; + +import lombok.Builder; +import lombok.Getter; + +import java.util.UUID; + +@Builder +@Getter +public class PartyChatFromWeb { + + private final UUID sender; + private final String message; + private final String partyId; + +} diff --git a/backend/src/main/java/com/alttd/altitudeweb/services/chat/to_server/data/PrivateChatFromWeb.java b/backend/src/main/java/com/alttd/altitudeweb/services/chat/to_server/data/PrivateChatFromWeb.java new file mode 100644 index 0000000..0ba3854 --- /dev/null +++ b/backend/src/main/java/com/alttd/altitudeweb/services/chat/to_server/data/PrivateChatFromWeb.java @@ -0,0 +1,16 @@ +package com.alttd.altitudeweb.services.chat.to_server.data; + +import lombok.Builder; +import lombok.Getter; + +import java.util.UUID; + +@Builder +@Getter +public class PrivateChatFromWeb { + + private final UUID sender; + private final String message; + private final UUID recipient; + +} diff --git a/backend/src/main/java/com/alttd/altitudeweb/services/chat/to_server/data/PunishFromWeb.java b/backend/src/main/java/com/alttd/altitudeweb/services/chat/to_server/data/PunishFromWeb.java new file mode 100644 index 0000000..86b8fcc --- /dev/null +++ b/backend/src/main/java/com/alttd/altitudeweb/services/chat/to_server/data/PunishFromWeb.java @@ -0,0 +1,18 @@ +package com.alttd.altitudeweb.services.chat.to_server.data; + +import lombok.Builder; +import lombok.Getter; + +import java.util.UUID; + +@Builder +@Getter +public class PunishFromWeb { + + private final UUID executor; + private final UUID target; + private final String type; + private final String reason; + private final String time; + +} diff --git a/backend/src/main/java/com/alttd/altitudeweb/services/chat/to_server/mappers/ChatFromWebMapper.java b/backend/src/main/java/com/alttd/altitudeweb/services/chat/to_server/mappers/ChatFromWebMapper.java new file mode 100644 index 0000000..3b6a4e2 --- /dev/null +++ b/backend/src/main/java/com/alttd/altitudeweb/services/chat/to_server/mappers/ChatFromWebMapper.java @@ -0,0 +1,18 @@ +package com.alttd.altitudeweb.services.chat.to_server.mappers; + +import com.alttd.altitudeweb.model.ServerMessageRequestDto; +import com.alttd.altitudeweb.services.chat.to_server.data.ChatFromWeb; +import lombok.experimental.UtilityClass; + +@UtilityClass +public class ChatFromWebMapper { + + public static ChatFromWeb fromDto(ServerMessageRequestDto dto) { + return ChatFromWeb.builder() + .sender(dto.getUuid()) + .message(dto.getMessage()) + .build(); + } + + +} diff --git a/backend/src/main/java/com/alttd/altitudeweb/services/chat/to_server/mappers/PartyChatFromWebMapper.java b/backend/src/main/java/com/alttd/altitudeweb/services/chat/to_server/mappers/PartyChatFromWebMapper.java new file mode 100644 index 0000000..4f56c62 --- /dev/null +++ b/backend/src/main/java/com/alttd/altitudeweb/services/chat/to_server/mappers/PartyChatFromWebMapper.java @@ -0,0 +1,18 @@ +package com.alttd.altitudeweb.services.chat.to_server.mappers; + +import com.alttd.altitudeweb.model.PartyMessageRequestDto; +import com.alttd.altitudeweb.services.chat.to_server.data.PartyChatFromWeb; +import lombok.experimental.UtilityClass; + +@UtilityClass +public class PartyChatFromWebMapper { + + public static PartyChatFromWeb fromDto(PartyMessageRequestDto dto) { + return PartyChatFromWeb.builder() + .sender(dto.getFrom()) + .message(dto.getMessage()) + .partyId(dto.getPartyId()) + .build(); + } + +} diff --git a/backend/src/main/java/com/alttd/altitudeweb/services/chat/to_server/mappers/PrivateChatFromWebMapper.java b/backend/src/main/java/com/alttd/altitudeweb/services/chat/to_server/mappers/PrivateChatFromWebMapper.java new file mode 100644 index 0000000..1f5a3c5 --- /dev/null +++ b/backend/src/main/java/com/alttd/altitudeweb/services/chat/to_server/mappers/PrivateChatFromWebMapper.java @@ -0,0 +1,18 @@ +package com.alttd.altitudeweb.services.chat.to_server.mappers; + +import com.alttd.altitudeweb.model.PrivateMessageRequestDto; +import com.alttd.altitudeweb.services.chat.to_server.data.PrivateChatFromWeb; +import lombok.experimental.UtilityClass; + +@UtilityClass +public class PrivateChatFromWebMapper { + + public static PrivateChatFromWeb fromDto(PrivateMessageRequestDto dto) { + return PrivateChatFromWeb.builder() + .sender(dto.getFrom()) + .message(dto.getMessage()) + .recipient(dto.getTo()) + .build(); + } + +} diff --git a/backend/src/main/java/com/alttd/altitudeweb/services/chat/to_server/mappers/PunishFromWebMapper.java b/backend/src/main/java/com/alttd/altitudeweb/services/chat/to_server/mappers/PunishFromWebMapper.java new file mode 100644 index 0000000..0e3424b --- /dev/null +++ b/backend/src/main/java/com/alttd/altitudeweb/services/chat/to_server/mappers/PunishFromWebMapper.java @@ -0,0 +1,20 @@ +package com.alttd.altitudeweb.services.chat.to_server.mappers; + +import com.alttd.altitudeweb.model.PunishRequestDto; +import com.alttd.altitudeweb.services.chat.to_server.data.PunishFromWeb; +import lombok.experimental.UtilityClass; + +@UtilityClass +public class PunishFromWebMapper { + + public static PunishFromWeb fromDto(PunishRequestDto dto) { + return PunishFromWeb.builder() + .executor(dto.getExecutor()) + .target(dto.getTarget()) + .type(dto.getType().getValue()) + .reason(dto.getReason()) + .time(dto.getTime()) + .build(); + } + +} diff --git a/open_api/src/main/resources/api.yml b/open_api/src/main/resources/api.yml index 048a3b7..b11ef7d 100644 --- a/open_api/src/main/resources/api.yml +++ b/open_api/src/main/resources/api.yml @@ -107,3 +107,11 @@ paths: $ref: './schemas/chat_info/chat_info.yml#/UserName' /api/site/chat/send-message/{server}: $ref: './schemas/server-message/server-message.yml#/sendServerMessage' + /api/site/chat/send-admin-chat/{server}: + $ref: './schemas/server-message/server-message.yml#/sendAdminChat' + /api/site/chat/send-private-message: + $ref: './schemas/server-message/server-message.yml#/sendPrivateMessage' + /api/site/chat/send-party-message: + $ref: './schemas/server-message/server-message.yml#/sendPartyMessage' + /api/site/chat/punish/{server}: + $ref: './schemas/server-message/server-message.yml#/punishPlayer' diff --git a/open_api/src/main/resources/schemas/server-message/server-message.yml b/open_api/src/main/resources/schemas/server-message/server-message.yml index 139bfc6..a89ccbf 100644 --- a/open_api/src/main/resources/schemas/server-message/server-message.yml +++ b/open_api/src/main/resources/schemas/server-message/server-message.yml @@ -22,7 +22,7 @@ sendServerMessage: sendAdminChat: post: tags: - - admin-chat + - server-message summary: Send an admin chat to a specific server operationId: sendAdminChat parameters: @@ -40,6 +40,61 @@ sendAdminChat: description: Server not found or not connected '400': description: Invalid request +sendPrivateMessage: + post: + tags: + - server-message + summary: Send a private message + operationId: sendPrivateMessage + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/PrivateMessageRequest' + responses: + '202': + description: Message accepted and sent + '400': + description: Invalid request +sendPartyMessage: + post: + tags: + - server-message + summary: Send a party message + operationId: sendPartyMessage + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/PartyMessageRequest' + responses: + '202': + description: Message accepted and sent + '400': + description: Invalid request +punishPlayer: + post: + tags: + - server-message + summary: Punish a player on a specific server + operationId: punishPlayer + parameters: + - $ref: '#/components/parameters/Server' + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/PunishRequest' + responses: + '202': + description: Punishment accepted and applied + '404': + description: Server not found or not connected + '400': + description: Invalid request components: parameters: Server: