diff --git a/.github/workflows/auto-check.yml b/.github/workflows/auto-check.yml
new file mode 100644
index 0000000..6d6889a
--- /dev/null
+++ b/.github/workflows/auto-check.yml
@@ -0,0 +1,43 @@
+name: check
+on: pull_request
+
+jobs:
+ checkstyle:
+ name: Checkstyle
+ runs-on: ubuntu-18.04
+ steps:
+ - uses: actions/checkout@v2
+ - uses: reviewdog/action-setup@v1
+ with:
+ reviewdog_version: latest
+ - name: download checkstyle
+ run: curl -o checkstyle.jar -L https://github.com/checkstyle/checkstyle/releases/download/checkstyle-9.3/checkstyle-9.3-all.jar
+ - name: checkstyle
+ env:
+ REVIEWDOG_GITHUB_API_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ run: java -jar checkstyle.jar -c config/checkstyle/checkstyle.xml -f xml . | reviewdog -f=checkstyle -name="Checkstyle Report" -reporter="github-check" -fail-on-error=true -level="error" -filter-mode=nofilter
+
+ mysql-integration-test:
+ runs-on: ubuntu-latest
+ services:
+ mysql:
+ image: mysql:5.7
+ ports:
+ - 3306:3306
+ env:
+ MYSQL_ROOT_PASSWORD: "123456"
+ MYSQL_DATABASE: databasir
+ steps:
+ - uses: actions/checkout@v2
+ - name: Set up JDK 11
+ uses: actions/setup-java@v1
+ with:
+ java-version: '11'
+ server-id: github # Value of the distributionManagement/repository/id field of the pom.xml
+ settings-path: ${{ github.workspace }} # location for the settings.xml file
+
+ - name: Gradle Permission Grant
+ run: chmod +x ./gradlew
+
+ - name: Gradle Test
+ run: ./gradlew api:check core:check
diff --git a/.github/workflows/auto-checkstyle.yml b/.github/workflows/auto-checkstyle.yml
deleted file mode 100644
index 549d67f..0000000
--- a/.github/workflows/auto-checkstyle.yml
+++ /dev/null
@@ -1,18 +0,0 @@
-name: check
-on: pull_request
-
-jobs:
- checkstyle:
- name: Checkstyle
- runs-on: ubuntu-18.04
- steps:
- - uses: actions/checkout@v2
- - uses: reviewdog/action-setup@v1
- with:
- reviewdog_version: latest
- - name: download checkstyle
- run: curl -o checkstyle.jar -L https://github.com/checkstyle/checkstyle/releases/download/checkstyle-9.3/checkstyle-9.3-all.jar
- - name: checkstyle
- env:
- REVIEWDOG_GITHUB_API_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- run: java -jar checkstyle.jar -c config/checkstyle/checkstyle.xml -f xml . | reviewdog -f=checkstyle -name="Checkstyle Report" -reporter="github-check" -fail-on-error=true -level="error" -filter-mode=nofilter
\ No newline at end of file
diff --git a/core/build.gradle b/core/build.gradle
index 59aba72..7d03df8 100644
--- a/core/build.gradle
+++ b/core/build.gradle
@@ -37,5 +37,6 @@ dependencies {
// test
testImplementation "mysql:mysql-connector-java:${mysqlConnectorVersion}"
+ testImplementation 'org.springframework.boot:spring-boot-starter-test'
}
diff --git a/core/src/main/java/com/databasir/core/config/AsyncConfig.java b/core/src/main/java/com/databasir/core/config/AsyncConfig.java
new file mode 100644
index 0000000..bbecaf6
--- /dev/null
+++ b/core/src/main/java/com/databasir/core/config/AsyncConfig.java
@@ -0,0 +1,26 @@
+package com.databasir.core.config;
+
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.scheduling.annotation.AsyncConfigurer;
+import org.springframework.scheduling.annotation.EnableAsync;
+import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
+
+import java.util.concurrent.Executor;
+
+@EnableAsync
+@Configuration
+@Slf4j
+public class AsyncConfig implements AsyncConfigurer {
+
+ @Bean
+ public Executor mailThreadPoolTaskExecutor() {
+ ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
+ int availableProcessorCount = Runtime.getRuntime().availableProcessors();
+ executor.setCorePoolSize(availableProcessorCount << 1);
+ executor.setMaxPoolSize(32);
+ executor.setAllowCoreThreadTimeOut(true);
+ return executor;
+ }
+}
diff --git a/core/src/main/java/com/databasir/core/infrastructure/event/subscriber/DocumentEventSubscriber.java b/core/src/main/java/com/databasir/core/infrastructure/event/subscriber/DocumentEventSubscriber.java
index ba5f18a..a009493 100644
--- a/core/src/main/java/com/databasir/core/infrastructure/event/subscriber/DocumentEventSubscriber.java
+++ b/core/src/main/java/com/databasir/core/infrastructure/event/subscriber/DocumentEventSubscriber.java
@@ -13,6 +13,7 @@ import com.databasir.dao.tables.pojos.UserPojo;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.event.EventListener;
+import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;
import java.util.Collections;
@@ -24,6 +25,7 @@ import java.util.stream.Collectors;
@Component
@RequiredArgsConstructor
@Slf4j
+@Async("mailThreadPoolTaskExecutor")
public class DocumentEventSubscriber {
private final ProjectDao projectDao;
@@ -42,19 +44,20 @@ public class DocumentEventSubscriber {
ProjectPojo project = projectDao.selectById(created.getProjectId());
List to = userDao.selectEnabledGroupMembers(project.getGroupId())
.stream()
- .filter(UserPojo::getEnabled)
.map(UserPojo::getEmail)
.filter(userEmail -> userEmail.contains("@"))
.collect(Collectors.toList());
- String subject = project.getName() + " 文档有新的内容变更";
- List
您已成功注册 Databasir,用户名为 ${username}。
+
+
为了您的账号安全,请尽快通过以下密码登录系统并及时修改新密码
- ${newPassword}
+ ${password}
diff --git a/core/src/test/java/com/databasir/core/BaseTest.java b/core/src/test/java/com/databasir/core/BaseTest.java
new file mode 100644
index 0000000..443cfde
--- /dev/null
+++ b/core/src/test/java/com/databasir/core/BaseTest.java
@@ -0,0 +1,14 @@
+package com.databasir.core;
+
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.ActiveProfiles;
+import org.springframework.test.context.jdbc.Sql;
+import org.springframework.test.context.junit.jupiter.SpringExtension;
+
+@SpringBootTest(classes = CoreTestApplication.class)
+@ActiveProfiles("ut")
+@ExtendWith(SpringExtension.class)
+@Sql({"classpath:sql/init.sql"})
+public class BaseTest {
+}
diff --git a/core/src/test/java/com/databasir/core/CoreTestApplication.java b/core/src/test/java/com/databasir/core/CoreTestApplication.java
new file mode 100644
index 0000000..6c9a7b2
--- /dev/null
+++ b/core/src/test/java/com/databasir/core/CoreTestApplication.java
@@ -0,0 +1,22 @@
+package com.databasir.core;
+
+import com.databasir.core.config.AsyncConfig;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.autoconfigure.r2dbc.R2dbcAutoConfiguration;
+import org.springframework.context.annotation.ComponentScan;
+import org.springframework.context.annotation.FilterType;
+
+@SpringBootApplication(exclude = {
+ R2dbcAutoConfiguration.class
+})
+@ComponentScan(
+ basePackages = "com.databasir",
+ excludeFilters = {
+ @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = AsyncConfig.class)
+ })
+public class CoreTestApplication {
+ public static void main(String[] args) {
+ SpringApplication.run(CoreTestApplication.class, args);
+ }
+}
diff --git a/core/src/test/java/com/databasir/core/domain/group/service/GroupServiceTest.java b/core/src/test/java/com/databasir/core/domain/group/service/GroupServiceTest.java
new file mode 100644
index 0000000..a4ee563
--- /dev/null
+++ b/core/src/test/java/com/databasir/core/domain/group/service/GroupServiceTest.java
@@ -0,0 +1,32 @@
+package com.databasir.core.domain.group.service;
+
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+class GroupServiceTest {
+
+ @Test
+ void create() {
+ }
+
+ @Test
+ void update() {
+ }
+
+ @Test
+ void delete() {
+ }
+
+ @Test
+ void removeMember() {
+ }
+
+ @Test
+ void addMember() {
+ }
+
+ @Test
+ void changeMemberRole() {
+ }
+}
\ No newline at end of file
diff --git a/core/src/test/java/com/databasir/core/domain/user/service/UserServiceTest.java b/core/src/test/java/com/databasir/core/domain/user/service/UserServiceTest.java
new file mode 100644
index 0000000..15b9464
--- /dev/null
+++ b/core/src/test/java/com/databasir/core/domain/user/service/UserServiceTest.java
@@ -0,0 +1,97 @@
+package com.databasir.core.domain.user.service;
+
+import com.databasir.core.BaseTest;
+import com.databasir.core.domain.user.data.UserCreateRequest;
+import com.databasir.core.domain.user.data.UserSource;
+import com.databasir.core.infrastructure.event.subscriber.UserEventSubscriber;
+import com.databasir.dao.impl.LoginDao;
+import com.databasir.dao.impl.UserDao;
+import com.databasir.dao.tables.pojos.LoginPojo;
+import com.databasir.dao.tables.pojos.UserPojo;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.mock.mockito.MockBean;
+import org.springframework.test.context.jdbc.Sql;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.util.Optional;
+import java.util.UUID;
+
+import static org.junit.jupiter.api.Assertions.*;
+import static org.mockito.Mockito.*;
+
+@Transactional
+class UserServiceTest extends BaseTest {
+
+ @Autowired
+ private UserService userService;
+
+ @MockBean
+ private UserEventSubscriber userEventSubscriber;
+
+ @Autowired
+ private UserDao userDao;
+
+ @Autowired
+ private LoginDao loginDao;
+
+ @Test
+ void create() {
+ doNothing().when(userEventSubscriber).onUserCreated(any());
+
+ String username = UUID.randomUUID().toString().replace("-", "");
+ UserCreateRequest request = new UserCreateRequest();
+ request.setAvatar(username);
+ request.setUsername(username);
+ request.setNickname(username);
+ request.setEmail(username + "@Databasir-ut.com");
+ request.setPassword("123456");
+ request.setEnabled(true);
+ Integer id = userService.create(request, UserSource.MANUAL);
+ assertNotNull(id);
+ verify(userEventSubscriber, times(1)).onUserCreated(any());
+ }
+
+ @Test
+ @Sql("classpath:sql/domain/user/RenewPassword.sql")
+ void renewPassword() {
+ doNothing().when(userEventSubscriber).onPasswordRenewed(any());
+ String newPassword = userService.renewPassword(1, 2);
+ assertNotNull(newPassword);
+ assertEquals(8, newPassword.length());
+ verify(userEventSubscriber, times(1)).onPasswordRenewed(any());
+ }
+
+ @Test
+ @Sql("classpath:sql/domain/user/SwitchEnableStatus.sql")
+ void switchEnableStatusToFalse() {
+ Integer userId = 1;
+ userService.switchEnableStatus(userId, false);
+ UserPojo user = userDao.selectById(userId);
+ assertNotNull(user);
+ assertFalse(user.getEnabled());
+
+ Optional loginPojoOpt = loginDao.selectByUserId(userId);
+ assertTrue(loginPojoOpt.isEmpty());
+ }
+
+ @Test
+ void removeSysOwnerFrom() {
+ // TODO
+ }
+
+ @Test
+ void addSysOwnerTo() {
+ // TODO
+ }
+
+ @Test
+ void updatePassword() {
+ // TODO
+ }
+
+ @Test
+ void updateNickname() {
+ // TODO
+ }
+}
\ No newline at end of file
diff --git a/core/src/test/java/com/databasir/core/infrastructure/event/subscriber/DocumentEventSubscriberTest.java b/core/src/test/java/com/databasir/core/infrastructure/event/subscriber/DocumentEventSubscriberTest.java
new file mode 100644
index 0000000..93807c5
--- /dev/null
+++ b/core/src/test/java/com/databasir/core/infrastructure/event/subscriber/DocumentEventSubscriberTest.java
@@ -0,0 +1,63 @@
+package com.databasir.core.infrastructure.event.subscriber;
+
+import com.databasir.core.BaseTest;
+import com.databasir.core.diff.data.DiffType;
+import com.databasir.core.diff.data.FieldDiff;
+import com.databasir.core.diff.data.RootDiff;
+import com.databasir.core.domain.document.event.DocumentUpdated;
+import com.databasir.core.infrastructure.mail.MailSender;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.mock.mockito.MockBean;
+import org.springframework.test.context.jdbc.Sql;
+
+import java.util.List;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.*;
+
+class DocumentEventSubscriberTest extends BaseTest {
+
+ @Autowired
+ private DocumentEventSubscriber documentEventSubscriber;
+
+ @MockBean
+ private MailSender mailSender;
+
+ @BeforeEach
+ void mock() {
+ doNothing().when(mailSender).batchSendHtml(any(), any(), any(), any());
+ }
+
+ @Test
+ @Sql("classpath:/sql/event/subscriber/DocumentEventSubscriberTest.sql")
+ void onDocumentUpdated() {
+ var event = new DocumentUpdated();
+ RootDiff diff = new RootDiff();
+ FieldDiff tablesFields = FieldDiff.builder()
+ .fieldName("tables")
+ .fields(List.of(
+ tableDiff("user", DiffType.ADDED),
+ tableDiff("role", DiffType.MODIFIED),
+ tableDiff("permission", DiffType.REMOVED)
+ )
+ )
+ .build();
+ diff.setFields(List.of(tablesFields));
+ diff.setDiffType(DiffType.MODIFIED);
+ event.setDiff(diff);
+ event.setNewVersion(2L);
+ event.setOldVersion(1L);
+ event.setProjectId(1);
+ documentEventSubscriber.onDocumentUpdated(event);
+ verify(mailSender, times(1)).batchSendHtml(any(), any(), any(), any());
+ }
+
+ private FieldDiff tableDiff(String tableName, DiffType type) {
+ return FieldDiff.builder()
+ .fieldName(tableName)
+ .diffType(type)
+ .build();
+ }
+}
\ No newline at end of file
diff --git a/core/src/test/java/com/databasir/core/infrastructure/event/subscriber/UserEventSubscriberTest.java b/core/src/test/java/com/databasir/core/infrastructure/event/subscriber/UserEventSubscriberTest.java
new file mode 100644
index 0000000..df13add
--- /dev/null
+++ b/core/src/test/java/com/databasir/core/infrastructure/event/subscriber/UserEventSubscriberTest.java
@@ -0,0 +1,59 @@
+package com.databasir.core.infrastructure.event.subscriber;
+
+import com.databasir.core.BaseTest;
+import com.databasir.core.domain.user.data.UserSource;
+import com.databasir.core.domain.user.event.UserCreated;
+import com.databasir.core.domain.user.event.UserPasswordRenewed;
+import com.databasir.core.infrastructure.mail.MailSender;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.mock.mockito.MockBean;
+import org.springframework.test.context.jdbc.Sql;
+
+import java.time.LocalDateTime;
+
+import static org.mockito.Mockito.*;
+
+class UserEventSubscriberTest extends BaseTest {
+
+ @Autowired
+ private UserEventSubscriber userEventSubscriber;
+
+ @MockBean
+ private MailSender mailSender;
+
+ @BeforeEach
+ void mock() {
+ doNothing().when(mailSender).sendHtml(any(), any(), any(), any());
+ }
+
+ @Test
+ @Sql("classpath:sql/event/subscriber/UserEventSubscriberTest.sql")
+ void onPasswordRenewed() {
+ var event = UserPasswordRenewed.builder()
+ .email("ut@databasir.com")
+ .newPassword("123456")
+ .nickname("demo")
+ .renewTime(LocalDateTime.now())
+ .renewByUserId(1)
+ .build();
+ userEventSubscriber.onPasswordRenewed(event);
+ verify(mailSender, times(1)).sendHtml(any(), any(), any(), any());
+ }
+
+ @Test
+ @Sql("classpath:sql/event/subscriber/UserEventSubscriberTest.sql")
+ void onUserCreated() {
+ var event = UserCreated.builder()
+ .username("ut")
+ .email("ut@databasir.com")
+ .rawPassword("123456")
+ .userId(1)
+ .nickname("demo")
+ .source(UserSource.MANUAL)
+ .build();
+ userEventSubscriber.onUserCreated(event);
+ verify(mailSender, times(1)).sendHtml(any(), any(), any(), any());
+ }
+}
\ No newline at end of file
diff --git a/core/src/test/resources/application-ut.properties b/core/src/test/resources/application-ut.properties
new file mode 100644
index 0000000..20aeaa1
--- /dev/null
+++ b/core/src/test/resources/application-ut.properties
@@ -0,0 +1,18 @@
+logging.level.org.jooq=INFO
+server.port=8080
+# datasource
+spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
+spring.datasource.username=${databasir.db.username}
+spring.datasource.password=${databasir.db.password}
+spring.datasource.url=jdbc:mysql://${databasir.db.url}/${databasir.db.name:databasir}
+# driver directory
+spring.jooq.sql-dialect=mysql
+# flyway
+spring.flyway.enabled=true
+spring.flyway.baseline-on-migrate=true
+spring.flyway.locations=classpath:db/migration
+# db
+databasir.db.url=localhost:3306
+databasir.db.username=root
+databasir.db.password=123456
+databasir.db.driver-directory=drivers
\ No newline at end of file
diff --git a/core/src/test/resources/sql/domain/user/AddSysOwnerTo.sql b/core/src/test/resources/sql/domain/user/AddSysOwnerTo.sql
new file mode 100644
index 0000000..a1bdd23
--- /dev/null
+++ b/core/src/test/resources/sql/domain/user/AddSysOwnerTo.sql
@@ -0,0 +1,4 @@
+INSERT IGNORE INTO databasir.user (id, email, username, password, nickname, avatar, enabled)
+VALUES (1, 'N/A', 'databasir', '$2a$10$8Wjfdbbk76jDNbQ0zKq', 'Databasir Admin', NULL, 1),
+ (2, 'sysOwner@databasir.com', 'sysOwner', '$2a$10$wXPDzPceCXeU1PLXGKRAEW', 'a', NULL, 1),
+ (3, 'notSysOwner@databasir.com', 'notSysOwner', '$2a$10$wXPDzPceU1PLXGKRAEW', 'b', NULL, 1);
diff --git a/core/src/test/resources/sql/domain/user/RenewPassword.sql b/core/src/test/resources/sql/domain/user/RenewPassword.sql
new file mode 100644
index 0000000..6f57ef2
--- /dev/null
+++ b/core/src/test/resources/sql/domain/user/RenewPassword.sql
@@ -0,0 +1,3 @@
+INSERT IGNORE INTO databasir.user (id, email, username, password, nickname, avatar, enabled)
+VALUES (1, 'N/A', 'databasir', '$2a$10$8WjfdbbDpzvkz5Rc.8TBk76jDNbQ0zKq', 'Databasir Admin', NULL, 1),
+ (2, 'vran@databasir.com', 'vran', '$2a$10$wXPDzPceCpqYErlZ3DRh.gOpgXXeU1PLXGKRAEW', 'vranssss', NULL, 1);
\ No newline at end of file
diff --git a/core/src/test/resources/sql/domain/user/SwitchEnableStatus.sql b/core/src/test/resources/sql/domain/user/SwitchEnableStatus.sql
new file mode 100644
index 0000000..8819e64
--- /dev/null
+++ b/core/src/test/resources/sql/domain/user/SwitchEnableStatus.sql
@@ -0,0 +1,7 @@
+INSERT IGNORE INTO databasir.user (id, email, username, password, nickname, avatar, enabled)
+VALUES (1, 'N/A', 'databasir', '$2a$10$8WjfdbbDpzvkz5Rc.8TBk76jDNbQ0zKq', 'Databasir Admin', NULL, 1),
+ (2, 'vran@databasir.com', 'vran', '$2a$10$wXPDzPceCpqYErlZ3DRh.gOpgXXeU1PLXGKRAEW', 'vranssss', NULL, 1);
+
+INSERT IGNORE INTO databasir.login (user_id, access_token, refresh_token, access_token_expire_at,
+ refresh_token_expire_at)
+VALUES (2, 'eyJ0eXAiOiJKV1QM', '1a884c14ef6542ce0261', '2022-03-12 20:24:28', '2022-03-27 20:09:29');
diff --git a/core/src/test/resources/sql/event/subscriber/DocumentEventSubscriberTest.sql b/core/src/test/resources/sql/event/subscriber/DocumentEventSubscriberTest.sql
new file mode 100644
index 0000000..4aa49f3
--- /dev/null
+++ b/core/src/test/resources/sql/event/subscriber/DocumentEventSubscriberTest.sql
@@ -0,0 +1,22 @@
+INSERT IGNORE INTO databasir.user (id, email, username, password, nickname, avatar, enabled)
+VALUES (1, 'N/A', 'databasir', '$2a$10$8WjfdbbDpzvkz5Rc.8TBk76jDNbQ0zKq', 'Databasir Admin', NULL, 1),
+ (2, 'vran@databasir.com', 'vran', '$2a$10$wXPDzPceCpqYErlZ3DRh.gOpgXXeU1PLXGKRAEW', 'vranssss', NULL, 1),
+ (3, 'test@databasir.com', 'test', '$2a$10$XbnZlQB26cKKGB4WLlgZxxwbUr9tD1Amn/3Tf5H0i', 'test', NULL, 1),
+ (4, 'sample@databasir.com', 'sample', '$2a$10$Ua0zrJ7.HDb6ZIRNWb7fCJiG2OZRTN1.', 'sample', NULL, 1),
+ (5, 'demo@databasir.com', 'demo', '$2a$10$J4JT19JBO3LpWAvRARDxieFtm/pFQtna.dDq', 'demo', NULL, 0);
+
+INSERT IGNORE INTO databasir.project (id, name, description, group_id, deleted, deleted_token)
+VALUES (1, 'demo', 'demo', 1, 0, 1),
+ (2, 'no member', 'no member', 1, 0, 1);
+
+INSERT IGNORE INTO databasir.`group` (id, name, description, deleted)
+VALUES (1, '会员平台', '会员平台', 0),
+ (2, '成员为空', '会员平台', 0);
+
+INSERT IGNORE INTO databasir.user_role (user_id, role, group_id)
+VALUES (1, 'SYS_OWNER', NULL),
+ (1, 'GROUP_OWNER', 1),
+ (2, 'GROUP_OWNER', 1),
+ (3, 'GROUP_MEMBER', 1),
+ (4, 'GROUP_OWNER', 1),
+ (5, 'GROUP_OWNER', 1);
diff --git a/core/src/test/resources/sql/event/subscriber/UserEventSubscriberTest.sql b/core/src/test/resources/sql/event/subscriber/UserEventSubscriberTest.sql
new file mode 100644
index 0000000..d052db5
--- /dev/null
+++ b/core/src/test/resources/sql/event/subscriber/UserEventSubscriberTest.sql
@@ -0,0 +1,7 @@
+INSERT IGNORE INTO databasir.user (id, email, username, password, nickname, avatar, enabled)
+VALUES (1, 'N/A', 'databasir', '$2a$10$8WjfdbbDpzvkz5Rc.8TBk76jDNbQ0zKq', 'Databasir Admin', NULL, 1),
+ (2, 'vran@databasir.com', 'vran', '$2a$10$wXPDzPceCpqYErlZ3DRh.gOpgXXeU1PLXGKRAEW', 'vranssss', NULL, 1),
+ (3, 'test@databasir.com', 'test', '$2a$10$XbnZlQB26cKKGB4WLlgZxxwbUr9tD1Amn/3Tf5H0i', 'test', NULL, 1),
+ (4, 'sample@databasir.com', 'sample', '$2a$10$Ua0zrJ7.HDb6ZIRNWb7fCJiG2OZRTN1.', 'sample', NULL, 1),
+ (5, 'demo@databasir.com', 'demo', '$2a$10$J4JT19JBO3LpWAvRARDxieFtm/pFQtna.dDq', 'demo', NULL, 0);
+
diff --git a/core/src/test/resources/sql/init.sql b/core/src/test/resources/sql/init.sql
new file mode 100644
index 0000000..b82c32f
--- /dev/null
+++ b/core/src/test/resources/sql/init.sql
@@ -0,0 +1,4 @@
+# mail configuration
+REPLACE INTO databasir.sys_mail (id, username, password, smtp_host, smtp_port, use_ssl, update_at, create_at)
+VALUES (999, 'ut@databasir.com', '123456', 'smtp.exmail.databasir.com', 465, 1, '2022-03-25 03:14:27',
+ '2022-03-21 14:20:56');