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

feat: PasswordEncoder 변경 및 DirtiesContext 삭제 #429

Merged
merged 5 commits into from
Nov 17, 2023
Merged
Show file tree
Hide file tree
Changes from 3 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 @@ -47,8 +47,8 @@ private Member(final String username, final Password password, final Provider pr
this.nickname = nickname;
}

public static Member self(final String username, final String password) {
return new Member(username, new Password(password), Provider.SELF, Nickname.random());
public static Member self(final String username, final Password password) {
return new Member(username, password, Provider.SELF, Nickname.random());
}

public static Member social(final String username, final Provider provider, final String nickname) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package com.digginroom.digginroom.domain.member;

import com.digginroom.digginroom.util.DigginRoomPasswordEncoder;
import com.digginroom.digginroom.util.PasswordEncoder;
import jakarta.persistence.Embeddable;
import lombok.AccessLevel;
import lombok.Getter;
Expand All @@ -17,15 +17,15 @@ public class Password {

private String password = EMPTY_PASSWORD;

public Password(final String password) {
this.password = DigginRoomPasswordEncoder.encode(password);
public Password(final String password, final PasswordEncoder passwordEncoder) {
this.password = passwordEncoder.encode(password);
}

public boolean doesNotMatch(final String password) {
public boolean doesNotMatch(final String password, final PasswordEncoder passwordEncoder) {
if (this.isEmpty()) {
return false;
}
return !DigginRoomPasswordEncoder.matches(password, this.password);
return !passwordEncoder.matches(password, this.password);
}

public boolean isEmpty() {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,20 +1,22 @@
package com.digginroom.digginroom.service;

import com.digginroom.digginroom.service.dto.FavoriteGenresRequest;
import com.digginroom.digginroom.service.dto.MemberDetailsResponse;
import com.digginroom.digginroom.service.dto.MemberDuplicationResponse;
import com.digginroom.digginroom.service.dto.MemberLoginRequest;
import com.digginroom.digginroom.service.dto.MemberLoginResponse;
import com.digginroom.digginroom.service.dto.MemberSaveRequest;
import com.digginroom.digginroom.domain.Genre;
import com.digginroom.digginroom.domain.member.Member;
import com.digginroom.digginroom.domain.member.Password;
import com.digginroom.digginroom.domain.member.Provider;
import com.digginroom.digginroom.exception.MemberException.DuplicationException;
import com.digginroom.digginroom.exception.MemberException.NotFoundException;
import com.digginroom.digginroom.exception.MemberException.WrongProviderException;
import com.digginroom.digginroom.oauth.IdTokenResolver;
import com.digginroom.digginroom.oauth.payload.IdTokenPayload;
import com.digginroom.digginroom.repository.MemberRepository;
import com.digginroom.digginroom.service.dto.FavoriteGenresRequest;
import com.digginroom.digginroom.service.dto.MemberDetailsResponse;
import com.digginroom.digginroom.service.dto.MemberDuplicationResponse;
import com.digginroom.digginroom.service.dto.MemberLoginRequest;
import com.digginroom.digginroom.service.dto.MemberLoginResponse;
import com.digginroom.digginroom.service.dto.MemberSaveRequest;
import com.digginroom.digginroom.util.PasswordEncoder;
import java.util.List;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
Expand All @@ -27,13 +29,15 @@ public class MemberService {

private final MemberRepository memberRepository;
private final IdTokenResolver idTokenResolver;
private final PasswordEncoder passwordEncoder;


public void save(final MemberSaveRequest request) {
if (isDuplicated(request.username())) {
throw new DuplicationException();
}
memberRepository.save(request.toMember());
Password password = new Password(request.password(), passwordEncoder);
memberRepository.save(Member.self(request.username(), password));
}

private boolean isDuplicated(final String username) {
Expand Down Expand Up @@ -73,7 +77,7 @@ public MemberLoginResponse loginMember(final MemberLoginRequest request) {
throw new WrongProviderException();
}

if (member.getPassword().doesNotMatch(request.password())) {
if (member.getPassword().doesNotMatch(request.password(), passwordEncoder)) {
throw new NotFoundException();
}
return MemberLoginResponse.of(member);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package com.digginroom.digginroom.service.dto;

import com.digginroom.digginroom.domain.member.Member;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Pattern;
import jakarta.validation.constraints.Size;
Expand All @@ -21,8 +20,4 @@ public record MemberSaveRequest(
)
String password
) {

public Member toMember() {
return Member.self(username, password);
}
}
Original file line number Diff line number Diff line change
@@ -1,19 +1,23 @@
package com.digginroom.digginroom.util;

import java.util.UUID;
import org.springframework.stereotype.Component;

public class DigginRoomPasswordEncoder {
@Component
public class DigginRoomPasswordEncoder implements PasswordEncoder {

private static final int SALT_LENGTH = 36;
private static final int SALT_START_INDEX = 0;

public static String encode(final String plainText) {
@Override
public String encode(final String plainText) {
UUID salt = UUID.randomUUID();
String hashed = HashAlgorithm.encrypt(salt + plainText);
return salt + hashed;
}

public static boolean matches(final String plainText, final String encoded) {
@Override
public boolean matches(final String plainText, final String encoded) {
String salt = encoded.substring(SALT_START_INDEX, SALT_LENGTH);
String hashed = HashAlgorithm.encrypt(salt + plainText);
return (salt + hashed).equals(encoded);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package com.digginroom.digginroom.util;

public interface PasswordEncoder {

String encode(final String plainText);

boolean matches(final String plainText, final String encoded);
}
16 changes: 10 additions & 6 deletions backend/src/test/java/com/digginroom/digginroom/TestFixture.java
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
package com.digginroom.digginroom;

import com.digginroom.digginroom.service.dto.CommentRequest;
import com.digginroom.digginroom.service.dto.MemberLoginRequest;
import com.digginroom.digginroom.service.dto.MemberSaveRequest;
import com.digginroom.digginroom.domain.Genre;
import com.digginroom.digginroom.domain.member.Member;
import com.digginroom.digginroom.domain.member.Password;
import com.digginroom.digginroom.domain.member.Provider;
import com.digginroom.digginroom.domain.room.Room;
import com.digginroom.digginroom.domain.track.Track;
Expand All @@ -13,7 +11,10 @@
import com.digginroom.digginroom.oauth.jwk.KakaoJwkProvider;
import com.digginroom.digginroom.oauth.jwk.ThirdPartyJwkProviders;
import com.digginroom.digginroom.oauth.payload.IdTokenPayload;

import com.digginroom.digginroom.service.dto.CommentRequest;
import com.digginroom.digginroom.service.dto.MemberLoginRequest;
import com.digginroom.digginroom.service.dto.MemberSaveRequest;
import com.digginroom.digginroom.util.DigginRoomPasswordEncoder;
import java.util.List;

//TODO: 픽스쳐 분리
Expand All @@ -30,12 +31,15 @@ public class TestFixture {
public static final MemberLoginRequest MEMBER2_LOGIN_REQUEST = new MemberLoginRequest(MEMBER2_USERNAME,
MEMBER2_PASSWORD);

public static Password PASSWORD = new Password(MEMBER_PASSWORD, new DigginRoomPasswordEncoder());
public static Password PASSWORD2 = new Password(MEMBER2_PASSWORD, new DigginRoomPasswordEncoder());

public static Member 파워() {
return Member.self(MEMBER_USERNAME, MEMBER_PASSWORD);
return Member.self(MEMBER_USERNAME, PASSWORD);
}

public static Member 블랙캣() {
return Member.self(MEMBER2_USERNAME, MEMBER2_PASSWORD);
return Member.self(MEMBER2_USERNAME, PASSWORD2);
}

public static final CommentRequest COMMENT_REQUEST = new CommentRequest("베리는 REST API 고수");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,8 @@
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.test.annotation.DirtiesContext;

@SuppressWarnings("NonAsciiCharacters")
@DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_EACH_TEST_METHOD)
class CommentControllerTest extends ControllerTest {

@Autowired
Expand All @@ -40,6 +38,7 @@ class CommentControllerTest extends ControllerTest {
private RoomRepository roomRepository;
@Autowired
private CommentRepository commentRepository;

private Room 나무;
private Room 차이;
private Member 파워;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
package com.digginroom.digginroom.controller;


import com.digginroom.digginroom.util.DatabaseCleanerExtension;
import io.restassured.RestAssured;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayNameGeneration;
import org.junit.jupiter.api.DisplayNameGenerator.ReplaceUnderscores;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
import org.springframework.boot.test.web.server.LocalServerPort;

@ExtendWith(DatabaseCleanerExtension.class)
@DisplayNameGeneration(ReplaceUnderscores.class)
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
public abstract class ControllerTest {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,8 @@
import org.hamcrest.Matchers;
import org.junit.jupiter.api.Test;
import org.springframework.http.HttpStatus;
import org.springframework.test.annotation.DirtiesContext;

@SuppressWarnings("NonAsciiCharacters")
@DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_EACH_TEST_METHOD)
class MemberArgumentResolverTest extends ControllerTest {

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,12 @@
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.test.annotation.DirtiesContext;

import static com.digginroom.digginroom.TestFixture.MEMBER_LOGIN_REQUEST;
import static com.digginroom.digginroom.TestFixture.파워;
import static org.hamcrest.Matchers.*;

@SuppressWarnings("NonAsciiCharacters")
@DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_EACH_TEST_METHOD)
class MemberLoginControllerTest extends ControllerTest {

@Autowired
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,8 @@
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.http.HttpStatus;
import org.springframework.test.annotation.DirtiesContext;

@SuppressWarnings("NonAsciiCharacters")
@DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_EACH_TEST_METHOD)
class MemberOperationControllerTest extends ControllerTest {

private String cookie;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,8 @@
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.test.annotation.DirtiesContext;

@SuppressWarnings("NonAsciiCharacters")
@DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_EACH_TEST_METHOD)
class RoomControllerTest extends ControllerTest {

@Autowired
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
import static org.assertj.core.api.Assertions.assertThat;

import com.digginroom.digginroom.domain.member.Password;
import com.digginroom.digginroom.util.DigginRoomPasswordEncoder;
import com.digginroom.digginroom.util.PasswordEncoder;
import org.junit.jupiter.api.DisplayNameGeneration;
import org.junit.jupiter.api.DisplayNameGenerator;
import org.junit.jupiter.api.Test;
Expand All @@ -11,37 +13,38 @@
@DisplayNameGeneration(DisplayNameGenerator.ReplaceUnderscores.class)
class PasswordTest {

private static final PasswordEncoder passwordEncoder = new DigginRoomPasswordEncoder();
private static final String PLAIN_TEXT = "konghanapassword";

@Test
void 패스워드를_직접_생성하면_암호화된_패스워드가_생성된다() {
Password password = new Password(PLAIN_TEXT);
Password password = new Password(PLAIN_TEXT, passwordEncoder);

assertThat(password.getPassword()).isNotEqualTo(PLAIN_TEXT);
}

@Test
void 빈_패스워드인지_확인할_수_있다() {
assertThat(new Password(PLAIN_TEXT).isEmpty()).isFalse();
assertThat(new Password(PLAIN_TEXT, passwordEncoder).isEmpty()).isFalse();
assertThat(Password.EMPTY.isEmpty()).isTrue();
}

@Test
void 패스워드가_일치하는지_확인할_수_있다() {
Password password = new Password(PLAIN_TEXT);
Password password = new Password(PLAIN_TEXT, passwordEncoder);

assertThat(password.doesNotMatch(PLAIN_TEXT)).isFalse();
assertThat(password.doesNotMatch(PLAIN_TEXT, passwordEncoder)).isFalse();
}

@Test
void 패스워드가_일치하지_않는지_확인할_수_있다() {
Password password = new Password(PLAIN_TEXT);
Password password = new Password(PLAIN_TEXT, passwordEncoder);

assertThat(password.doesNotMatch("anotherpassword")).isTrue();
assertThat(password.doesNotMatch("anotherpassword", passwordEncoder)).isTrue();
}

@Test
void 빈_패스워드는_어떤_문자열과도_일치하지_않는다() {
assertThat(Password.EMPTY.doesNotMatch("")).isFalse();
assertThat(Password.EMPTY.doesNotMatch("", passwordEncoder)).isFalse();
}
}
Loading