From 5f386241ff2fc3aeaf2139177a0d2db66ab883b7 Mon Sep 17 00:00:00 2001 From: Tim <47184194+imgde@users.noreply.github.com> Date: Fri, 23 May 2025 11:12:26 +0200 Subject: [PATCH] AccountController + AccountService + PasswordService (useless because missing CustomerController/Service) --- 00-backend/README.md | 6 ++ 00-backend/pom.xml | 5 ++ .../webshop/config/ControllerPathConfig.java | 5 ++ .../webshop/config/ParameterConfig.java | 1 + .../webshop/controller/AccountController.java | 74 +++++++++++++++++++ .../webshop/repository/AccountRepository.java | 2 + .../webshop/service/AccountService.java | 12 +++ .../webshop/service/PasswordService.java | 6 ++ .../service/impl/AccountServiceImpl.java | 60 +++++++++++++++ .../service/impl/PasswordServiceImpl.java | 33 +++++++++ 10 files changed, 204 insertions(+) create mode 100644 00-backend/src/main/java/de/htwsaar/webshop/controller/AccountController.java create mode 100644 00-backend/src/main/java/de/htwsaar/webshop/service/AccountService.java create mode 100644 00-backend/src/main/java/de/htwsaar/webshop/service/PasswordService.java create mode 100644 00-backend/src/main/java/de/htwsaar/webshop/service/impl/AccountServiceImpl.java create mode 100644 00-backend/src/main/java/de/htwsaar/webshop/service/impl/PasswordServiceImpl.java diff --git a/00-backend/README.md b/00-backend/README.md index 1adf6d8..bf577ba 100644 --- a/00-backend/README.md +++ b/00-backend/README.md @@ -22,6 +22,12 @@ ```shell mvn clean package ``` + +## Interesting Knowledge +- `controller/` includes all REST-Endpoints +- `model/` includes all REST-Responses +- `service/` includes all Business Logic +- `repository/entities` includes all DB-Objects # Contributors - Laura Katharina Dolibois diff --git a/00-backend/pom.xml b/00-backend/pom.xml index 1acb389..357de3e 100644 --- a/00-backend/pom.xml +++ b/00-backend/pom.xml @@ -58,6 +58,11 @@ spring-boot-starter-validation 3.4.1 + + org.springframework.security + spring-security-crypto + 6.4.4 + org.xerial sqlite-jdbc diff --git a/00-backend/src/main/java/de/htwsaar/webshop/config/ControllerPathConfig.java b/00-backend/src/main/java/de/htwsaar/webshop/config/ControllerPathConfig.java index 9fd86de..5e8b9e4 100644 --- a/00-backend/src/main/java/de/htwsaar/webshop/config/ControllerPathConfig.java +++ b/00-backend/src/main/java/de/htwsaar/webshop/config/ControllerPathConfig.java @@ -15,4 +15,9 @@ public class ControllerPathConfig { //ImageController public static final String IMAGE_BASE = "/image"; public static final String IMAGE_GET_ALL = IMAGE_BASE + "/all"; + + //AccountController + public static final String ACCOUNT_BASE = "/account"; + public static final String EMAIL_BASE = "/email"; + } \ No newline at end of file diff --git a/00-backend/src/main/java/de/htwsaar/webshop/config/ParameterConfig.java b/00-backend/src/main/java/de/htwsaar/webshop/config/ParameterConfig.java index 62836f3..ce6c394 100644 --- a/00-backend/src/main/java/de/htwsaar/webshop/config/ParameterConfig.java +++ b/00-backend/src/main/java/de/htwsaar/webshop/config/ParameterConfig.java @@ -7,5 +7,6 @@ public class ParameterConfig { public static final String PARAM_UUID = "uuid"; public static final String PARAM_ARTICLE_ID = "articleId"; public static final String PARAM_IMAGE_ID = "imageId"; + public static final String PARAM_EMAIL = "email"; } diff --git a/00-backend/src/main/java/de/htwsaar/webshop/controller/AccountController.java b/00-backend/src/main/java/de/htwsaar/webshop/controller/AccountController.java new file mode 100644 index 0000000..dce295e --- /dev/null +++ b/00-backend/src/main/java/de/htwsaar/webshop/controller/AccountController.java @@ -0,0 +1,74 @@ +package de.htwsaar.webshop.controller; + +import de.htwsaar.webshop.repository.entities.Account; +import de.htwsaar.webshop.service.AccountService; +import de.htwsaar.webshop.service.ValidatorService; +import jakarta.servlet.http.HttpServletRequest; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +import static de.htwsaar.webshop.config.ControllerPathConfig.ACCOUNT_BASE; +import static de.htwsaar.webshop.config.ControllerPathConfig.EMAIL_BASE; +import static de.htwsaar.webshop.config.ParameterConfig.PARAM_EMAIL; +import static de.htwsaar.webshop.util.LoggerUtil.logRequest; + +@RestController +@Slf4j +public class AccountController { + + private final AccountService accountService; + private final ValidatorService validatorService; + + @Autowired + public AccountController(AccountService accountService, ValidatorService validatorService) { + this.accountService = accountService; + this.validatorService = validatorService; + } + + @RequestMapping(path = EMAIL_BASE, method = RequestMethod.GET, produces = "application/json") + public ResponseEntity isEmailValid(HttpServletRequest request, + @RequestParam(PARAM_EMAIL) String email) { + logRequest(request); + return accountService.existsWithEmail(email) ? + ResponseEntity.ok(true) : + ResponseEntity.notFound().build(); + } + + @RequestMapping(path = ACCOUNT_BASE, method = RequestMethod.POST, produces = "application/json") + public ResponseEntity createAccount(HttpServletRequest request, + @RequestBody Account account) { + logRequest(request); + if (validatorService.isInvalid(account)) { + log.warn("[{}] failed Validation, sending bad request", request.getRequestURI()); + return ResponseEntity.badRequest().build(); + } + if(accountService.existsWithEmail(account.getEmail())) { + log.warn("[{}] Account cant be created, Email is already in use", request.getRequestURI()); + return ResponseEntity.unprocessableEntity().build(); + } + if(accountService.saveNew(account).getId() == null) { + return ResponseEntity.internalServerError().build(); + } + return ResponseEntity.ok().build(); + } + + @RequestMapping(path = ACCOUNT_BASE, method = RequestMethod.DELETE, produces = "application/json") + public ResponseEntity deleteAccount(HttpServletRequest request, + @RequestBody Account account) { + logRequest(request); + if (validatorService.isInvalid(account)) { + log.warn("[{}] failed Validation, sending bad request", request.getRequestURI()); + return ResponseEntity.badRequest().build(); + } + if(accountService.existsWithEmail(account.getEmail())) { + return ResponseEntity.badRequest().build(); + } + if(!accountService.deleteIfExists(account)) { + return ResponseEntity.badRequest().build(); + } + return ResponseEntity.ok().build(); + } + +} diff --git a/00-backend/src/main/java/de/htwsaar/webshop/repository/AccountRepository.java b/00-backend/src/main/java/de/htwsaar/webshop/repository/AccountRepository.java index 65109d4..8dedd67 100644 --- a/00-backend/src/main/java/de/htwsaar/webshop/repository/AccountRepository.java +++ b/00-backend/src/main/java/de/htwsaar/webshop/repository/AccountRepository.java @@ -6,5 +6,7 @@ import org.springframework.stereotype.Repository; @Repository public interface AccountRepository extends JpaRepository { + Account getAccountByEmail(String email); + boolean existsAccountByEmail(String email); } diff --git a/00-backend/src/main/java/de/htwsaar/webshop/service/AccountService.java b/00-backend/src/main/java/de/htwsaar/webshop/service/AccountService.java new file mode 100644 index 0000000..5e4b700 --- /dev/null +++ b/00-backend/src/main/java/de/htwsaar/webshop/service/AccountService.java @@ -0,0 +1,12 @@ +package de.htwsaar.webshop.service; + +import de.htwsaar.webshop.repository.entities.Account; + +public interface AccountService { + Account saveNew(Account account); + Account save(Account account); + boolean deleteIfExists(Account account); + Account getAccountByEmail(String email); + boolean isValidLogin(String email, String password); + boolean existsWithEmail(String email); +} \ No newline at end of file diff --git a/00-backend/src/main/java/de/htwsaar/webshop/service/PasswordService.java b/00-backend/src/main/java/de/htwsaar/webshop/service/PasswordService.java new file mode 100644 index 0000000..5dbc1e0 --- /dev/null +++ b/00-backend/src/main/java/de/htwsaar/webshop/service/PasswordService.java @@ -0,0 +1,6 @@ +package de.htwsaar.webshop.service; + +public interface PasswordService { + String hashPassword(String password); + boolean verifyPassword(String password, String hashedPassword); +} \ No newline at end of file diff --git a/00-backend/src/main/java/de/htwsaar/webshop/service/impl/AccountServiceImpl.java b/00-backend/src/main/java/de/htwsaar/webshop/service/impl/AccountServiceImpl.java new file mode 100644 index 0000000..9ab6e97 --- /dev/null +++ b/00-backend/src/main/java/de/htwsaar/webshop/service/impl/AccountServiceImpl.java @@ -0,0 +1,60 @@ +package de.htwsaar.webshop.service.impl; + +import de.htwsaar.webshop.repository.AccountRepository; +import de.htwsaar.webshop.repository.entities.Account; +import de.htwsaar.webshop.service.AccountService; +import de.htwsaar.webshop.service.PasswordService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +@Service +public class AccountServiceImpl implements AccountService { + private final AccountRepository accountRepository; + private final PasswordService passwordService; + + @Autowired + public AccountServiceImpl(AccountRepository accountRepository, PasswordService passwordService) { + this.accountRepository = accountRepository; + this.passwordService = passwordService; + } + + @Override + public Account save(Account account) { + return accountRepository.save(account); + } + + @Override + public Account saveNew(Account account) { + account.setPassword(passwordService.hashPassword(account.getPassword())); + return this.save(account); + } + + @Override + public boolean deleteIfExists(Account account) { + Account tbd = accountRepository.getAccountByEmail(account.getEmail()); + if(tbd == null) { + return false; + } + accountRepository.delete(tbd); + return true; + } + + @Override + public Account getAccountByEmail(String email) { + return accountRepository.getAccountByEmail(email); + } + + @Override + public boolean isValidLogin(String email, String password) { + Account acc = accountRepository.getAccountByEmail(email); + if(acc == null) { + return false; + } + return passwordService.verifyPassword(password, acc.getPassword()); + } + + @Override + public boolean existsWithEmail(String email) { + return accountRepository.existsAccountByEmail(email); + } +} diff --git a/00-backend/src/main/java/de/htwsaar/webshop/service/impl/PasswordServiceImpl.java b/00-backend/src/main/java/de/htwsaar/webshop/service/impl/PasswordServiceImpl.java new file mode 100644 index 0000000..70e9de9 --- /dev/null +++ b/00-backend/src/main/java/de/htwsaar/webshop/service/impl/PasswordServiceImpl.java @@ -0,0 +1,33 @@ +package de.htwsaar.webshop.service.impl; + +import de.htwsaar.webshop.service.PasswordService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.security.crypto.bcrypt.BCrypt; +import org.springframework.stereotype.Service; + + +/** + * Implementation of {@link PasswordService} responsible for creating the salt string. + *

+ * This service generates the salt. + *

+ */ +@Service +@Slf4j +public class PasswordServiceImpl implements PasswordService { + /** + * A way to generate Password aafterBCrypt Standard
+ * This is computationally expensive + * + * @return a non-deterministic Salt for BCrypt. + */ + @Override + public String hashPassword(String password) { + return BCrypt.hashpw(password, BCrypt.gensalt(12)); + } + + @Override + public boolean verifyPassword(String password, String hashedPassword) { + return BCrypt.checkpw(password, hashedPassword); + } +} \ No newline at end of file