-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
a8e4af0
commit f380677
Showing
14 changed files
with
327 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
40 changes: 40 additions & 0 deletions
40
src/main/java/com/github/cokothon/common/property/AwsProperty.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
package com.github.cokothon.common.property; | ||
|
||
import org.springframework.boot.context.properties.ConfigurationProperties; | ||
import org.springframework.boot.context.properties.NestedConfigurationProperty; | ||
import org.springframework.context.annotation.Configuration; | ||
|
||
import jakarta.validation.constraints.NotBlank; | ||
import lombok.Data; | ||
|
||
@Data | ||
@Configuration | ||
@ConfigurationProperties(prefix = "cloud.aws") | ||
public class AwsProperty { | ||
|
||
@NotBlank | ||
private String region; | ||
|
||
@NestedConfigurationProperty | ||
private S3 s3; | ||
|
||
@NestedConfigurationProperty | ||
private Credential credential; | ||
|
||
@Data | ||
public static class S3 { | ||
|
||
@NotBlank | ||
private String bucket; | ||
} | ||
|
||
@Data | ||
public static class Credential { | ||
|
||
@NotBlank | ||
private String accessKey; | ||
|
||
@NotBlank | ||
private String secretKey; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
package com.github.cokothon.common.s3; | ||
|
||
import org.springframework.context.annotation.Bean; | ||
import org.springframework.context.annotation.Configuration; | ||
|
||
import com.amazonaws.auth.AWSCredentials; | ||
import com.amazonaws.auth.AWSCredentialsProvider; | ||
import com.amazonaws.auth.AWSStaticCredentialsProvider; | ||
import com.amazonaws.auth.BasicAWSCredentials; | ||
import com.amazonaws.services.s3.AmazonS3Client; | ||
import com.amazonaws.services.s3.AmazonS3ClientBuilder; | ||
import com.github.cokothon.common.property.AwsProperty; | ||
|
||
import lombok.RequiredArgsConstructor; | ||
|
||
@Configuration | ||
@RequiredArgsConstructor | ||
public class S3Config { | ||
|
||
private final AwsProperty awsProperty; | ||
|
||
@Bean | ||
public AWSCredentialsProvider awsCredentials() { | ||
AWSCredentials awsCredentials = new BasicAWSCredentials(awsProperty.getCredential().getAccessKey(), awsProperty.getCredential().getSecretKey()); | ||
return new AWSStaticCredentialsProvider(awsCredentials); | ||
} | ||
|
||
@Bean | ||
public AmazonS3Client amazonS3Client() { | ||
return (AmazonS3Client) AmazonS3ClientBuilder.standard() | ||
.withRegion(awsProperty.getRegion()) | ||
.withCredentials(awsCredentials()) | ||
.build(); | ||
} | ||
} |
49 changes: 49 additions & 0 deletions
49
src/main/java/com/github/cokothon/common/s3/S3Service.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
package com.github.cokothon.common.s3; | ||
|
||
import java.io.IOException; | ||
import java.io.InputStream; | ||
|
||
import org.springframework.stereotype.Component; | ||
import org.springframework.web.multipart.MultipartFile; | ||
|
||
import com.amazonaws.services.s3.AmazonS3Client; | ||
import com.amazonaws.services.s3.model.CannedAccessControlList; | ||
import com.amazonaws.services.s3.model.ObjectMetadata; | ||
import com.amazonaws.services.s3.model.PutObjectRequest; | ||
import com.github.cokothon.common.property.AwsProperty; | ||
|
||
import lombok.RequiredArgsConstructor; | ||
import lombok.SneakyThrows; | ||
|
||
@Component | ||
@RequiredArgsConstructor | ||
public class S3Service { | ||
|
||
private final AwsProperty awsProperty; | ||
private final AmazonS3Client amazonS3Client; | ||
|
||
@SneakyThrows(IOException.class) | ||
public String uploadFile(String key, MultipartFile file) { | ||
|
||
ObjectMetadata objectMetadata = new ObjectMetadata(); | ||
objectMetadata.setContentType(file.getContentType()); | ||
objectMetadata.setContentLength(file.getSize()); | ||
|
||
return uploadFile(key, file.getInputStream(), objectMetadata); | ||
} | ||
|
||
public String uploadFile(String key, InputStream inputStream, ObjectMetadata objectMetadata) { | ||
|
||
PutObjectRequest putObjectRequest = new PutObjectRequest(awsProperty.getS3().getBucket(), key, inputStream, objectMetadata) | ||
.withCannedAcl(CannedAccessControlList.PublicRead); | ||
|
||
amazonS3Client.putObject(putObjectRequest); | ||
|
||
return "https://" + awsProperty.getS3().getBucket() + ".s3." + awsProperty.getRegion() + ".amazonaws.com/" + key; | ||
} | ||
|
||
public void deleteFile(String key) { | ||
|
||
amazonS3Client.deleteObject(awsProperty.getS3().getBucket(), key); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
72 changes: 72 additions & 0 deletions
72
src/main/java/com/github/cokothon/domain/user/controller/UserController.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
package com.github.cokothon.domain.user.controller; | ||
|
||
import org.springframework.security.access.prepost.PreAuthorize; | ||
import org.springframework.web.bind.annotation.DeleteMapping; | ||
import org.springframework.web.bind.annotation.PutMapping; | ||
import org.springframework.web.bind.annotation.RequestBody; | ||
import org.springframework.web.bind.annotation.RequestMapping; | ||
import org.springframework.web.bind.annotation.RequestPart; | ||
import org.springframework.web.bind.annotation.RestController; | ||
import org.springframework.web.multipart.MultipartFile; | ||
|
||
import com.github.cokothon.common.api.dto.response.ApiResponse; | ||
import com.github.cokothon.common.security.util.UserContext; | ||
import com.github.cokothon.domain.user.dto.request.ChangeInfoRequest; | ||
import com.github.cokothon.domain.user.dto.request.ChangePasswordRequest; | ||
import com.github.cokothon.domain.user.schema.User; | ||
import com.github.cokothon.domain.user.service.UserService; | ||
|
||
import jakarta.validation.Valid; | ||
import lombok.RequiredArgsConstructor; | ||
|
||
@RestController | ||
@RequestMapping("/user") | ||
@RequiredArgsConstructor | ||
public class UserController { | ||
|
||
private final UserService userService; | ||
|
||
@PutMapping("/my/info") | ||
@PreAuthorize("isAuthenticated()") | ||
public ApiResponse<Void> changeInfo(@RequestBody @Valid ChangeInfoRequest request) { | ||
|
||
User user = UserContext.getUser(); | ||
|
||
userService.changeInfo(user, request); | ||
|
||
return ApiResponse.ok(); | ||
} | ||
|
||
@PutMapping("/my/password") | ||
@PreAuthorize("isAuthenticated()") | ||
public ApiResponse<Void> changePassword(@RequestBody @Valid ChangePasswordRequest request) { | ||
|
||
User user = UserContext.getUser(); | ||
|
||
userService.changePassword(user, request); | ||
|
||
return ApiResponse.ok(); | ||
} | ||
|
||
@PutMapping("/my/avatar") | ||
@PreAuthorize("isAuthenticated()") | ||
public ApiResponse<Void> changeAvatar(@RequestPart("avatar") MultipartFile avatar) { | ||
|
||
User user = UserContext.getUser(); | ||
|
||
userService.changeAvatar(user, avatar); | ||
|
||
return ApiResponse.ok(); | ||
} | ||
|
||
@DeleteMapping("/my/avatar") | ||
@PreAuthorize("isAuthenticated()") | ||
public ApiResponse<Void> deleteAvatar() { | ||
|
||
User user = UserContext.getUser(); | ||
|
||
userService.deleteAvatar(user); | ||
|
||
return ApiResponse.ok(); | ||
} | ||
} |
10 changes: 10 additions & 0 deletions
10
src/main/java/com/github/cokothon/domain/user/dto/request/ChangeInfoRequest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
package com.github.cokothon.domain.user.dto.request; | ||
|
||
import jakarta.validation.constraints.NotBlank; | ||
|
||
public record ChangeInfoRequest( | ||
|
||
@NotBlank | ||
String nickname | ||
) { | ||
} |
15 changes: 15 additions & 0 deletions
15
src/main/java/com/github/cokothon/domain/user/dto/request/ChangePasswordRequest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
package com.github.cokothon.domain.user.dto.request; | ||
|
||
import jakarta.validation.constraints.NotBlank; | ||
import jakarta.validation.constraints.Pattern; | ||
|
||
public record ChangePasswordRequest( | ||
|
||
@NotBlank | ||
String password, | ||
|
||
@NotBlank | ||
@Pattern(regexp = "^(?=.*[a-zA-Z])(?=.*\\d)\\S{8,}$") | ||
String newPassword | ||
) { | ||
} |
13 changes: 13 additions & 0 deletions
13
src/main/java/com/github/cokothon/domain/user/exception/AvatarNotImageException.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
package com.github.cokothon.domain.user.exception; | ||
|
||
import org.springframework.http.HttpStatus; | ||
|
||
import com.github.cokothon.common.api.exception.ApiException; | ||
|
||
public class AvatarNotImageException extends ApiException { | ||
|
||
public AvatarNotImageException() { | ||
|
||
super(HttpStatus.BAD_REQUEST, "프로필 사진이 이미지 파일이 아닙니다."); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -22,6 +22,8 @@ public class User extends BaseSchema { | |
|
||
private String nickname; | ||
|
||
private String avatar; | ||
|
||
private int level; | ||
} | ||
|
76 changes: 76 additions & 0 deletions
76
src/main/java/com/github/cokothon/domain/user/service/UserService.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
package com.github.cokothon.domain.user.service; | ||
|
||
import org.springframework.security.authentication.AuthenticationManager; | ||
import org.springframework.security.core.Authentication; | ||
import org.springframework.security.crypto.password.PasswordEncoder; | ||
import org.springframework.stereotype.Service; | ||
import org.springframework.web.multipart.MultipartFile; | ||
|
||
import com.github.cokothon.common.s3.S3Service; | ||
import com.github.cokothon.common.security.authentication.UserAuthentication; | ||
import com.github.cokothon.domain.user.dto.request.ChangeInfoRequest; | ||
import com.github.cokothon.domain.user.dto.request.ChangePasswordRequest; | ||
import com.github.cokothon.domain.user.exception.AvatarNotImageException; | ||
import com.github.cokothon.domain.user.repository.UserRepository; | ||
import com.github.cokothon.domain.user.schema.User; | ||
|
||
import lombok.RequiredArgsConstructor; | ||
|
||
@Service | ||
@RequiredArgsConstructor | ||
public class UserService { | ||
|
||
private final UserRepository userRepository; | ||
private final S3Service s3Service; | ||
|
||
private final AuthenticationManager authenticationManager; | ||
private final PasswordEncoder passwordEncoder; | ||
|
||
public void changeInfo(User user, ChangeInfoRequest dto) { | ||
|
||
String nickname = dto.nickname(); | ||
|
||
user.setNickname(nickname); | ||
|
||
userRepository.save(user); | ||
} | ||
|
||
public void changePassword(User user, ChangePasswordRequest dto) { | ||
|
||
String password = dto.password(); | ||
String newPassword = dto.newPassword(); | ||
|
||
UserAuthentication authentication = new UserAuthentication(user, password); | ||
Authentication authenticate = authenticationManager.authenticate(authentication); | ||
|
||
assert authenticate.isAuthenticated(); | ||
|
||
user.setPassword(passwordEncoder.encode(newPassword)); | ||
|
||
userRepository.save(user); | ||
} | ||
|
||
public void changeAvatar(User user, MultipartFile avatar) { | ||
|
||
if (avatar.getOriginalFilename() == null || avatar.getContentType() != null && !avatar.getContentType().startsWith("image")) { | ||
|
||
throw new AvatarNotImageException(); | ||
} | ||
|
||
String extension = avatar.getOriginalFilename().substring(avatar.getOriginalFilename().lastIndexOf(".") + 1); | ||
String avatarUrl = s3Service.uploadFile("avatar/%s.%s".formatted(user.getId(), extension), avatar); | ||
|
||
user.setAvatar(avatarUrl); | ||
|
||
userRepository.save(user); | ||
} | ||
|
||
public void deleteAvatar(User user) { | ||
|
||
s3Service.deleteFile(user.getAvatar().split("amazonaws.com/")[1]); | ||
|
||
user.setAvatar(null); | ||
|
||
userRepository.save(user); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
cloud: | ||
aws: | ||
region: ap-northeast-2 | ||
s3: | ||
bucket: cokothon | ||
credential: | ||
accessKey: accessKey | ||
secretKey: secretKey |