Skip to content

Commit

Permalink
Merge pull request #48 from Soundbar91/develop
Browse files Browse the repository at this point in the history
main 브랜치 반영을 위한 PR
  • Loading branch information
Soundbar91 authored Sep 6, 2024
2 parents 06eabb1 + 424276c commit 71bec5b
Show file tree
Hide file tree
Showing 9 changed files with 377 additions and 578 deletions.
1 change: 1 addition & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ dependencies {
implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
implementation 'io.hypersistence:hypersistence-utils-hibernate-63:3.8.1'
implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.2.0'
implementation 'org.flywaydb:flyway-mysql'

runtimeOnly 'com.mysql:mysql-connector-j'

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,10 +45,13 @@ public class User {
private boolean isActive;

@Builder
public User(String username, String email, String password) {
public User(String username, String email, String password, boolean isActive, double exp, Role role) {
this.username = username;
this.email = email;
this.password = password;
this.isActive = isActive;
this.exp = exp;
this.role = role;
}

public void changePassword(String newPassword) {
Expand Down
4 changes: 3 additions & 1 deletion src/main/resources/application.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@ spring:
jpa:
database: mysql
hibernate:
ddl-auto: update
ddl-auto: validate
flyway:
enabled: true
springdoc:
swagger-ui:
operations-sorter: method
116 changes: 116 additions & 0 deletions src/main/resources/db/migration/V1__init.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
CREATE TABLE `user`
(
`id` bigint NOT NULL AUTO_INCREMENT,
`email` varchar(100) NOT NULL,
`exp` decimal(10, 2) NOT NULL DEFAULT '0.00',
`is_active` bit(1) NOT NULL DEFAULT b'1',
`password` varchar(255) NOT NULL,
`role` tinyint NOT NULL DEFAULT '0',
`username` varchar(20) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `UK_email` (`email`),
UNIQUE KEY `UK_username` (`username`),
CONSTRAINT `user_chk_1` CHECK (`role` between 0 and 4)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

CREATE TABLE `problem`
(
`id` bigint NOT NULL AUTO_INCREMENT,
`algorithms` text NOT NULL,
`answer` int NOT NULL DEFAULT '0',
`create_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`example_inout` json NOT NULL,
`input_explanation` text NOT NULL,
`level` int NOT NULL,
`memory` int NOT NULL,
`modify_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`output_explanation` text NOT NULL,
`problem_explanation` text NOT NULL,
`runtime` json NOT NULL,
`submit` int NOT NULL DEFAULT '0',
`title` varchar(100) NOT NULL,
`user_id` bigint NOT NULL,
PRIMARY KEY (`id`),
KEY `FK_user_id` (`user_id`),
CONSTRAINT `FK_user_id_P` FOREIGN KEY (`user_id`) REFERENCES `user` (`id`),
CONSTRAINT `problem_chk_1` CHECK (`level` BETWEEN 1 AND 10),
CONSTRAINT `problem_chk_2` CHECK (`memory` BETWEEN 1 AND 2048)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

CREATE TABLE `result`
(
`id` bigint NOT NULL AUTO_INCREMENT,
`code` text NOT NULL,
`code_length` int NOT NULL,
`grade` tinyint NOT NULL,
`language` tinyint NOT NULL,
`memory` int NOT NULL,
`runtime` int NOT NULL,
`submit_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`problem_id` bigint NOT NULL,
`user_id` bigint NOT NULL,
PRIMARY KEY (`id`),
KEY `FK_problem_id` (`problem_id`),
KEY `FK_user_id` (`user_id`),
CONSTRAINT `FK_user_id_R` FOREIGN KEY (`user_id`) REFERENCES `user` (`id`),
CONSTRAINT `FK_problem_id_R` FOREIGN KEY (`problem_id`) REFERENCES `problem` (`id`),
CONSTRAINT `result_chk_1` CHECK (`grade` between 0 and 5),
CONSTRAINT `result_chk_2` CHECK (`language` between 0 and 2)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

CREATE TABLE `post`
(
`id` bigint NOT NULL AUTO_INCREMENT,
`category` tinyint NOT NULL,
`content` text NOT NULL,
`create_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`modify_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`title` varchar(100) NOT NULL,
`problem_id` bigint NOT NULL,
`user_id` bigint NOT NULL,
PRIMARY KEY (`id`),
KEY `FK_problem_id` (`problem_id`),
KEY `FK_user_id` (`user_id`),
CONSTRAINT `FK_user_id_PO` FOREIGN KEY (`user_id`) REFERENCES `user` (`id`),
CONSTRAINT `FK_problem_id_PO` FOREIGN KEY (`problem_id`) REFERENCES `problem` (`id`),
CONSTRAINT `post_chk_1` CHECK (`category` between 0 and 2)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

CREATE TABLE `post_like`
(
`id` bigint NOT NULL AUTO_INCREMENT,
`post_id` bigint NOT NULL,
`user_id` bigint NOT NULL,
PRIMARY KEY (`id`),
KEY `FK_post_id` (`post_id`),
KEY `FK_user_id` (`user_id`),
CONSTRAINT `FK_user_id_PL` FOREIGN KEY (`user_id`) REFERENCES `user` (`id`),
CONSTRAINT `FK_post_id_PL` FOREIGN KEY (`post_id`) REFERENCES `post` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

CREATE TABLE `comment`
(
`id` bigint NOT NULL AUTO_INCREMENT,
`context` text NOT NULL,
`create_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`modify_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`post_id` bigint NOT NULL,
`user_id` bigint NOT NULL,
PRIMARY KEY (`id`),
KEY `FK_post_id` (`post_id`),
KEY `FK_user_id` (`user_id`),
CONSTRAINT `FK_user_id_C` FOREIGN KEY (`user_id`) REFERENCES `user` (`id`),
CONSTRAINT `FK_post_id_C` FOREIGN KEY (`post_id`) REFERENCES `post` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

CREATE TABLE `comment_like`
(
`id` bigint NOT NULL AUTO_INCREMENT,
`comment_id` bigint NOT NULL,
`user_id` bigint NOT NULL,
PRIMARY KEY (`id`),
KEY `FK_comment_id` (`comment_id`),
KEY `FK_user_id` (`user_id`),
CONSTRAINT `FK_user_id_CL` FOREIGN KEY (`user_id`) REFERENCES `user` (`id`),
CONSTRAINT `FK_comment_id_CL` FOREIGN KEY (`comment_id`) REFERENCES `comment` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
package com.soundbar91.retrospect_project.api;

import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.request;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestInstance;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.http.MediaType;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.MvcResult;

import com.soundbar91.retrospect_project.fixture.UserFixture;
import com.soundbar91.retrospect_project.user.entity.User;

import jakarta.transaction.Transactional;

@SpringBootTest
@AutoConfigureMockMvc
@SuppressWarnings("NonAsciiCharacters")
@Transactional
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
public class AuthApiTest {

@Autowired
private MockMvc mockMvc;

@Autowired
private UserFixture userFixture;

@Test
void 회원_로그인() throws Exception {
User user = userFixture.사용자();
String username = user.getUsername();
String password = "1q2w3e4r1!";

mockMvc.perform(
post("/auth/login")
.content("""
{
"username" : "%s",
"password" : "%s"
}
""".formatted(username, password))
.contentType(MediaType.APPLICATION_JSON)
)
.andExpect(status().is3xxRedirection())
.andExpect(request().sessionAttribute("username", username));
}

@Test
void 회원_로그아웃() throws Exception {
User user = userFixture.사용자();
String username = user.getUsername();
String password = "1q2w3e4r1!";

MvcResult result = mockMvc.perform(
post("/auth/login")
.content("""
{
"username" : "%s",
"password" : "%s"
}
""".formatted(username, password))
.contentType(MediaType.APPLICATION_JSON)
)
.andExpect(status().is3xxRedirection())
.andExpect(request().sessionAttribute("username", username))
.andReturn();

Long sessionUserid = (Long)result.getRequest().getSession().getAttribute("userId");
String sessionUsername = (String)result.getRequest().getSession().getAttribute("username");

mockMvc.perform(
post("/auth/logout")
.sessionAttr("userId", sessionUserid)
.sessionAttr("username", sessionUsername)
)
.andExpect(status().isNoContent())
.andExpect(request().sessionAttributeDoesNotExist("userId"))
.andExpect(request().sessionAttributeDoesNotExist("username"));
}
}
136 changes: 136 additions & 0 deletions src/test/java/com/soundbar91/retrospect_project/api/UserApiTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
package com.soundbar91.retrospect_project.api;

import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.request;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;

import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestInstance;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.http.MediaType;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.MvcResult;

import com.soundbar91.retrospect_project.fixture.UserFixture;
import com.soundbar91.retrospect_project.user.entity.User;
import com.soundbar91.retrospect_project.user.repository.UserRepository;

import jakarta.transaction.Transactional;

@SpringBootTest
@AutoConfigureMockMvc
@SuppressWarnings("NonAsciiCharacters")
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
public class UserApiTest {

private User user;
private Long userId;
private String username;
private String password;

@Autowired
private MockMvc mockMvc;

@Autowired
private UserFixture userFixture;

@Autowired
private UserRepository userRepository;

@BeforeAll
void 초기_설정() throws Exception {
user = userFixture.사용자();
username = user.getUsername();
password = "1q2w3e4r1!";

MvcResult result = mockMvc.perform(
post("/auth/login")
.content("""
{
"username" : "%s",
"password" : "%s"
}
""".formatted(username, password))
.contentType(MediaType.APPLICATION_JSON)
)
.andExpect(status().is3xxRedirection())
.andExpect(request().sessionAttribute("username", username))
.andReturn();

userId = (Long)result.getRequest().getSession().getAttribute("userId");
}

@Test
@Transactional
void 비밀번호_변경() throws Exception {
String newPassword = "1q2w3e4r4$";

mockMvc.perform(
put("/user/password")
.content("""
{
"curPassword" : "%s",
"newPassword" : "%s"
}
""".formatted(password, newPassword))
.contentType(MediaType.APPLICATION_JSON)
.sessionAttr("userId", userId)
.sessionAttr("username", username)
)
.andExpect(status().isOk());

password = newPassword;
}

@Test
@Transactional
void 유저_조회() throws Exception {
mockMvc.perform(
get("/user/" + username)
.contentType(MediaType.APPLICATION_JSON)
.sessionAttr("userId", userId)
.sessionAttr("username", username)
)
.andExpect(status().isOk())
.andExpect(content().json("""
{
"username": "testUser",
"email": "testUser@gmail.com",
"role": "브론즈",
"exp": 0.0
}
"""));
}

@AfterAll
void 회원탈퇴_종료() throws Exception {
mockMvc.perform(
delete("/user")
.contentType(MediaType.APPLICATION_JSON)
.sessionAttr("userId", userId)
.sessionAttr("username", username)
)
.andExpect(status().isNoContent())
.andExpect(request().sessionAttributeDoesNotExist("userId"))
.andExpect(request().sessionAttributeDoesNotExist("username"));

mockMvc.perform(
get("/user/" + username)
.contentType(MediaType.APPLICATION_JSON)
.sessionAttr("userId", userId)
.sessionAttr("username", username)
)
.andExpect(status().isNotFound())
.andExpect(content().json("""
{
"message": "탈퇴한 유저입니다"
}
"""));

userRepository.deleteById(userId);
}
}
Loading

0 comments on commit 71bec5b

Please sign in to comment.