-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* refactor: 도메인 이름을 user에서 member로 변경 * feat: 회원 도메인 구현 * test: 회원 테스트 작성 * refactor: `.gitkeep` 삭제 * chore: 시큐리티 의존성 추가 * feat: 시큐리티 설정 추가 * fix: 전역 응답객체와 호환되기 위해 String에서 임시 응답객체로 변경 * feat: 멤버 레포지터리 추가 * feat: 임시 UserDetail 추가 * refactor: 시큐리티 패키지로 이동 * feat: PrincipalDetails 구현 * fix: 에러코드 생성자 수정 * feat: 멤버 레포지터리 추가 * style: 포매팅 적용 * feat: 시큐리티 유틸리티 구현 * feat: 멤버 유틸리티 구현 * refactor: gitkeep 삭제 * feat: 에러코드 추가 * fix: 미수정 코드 제거 * test: 멤버 유틸리티 테스트 추가 * style: 포매팅 적용 * fix: 오타 수정 * test: 임시 회원 삽입 테스트 * style: 포매팅 수정 * refactor: gitkeep 삭제 * refactor: 빌더를 사용하도록 변경 * fix: 빌더 접근제어 설정 추가 * refactor: 기본 생성자 접근제어 수정 * docs: TODO 추가 * style: 포매팅 수정 * docs: 주석 수정
- Loading branch information
Showing
23 changed files
with
383 additions
and
5 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
File renamed without changes.
File renamed without changes.
6 changes: 6 additions & 0 deletions
6
src/main/java/com/depromeet/domain/member/dao/MemberRepository.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,6 @@ | ||
package com.depromeet.domain.member.dao; | ||
|
||
import com.depromeet.domain.member.domain.Member; | ||
import org.springframework.data.jpa.repository.JpaRepository; | ||
|
||
public interface MemberRepository extends JpaRepository<Member, Long> {} |
57 changes: 57 additions & 0 deletions
57
src/main/java/com/depromeet/domain/member/domain/Member.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,57 @@ | ||
package com.depromeet.domain.member.domain; | ||
|
||
import com.depromeet.domain.common.model.BaseTimeEntity; | ||
import jakarta.persistence.*; | ||
import java.time.LocalDateTime; | ||
import lombok.AccessLevel; | ||
import lombok.Builder; | ||
import lombok.Getter; | ||
import lombok.NoArgsConstructor; | ||
|
||
@Getter | ||
@Entity | ||
@NoArgsConstructor(access = AccessLevel.PROTECTED) | ||
public class Member extends BaseTimeEntity { | ||
|
||
@Id | ||
@GeneratedValue(strategy = GenerationType.IDENTITY) | ||
@Column(name = "member_id") | ||
private Long id; | ||
|
||
@Embedded private Profile profile; | ||
|
||
@Enumerated(EnumType.STRING) | ||
private MemberStatus status; | ||
|
||
@Enumerated(EnumType.STRING) | ||
private MemberRole role; | ||
|
||
@Enumerated(EnumType.STRING) | ||
private MemberVisibility visibility; | ||
|
||
private LocalDateTime lastLoginAt; | ||
|
||
@Builder(access = AccessLevel.PRIVATE) | ||
private Member( | ||
Profile profile, | ||
MemberStatus status, | ||
MemberRole role, | ||
MemberVisibility visibility, | ||
LocalDateTime lastLoginAt) { | ||
this.profile = profile; | ||
this.status = status; | ||
this.role = role; | ||
this.visibility = visibility; | ||
this.lastLoginAt = lastLoginAt; | ||
} | ||
|
||
public static Member createNormalMember(Profile profile) { | ||
return Member.builder() | ||
.profile(profile) | ||
.status(MemberStatus.NORMAL) | ||
.role(MemberRole.USER) | ||
.visibility(MemberVisibility.PUBLIC) | ||
.lastLoginAt(LocalDateTime.now()) | ||
.build(); | ||
} | ||
} |
13 changes: 13 additions & 0 deletions
13
src/main/java/com/depromeet/domain/member/domain/MemberRole.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,13 @@ | ||
package com.depromeet.domain.member.domain; | ||
|
||
import lombok.AllArgsConstructor; | ||
import lombok.Getter; | ||
|
||
@Getter | ||
@AllArgsConstructor | ||
public enum MemberRole { | ||
USER("USER"), | ||
ADMIN("ADMIN"); | ||
|
||
private final String value; | ||
} |
14 changes: 14 additions & 0 deletions
14
src/main/java/com/depromeet/domain/member/domain/MemberStatus.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,14 @@ | ||
package com.depromeet.domain.member.domain; | ||
|
||
import lombok.AllArgsConstructor; | ||
import lombok.Getter; | ||
|
||
@Getter | ||
@AllArgsConstructor | ||
public enum MemberStatus { | ||
NORMAL("NORMAL"), | ||
DELETED("DELETED"), | ||
FORBIDDEN("FORBIDDEN"); | ||
|
||
private final String value; | ||
} |
13 changes: 13 additions & 0 deletions
13
src/main/java/com/depromeet/domain/member/domain/MemberVisibility.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,13 @@ | ||
package com.depromeet.domain.member.domain; | ||
|
||
import lombok.AllArgsConstructor; | ||
import lombok.Getter; | ||
|
||
@Getter | ||
@AllArgsConstructor | ||
public enum MemberVisibility { | ||
PUBLIC("PUBLIC"), | ||
PRIVATE("PRIVATE"); | ||
|
||
private final String value; | ||
} |
3 changes: 3 additions & 0 deletions
3
src/main/java/com/depromeet/domain/member/domain/Profile.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,3 @@ | ||
package com.depromeet.domain.member.domain; | ||
|
||
public record Profile(String nickname, String profileImageUrl) {} |
File renamed without changes.
File renamed without changes.
Empty file.
Empty file.
50 changes: 50 additions & 0 deletions
50
src/main/java/com/depromeet/global/config/security/PrincipalDetails.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,50 @@ | ||
package com.depromeet.global.config.security; | ||
|
||
import java.util.Collection; | ||
import java.util.Collections; | ||
import lombok.AllArgsConstructor; | ||
import org.springframework.security.core.GrantedAuthority; | ||
import org.springframework.security.core.authority.SimpleGrantedAuthority; | ||
import org.springframework.security.core.userdetails.UserDetails; | ||
|
||
@AllArgsConstructor | ||
public class PrincipalDetails implements UserDetails { | ||
|
||
private final Long memberId; | ||
private final String role; | ||
|
||
@Override | ||
public Collection<? extends GrantedAuthority> getAuthorities() { | ||
return Collections.singleton(new SimpleGrantedAuthority("ROLE_" + role)); | ||
} | ||
|
||
@Override | ||
public String getPassword() { | ||
return null; | ||
} | ||
|
||
@Override | ||
public String getUsername() { | ||
return memberId.toString(); | ||
} | ||
|
||
@Override | ||
public boolean isAccountNonExpired() { | ||
return true; | ||
} | ||
|
||
@Override | ||
public boolean isAccountNonLocked() { | ||
return true; | ||
} | ||
|
||
@Override | ||
public boolean isCredentialsNonExpired() { | ||
return true; | ||
} | ||
|
||
@Override | ||
public boolean isEnabled() { | ||
return true; | ||
} | ||
} |
51 changes: 51 additions & 0 deletions
51
src/main/java/com/depromeet/global/config/security/WebSecurityConfig.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,51 @@ | ||
package com.depromeet.global.config.security; | ||
|
||
import org.springframework.context.annotation.Bean; | ||
import org.springframework.context.annotation.Configuration; | ||
import org.springframework.security.config.annotation.web.builders.HttpSecurity; | ||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; | ||
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer; | ||
import org.springframework.security.web.SecurityFilterChain; | ||
import org.springframework.web.cors.CorsConfiguration; | ||
import org.springframework.web.cors.CorsConfigurationSource; | ||
import org.springframework.web.cors.UrlBasedCorsConfigurationSource; | ||
|
||
@Configuration | ||
@EnableWebSecurity | ||
public class WebSecurityConfig { | ||
|
||
@Bean | ||
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { | ||
http.csrf(AbstractHttpConfigurer::disable); | ||
|
||
http.authorizeHttpRequests( | ||
authorize -> | ||
authorize | ||
.requestMatchers("/10mm-actuator/**") | ||
.permitAll() // 액추에이터 | ||
.requestMatchers("/v1/**") | ||
.permitAll() // 임시로 모든 요청 허용 | ||
.anyRequest() | ||
.authenticated()); | ||
|
||
return http.build(); | ||
} | ||
|
||
@Bean | ||
public CorsConfigurationSource corsConfigurationSource() { | ||
CorsConfiguration configuration = new CorsConfiguration(); | ||
|
||
configuration.addAllowedOriginPattern("https://10mm.today"); | ||
|
||
// TODO: 운영환경에 따라 허용되는 도메인이 달라지도록 개선 | ||
configuration.addAllowedOriginPattern("http://localhost:3000"); | ||
|
||
configuration.addAllowedHeader("*"); | ||
configuration.addAllowedMethod("*"); | ||
configuration.setAllowCredentials(true); | ||
|
||
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); | ||
source.registerCorsConfiguration("/**", configuration); | ||
return source; | ||
} | ||
} |
7 changes: 5 additions & 2 deletions
7
src/main/java/com/depromeet/global/error/exception/CustomException.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 |
---|---|---|
@@ -1,11 +1,14 @@ | ||
package com.depromeet.global.error.exception; | ||
|
||
import lombok.AllArgsConstructor; | ||
import lombok.Getter; | ||
|
||
@Getter | ||
@AllArgsConstructor | ||
public class CustomException extends RuntimeException { | ||
|
||
private final ErrorCode errorCode; | ||
|
||
public CustomException(ErrorCode errorCode) { | ||
super(errorCode.getMessage()); | ||
this.errorCode = errorCode; | ||
} | ||
} |
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
Empty file.
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.depromeet.global.util; | ||
|
||
import com.depromeet.domain.member.dao.MemberRepository; | ||
import com.depromeet.domain.member.domain.Member; | ||
import com.depromeet.domain.member.domain.Profile; | ||
import com.depromeet.global.error.exception.CustomException; | ||
import com.depromeet.global.error.exception.ErrorCode; | ||
import lombok.RequiredArgsConstructor; | ||
import org.springframework.stereotype.Component; | ||
|
||
@Component | ||
@RequiredArgsConstructor | ||
public class MemberUtil { | ||
|
||
private final SecurityUtil securityUtil; | ||
private final MemberRepository memberRepository; | ||
|
||
// TODO: 데이터베이스 연동 및 픽스쳐 데이터 삽입 이후 삭제 | ||
private void insertMockMemberIfNotExist() { | ||
if (memberRepository.count() != 0) { | ||
return; | ||
} | ||
|
||
Member memeber = Member.createNormalMember(new Profile("testNickname", "testImageUrl")); | ||
|
||
memberRepository.save(memeber); | ||
} | ||
|
||
public Member getCurrentMember() { | ||
insertMockMemberIfNotExist(); | ||
|
||
return memberRepository | ||
.findById(securityUtil.getCurrentMemberId()) | ||
.orElseThrow(() -> new CustomException(ErrorCode.MEMBER_NOT_FOUND)); | ||
} | ||
} |
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,27 @@ | ||
package com.depromeet.global.util; | ||
|
||
import com.depromeet.global.config.security.PrincipalDetails; | ||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; | ||
import org.springframework.security.core.Authentication; | ||
import org.springframework.security.core.context.SecurityContextHolder; | ||
import org.springframework.stereotype.Component; | ||
|
||
@Component | ||
public class SecurityUtil { | ||
|
||
private void setMockAuthentication() { | ||
PrincipalDetails principal = new PrincipalDetails(1L, "USER"); | ||
Authentication authentication = | ||
new UsernamePasswordAuthenticationToken( | ||
principal, "password", principal.getAuthorities()); | ||
SecurityContextHolder.getContext().setAuthentication(authentication); | ||
} | ||
|
||
public Long getCurrentMemberId() { | ||
setMockAuthentication(); | ||
PrincipalDetails principal = | ||
(PrincipalDetails) | ||
SecurityContextHolder.getContext().getAuthentication().getPrincipal(); | ||
return Long.parseLong(principal.getUsername()); | ||
} | ||
} |
53 changes: 53 additions & 0 deletions
53
src/test/java/com/depromeet/domain/member/domain/MemberTest.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,53 @@ | ||
package com.depromeet.domain.member.domain; | ||
|
||
import static org.junit.jupiter.api.Assertions.assertEquals; | ||
|
||
import org.junit.jupiter.api.BeforeEach; | ||
import org.junit.jupiter.api.Test; | ||
|
||
class MemberTest { | ||
|
||
// Fixture | ||
Profile profile; | ||
|
||
@BeforeEach | ||
void setUp() { | ||
profile = new Profile("testNickname", "testProfileImageUrl"); | ||
} | ||
|
||
@Test | ||
void 회원가입시_초기_상태는_NORMAL이다() { | ||
// given | ||
Member member = Member.createNormalMember(profile); | ||
|
||
// when | ||
MemberStatus status = member.getStatus(); | ||
|
||
// then | ||
assertEquals(MemberStatus.NORMAL, status); | ||
} | ||
|
||
@Test | ||
void 회원가입시_초기_역할은_USER이다() { | ||
// given | ||
Member member = Member.createNormalMember(profile); | ||
|
||
// when | ||
MemberRole role = member.getRole(); | ||
|
||
// then | ||
assertEquals(MemberRole.USER, role); | ||
} | ||
|
||
@Test | ||
void 회원가입시_초기_공개여부는_PUBLIC이다() { | ||
// given | ||
Member member = Member.createNormalMember(profile); | ||
|
||
// when | ||
MemberVisibility visibility = member.getVisibility(); | ||
|
||
// then | ||
assertEquals(MemberVisibility.PUBLIC, visibility); | ||
} | ||
} |
Oops, something went wrong.