-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #10 from BBack-BBoo-Team/사용자_로그인_회원가입_시혁
[서버] 사용자 정보 조회 및 저장 API
- Loading branch information
Showing
13 changed files
with
409 additions
and
16 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
package com.book.app.infra.config; | ||
|
||
import org.springframework.context.annotation.Configuration; | ||
import org.springframework.data.jpa.repository.config.EnableJpaAuditing; | ||
|
||
@EnableJpaAuditing | ||
@Configuration | ||
public class JpaConfig { | ||
|
||
} |
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,73 @@ | ||
package com.book.app.modules.account; | ||
|
||
import jakarta.persistence.*; | ||
import lombok.AccessLevel; | ||
import lombok.Getter; | ||
import lombok.NoArgsConstructor; | ||
import lombok.ToString; | ||
import org.springframework.data.annotation.CreatedDate; | ||
import org.springframework.data.jpa.domain.support.AuditingEntityListener; | ||
import org.springframework.format.annotation.DateTimeFormat; | ||
|
||
import java.time.LocalDateTime; | ||
import java.util.Objects; | ||
|
||
@ToString | ||
@Getter | ||
@EntityListeners(AuditingEntityListener.class) | ||
@NoArgsConstructor(access = AccessLevel.PROTECTED) | ||
@Table(name = "ACCOUNT") | ||
@Entity | ||
public class Account { | ||
|
||
@Id | ||
@Column(name = "ACCOUNT_ID") | ||
@GeneratedValue(strategy = GenerationType.IDENTITY) | ||
private Long id; | ||
|
||
@Column(name = "UID", unique = true, updatable = false, nullable = false) | ||
private String uid; // Supabase 제공 | ||
|
||
@Column(name = "EMAIL", unique = true, nullable = false, length = 100) | ||
private String email; | ||
|
||
@Column(name = "NICKNAME", unique = true, nullable = false, length = 20) | ||
private String nickname; | ||
|
||
@DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) | ||
@CreatedDate | ||
@Column(name = "JOIN_AT", nullable = false, updatable = false) | ||
private LocalDateTime joinAt; | ||
|
||
@Column(name = "PROFILE_IMG") | ||
private String profileImg; | ||
|
||
private Account(String uid, String email, String nickname) { | ||
this.uid = uid; | ||
this.email = email; | ||
this.nickname = nickname; | ||
} | ||
|
||
public static Account of(String uid, String email, String nickname) { | ||
return new Account(uid, email, nickname); | ||
} | ||
|
||
@Override | ||
public boolean equals(Object o) { | ||
if (this == o) return true; | ||
if (!(o instanceof Account account)) return false; | ||
return id != null && id.equals(account.id); | ||
} | ||
|
||
@Override | ||
public int hashCode() { | ||
return Objects.hash(id); | ||
} | ||
|
||
public String getProfileImg() { | ||
return this.profileImg == null | ||
? "" | ||
: this.profileImg; | ||
} | ||
} | ||
|
46 changes: 46 additions & 0 deletions
46
src/main/java/com/book/app/modules/account/AccountController.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,46 @@ | ||
package com.book.app.modules.account; | ||
|
||
import com.book.app.modules.account.dto.AccountInfoDto; | ||
import com.book.app.modules.account.dto.SignUpDto; | ||
import com.book.app.modules.account.service.AccountService; | ||
import com.book.app.modules.global.response.SuccessResponseDto; | ||
import jakarta.validation.Valid; | ||
import lombok.RequiredArgsConstructor; | ||
import lombok.extern.slf4j.Slf4j; | ||
import org.springframework.http.HttpStatus; | ||
import org.springframework.http.ResponseEntity; | ||
import org.springframework.validation.annotation.Validated; | ||
import org.springframework.web.bind.annotation.*; | ||
|
||
@Slf4j | ||
@Validated | ||
@RequiredArgsConstructor | ||
@RequestMapping("/accounts") | ||
@RestController | ||
public class AccountController { | ||
|
||
private final AccountService accountService; | ||
|
||
// 사용자 정보 저장 | ||
@PostMapping("/sign-up") | ||
public ResponseEntity<SuccessResponseDto> signUp(@RequestBody @Valid SignUpDto info) { | ||
log.info("sign-up info = {}",info); | ||
Account newAccount = accountService.saveSignUpInfo(info.toEntity()); | ||
log.info("newAccount = {}", newAccount); | ||
SuccessResponseDto<AccountInfoDto> result | ||
= new SuccessResponseDto<>("account", AccountInfoDto.from(newAccount)); | ||
return new ResponseEntity<>(result, HttpStatus.CREATED); | ||
} | ||
|
||
// 사용자 정보 조회 | ||
@GetMapping("/info/{uid}") | ||
public ResponseEntity<SuccessResponseDto> getInfoAccount(@PathVariable("uid") String uid) { | ||
log.info("uid = {}", uid); | ||
Account getAccount = accountService.getAccountByUid(uid); | ||
log.info("getAccount = {} ", getAccount); | ||
SuccessResponseDto<AccountInfoDto> result | ||
= new SuccessResponseDto<>("account", AccountInfoDto.from(getAccount)); | ||
return new ResponseEntity<>(result, HttpStatus.OK); | ||
} | ||
|
||
} |
12 changes: 12 additions & 0 deletions
12
src/main/java/com/book/app/modules/account/AccountRepository.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,12 @@ | ||
package com.book.app.modules.account; | ||
|
||
import org.springframework.data.jpa.repository.JpaRepository; | ||
import org.springframework.stereotype.Repository; | ||
|
||
import java.util.Optional; | ||
|
||
@Repository | ||
public interface AccountRepository extends JpaRepository<Account, Long> { | ||
Optional<Account> findByNickname(String nickname); | ||
Optional<Account> findByUid(String uid); | ||
} |
42 changes: 42 additions & 0 deletions
42
src/main/java/com/book/app/modules/account/dto/AccountInfoDto.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,42 @@ | ||
package com.book.app.modules.account.dto; | ||
|
||
import com.book.app.modules.account.Account; | ||
import com.fasterxml.jackson.annotation.JsonProperty; | ||
import lombok.*; | ||
|
||
import java.time.LocalDateTime; | ||
|
||
/** | ||
* 단일 사용자 데이터 | ||
* @uid : Supabase에서 제공하는 사용자 식별자 | ||
* @email : 로그인을 위한 이메일 | ||
* @nickname : 사용자 별칭 | ||
* @joinAt : DB 저장 날짜 및 시간 | ||
* @profileImg : 프로필 이미지. null 이라면, length 0인 문자열 "" 반환 | ||
*/ | ||
@Getter | ||
@Builder | ||
@AllArgsConstructor | ||
@NoArgsConstructor(access = AccessLevel.PROTECTED) | ||
public class AccountInfoDto { | ||
|
||
private String uid; | ||
private String email; | ||
private String nickname; | ||
|
||
@JsonProperty("join_at") | ||
private LocalDateTime joinAt; | ||
|
||
@JsonProperty("profile_img") | ||
private String profileImg; | ||
|
||
public static AccountInfoDto from(Account account) { | ||
return AccountInfoDto.builder() | ||
.uid(account.getUid()) | ||
.email(account.getEmail()) | ||
.nickname(account.getNickname()) | ||
.joinAt(account.getJoinAt()) | ||
.profileImg(account.getProfileImg()) | ||
.build(); | ||
} | ||
} |
40 changes: 40 additions & 0 deletions
40
src/main/java/com/book/app/modules/account/dto/SignUpDto.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.book.app.modules.account.dto; | ||
|
||
import com.book.app.modules.account.Account; | ||
import jakarta.validation.constraints.Email; | ||
import jakarta.validation.constraints.NotBlank; | ||
import jakarta.validation.constraints.Pattern; | ||
import lombok.*; | ||
import org.hibernate.validator.constraints.Length; | ||
|
||
/** | ||
* 회원가입 데이터 | ||
* @uid : Supabase에서 제공하는 사용자 식별자 | ||
* @email : 로그인을 위한 이메일 | ||
* @nickname : 사용자 별칭 | ||
*/ | ||
@ToString | ||
@Getter | ||
@AllArgsConstructor | ||
@NoArgsConstructor(access = AccessLevel.PROTECTED) | ||
public class SignUpDto { | ||
|
||
@NotBlank(message = "uid를 입력해주세요.") | ||
private String uid; | ||
|
||
@Email(message = "이메일 형식에 맞춰주세요.") | ||
@NotBlank(message = "이메일을 입력해주세요.") | ||
private String email; | ||
|
||
/** | ||
* 2~20자 길이의 한글, 영어(대소문자), 숫자(0-9) 만 허용 | ||
*/ | ||
@NotBlank(message = "닉네임을 입력해주세요.") | ||
@Length(min = 2, max = 20, message = "닉네임 길이는 2자 이상 20자 이하로 작성해주세요.") | ||
@Pattern(regexp = "^[ㄱ-ㅎ가-힣A-Za-z0-9]{2,20}$", message = "닉네임은 한글, 영어(대소문자), 숫자만 허용하며 2자에서 20자 사이어야 합니다.") | ||
private String nickname; | ||
|
||
public Account toEntity() { | ||
return Account.of(this.uid, this.email, this.nickname); | ||
} | ||
} |
22 changes: 22 additions & 0 deletions
22
src/main/java/com/book/app/modules/account/service/AccountService.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,22 @@ | ||
package com.book.app.modules.account.service; | ||
|
||
import com.book.app.modules.account.Account; | ||
|
||
/** | ||
* 사용자 CRUD에 해당하는 기능을 포함합니다. | ||
*/ | ||
public interface AccountService { | ||
|
||
/** | ||
* 회원가입을 하는 사용자의 정보(uid, email, nickname)를 DB에 저장합니다. | ||
* 중복된 닉네임이 있는지 검증합니다. | ||
*/ | ||
Account saveSignUpInfo(Account account); | ||
|
||
/** | ||
* uid에 해당하는 사용자 정보 조회 | ||
* @param uid | ||
* @return Account | ||
*/ | ||
Account getAccountByUid(String uid); | ||
} |
36 changes: 36 additions & 0 deletions
36
src/main/java/com/book/app/modules/account/service/AccountServiceImpl.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,36 @@ | ||
package com.book.app.modules.account.service; | ||
|
||
import com.book.app.modules.account.Account; | ||
import com.book.app.modules.account.AccountRepository; | ||
import lombok.RequiredArgsConstructor; | ||
import org.springframework.data.crossstore.ChangeSetPersister; | ||
import org.springframework.stereotype.Service; | ||
import org.springframework.transaction.annotation.Transactional; | ||
|
||
import java.util.NoSuchElementException; | ||
|
||
@RequiredArgsConstructor | ||
@Transactional(readOnly = true) | ||
@Service | ||
public class AccountServiceImpl implements AccountService { | ||
|
||
private final AccountRepository accountRepository; | ||
|
||
@Override | ||
@Transactional | ||
public Account saveSignUpInfo(Account account) { | ||
verifyExistsNickname(account); | ||
return accountRepository.save(account); | ||
} | ||
|
||
@Override | ||
public Account getAccountByUid(String uid) { | ||
return accountRepository.findByUid(uid).orElseThrow(() -> new NoSuchElementException("uid에 해당하는 사용자를 찾을 수 없습니다.")); | ||
} | ||
|
||
private void verifyExistsNickname(Account account) { | ||
accountRepository.findByNickname(account.getNickname()).ifPresent(e -> { | ||
throw new IllegalArgumentException("중복된 닉네임입니다."); | ||
}); | ||
} | ||
} |
19 changes: 19 additions & 0 deletions
19
src/main/java/com/book/app/modules/global/response/SuccessResponseDto.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,19 @@ | ||
package com.book.app.modules.global.response; | ||
|
||
import lombok.Getter; | ||
import lombok.NoArgsConstructor; | ||
|
||
@Getter | ||
@NoArgsConstructor | ||
public class SuccessResponseDto<T> { | ||
|
||
private String status; | ||
private String domain; | ||
private T data; | ||
|
||
public SuccessResponseDto(String domain, T data) { | ||
this.status = "success"; | ||
this.domain = domain; | ||
this.data = data; | ||
} | ||
} |
15 changes: 0 additions & 15 deletions
15
src/test/java/com/book/app/SebadogBookServerApplicationTests.java
This file was deleted.
Oops, something went wrong.
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,20 @@ | ||
package com.book.app.infra; | ||
|
||
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; | ||
import org.springframework.boot.test.context.SpringBootTest; | ||
import org.springframework.test.context.ActiveProfiles; | ||
import org.springframework.transaction.annotation.Transactional; | ||
|
||
import java.lang.annotation.ElementType; | ||
import java.lang.annotation.Retention; | ||
import java.lang.annotation.RetentionPolicy; | ||
import java.lang.annotation.Target; | ||
|
||
@Retention(RetentionPolicy.RUNTIME) | ||
@Target(ElementType.TYPE) | ||
@ActiveProfiles("test") | ||
@Transactional | ||
@SpringBootTest | ||
@AutoConfigureMockMvc | ||
public @interface MockMvcTest { | ||
} |
Oops, something went wrong.