Skip to content

Commit

Permalink
Merge pull request #54 from kckc0608/kckc0608
Browse files Browse the repository at this point in the history
[19기_권찬] Docker & API 리팩토링 미션 제출합니다.
  • Loading branch information
yoonsseo authored May 16, 2024
2 parents 8224ded + 1782ee7 commit ee21262
Show file tree
Hide file tree
Showing 12 changed files with 544 additions and 13 deletions.
4 changes: 4 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
FROM openjdk:17
ARG JAR_FILE=/build/libs/*.jar
COPY ${JAR_FILE} app.jar
ENTRYPOINT ["java","-jar", "/app.jar"]
433 changes: 433 additions & 0 deletions README.md

Large diffs are not rendered by default.

5 changes: 5 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ dependencies {

runtimeOnly 'com.mysql:mysql-connector-j'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
testImplementation 'org.springframework.security:spring-security-test'

annotationProcessor 'org.projectlombok:lombok'
}
Expand All @@ -41,3 +42,7 @@ tasks.named('bootBuildImage') {
tasks.named('test') {
useJUnitPlatform()
}

tasks.named('jar') {
enabled = false
}
28 changes: 28 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
services:
web:
container_name: spring
build: .
ports:
- "8080:8080"
depends_on:
- db
environment:
mysql_host: db
restart: always
volumes:
- app:/app

db:
image: mysql:8.0
environment:
MYSQL_ROOT_PASSWORD: mysql
MYSQL_DATABASE: spring_everytime
volumes:
- dbdata:/var/lib/mysql
ports:
- 3307:3306
restart: always

volumes:
dbdata:
app:
Original file line number Diff line number Diff line change
Expand Up @@ -37,15 +37,7 @@ protected void doFilterInternal(HttpServletRequest request, HttpServletResponse

String loginId = jwtUtil.getLoginId(token);

User user = new User(
loginId,
"",
"",
"",
"",
"",
""
);
User user = User.builder().loginId(loginId).build();

CustomUserDetails customUserDetails = new CustomUserDetails(user);
Authentication authToken = new UsernamePasswordAuthenticationToken(customUserDetails, null, customUserDetails.getAuthorities());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;

import org.springframework.http.HttpStatusCode;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
Expand Down Expand Up @@ -50,6 +52,6 @@ protected void successfulAuthentication(HttpServletRequest request, HttpServletR
* */
@Override
protected void unsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response, AuthenticationException failed) throws IOException, ServletException {
response.setStatus(401);
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,10 @@ public List<CategoryPostResponse> getPosts(final Long categoryId, final Pageable
private void validateCategoryCreatedBefore14Days(Category category) {
LocalDateTime today = LocalDateTime.now();

if (today.compareTo(category.getCreateDate()) < 14) {
if (today.minusDays(14).isBefore(category.getCreateDate())) {
System.out.println(today);
System.out.println(category.getCreateDate());
System.out.println(today.compareTo(category.getCreateDate()));
throw new BadRequestException(SHOULD_EXCEED_14_DAYS_TO_DELETE);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
Expand All @@ -21,4 +24,10 @@ public ResponseEntity<Void> registerUser(@RequestBody @Valid final UserCreateReq
userService.register(request);
return ResponseEntity.ok().build();
}

@DeleteMapping
public ResponseEntity<Void> deleteUser() {
userService.delete();
return ResponseEntity.noContent().build();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
import java.util.Date;

@Entity
@RequiredArgsConstructor
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@Getter
public class User extends BaseEntity {
Expand Down Expand Up @@ -50,4 +49,15 @@ public class User extends BaseEntity {
public void authenticateUniversity() {
this.isEnrolled = true;
}

@Builder
public User(String loginId, String pw, String nickname, String name, String major, String admissionYear, String email) {
this.loginId = loginId;
this.pw = pw;
this.nickname = nickname;
this.name = name;
this.major = major;
this.admissionYear = admissionYear;
this.email = email;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,14 @@

import com.ceos19.springeverytime.domain.user.domain.User;
import com.ceos19.springeverytime.domain.user.dto.request.UserCreateRequest;
import com.ceos19.springeverytime.domain.user.dto.response.CustomUserDetails;
import com.ceos19.springeverytime.domain.user.repository.UserRepository;
import com.ceos19.springeverytime.global.exception.BadRequestException;
import com.ceos19.springeverytime.global.exception.ExceptionCode;
import lombok.RequiredArgsConstructor;

import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;

Expand All @@ -31,7 +35,13 @@ public User register(UserCreateRequest request) {
return userRepository.save(user);
}

public void delete(User user) {
public void delete() {
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
CustomUserDetails userDetails = (CustomUserDetails) auth.getPrincipal();
String loginId = userDetails.getUsername();
User user = userRepository.findByLoginId(loginId).orElseThrow(
() -> new BadRequestException(ExceptionCode.NOT_FOUND_LOGIN_ID)
);
userRepository.delete(user);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ public BCryptPasswordEncoder bCryptPasswordEncoder () {
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http.authorizeHttpRequests((auth) -> auth
.requestMatchers("/swagger-ui/**", "/login").permitAll()
.requestMatchers("/swagger-ui.html", "/v3/api-docs/**").permitAll()
.requestMatchers(HttpMethod.POST, "/user").permitAll()
.anyRequest().authenticated()
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,31 @@
import com.ceos19.springeverytime.common.EntityGenerator;
import com.ceos19.springeverytime.domain.user.domain.User;
import com.ceos19.springeverytime.domain.user.dto.request.UserCreateRequest;
import com.ceos19.springeverytime.domain.user.dto.response.CustomUserDetails;
import com.ceos19.springeverytime.domain.user.repository.UserRepository;
import com.ceos19.springeverytime.domain.user.service.UserService;
import org.assertj.core.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.test.context.support.WithMockUser;

import static org.mockito.ArgumentMatchers.*;
import static org.mockito.BDDMockito.given;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import java.util.Optional;

@ExtendWith(MockitoExtension.class)
public class UserServiceTest {
Expand All @@ -28,6 +40,14 @@ public class UserServiceTest {
@InjectMocks
UserService userService;

@BeforeEach
void setup() {
CustomUserDetails userDetails = new CustomUserDetails(EntityGenerator.generateUser("test"));
Authentication auth = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
SecurityContextHolder.getContext().setAuthentication(auth);
}


@Test
@DisplayName("회원 가입 테스트")
void 회원가입_테스트() {
Expand All @@ -52,4 +72,18 @@ public class UserServiceTest {
// then
Assertions.assertThat(joinUser).isSameAs(user);
}

@Test
@DisplayName("유저 회원 탈퇴 테스트")
void 회원탈퇴_테스트() {
// given
User user = EntityGenerator.generateUser("test");
when(userRepository.findByLoginId(anyString())).thenReturn(Optional.of(user));

// when
userService.delete();

// then
verify(userRepository, times(1)).delete(user);
}
}

0 comments on commit ee21262

Please sign in to comment.