Skip to content

Commit

Permalink
Merge pull request #188 from prgrms-web-devcourse-final-project/develop
Browse files Browse the repository at this point in the history
develop to main
  • Loading branch information
yeonsu00 authored Dec 9, 2024
2 parents 4bdeadd + 043facc commit e0bfeac
Show file tree
Hide file tree
Showing 16 changed files with 120 additions and 6 deletions.
1 change: 1 addition & 0 deletions .github/workflows/cd.yml
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ jobs:
# Slack 환경변수
SLACK_TOKEN: ${{ secrets.SLACK_TOKEN }}


steps:
- name: 코드 가져오기
uses: actions/checkout@v4
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ jobs:
# Slack 환경변수
SLACK_TOKEN: ${{ secrets.SLACK_TOKEN }}


steps:
- name: 코드 가져오기
uses: actions/checkout@v4
Expand Down
1 change: 1 addition & 0 deletions src/main/java/postman/bottler/config/SecurityConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Excepti
.requestMatchers("/auth/**").permitAll()
.requestMatchers("/oauth/**").permitAll()
.requestMatchers("/user/signup").permitAll()
.requestMatchers("/user/developer").permitAll()
.requestMatchers("/user/duplicate-check/**").permitAll()
.requestMatchers("/user/email/**").permitAll()
.requestMatchers("/map/guest/**").permitAll()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ public enum ErrorStatus {
DUPLICATE_REPLY_LETTER(HttpStatus.BAD_REQUEST, "REPLY_LETTER4002"),
LETTER_AUTHOR_MISMATCH(HttpStatus.BAD_REQUEST, "LETTER4004"),
UNAUTHORIZED_LETTER_ACCESS(HttpStatus.UNAUTHORIZED, "LETTER4010"),
DEVELOPER_LETTER(HttpStatus.BAD_REQUEST, "LETTER4005"),

// 추천 에러
TEMP_RECOMMENDATIONS_NOT_FOUND(HttpStatus.NOT_FOUND, "TEMP_RECOMMENDATIONS_4040"),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
import postman.bottler.letter.exception.LetterNotFoundException;
import postman.bottler.letter.exception.TempRecommendationsNotFoundException;
import postman.bottler.letter.service.LetterBoxService;
import postman.bottler.letter.service.LetterService;
import postman.bottler.letter.service.LetterServiceRedis;
import postman.bottler.notification.dto.request.RecommendNotificationRequestDTO;

@Service
Expand All @@ -26,14 +26,20 @@ public class RedisLetterService {
private final RedisTemplate<String, List<Long>> redisTemplate;
private final LetterBoxService letterBoxService;
private static final int MAX_RECOMMENDATIONS = 3;
private final LetterService letterService;
private final LetterServiceRedis letterService;

@Transactional
public void saveRecommendationsTemp(Long userId, List<Long> recommendations) {
String key = RedisLetterKeyUtil.getTempRecommendationKey(userId);
redisTemplate.opsForValue().set(key, recommendations);
}

@Transactional
public void saveDeveloperLetter(Long userId, List<Long> recommendations) {
String key = RedisLetterKeyUtil.getActiveRecommendationKey(userId);
redisTemplate.opsForValue().set(key, recommendations);
}

@Transactional
public RecommendNotificationRequestDTO updateRecommendationsFromTemp(Long userId) {
String tempKey = RedisLetterKeyUtil.getTempRecommendationKey(userId);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import jakarta.validation.Valid;
import java.util.List;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.DeleteMapping;
Expand Down Expand Up @@ -43,6 +44,7 @@ public class LetterController {
private final RedisLetterService redisLetterService;
private final LetterBoxService letterBoxService;


@Operation(
summary = "키워드 편지 생성",
description = "새로운 키워드 편지를 생성합니다."
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package postman.bottler.letter.exception;

public class DeveloperLetterException extends RuntimeException {
public DeveloperLetterException(String message) {
super(message);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -131,4 +131,10 @@ public ResponseEntity<ApiResponse<String>> handleUnauthorizedLetterAccessExcepti
.status(UNAUTHORIZED_LETTER_ACCESS.getHttpStatus())
.body(ApiResponse.onFailure(UNAUTHORIZED_LETTER_ACCESS.getCode(), e.getMessage(), null));
}

@ExceptionHandler(DeveloperLetterException.class)
public ApiResponse<?> handleDeveloperLetterException(DeveloperLetterException e) {
log.error(e.getMessage());
return ApiResponse.onFailure(ErrorStatus.DEVELOPER_LETTER.getCode(), e.getMessage(), null);
}
}
10 changes: 10 additions & 0 deletions src/main/java/postman/bottler/letter/service/LetterService.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
import postman.bottler.letter.dto.request.LetterRequestDTO;
import postman.bottler.letter.dto.response.LetterDetailResponseDTO;
import postman.bottler.letter.dto.response.LetterRecommendHeadersResponseDTO;
import postman.bottler.letter.exception.DeveloperLetterException;
import postman.bottler.letter.exception.LetterAuthorMismatchException;
import postman.bottler.letter.exception.LetterNotFoundException;
import postman.bottler.notification.dto.request.NotificationLabelRequestDTO;
Expand All @@ -36,6 +37,15 @@ public Letter createLetter(LetterRequestDTO letterRequestDTO, Long userId) {
return letter;
}

@Transactional
public void createDeveloperLetter(LetterRequestDTO letterRequestDTO, Long userId) {
List<String> keywords = letterRequestDTO.keywords();
if (keywords.size() == 1 && "개발자편지".equals(keywords.get(0))) {
throw new DeveloperLetterException("개발자 편지에는 개발자편지 키워드만 추가할 수 있습니다.");
}
letterRepository.save(letterRequestDTO.toDomain(userId));
}

@Transactional
public void deleteLetters(List<Long> letterIds, Long userId) {
letterIds.forEach(letterId -> {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package postman.bottler.letter.service;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import postman.bottler.letter.domain.Letter;
import postman.bottler.letter.exception.LetterNotFoundException;

@Slf4j
@Service
@RequiredArgsConstructor
public class LetterServiceRedis {

private final LetterRepository letterRepository;

@Transactional(readOnly = true)
public Letter findLetter(Long letterId) {
return letterRepository.findById(letterId)
.orElseThrow(() -> new LetterNotFoundException("키워드 편지가 존재하지 않습니다."));
}

public boolean checkLetterExists(Long letterId) {
return letterRepository.checkLetterExists(letterId);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,14 @@ public ApiResponse<String> verifyEmail(@Valid @RequestBody AuthEmailRequestDTO a
return ApiResponse.onSuccess("이메일 인증을 성공했습니다.");
}

@Operation(summary = "개발자 계정 생성", description = "개발자 계정 생성")
@PostMapping("/developer")
public ApiResponse<String> createDeveloper(@Valid @RequestBody SignUpRequestDTO signUpRequestDTO, BindingResult bindingResult) {
validateRequestDTO(bindingResult);
userService.createDeveloper(signUpRequestDTO.email(), signUpRequestDTO.password(), signUpRequestDTO.nickname());
return ApiResponse.onCreateSuccess("개발자 회원가입 성공");
}

private void validateRequestDTO(BindingResult bindingResult) {
if (bindingResult.hasErrors()) {
bindingResult.getFieldErrors().forEach(error -> {
Expand Down
3 changes: 2 additions & 1 deletion src/main/java/postman/bottler/user/domain/Role.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,6 @@

public enum Role {
USER, // 일반 유저
BAN_USER // 정지된 사용자
BAN_USER, // 정지된 사용자
DEVELOPER // 개발자
}
17 changes: 17 additions & 0 deletions src/main/java/postman/bottler/user/domain/User.java
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,19 @@ private User(String email, String nickname, String imageUrl, String password, Pr
this.warningCount = 0;
}

private User(String email, String password, String nickname, String imageUrl, Role role) {
this.email = email;
this.password = password;
this.nickname = nickname;
this.imageUrl = imageUrl;
this.role = role;
this.provider = Provider.LOCAL;
this.createdAt = LocalDateTime.now();
this.updatedAt = LocalDateTime.now();
this.isDeleted = false;
this.warningCount = 0;
}

public static User createUser(Long userId, String email, String password, String nickname, String imageUrl,
Role role, Provider provider, LocalDateTime createdAt, LocalDateTime updatedAt,
boolean isDeleted, int warningCount) {
Expand All @@ -76,6 +89,10 @@ public static User createKakaoUser(String email, String nickname, String imageUr
return new User(email, nickname, imageUrl, password, Provider.KAKAO);
}

public static User createDeveloper(String email, String password, String nickname, String imageUrl) { //개발자 계정
return new User(email, password, nickname, imageUrl, Role.DEVELOPER);
}

public void updateWarningCount() {
this.warningCount++;
this.updatedAt = LocalDateTime.now();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,9 @@ public class UserRepositoryImpl implements UserRepository {
private final UserJpaRepository userJpaRepository;

@Override
public void save(User user) {
userJpaRepository.save(UserEntity.from(user));
public User save(User user) {
UserEntity userEntity = userJpaRepository.save(UserEntity.from(user));
return UserEntity.toUser(userEntity);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
import postman.bottler.user.domain.User;

public interface UserRepository {
void save(User user);
User save(User user);
boolean existsByEmail(String email);
boolean existsByNickname(String nickname);
User findByEmail(String email);
Expand Down
26 changes: 26 additions & 0 deletions src/main/java/postman/bottler/user/service/UserService.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,11 @@

import jakarta.mail.MessagingException;
import java.security.SecureRandom;
import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Random;
import java.util.Set;
import java.util.stream.Collectors;
import lombok.RequiredArgsConstructor;
import org.springframework.security.authentication.BadCredentialsException;
Expand All @@ -13,6 +17,7 @@
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import postman.bottler.keyword.service.RedisLetterService;
import postman.bottler.notification.domain.NotificationType;
import postman.bottler.notification.service.NotificationService;
import postman.bottler.slack.SlackConstant;
Expand Down Expand Up @@ -48,6 +53,7 @@ public class UserService {
private final EmailService emailService;
private final SlackService slackService;
private final NotificationService notificationService;
private final RedisLetterService redisLetterService;

private static final String CHARACTERS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
private static final int CODE_LENGTH = 8;
Expand All @@ -57,6 +63,26 @@ public class UserService {
public void createUser(String email, String password, String nickname) {
String profileImageUrl = profileImageRepository.findProfileImage();
User user = User.createUser(email, passwordEncoder.encode(password), nickname, profileImageUrl);
User storedUser = userRepository.save(user);
redisLetterService.saveDeveloperLetter(storedUser.getUserId(), findRandomDevelopLetter());
}

private List<Long> findRandomDevelopLetter() {
Random random = new Random();
Set<Long> randomNumbers = new LinkedHashSet<>();

while (randomNumbers.size() < 3) {
long number = 1L + random.nextInt(8);
randomNumbers.add(number);
}

return new ArrayList<>(randomNumbers);
}

@Transactional
public void createDeveloper(String email, String password, String nickname) {
String profileImageUrl = profileImageRepository.findProfileImage();
User user = User.createDeveloper(email, passwordEncoder.encode(password), nickname, profileImageUrl);
userRepository.save(user);
}

Expand Down

0 comments on commit e0bfeac

Please sign in to comment.