package io.spring.graphql; import com.netflix.graphql.dgs.DgsComponent; import com.netflix.graphql.dgs.DgsData; import com.netflix.graphql.dgs.InputArgument; import graphql.execution.DataFetcherResult; import io.spring.api.exception.NoAuthorizationException; import io.spring.api.exception.ResourceNotFoundException; import io.spring.application.article.ArticleCommandService; import io.spring.application.article.NewArticleParam; import io.spring.application.article.UpdateArticleParam; import io.spring.core.article.Article; import io.spring.core.article.ArticleRepository; import io.spring.core.favorite.ArticleFavorite; import io.spring.core.favorite.ArticleFavoriteRepository; import io.spring.core.service.AuthorizationService; import io.spring.core.user.User; import io.spring.graphql.DgsConstants.MUTATION; import io.spring.graphql.exception.AuthenticationException; import io.spring.graphql.types.ArticlePayload; import io.spring.graphql.types.CreateArticleInput; import io.spring.graphql.types.DeletionStatus; import io.spring.graphql.types.UpdateArticleInput; import java.util.Collections; import org.springframework.beans.factory.annotation.Autowired; @DgsComponent public class ArticleMutation { private ArticleCommandService articleCommandService; private ArticleFavoriteRepository articleFavoriteRepository; private ArticleRepository articleRepository; @Autowired public ArticleMutation( ArticleCommandService articleCommandService, ArticleFavoriteRepository articleFavoriteRepository, ArticleRepository articleRepository) { this.articleCommandService = articleCommandService; this.articleFavoriteRepository = articleFavoriteRepository; this.articleRepository = articleRepository; } @DgsData(parentType = MUTATION.TYPE_NAME, field = MUTATION.CreateArticle) public DataFetcherResult createArticle( @InputArgument("input") CreateArticleInput input) { User user = SecurityUtil.getCurrentUser().orElseThrow(AuthenticationException::new); NewArticleParam newArticleParam = NewArticleParam.builder() .title(input.getTitle()) .description(input.getDescription()) .body(input.getBody()) .tagList(input.getTagList() == null ? Collections.emptyList() : input.getTagList()) .build(); Article article = articleCommandService.createArticle(newArticleParam, user); return DataFetcherResult.newResult() .data(ArticlePayload.newBuilder().build()) .localContext(article) .build(); } @DgsData(parentType = MUTATION.TYPE_NAME, field = MUTATION.UpdateArticle) public DataFetcherResult updateArticle( @InputArgument("slug") String slug, @InputArgument("changes") UpdateArticleInput params) { Article article = articleRepository.findBySlug(slug).orElseThrow(ResourceNotFoundException::new); User user = SecurityUtil.getCurrentUser().orElseThrow(AuthenticationException::new); if (!AuthorizationService.canWriteArticle(user, article)) { throw new NoAuthorizationException(); } article = articleCommandService.updateArticle( article, new UpdateArticleParam(params.getTitle(), params.getBody(), params.getDescription())); return DataFetcherResult.newResult() .data(ArticlePayload.newBuilder().build()) .localContext(article) .build(); } @DgsData(parentType = MUTATION.TYPE_NAME, field = MUTATION.FavoriteArticle) public DataFetcherResult favoriteArticle(@InputArgument("slug") String slug) { User user = SecurityUtil.getCurrentUser().orElseThrow(AuthenticationException::new); Article article = articleRepository.findBySlug(slug).orElseThrow(ResourceNotFoundException::new); ArticleFavorite articleFavorite = new ArticleFavorite(article.getId(), user.getId()); articleFavoriteRepository.save(articleFavorite); return DataFetcherResult.newResult() .data(ArticlePayload.newBuilder().build()) .localContext(article) .build(); } @DgsData(parentType = MUTATION.TYPE_NAME, field = MUTATION.UnfavoriteArticle) public DataFetcherResult unfavoriteArticle(@InputArgument("slug") String slug) { User user = SecurityUtil.getCurrentUser().orElseThrow(AuthenticationException::new); Article article = articleRepository.findBySlug(slug).orElseThrow(ResourceNotFoundException::new); articleFavoriteRepository .find(article.getId(), user.getId()) .ifPresent( favorite -> { articleFavoriteRepository.remove(favorite); }); return DataFetcherResult.newResult() .data(ArticlePayload.newBuilder().build()) .localContext(article) .build(); } @DgsData(parentType = MUTATION.TYPE_NAME, field = MUTATION.DeleteArticle) public DeletionStatus deleteArticle(@InputArgument("slug") String slug) { User user = SecurityUtil.getCurrentUser().orElseThrow(AuthenticationException::new); Article article = articleRepository.findBySlug(slug).orElseThrow(ResourceNotFoundException::new); if (!AuthorizationService.canWriteArticle(user, article)) { throw new NoAuthorizationException(); } articleRepository.remove(article); return DeletionStatus.newBuilder().success(true).build(); } }