From 426e60c716d9aae1ebd2c6f0fa7da5eb053e11bc Mon Sep 17 00:00:00 2001 From: ScarletRedMan Date: Thu, 25 Apr 2024 16:18:31 +0700 Subject: [PATCH] Implemented account management controller --- .../api/exception/ExceptionFactory.java | 1 + .../PermissionNotFoundException.java | 34 +++++++++++++ .../response/AllAccountsResponse.java | 7 +++ .../picker/controller/AccountsController.java | 51 ++++++++++++++++--- .../ExceptionHandlerController.java | 5 ++ .../picker/service/AccountService.java | 3 ++ .../service/impl/AccountServiceImpl.java | 6 +++ 7 files changed, 101 insertions(+), 6 deletions(-) create mode 100644 client-api/src/main/java/ru/dragonestia/picker/api/exception/PermissionNotFoundException.java create mode 100644 client-api/src/main/java/ru/dragonestia/picker/api/repository/response/AllAccountsResponse.java diff --git a/client-api/src/main/java/ru/dragonestia/picker/api/exception/ExceptionFactory.java b/client-api/src/main/java/ru/dragonestia/picker/api/exception/ExceptionFactory.java index b9ef5d5..1d9712a 100644 --- a/client-api/src/main/java/ru/dragonestia/picker/api/exception/ExceptionFactory.java +++ b/client-api/src/main/java/ru/dragonestia/picker/api/exception/ExceptionFactory.java @@ -26,6 +26,7 @@ public class ExceptionFactory { factory.put(RoomNotFoundException.ERROR_ID, RoomNotFoundException::new); factory.put(NotPersistedNodeException.ERROR_ID, NotPersistedNodeException::new); factory.put(AccountDoesNotExistsException.ERROR_ID, AccountDoesNotExistsException::new); + factory.put(PermissionNotFoundException.ERROR_ID, PermissionNotFoundException::new); return factory; } diff --git a/client-api/src/main/java/ru/dragonestia/picker/api/exception/PermissionNotFoundException.java b/client-api/src/main/java/ru/dragonestia/picker/api/exception/PermissionNotFoundException.java new file mode 100644 index 0000000..6087483 --- /dev/null +++ b/client-api/src/main/java/ru/dragonestia/picker/api/exception/PermissionNotFoundException.java @@ -0,0 +1,34 @@ +package ru.dragonestia.picker.api.exception; + +import ru.dragonestia.picker.api.repository.response.ErrorResponse; + +import java.util.Map; + +public final class PermissionNotFoundException extends ApiException { + + public static final String ERROR_ID = "err.permission.not_found"; + + private final String permissionId; + + public PermissionNotFoundException(String permissionId) { + this.permissionId = permissionId; + } + + public PermissionNotFoundException(ErrorResponse errorResponse) { + this(errorResponse.details().get("permissionId")); + } + + public String getPermissionId() { + return permissionId; + } + + @Override + public String getErrorId() { + return ERROR_ID; + } + + @Override + public void appendDetailsToErrorResponse(Map details) { + details.put("permissionId", permissionId); + } +} diff --git a/client-api/src/main/java/ru/dragonestia/picker/api/repository/response/AllAccountsResponse.java b/client-api/src/main/java/ru/dragonestia/picker/api/repository/response/AllAccountsResponse.java new file mode 100644 index 0000000..90a7609 --- /dev/null +++ b/client-api/src/main/java/ru/dragonestia/picker/api/repository/response/AllAccountsResponse.java @@ -0,0 +1,7 @@ +package ru.dragonestia.picker.api.repository.response; + +import ru.dragonestia.picker.api.model.account.ResponseAccount; + +import java.util.List; + +public record AllAccountsResponse(List accounts) {} diff --git a/server/src/main/java/ru/dragonestia/picker/controller/AccountsController.java b/server/src/main/java/ru/dragonestia/picker/controller/AccountsController.java index fcb507b..4ad8352 100644 --- a/server/src/main/java/ru/dragonestia/picker/controller/AccountsController.java +++ b/server/src/main/java/ru/dragonestia/picker/controller/AccountsController.java @@ -6,11 +6,15 @@ import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.core.userdetails.UsernameNotFoundException; import org.springframework.web.bind.annotation.*; +import ru.dragonestia.picker.api.exception.AccountDoesNotExistsException; +import ru.dragonestia.picker.api.exception.PermissionNotFoundException; import ru.dragonestia.picker.api.model.account.ResponseAccount; +import ru.dragonestia.picker.api.repository.response.AllAccountsResponse; import ru.dragonestia.picker.model.Account; +import ru.dragonestia.picker.model.Permission; import ru.dragonestia.picker.service.AccountService; -import java.util.List; +import java.util.HashSet; @RestController @RequestMapping("/accounts") @@ -36,22 +40,57 @@ public class AccountsController { } @GetMapping - List allAccounts() { - throw new UnsupportedOperationException("Not implemented"); + AllAccountsResponse allAccounts() { + return new AllAccountsResponse(accountService.allAccounts().stream() + .map(Account::toResponseObject) + .toList()); } @PostMapping ResponseAccount registerAccount(@RequestParam String username, @RequestParam String password, @RequestParam String permissions) { - throw new UnsupportedOperationException("Not implemented"); + var account = accountService.createNewAccount(username, password); + + var authorities = new HashSet(); + for (var permStr : permissions.split(",")) { + try { + var perm = Permission.valueOf(permStr); + authorities.add(perm); + } catch (IllegalArgumentException ex) { + throw new PermissionNotFoundException(permStr); + } + } + account.setAuthorities(authorities); + + accountService.updateState(account); + + return account.toResponseObject(); } @PutMapping("/{accountId}") ResponseEntity updatePermissions(@PathVariable String accountId, @RequestParam String permissions) { - throw new UnsupportedOperationException("Not implemented"); + var account = accountService.findAccount(accountId).orElseThrow(() -> new AccountDoesNotExistsException(accountId)); + + var authorities = new HashSet(); + for (var permStr : permissions.split(",")) { + try { + var perm = Permission.valueOf(permStr); + authorities.add(perm); + } catch (IllegalArgumentException ex) { + throw new PermissionNotFoundException(permStr); + } + } + account.setAuthorities(authorities); + + accountService.updateState(account); + + return ResponseEntity.ok().build(); } @DeleteMapping("/{accountId}") ResponseEntity removeAccount(@PathVariable String accountId) { - throw new UnsupportedOperationException("Not implemented"); + var account = accountService.findAccount(accountId).orElseThrow(() -> new AccountDoesNotExistsException(accountId)); + accountService.removeAccount(account); + + return ResponseEntity.ok().build(); } } diff --git a/server/src/main/java/ru/dragonestia/picker/controller/ExceptionHandlerController.java b/server/src/main/java/ru/dragonestia/picker/controller/ExceptionHandlerController.java index 6a273ee..51f6f74 100644 --- a/server/src/main/java/ru/dragonestia/picker/controller/ExceptionHandlerController.java +++ b/server/src/main/java/ru/dragonestia/picker/controller/ExceptionHandlerController.java @@ -66,6 +66,11 @@ public class ExceptionHandlerController { return create(404, ex); } + @ExceptionHandler({PermissionNotFoundException.class}) + ResponseEntity permissionNotFound(PermissionNotFoundException ex) { + return create(400, ex); + } + private ResponseEntity create(int code, ApiException ex) { var details = new HashMap(); ex.appendDetailsToErrorResponse(details); diff --git a/server/src/main/java/ru/dragonestia/picker/service/AccountService.java b/server/src/main/java/ru/dragonestia/picker/service/AccountService.java index a77989c..1a3a516 100644 --- a/server/src/main/java/ru/dragonestia/picker/service/AccountService.java +++ b/server/src/main/java/ru/dragonestia/picker/service/AccountService.java @@ -7,12 +7,15 @@ import org.springframework.security.core.userdetails.UsernameNotFoundException; import ru.dragonestia.picker.model.Account; import java.util.Collection; +import java.util.Optional; public interface AccountService extends UserDetailsService { @PreAuthorize("hasRole('ADMIN')") @NotNull Account createNewAccount(@NotNull String username, @NotNull String password); + @NotNull Optional findAccount(@NotNull String accountId); + @PreAuthorize("hasRole('ADMIN')") @NotNull Collection allAccounts(); diff --git a/server/src/main/java/ru/dragonestia/picker/service/impl/AccountServiceImpl.java b/server/src/main/java/ru/dragonestia/picker/service/impl/AccountServiceImpl.java index 3432413..8f1bf1d 100644 --- a/server/src/main/java/ru/dragonestia/picker/service/impl/AccountServiceImpl.java +++ b/server/src/main/java/ru/dragonestia/picker/service/impl/AccountServiceImpl.java @@ -13,6 +13,7 @@ import ru.dragonestia.picker.service.AccountService; import java.util.Arrays; import java.util.Collection; import java.util.Map; +import java.util.Optional; import java.util.concurrent.ConcurrentHashMap; import java.util.stream.Collectors; @@ -38,6 +39,11 @@ public class AccountServiceImpl implements AccountService { return account; } + @Override + public @NotNull Optional findAccount(@NotNull String accountId) { + return Optional.ofNullable(accounts.getOrDefault(accountId, null)); + } + @Override public @NotNull Collection allAccounts() { return accounts.values();