Skip to content

Commit

Permalink
Merge pull request #78 from Tune-Fun/feature/account/email
Browse files Browse the repository at this point in the history
Feature/account/email
  • Loading branch information
habinkim authored Jun 1, 2024
2 parents d2b1675 + 3681d51 commit b36925a
Show file tree
Hide file tree
Showing 34 changed files with 724 additions and 261 deletions.
54 changes: 42 additions & 12 deletions src/docs/asciidoc/account-api.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,6 @@ operation::logout-success[snippets='http-request,http-response,request-fields,re

operation::refresh-success[snippets='http-request,http-response,request-fields,response-fields']

=== 이메일 중복확인 API

==== 성공

operation::check-email-duplicate-success[snippets='http-request,http-response,query-parameters,response-fields']

==== 실패

operation::check-email-duplicate-failed[snippets='http-request,http-response,query-parameters,response-fields']
Expand All @@ -45,26 +39,62 @@ operation::check-username-duplicate-success[snippets='http-request,http-response

operation::check-username-duplicate-success-failed[snippets='http-request,http-response']

=== 비밀번호 찾기 OTP 전송 API

==== 성공

operation::send-forgot-password-otp-success[snippets='http-request,http-response,request-fields,response-fields']

=== 비밀번호 재설정 API

==== 성공

operation::set-new-password-success[snippets='http-request,http-response,request-fields,response-fields']

=== 닉네임 변경 API

==== 성공

operation::update-nickname-success[snippets='http-request,http-response,request-fields,response-fields'

== Email API

=== 이메일 중복확인 API

==== 성공

operation::check-email-duplicate-success[snippets='http-request,http-response,query-parameters,response-fields']

==== 실패

operation::check-email-duplicate-failed[snippets='http-request,http-response,query-parameters,response-fields']

=== 이메일 인증여부 확인 API

==== 성공

operation::check-email-verified-success[snippets='http-request,http-response,response-fields']

=== 비밀번호 찾기 OTP 전송 API
=== 이메일 등록 API

==== 성공

operation::send-forgot-password-otp-success[snippets='http-request,http-response,request-fields,response-fields']
operation::register-email-success[snippets='http-request,http-response,request-fields,response-fields']

=== 비밀번호 재설정 API
=== 이메일 인증번호 발송 API

==== 성공

operation::set-new-password-success[snippets='http-request,http-response,request-fields,response-fields']
operation::verify-email-success[snippets='http-request,http-response,response-fields']

=== 닉네임 변경 API
=== 이메일 변경 API

==== 성공

operation::change-email-success[snippets='http-request,http-response,request-fields,response-fields']

=== 이메일 해제 API

==== 성공

operation::update-nickname-success[snippets='http-request,http-response,request-fields,response-fields']
operation::unlink-email-success[snippets='http-request,http-response,response-fields']

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
package com.tune_fun.v1.account.adapter.input.rest;

import com.tune_fun.v1.account.application.port.input.command.AccountCommands;
import com.tune_fun.v1.account.application.port.input.usecase.email.*;
import com.tune_fun.v1.account.domain.value.CurrentUser;
import com.tune_fun.v1.common.config.Uris;
import com.tune_fun.v1.common.hexagon.WebAdapter;
import com.tune_fun.v1.common.response.BasePayload;
import com.tune_fun.v1.common.response.Response;
import com.tune_fun.v1.common.response.ResponseMapper;
import jakarta.validation.Valid;
import jakarta.validation.constraints.NotBlank;
import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.security.core.userdetails.User;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import static com.tune_fun.v1.common.response.MessageCode.SUCCESS_EMAIL_UNIQUE;
import static com.tune_fun.v1.common.response.MessageCode.SUCCESS_EMAIL_VERIFIED;

@RestController
@WebAdapter
@Validated
@RequiredArgsConstructor
public class EmailController {

private final CheckEmailDuplicateUseCase checkEmailDuplicateUseCase;
private final CheckEmailVerifiedUseCase checkEmailVerifiedUseCase;

private final RegisterEmailUseCase registerEmailUseCase;
private final VerifyEmailUseCase verifyEmailUseCase;
private final ChangeEmailUseCase changeEmailUseCase;
private final UnlinkEmailUseCase unlinkEmailUseCase;

private final ResponseMapper responseMapper;

@GetMapping(value = Uris.CHECK_EMAIL_DUPLICATE)
public ResponseEntity<Response<BasePayload>> checkUsernameDuplicate(@RequestParam(name = "email")
@NotBlank(message = "{email.not_blank}") final String email) {
checkEmailDuplicateUseCase.checkEmailDuplicate(email);
return responseMapper.ok(SUCCESS_EMAIL_UNIQUE);
}

@GetMapping(value = Uris.CHECK_EMAIL_VERIFIED)
public ResponseEntity<Response<BasePayload>> checkEmailVerified(@CurrentUser User user) {
checkEmailVerifiedUseCase.checkEmailVerified(user);
return responseMapper.ok(SUCCESS_EMAIL_VERIFIED);
}

@PostMapping(value = Uris.EMAIL_ROOT)
public ResponseEntity<?> registerEmail(@Valid @RequestBody AccountCommands.SaveEmail command, @CurrentUser User user) throws Exception {
registerEmailUseCase.registerEmail(command, user);
return responseMapper.ok();
}

@PostMapping(value = Uris.VERIFY_EMAIL)
public ResponseEntity<?> verifyEmail(@CurrentUser User user) throws Exception {
verifyEmailUseCase.verifyEmail(user);
return responseMapper.ok();
}

@PatchMapping(value = Uris.EMAIL_ROOT)
public ResponseEntity<?> changeEmail(@Valid @RequestBody AccountCommands.SaveEmail command, @CurrentUser User user) {
changeEmailUseCase.changeEmail(command, user);
return responseMapper.ok();
}

@DeleteMapping(value = Uris.EMAIL_ROOT)
public ResponseEntity<?> unlinkEmail(@CurrentUser User user) {
unlinkEmailUseCase.unlinkEmail(user);
return responseMapper.ok();
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,6 @@ public class AccountJpaEntity extends BaseEntity implements UserDetails {
@Comment("비밀번호")
private String password;

@NotNull
@Column(name = "email", length = 2000)
@Comment("이메일")
private String email;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
public class AccountPersistenceAdapter implements
LoadAccountPort, SaveAccountPort,
SaveOAuth2AccountPort, DisableOAuth2AccountPort,
DeleteAccountPort,
DeleteAccountPort, SaveEmailPort,
RecordLastLoginAtPort, RecordEmailVerifiedAtPort,
UpdatePasswordPort, UpdateNicknamePort {

Expand Down Expand Up @@ -73,12 +73,29 @@ public void deleteAll() {
accountRepository.deleteAll();
}

@Override
public void saveEmail(final String email, final String username) {
loadAccountByUsername(username)
.ifPresent(account -> {
AccountJpaEntity updatedAccount = account.toBuilder().email(email).build();
accountRepository.save(updatedAccount);
});
}

@Override
public void clearEmail(String username) {
loadAccountByUsername(username)
.ifPresent(account -> {
AccountJpaEntity updatedAccount = account.toBuilder().email(null).build();
accountRepository.save(updatedAccount);
});
}

@Override
public void recordLastLoginAt(final String username) {
loadAccountByUsername(username)
.ifPresent(account -> {
AccountJpaEntity updatedAccount = account.toBuilder()
.lastLoginAt(LocalDateTime.now()).build();
AccountJpaEntity updatedAccount = account.toBuilder().lastLoginAt(LocalDateTime.now()).build();
accountRepository.save(updatedAccount);
});
}
Expand All @@ -87,8 +104,16 @@ public void recordLastLoginAt(final String username) {
public void recordEmailVerifiedAt(final String username) {
loadAccountByUsername(username)
.ifPresent(account -> {
AccountJpaEntity updatedAccount = account.toBuilder()
.emailVerifiedAt(LocalDateTime.now()).build();
AccountJpaEntity updatedAccount = account.toBuilder().emailVerifiedAt(LocalDateTime.now()).build();
accountRepository.save(updatedAccount);
});
}

@Override
public void clearEmailVerifiedAt(final String username) {
loadAccountByUsername(username)
.ifPresent(account -> {
AccountJpaEntity updatedAccount = account.toBuilder().emailVerifiedAt(null).build();
accountRepository.save(updatedAccount);
});
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,4 +72,8 @@ public record SetNewPassword(@NotBlank(message = "{new_password.not_blank}") Str
public record UpdateNickname(@NotBlank(message = "{new_nickname.not_blank}") String newNickname) {
}

@JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class)
public record SaveEmail(@NotBlank(message = "{email.not_blank}") String email) {
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package com.tune_fun.v1.account.application.port.input.usecase.email;

import com.tune_fun.v1.account.application.port.input.command.AccountCommands;
import org.springframework.security.core.userdetails.User;

@FunctionalInterface
public interface ChangeEmailUseCase {
void changeEmail(final AccountCommands.SaveEmail command, final User user);
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.tune_fun.v1.account.application.port.input.usecase;
package com.tune_fun.v1.account.application.port.input.usecase.email;

@FunctionalInterface
public interface CheckEmailDuplicateUseCase {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.tune_fun.v1.account.application.port.input.usecase;
package com.tune_fun.v1.account.application.port.input.usecase.email;

import org.springframework.security.core.userdetails.User;

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.tune_fun.v1.account.application.port.input.usecase.email;

import com.tune_fun.v1.account.application.port.input.command.AccountCommands;
import org.springframework.security.core.userdetails.User;

@FunctionalInterface
public interface RegisterEmailUseCase {

void registerEmail(final AccountCommands.SaveEmail command, final User user) throws Exception;

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.tune_fun.v1.account.application.port.input.usecase.email;

import org.springframework.security.core.userdetails.User;

public interface UnlinkEmailUseCase {
void unlinkEmail(final User user);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package com.tune_fun.v1.account.application.port.input.usecase.email;

import org.springframework.security.core.userdetails.User;

@FunctionalInterface
public interface VerifyEmailUseCase {
void verifyEmail(final User user) throws Exception;
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,6 @@

public interface RecordEmailVerifiedAtPort {
void recordEmailVerifiedAt(final String username);

void clearEmailVerifiedAt(final String username);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.tune_fun.v1.account.application.port.output;

public interface SaveEmailPort {
void saveEmail(final String email, final String username);

void clearEmail(final String username);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package com.tune_fun.v1.account.application.service.email;

import com.tune_fun.v1.account.application.port.input.command.AccountCommands;
import com.tune_fun.v1.account.application.port.input.usecase.email.ChangeEmailUseCase;
import com.tune_fun.v1.account.application.port.output.RecordEmailVerifiedAtPort;
import com.tune_fun.v1.account.application.port.output.SaveEmailPort;
import com.tune_fun.v1.common.hexagon.UseCase;
import lombok.RequiredArgsConstructor;
import org.springframework.security.core.userdetails.User;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
@UseCase
@RequiredArgsConstructor
public class ChangeEmailService implements ChangeEmailUseCase {

private final SaveEmailPort saveEmailPort;
private final RecordEmailVerifiedAtPort recordEmailVerifiedAtPort;

@Transactional
@Override
public void changeEmail(final AccountCommands.SaveEmail command, final User user) {
saveEmailPort.saveEmail(command.email(), user.getUsername());
recordEmailVerifiedAtPort.clearEmailVerifiedAt(user.getUsername());
}
}
Loading

0 comments on commit b36925a

Please sign in to comment.