Skip to content

Commit

Permalink
Merge pull request #56 from neuefische/ISSUE-55
Browse files Browse the repository at this point in the history
ISSUE-55: Add multiuser support.
  • Loading branch information
Krisssssssssssssssssssssss authored Oct 23, 2024
2 parents 63ff4a3 + 1aee83c commit a88e72c
Show file tree
Hide file tree
Showing 17 changed files with 466 additions and 103 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.HttpStatusEntryPoint;
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;

@Configuration
@EnableWebSecurity
Expand All @@ -21,7 +20,9 @@ public class SecurityConfig {
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.csrf(AbstractHttpConfigurer::disable)
.csrf((csrf) -> csrf
.ignoringRequestMatchers("/api/**")
)
.authorizeHttpRequests(a -> a
.requestMatchers("/api/**").authenticated()
.anyRequest().permitAll()
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
package com.example.backend.controller;

import com.example.backend.dto.CreateMovieRequest;
import com.example.backend.dto.MovieRatingResponse;
import com.example.backend.dto.MovieResponse;
import com.example.backend.model.Movie;
import com.example.backend.model.RatingRepository;
import com.example.backend.service.MovieService;
import jakarta.validation.constraints.NotNull;
import lombok.AllArgsConstructor;
import lombok.NonNull;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.security.oauth2.core.user.OAuth2User;
import org.springframework.web.bind.annotation.*;

import java.util.List;
Expand All @@ -17,6 +21,7 @@
@RequestMapping("/api/movie")
public class MovieController {
private final MovieService movieService;
private final RatingRepository ratingRepository;

@PostMapping
public MovieResponse save(@RequestBody @NotNull CreateMovieRequest movieRequest) {
Expand Down Expand Up @@ -48,12 +53,16 @@ public void delete(@PathVariable String id) {
}

@GetMapping("/watched")
public List<MovieResponse> getWatchedMovies() {
return movieService.getWatchedMovies().stream().map(MovieResponse::from).collect(Collectors.toList());
public List<MovieRatingResponse> getWatchedMovies(@AuthenticationPrincipal OAuth2User user) {
return movieService.getWatchedMovies(user.getAttributes().get("login").toString()).stream()
.map(ratingMoviePair -> MovieRatingResponse.from(ratingMoviePair.getFirst(), ratingMoviePair.getSecond()))
.collect(Collectors.toList());
}

@GetMapping("/wishlist")
public List<MovieResponse> getWishlistedMovies() {
return movieService.getWishlistedMovies().stream().map(MovieResponse::from).collect(Collectors.toList());
public List<MovieRatingResponse> getWishlistedMovies(@AuthenticationPrincipal OAuth2User user) {
return movieService.getWishlistedMovies(user.getAttributes().get("login").toString()).stream()
.map(ratingMoviePair -> MovieRatingResponse.from(ratingMoviePair.getFirst(), ratingMoviePair.getSecond()))
.collect(Collectors.toList());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package com.example.backend.controller;

import com.example.backend.dto.CreateRatingRequest;
import com.example.backend.dto.RatingResponse;
import com.example.backend.model.Rating;
import com.example.backend.service.RatingService;
import lombok.AllArgsConstructor;
import org.jetbrains.annotations.NotNull;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.security.oauth2.core.user.OAuth2User;
import org.springframework.web.bind.annotation.*;

@RestController
@AllArgsConstructor
@RequestMapping("/api/rating")
public class RatingController {

private final RatingService ratingService;

@PostMapping
public void save(@RequestBody @NotNull CreateRatingRequest request, @AuthenticationPrincipal OAuth2User user) {
String login = user.getAttributes().get("login").toString();
Rating rating = request.toRating(login);

ratingService.save(rating);
}

@GetMapping("/{movieId}")
public RatingResponse get(@AuthenticationPrincipal OAuth2User user, @PathVariable String movieId) {
String login = user.getAttributes().get("login").toString();
Rating rating = ratingService.get(login, movieId);

return RatingResponse.from(rating);
}
}
Original file line number Diff line number Diff line change
@@ -1,19 +1,12 @@
package com.example.backend.dto;

import com.example.backend.model.Actor;
import com.example.backend.model.Movie;
import jakarta.validation.constraints.Max;
import jakarta.validation.constraints.Min;
import lombok.NonNull;


public record CreateMovieRequest(
@NonNull String name,
boolean isWatched,
@Min(Movie.MIN_RATING) @Max(Movie.MAX_RATING) Integer rating

@NonNull String name
) {
public Movie toMovie() {
return Movie.builder().name(name).isWatched(isWatched).rating(rating).build();
return Movie.builder().name(name).build();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package com.example.backend.dto;

import com.example.backend.model.Movie;
import com.example.backend.model.Rating;
import jakarta.validation.constraints.Max;
import jakarta.validation.constraints.Min;
import lombok.NonNull;


public record CreateRatingRequest(
@NonNull String movieId,
boolean isWatched,
@Min(Rating.MIN_RATING) @Max(Rating.MAX_RATING) Integer rating
) {
public Rating toRating(String userId) {
return Rating.builder().userId(userId).movieId(movieId).isWatched(isWatched).rating(rating).build();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package com.example.backend.dto;

import com.example.backend.model.Movie;
import com.example.backend.model.Rating;
import lombok.Builder;
import lombok.NonNull;

@Builder
public record MovieRatingResponse(@NonNull String id, @NonNull String movieName, Integer rating, boolean isWatched) {
public static MovieRatingResponse from(Rating rating, Movie movie) {
return MovieRatingResponse.builder()
.id(movie.getId())
.movieName(movie.getName())
.rating(rating.getRating())
.isWatched(rating.isWatched())
.build();
}
}
Original file line number Diff line number Diff line change
@@ -1,19 +1,15 @@
package com.example.backend.dto;

import com.example.backend.model.Movie;
import jakarta.annotation.Nullable;
import lombok.Builder;
import lombok.NonNull;

@Builder
public record MovieResponse(@NonNull String id, @NonNull String name, boolean isWatched,
@Nullable Integer rating) {
public record MovieResponse(@NonNull String id, @NonNull String name) {
public static MovieResponse from(Movie movie) {
return MovieResponse.builder()
.id(movie.getId())
.name(movie.getName())
.isWatched(movie.isWatched())
.rating(movie.getRating())
.build();
}
}
19 changes: 19 additions & 0 deletions backend/src/main/java/com/example/backend/dto/RatingResponse.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package com.example.backend.dto;

import com.example.backend.model.Rating;
import jakarta.annotation.Nullable;
import lombok.Builder;
import lombok.NonNull;

@Builder
public record RatingResponse(String userId, String movieId, Integer rating,
boolean isWatched) {
public static RatingResponse from(Rating rating) {
return RatingResponse.builder()
.userId(rating.getUserId())
.movieId(rating.getMovieId())
.rating(rating.getRating())
.isWatched(rating.isWatched())
.build();
}
}
7 changes: 0 additions & 7 deletions backend/src/main/java/com/example/backend/model/Movie.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,8 @@
@Data
@Document("Movie")
public class Movie {
public static final int MIN_RATING = 1;
public static final int MAX_RATING = 10;

@Id
private String id;

private Integer rating;

private boolean isWatched;

private String name;
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,4 @@

@Repository
public interface MovieRepository extends MongoRepository<Movie, String> {
List<Movie> findAllByIsWatchedIsFalse();

List<Movie> findAllByIsWatchedIsTrue();
}
27 changes: 27 additions & 0 deletions backend/src/main/java/com/example/backend/model/Rating.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package com.example.backend.model;

import lombok.*;
import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.mapping.Document;

@AllArgsConstructor
@NoArgsConstructor
@Builder
@With
@Data
@Document("Rating")
public class Rating {
public static final int MIN_RATING = 1;
public static final int MAX_RATING = 10;

@Id
private String id;

private String movieId;

private String userId;

private Integer rating;

private boolean isWatched;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package com.example.backend.model;

import org.springframework.data.mongodb.repository.MongoRepository;
import org.springframework.stereotype.Repository;

import java.util.List;
import java.util.Optional;

@Repository
public interface RatingRepository extends MongoRepository<Rating, String> {
Optional<Rating> findFirstByUserIdAndMovieId(String userId, String movieId);

List<Rating> findAllByUserIdAndIsWatchedIsFalse(String userId);

List<Rating> findAllByUserIdAndIsWatchedIsTrue(String userId);

List<Rating> findAllByMovieIdAndUserId(List<String> movieId, String userId);
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,11 @@

import com.example.backend.model.Movie;
import com.example.backend.model.MovieRepository;
import com.example.backend.model.Rating;
import com.example.backend.model.RatingRepository;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import org.springframework.data.util.Pair;
import org.springframework.stereotype.Service;

import java.util.List;
Expand All @@ -12,9 +16,7 @@
public class MovieService {
private final MovieRepository movieRepository;

private final MovieActorService movieActorService;

private final MovieDirectorService movieDirectorService;
private final RatingRepository ratingRepository;

private final IdService idService;

Expand All @@ -28,12 +30,33 @@ public List<Movie> getAllMovies() {
return movieRepository.findAll();
}

public List<Movie> getWatchedMovies() {
return movieRepository.findAllByIsWatchedIsTrue();
public List<Pair<Rating, Movie>> getWatchedMovies(@NonNull String userId) {
List<Rating> ratings = ratingRepository.findAllByUserIdAndIsWatchedIsTrue(userId);

return getMovieRatings(ratings);
}

public List<Pair<Rating, Movie>> getWishlistedMovies(@NonNull String userId) {
List<Rating> ratings = ratingRepository.findAllByUserIdAndIsWatchedIsFalse(userId);

return getMovieRatings(ratings);
}

public List<Movie> getWishlistedMovies() {
return movieRepository.findAllByIsWatchedIsFalse();
private List<Pair<Rating, Movie>> getMovieRatings(List<Rating> ratings) {
List<String> movieIds = ratings.stream().map(Rating::getMovieId).toList();
List<Movie> movies = movieRepository.findAllById(movieIds);

return ratings.stream().map(
(Rating rating) -> {
return Pair.of(
rating,
movies.stream().filter(
(Movie movie) -> movie.getId().equals(rating.getMovieId())
).findFirst().orElse(null)
);
}
).filter(ratingMoviePair -> ratingMoviePair.getSecond() != null)
.toList();
}

public Movie getMovieById(String movieId) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package com.example.backend.service;

import com.example.backend.model.Rating;
import com.example.backend.model.RatingRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

@Service
@RequiredArgsConstructor
public class RatingService {
private final RatingRepository ratingRepository;

public void save(Rating rating) {
ratingRepository
.findFirstByUserIdAndMovieId(rating.getUserId(), rating.getMovieId())
.ifPresentOrElse(
(entity) -> ratingRepository.save(entity.withRating(rating.getRating()).withWatched(rating.isWatched())),
() -> ratingRepository.save(rating)
);
}

public Rating get(String userId, String movieId) {
return ratingRepository.findFirstByUserIdAndMovieId(userId, movieId).orElseThrow();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -45,12 +45,6 @@ private SecurityMockMvcRequestPostProcessors.OidcLoginRequestPostProcessor mockU
@Autowired
private ActorRepository actorRepository;

@Autowired
private MovieRepository movieRepository;

@Autowired
private MovieActorRelationRepository movieActorRelationRepository;

@Test
@DirtiesContext
void saveTest_correct() throws Exception {
Expand Down
Loading

0 comments on commit a88e72c

Please sign in to comment.