Skip to content

Commit

Permalink
Merge pull request #130 from IT-Cotato/develop
Browse files Browse the repository at this point in the history
[Release]: V2.2024.08.23.01
  • Loading branch information
Youthhing authored Aug 22, 2024
2 parents 961a7eb + 9b9f1c0 commit 327c873
Show file tree
Hide file tree
Showing 14 changed files with 217 additions and 13 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,24 @@

import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import java.util.List;
import lombok.RequiredArgsConstructor;
import org.cotato.csquiz.api.project.dto.CreateProjectImageRequest;
import org.cotato.csquiz.api.project.dto.CreateProjectRequest;
import org.cotato.csquiz.api.project.dto.CreateProjectResponse;
import org.cotato.csquiz.api.project.dto.ProjectDetailResponse;
import org.cotato.csquiz.api.project.dto.ProjectSummaryResponse;
import org.cotato.csquiz.common.error.exception.ImageException;
import org.cotato.csquiz.domain.generation.service.ProjectImageService;
import org.cotato.csquiz.domain.generation.service.ProjectService;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

Expand All @@ -20,6 +30,7 @@
public class ProjectController {

private final ProjectService projectService;
private final ProjectImageService projectImageService;

@Operation(summary = "특정 프로젝트 상세 정보 조회 API")
@GetMapping("/{projectId}")
Expand All @@ -32,4 +43,18 @@ public ResponseEntity<ProjectDetailResponse> getProjectDetail(@PathVariable("pro
public ResponseEntity<List<ProjectSummaryResponse>> getAllProjectSummaries() {
return ResponseEntity.ok(projectService.getAllProjectSummaries());
}

@Operation(summary = "프로젝트 등록 API")
@PostMapping
public ResponseEntity<CreateProjectResponse> createProject(@RequestBody @Valid CreateProjectRequest request) {
return ResponseEntity.status(HttpStatus.CREATED).body(projectService.createProject(request));
}

@Operation(summary = "프로젝트 사진 등록 API")
@PostMapping(value = "/images", consumes = "multipart/form-data")
public ResponseEntity<Void> createProjectImage(@ModelAttribute CreateProjectImageRequest request)
throws ImageException {
projectImageService.createProjectImage(request.projectId(), request.logoImage(), request.thumbNailImage());
return ResponseEntity.status(HttpStatus.CREATED).build();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package org.cotato.csquiz.api.project.dto;

import org.springframework.web.multipart.MultipartFile;

public record CreateProjectImageRequest(
Long projectId,
MultipartFile logoImage,
MultipartFile thumbNailImage
) {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package org.cotato.csquiz.api.project.dto;

public record CreateProjectImageResponse(

) {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package org.cotato.csquiz.api.project.dto;

import jakarta.validation.Valid;
import jakarta.validation.constraints.NotNull;
import java.util.List;

public record CreateProjectRequest(
@NotNull
Integer generationNumber,
@NotNull
String projectName,
String projectIntroduction,
String githubUrl,
String behanceUrl,
String projectUrl,
@Valid @NotNull List<ProjectMemberRequest> members
) {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package org.cotato.csquiz.api.project.dto;

import io.swagger.v3.oas.annotations.media.Schema;
import org.cotato.csquiz.domain.generation.entity.Project;

public record CreateProjectResponse(
@Schema(description = "생성된 프로젝트 PK")
Long projectId
) {
public static CreateProjectResponse from(Project createdProject) {
return new CreateProjectResponse(createdProject.getId());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package org.cotato.csquiz.api.project.dto;

import org.cotato.csquiz.domain.generation.enums.ProjectImageType;
import org.springframework.web.multipart.MultipartFile;

public record ProjectImageRequest(
ProjectImageType imageType,
MultipartFile image
) {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package org.cotato.csquiz.api.project.dto;

import jakarta.validation.constraints.NotNull;
import org.cotato.csquiz.domain.auth.enums.MemberPosition;

public record ProjectMemberRequest(
@NotNull
String name,
@NotNull
MemberPosition position
) {
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,7 @@ public record ProjectSummaryResponse(
String introduction,
Long generationId,
Integer generationNumber,
String imageUrl,
String githubUrl,
String behanceUrl,
String projectUrl
String logoUrl
) {
public static ProjectSummaryResponse of(Project project, Integer generationNumber, ProjectImage projectImage) {
return new ProjectSummaryResponse(
Expand All @@ -21,10 +18,7 @@ public static ProjectSummaryResponse of(Project project, Integer generationNumbe
project.getIntroduction(),
project.getGenerationId(),
generationNumber,
projectImage != null ? projectImage.getS3Info().getUrl() : null,
project.getGithubUrl(),
project.getBehanceUrl(),
project.getProjectUrl()
projectImage != null ? projectImage.getS3Info().getUrl() : null
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import org.cotato.csquiz.common.error.handler.CustomAccessDeniedHandler;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
Expand All @@ -32,7 +33,8 @@ public class SecurityConfig {
"/v1/api/generation",
"/v1/api/session",
"/websocket/csquiz",
"/v2/api/policies"
"/v2/api/policies",
"/v2/api/events/**"
};

private final JwtTokenProvider jwtTokenProvider;
Expand Down Expand Up @@ -87,8 +89,10 @@ public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
.requestMatchers("/v2/api/attendance").hasAnyRole("ADMIN")
.requestMatchers(new AntPathRequestMatcher("/v1/api/socket/token", "POST"))
.hasAnyRole("MEMBER", "EDUCATION", "ADMIN")
.requestMatchers("/v2/api/events/attendances").hasAnyRole("MEMBER", "ADMIN", "EDUCATION")
// .requestMatchers("/v2/api/events/attendances").hasAnyRole("MEMBER", "ADMIN", "EDUCATION")
.requestMatchers("/v1/api/socket/**").hasAnyRole("EDUCATION", "ADMIN")
.requestMatchers(HttpMethod.POST, "/v2/api/projects").hasRole("ADMIN")
.requestMatchers(HttpMethod.GET, "/v2/api/projects/**").permitAll()
.anyRequest().authenticated()
);
return http.build();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,4 +41,20 @@ public ProjectImage(ProjectImageType projectImageType, S3Info s3Info, Long proje
this.s3Info = s3Info;
this.projectId = projectId;
}

public static ProjectImage logoImage(S3Info imageInfo, Long projectId) {
return new ProjectImage(
ProjectImageType.LOGO,
imageInfo,
projectId
);
}

public static ProjectImage thumbNailImage(S3Info thumbNailInfo, Long projectId) {
return new ProjectImage(
ProjectImageType.THUMBNAIL,
thumbNailInfo,
projectId
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -39,4 +39,8 @@ public ProjectMember(MemberPosition memberPosition, String name, Long projectId)
this.name = name;
this.projectId = projectId;
}

public static ProjectMember of(MemberPosition memberPosition, String name, Project project) {
return new ProjectMember(memberPosition, name, project.getId());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package org.cotato.csquiz.domain.generation.service;

import java.util.ArrayList;
import java.util.List;
import lombok.RequiredArgsConstructor;
import org.cotato.csquiz.api.project.dto.ProjectImageRequest;
import org.cotato.csquiz.common.entity.S3Info;
import org.cotato.csquiz.common.error.exception.ImageException;
import org.cotato.csquiz.common.s3.S3Uploader;
import org.cotato.csquiz.domain.generation.entity.Project;
import org.cotato.csquiz.domain.generation.entity.ProjectImage;
import org.cotato.csquiz.domain.generation.repository.ProjectImageRepository;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

@Service
@RequiredArgsConstructor
public class ProjectImageService {

private static final String PROJECT_IMAGE = "projects";
private final S3Uploader s3Uploader;
private final ProjectImageRepository projectImageRepository;

@Transactional
public void createProjectImage(Long projectId, MultipartFile logoImage, MultipartFile thumbNameImage)
throws ImageException {
List<ProjectImage> newImages = new ArrayList<>();

S3Info logoImageInfo = s3Uploader.uploadFiles(logoImage, PROJECT_IMAGE);
newImages.add(ProjectImage.logoImage(logoImageInfo, projectId));

S3Info thumbNailInfo = s3Uploader.uploadFiles(thumbNameImage, PROJECT_IMAGE);
newImages.add(ProjectImage.thumbNailImage(thumbNailInfo, projectId));

projectImageRepository.saveAll(newImages);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package org.cotato.csquiz.domain.generation.service;

import java.util.ArrayList;
import java.util.List;
import lombok.RequiredArgsConstructor;
import org.cotato.csquiz.api.project.dto.ProjectMemberRequest;
import org.cotato.csquiz.domain.generation.entity.Project;
import org.cotato.csquiz.domain.generation.entity.ProjectMember;
import org.cotato.csquiz.domain.generation.repository.ProjectMemberRepository;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
@RequiredArgsConstructor
public class ProjectMemberService {

private final ProjectMemberRepository projectMemberRepository;

@Transactional
public void createProjectMember(Project project, List<ProjectMemberRequest> members) {
List<ProjectMember> newMembers = members.stream()
.map(request -> ProjectMember.of(request.position(), request.name(), project))
.toList();

projectMemberRepository.saveAll(newMembers);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
import java.util.function.Function;
import java.util.stream.Collectors;
import lombok.RequiredArgsConstructor;
import org.cotato.csquiz.api.project.dto.CreateProjectRequest;
import org.cotato.csquiz.api.project.dto.CreateProjectResponse;
import org.cotato.csquiz.api.project.dto.ProjectDetailResponse;
import org.cotato.csquiz.api.project.dto.ProjectSummaryResponse;
import org.cotato.csquiz.domain.generation.entity.Generation;
Expand All @@ -25,6 +27,8 @@
@RequiredArgsConstructor
public class ProjectService {

private final ProjectImageService projectImageService;
private final ProjectMemberService projectMemberService;
private final ProjectRepository projectRepository;
private final ProjectImageRepository projectImageRepository;
private final ProjectMemberRepository projectMemberRepository;
Expand All @@ -45,7 +49,7 @@ public ProjectDetailResponse getProjectDetail(Long projectId) {
}

@Transactional
public List<ProjectSummaryResponse> getAllProjectSummaries(){
public List<ProjectSummaryResponse> getAllProjectSummaries() {

List<Project> projects = projectRepository.findAll();

Expand All @@ -61,11 +65,34 @@ public List<ProjectSummaryResponse> getAllProjectSummaries(){
Map<Long, Integer> generationNumber = generationRepository.findAllByIdsInQuery(generationIds).stream()
.collect(Collectors.toUnmodifiableMap(Generation::getId, Generation::getNumber));

Map<Long, ProjectImage> projectImage = projectImageRepository.findAllByProjectIdInAndProjectImageType(projectIds, ProjectImageType.LOGO).stream()
Map<Long, ProjectImage> projectImage = projectImageRepository.findAllByProjectIdInAndProjectImageType(
projectIds, ProjectImageType.LOGO).stream()
.collect(Collectors.toUnmodifiableMap(ProjectImage::getProjectId, Function.identity()));

return projects.stream()
.map(project -> ProjectSummaryResponse.of(project, generationNumber.get(project.getGenerationId()), projectImage.get(project.getId())))
.map(project -> ProjectSummaryResponse.of(project, generationNumber.get(project.getGenerationId()),
projectImage.get(project.getId())))
.toList();
}

@Transactional
public CreateProjectResponse createProject(CreateProjectRequest request) {

Generation generation = generationRepository.findByNumber(request.generationNumber())
.orElseThrow(() -> new EntityNotFoundException("해당 번호의 기수를 찾을 수 없습니다."));

Project createdProject = Project.builder()
.name(request.projectName())
.introduction(request.projectIntroduction())
.githubUrl(request.githubUrl())
.projectUrl(request.projectUrl())
.behanceUrl(request.behanceUrl())
.projectUrl(request.projectUrl())
.generationId(generation.getId())
.build();
projectRepository.save(createdProject);
projectMemberService.createProjectMember(createdProject, request.members());

return CreateProjectResponse.from(createdProject);
}
}

0 comments on commit 327c873

Please sign in to comment.