Password hashing und jft
This commit is contained in:
parent
fce585e089
commit
75644d012d
45
pom.xml
45
pom.xml
@ -55,6 +55,51 @@
|
|||||||
<artifactId>spring-boot-starter-test</artifactId>
|
<artifactId>spring-boot-starter-test</artifactId>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<!-- Spring Security für Passwort-Hashing -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-security</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- JJWT API -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.jsonwebtoken</groupId>
|
||||||
|
<artifactId>jjwt-api</artifactId>
|
||||||
|
<version>0.11.5</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- JJWT Implementierung (zur Laufzeit) -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.jsonwebtoken</groupId>
|
||||||
|
<artifactId>jjwt-impl</artifactId>
|
||||||
|
<version>0.11.5</version>
|
||||||
|
<scope>runtime</scope>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- JJWT Jackson für JSON-Verarbeitung (zur Laufzeit) -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.jsonwebtoken</groupId>
|
||||||
|
<artifactId>jjwt-jackson</artifactId>
|
||||||
|
<version>0.11.5</version>
|
||||||
|
<scope>runtime</scope>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- Spring Boot Validation für Request-Validierung -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-validation</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- Lombok (Optional, aber erleichtert die Code-Generierung) -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.projectlombok</groupId>
|
||||||
|
<artifactId>lombok</artifactId>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter</artifactId>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
|
@ -1,43 +0,0 @@
|
|||||||
package com.example.hangry;
|
|
||||||
|
|
||||||
import org.springframework.http.ResponseEntity;
|
|
||||||
import org.springframework.web.bind.annotation.*;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
@RestController
|
|
||||||
@RequestMapping("/api/groups")
|
|
||||||
@CrossOrigin(origins = "*")
|
|
||||||
public class GroupController {
|
|
||||||
|
|
||||||
private final GroupService groupService;
|
|
||||||
|
|
||||||
public GroupController(GroupService groupService) {
|
|
||||||
this.groupService = groupService;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Neue Gruppe erstellen
|
|
||||||
@PostMapping
|
|
||||||
public ResponseEntity<Group> createGroup(@RequestParam String name, @RequestParam String description) {
|
|
||||||
return ResponseEntity.ok(groupService.createGroup(name, description));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Gruppe beitreten
|
|
||||||
@PostMapping("/{groupId}/join/{userId}")
|
|
||||||
public ResponseEntity<String> joinGroup(@PathVariable Long groupId, @PathVariable Long userId) {
|
|
||||||
boolean joined = groupService.joinGroup(userId, groupId);
|
|
||||||
return joined ? ResponseEntity.ok("Gruppe beigetreten") : ResponseEntity.badRequest().body("Bereits Mitglied");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Gruppe verlassen
|
|
||||||
@PostMapping("/{groupId}/leave/{userId}")
|
|
||||||
public ResponseEntity<String> leaveGroup(@PathVariable Long groupId, @PathVariable Long userId) {
|
|
||||||
boolean left = groupService.leaveGroup(userId, groupId);
|
|
||||||
return left ? ResponseEntity.ok("Gruppe verlassen") : ResponseEntity.badRequest().body("Nicht in der Gruppe");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Mitglieder einer Gruppe abrufen
|
|
||||||
@GetMapping("/{groupId}/members")
|
|
||||||
public ResponseEntity<Set<User>> getGroupMembers(@PathVariable Long groupId) {
|
|
||||||
return ResponseEntity.ok(groupService.getGroupMembers(groupId));
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,32 +0,0 @@
|
|||||||
package com.example.hangry;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
import org.springframework.http.ResponseEntity;
|
|
||||||
import org.springframework.web.bind.annotation.*;
|
|
||||||
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
|
|
||||||
@RestController
|
|
||||||
@RequestMapping("/api/group-recipes")
|
|
||||||
@CrossOrigin(origins = "*")
|
|
||||||
public class GroupRecipeController {
|
|
||||||
|
|
||||||
private final GroupRecipeService groupRecipeService;
|
|
||||||
|
|
||||||
public GroupRecipeController(GroupRecipeService groupRecipeService) {
|
|
||||||
this.groupRecipeService = groupRecipeService;
|
|
||||||
}
|
|
||||||
|
|
||||||
@PostMapping("/{groupId}/share/{recipeId}")
|
|
||||||
public ResponseEntity<String> shareRecipe(@PathVariable Long groupId, @PathVariable Long recipeId) {
|
|
||||||
boolean shared = groupRecipeService.shareRecipeWithGroup(groupId, recipeId);
|
|
||||||
return shared ? ResponseEntity.ok("Rezept geteilt") : ResponseEntity.badRequest().body("Fehler beim Teilen");
|
|
||||||
}
|
|
||||||
|
|
||||||
@GetMapping("/{groupId}")
|
|
||||||
public ResponseEntity<Set<Recipe>> getGroupRecipes(@PathVariable Long groupId) {
|
|
||||||
return ResponseEntity.ok(groupRecipeService.getGroupRecipes(groupId));
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,38 +0,0 @@
|
|||||||
package com.example.hangry;
|
|
||||||
|
|
||||||
import org.springframework.stereotype.Service;
|
|
||||||
import java.util.Set;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
@Service
|
|
||||||
public class GroupRecipeService {
|
|
||||||
|
|
||||||
private final GroupRepository groupRepository;
|
|
||||||
private final RecipeRepository recipeRepository;
|
|
||||||
private final GroupRecipeRepository groupRecipeRepository;
|
|
||||||
|
|
||||||
public GroupRecipeService(GroupRepository groupRepository, RecipeRepository recipeRepository, GroupRecipeRepository groupRecipeRepository) {
|
|
||||||
this.groupRepository = groupRepository;
|
|
||||||
this.recipeRepository = recipeRepository;
|
|
||||||
this.groupRecipeRepository = groupRecipeRepository;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Rezept mit Gruppe teilen
|
|
||||||
public boolean shareRecipeWithGroup(Long groupId, Long recipeId) {
|
|
||||||
Group group = groupRepository.findById(groupId)
|
|
||||||
.orElseThrow(() -> new RuntimeException("Gruppe nicht gefunden"));
|
|
||||||
Recipe recipe = recipeRepository.findById(recipeId)
|
|
||||||
.orElseThrow(() -> new RuntimeException("Rezept nicht gefunden"));
|
|
||||||
|
|
||||||
GroupRecipe groupRecipe = new GroupRecipe(group, recipe);
|
|
||||||
groupRecipeRepository.save(groupRecipe);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Alle Rezepte einer Gruppe abrufen
|
|
||||||
public Set<Recipe> getGroupRecipes(Long groupId) {
|
|
||||||
Group group = groupRepository.findById(groupId)
|
|
||||||
.orElseThrow(() -> new RuntimeException("Gruppe nicht gefunden"));
|
|
||||||
return group.getSharedRecipes().stream().map(GroupRecipe::getRecipe).collect(Collectors.toSet());
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,60 +0,0 @@
|
|||||||
package com.example.hangry;
|
|
||||||
|
|
||||||
import org.springframework.stereotype.Service;
|
|
||||||
import java.util.Optional;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
@Service
|
|
||||||
public class GroupService {
|
|
||||||
|
|
||||||
private final GroupRepository groupRepository;
|
|
||||||
private final UserRepository userRepository;
|
|
||||||
|
|
||||||
public GroupService(GroupRepository groupRepository, UserRepository userRepository) {
|
|
||||||
this.groupRepository = groupRepository;
|
|
||||||
this.userRepository = userRepository;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Gruppe erstellen
|
|
||||||
public Group createGroup(String name, String description) {
|
|
||||||
Group group = new Group(name, description);
|
|
||||||
return groupRepository.save(group);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Gruppe beitreten
|
|
||||||
public boolean joinGroup(Long userId, Long groupId) {
|
|
||||||
User user = userRepository.findById(userId)
|
|
||||||
.orElseThrow(() -> new RuntimeException("User nicht gefunden"));
|
|
||||||
Group group = groupRepository.findById(groupId)
|
|
||||||
.orElseThrow(() -> new RuntimeException("Gruppe nicht gefunden"));
|
|
||||||
|
|
||||||
if (!group.getMembers().contains(user)) {
|
|
||||||
group.getMembers().add(user);
|
|
||||||
groupRepository.save(group);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Gruppe verlassen
|
|
||||||
public boolean leaveGroup(Long userId, Long groupId) {
|
|
||||||
User user = userRepository.findById(userId)
|
|
||||||
.orElseThrow(() -> new RuntimeException("User nicht gefunden"));
|
|
||||||
Group group = groupRepository.findById(groupId)
|
|
||||||
.orElseThrow(() -> new RuntimeException("Gruppe nicht gefunden"));
|
|
||||||
|
|
||||||
if (group.getMembers().contains(user)) {
|
|
||||||
group.getMembers().remove(user);
|
|
||||||
groupRepository.save(group);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Alle Mitglieder einer Gruppe abrufen
|
|
||||||
public Set<User> getGroupMembers(Long groupId) {
|
|
||||||
Group group = groupRepository.findById(groupId)
|
|
||||||
.orElseThrow(() -> new RuntimeException("Gruppe nicht gefunden"));
|
|
||||||
return group.getMembers();
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,45 +0,0 @@
|
|||||||
package com.example.hangry;
|
|
||||||
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.http.HttpStatus;
|
|
||||||
import org.springframework.http.ResponseEntity;
|
|
||||||
import org.springframework.web.bind.annotation.*;
|
|
||||||
import java.util.*;
|
|
||||||
|
|
||||||
@RestController
|
|
||||||
@RequestMapping("/api/ingredients")
|
|
||||||
public class IngredientController {
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private IngredientService ingredientService;
|
|
||||||
|
|
||||||
// Globale Zutaten abrufen
|
|
||||||
@GetMapping("/global")
|
|
||||||
public List<Ingredient> getGlobalIngredients() {
|
|
||||||
return ingredientService.getGlobalIngredients();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Benutzerspezifische Zutaten abrufen
|
|
||||||
@GetMapping("/user/{userId}")
|
|
||||||
public List<Ingredient> getUserIngredients(@PathVariable Long userId) {
|
|
||||||
return ingredientService.getUserIngredients(userId);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Neue globale Zutat hinzufügen
|
|
||||||
@PostMapping("/global")
|
|
||||||
public Ingredient addGlobalIngredient(@RequestBody Ingredient ingredient) {
|
|
||||||
return ingredientService.addGlobalIngredient(ingredient);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Neue benutzerspezifische Zutat hinzufügen
|
|
||||||
@PostMapping("/user/{userId}")
|
|
||||||
public ResponseEntity<Ingredient> addUserIngredient(@PathVariable Long userId, @RequestBody Ingredient ingredient) {
|
|
||||||
try {
|
|
||||||
Ingredient newIngredient = ingredientService.addUserIngredient(userId, ingredient);
|
|
||||||
return ResponseEntity.status(HttpStatus.CREATED).body(newIngredient);
|
|
||||||
} catch (IllegalArgumentException e) {
|
|
||||||
// Falls die Zutat bereits global existiert
|
|
||||||
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(null);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,55 +0,0 @@
|
|||||||
package com.example.hangry;
|
|
||||||
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.stereotype.Service;
|
|
||||||
import java.util.*;
|
|
||||||
|
|
||||||
@Service
|
|
||||||
public class IngredientService {
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private IngredientRepository ingredientRepository;
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private UserRepository userRepository;
|
|
||||||
|
|
||||||
// Globale Zutaten abrufen
|
|
||||||
public List<Ingredient> getGlobalIngredients() {
|
|
||||||
return ingredientRepository.findByIsGlobal(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Benutzerspezifische Zutaten abrufen
|
|
||||||
public List<Ingredient> getUserIngredients(Long userId) {
|
|
||||||
Optional<User> user = userRepository.findById(userId);
|
|
||||||
if (user.isPresent()) {
|
|
||||||
return ingredientRepository.findByUserId(userId);
|
|
||||||
} else {
|
|
||||||
throw new IllegalArgumentException("User not found with ID: " + userId);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Globale Zutat hinzufügen
|
|
||||||
public Ingredient addGlobalIngredient(Ingredient ingredient) {
|
|
||||||
ingredient.setGlobal(true); // Zutat als global markieren
|
|
||||||
return ingredientRepository.save(ingredient);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Benutzerdefinierte Zutat hinzufügen, nur wenn sie nicht global existiert
|
|
||||||
public Ingredient addUserIngredient(Long userId, Ingredient ingredient) {
|
|
||||||
// Zuerst prüfen, ob diese Zutat bereits global existiert
|
|
||||||
boolean isGlobalIngredientExists = ingredientRepository.existsByNameAndIsGlobal(ingredient.getName(), true);
|
|
||||||
|
|
||||||
if (isGlobalIngredientExists) {
|
|
||||||
throw new IllegalArgumentException("Zutat existiert bereits als globale Zutat.");
|
|
||||||
}
|
|
||||||
|
|
||||||
Optional<User> user = userRepository.findById(userId);
|
|
||||||
if (user.isPresent()) {
|
|
||||||
ingredient.setGlobal(false); // Zutat als benutzerspezifisch markieren
|
|
||||||
ingredient.setUser(user.get()); // Zutat dem Benutzer zuweisen
|
|
||||||
return ingredientRepository.save(ingredient);
|
|
||||||
} else {
|
|
||||||
throw new IllegalArgumentException("User not found with ID: " + userId);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,44 +0,0 @@
|
|||||||
package com.example.hangry;
|
|
||||||
|
|
||||||
import org.springframework.http.ResponseEntity;
|
|
||||||
import org.springframework.web.bind.annotation.*;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
@RestController
|
|
||||||
@RequestMapping("/api/likes")
|
|
||||||
@CrossOrigin(origins = "*")
|
|
||||||
public class LikeController {
|
|
||||||
|
|
||||||
private final LikeService likeService;
|
|
||||||
|
|
||||||
public LikeController(LikeService likeService) {
|
|
||||||
this.likeService = likeService;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Rezept liken
|
|
||||||
@PostMapping("/{userId}/{recipeId}")
|
|
||||||
public ResponseEntity<String> likeRecipe(@PathVariable Long userId, @PathVariable Long recipeId) {
|
|
||||||
boolean liked = likeService.likeRecipe(userId, recipeId);
|
|
||||||
return liked ? ResponseEntity.ok("Rezept geliked") : ResponseEntity.badRequest().body("Bereits geliked");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Rezept entliken
|
|
||||||
@DeleteMapping("/{userId}/{recipeId}")
|
|
||||||
public ResponseEntity<String> unlikeRecipe(@PathVariable Long userId, @PathVariable Long recipeId) {
|
|
||||||
boolean unliked = likeService.unlikeRecipe(userId, recipeId);
|
|
||||||
return unliked ? ResponseEntity.ok("Like entfernt") : ResponseEntity.badRequest().body("Like existiert nicht");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Anzahl der Likes für ein Rezept abrufen
|
|
||||||
@GetMapping("/count/{recipeId}")
|
|
||||||
public ResponseEntity<Long> getLikeCount(@PathVariable Long recipeId) {
|
|
||||||
return ResponseEntity.ok(likeService.getLikeCount(recipeId));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Alle geliketen Rezepte eines Users abrufen
|
|
||||||
@GetMapping("/user/{userId}")
|
|
||||||
public ResponseEntity<List<Recipe>> getLikedRecipes(@PathVariable Long userId) {
|
|
||||||
return ResponseEntity.ok(likeService.getLikedRecipes(userId));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,66 +0,0 @@
|
|||||||
package com.example.hangry;
|
|
||||||
|
|
||||||
import org.springframework.stereotype.Service;
|
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
@Service
|
|
||||||
public class LikeService {
|
|
||||||
|
|
||||||
private final LikeRepository likeRepository;
|
|
||||||
private final RecipeRepository recipeRepository;
|
|
||||||
private final UserRepository userRepository;
|
|
||||||
|
|
||||||
public LikeService(LikeRepository likeRepository, RecipeRepository recipeRepository, UserRepository userRepository) {
|
|
||||||
this.likeRepository = likeRepository;
|
|
||||||
this.recipeRepository = recipeRepository;
|
|
||||||
this.userRepository = userRepository;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Rezept liken
|
|
||||||
public boolean likeRecipe(Long userId, Long recipeId) {
|
|
||||||
User user = userRepository.findById(userId).orElseThrow();
|
|
||||||
Recipe recipe = recipeRepository.findById(recipeId).orElseThrow();
|
|
||||||
|
|
||||||
if (likeRepository.existsByUserAndRecipe(user, recipe)) {
|
|
||||||
return false; // Bereits geliked
|
|
||||||
}
|
|
||||||
|
|
||||||
Like like = new Like();
|
|
||||||
like.setUser(user);
|
|
||||||
like.setRecipe(recipe);
|
|
||||||
likeRepository.save(like);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Rezept entliken
|
|
||||||
@Transactional
|
|
||||||
public boolean unlikeRecipe(Long userId, Long recipeId) {
|
|
||||||
User user = userRepository.findById(userId)
|
|
||||||
.orElseThrow(() -> new RuntimeException("User nicht gefunden"));
|
|
||||||
Recipe recipe = recipeRepository.findById(recipeId)
|
|
||||||
.orElseThrow(() -> new RuntimeException("Rezept nicht gefunden"));
|
|
||||||
|
|
||||||
// Prüfen, ob das Like existiert
|
|
||||||
if (!likeRepository.existsByUserAndRecipe(user, recipe)) {
|
|
||||||
return false; // Like existiert nicht
|
|
||||||
}
|
|
||||||
|
|
||||||
likeRepository.deleteByUserAndRecipe(user, recipe);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Anzahl der Likes für ein Rezept abrufen
|
|
||||||
public long getLikeCount(Long recipeId) {
|
|
||||||
Recipe recipe = recipeRepository.findById(recipeId).orElseThrow();
|
|
||||||
return likeRepository.countByRecipe(recipe);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Alle geliketen Rezepte eines Users abrufen
|
|
||||||
public List<Recipe> getLikedRecipes(Long userId) {
|
|
||||||
User user = userRepository.findById(userId).orElseThrow();
|
|
||||||
List<Like> likes = likeRepository.findAllByUser(user);
|
|
||||||
return likes.stream().map(Like::getRecipe).toList();
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,68 +0,0 @@
|
|||||||
package com.example.hangry;
|
|
||||||
|
|
||||||
import org.springframework.http.HttpStatus;
|
|
||||||
import org.springframework.http.ResponseEntity;
|
|
||||||
import org.springframework.web.bind.annotation.*;
|
|
||||||
import org.springframework.data.domain.Page;
|
|
||||||
import org.springframework.data.domain.Pageable;
|
|
||||||
import java.util.Optional;
|
|
||||||
|
|
||||||
@RestController
|
|
||||||
@RequestMapping("/api/recipes")
|
|
||||||
@CrossOrigin(origins = "*") // Erlaubt CORS für alle Domains, kann angepasst werden
|
|
||||||
public class RecipeController {
|
|
||||||
|
|
||||||
private final RecipeService recipeService;
|
|
||||||
|
|
||||||
public RecipeController(RecipeService recipeService) {
|
|
||||||
this.recipeService = recipeService;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Alle Rezepte mit Pagination abrufen
|
|
||||||
@GetMapping
|
|
||||||
public Page<Recipe> getAllRecipes(Pageable pageable) {
|
|
||||||
return recipeService.getAllRecipes(pageable);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Einzelnes Rezept nach ID abrufen
|
|
||||||
@GetMapping("/{id}")
|
|
||||||
public ResponseEntity<Recipe> getRecipeById(@PathVariable Long id) {
|
|
||||||
Optional<Recipe> recipe = recipeService.getRecipeById(id);
|
|
||||||
return recipe.map(ResponseEntity::ok).orElseGet(() -> ResponseEntity.notFound().build());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Neues Rezept erstellen
|
|
||||||
@PostMapping
|
|
||||||
public ResponseEntity<Recipe> createRecipe(@RequestBody Recipe recipe) {
|
|
||||||
Recipe savedRecipe = recipeService.createRecipe(recipe);
|
|
||||||
return ResponseEntity.status(HttpStatus.CREATED).body(savedRecipe);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Rezept aktualisieren
|
|
||||||
@PutMapping("/{id}")
|
|
||||||
public ResponseEntity<Recipe> updateRecipe(@PathVariable Long id, @RequestBody Recipe recipe) {
|
|
||||||
Optional<Recipe> updatedRecipe = recipeService.updateRecipe(id, recipe);
|
|
||||||
return updatedRecipe.map(ResponseEntity::ok).orElseGet(() -> ResponseEntity.notFound().build());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Rezept löschen
|
|
||||||
@DeleteMapping("/{id}")
|
|
||||||
public ResponseEntity<Void> deleteRecipe(@PathVariable Long id) {
|
|
||||||
if (recipeService.deleteRecipe(id)) {
|
|
||||||
return ResponseEntity.noContent().build();
|
|
||||||
} else {
|
|
||||||
return ResponseEntity.notFound().build();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//Endpunkt: Filter nach Kategorie (z. B. "/api/recipes/filter/category?category=vegan")
|
|
||||||
@GetMapping("/filter/category")
|
|
||||||
public Page<Recipe> getRecipesByCategory(@RequestParam String category, Pageable pageable) {
|
|
||||||
return recipeService.getRecipesByCategory(category, pageable);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Endpunkt: Filter nach Zutat (z. B. "/api/recipes/filter/ingredient?ingredient=tomate")
|
|
||||||
@GetMapping("/filter/ingredient")
|
|
||||||
public Page<Recipe> getRecipesByIngredient(@RequestParam String ingredient, Pageable pageable) {
|
|
||||||
return recipeService.getRecipesByIngredient(ingredient, pageable);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,64 +0,0 @@
|
|||||||
package com.example.hangry;
|
|
||||||
|
|
||||||
import org.springframework.data.domain.Page;
|
|
||||||
import org.springframework.data.domain.Pageable;
|
|
||||||
import org.springframework.stereotype.Service;
|
|
||||||
|
|
||||||
import java.util.Optional;
|
|
||||||
|
|
||||||
@Service
|
|
||||||
public class RecipeService {
|
|
||||||
|
|
||||||
private final RecipeRepository recipeRepository;
|
|
||||||
|
|
||||||
public RecipeService(RecipeRepository recipeRepository) {
|
|
||||||
this.recipeRepository = recipeRepository;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Alle Rezepte mit Pagination abrufen
|
|
||||||
public Page<Recipe> getAllRecipes(Pageable pageable) {
|
|
||||||
return recipeRepository.findAll(pageable);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Einzelnes Rezept nach ID abrufen
|
|
||||||
public Optional<Recipe> getRecipeById(Long id) {
|
|
||||||
return recipeRepository.findById(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Neues Rezept erstellen
|
|
||||||
public Recipe createRecipe(Recipe recipe) {
|
|
||||||
return recipeRepository.save(recipe);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Rezept aktualisieren
|
|
||||||
public Optional<Recipe> updateRecipe(Long id, Recipe recipeDetails) {
|
|
||||||
return recipeRepository.findById(id).map(recipe -> {
|
|
||||||
if (recipeDetails.getName() != null) recipe.setName(recipeDetails.getName());
|
|
||||||
if (recipeDetails.getDescription() != null) recipe.setDescription(recipeDetails.getDescription());
|
|
||||||
if (recipeDetails.getCategory() != null) recipe.setCategory(recipeDetails.getCategory());
|
|
||||||
if (recipeDetails.getImageUrl() != null) recipe.setImageUrl(recipeDetails.getImageUrl());
|
|
||||||
return recipeRepository.save(recipe);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Rezept löschen
|
|
||||||
public boolean deleteRecipe(Long id) {
|
|
||||||
if (recipeRepository.existsById(id)) {
|
|
||||||
recipeRepository.deleteById(id);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
//Filter nach Kategorie
|
|
||||||
public Page<Recipe> getRecipesByCategory(String category, Pageable pageable) {
|
|
||||||
return recipeRepository.findByCategoryIgnoreCase(category, pageable);
|
|
||||||
}
|
|
||||||
|
|
||||||
//Filter nach Zutat
|
|
||||||
public Page<Recipe> getRecipesByIngredient(String ingredient, Pageable pageable) {
|
|
||||||
return recipeRepository.findByIngredient(ingredient, pageable);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,33 +0,0 @@
|
|||||||
package com.example.hangry;
|
|
||||||
|
|
||||||
import org.springframework.web.bind.annotation.*;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
@RestController
|
|
||||||
@RequestMapping("/users")
|
|
||||||
public class UserController {
|
|
||||||
|
|
||||||
private final UserService userService;
|
|
||||||
|
|
||||||
public UserController(UserService userService) {
|
|
||||||
this.userService = userService;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Endpunkt: Benutzer erstellen
|
|
||||||
@PostMapping
|
|
||||||
public User createUser(@RequestBody User user) {
|
|
||||||
return userService.createUser(user);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Endpunkt: Benutzer nach Benutzername abrufen
|
|
||||||
@GetMapping("/username/{username}")
|
|
||||||
public User getUserByUsername(@PathVariable String username) {
|
|
||||||
return userService.getUserByUsername(username);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Endpunkt: Benutzer nach E-Mail abrufen
|
|
||||||
@GetMapping("/email/{email}")
|
|
||||||
public User getUserByEmail(@PathVariable String email) {
|
|
||||||
return userService.getUserByEmail(email);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,29 +0,0 @@
|
|||||||
package com.example.hangry;
|
|
||||||
|
|
||||||
import org.springframework.stereotype.Service;
|
|
||||||
|
|
||||||
@Service
|
|
||||||
public class UserService {
|
|
||||||
|
|
||||||
private final UserRepository userRepository;
|
|
||||||
|
|
||||||
// Dependency Injection (Spring kümmert sich darum)
|
|
||||||
public UserService(UserRepository userRepository) {
|
|
||||||
this.userRepository = userRepository;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Einen neuen Benutzer erstellen
|
|
||||||
public User createUser(User user) {
|
|
||||||
return userRepository.save(user);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Benutzer anhand des Benutzernamens suchen
|
|
||||||
public User getUserByUsername(String username) {
|
|
||||||
return userRepository.findByUsername(username);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Benutzer anhand der E-Mail suchen
|
|
||||||
public User getUserByEmail(String email) {
|
|
||||||
return userRepository.findByEmail(email);
|
|
||||||
}
|
|
||||||
}
|
|
42
src/main/java/com/example/hangry/security/JwtUtil.java
Normal file
42
src/main/java/com/example/hangry/security/JwtUtil.java
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
package com.example.hangry.security;
|
||||||
|
|
||||||
|
import io.jsonwebtoken.*;
|
||||||
|
import io.jsonwebtoken.security.Keys;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import java.security.Key;
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
public class JwtUtil {
|
||||||
|
private final String SECRET_KEY = "geheimeschluesselgeheimeschluessel"; // Sollte mind. 256 Bit lang sein
|
||||||
|
private final long EXPIRATION_TIME = 1000 * 60 * 60; // 1 Stunde gültig
|
||||||
|
|
||||||
|
private final Key key = Keys.hmacShaKeyFor(SECRET_KEY.getBytes());
|
||||||
|
|
||||||
|
//Token generieren
|
||||||
|
public String generateToken(String username) {
|
||||||
|
return Jwts.builder()
|
||||||
|
.setSubject(username) // Benutzername in das Token schreiben
|
||||||
|
.setIssuedAt(new Date()) // Zeitpunkt der Erstellung
|
||||||
|
.setExpiration(new Date(System.currentTimeMillis() + EXPIRATION_TIME)) // Ablaufzeit setzen
|
||||||
|
.signWith(key, SignatureAlgorithm.HS256) // Signieren mit geheimer Schlüssel
|
||||||
|
.compact();
|
||||||
|
}
|
||||||
|
|
||||||
|
//Token validieren
|
||||||
|
public boolean validateToken(String token) {
|
||||||
|
try {
|
||||||
|
Jwts.parserBuilder().setSigningKey(key).build().parseClaimsJws(token);
|
||||||
|
return true;
|
||||||
|
} catch (JwtException | IllegalArgumentException e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Benutzername aus Token extrahieren
|
||||||
|
public String extractUsername(String token) {
|
||||||
|
return Jwts.parserBuilder().setSigningKey(key).build()
|
||||||
|
.parseClaimsJws(token).getBody().getSubject();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,28 @@
|
|||||||
|
package com.example.hangry.security;
|
||||||
|
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||||
|
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
||||||
|
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
|
||||||
|
import org.springframework.security.web.SecurityFilterChain;
|
||||||
|
import org.springframework.security.config.http.SessionCreationPolicy;
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
@EnableWebSecurity // Aktiviert Spring Security
|
||||||
|
public class SecurityConfig {
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
|
||||||
|
http
|
||||||
|
.csrf(AbstractHttpConfigurer::disable) // Neue Syntax für CSRF-Disable
|
||||||
|
.authorizeHttpRequests(auth -> auth
|
||||||
|
.requestMatchers("/api/auth/register", "/api/auth/login").permitAll() // Registrierung & Login erlauben
|
||||||
|
.anyRequest().authenticated() // Alles andere erfordert Authentifizierung
|
||||||
|
)
|
||||||
|
.sessionManagement(sess -> sess.sessionCreationPolicy(SessionCreationPolicy.STATELESS)); // JWT: Keine Session
|
||||||
|
|
||||||
|
return http.build();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
25
src/main/java/com/example/hangry/services/JwtService.java
Normal file
25
src/main/java/com/example/hangry/services/JwtService.java
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
package com.example.hangry.services;
|
||||||
|
|
||||||
|
import com.example.hangry.User;
|
||||||
|
import io.jsonwebtoken.Jwts;
|
||||||
|
import io.jsonwebtoken.SignatureAlgorithm;
|
||||||
|
import io.jsonwebtoken.security.Keys;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import java.security.Key;
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
public class JwtService {
|
||||||
|
|
||||||
|
private static final Key SECRET_KEY = Keys.secretKeyFor(SignatureAlgorithm.HS256);
|
||||||
|
private static final long EXPIRATION_TIME = 1000 * 60 * 60 * 24; // 24 Stunden
|
||||||
|
|
||||||
|
public String generateToken(User user) {
|
||||||
|
return Jwts.builder()
|
||||||
|
.setSubject(user.getEmail())
|
||||||
|
.setIssuedAt(new Date())
|
||||||
|
.setExpiration(new Date(System.currentTimeMillis() + EXPIRATION_TIME))
|
||||||
|
.signWith(SECRET_KEY)
|
||||||
|
.compact();
|
||||||
|
}
|
||||||
|
}
|
@ -10,3 +10,5 @@ spring.jpa.properties.hibernate.use_sql_comments=true
|
|||||||
spring.jpa.hibernate.ddl-auto=update
|
spring.jpa.hibernate.ddl-auto=update
|
||||||
|
|
||||||
|
|
||||||
|
server.port=8080
|
||||||
|
server.address=0.0.0.0
|
Loading…
x
Reference in New Issue
Block a user