Skip to content

Commit

Permalink
Merge pull request #740 from bounswe/backend/group-implementation
Browse files Browse the repository at this point in the history
group implementation (get-all, get, create)
  • Loading branch information
zeynep-baydemir authored Nov 18, 2023
2 parents 0fc2cb7 + 792c322 commit 9ba1800
Show file tree
Hide file tree
Showing 12 changed files with 404 additions and 2 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
package com.app.gamereview.controller;

import com.app.gamereview.dto.request.group.CreateGroupRequestDto;
import com.app.gamereview.dto.request.group.GetAllGroupsFilterRequestDto;
import com.app.gamereview.dto.request.review.CreateReviewRequestDto;
import com.app.gamereview.dto.request.review.GetAllReviewsFilterRequestDto;
import com.app.gamereview.dto.request.review.UpdateReviewRequestDto;
import com.app.gamereview.dto.response.review.GetAllReviewsResponseDto;
import com.app.gamereview.model.Group;
import com.app.gamereview.model.Review;
import com.app.gamereview.model.User;
import com.app.gamereview.repository.GroupRepository;
import com.app.gamereview.service.GroupService;
import com.app.gamereview.service.ReviewService;
import com.app.gamereview.util.validation.annotation.AuthorizationRequired;
import io.jsonwebtoken.*;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.validation.Valid;
import org.springdoc.core.annotations.ParameterObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpHeaders;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.util.Date;
import java.util.List;

@RestController
@RequestMapping("/api/group")
@Validated
public class GroupController {

@Value("${SECRET_KEY}")
private String secret_key = "${SECRET_KEY}";

private final GroupService groupService;

@Autowired
public GroupController(
GroupService groupService
) {
this.groupService = groupService;
}

@GetMapping("/get-all")
public ResponseEntity<List<Group>> getReviews(
@ParameterObject GetAllGroupsFilterRequestDto filter) {
List<Group> groups = groupService.getAllGroups(filter);
return ResponseEntity.ok(groups);
}

@GetMapping("/get")
public ResponseEntity<Group> getGroup(@RequestParam String id) {
Group group = groupService.getGroupById(id);

return ResponseEntity.ok(group);
}

@AuthorizationRequired
@PostMapping("/create")
public ResponseEntity<Group> createGroup(@Valid @RequestBody CreateGroupRequestDto createGroupRequestDto,
@RequestHeader String Authorization, HttpServletRequest request) {
User user = (User) request.getAttribute("authenticatedUser");
Group groupToCreate = groupService.createGroup(createGroupRequestDto, user);
return ResponseEntity.ok(groupToCreate);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package com.app.gamereview.dto.request.group;

import com.app.gamereview.enums.MembershipPolicy;
import com.app.gamereview.enums.TagType;
import com.app.gamereview.util.validation.annotation.ValidMemberPolicy;
import jakarta.validation.constraints.*;
import lombok.Getter;
import lombok.Setter;

import java.util.ArrayList;
import java.util.List;

@Getter
@Setter
public class CreateGroupRequestDto {

@NotEmpty(message = "Title field cannot be null or empty")
@Size(min = 3, message = "Title must be at least 3 characters long")
@Size(max = 25, message = "Title must be at most 25 characters long")
private String title;

@NotNull(message = "Description field cannot be null")
@Size(max = 600, message = "Description must be at most 600 characters long")
private String description;

@ValidMemberPolicy(allowedValues = {MembershipPolicy.PUBLIC, MembershipPolicy.PRIVATE})
private String membershipPolicy;

private List<String> tags = new ArrayList<>(); // list of tag ids

@NotEmpty(message = "Game Id must be provided")
@Pattern(regexp = "^[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}$",
message = "Game has Invalid Id (UUID) format")
private String gameId; // id of related game

@Positive(message = "Quota cannot be negative or zero")
private int quota;

private Boolean avatarOnly = false;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package com.app.gamereview.dto.request.group;

import com.app.gamereview.enums.SortDirection;
import com.app.gamereview.enums.SortType;
import com.app.gamereview.util.validation.annotation.ValidSortDirection;
import com.app.gamereview.util.validation.annotation.ValidSortType;
import lombok.Getter;
import lombok.Setter;

import java.util.ArrayList;
import java.util.List;

@Getter
@Setter
public class GetAllGroupsFilterRequestDto {
private String title;

private String membershipPolicy;

private List<String> tags = new ArrayList<>(); // list of tag ids

private String gameName; // id of related game

@ValidSortType(allowedValues = {SortType.QUOTA, SortType.CREATION_DATE})
private String sortBy = SortType.CREATION_DATE.name();

@ValidSortDirection(allowedValues = {SortDirection.ASCENDING, SortDirection.DESCENDING})
private String sortDirection = SortDirection.DESCENDING.name();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package com.app.gamereview.enums;

public enum MembershipPolicy {
PUBLIC,
PRIVATE
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,6 @@ public enum SortType {
CREATION_DATE,
EDIT_DATE,
OVERALL_VOTE,
VOTE_COUNT
VOTE_COUNT,
QUOTA
}
40 changes: 40 additions & 0 deletions app/backend/src/main/java/com/app/gamereview/model/Group.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package com.app.gamereview.model;

import com.app.gamereview.enums.MembershipPolicy;
import com.app.gamereview.model.common.BaseModel;
import lombok.Getter;
import lombok.Setter;
import org.springframework.data.annotation.TypeAlias;
import org.springframework.data.mongodb.core.mapping.Document;

import java.util.ArrayList;
import java.util.List;

@Document(collection = "Group")
@TypeAlias("Group")
@Getter
@Setter
public class Group extends BaseModel {
private String title;

private String description;

private MembershipPolicy membershipPolicy;

private List<String> tags = new ArrayList<>(); // list of tag ids

private String gameId; // id of related game

private String forumId; // id of the forum of the group

private int quota;

private List<String> moderators = new ArrayList<>(); // userIds of the moderators

private List<String> members = new ArrayList<>(); // userIds of the members

private List<String> bannedMembers = new ArrayList<>(); // userIds of the banned members

private Boolean avatarOnly;

}
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,6 @@ public interface GameRepository extends MongoRepository<Game, String> {

Optional<Game> findByGameNameAndIsDeletedFalse(String gameName);

Optional<Game> findByIdAndIsDeletedFalse(String id);

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.app.gamereview.repository;

import com.app.gamereview.model.Group;
import org.springframework.data.mongodb.repository.MongoRepository;

import java.util.Optional;

public interface GroupRepository extends MongoRepository<Group, String> {
Optional<Group> findByIdAndIsDeletedFalse(String id);

Optional<Group> findByTitleAndIsDeletedFalse(String title);
}
Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,7 @@ public Game createGame(CreateGameRequestDto request){
for (String genreId : request.getGenre()) {
Optional<Tag> genre = tagRepository.findByIdAndIsDeletedFalse(genreId);
if (genre.isEmpty() || genre.get().getTagType() != TagType.GENRE) {
throw new ResourceNotFoundException("One of the givem genre is not found.");
throw new ResourceNotFoundException("One of the given genre is not found.");
}
}

Expand Down
155 changes: 155 additions & 0 deletions app/backend/src/main/java/com/app/gamereview/service/GroupService.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
package com.app.gamereview.service;

import com.app.gamereview.dto.request.group.CreateGroupRequestDto;
import com.app.gamereview.dto.request.group.GetAllGroupsFilterRequestDto;
import com.app.gamereview.dto.request.tag.AddGameTagRequestDto;
import com.app.gamereview.enums.ForumType;
import com.app.gamereview.enums.SortDirection;
import com.app.gamereview.enums.SortType;
import com.app.gamereview.exception.BadRequestException;
import com.app.gamereview.exception.ResourceNotFoundException;
import com.app.gamereview.model.*;
import com.app.gamereview.repository.*;
import org.modelmapper.ModelMapper;
import org.modelmapper.PropertyMap;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.stereotype.Service;

import java.util.*;

@Service
public class GroupService {

private final GroupRepository groupRepository;

private final GameRepository gameRepository;

private final ForumRepository forumRepository;

private final TagRepository tagRepository;

private final MongoTemplate mongoTemplate;

private final ModelMapper modelMapper;

@Autowired
public GroupService(
GroupRepository groupRepository,
GameRepository gameRepository,
ForumRepository forumRepository,
TagRepository tagRepository,
MongoTemplate mongoTemplate,
ModelMapper modelMapper
) {
this.groupRepository = groupRepository;
this.gameRepository = gameRepository;
this.forumRepository = forumRepository;
this.tagRepository = tagRepository;
this.mongoTemplate = mongoTemplate;
this.modelMapper = modelMapper;

modelMapper.addMappings(new PropertyMap<CreateGroupRequestDto, Group>() {
@Override
protected void configure() {
map().setGameId(source.getGameId());
skip().setId(null); // Exclude id from mapping
}
});
}

public List<Group> getAllGroups(GetAllGroupsFilterRequestDto filter){
Query query = new Query();

// search for title
if(filter.getTitle() != null && !filter.getTitle().isBlank()){
String regexPattern = ".*" + filter.getTitle() + ".*";
query.addCriteria(Criteria.where("title").regex(regexPattern, "i"));
}
if (filter.getMembershipPolicy() != null) {
query.addCriteria(Criteria.where("membershipPolicy").is(filter.getMembershipPolicy()));
}
if (filter.getTags() != null && !filter.getTags().isEmpty()) {
query.addCriteria(Criteria.where("tags").in(filter.getTags()));
}
if (filter.getGameName() != null && !filter.getGameName().isBlank()) {
String gameName = filter.getGameName();
Optional<Game> game = gameRepository.findByGameNameAndIsDeletedFalse(gameName);
if(game.isEmpty()){
return new ArrayList<>();
}
query.addCriteria(Criteria.where("gameId").is(game.get().getId()));
}
if (filter.getSortBy() != null) {
Sort.Direction sortDirection = Sort.Direction.DESC;
if (filter.getSortDirection() != null) {
sortDirection = filter.getSortDirection().equals(SortDirection.ASCENDING.name()) ? Sort.Direction.ASC
: Sort.Direction.DESC;
}
if (filter.getSortBy().equals(SortType.CREATION_DATE.name())) {
query.with(Sort.by(sortDirection, "createdAt"));
}
else if (filter.getSortBy().equals(SortType.QUOTA.name())) {
query.with(Sort.by(sortDirection, "quota"));
}
}

return mongoTemplate.find(query,Group.class);
}

public Group getGroupById(String groupId){
Optional<Group> isGroupExists = groupRepository.findByIdAndIsDeletedFalse(groupId);

if(isGroupExists.isEmpty()){
throw new ResourceNotFoundException("Group not found");
}

return isGroupExists.get();
}

public Group createGroup(CreateGroupRequestDto request, User user){

Optional<Group> sameTitle = groupRepository.findByTitleAndIsDeletedFalse(request.getTitle());

if(sameTitle.isPresent()){
throw new BadRequestException("Group with same title already exists, please pick a new title");
}

if(request.getTags() != null){
for(String tagId : request.getTags()){
Optional<Tag> tag = tagRepository.findByIdAndIsDeletedFalse(tagId);
if(tag.isEmpty()){
throw new ResourceNotFoundException("One of the added tag is not found");
}
}
}

if(request.getGameId() != null){
Optional<Game> game = gameRepository.findByIdAndIsDeletedFalse(request.getGameId());
if(game.isEmpty()){
throw new ResourceNotFoundException("Game is not found");
}
}

Group groupToCreate = modelMapper.map(request, Group.class);

Forum correspondingForum = new Forum(groupToCreate.getTitle(), ForumType.GROUP,
groupToCreate.getId(), new ArrayList<>(), new ArrayList<>());
forumRepository.save(correspondingForum);
groupToCreate.setForumId(correspondingForum.getId());

List<String> moderators = new ArrayList<>();
moderators.add(user.getId());
List<String> members = new ArrayList<>();
members.add(user.getId());

groupToCreate.setModerators(moderators);
groupToCreate.setMembers(members);

return groupRepository.save(groupToCreate);
}

}
Loading

0 comments on commit 9ba1800

Please sign in to comment.