Merge branch 'NapoleonsLeftBoot-main-patch-74b7' into 'main'

Update 12 files

See merge request etc404/software-engineering-project!2
This commit is contained in:
Autumn Wolf
2026-04-16 17:16:59 -06:00
12 changed files with 315 additions and 155 deletions
@@ -9,24 +9,29 @@ import org.springframework.security.web.SecurityFilterChain;
@Configuration
public class SecurityConfig {
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.authorizeHttpRequests(auth -> auth
.requestMatchers("/login", "/register", "/css/**", "/images/**").permitAll()
.anyRequest().authenticated()
)
.formLogin(form -> form
.loginPage("/login")
.defaultSuccessUrl("/", true)
.permitAll()
)
.logout(logout -> logout.permitAll());
return http.build();
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.csrf(csrf -> csrf.disable())
.authorizeHttpRequests(auth -> auth
.requestMatchers("/login", "/register", "/css/**", "/images/**").permitAll()
.requestMatchers("/api/users").permitAll()
.requestMatchers("/api/admin/**").hasRole("ADMIN")
.anyRequest().authenticated()
)
.formLogin(form -> form
.loginPage("/login")
.defaultSuccessUrl("/", true)
.permitAll()
)
.logout(logout -> logout.permitAll());
return http.build();
}
}
@@ -0,0 +1,39 @@
package com.example.demo.controller;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import com.example.demo.dto.UserDto;
import com.example.demo.service.UserService;
@RestController
@RequestMapping("/api/admin")
public class AdminController {
private final UserService userService;
public AdminController(UserService userService) {
this.userService = userService;
}
@PostMapping("/users/{id}/ban")
public ResponseEntity<UserDto> banUser(@PathVariable Integer id) {
return new ResponseEntity<>(userService.banUser(id), HttpStatus.OK);
}
@PostMapping("/users/{id}/unban")
public ResponseEntity<UserDto> unbanUser(@PathVariable Integer id) {
return new ResponseEntity<>(userService.unbanUser(id), HttpStatus.OK);
}
@PostMapping("/users/{id}/make-admin")
public ResponseEntity<UserDto> makeAdmin(@PathVariable Integer id) {
return new ResponseEntity<>(userService.makeAdmin(id), HttpStatus.OK);
}
@PostMapping("/users/{id}/make-user")
public ResponseEntity<UserDto> makeUser(@PathVariable Integer id) {
return new ResponseEntity<>(userService.makeUser(id), HttpStatus.OK);
}
}
@@ -13,6 +13,7 @@ import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.security.core.Authentication;
import com.example.demo.dto.RecipeDto;
import com.example.demo.dto.UserDto;
@@ -35,9 +36,9 @@ public class RecipeController {
// build create recipe REST API
@PostMapping
public ResponseEntity<RecipeDto> saveRecipe(@Valid @RequestBody Recipe recipe) {
RecipeDto recipeDto = recipeService.convertToDto(recipe);
return new ResponseEntity<RecipeDto>(recipeService.saveRecipe(recipeDto), HttpStatus.CREATED);
public ResponseEntity<RecipeDto> saveRecipe(@RequestBody RecipeDto recipeDto, Authentication authentication) {
String currentUsername = authentication.getName();
return new ResponseEntity<>(recipeService.saveRecipe(recipeDto, currentUsername), HttpStatus.CREATED);
}
// build get all recipes REST API
@@ -69,17 +70,21 @@ public class RecipeController {
// build update recipe REST API
// http://localhost:8080/api/recipes/(id number goes here)
@PutMapping("{id}")
public ResponseEntity<RecipeDto> updateRecipe(@PathVariable("id") Integer recipeId, @RequestBody Recipe recipe) {
RecipeDto recipeDto = recipeService.convertToDto(recipe);
return new ResponseEntity<RecipeDto>(recipeService.updateRecipe(recipeDto, recipeId), HttpStatus.OK);
public ResponseEntity<RecipeDto> updateRecipe(
@PathVariable("id") Integer recipeId,
@RequestBody RecipeDto recipeDto,
Authentication authentication) {
String currentUsername = authentication.getName();
return new ResponseEntity<>(recipeService.updateRecipe(recipeDto, recipeId, currentUsername), HttpStatus.OK);
}
// build delete recipe REST API
// http://localhost:8080/api/recipes/(id number goes here)
@DeleteMapping("{id}")
public ResponseEntity<String> deleteRecipe(@PathVariable("id") Integer recipeId) {
recipeService.deleteRecipe(recipeId);
return new ResponseEntity<String>("Recipe deleted succesfully!", HttpStatus.OK);
public ResponseEntity<String> deleteRecipe(@PathVariable("id") Integer recipeId, Authentication authentication) {
String currentUsername = authentication.getName();
recipeService.deleteRecipe(recipeId, currentUsername);
return new ResponseEntity<>("Recipe deleted successfully!", HttpStatus.OK);
}
}
@@ -1,8 +1,6 @@
package com.example.demo.controller;
import java.security.Principal;
import java.util.List;
import java.util.Optional;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
@@ -15,26 +13,20 @@ import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import com.example.demo.dto.UserDto;
import com.example.demo.entity.User;
import com.example.demo.service.UserService;
import com.example.demo.repository.UserRepo;
@RestController
@RequestMapping("/api/users")
public class UserController {
private UserService userService;
private UserRepo userRepo;
public UserController(UserService userService, UserRepo userRepo) {
public UserController(UserService userService) {
super();
this.userService = userService;
this.userRepo = userRepo;
}
// build create user REST API
@@ -52,20 +44,10 @@ public class UserController {
// build get user by name REST API
@GetMapping("/search")
public ResponseEntity<List<UserDto>> getUsersByName(@RequestParam String string) {
List<UserDto> users = userService.getUsersByName(string);
public ResponseEntity<List<UserDto>> getUsersByName(@RequestParam String name) {
List<UserDto> users = userService.getUsersByName(name);
return new ResponseEntity<>(users, HttpStatus.OK);
}
// build get current user REST API
@GetMapping("/me")
public UserDto getLoggedInUser(Principal principal) {
if (principal == null) return null;
String username = principal.getName();
User user = (userRepo.findByUsername(username))
.orElse(null);
return userService.convertToDto(user);
}
// build get user by id REST API
@@ -5,7 +5,6 @@ import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Positive;
import jakarta.validation.constraints.Size;
import lombok.EqualsAndHashCode;
import java.math.BigDecimal;
@@ -20,21 +19,18 @@ public class Recipe {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
@Column(columnDefinition = "TEXT")
@NotBlank(message = "Please provide a recipe title")
@Size(max = 128, message = "Title cannot be longer than 128 characters")
private String title;
@Column(columnDefinition = "TEXT")
@Size(max = 500, message = "Description cannot be longer than 500 characters")
private String description;
@NotNull(message = "Please Provide a prep time amount in minutes")
@NotNull(message = "Please Provide a prep time amount in mintutes")
@Positive(message = "This value cannot be negative")
private Integer prepTimeMinutes;
@NotNull(message = "Please Provide a cook time amount in minutes")
@NotNull(message = "Please Provide a cook time amount in mintutes")
@Positive(message = "This value cannot be negative")
private Integer cookTimeMinutes;
@@ -55,14 +51,11 @@ public class Recipe {
// Recipe ingredients relationship
@OneToMany(mappedBy = "recipe", cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.LAZY)
@NotEmpty(message = "At least one ingredient is required")
@Size(max = 256, message = "Cannot have more than 256 ingredients")
@NotEmpty(message = "At least one ingredient is required")
private Set<RecipeIngredient> recipeIngredients = new HashSet<>();
// Recipe Steps relationship
@OneToMany(mappedBy = "recipe", cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.LAZY)
@NotEmpty(message = "At least one step is required")
@Size(max = 50, message = "Cannot have more than 50 steps")
private Set<Step> steps = new HashSet<>();
// Recipe Images relationship
@@ -1,28 +1,26 @@
package com.example.demo.entity;
import jakarta.persistence.CascadeType;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.FetchType;
import jakarta.persistence.Table;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.JoinTable;
import jakarta.persistence.ManyToMany;
import jakarta.persistence.OneToMany;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.CascadeType;
import jakarta.persistence.Column;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import com.fasterxml.jackson.annotation.JsonIgnore;
import jakarta.persistence.Table;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
@Entity
@@ -31,17 +29,15 @@ public class User implements UserDetails {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@NotNull
private Integer id;
@Column(nullable = false, unique = true)
@NotBlank(message = "Username is required")
private String username;
@Column(nullable = false)
private String role;
@Column(unique = true)
@NotBlank(message = "Email is required")
private String email;
private String hashedpassword;
@@ -49,20 +45,23 @@ public class User implements UserDetails {
@Column(name = "created_at")
private LocalDateTime createdAt;
// User Recipe relationship
@Column(nullable = false)
private boolean banned = false;
@OneToMany(mappedBy = "user", cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.LAZY)
private Set<Recipe> recipes = new HashSet<>();
// Favorite relationship and also junction table
@ManyToMany(fetch = FetchType.LAZY)
@JsonIgnore
@JoinTable(name = "favorites", joinColumns = { @JoinColumn(name = "userId") }, inverseJoinColumns = {
@JoinColumn(name = "recipeId") })
@JoinTable(
name = "favorites",
joinColumns = { @JoinColumn(name = "userId") },
inverseJoinColumns = { @JoinColumn(name = "recipeId") }
)
private Set<Recipe> FavRecipes = new HashSet<>();
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return new ArrayList<>();
return List.of(new SimpleGrantedAuthority(role));
}
@Override
@@ -75,6 +74,26 @@ public class User implements UserDetails {
return username;
}
@Override
public boolean isAccountNonExpired() {
return true;
}
@Override
public boolean isAccountNonLocked() {
return !banned;
}
@Override
public boolean isCredentialsNonExpired() {
return true;
}
@Override
public boolean isEnabled() {
return !banned;
}
public User() {
}
@@ -84,6 +103,7 @@ public class User implements UserDetails {
this.email = email;
this.hashedpassword = hashedpassword;
this.createdAt = createdAt;
this.banned = false;
}
public Integer getId() {
@@ -130,12 +150,27 @@ public class User implements UserDetails {
this.createdAt = createdAt;
}
public boolean isBanned() {
return banned;
}
public void setBanned(boolean banned) {
this.banned = banned;
}
public Set<Recipe> getRecipes() {
return recipes;
}
public void setRecipes(Set<Recipe> recipes) {
this.recipes = recipes;
}
public Set<Recipe> getFavRecipes() {
return FavRecipes;
}
public void setFavRecipes(Set<Recipe> favRecipes) {
FavRecipes = favRecipes;
this.FavRecipes = favRecipes;
}
}
@@ -1,5 +1,6 @@
package com.example.demo.repository;
import java.time.LocalDateTime;
import java.util.List;
import org.springframework.data.jpa.repository.JpaRepository;
@@ -9,5 +10,9 @@ public interface RecipeRepo extends JpaRepository<Recipe, Integer> {
List<Recipe> findByTitleContainingIgnoreCase(String name);
List<Recipe> findByTitleContainingIgnoreCaseAndTags_NameIn(String title, List<String> tags);
long countByUserIdAndCreatedAtAfter(Integer userId, LocalDateTime after);
List<Recipe> findByUserId(Integer userId);
}
@@ -17,7 +17,8 @@ public class CustomUserDetailsService implements UserDetailsService {
}
@Override
public UserDetails loadUserByUsername(@NonNull String username) throws UsernameNotFoundException {
return userRepo.findByUsername(username).orElseThrow(() -> new UsernameNotFoundException("User not found"));
}
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
return userRepo.findByUsername(username)
.orElseThrow(() -> new UsernameNotFoundException("User not found: " + username));
}
}
@@ -1,9 +1,11 @@
package com.example.demo.service.Impl;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.stereotype.Service;
import com.example.demo.dto.RecipeDto;
@@ -55,6 +57,7 @@ public class RecipeServiceImpl implements RecipeService {
this.tagRepository = tagRepository;
}
@Override
public RecipeDto convertToDto(Recipe recipe) {
List<RecipeIngredientDto> ingredientDtos = recipe.getRecipeIngredients().stream()
.map(ri -> new RecipeIngredientDto(ri.getIngredient().getName(), ri.getQuantity(), ri.getUnit(),
@@ -71,34 +74,79 @@ public class RecipeServiceImpl implements RecipeService {
UserDto userDto = new UserDto(recipe.getUser().getId(), recipe.getUser().getUsername(),
recipe.getUser().getEmail());
return new RecipeDto(recipe.getTitle(), recipe.getDescription(), recipe.getPrepTimeMinutes(),
RecipeDto dto = new RecipeDto(recipe.getTitle(), recipe.getDescription(), recipe.getPrepTimeMinutes(),
recipe.getCookTimeMinutes(), recipe.getServings(), userDto, recipe.getStatus(), ingredientDtos,
stepDtos, imageDtos, tagDtos);
dto.setId(recipe.getId());
return dto;
}
private User getCurrentUser(String currentUsername) {
return userRepository.findByUsername(currentUsername)
.orElseThrow(() -> new NotFoundException("User", "username", currentUsername));
}
private boolean isAdmin(User user) {
return "ROLE_ADMIN".equals(user.getRole());
}
private void ensureUserNotBanned(User user) {
if (user.isBanned()) {
throw new AccessDeniedException("Banned users cannot perform this action.");
}
}
private void enforceUploadLimit(User user) {
if (isAdmin(user)) {
return;
}
LocalDateTime cutoff = LocalDateTime.now().minusHours(24);
long uploadsInLast24Hours = recipeRepository.countByUserIdAndCreatedAtAfter(user.getId(), cutoff);
if (uploadsInLast24Hours >= 10) {
throw new AccessDeniedException("Upload limit reached. Maximum is 10 recipes per 24 hours.");
}
}
private void enforceOwnerOrAdmin(User currentUser, Recipe recipe) {
if (isAdmin(currentUser)) {
return;
}
if (!recipe.getUser().getId().equals(currentUser.getId())) {
throw new AccessDeniedException("You do not have permission to modify this recipe.");
}
}
@Override
@Transactional
public RecipeDto saveRecipe(RecipeDto dto) {
public RecipeDto saveRecipe(RecipeDto dto, String currentUsername) {
User user = userRepository.findById(dto.getUserDto().getId())
.orElseThrow(() -> new NotFoundException("User", "id", dto.getUserDto().getId()));
User currentUser = getCurrentUser(currentUsername);
ensureUserNotBanned(currentUser);
enforceUploadLimit(currentUser);
Recipe recipe = new Recipe(dto.getTitle(), dto.getDescription(), dto.getPrepTimeMinutes(),
dto.getCookTimeMinutes(), dto.getServings(), user, dto.getStatus());
dto.getCookTimeMinutes(), dto.getServings(), currentUser, dto.getStatus());
for (RecipeIngredientDto riDto : dto.getIngredients()) {
if (dto.getIngredients() != null) {
for (RecipeIngredientDto riDto : dto.getIngredients()) {
Ingredient ingredient = ingredientRepository.findByNameIgnoreCase(riDto.getIngredientName())
.orElseGet(() -> new Ingredient(riDto.getIngredientName()));
Ingredient ingredient = ingredientRepository.findByNameIgnoreCase(riDto.getIngredientName())
.orElseGet(() -> new Ingredient(riDto.getIngredientName()));
if (ingredient.getId() == null) {
ingredientRepository.save(ingredient);
if (ingredient.getId() == null) {
ingredientRepository.save(ingredient);
}
RecipeIngredient ri = new RecipeIngredient(recipe, ingredient, riDto.getQuantity(), riDto.getUnit(),
riDto.getNotes());
recipe.getRecipeIngredients().add(ri);
}
RecipeIngredient ri = new RecipeIngredient(recipe, ingredient, riDto.getQuantity(), riDto.getUnit(),
riDto.getNotes());
recipe.getRecipeIngredients().add(ri);
}
if (dto.getSteps() != null) {
@@ -115,20 +163,21 @@ public class RecipeServiceImpl implements RecipeService {
}
}
for (TagDto tDto : dto.getTags()) {
if (dto.getTags() != null) {
for (TagDto tDto : dto.getTags()) {
Tag tag = tagRepository.findByName(tDto.getName()).orElseGet(() -> new Tag(tDto.getName()));
Tag tag = tagRepository.findByName(tDto.getName()).orElseGet(() -> new Tag(tDto.getName()));
if (tag.getId() == null) {
tagRepository.save(tag);
if (tag.getId() == null) {
tagRepository.save(tag);
}
recipe.getTags().add(tag);
}
recipe.getTags().add(tag);
}
Recipe saved = recipeRepository.save(recipe);
return getRecipeById(saved.getId());
//return convertToDto(saved);
}
@Override
@@ -152,10 +201,15 @@ public class RecipeServiceImpl implements RecipeService {
@Override
@Transactional
public RecipeDto updateRecipe(RecipeDto recipeDto, Integer id) {
public RecipeDto updateRecipe(RecipeDto recipeDto, Integer id, String currentUsername) {
User currentUser = getCurrentUser(currentUsername);
ensureUserNotBanned(currentUser);
Recipe existingRecipe = recipeRepository.findById(id)
.orElseThrow(() -> new NotFoundException("Recipe", "id", id));
enforceOwnerOrAdmin(currentUser, existingRecipe);
existingRecipe.setTitle(recipeDto.getTitle());
existingRecipe.setDescription(recipeDto.getDescription());
existingRecipe.setPrepTimeMinutes(recipeDto.getPrepTimeMinutes());
@@ -197,13 +251,10 @@ public class RecipeServiceImpl implements RecipeService {
for (RecipeIngredientDto riDto : updatedIngredients) {
// go through the old list of ingredients until we find a match with updated
// list
RecipeIngredient existingRI = existingRecipe.getRecipeIngredients().stream()
.filter(ri -> ri.getIngredient().getName().equals(riDto.getIngredientName())).findFirst()
.orElse(null);
// if old ingredient just update parameters
if (existingRI != null) {
existingRI.setQuantity(riDto.getQuantity());
@@ -211,7 +262,6 @@ public class RecipeServiceImpl implements RecipeService {
existingRI.setNotes(riDto.getNotes());
}
// if new ingredient, have to make a whole new thing
else {
Ingredient ingredient = ingredientRepository.findByNameIgnoreCase(riDto.getIngredientName())
@@ -229,7 +279,6 @@ public class RecipeServiceImpl implements RecipeService {
}
if (updatedSteps != null) {
// find steps that weren't included
for (Step step : existingRecipe.getSteps()) {
boolean existsInUpdatedList = updatedSteps.stream()
.anyMatch(dto -> dto.getStepNumber().equals(step.getStepNumber()));
@@ -237,22 +286,17 @@ public class RecipeServiceImpl implements RecipeService {
if (!existsInUpdatedList)
stepsToRemove.add(step);
}
// delete those steps
existingRecipe.getSteps().removeAll(stepsToRemove);
// go through updated steps
for (StepDto stepDto : updatedSteps) {
// find matching step by step number
Step existingStep = existingRecipe.getSteps().stream()
.filter(s -> s.getStepNumber().equals(stepDto.getStepNumber())).findFirst().orElse(null);
// if there's a match update the instruction string
if (existingStep != null) {
existingStep.setInstruction(stepDto.getInstruction());
}
// if no match then make a whole new step
else {
Step newStep = new Step(existingRecipe, stepDto.getStepNumber(), stepDto.getInstruction());
existingRecipe.getSteps().add(newStep);
@@ -260,7 +304,6 @@ public class RecipeServiceImpl implements RecipeService {
}
}
// same process as above just with images instead
if (updatedImages != null) {
for (Image image : existingRecipe.getImages()) {
boolean existsInUpdatedList = updatedImages.stream()
@@ -284,8 +327,6 @@ public class RecipeServiceImpl implements RecipeService {
}
}
// same process as above just with tags instead, except for saving the tag
// since the relationship for this one was slightly different
if (updatedTags != null) {
for (Tag tag : existingRecipe.getTags()) {
boolean existsInUpdatedList = updatedTags.stream().anyMatch(dto -> dto.getName().equals(tag.getName()));
@@ -314,39 +355,45 @@ public class RecipeServiceImpl implements RecipeService {
}
@Override
public void deleteRecipe(Integer Id) {
recipeRepository.findById(Id).orElseThrow(() -> new NotFoundException("Recipe", "id", Id));
recipeRepository.deleteById(Id);
@Transactional
public void deleteRecipe(Integer id, String currentUsername) {
User currentUser = getCurrentUser(currentUsername);
ensureUserNotBanned(currentUser);
Recipe recipe = recipeRepository.findById(id)
.orElseThrow(() -> new NotFoundException("Recipe", "id", id));
enforceOwnerOrAdmin(currentUser, recipe);
recipeRepository.delete(recipe);
}
@Override
@Override
@Transactional
public List<RecipeDto> getRecipes(String name, List<String> tags) {
List<Recipe> recipes;
if(!name.isBlank()) {
recipes = recipeRepository.findByTitleContainingIgnoreCase(name);
}
else {
recipes = recipeRepository.findAll();
}
if(!tags.isEmpty() && !recipes.isEmpty()) {
recipes = recipes.stream()
.filter(recipe -> recipe.getTags().stream().anyMatch(tag -> tags.contains(tag.getName())))
.collect(Collectors.toList());
}
List<RecipeDto> recipeList = new ArrayList<>();
for (Recipe recipe : recipes) {
RecipeDto dto = convertToDto(recipe);
recipeList.add(dto);
}
return recipeList;
List<Recipe> recipes;
if (!name.isBlank()) {
recipes = recipeRepository.findByTitleContainingIgnoreCase(name);
}
else {
recipes = recipeRepository.findAll();
}
if (!tags.isEmpty() && !recipes.isEmpty()) {
recipes = recipes.stream()
.filter(recipe -> recipe.getTags().stream().anyMatch(tag -> tags.contains(tag.getName())))
.collect(Collectors.toList());
}
List<RecipeDto> recipeList = new ArrayList<>();
for (Recipe recipe : recipes) {
RecipeDto dto = convertToDto(recipe);
recipeList.add(dto);
}
return recipeList;
}
}
@@ -1,4 +1,4 @@
package com.example.demo.service.Impl;
ppackage com.example.demo.service.Impl;
import java.util.ArrayList;
import java.util.List;
@@ -39,6 +39,10 @@ public class UserServiceImpl implements UserService {
@Override
public User saveUser(User user) {
if (user.getRole() == null || user.getRole().isBlank()) {
user.setRole("ROLE_USER");
}
user.setBanned(false);
return userRepository.save(user);
}
@@ -125,4 +129,39 @@ public class UserServiceImpl implements UserService {
return userList;
}
@Override
public UserDto banUser(Integer id) {
User user = userRepository.findById(id)
.orElseThrow(() -> new NotFoundException("User", "id", id));
user.setBanned(true);
userRepository.save(user);
return convertToDto(user);
}
@Override
public UserDto unbanUser(Integer id) {
User user = userRepository.findById(id)
.orElseThrow(() -> new NotFoundException("User", "id", id));
user.setBanned(false);
userRepository.save(user);
return convertToDto(user);
}
@Override
public UserDto makeAdmin(Integer id) {
User user = userRepository.findById(id)
.orElseThrow(() -> new NotFoundException("User", "id", id));
user.setRole("ROLE_ADMIN");
userRepository.save(user);
return convertToDto(user);
}
@Override
public UserDto makeUser(Integer id) {
User user = userRepository.findById(id)
.orElseThrow(() -> new NotFoundException("User", "id", id));
user.setRole("ROLE_USER");
userRepository.save(user);
return convertToDto(user);
}
}
@@ -11,7 +11,7 @@ import com.example.demo.entity.User;
public interface RecipeService {
RecipeDto convertToDto(Recipe recipe);
RecipeDto saveRecipe(RecipeDto recipe);
RecipeDto saveRecipe(RecipeDto recipe, String currentUsername);
List<RecipeDto> getAllRecipes();
@@ -19,8 +19,9 @@ public interface RecipeService {
List<RecipeDto> getRecipes(String name, List<String> tags);
RecipeDto updateRecipe(RecipeDto recipedto, Integer Id);
RecipeDto updateRecipe(RecipeDto recipedto, Integer Id, String currentUsername);
void deleteRecipe(Integer Id);
void deleteRecipe(Integer Id, String currentUsername);
}
@@ -12,15 +12,23 @@ public interface UserService {
List<UserDto> getAllUsers();
UserDto getUserById(Integer Id);
UserDto getUserById(Integer id);
List<UserDto> getUsersByName(String name);
UserDto saveFavorite(Integer userId, Integer recipeId);
UserDto updateUser(User user, Integer Id);
UserDto updateUser(User user, Integer id);
void deleteUser(Integer Id);
void deleteUser(Integer id);
void deleteFavorite(Integer userId, Integer recipeId);
UserDto banUser(Integer id);
UserDto unbanUser(Integer id);
UserDto makeAdmin(Integer id);
UserDto makeUser(Integer id);
}