Skip to content
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
Expand Up @@ -2,7 +2,9 @@

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableScheduling;

@EnableScheduling
@SpringBootApplication
public class SolidConnectionApplication {

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.example.solidconnection.auth.controller;

import com.example.solidconnection.auth.dto.SignUpRequestDto;
import com.example.solidconnection.auth.dto.SignUpResponseDto;
import com.example.solidconnection.auth.dto.kakao.KakaoCodeDto;
import com.example.solidconnection.auth.dto.kakao.KakaoOauthResponseDto;
import com.example.solidconnection.auth.service.AuthService;
Expand All @@ -9,10 +10,7 @@
import com.example.solidconnection.custom.response.DataResponse;
import com.example.solidconnection.custom.response.StatusResponse;
import lombok.RequiredArgsConstructor;
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 org.springframework.web.bind.annotation.*;

import java.security.Principal;

Expand All @@ -31,13 +29,19 @@ public CustomResponse kakaoOauth(@RequestBody KakaoCodeDto kakaoCodeDto) {

@PostMapping("/sign-up")
public CustomResponse signUp(@RequestBody SignUpRequestDto signUpRequestDto) {
boolean status = authService.signUp(signUpRequestDto);
return new StatusResponse(status);
SignUpResponseDto signUpResponseDto = authService.signUp(signUpRequestDto);
return new DataResponse<>(signUpResponseDto);
}

@PostMapping("/sign-out")
public CustomResponse signOut(Principal principal) {
boolean status = authService.signOut(principal.getName());
return new StatusResponse(status);
}

@PatchMapping("/quit")
public CustomResponse quit(Principal principal) {
boolean status = authService.quit(principal.getName());
return new StatusResponse(status);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package com.example.solidconnection.auth.dto;

import lombok.*;

@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class SignUpResponseDto {
private String accessToken;
private String refreshToken;
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,24 @@


import com.example.solidconnection.auth.dto.SignUpRequestDto;
import com.example.solidconnection.auth.dto.SignUpResponseDto;
import com.example.solidconnection.config.token.TokenService;
import com.example.solidconnection.config.token.TokenType;
import com.example.solidconnection.config.token.TokenValidator;
import com.example.solidconnection.country.CountryRepository;
import com.example.solidconnection.country.InterestedCountyRepository;
import com.example.solidconnection.custom.exception.CustomException;
import com.example.solidconnection.entity.*;
import com.example.solidconnection.region.InterestedRegionRepository;
import com.example.solidconnection.region.RegionRepository;
import com.example.solidconnection.repositories.CountryRepository;
import com.example.solidconnection.repositories.InterestedCountyRepository;
import com.example.solidconnection.repositories.InterestedRegionRepository;
import com.example.solidconnection.repositories.RegionRepository;
import com.example.solidconnection.siteuser.repository.SiteUserRepository;
import com.example.solidconnection.type.CountryCode;
import com.example.solidconnection.type.RegionCode;
import com.example.solidconnection.type.Role;
import lombok.RequiredArgsConstructor;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
Expand All @@ -29,6 +31,7 @@
import static com.example.solidconnection.custom.exception.ErrorCode.*;

@Service
@Transactional
@RequiredArgsConstructor
public class AuthService {

Expand All @@ -41,7 +44,7 @@ public class AuthService {
private final CountryRepository countryRepository;
private final InterestedCountyRepository interestedCountyRepository;

public boolean signUp(SignUpRequestDto signUpRequestDto) {
public SignUpResponseDto signUp(SignUpRequestDto signUpRequestDto) {
tokenValidator.validateKakaoToken(signUpRequestDto.getKakaoOauthToken());
validateUserNotDuplicated(signUpRequestDto);
validateNicknameDuplicated(signUpRequestDto.getNickname());
Expand All @@ -52,7 +55,16 @@ public boolean signUp(SignUpRequestDto signUpRequestDto) {

saveInterestedRegion(signUpRequestDto, savedSiteUser);
saveInterestedCountry(signUpRequestDto, savedSiteUser);
return true;

String email = savedSiteUser.getEmail();
String accessToken = tokenService.generateToken(email, TokenType.ACCESS);
String refreshToken = tokenService.generateToken(email, TokenType.REFRESH);
tokenService.saveToken(refreshToken, TokenType.REFRESH);

return SignUpResponseDto.builder()
.accessToken(accessToken)
.refreshToken(refreshToken)
.build();
}

public boolean signOut(String email){
Expand All @@ -65,6 +77,16 @@ public boolean signOut(String email){
return true;
}

public boolean quit(String email){
SiteUser siteUser = getValidatedUser(email);
siteUser.setQuitedAt(LocalDate.now().plusDays(1));
return true;
}

private SiteUser getValidatedUser(String email){
return siteUserRepository.findByEmail(email).orElseThrow(() -> new CustomException(USER_NOT_FOUND));
}

private void validateUserNotDuplicated(SignUpRequestDto signUpRequestDto){
String email = tokenService.getEmail(signUpRequestDto.getKakaoOauthToken());
if(siteUserRepository.existsByEmail(email)){
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,13 @@
import com.example.solidconnection.config.token.TokenService;
import com.example.solidconnection.config.token.TokenType;
import com.example.solidconnection.custom.exception.CustomException;
import com.example.solidconnection.entity.SiteUser;
import com.example.solidconnection.siteuser.repository.SiteUserRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.*;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.util.UriComponentsBuilder;

Expand All @@ -18,6 +20,7 @@
import static com.example.solidconnection.custom.exception.ErrorCode.*;

@Service
@Transactional
@RequiredArgsConstructor
public class KakaoOAuthService {

Expand All @@ -40,6 +43,7 @@ public KakaoOauthResponseDto processOauth(String code) throws CustomException {
String email = kakaoUserInfoDto.getKakaoAccount().getEmail();
boolean isAlreadyRegistered = siteUserRepository.existsByEmail(email);
if (isAlreadyRegistered) {
resetQuitedAt(email);
return kakaoSignIn(email);
}
String kakaoOauthToken = tokenService.generateToken(email, TokenType.KAKAO_OAUTH);
Expand Down Expand Up @@ -103,4 +107,9 @@ private SignInResponseDto kakaoSignIn(String email) {
.refreshToken(refreshToken)
.build();
}

public void resetQuitedAt(String email){
SiteUser siteUser = siteUserRepository.findByEmail(email).orElseThrow(() -> new CustomException(USER_NOT_FOUND));
siteUser.setQuitedAt(null);
}
}
15 changes: 8 additions & 7 deletions src/main/java/com/example/solidconnection/entity/SiteUser.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,9 @@
import com.example.solidconnection.type.PreparationStatus;
import com.example.solidconnection.type.Role;
import jakarta.persistence.*;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.*;

import java.time.LocalDateTime;
import java.time.LocalDate;
import java.util.Set;

@Entity
Expand All @@ -26,9 +23,11 @@ public class SiteUser {
private String email;

@Column(nullable = false, length = 100)
@Setter
private String nickname;

@Column(length = 500)
@Setter
private String profileImageUrl;

@Column(nullable = false, length = 20)
Expand All @@ -46,9 +45,11 @@ public class SiteUser {
@Enumerated(EnumType.STRING)
private Gender gender;

private LocalDateTime nicknameModifiedAt;
@Setter
private LocalDate nicknameModifiedAt;

private LocalDateTime quitedAt;
@Setter
private LocalDate quitedAt;

// 연관관계
@OneToMany(mappedBy = "siteUser")
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.example.solidconnection.country;
package com.example.solidconnection.repositories;

import com.example.solidconnection.entity.Country;
import com.example.solidconnection.type.CountryCode;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.example.solidconnection.country;
package com.example.solidconnection.repositories;

import com.example.solidconnection.entity.InterestedCountry;
import org.springframework.data.jpa.repository.JpaRepository;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.example.solidconnection.region;
package com.example.solidconnection.repositories;

import com.example.solidconnection.entity.InterestedRegion;
import org.springframework.data.jpa.repository.JpaRepository;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.example.solidconnection.region;
package com.example.solidconnection.repositories;

import com.example.solidconnection.entity.Region;
import com.example.solidconnection.type.RegionCode;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package com.example.solidconnection.scheduler;

import com.example.solidconnection.siteuser.service.SiteUserService;
import lombok.RequiredArgsConstructor;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

@Component
@RequiredArgsConstructor
public class UserRemovalScheduler {
private final SiteUserService siteUserService;

@Scheduled(cron = "0 0 0 * * ?") // 매일 자정에 실행
public void scheduledUserRemoval() {
siteUserService.deleteUsersNeverVisitedAfterQuited();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,20 @@

import com.example.solidconnection.entity.SiteUser;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;

import java.time.LocalDate;
import java.util.List;
import java.util.Optional;

@Repository
public interface SiteUserRepository extends JpaRepository<SiteUser, Long> {
Optional<SiteUser> findByEmail(String email);
boolean existsByEmail(String email);
boolean existsByNickname(String nickname);

@Query("SELECT u FROM SiteUser u WHERE u.quitedAt <= :cutoffDate")
List<SiteUser> findUsersToBeRemoved(@Param("cutoffDate") LocalDate cutoffDate);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package com.example.solidconnection.siteuser.service;

import com.example.solidconnection.entity.SiteUser;
import com.example.solidconnection.siteuser.repository.SiteUserRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

import java.time.LocalDate;
import java.util.List;

@Service
@RequiredArgsConstructor
public class SiteUserService {
private final SiteUserRepository siteUserRepository;

public void deleteUsersNeverVisitedAfterQuited() {
LocalDate cutoffDate = LocalDate.now().minusDays(30);
List<SiteUser> usersToRemove = siteUserRepository.findUsersToBeRemoved(cutoffDate);
siteUserRepository.deleteAll(usersToRemove);
}
}