diff --git a/community-backend/app/app-monolith/build.gradle b/community-backend/app/app-monolith/build.gradle index 3102ede3..dde59071 100644 --- a/community-backend/app/app-monolith/build.gradle +++ b/community-backend/app/app-monolith/build.gradle @@ -25,6 +25,9 @@ dependencies { implementation project(':core:core-user-resource') implementation project(':domain:domain-user-resource') + implementation project(':core:core-article') + implementation project(':domain:domain-article') + implementation 'org.springframework.boot:spring-boot-starter-data-jpa' implementation 'org.springframework.boot:spring-boot-starter-web' implementation 'org.springframework.boot:spring-boot-starter-actuator' diff --git a/community-backend/app/app-monolith/src/main/java/org/kiworkshop/community/article/api/ArticleController.java b/community-backend/app/app-monolith/src/main/java/org/kiworkshop/community/article/api/ArticleController.java new file mode 100644 index 00000000..7b0c477b --- /dev/null +++ b/community-backend/app/app-monolith/src/main/java/org/kiworkshop/community/article/api/ArticleController.java @@ -0,0 +1,48 @@ +package org.kiworkshop.community.article.api; + +import lombok.RequiredArgsConstructor; +import org.kiworkshop.community.article.dto.ArticleRequestDto; +import org.kiworkshop.community.article.dto.ArticleResponseDto; +import org.kiworkshop.community.article.domain.service.ArticleService; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.data.domain.Sort; +import org.springframework.data.web.PageableDefault; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +import java.security.Principal; + +@RestController +@RequestMapping("/article") +@RequiredArgsConstructor +public class ArticleController { + private final ArticleService articleService; + + @PostMapping + public Long create(@RequestBody ArticleRequestDto articleRequestDto, Principal principal) { + return articleService.create(articleRequestDto); + } + + @GetMapping + public Page readPage( + @PageableDefault(sort = "id", direction = Sort.Direction.DESC) Pageable pageable + ) { + return articleService.readPage(pageable); + } + + @GetMapping("/{id}") + public ArticleResponseDto read(@PathVariable Long id) { + return articleService.read(id); + } + + @DeleteMapping("/{id}") + public void delete(@PathVariable Long id, Principal principal) { + articleService.delete(id, principal); + } + + @PutMapping("/{id}") + public void update(@PathVariable Long id, @RequestBody ArticleRequestDto articleRequestDto, Principal principal) { + articleService.update(id, articleRequestDto); + } +} diff --git a/community-backend/app/app-monolith/src/test/java/org/kiworkshop/community/article/api/ArticleControllerTest.java b/community-backend/app/app-monolith/src/test/java/org/kiworkshop/community/article/api/ArticleControllerTest.java new file mode 100644 index 00000000..90e94548 --- /dev/null +++ b/community-backend/app/app-monolith/src/test/java/org/kiworkshop/community/article/api/ArticleControllerTest.java @@ -0,0 +1,4 @@ +package org.kiworkshop.community.article.api; + +public class ArticleControllerTest { +} diff --git a/community-backend/core/core-article/build.gradle b/community-backend/core/core-article/build.gradle new file mode 100644 index 00000000..51c419ea --- /dev/null +++ b/community-backend/core/core-article/build.gradle @@ -0,0 +1,15 @@ +plugins { + id 'java' +} + +version 'unspecified' + +repositories { + mavenCentral() +} + +dependencies { + implementation "javax.validation:validation-api:${javaxValidationApiVersion}" + + testFixturesImplementation "org.springframework:spring-test:${springTestVersion}" +} diff --git a/community-backend/core/core-article/lombok.config b/community-backend/core/core-article/lombok.config new file mode 100644 index 00000000..189c0bef --- /dev/null +++ b/community-backend/core/core-article/lombok.config @@ -0,0 +1,3 @@ +# This file is generated by the 'io.freefair.lombok' Gradle plugin +config.stopBubbling = true +lombok.addLombokGeneratedAnnotation = true diff --git a/community-backend/core/core-article/src/main/java/org/kiworkshop/community/article/dto/ArticleRequestDto.java b/community-backend/core/core-article/src/main/java/org/kiworkshop/community/article/dto/ArticleRequestDto.java new file mode 100644 index 00000000..ee4a83c5 --- /dev/null +++ b/community-backend/core/core-article/src/main/java/org/kiworkshop/community/article/dto/ArticleRequestDto.java @@ -0,0 +1,16 @@ +package org.kiworkshop.community.article.dto; + + +import javax.validation.constraints.NotEmpty; + +import lombok.Getter; + +@Getter +public class ArticleRequestDto { + @NotEmpty + private String title; + @NotEmpty + private String content; + @NotEmpty + private String username; +} diff --git a/community-backend/core/core-article/src/main/java/org/kiworkshop/community/article/dto/ArticleResponseDto.java b/community-backend/core/core-article/src/main/java/org/kiworkshop/community/article/dto/ArticleResponseDto.java new file mode 100644 index 00000000..56671f83 --- /dev/null +++ b/community-backend/core/core-article/src/main/java/org/kiworkshop/community/article/dto/ArticleResponseDto.java @@ -0,0 +1,33 @@ +package org.kiworkshop.community.article.dto; + +import java.time.ZonedDateTime; + +import lombok.Builder; +import lombok.Getter; + +@Getter +public class ArticleResponseDto { + private Long id; + private String title; + private String content; + private String username; + private ZonedDateTime createdAt; + private ZonedDateTime updatedAt; + + @Builder + private ArticleResponseDto( + Long id, + String title, + String content, + String username, + ZonedDateTime createdAt, + ZonedDateTime updatedAt + ) { + this.id = id; + this.title = title; + this.content =content; + this.username = username; + this.createdAt = createdAt; + this.updatedAt = updatedAt; + } +} diff --git a/community-backend/core/core-article/src/test/java/org/kiworkshop/community/article/dto/ArticleRequestDtoTest.java b/community-backend/core/core-article/src/test/java/org/kiworkshop/community/article/dto/ArticleRequestDtoTest.java new file mode 100644 index 00000000..be3ea5cd --- /dev/null +++ b/community-backend/core/core-article/src/test/java/org/kiworkshop/community/article/dto/ArticleRequestDtoTest.java @@ -0,0 +1,38 @@ +package org.kiworkshop.community.article.dto; + +import static org.assertj.core.api.BDDAssertions.then; + +import javax.validation.Validation; +import javax.validation.Validator; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.CsvSource; +import org.springframework.test.util.ReflectionTestUtils; + +class ArticleRequestDtoTest { + + private static final Validator validator = Validation.buildDefaultValidatorFactory().getValidator(); + private ArticleRequestDto articleRequestDto; + + @BeforeEach + void setUp() { + articleRequestDto = ArticleRequestDtoFixture.get(); + } + + @ParameterizedTest + @CsvSource({ + "title,empty", + "content,empty", + "username,empty" + }) + void validate_InvalidValue_ThrowException(String fieldName, String value) { + // given + String valueToInject = "empty".equals(value) ? "" : value; + ReflectionTestUtils.setField(articleRequestDto, fieldName, valueToInject); + + var violations = validator.validate(articleRequestDto); + + then(violations.size()).isEqualTo(1); + } +} diff --git a/community-backend/core/core-article/src/testFixtures/java/org/kiworkshop/community/article/dto/ArticleRequestDtoFixture.java b/community-backend/core/core-article/src/testFixtures/java/org/kiworkshop/community/article/dto/ArticleRequestDtoFixture.java new file mode 100644 index 00000000..13042468 --- /dev/null +++ b/community-backend/core/core-article/src/testFixtures/java/org/kiworkshop/community/article/dto/ArticleRequestDtoFixture.java @@ -0,0 +1,15 @@ +package org.kiworkshop.community.article.dto; + +import org.springframework.test.util.ReflectionTestUtils; + +public class ArticleRequestDtoFixture { + public static ArticleRequestDto get() { + ArticleRequestDto articleRequestDto = new ArticleRequestDto(); + + ReflectionTestUtils.setField(articleRequestDto, "title", "title"); + ReflectionTestUtils.setField(articleRequestDto, "content", "content"); + ReflectionTestUtils.setField(articleRequestDto, "username", "username"); + + return articleRequestDto; + } +} diff --git a/community-backend/core/core-article/src/testFixtures/java/org/kiworkshop/community/article/dto/ArticleResponseDtoFixture.java b/community-backend/core/core-article/src/testFixtures/java/org/kiworkshop/community/article/dto/ArticleResponseDtoFixture.java new file mode 100644 index 00000000..96a1aee0 --- /dev/null +++ b/community-backend/core/core-article/src/testFixtures/java/org/kiworkshop/community/article/dto/ArticleResponseDtoFixture.java @@ -0,0 +1,16 @@ +package org.kiworkshop.community.article.dto; + +import java.time.ZonedDateTime; + +public class ArticleResponseDtoFixture { + public static ArticleResponseDto get() { + return ArticleResponseDto.builder() + .id(1L) + .title("title") + .content("content") + .username("username") + .createdAt(ZonedDateTime.now()) + .updatedAt(ZonedDateTime.now()) + .build(); + } +} diff --git a/community-backend/db-migration/V8__Create_table_article.sql b/community-backend/db-migration/V8__Create_table_article.sql new file mode 100644 index 00000000..e17134dd --- /dev/null +++ b/community-backend/db-migration/V8__Create_table_article.sql @@ -0,0 +1,10 @@ +create table article ( + id bigint not null auto_increment, + created_at datetime(6), + updated_at datetime(6), + title varchar(255) not null, + content LONGTEXT not null, + username varchar(255) not null, + active bit, + primary key (id) +); diff --git a/community-backend/domain/domain-article/build.gradle b/community-backend/domain/domain-article/build.gradle new file mode 100644 index 00000000..cc2dc428 --- /dev/null +++ b/community-backend/domain/domain-article/build.gradle @@ -0,0 +1,21 @@ +plugins { + id 'java' +} + +version 'unspecified' + +repositories { + mavenCentral() +} + +dependencies { + implementation project(':domain:domain-common') + implementation project(':core:core-article') + + implementation 'org.springframework.boot:spring-boot-starter-data-jpa' + + testImplementation testFixtures(project(":core:core-article")) + testFixturesImplementation project(":core:core-article") + testFixturesImplementation project(":domain:domain-common") + testFixturesImplementation "org.springframework:spring-test:${springTestVersion}" +} diff --git a/community-backend/domain/domain-article/lombok.config b/community-backend/domain/domain-article/lombok.config new file mode 100644 index 00000000..189c0bef --- /dev/null +++ b/community-backend/domain/domain-article/lombok.config @@ -0,0 +1,3 @@ +# This file is generated by the 'io.freefair.lombok' Gradle plugin +config.stopBubbling = true +lombok.addLombokGeneratedAnnotation = true diff --git a/community-backend/domain/domain-article/src/main/java/org/kiworkshop/community/article/domain/exception/ArticleNotFoundException.java b/community-backend/domain/domain-article/src/main/java/org/kiworkshop/community/article/domain/exception/ArticleNotFoundException.java new file mode 100644 index 00000000..3194a95f --- /dev/null +++ b/community-backend/domain/domain-article/src/main/java/org/kiworkshop/community/article/domain/exception/ArticleNotFoundException.java @@ -0,0 +1,9 @@ +package org.kiworkshop.community.article.domain.exception; + +import javax.persistence.EntityNotFoundException; + +public class ArticleNotFoundException extends EntityNotFoundException { + public ArticleNotFoundException(Long id) { + super("Article of id:" + id + " is not found."); + } +} diff --git a/community-backend/domain/domain-article/src/main/java/org/kiworkshop/community/article/domain/model/Article.java b/community-backend/domain/domain-article/src/main/java/org/kiworkshop/community/article/domain/model/Article.java new file mode 100644 index 00000000..5a0d6e27 --- /dev/null +++ b/community-backend/domain/domain-article/src/main/java/org/kiworkshop/community/article/domain/model/Article.java @@ -0,0 +1,70 @@ +package org.kiworkshop.community.article.domain.model; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.Lob; + +import org.kiworkshop.community.common.domain.BaseEntity; +import org.springframework.util.Assert; + +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@NoArgsConstructor +@Getter +@Entity +public class Article extends BaseEntity { + private static final String DELETED_ARTICLE_MESSAGE = "삭제된 게시글입니다."; + + @Column(nullable = false) + private String title; + @Lob + @Column(nullable = false) + private String content; + @Column(nullable = false) + private String username; + private boolean active = true; + + @Builder + private Article(String title, String content, String username) { + Assert.hasLength(title, "title must have length."); + Assert.hasLength(content, "content must have length."); + Assert.hasLength(username, "username must have length."); + this.title = title; + this.content = content; + this.username = username; + } + + public void update(Article article) { + // TODO: 20. 8. 31. Error Code 가 400이 되어야 할지? 403이 되어야 할지 고민 + Assert.isTrue(this.username.equals(article.username), "unauthorized username"); + this.title = article.title; + this.content = article.content; + } + + public boolean isAuthor(String name) { + return this.username.equals(name); + } + + public void deactivate(String username) { + if (!this.username.equals(username)) { + throw new IllegalArgumentException("unauthorized user"); + } + this.active = false; + } + + public String getTitle() { + if (this.active) { + return DELETED_ARTICLE_MESSAGE; + } + return this.title; + } + + public String getContent() { + if (this.active) { + return DELETED_ARTICLE_MESSAGE; + } + return this.content; + } +} diff --git a/community-backend/domain/domain-article/src/main/java/org/kiworkshop/community/article/domain/model/ArticleRepository.java b/community-backend/domain/domain-article/src/main/java/org/kiworkshop/community/article/domain/model/ArticleRepository.java new file mode 100644 index 00000000..5558b531 --- /dev/null +++ b/community-backend/domain/domain-article/src/main/java/org/kiworkshop/community/article/domain/model/ArticleRepository.java @@ -0,0 +1,10 @@ +package org.kiworkshop.community.article.domain.model; + + +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface ArticleRepository extends JpaRepository { + Page
findAllByActiveIsTrue(Pageable pageable); +} diff --git a/community-backend/domain/domain-article/src/main/java/org/kiworkshop/community/article/domain/service/ArticleConverter.java b/community-backend/domain/domain-article/src/main/java/org/kiworkshop/community/article/domain/service/ArticleConverter.java new file mode 100644 index 00000000..fe7e82b8 --- /dev/null +++ b/community-backend/domain/domain-article/src/main/java/org/kiworkshop/community/article/domain/service/ArticleConverter.java @@ -0,0 +1,30 @@ +package org.kiworkshop.community.article.domain.service; + +import org.kiworkshop.community.article.domain.model.Article; +import org.kiworkshop.community.article.dto.ArticleRequestDto; +import org.kiworkshop.community.article.dto.ArticleResponseDto; + +import lombok.AccessLevel; +import lombok.NoArgsConstructor; + +@NoArgsConstructor(access = AccessLevel.PRIVATE) +public class ArticleConverter { + public static Article toEntity(ArticleRequestDto articleRequestDto) { + return Article.builder() + .title(articleRequestDto.getTitle()) + .content(articleRequestDto.getContent()) + .username(articleRequestDto.getUsername()) + .build(); + } + + public static ArticleResponseDto from(Article article) { + return ArticleResponseDto.builder() + .id(article.getId()) + .title(article.getTitle()) + .content(article.getContent()) + .username(article.getUsername()) + .createdAt(article.getCreatedAt()) + .updatedAt(article.getUpdatedAt()) + .build(); + } +} diff --git a/community-backend/domain/domain-article/src/main/java/org/kiworkshop/community/article/domain/service/ArticleService.java b/community-backend/domain/domain-article/src/main/java/org/kiworkshop/community/article/domain/service/ArticleService.java new file mode 100644 index 00000000..bc19180c --- /dev/null +++ b/community-backend/domain/domain-article/src/main/java/org/kiworkshop/community/article/domain/service/ArticleService.java @@ -0,0 +1,53 @@ +package org.kiworkshop.community.article.domain.service; + +import java.security.Principal; + +import org.kiworkshop.community.article.domain.exception.ArticleNotFoundException; +import org.kiworkshop.community.article.domain.model.Article; +import org.kiworkshop.community.article.domain.model.ArticleRepository; +import org.kiworkshop.community.article.dto.ArticleRequestDto; +import org.kiworkshop.community.article.dto.ArticleResponseDto; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.stereotype.Service; + +import lombok.RequiredArgsConstructor; + +@RequiredArgsConstructor +@Service +public class ArticleService { + private final ArticleRepository articleRepository; + + public Long create(ArticleRequestDto articleRequestDto) { + Article article = articleRepository.save(ArticleConverter.toEntity(articleRequestDto)); + return article.getId(); + } + + public Page readPage(Pageable pageable) { + return articleRepository.findAllByActiveIsTrue(pageable).map(ArticleConverter::from); + } + + public ArticleResponseDto read(Long id) { + Article article = findById(id); + return ArticleConverter.from(article); + } + + public void update(Long id, ArticleRequestDto articleRequestDto) { + Article article = findById(id); + article.update(ArticleConverter.toEntity(articleRequestDto)); + } + + public void delete(Long id, Principal principal) { + Article article = findById(id); + article.deactivate(principal.getName()); + // TODO: 20. 8. 31. soft delete를 할지? hard delete를 할지 고민 + // if (!article.isAuthor(principal.getName())) { + // throw new IllegalArgumentException("unauthorized user"); + // } + // articleRepository.delete(article); + } + + private Article findById(Long id) { + return articleRepository.findById(id).orElseThrow(() -> new ArticleNotFoundException(id)); + } +} diff --git a/community-backend/domain/domain-article/src/test/java/org/kiworkshop/community/article/domain/service/ArticleServiceTest.java b/community-backend/domain/domain-article/src/test/java/org/kiworkshop/community/article/domain/service/ArticleServiceTest.java new file mode 100644 index 00000000..14729a76 --- /dev/null +++ b/community-backend/domain/domain-article/src/test/java/org/kiworkshop/community/article/domain/service/ArticleServiceTest.java @@ -0,0 +1,142 @@ +package org.kiworkshop.community.article.domain.service; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyLong; +import static org.mockito.BDDMockito.*; + +import java.security.Principal; +import java.util.List; +import java.util.Optional; +import java.util.stream.Collectors; +import java.util.stream.LongStream; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.kiworkshop.community.article.domain.exception.ArticleNotFoundException; +import org.kiworkshop.community.article.domain.model.Article; +import org.kiworkshop.community.article.domain.model.ArticleFixture; +import org.kiworkshop.community.article.domain.model.ArticleRepository; +import org.kiworkshop.community.article.dto.ArticleRequestDto; +import org.kiworkshop.community.article.dto.ArticleRequestDtoFixture; +import org.kiworkshop.community.article.dto.ArticleResponseDto; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageImpl; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Pageable; +import org.springframework.test.util.ReflectionTestUtils; + +@ExtendWith(MockitoExtension.class) +class ArticleServiceTest { + private ArticleService articleService; + @Mock + private ArticleRepository articleRepository; + @Mock + private Principal principal; + private Article article; + + @BeforeEach + void setUp() { + this.articleService = new ArticleService(articleRepository); + this.article = ArticleFixture.get(); + } + + @Test + void create() { + //given + ArticleRequestDto articleRequestDto = ArticleRequestDtoFixture.get(); + given(articleRepository.save(any(Article.class))).willReturn(article); + //when + Long id = articleService.create(articleRequestDto); + //then + assertThat(id).isNotNull(); + then(articleRepository).should().save(any(Article.class)); + } + + @Test + void readPage() { + Long articleNum = 10L; + // given + List
articles = LongStream.rangeClosed(1L, articleNum) + .mapToObj(ArticleFixture::get) + .collect(Collectors.toList()); + PageImpl
articlePage = new PageImpl<>(articles); + given(articleRepository.findAllByActiveIsTrue(any())).willReturn(articlePage); + + // when + Pageable pageable = PageRequest.of(0, articleNum.intValue()); + Page articleResponseDtoPage = articleService.readPage(pageable); + + // then + assertThat(articleResponseDtoPage.getTotalElements()).isEqualTo(articleNum); + } + + @Test + void read() { + //given + given(articleRepository.findById(anyLong())).willReturn(Optional.of(article)); + //when + ArticleResponseDto articleResponseDto = articleService.read(1L); + //then + assertThat(articleResponseDto.getTitle()).isEqualTo(article.getTitle()); + assertThat(articleResponseDto.getContent()).isEqualTo(article.getContent()); + then(articleRepository).should().findById(anyLong()); + } + + @Test + void update() { + //given + ArticleRequestDto articleRequestDto = ArticleRequestDtoFixture.get(); + given(articleRepository.findById(anyLong())).willReturn(Optional.of(article)); + //when + articleService.update(1L, articleRequestDto); + //then + then(articleRepository).should().findById(anyLong()); + } + + @Test + void update_throw_exception() { + //given + ArticleRequestDto articleRequestDto = ArticleRequestDtoFixture.get(); + given(articleRepository.findById(anyLong())).willReturn(Optional.of(article)); + + ReflectionTestUtils.setField(articleRequestDto, "username", "wrong username"); + //when & then + assertThrows(IllegalArgumentException.class, () -> articleService.update(1L, articleRequestDto)); + then(articleRepository).should().findById(anyLong()); + } + + @Test + void delete() { + //given + given(articleRepository.findById(anyLong())).willReturn(Optional.of(article)); + given(principal.getName()).willReturn("username"); + //when + articleService.delete(1L, principal); + //then + assertThat(article.isActive()).isEqualTo(false); + } + + @Test + void delete_throw_exception() { + //given + given(articleRepository.findById(anyLong())).willReturn(Optional.of(article)); + given(principal.getName()).willReturn("username1"); + //when + assertThrows(IllegalArgumentException.class, () -> articleService.delete(1L, principal)); + then(articleRepository).should().findById(anyLong()); + } + + @Test + void findByIdThrowsException() { + //given + ArticleRequestDto articleRequestDto = ArticleRequestDtoFixture.get(); + //when & then + assertThrows(ArticleNotFoundException.class, () -> articleService.read(1L)); + assertThrows(ArticleNotFoundException.class, () -> articleService.update(1L, articleRequestDto)); + } +} diff --git a/community-backend/domain/domain-article/src/testFixtures/java/org/kiworkshop/community/article/domain/model/ArticleFixture.java b/community-backend/domain/domain-article/src/testFixtures/java/org/kiworkshop/community/article/domain/model/ArticleFixture.java new file mode 100644 index 00000000..09a122db --- /dev/null +++ b/community-backend/domain/domain-article/src/testFixtures/java/org/kiworkshop/community/article/domain/model/ArticleFixture.java @@ -0,0 +1,28 @@ +package org.kiworkshop.community.article.domain.model; + +import java.time.ZonedDateTime; + +import org.springframework.test.util.ReflectionTestUtils; + +import lombok.AccessLevel; +import lombok.NoArgsConstructor; + +@NoArgsConstructor(access = AccessLevel.PRIVATE) +public class ArticleFixture { + public static Article get() { + return get(1L); + } + + public static Article get(Long id) { + Article article = new Article(); + + ReflectionTestUtils.setField(article, "id", id); + ReflectionTestUtils.setField(article, "title", "title"); + ReflectionTestUtils.setField(article, "content", "content"); + ReflectionTestUtils.setField(article, "username", "username"); + ReflectionTestUtils.setField(article, "createdAt", ZonedDateTime.now()); + ReflectionTestUtils.setField(article, "updatedAt", ZonedDateTime.now()); + + return article; + } +} diff --git a/community-backend/settings.gradle b/community-backend/settings.gradle index 10ae2096..7864aeff 100644 --- a/community-backend/settings.gradle +++ b/community-backend/settings.gradle @@ -15,12 +15,14 @@ include 'domain:domain-file' include 'domain:domain-comment' include 'domain:domain-common' include 'domain:domain-user-resource' +include 'domain:domain-article' include 'core:core-mother' include 'core:core-file' include 'core:core-comment' include 'core:core-auth' include 'core:core-user-resource' +include 'core:core-article' include 'in-system-available:common-web'