Skip to content

Commit

Permalink
Merge branch 'dev' into feature/2
Browse files Browse the repository at this point in the history
  • Loading branch information
eunsol-an authored Dec 24, 2022
2 parents f517125 + 44ec0e7 commit cca7d2b
Show file tree
Hide file tree
Showing 19 changed files with 451 additions and 48 deletions.
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ dependencies {
implementation 'org.springframework.boot:spring-boot-starter-validation'

// s3 ์„ค์ • ๊ด€๋ จ
// implementation 'org.springframework.cloud:spring-cloud-starter-aws:2.2.6.RELEASE'
implementation 'org.springframework.cloud:spring-cloud-starter-aws:2.2.6.RELEASE'
}

tasks.named('test') {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,15 +31,17 @@ public PasswordEncoder passwordEncoder() {
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
// CSRF ์„ค์ •
http.csrf().disable();

http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);

http.httpBasic().disable()
.authorizeRequests()
.antMatchers("/api/users/**").permitAll()
.antMatchers(HttpMethod.GET, "/**").permitAll()

.anyRequest().authenticated()
.and()
.addFilterBefore(new JwtAuthFilter(jwtUtil),
UsernamePasswordAuthenticationFilter.class);
.addFilterBefore(new JwtAuthFilter(jwtUtil),UsernamePasswordAuthenticationFilter.class);
http.cors();

return http.build();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@

@Getter
@Builder
public class ErrorResponse {
public class
ErrorResponse {

private final int statusCode;
private final String message;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@ public enum StatusMsgCode {
//
// /* 409 CONFLICT : Resource์˜ ํ˜„์žฌ ์ƒํƒœ์™€ ์ถฉ๋Œ, ๋ณดํ†ต ์ค‘๋ณต๋œ ๋ฐ์ดํ„ฐ ์กด์žฌ */
DUPLICATE_RESOURCE(HttpStatus.CONFLICT, "๋ฐ์ดํ„ฐ๊ฐ€ ์ด๋ฏธ ์กด์žฌํ•ฉ๋‹ˆ๋‹ค."),
ALREADY_CLICKED_LIKE(HttpStatus.CONFLICT, "์ด๋ฏธ ์ข‹์•„์š”๋ฅผ ๋ˆŒ๋ €์Šต๋‹ˆ๋‹ค"),
ALREADY_CANCEL_LIKE(HttpStatus.CONFLICT, "์ด๋ฏธ ์ข‹์•„์š” ์ทจ์†Œ๋ฅผ ๋ˆŒ๋ €์Šต๋‹ˆ๋‹ค"),

//
// /* 500 INTERNAL_SERVER_ERROR */
// INTERNAL_SERVER_ERROR(HttpStatus.INTERNAL_SERVER_ERROR, "์„œ๋ฒ„๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค.");
Expand All @@ -40,7 +43,10 @@ public enum StatusMsgCode {
LIKE(HttpStatus.OK, "์ข‹์•„์š” ์„ฑ๊ณต"),
CANCEL_LIKE(HttpStatus.OK, "์ข‹์•„์š” ์ทจ์†Œ"),
DELETE_POST(HttpStatus.OK, "๊ฒŒ์‹œ๊ธ€์„ ์‚ญ์ œํ•˜์˜€์Šต๋‹ˆ๋‹ค"),
DELETE_COMMENT(HttpStatus.OK, "๋Œ“๊ธ€์„ ์‚ญ์ œํ•˜์˜€์Šต๋‹ˆ๋‹ค");
DONE_POST(HttpStatus.OK, "์ˆ™์†Œ ๋“ฑ๋ก ์™„๋ฃŒ"),
DELETE_COMMENT(HttpStatus.OK, "๋Œ“๊ธ€์„ ์‚ญ์ œํ•˜์˜€์Šต๋‹ˆ๋‹ค"),
NICKNAME(HttpStatus.OK, "์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ๋‹‰๋„ค์ž„์ž…๋‹ˆ๋‹ค."),
EMAIL(HttpStatus.OK, "์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ์ด๋ฉ”์ผ์ž…๋‹ˆ๋‹ค.");


private final HttpStatus httpStatus;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package com.cloneweek.hanghaebnb.common.s3;

import com.amazonaws.auth.AWSStaticCredentialsProvider;
import com.amazonaws.auth.BasicAWSCredentials;
import com.amazonaws.services.s3.AmazonS3Client;
import com.amazonaws.services.s3.AmazonS3ClientBuilder;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class AmazonS3Config {

@Value("${cloud.aws.credentials.accessKey}") //S3 accessKey
private String accessKey;

@Value("${cloud.aws.credentials.secretKey}") //S3 secretKey
private String secretKey;

@Value("${cloud.aws.region.static}") //S3 region
private String region;

@Bean
public AmazonS3Client amazonS3Client() {
BasicAWSCredentials awsCredentials = new BasicAWSCredentials(accessKey, secretKey);

return (AmazonS3Client) AmazonS3ClientBuilder.standard()
.withRegion(region)
.withCredentials(new AWSStaticCredentialsProvider(awsCredentials))
.build();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package com.cloneweek.hanghaebnb.common.s3;

import com.cloneweek.hanghaebnb.common.security.UserDetailsImpl;
import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestPart;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.http.MediaType;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.List;

@RequiredArgsConstructor
@RestController
@RequestMapping("/api")
public class AmazonS3Controller {

private final AmazonS3Service s3Service;

// @PostMapping(value = "/upload", consumes = {MediaType.MULTIPART_FORM_DATA_VALUE})
// public String uploadImage(@RequestPart List<MultipartFile> imagelist,
// @AuthenticationPrincipal UserDetailsImpl userDetails) throws IOException{
// s3Service.upload(imagelist,"static",userDetails.getUser());
// return "success";
// }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
package com.cloneweek.hanghaebnb.common.s3;

import com.amazonaws.services.s3.AmazonS3Client;
import com.amazonaws.services.s3.model.CannedAccessControlList;
import com.amazonaws.services.s3.model.DeleteObjectRequest;
import com.amazonaws.services.s3.model.PutObjectRequest;
import com.cloneweek.hanghaebnb.entity.ImageFile;
import com.cloneweek.hanghaebnb.entity.Room;
import com.cloneweek.hanghaebnb.entity.User;
import com.cloneweek.hanghaebnb.repository.ImageFileRepository;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.List;
import java.util.Optional;
import java.util.UUID;

@Slf4j
@Component
@RequiredArgsConstructor
@Service
public class AmazonS3Service {


private final AmazonS3Client amazonS3Client;
private final ImageFileRepository imageFileRepository;

@Value("${cloud.aws.s3.bucket}") //bucket ์ด๋ฆ„
public String bucket;


public void upload(List<MultipartFile> multipartFilelist, String dirName, Room room, User user) throws IOException {

for (MultipartFile multipartFile : multipartFilelist){
if (multipartFile != null){
File uploadFile = convert(multipartFile).orElseThrow(() -> new IllegalArgumentException("ํŒŒ์ผ ์ „ํ™˜ ์‹คํŒจ"));
ImageFile imageFile = new ImageFile(upload(uploadFile, dirName), user,room); //url, user, room ์ •๋ณด ์ €์žฅ
imageFileRepository.save(imageFile);
}
}
}

// S3๋กœ ํŒŒ์ผ ์—…๋กœ๋“œํ•˜๊ธฐ
private String upload(File uploadFile, String dirName) {
String fileName = dirName + "/" + UUID.randomUUID(); // S3์— ์ €์žฅ๋œ ํŒŒ์ผ ์ด๋ฆ„
String uploadImageUrl = putS3(uploadFile, fileName); // s3๋กœ ์—…๋กœ๋“œ
removeNewFile(uploadFile);
return uploadImageUrl;
}

// S3๋กœ ์—…๋กœ๋“œ
private String putS3(File uploadFile, String fileName) {
amazonS3Client.putObject(new PutObjectRequest(bucket, fileName, uploadFile).withCannedAcl(CannedAccessControlList.PublicRead));
return amazonS3Client.getUrl(bucket, fileName).toString();
}


// ๋กœ์ปฌ์— ์ €์žฅ๋œ ์ด๋ฏธ์ง€ ์ง€์šฐ๊ธฐ
private void removeNewFile(File targetFile) {
if (targetFile.delete()) {
log.info("File delete success");
return;
}
log.info("File delete fail");
}

private Optional<File> convert(MultipartFile multipartFile) throws IOException {
// File convertFile = new File(System.getProperty("user.dir") + "/" + multipartFile.getOriginalFilename()); //์ด์ „์ฝ”๋“œ 12.23 11:37
File convertFile = new File(multipartFile.getOriginalFilename());
// ๋ฐ”๋กœ ์œ„์—์„œ ์ง€์ •ํ•œ ๊ฒฝ๋กœ์— File์ด ์ƒ์„ฑ๋จ (๊ฒฝ๋กœ๊ฐ€ ์ž˜๋ชป๋˜์—ˆ๋‹ค๋ฉด ์ƒ์„ฑ ๋ถˆ๊ฐ€๋Šฅ)
if (convertFile.createNewFile()) {
try (FileOutputStream fos = new FileOutputStream(convertFile)) { // FileOutputStream ๋ฐ์ดํ„ฐ๋ฅผ ํŒŒ์ผ์— ๋ฐ”์ดํŠธ ์ŠคํŠธ๋ฆผ์œผ๋กœ ์ €์žฅํ•˜๊ธฐ ์œ„ํ•จ
fos.write(multipartFile.getBytes());
}
return Optional.of(convertFile);
}

return Optional.empty();
}

// find image from s3
public String getThumbnailPath(String path) {
return amazonS3Client.getUrl(bucket, path).toString();
}

//remove s3 object
public void deleteFile(String fileName){
DeleteObjectRequest request = new DeleteObjectRequest(bucket, fileName);
amazonS3Client.deleteObject(request);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,13 @@
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.List;

@RestController
Expand All @@ -21,23 +24,48 @@
public class RoomController {
private final RoomService roomService;

@PostMapping("/rooms")
public ResponseEntity<RoomResponseDto> createRoom(@RequestBody RoomRequestDto requestDto, @AuthenticationPrincipal UserDetailsImpl userDetails) {
return ResponseEntity.ok(roomService.createRoom(requestDto, userDetails.getUser()));
//์ˆ™์†Œ ๋“ฑ๋ก
@PostMapping(value = "/rooms",consumes = {MediaType.APPLICATION_JSON_VALUE, MediaType.MULTIPART_FORM_DATA_VALUE})
public ResponseEntity<ResponseMsgDto> createRoom(@RequestPart(value = "data") RoomRequestDto requestDto,
@RequestPart(value = "file") List<MultipartFile> multipartFilelist,
@AuthenticationPrincipal UserDetailsImpl userDetails) throws IOException {
return ResponseEntity.ok(roomService.createRoom(requestDto, userDetails.getUser(),multipartFilelist));
}

//์ˆ™์†Œ ์ „์ฒด ์กฐํšŒ
@GetMapping("/rooms")
public ResponseEntity<Page<Room>> getRooms(Pageable pageable) { // size /api/rooms?page=0&size=3
return ResponseEntity.ok(roomService.getRooms(pageable));
public ResponseEntity<Page<Room>> getRooms(@AuthenticationPrincipal UserDetailsImpl userDetails, Pageable pageable) { // size /api/rooms?page=0&size=3
return ResponseEntity.ok(roomService.getRooms(pageable, userDetails.getUser()));
}

//์ˆ™์ˆ˜ ์ •๋ณด ์ˆ˜์ •
@CrossOrigin
@PatchMapping("/rooms/{roomId}")
public ResponseEntity<RoomResponseDto> updateRoom(@PathVariable Long roomId, @RequestBody RoomRequestDto requestDto, @AuthenticationPrincipal UserDetailsImpl userDetails) {
return ResponseEntity.ok(roomService.update(roomId, requestDto, userDetails.getUser()));
public ResponseEntity<RoomResponseDto> updateRoom(@PathVariable Long roomId,
@RequestPart(value = "data") RoomRequestDto requestDto,
@RequestPart(value = "file") List<MultipartFile> multipartFilelist,
@AuthenticationPrincipal UserDetailsImpl userDetails) throws IOException {
return ResponseEntity.ok(roomService.update(roomId, requestDto, userDetails.getUser(),multipartFilelist));
}

@DeleteMapping("rooms/{roomId}")
//์ˆ™์†Œ ์‚ญ์ œ
@DeleteMapping("/rooms/{roomId}")
public ResponseEntity<ResponseMsgDto> deleteRoom(@PathVariable Long roomId, @AuthenticationPrincipal UserDetailsImpl userDetails) {
return ResponseEntity.ok(roomService.delete(roomId, userDetails.getUser()));
}
// ์ˆ™์†Œ ์ข‹์•„์š”
@PostMapping("/rooms/{roomId}/like")
public ResponseEntity<ResponseMsgDto> saveLike(
@PathVariable Long roomId,
@AuthenticationPrincipal UserDetailsImpl userDetails) {
return ResponseEntity.ok().body(roomService.saveLike(roomId, userDetails.getUser()));
}

// ๊ฒŒ์‹œ๊ธ€ ์ข‹์•„์š” ์ทจ์†Œ
@DeleteMapping("/rooms/{roomId}/like")
public ResponseEntity<ResponseMsgDto> cancelLike(
@PathVariable Long roomId,
@AuthenticationPrincipal UserDetailsImpl userDetails) {
return ResponseEntity.ok().body(roomService.cancelLike(roomId, userDetails.getUser()));
}
}
Original file line number Diff line number Diff line change
@@ -1,17 +1,16 @@
package com.cloneweek.hanghaebnb.controller;

import com.cloneweek.hanghaebnb.common.exception.StatusMsgCode;
import com.cloneweek.hanghaebnb.dto.LoginRequestDto;
import com.cloneweek.hanghaebnb.dto.ResponseMsgDto;
import com.cloneweek.hanghaebnb.dto.SignupRequestDto;
import com.cloneweek.hanghaebnb.service.UserService;
import lombok.RequiredArgsConstructor;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
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;

import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;

Expand All @@ -26,28 +25,28 @@ public class UserController {
@PostMapping("/signup")
public ResponseEntity<ResponseMsgDto> signup(@RequestBody @Valid SignupRequestDto dto) {
userService.signup(dto);
return ResponseEntity.ok(new ResponseMsgDto(HttpStatus.OK.value(), "ํšŒ์›๊ฐ€์ž… ์„ฑ๊ณต!"));
return ResponseEntity.ok(new ResponseMsgDto(StatusMsgCode.SIGN_UP));
}

// ๋กœ๊ทธ์ธ
@PostMapping("/login")
public ResponseEntity<ResponseMsgDto> login(@RequestBody LoginRequestDto dto, HttpServletResponse response) {
userService.login(dto, response);
return ResponseEntity.ok(new ResponseMsgDto(HttpStatus.OK.value(), "๋กœ๊ทธ์ธ ์„ฑ๊ณต!"));
return ResponseEntity.ok(new ResponseMsgDto(StatusMsgCode.LOG_IN));
}

// ์ด๋ฉ”์ผ ์ค‘๋ณต ํ™•์ธ
@PostMapping("/email-check")
public ResponseEntity<ResponseMsgDto> idCheck(@RequestBody @Valid SignupRequestDto dto) {
userService.emailCheck(dto);
return ResponseEntity.ok(new ResponseMsgDto(HttpStatus.OK.value(), "์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ์ด๋ฉ”์ผ์ž…๋‹ˆ๋‹ค."));
return ResponseEntity.ok(new ResponseMsgDto(StatusMsgCode.EMAIL));
}

// ๋‹‰๋„ค์ž„ ์ค‘๋ณต ํ™•์ธ
@PostMapping("/nick-check")
public ResponseEntity<ResponseMsgDto> nickCheck(@RequestBody SignupRequestDto dto) {
userService.nickCheck(dto);
return ResponseEntity.ok(new ResponseMsgDto(HttpStatus.OK.value(), "์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ๋‹‰๋„ค์ž„์ž…๋‹ˆ๋‹ค."));
return ResponseEntity.ok(new ResponseMsgDto(StatusMsgCode.NICKNAME));
}

}
Expand Down
11 changes: 8 additions & 3 deletions src/main/java/com/cloneweek/hanghaebnb/dto/ResponseMsgDto.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package com.cloneweek.hanghaebnb.dto;

import com.cloneweek.hanghaebnb.common.exception.StatusMsgCode;
import lombok.Getter;
import lombok.NoArgsConstructor;
import org.springframework.http.HttpStatus;

@Getter
@NoArgsConstructor
Expand All @@ -10,11 +12,14 @@ public class ResponseMsgDto {
private int statusCode;
private String message;

public ResponseMsgDto(int statusCode) {
this.statusCode = statusCode;
}
public ResponseMsgDto(int statusCode, String message) {
this.statusCode = statusCode;
this.message = message;
}

public ResponseMsgDto(StatusMsgCode statusMsgCode){
this.statusCode = statusMsgCode.getHttpStatus().value();
this.message = statusMsgCode.getDetail();

}
}
Loading

0 comments on commit cca7d2b

Please sign in to comment.