Skip to content

Commit

Permalink
Release 3.2 (#212)
Browse files Browse the repository at this point in the history
  • Loading branch information
BeomSeogKim authored Jan 19, 2024
2 parents 92c7dd6 + 074c00b commit b60dd11
Show file tree
Hide file tree
Showing 11 changed files with 214 additions and 17 deletions.
7 changes: 3 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
# 우.이.삭 (우리 이거 삭제하지 말자)
- [서비스 링크](https://woisac.netlify.app/login)
- [API 문서](https://love-back.kro.kr/docs/index.html)

# Introduction

Expand All @@ -11,9 +13,6 @@
우이삭을 통해 서로 추억이 쌓인 장소들을 기록하고 추억을 공유하세요.
</div>

---


# Members
| Backend | Backend | Backend |
|:----------------------------------------------------------------------------------------:|:---------------------------------------------------------------------------------------------------------------------------------------:|:---------------------------------------------------------------------------------------------------------------------------------:|
Expand All @@ -39,4 +38,4 @@
[![Vulnerabilities](https://sonarcloud.io/api/project_badges/measure?project=Lovely-4K_love-backend&metric=vulnerabilities)](https://sonarcloud.io/summary/new_code?id=Lovely-4K_love-backend)
[![Duplicated Lines (%)](https://sonarcloud.io/api/project_badges/measure?project=Lovely-4K_love-backend&metric=duplicated_lines_density)](https://sonarcloud.io/summary/new_code?id=Lovely-4K_love-backend)
[![Security Rating](https://sonarcloud.io/api/project_badges/measure?project=Lovely-4K_love-backend&metric=security_rating)](https://sonarcloud.io/summary/new_code?id=Lovely-4K_love-backend)
[![Code Smells](https://sonarcloud.io/api/project_badges/measure?project=Lovely-4K_love-backend&metric=code_smells)](https://sonarcloud.io/summary/new_code?id=Lovely-4K_love-backend)
[![Code Smells](https://sonarcloud.io/api/project_badges/measure?project=Lovely-4K_love-backend&metric=code_smells)](https://sonarcloud.io/summary/new_code?id=Lovely-4K_love-backend)
13 changes: 13 additions & 0 deletions api/src/docs/asciidoc/api/login/login-trial.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
[[login-trial]]
=== 체험용 계정 로그인

해당 API를 통해 체험 계정에 로그인 할 수 있습니다.

해당 문서에 있는 Response는 예시이며 실제 받는 토큰값은 상이할 수 있습니다.

==== Http Request
include::{snippets}/login-trial/http-request.adoc[]
==== Http Response

include::{snippets}/login-trial/http-response.adoc[]
include::{snippets}/login-trial/response-fields.adoc[]
4 changes: 3 additions & 1 deletion api/src/docs/asciidoc/api/login/login.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -42,4 +42,6 @@ message: "Login success"
}
----

재결합을 요청하고자 한다면 `POST` 방식으로 상위 url에 요청을 주시면 됩니다.
재결합을 요청하고자 한다면 `POST` 방식으로 상위 url에 요청을 주시면 됩니다.

include::../login/login-trial.adoc[]
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package com.lovely4k.backend.authentication.trial_login;

import com.lovely4k.backend.common.ApiResponse;
import lombok.RequiredArgsConstructor;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.hateoas.MediaTypes;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@Slf4j
@RestController
@RequiredArgsConstructor
@RequestMapping(value = "/v1/members", produces = MediaTypes.HAL_JSON_VALUE)
public class LoginController {

private final LoginService loginService;

@SneakyThrows
@GetMapping(path = "/trial")
public ResponseEntity<ApiResponse<LoginResponse>> trialLogin(
) {
long trialMemberId = 200395L;
return ApiResponse.ok(loginService.trialLogin(trialMemberId));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.lovely4k.backend.authentication.trial_login;

import com.lovely4k.backend.authentication.token.TokenDto;

public record LoginResponse(
String accessToken,
String refreshToken
) {
public static LoginResponse of(TokenDto tokenDto) {
return new LoginResponse(tokenDto.accessToken(), tokenDto.refreshToken());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package com.lovely4k.backend.authentication.trial_login;

import com.lovely4k.backend.authentication.token.TokenDto;
import com.lovely4k.backend.authentication.token.TokenProvider;
import com.lovely4k.backend.member.Member;
import com.lovely4k.backend.member.repository.MemberRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
@RequiredArgsConstructor
@Transactional(readOnly = true)
public class LoginService {

private final MemberRepository memberRepository;
private final TokenProvider tokenProvider;

@Transactional
public LoginResponse trialLogin(long memberId) {
Member trialMember = memberRepository.findById(memberId).orElseThrow();
TokenDto tokenDto = tokenProvider.generateTokenDto(trialMember);
return LoginResponse.of(tokenDto);
}
}
Original file line number Diff line number Diff line change
@@ -1,22 +1,18 @@
package com.lovely4k.backend.member.controller;

import com.lovely4k.backend.authentication.token.UserDetailsImpl;
import com.lovely4k.backend.common.ApiResponse;
import com.lovely4k.backend.common.sessionuser.LoginUser;
import com.lovely4k.backend.common.sessionuser.SessionUser;
import com.lovely4k.backend.member.controller.request.MemberProfileEditRequest;
import com.lovely4k.backend.member.service.MemberService;
import com.lovely4k.backend.member.service.response.MemberProfileGetResponse;
import com.nimbusds.jose.proc.SecurityContext;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.hateoas.MediaTypes;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
package com.lovely4k.backend.authentication;

import com.lovely4k.backend.IntegrationTestSupport;
import com.lovely4k.backend.authentication.trial_login.LoginResponse;
import com.lovely4k.backend.authentication.trial_login.LoginService;
import com.lovely4k.backend.member.Member;
import com.lovely4k.backend.member.Role;
import com.lovely4k.backend.member.repository.MemberRepository;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDate;

import static com.lovely4k.backend.member.Sex.MALE;
import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.*;

@Transactional
class LoginServiceTest extends IntegrationTestSupport {

@Autowired
MemberRepository memberRepository;

@Autowired
RefreshTokenRepository refreshTokenRepository;

@Autowired
LoginService loginService;

@DisplayName("trialLogin을 통해 accessToken 값과 refreshToken 값을 받아올 수 있다.")
@Test
void trialLogin() {

// given
Member member = createMember();
Member savedMember = memberRepository.save(member);

// when
LoginResponse loginResponse = loginService.trialLogin(savedMember.getId());

// then
RefreshToken refreshToken = refreshTokenRepository.findByMember(savedMember).orElseThrow();

assertAll(
() -> assertThat(loginResponse.accessToken()).isNotNull(),
() -> assertThat(loginResponse.refreshToken()).isNotNull(),
() -> assertThat(refreshToken).isNotNull(),
() -> assertThat(refreshToken.getMember()).isEqualTo(savedMember)
);

}

private Member createMember() {
return Member.builder()
.coupleId(1L)
.sex(MALE)
.nickname("듬직이")
.birthday(LocalDate.of(1996, 7, 30))
.mbti("ESFJ")
.calendarColor("white")
.imageUrl("http://www.imageUrlSample.com")
.role(Role.USER)
.build();
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.lovely4k.backend.member.service;

import com.lovely4k.backend.IntegrationTestSupport;
import com.lovely4k.backend.common.imageuploader.ImageUploader;
import com.lovely4k.backend.member.Member;
import com.lovely4k.backend.member.Role;
Expand All @@ -10,7 +11,6 @@
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.transaction.annotation.Transactional;
Expand All @@ -25,9 +25,8 @@
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.BDDMockito.given;

@SpringBootTest
@Transactional
class MemberServiceTest {
class MemberServiceTest extends IntegrationTestSupport {

@Autowired
private MemberService memberService;
Expand All @@ -40,7 +39,7 @@ class MemberServiceTest {

@Test
@DisplayName("회원 정보를 조회한다.")
void getMemberProfile() throws Exception {
void getMemberProfile() {
//given
Member member = createMember();

Expand All @@ -57,7 +56,7 @@ void getMemberProfile() throws Exception {

@Test
@DisplayName("존재하지 않는 id로 프로필을 조회할 경우 예외가 발생한다.")
void getMemberProfileByWrongId() throws Exception {
void getMemberProfileByWrongId() {
//given
Member member = createMember();

Expand All @@ -70,7 +69,7 @@ void getMemberProfileByWrongId() throws Exception {

@Test
@DisplayName("회원의 프로필 정보를 수정할 수 있다.")
void updateMemberProfile() throws Exception {
void updateMemberProfile() {
//given
Member member = createMember();
Member savedMember = memberRepository.save(member);
Expand Down Expand Up @@ -101,7 +100,7 @@ void updateMemberProfile() throws Exception {

@Test
@DisplayName("프로필 수정 시 두개 이상의 이미지를 요청하면 에러가 발생한다.")
void updateMemberProfileWithMoreThanOneImage() throws Exception {
void updateMemberProfileWithMoreThanOneImage() {
//given
Member member = createMember();
Member savedMember = memberRepository.save(member);
Expand All @@ -125,7 +124,7 @@ void updateMemberProfileWithMoreThanOneImage() throws Exception {

@Test
@DisplayName("프로필 수정 시 이미지가 없는 경우 기존 imageUrl이 유지된다.")
void updateMemberProfileWithoutImage() throws Exception {
void updateMemberProfileWithoutImage() {
//given
Member member = createMember();
Member savedMember = memberRepository.save(member);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import com.lovely4k.backend.question.repository.response.QuestionGameResponse;
import jakarta.persistence.EntityNotFoundException;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
Expand All @@ -32,6 +33,7 @@ class QuestionQueryServiceForGameTest extends IntegrationTestSupport {
CoupleRepository coupleRepository;

@Test
@Disabled
@DisplayName("coupleId를 통해서 기존에 답변했던 질문들 중 랜덤으로 하나를 조회할 수 있다.")
void findQuestionGame() {
//given
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package com.lovely4k.docs.authentication;

import com.lovely4k.backend.authentication.trial_login.LoginController;
import com.lovely4k.backend.authentication.trial_login.LoginResponse;
import com.lovely4k.backend.authentication.trial_login.LoginService;
import com.lovely4k.docs.RestDocsSupport;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.springframework.restdocs.payload.JsonFieldType;

import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document;
import static org.springframework.restdocs.payload.PayloadDocumentation.fieldWithPath;
import static org.springframework.restdocs.payload.PayloadDocumentation.responseFields;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

class LoginControllerDocsTest extends RestDocsSupport {

private final LoginService loginService = mock(LoginService.class);

@Override
protected Object initController() {
return new LoginController(loginService);
}

@DisplayName("체험용 아이디로 로그인 하는 API")
@Test
void trialLogin() throws Exception {
// stubbing
when(loginService.trialLogin(200395L)).thenReturn(new LoginResponse("ekq;jelkr", "qe;jkrqew;lkrjq;ewlrj"));

mockMvc.perform(
get("/v1/members/trial")
.characterEncoding("UTF-8")
)
.andDo(print())
.andExpect(status().isOk())
.andDo(document("login-trial",
responseFields(
fieldWithPath("code").type(JsonFieldType.NUMBER)
.description("응답 코드"),
fieldWithPath("body.accessToken").type(JsonFieldType.STRING)
.description("access token value"),
fieldWithPath("body.refreshToken").type(JsonFieldType.STRING)
.description("refresh token value"),
fieldWithPath("links").type(JsonFieldType.ARRAY)
.description("relation links")
)
));
}
}

0 comments on commit b60dd11

Please sign in to comment.