From b48f954cdd5c9f1b2a7c454882187e7686be91f6 Mon Sep 17 00:00:00 2001 From: mirrerror Date: Fri, 22 Dec 2023 20:02:01 +0200 Subject: [PATCH] update families --- .../controller/ExpenseController.java | 2 +- .../controller/FamilyController.java | 130 ++++++++++++++++++ .../controller/IncomeController.java | 2 +- .../expensetrackerfaf/model/Family.java | 16 ++- .../repository/FamilyRepository.java | 4 +- .../service/ExpenseService.java | 2 + .../service/FamilyService.java | 54 ++++++++ .../service/IncomeService.java | 2 + .../exceptions/FamiliesNotFoundException.java | 9 ++ .../exceptions/FamilyNotCreatedException.java | 9 ++ .../exceptions/FamilyNotUpdatedException.java | 9 ++ .../exceptions/NotAMemberOfTheFamily.java | 9 ++ 12 files changed, 243 insertions(+), 5 deletions(-) create mode 100644 src/main/java/com/faf223/expensetrackerfaf/controller/FamilyController.java create mode 100644 src/main/java/com/faf223/expensetrackerfaf/util/exceptions/FamiliesNotFoundException.java create mode 100644 src/main/java/com/faf223/expensetrackerfaf/util/exceptions/FamilyNotCreatedException.java create mode 100644 src/main/java/com/faf223/expensetrackerfaf/util/exceptions/FamilyNotUpdatedException.java create mode 100644 src/main/java/com/faf223/expensetrackerfaf/util/exceptions/NotAMemberOfTheFamily.java diff --git a/src/main/java/com/faf223/expensetrackerfaf/controller/ExpenseController.java b/src/main/java/com/faf223/expensetrackerfaf/controller/ExpenseController.java index 18432c9..d752fa1 100644 --- a/src/main/java/com/faf223/expensetrackerfaf/controller/ExpenseController.java +++ b/src/main/java/com/faf223/expensetrackerfaf/controller/ExpenseController.java @@ -98,7 +98,7 @@ public class ExpenseController { @GetMapping("/personal-expenses") @Transactional(readOnly = true) - public ResponseEntity> getExpensesByUser(@RequestParam Optional date, + public ResponseEntity> getExpensesByTimeUnits(@RequestParam Optional date, @RequestParam Optional month, @RequestParam Optional startYear, @RequestParam Optional endYear, diff --git a/src/main/java/com/faf223/expensetrackerfaf/controller/FamilyController.java b/src/main/java/com/faf223/expensetrackerfaf/controller/FamilyController.java new file mode 100644 index 0000000..b592579 --- /dev/null +++ b/src/main/java/com/faf223/expensetrackerfaf/controller/FamilyController.java @@ -0,0 +1,130 @@ +package com.faf223.expensetrackerfaf.controller; + +import com.faf223.expensetrackerfaf.dto.FamilyCreationDTO; +import com.faf223.expensetrackerfaf.dto.FamilyDTO; +import com.faf223.expensetrackerfaf.dto.mappers.FamilyMapper; +import com.faf223.expensetrackerfaf.model.Family; +import com.faf223.expensetrackerfaf.model.User; +import com.faf223.expensetrackerfaf.service.FamilyService; +import com.faf223.expensetrackerfaf.service.UserService; +import com.faf223.expensetrackerfaf.util.errors.ErrorResponse; +import com.faf223.expensetrackerfaf.util.exceptions.*; +import jakarta.validation.Valid; +import lombok.RequiredArgsConstructor; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.BindingResult; +import org.springframework.web.bind.annotation.*; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.stream.Collectors; + +@RestController +@RequestMapping("/families") +@RequiredArgsConstructor +public class FamilyController { + + private final FamilyService familyService; + private final FamilyMapper familyMapper; + private final UserService userService; + + @GetMapping() + @PreAuthorize("hasRole('ADMIN')") + public ResponseEntity> getAllFamilies() { + List families = familyService.getFamilies().stream().map(familyMapper::toDto).collect(Collectors.toList()); + if (!families.isEmpty()) return ResponseEntity.ok(families); + else throw new FamiliesNotFoundException("Families not found"); + } + + @PostMapping() + public ResponseEntity> createNewFamily(@RequestBody @Valid FamilyCreationDTO familyCreationDTO, + BindingResult bindingResult) { + if(bindingResult.hasErrors()) + throw new FamilyNotCreatedException("Could not create new family"); + + Family family = familyMapper.toFamily(familyCreationDTO); + + familyService.createOrUpdate(family); + Map response = new HashMap<>(); + response.put("familyId", family.getId()); + return ResponseEntity.status(HttpStatus.CREATED).body(response); + } + + @PatchMapping("/update/{id}") + public ResponseEntity updateFamily(@PathVariable long id, @RequestBody @Valid FamilyCreationDTO familyDTO, + BindingResult bindingResult) { + if(bindingResult.hasErrors()) + throw new FamilyNotUpdatedException(ErrorResponse.from(bindingResult).getMessage()); + + Family family = familyService.getFamilyById(id); + + if(family == null) + throw new FamiliesNotFoundException("The family has not been found"); + + if(!familyService.containsMember(family)) + throw new NotAMemberOfTheFamily("You are not a member of this family"); + + family.setName(familyDTO.getName()); + + familyService.createOrUpdate(family); + return ResponseEntity.status(HttpStatus.CREATED).build(); + } + + @DeleteMapping("/delete/{id}") + public void deleteFamily(@PathVariable long id) { + familyService.deleteFamilyById(id); + } + + @PatchMapping("/add-member/{id}") + public ResponseEntity addFamilyMember(@PathVariable long id, @RequestParam Optional email) { + if(email.isEmpty()) + throw new UserNotFoundException("You have not specified the user email"); + + Family family = familyService.getFamilyById(id); + + if(family == null) + throw new FamiliesNotFoundException("The family has not been found"); + + if(!familyService.containsMember(family)) + throw new NotAMemberOfTheFamily("You are not a member of this family"); + + User user = userService.getUserByEmail(email.get()); + + if(user == null) + throw new UserNotFoundException("User with the specified email has not been found"); + + family.getMembers().add(user); + + familyService.createOrUpdate(family); + return ResponseEntity.status(HttpStatus.CREATED).build(); + } + + @PatchMapping("/remove-member/{id}") + public ResponseEntity removeFamilyMember(@PathVariable long id, @RequestParam Optional email) { + if(email.isEmpty()) + throw new UserNotFoundException("You have not specified the user email"); + + Family family = familyService.getFamilyById(id); + + if(family == null) + throw new FamiliesNotFoundException("The family has not been found"); + + if(!familyService.containsMember(family)) + throw new NotAMemberOfTheFamily("You are not a member of this family"); + + User user = userService.getUserByEmail(email.get()); + + if(user == null) + throw new UserNotFoundException("User with the specified email has not been found"); + + family.getMembers().remove(user); + + familyService.createOrUpdate(family); + return ResponseEntity.status(HttpStatus.CREATED).build(); + } + +} diff --git a/src/main/java/com/faf223/expensetrackerfaf/controller/IncomeController.java b/src/main/java/com/faf223/expensetrackerfaf/controller/IncomeController.java index d73d0fb..f0eef54 100644 --- a/src/main/java/com/faf223/expensetrackerfaf/controller/IncomeController.java +++ b/src/main/java/com/faf223/expensetrackerfaf/controller/IncomeController.java @@ -98,7 +98,7 @@ public class IncomeController { @GetMapping("/personal-incomes") @Transactional(readOnly = true) - public ResponseEntity> getIncomesByUser(@RequestParam Optional date, + public ResponseEntity> getIncomesByTimeUnits(@RequestParam Optional date, @RequestParam Optional month, @RequestParam Optional startYear, @RequestParam Optional endYear, diff --git a/src/main/java/com/faf223/expensetrackerfaf/model/Family.java b/src/main/java/com/faf223/expensetrackerfaf/model/Family.java index 38df80b..ea3f148 100644 --- a/src/main/java/com/faf223/expensetrackerfaf/model/Family.java +++ b/src/main/java/com/faf223/expensetrackerfaf/model/Family.java @@ -5,11 +5,12 @@ import jakarta.validation.constraints.NotEmpty; import lombok.*; import java.util.List; +import java.util.Objects; @Data @AllArgsConstructor @NoArgsConstructor -@Entity(name = "families") +@Entity(name = "family") @Builder public class Family { @@ -19,10 +20,23 @@ public class Family { private Long id; @NotEmpty + @Column(name = "family_name") private String name; @OneToMany(mappedBy = "family", fetch = FetchType.LAZY, cascade = CascadeType.ALL) @ToString.Exclude private List members; + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + Family family = (Family) o; + return Objects.equals(id, family.id) && Objects.equals(name, family.name); + } + + @Override + public int hashCode() { + return Objects.hash(id, name); + } } diff --git a/src/main/java/com/faf223/expensetrackerfaf/repository/FamilyRepository.java b/src/main/java/com/faf223/expensetrackerfaf/repository/FamilyRepository.java index 6fa3998..60ecd39 100644 --- a/src/main/java/com/faf223/expensetrackerfaf/repository/FamilyRepository.java +++ b/src/main/java/com/faf223/expensetrackerfaf/repository/FamilyRepository.java @@ -1,9 +1,9 @@ package com.faf223.expensetrackerfaf.repository; -import com.faf223.expensetrackerfaf.model.IncomeCategory; +import com.faf223.expensetrackerfaf.model.Family; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; @Repository -public interface FamilyRepository extends JpaRepository { +public interface FamilyRepository extends JpaRepository { } diff --git a/src/main/java/com/faf223/expensetrackerfaf/service/ExpenseService.java b/src/main/java/com/faf223/expensetrackerfaf/service/ExpenseService.java index d046ac1..9bb5611 100644 --- a/src/main/java/com/faf223/expensetrackerfaf/service/ExpenseService.java +++ b/src/main/java/com/faf223/expensetrackerfaf/service/ExpenseService.java @@ -130,6 +130,8 @@ public class ExpenseService implements ITransactionService { } + return true; + } throw new UserNotAuthenticatedException("You are not authenticated"); diff --git a/src/main/java/com/faf223/expensetrackerfaf/service/FamilyService.java b/src/main/java/com/faf223/expensetrackerfaf/service/FamilyService.java index 8b294af..0ee4e63 100644 --- a/src/main/java/com/faf223/expensetrackerfaf/service/FamilyService.java +++ b/src/main/java/com/faf223/expensetrackerfaf/service/FamilyService.java @@ -1,13 +1,67 @@ package com.faf223.expensetrackerfaf.service; +import com.faf223.expensetrackerfaf.model.Credential; +import com.faf223.expensetrackerfaf.model.Family; +import com.faf223.expensetrackerfaf.model.User; +import com.faf223.expensetrackerfaf.repository.CredentialRepository; import com.faf223.expensetrackerfaf.repository.FamilyRepository; +import com.faf223.expensetrackerfaf.repository.UserRepository; +import com.faf223.expensetrackerfaf.util.exceptions.UserNotAuthenticatedException; +import com.faf223.expensetrackerfaf.util.exceptions.UserNotFoundException; import lombok.RequiredArgsConstructor; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.core.userdetails.UserDetails; import org.springframework.stereotype.Service; +import java.util.List; +import java.util.Optional; + @Service @RequiredArgsConstructor public class FamilyService { private final FamilyRepository familyRepository; + private final CredentialRepository credentialRepository; + private final UserRepository userRepository; + + public List getFamilies() { + return familyRepository.findAll(); + } + + public void createOrUpdate(Family family) { + familyRepository.save(family); + } + + public Family getFamilyById(long id) { + return familyRepository.findById(id).orElse(null); + } + + public boolean containsMember(Family family) { + Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); + + if (authentication != null && authentication.getPrincipal() instanceof UserDetails userDetails) { + + if(authentication.getAuthorities().stream().noneMatch(authority -> authority.getAuthority().equals("ADMIN"))) { + + Optional credential = credentialRepository.findByEmail(userDetails.getUsername()); + if(credential.isEmpty()) throw new UserNotFoundException("The user has not been found"); + Optional user = userRepository.findById(credential.get().getUser().getUserUuid()); + if(user.isEmpty()) throw new UserNotFoundException("The user has not been found"); + + return user.get().getFamily().equals(family); + + } + + return true; + + } + + throw new UserNotAuthenticatedException("You are not authenticated"); + } + + public void deleteFamilyById(long id) { + familyRepository.deleteById(id); + } } diff --git a/src/main/java/com/faf223/expensetrackerfaf/service/IncomeService.java b/src/main/java/com/faf223/expensetrackerfaf/service/IncomeService.java index 61ac152..12c469f 100644 --- a/src/main/java/com/faf223/expensetrackerfaf/service/IncomeService.java +++ b/src/main/java/com/faf223/expensetrackerfaf/service/IncomeService.java @@ -129,6 +129,8 @@ public class IncomeService implements ITransactionService { } + return true; + } throw new UserNotAuthenticatedException("You are not authenticated"); diff --git a/src/main/java/com/faf223/expensetrackerfaf/util/exceptions/FamiliesNotFoundException.java b/src/main/java/com/faf223/expensetrackerfaf/util/exceptions/FamiliesNotFoundException.java new file mode 100644 index 0000000..916c1bb --- /dev/null +++ b/src/main/java/com/faf223/expensetrackerfaf/util/exceptions/FamiliesNotFoundException.java @@ -0,0 +1,9 @@ +package com.faf223.expensetrackerfaf.util.exceptions; + +public class FamiliesNotFoundException extends RuntimeException { + + public FamiliesNotFoundException(String message) { + super(message); + } + +} diff --git a/src/main/java/com/faf223/expensetrackerfaf/util/exceptions/FamilyNotCreatedException.java b/src/main/java/com/faf223/expensetrackerfaf/util/exceptions/FamilyNotCreatedException.java new file mode 100644 index 0000000..e5dba3f --- /dev/null +++ b/src/main/java/com/faf223/expensetrackerfaf/util/exceptions/FamilyNotCreatedException.java @@ -0,0 +1,9 @@ +package com.faf223.expensetrackerfaf.util.exceptions; + +public class FamilyNotCreatedException extends RuntimeException { + + public FamilyNotCreatedException(String message) { + super(message); + } + +} diff --git a/src/main/java/com/faf223/expensetrackerfaf/util/exceptions/FamilyNotUpdatedException.java b/src/main/java/com/faf223/expensetrackerfaf/util/exceptions/FamilyNotUpdatedException.java new file mode 100644 index 0000000..d043653 --- /dev/null +++ b/src/main/java/com/faf223/expensetrackerfaf/util/exceptions/FamilyNotUpdatedException.java @@ -0,0 +1,9 @@ +package com.faf223.expensetrackerfaf.util.exceptions; + +public class FamilyNotUpdatedException extends RuntimeException { + + public FamilyNotUpdatedException(String message) { + super(message); + } + +} diff --git a/src/main/java/com/faf223/expensetrackerfaf/util/exceptions/NotAMemberOfTheFamily.java b/src/main/java/com/faf223/expensetrackerfaf/util/exceptions/NotAMemberOfTheFamily.java new file mode 100644 index 0000000..0dfad27 --- /dev/null +++ b/src/main/java/com/faf223/expensetrackerfaf/util/exceptions/NotAMemberOfTheFamily.java @@ -0,0 +1,9 @@ +package com.faf223.expensetrackerfaf.util.exceptions; + +public class NotAMemberOfTheFamily extends RuntimeException { + + public NotAMemberOfTheFamily(String message) { + super(message); + } + +}