Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix: 회원탈퇴 Hard Delete & 슬랙 알림 발송 #352

Merged
merged 10 commits into from
Apr 9, 2024
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,6 @@ public interface OwnerAttachmentRepository extends Repository<OwnerAttachment, L
OwnerAttachment save(OwnerAttachment ownerAttachment);

OwnerAttachment findById(Long id);

void deleteByOwnerId(Long ownerId);
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,6 @@ default Owner getById(Long ownerId) {
Owner save(Owner owner);

Optional<Owner> findByCompanyRegistrationNumber(String companyRegistrationNumber);

void deleteByUserId(Long userId);
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@
@Entity
@Table(name = "users")
@Where(clause = "is_deleted=0")
@SQLDelete(sql = "UPDATE users SET is_deleted = true WHERE id = ?")
@NoArgsConstructor(access = PROTECTED)
public class User extends BaseEntity {

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package in.koreatech.koin.domain.user.model;

public record UserDeleteEvent(
String email
) {

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package in.koreatech.koin.domain.user.model;

import static org.springframework.transaction.event.TransactionPhase.AFTER_COMMIT;

import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.event.TransactionalEventListener;

import in.koreatech.koin.global.domain.slack.SlackClient;
import in.koreatech.koin.global.domain.slack.model.SlackNotificationFactory;
import lombok.RequiredArgsConstructor;

@Component
@RequiredArgsConstructor
@Transactional(propagation = Propagation.REQUIRES_NEW)
public class UserEventListener {

private final SlackClient slackClient;
private final SlackNotificationFactory slackNotificationFactory;

@TransactionalEventListener(phase = AFTER_COMMIT)
public void onUserDeleteEvent(UserDeleteEvent event) {
var notification = slackNotificationFactory.generateUserDeleteNotification(event.email());
slackClient.sendMessage(notification);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,6 @@ default Student getById(Long userId) {
return findById(userId)
.orElseThrow(() -> UserNotFoundException.withDetail("userId: " + userId));
}

void deleteByUserId(Long userId);
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,13 @@
import java.util.Objects;
import java.util.UUID;

import org.springframework.context.ApplicationEventPublisher;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import in.koreatech.koin.domain.owner.repository.OwnerAttachmentRepository;
import in.koreatech.koin.domain.owner.repository.OwnerRepository;
import in.koreatech.koin.domain.user.dto.AuthResponse;
import in.koreatech.koin.domain.user.dto.EmailCheckExistsRequest;
import in.koreatech.koin.domain.user.dto.NicknameCheckExistsRequest;
Expand All @@ -16,7 +19,9 @@
import in.koreatech.koin.domain.user.dto.UserTokenRefreshRequest;
import in.koreatech.koin.domain.user.dto.UserTokenRefreshResponse;
import in.koreatech.koin.domain.user.model.User;
import in.koreatech.koin.domain.user.model.UserDeleteEvent;
import in.koreatech.koin.domain.user.model.UserToken;
import in.koreatech.koin.domain.user.repository.StudentRepository;
import in.koreatech.koin.domain.user.repository.UserRepository;
import in.koreatech.koin.domain.user.repository.UserTokenRepository;
import in.koreatech.koin.global.auth.JwtProvider;
Expand All @@ -31,8 +36,12 @@ public class UserService {

private final JwtProvider jwtProvider;
private final UserRepository userRepository;
private final StudentRepository studentRepository;
private final OwnerRepository ownerRepository;
private final OwnerAttachmentRepository ownerAttachmentRepository;
private final PasswordEncoder passwordEncoder;
private final UserTokenRepository userTokenRepository;
private final ApplicationEventPublisher eventPublisher;

@Transactional
public UserLoginResponse login(UserLoginRequest request) {
Expand Down Expand Up @@ -80,6 +89,16 @@ private String getUserId(String refreshToken) {
public void withdraw(Long userId) {
User user = userRepository.getById(userId);
userRepository.delete(user);

switch (user.getUserType()) {
case STUDENT:
studentRepository.deleteByUserId(userId);
case OWNER:
ownerRepository.deleteByUserId(userId);
ownerAttachmentRepository.deleteByOwnerId(userId);
}
Comment on lines +91 to +97
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

EventListener에 로직 구성해주시면 좋을거같아요

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

withdraw에서 user삭제하고 학생과 주인은 Listener에서 삭제구현하려했는데, 이렇게 분리하니 자꾸 안돼서 Listener에서 전부 삭제구현했습니다.


eventPublisher.publishEvent(new UserDeleteEvent(user.getEmail()));
}

public void checkExistsEmail(EmailCheckExistsRequest request) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -106,4 +106,19 @@ public SlackNotification generateStudentRegisterCompleteNotification(
)
.build();
}

/**
* 유저 탈퇴 알림
*/
public SlackNotification generateUserDeleteNotification(
String email
) {
return SlackNotification.builder()
.slackUrl(eventNotificationUrl)
.text(String.format("""
`%s님이 탈퇴하셨습니다.`
""", email)
)
.build();
}
}
Loading