Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

group implementation (get-all, get, create) #740

Merged
merged 1 commit into from
Nov 18, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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