From cf758bfe60432c6b269c3c285b3813d28180ec4c Mon Sep 17 00:00:00 2001 From: Teriuihi Date: Sat, 3 May 2025 04:37:47 +0200 Subject: [PATCH] Add endpoints and schema for history retrieval by UUID Introduced a new API endpoint to fetch all punishment history for a specified UUID. Updated existing schemas, controllers, and mappers to support this functionality. Adjusted login endpoints to improve request handling and streamlined frontend form setup for appeals. --- .../history/HistoryApiController.java | 18 +++++ .../controllers/login/LoginController.java | 7 +- .../database/litebans/UUIDHistoryMapper.java | 4 + .../src/app/forms/appeal/appeal.component.ts | 50 +++++++----- open_api/src/main/resources/api.yml | 6 +- .../src/main/resources/schemas/bans/bans.yml | 27 ++++--- .../resources/schemas/generic/parameters.yml | 9 +++ .../main/resources/schemas/login/login.yml | 80 ++++++++----------- 8 files changed, 117 insertions(+), 84 deletions(-) create mode 100644 open_api/src/main/resources/schemas/generic/parameters.yml diff --git a/backend/src/main/java/com/alttd/altitudeweb/controllers/history/HistoryApiController.java b/backend/src/main/java/com/alttd/altitudeweb/controllers/history/HistoryApiController.java index d09fec2..359e2df 100644 --- a/backend/src/main/java/com/alttd/altitudeweb/controllers/history/HistoryApiController.java +++ b/backend/src/main/java/com/alttd/altitudeweb/controllers/history/HistoryApiController.java @@ -153,6 +153,24 @@ public class HistoryApiController implements HistoryApi { return ResponseEntity.ok().body(searchResultCountCompletableFuture.join()); } + @Override + public ResponseEntity getAllHistoryForUUID(String uuid) { + PunishmentHistoryListDto punishmentHistoryList = new PunishmentHistoryListDto(); + CompletableFuture> historyRecordsCompletableFuture = new CompletableFuture<>(); + Connection.getConnection(Databases.LITE_BANS).runQuery(sqlSession -> { + log.debug("Loading all history for uuid {}", uuid); + try { + List punishments = sqlSession.getMapper(UUIDHistoryMapper.class) + .getAllHistoryForUUID(UUID.fromString(uuid)); + historyRecordsCompletableFuture.complete(punishments); + } catch (Exception e) { + log.error("Failed to load all history for uuid {}", uuid, e); + historyRecordsCompletableFuture.completeExceptionally(e); + } + }); + return mapPunishmentHistory(punishmentHistoryList, historyRecordsCompletableFuture); + } + @Override public ResponseEntity getHistoryById(String type, Integer id) { HistoryType historyTypeEnum = HistoryType.getHistoryType(type); diff --git a/backend/src/main/java/com/alttd/altitudeweb/controllers/login/LoginController.java b/backend/src/main/java/com/alttd/altitudeweb/controllers/login/LoginController.java index 4abbe96..e3fcee8 100644 --- a/backend/src/main/java/com/alttd/altitudeweb/controllers/login/LoginController.java +++ b/backend/src/main/java/com/alttd/altitudeweb/controllers/login/LoginController.java @@ -2,9 +2,6 @@ package com.alttd.altitudeweb.controllers.login; import com.alttd.altitudeweb.api.LoginApi; import com.alttd.altitudeweb.controllers.limits.RateLimit; -import com.alttd.altitudeweb.model.AddLoginDto; -import com.alttd.altitudeweb.model.LoginDataDto; -import com.alttd.altitudeweb.model.LoginResultDto; import org.springframework.http.HttpStatusCode; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.RestController; @@ -17,13 +14,13 @@ public class LoginController implements LoginApi { @RateLimit(limit = 100, timeValue = 1, timeUnit = TimeUnit.MINUTES, key = "addLogin") @Override - public ResponseEntity addLogin(AddLoginDto addLoginDto) { + public ResponseEntity requestLogin(String uuid) throws Exception { throw new ResponseStatusException(HttpStatusCode.valueOf(501), "Adding login is not yet supported"); } @RateLimit(limit = 5, timeValue = 1, timeUnit = TimeUnit.MINUTES, key = "login") @Override - public ResponseEntity login(LoginDataDto loginDataDto) { + public ResponseEntity login(String code) { throw new ResponseStatusException(HttpStatusCode.valueOf(501), "Logging in is not yet supported"); } } diff --git a/database/src/main/java/com/alttd/altitudeweb/database/litebans/UUIDHistoryMapper.java b/database/src/main/java/com/alttd/altitudeweb/database/litebans/UUIDHistoryMapper.java index 80e8a16..32cc327 100644 --- a/database/src/main/java/com/alttd/altitudeweb/database/litebans/UUIDHistoryMapper.java +++ b/database/src/main/java/com/alttd/altitudeweb/database/litebans/UUIDHistoryMapper.java @@ -80,6 +80,10 @@ public interface UUIDHistoryMapper { }; } + default List getAllHistoryForUUID(@NotNull UUID uuid) { + return getRecentAllHistory(uuid.toString(), "uuid", 100, 0); + } + private List getRecent(@NotNull String tableName, @NotNull UserType userType, @NotNull UUID uuid, int page) { int offset = page * PAGE_SIZE; diff --git a/frontend/src/app/forms/appeal/appeal.component.ts b/frontend/src/app/forms/appeal/appeal.component.ts index e51191f..82973d7 100644 --- a/frontend/src/app/forms/appeal/appeal.component.ts +++ b/frontend/src/app/forms/appeal/appeal.component.ts @@ -1,7 +1,7 @@ import {Component, OnInit} from '@angular/core'; import {FormsComponent} from '../forms.component'; -import {FormBuilder, FormGroup, Validators} from '@angular/forms'; -import {AppealsService} from '../../../api'; +import {FormControl, FormGroup, Validators} from '@angular/forms'; +import {AppealsService, MinecraftAppeal} from '../../../api'; @Component({ selector: 'app-appeal', @@ -13,22 +13,18 @@ import {AppealsService} from '../../../api'; }) export class AppealComponent implements OnInit { - public form: FormGroup | undefined; + public form: FormGroup; - constructor(private fb: FormBuilder, private appealApi: AppealsService) { + constructor(private appealApi: AppealsService) { + this.form = new FormGroup({ + username: new FormControl('', {nonNullable: true, validators: [Validators.required]}), + punishmentId: new FormControl('', {nonNullable: true, validators: [Validators.required]}), + email: new FormControl('', {nonNullable: true, validators: [Validators.required, Validators.email]}), + appeal: new FormControl('', {nonNullable: true, validators: [Validators.required, Validators.minLength(10)]}) + }); } ngOnInit() { - this.initForm() - } - - private initForm() { - this.form = this.fb.group({ - name: ['', [Validators.required]], - punishmentId: ['', [Validators.required]], - email: ['', [Validators.required, Validators.email]], - message: ['', [Validators.required, Validators.minLength(10)]] - }); } public onSubmit() { @@ -37,8 +33,7 @@ export class AppealComponent implements OnInit { return } if (this.form.valid) { - console.log('Form submitted:', this.form.value); - // Process form submission here + this.sendForm() } else { // Mark all fields as touched to trigger validation display Object.keys(this.form.controls).forEach(field => { @@ -52,12 +47,23 @@ export class AppealComponent implements OnInit { } } - private sendForm(validForm: FormGroup) { - // const appeal: MinecraftAppeal = { - // - // } - // this.appealApi.submitMinecraftAppeal() + private sendForm() { + const rawValue = this.form.getRawValue(); + const appeal: MinecraftAppeal = { + appeal: rawValue.appeal, + email: rawValue.email, + punishmentId: parseInt(rawValue.punishmentId), + username: rawValue.username, + uuid: ''//TODO + } + this.appealApi.submitMinecraftAppeal(appeal).subscribe() } - +} + +interface Appeal { + username: FormControl; + punishmentId: FormControl; + email: FormControl; + appeal: FormControl; } diff --git a/open_api/src/main/resources/api.yml b/open_api/src/main/resources/api.yml index 6428127..cbab541 100644 --- a/open_api/src/main/resources/api.yml +++ b/open_api/src/main/resources/api.yml @@ -28,6 +28,8 @@ paths: $ref: './schemas/bans/bans.yml#/getTotalResultsForUserSearch' /history/single/{type}/{id}: $ref: './schemas/bans/bans.yml#/getHistoryById' + /history/all/{uuid}: + $ref: './schemas/bans/bans.yml#/getAllHistoryForUUID' /history/total: $ref: './schemas/bans/bans.yml#/getTotalPunishments' /appeal/update-mail: @@ -36,7 +38,7 @@ paths: $ref: './schemas/forms/appeal/appeal.yml#/MinecraftAppeal' /appeal/discord-appeal: $ref: './schemas/forms/appeal/appeal.yml#/DiscordAppeal' - /login/addUserLogin: - $ref: './schemas/login/login.yml#/AddUserLogin' + /login/requestNewUserLogin/{uuid}: + $ref: './schemas/login/login.yml#/RequestNewUserLogin' /login/userLogin: $ref: './schemas/login/login.yml#/UserLogin' diff --git a/open_api/src/main/resources/schemas/bans/bans.yml b/open_api/src/main/resources/schemas/bans/bans.yml index 4215805..0d7309a 100644 --- a/open_api/src/main/resources/schemas/bans/bans.yml +++ b/open_api/src/main/resources/schemas/bans/bans.yml @@ -89,7 +89,7 @@ getHistoryForUuid: parameters: - $ref: '#/components/parameters/UserType' - $ref: '#/components/parameters/HistoryType' - - $ref: '#/components/parameters/Uuid' + - $ref: '../generic/parameters.yml#/components/parameters/Uuid' - $ref: '#/components/parameters/Page' responses: '200': @@ -158,7 +158,7 @@ getTotalResultsForUuidSearch: parameters: - $ref: '#/components/parameters/UserType' - $ref: '#/components/parameters/HistoryType' - - $ref: '#/components/parameters/Uuid' + - $ref: '../generic/parameters.yml#/components/parameters/Uuid' responses: '200': description: Successful operation @@ -195,6 +195,22 @@ getHistoryById: application/json: schema: $ref: '../generic/errors.yml#/components/schemas/ApiError' +getAllHistoryForUUID: + get: + tags: + - history + summary: Gets all history for specified UUID + description: Retrieves all history for specified UUID + operationId: getAllHistoryForUUID + parameters: + - $ref: '../generic/parameters.yml#/components/parameters/Uuid' + responses: + '200': + description: Successful operation + content: + application/json: + schema: + $ref: '#/components/schemas/PunishmentHistoryList' components: parameters: HistoryType: @@ -212,13 +228,6 @@ components: schema: type: string description: The (partial) username to search for - Uuid: - name: uuid - in: path - required: true - schema: - type: string - description: The uuid of the desired user UserType: name: userType in: path diff --git a/open_api/src/main/resources/schemas/generic/parameters.yml b/open_api/src/main/resources/schemas/generic/parameters.yml new file mode 100644 index 0000000..8ca42c8 --- /dev/null +++ b/open_api/src/main/resources/schemas/generic/parameters.yml @@ -0,0 +1,9 @@ +components: + parameters: + Uuid: + name: uuid + in: path + required: true + schema: + type: string + description: The uuid of the desired user diff --git a/open_api/src/main/resources/schemas/login/login.yml b/open_api/src/main/resources/schemas/login/login.yml index 05cf30e..e6b32ed 100644 --- a/open_api/src/main/resources/schemas/login/login.yml +++ b/open_api/src/main/resources/schemas/login/login.yml @@ -1,51 +1,55 @@ UserLogin: - post: + get: tags: - login summary: Log in to the site description: Log in to the site through a code from the server operationId: login - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/LoginData' + parameters: + - $ref: '#/components/parameters/Code' responses: '200': description: Logged in content: - application/json: + application/text: schema: - $ref: '#/components/schemas/LoginResult' + type: string + description: A JWT token for this user '401': description: Login failed - Invalid credentials content: - application/json: + application/text: schema: $ref: '../generic/errors.yml#/components/schemas/ApiError' default: description: Unexpected error content: - application/json: + application/text: schema: $ref: '../generic/errors.yml#/components/schemas/ApiError' -AddUserLogin: - post: +RequestNewUserLogin: + get: tags: - login - summary: Add a login - description: Add a code, user combination that can be used to log in - operationId: addLogin - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/AddLogin' + summary: Request a login + description: Request a code, that can be used to log in + operationId: requestLogin + parameters: + - $ref: '../generic/parameters.yml#/components/parameters/Uuid' responses: '200': description: Success + content: + application/text: + schema: + type: string + description: code to log in with + '401': + description: Login failed - Invalid secret + content: + application/json: + schema: + $ref: '../generic/errors.yml#/components/schemas/ApiError' default: description: Unexpected error content: @@ -53,6 +57,14 @@ AddUserLogin: schema: $ref: '../generic/errors.yml#/components/schemas/ApiError' components: + parameters: + Code: + name: code + in: path + required: true + schema: + type: string + description: The code to log in with schemas: LoginData: type: object @@ -62,35 +74,11 @@ components: loginCode: type: string description: The code to log in - LoginResult: - type: object - required: - - uuid - - userName - - auth - properties: - uuid: - type: string - format: uuid - description: UUID of logged in user - userName: - type: string - description: Name of the logged in user - auth: - type: string - description: Token to use along side requests AddLogin: type: object required: - - loginCode - uuid properties: - auth: - type: string - description: Token to verify the sender is allowed to add logins - loginCode: - type: string - description: The code that can be logged in with uuid: type: string format: uuid