Skip to content
Open
Show file tree
Hide file tree
Changes from all 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
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ plugins {

group = 'h3s1'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '1.8'
sourceCompatibility = '1.9'

configurations {
compileOnly {
Expand Down
23 changes: 23 additions & 0 deletions src/main/java/h3s1/tubesday/api/ApiResponse.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package h3s1.tubesday.api;

import lombok.Data;

@Data
public class ApiResponse<T> {

private StatusCode statusCode;
private T data;

private ApiResponse(StatusCode code, T data) {
this.statusCode = code;
this.data = data;
}

public static <T> ApiResponse<T> ok(T data) {
return new ApiResponse<>(StatusCode.OK, data);
}

public static ApiResponse<String> error(String message) {
return new ApiResponse<>(StatusCode.UNKNOWN_ERROR, message);
}
}
6 changes: 6 additions & 0 deletions src/main/java/h3s1/tubesday/api/ServiceErrorMessage.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package h3s1.tubesday.api;

public enum ServiceErrorMessage {
EMAIL_TYPE_INVALID,
PASSWORD_TYPE_INVALID
}
14 changes: 14 additions & 0 deletions src/main/java/h3s1/tubesday/api/ServiceException.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package h3s1.tubesday.api;

import lombok.Getter;

public class ServiceException extends RuntimeException {

@Getter
ServiceErrorMessage code;

public ServiceException(ServiceErrorMessage code, String detailMessage) {
super(detailMessage);
this.code = code;
}
}
12 changes: 12 additions & 0 deletions src/main/java/h3s1/tubesday/api/StatusCode.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package h3s1.tubesday.api;

public enum StatusCode {
OK("OOK00001"),
UNKNOWN_ERROR("ERR99999");

private String code;

StatusCode(String code) {
this.code = code;
}
}
69 changes: 69 additions & 0 deletions src/main/java/h3s1/tubesday/article/ArticleService.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
package h3s1.tubesday.article;

import h3s1.tubesday.tag.ArticleTagMatch;
import h3s1.tubesday.tag.ArticleTagMatchRepository;
import h3s1.tubesday.tag.Tag;
import h3s1.tubesday.tag.TagRepository;
import h3s1.tubesday.user.User;
import h3s1.tubesday.user.UserRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

@Service
public class ArticleService {

private ArticleRepository articleRepository;
private TagRepository tagRepository;
private ArticleTagMatchRepository articleTagMatchRepository;
private UserRepository userRepository;

@Autowired
ArticleService(ArticleRepository articleRepository, TagRepository tagRepository, ArticleTagMatchRepository articleTagMatchRepository, UserRepository userRepository) {
this.articleRepository = articleRepository;
this.tagRepository = tagRepository;
this.articleTagMatchRepository = articleTagMatchRepository;
this.userRepository = userRepository;
}

public Article createArticle(long userNo, String title, String content, String videoId, List<String> tags) {
final Optional<User> optionalAuthor = userRepository.findById(userNo);

if (!optionalAuthor.isPresent()) {
throw new RuntimeException("User not found!!");
}

final User author = optionalAuthor.get();

final List<ArticleTagMatch> articleTagMatches = new ArrayList<>();
final Article article = Article.builder()
.author(author)
.title(title)
.content(content)
.videoId(videoId)
.build();

for (String tagName : tags) {
Tag tag = tagRepository.findByTagName(tagName);

if (tag == null) {
tag = new Tag();
tag.setTagName(tagName);
tagRepository.save(tag);
}
ArticleTagMatch match = ArticleTagMatch.builder()
.tag(tag)
.article(article)
.build();

articleTagMatches.add(match);
}
article.setTagMatchList(articleTagMatches);

return articleRepository.save(article);
}

}
2 changes: 1 addition & 1 deletion src/main/java/h3s1/tubesday/user/User.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ public class User {
@Column(name = "user_no")
private Long userNo;

@Column(name = "email")
@Column(name = "email", unique = true)
private String email;

@Column
Expand Down
95 changes: 95 additions & 0 deletions src/main/java/h3s1/tubesday/user/UserService.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
package h3s1.tubesday.user;

import h3s1.tubesday.api.ServiceErrorMessage;
import h3s1.tubesday.api.ServiceException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.Optional;

@Service
public class UserService {

private UserRepository userRepository;

@Autowired
UserService(UserRepository userRepository) {
this.userRepository = userRepository;
}

public User createUser(String email, String password, String nickname, String avatarUrl) {
validateEmail(email);
validatePassword(password);
LocalDateTime now = LocalDateTime.now();
final User user = User.builder()
.email(email)
.password(password)
.nickname(nickname)
.avatarUrl(avatarUrl)
.createdAt(now)
.updatedAt(now)
.build();

userRepository.save(user);
return user;
}

public User getUserByUserNo(long userNo) {
final Optional<User> user = userRepository.findById(userNo);

if (user.isPresent()) {
return user.get();
}
throw new RuntimeException("That user doesn't exist.");
}

public User getUserByEmail(String email) {
return userRepository.findByEmail(email);
}

public User updateUserByUserNo(long userNo, String email, String password, String nickname, String avatarUrl) {
final Optional<User> optionalUser = userRepository.findById(userNo);
final User user;

if (optionalUser.isPresent()) {
user = optionalUser.get();
updateUser(user, email, password, nickname, avatarUrl);
return userRepository.save(user);
}
throw new RuntimeException("User not exist");
}

public User updateUserByEmail(String email, String password, String nickname, String avatarUrl) {
final User user = userRepository.findByEmail(email);

updateUser(user, email, password, nickname, avatarUrl);
return userRepository.save(user);
}


public void deleteUser(long userNo) {
userRepository.deleteById(userNo);
}

private void validateEmail(String email) {
if (email == null) throw new ServiceException(ServiceErrorMessage.EMAIL_TYPE_INVALID, "email is null");
if (!email.matches("^[_a-z0-9-]+(.[_a-z0-9-]+)*@(?:\\w+\\.)+\\w+$"))
throw new ServiceException(ServiceErrorMessage.EMAIL_TYPE_INVALID, "Email type doesn't invalid.");
}

private void validatePassword(String password) {
if (password == null || "".equals(password))
throw new ServiceException(ServiceErrorMessage.PASSWORD_TYPE_INVALID, "password is null");
if (password.length() < 2 || password.length() > 45)
throw new ServiceException(ServiceErrorMessage.PASSWORD_TYPE_INVALID, "password length is invalid.");
}

private void updateUser(User user, String email, String password, String nickname, String avatarUrl) {
user.setEmail("".equals(email) ? user.getEmail() : email);
user.setPassword("".equals(password) ? user.getPassword() : password);
user.setNickname("".equals(nickname) ? user.getNickname() : nickname);
user.setPassword("".equals(avatarUrl) ? user.getAvatarUrl() : avatarUrl);
user.setUpdatedAt(LocalDateTime.now());
}
}
60 changes: 60 additions & 0 deletions src/test/java/h3s1/tubesday/article/ArticleServiceTests.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package h3s1.tubesday.article;

import h3s1.tubesday.user.User;
import h3s1.tubesday.user.UserService;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import java.util.List;
import java.util.stream.Collectors;

import static org.junit.Assert.*;

@SpringBootTest
@RunWith(SpringJUnit4ClassRunner.class)
public class ArticleServiceTests {

@Autowired
ArticleService articleService;

@Autowired
UserService userService;

private static final String USER_EMAIL = "lee@zerobell.xyz";
private static final String USER_NICKNAME = "이영종";
private static final String USER_PASSWORD = "1q2w3e4r!";
private static final String USER_AVATAR = "test.png";

private static final String TITLE = "본인 방금 튭스데이로 뗴돈 버는 상상함 ㅋ";
private static final String CONTENT = "하지만 어림도 없지";
private static final String VIDEO_ID = "24iwWFzaSWU";

private User author;

@Before
public void init() {
author = userService.createUser(USER_EMAIL, USER_PASSWORD, USER_NICKNAME, USER_AVATAR);
}

@Test
public void createArticle_test() {
final List<String> tags = List.of("ASMR", "공부");
Article article = articleService.createArticle(author.getUserNo(), TITLE, CONTENT, VIDEO_ID, tags);
assertNotNull(article.getAritcleNo());
assertEquals(author, article.getAuthor());
assertEquals(TITLE, article.getTitle());
assertEquals(CONTENT, article.getContent());
assertEquals(VIDEO_ID, article.getVideoId());

assertNotNull(article.getTagMatchList());

final List<String> savedTags = article.getTagMatchList().stream().map(e -> e.getTag().getTagName()).collect(Collectors.toList());

assertTrue(savedTags.containsAll(tags));
assertTrue(tags.containsAll(savedTags));
}
}
54 changes: 54 additions & 0 deletions src/test/java/h3s1/tubesday/user/UserServiceTests.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package h3s1.tubesday.user;

import h3s1.tubesday.api.ServiceErrorMessage;
import h3s1.tubesday.api.ServiceException;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import static org.junit.Assert.*;

@SpringBootTest
@RunWith(SpringJUnit4ClassRunner.class)
public class UserServiceTests {

@Autowired
private UserService userService;

@Test
public void createUser_test() {
User user = userService.createUser("lee@zerobell.xyz", "12341234", "이영종이담마", "test.png");
assertNotNull(user.getUserNo());
}

@Test(expected = DataIntegrityViolationException.class)
public void createUser_withDuplicatedEmailTest() {
User user = userService.createUser("lee@zerobell.xyz", "12341234", "이영종이담마", "test.png");
assertNotNull(user.getUserNo());

userService.createUser("lee@zerobell.xyz", "998877", "이영종이라곰마", "test.png");
}

@Test
public void createUser_withInvalidEmailTest() {
try {
userService.createUser("아힝홍항", "112233", "이영종", "test.png");
fail();
} catch (ServiceException ex) {
assertEquals(ServiceErrorMessage.EMAIL_TYPE_INVALID, ex.getCode());
}
}

@Test
public void createUser_withInvalidPasswordTest() {
try {
userService.createUser("lee@zerobell.xyz", "", "이영종", "test.png");
fail();
} catch (ServiceException ex) {
assertEquals(ServiceErrorMessage.PASSWORD_TYPE_INVALID, ex.getCode());
}
}
}