org.mapstruct
@@ -166,6 +174,7 @@
+
org.apache.maven.plugins
@@ -174,6 +183,31 @@
-Dfile.encoding=UTF-8
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+
+
+
+ org.projectlombok
+ lombok
+ 1.18.24
+
+
+ org.mapstruct
+ mapstruct-processor
+ ${mapstruct.version}
+
+
+ org.projectlombok
+ lombok-mapstruct-binding
+ ${lombok-mapstruct-binding.version}
+
+
+
+
diff --git a/resources/mails/email-confirmation.html b/resources/mails/email-confirmation.html
index 106e6129a..e2a16674f 100644
--- a/resources/mails/email-confirmation.html
+++ b/resources/mails/email-confirmation.html
@@ -1,13 +1,19 @@
-
+
- JiraRush - подтверждение почты
+ JiraRush - подтверждение почты
-
-Чтобы завершить настройку учетной записи и начать пользоваться JiraRush, подтвердите, что вы правильно указали вашу
+
+Чтобы завершить настройку учетной записи и начать пользоваться JiraRush, подтвердите, что вы правильно указали вашу
электронную почту.
-Подтвердить почту
+ Подтвердить почту
+
-
\ No newline at end of file
+
diff --git a/resources/mails/password-reset.html b/resources/mails/password-reset.html
index b37a49007..8d6b756fb 100644
--- a/resources/mails/password-reset.html
+++ b/resources/mails/password-reset.html
@@ -1,12 +1,18 @@
-
+
- JiraRush - установить новый пароль
+ JiraRush - установить новый пароль
-
-
-Установить пароль
+
+
+Установить пароль
+
\ No newline at end of file
diff --git a/resources/view/index.html b/resources/view/index.html
index e8656ef96..8a3deda9b 100644
--- a/resources/view/index.html
+++ b/resources/view/index.html
@@ -1,14 +1,21 @@
-
+
-
+
- JiraRush Home page
+ JiraRush Home page
+
+
diff --git a/resources/view/login.html b/resources/view/login.html
index 8765ca8ff..58916bc53 100644
--- a/resources/view/login.html
+++ b/resources/view/login.html
@@ -48,14 +48,14 @@ Sign in
type="button">
-
-
-
-
-
-
+
+
+
+
+
+
+
+
diff --git a/src/main/java/com/javarush/jira/JiraRushApplication.java b/src/main/java/com/javarush/jira/JiraRushApplication.java
index 58be49fe7..96174f090 100644
--- a/src/main/java/com/javarush/jira/JiraRushApplication.java
+++ b/src/main/java/com/javarush/jira/JiraRushApplication.java
@@ -10,7 +10,6 @@
@EnableConfigurationProperties(AppProperties.class)
@EnableCaching
public class JiraRushApplication {
-
public static void main(String[] args) {
SpringApplication.run(JiraRushApplication.class, args);
}
diff --git a/src/main/java/com/javarush/jira/bugtracking/Handlers.java b/src/main/java/com/javarush/jira/bugtracking/Handlers.java
index 3c0d420e2..0003a1eeb 100644
--- a/src/main/java/com/javarush/jira/bugtracking/Handlers.java
+++ b/src/main/java/com/javarush/jira/bugtracking/Handlers.java
@@ -16,14 +16,8 @@
import com.javarush.jira.bugtracking.task.ActivityRepository;
import com.javarush.jira.bugtracking.task.Task;
import com.javarush.jira.bugtracking.task.TaskRepository;
-import com.javarush.jira.bugtracking.task.mapper.ActivityMapper;
-import com.javarush.jira.bugtracking.task.mapper.TaskExtMapper;
-import com.javarush.jira.bugtracking.task.mapper.TaskFullMapper;
-import com.javarush.jira.bugtracking.task.mapper.TaskMapper;
-import com.javarush.jira.bugtracking.task.to.ActivityTo;
-import com.javarush.jira.bugtracking.task.to.TaskTo;
-import com.javarush.jira.bugtracking.task.to.TaskToExt;
-import com.javarush.jira.bugtracking.task.to.TaskToFull;
+import com.javarush.jira.bugtracking.task.mapper.*;
+import com.javarush.jira.bugtracking.task.to.*;
import com.javarush.jira.common.BaseHandler;
import com.javarush.jira.common.BaseMapper;
import com.javarush.jira.common.BaseRepository;
@@ -80,6 +74,13 @@ public TaskExtHandler(TaskRepository repository, TaskExtMapper mapper) {
}
}
+ @Component
+ public static class TaskTagsHandler extends UserBelongHandler {
+ public TaskTagsHandler(TaskRepository repository, TaskTagsMapper mapper) {
+ super(repository, mapper);
+ }
+ }
+
@Component
public static class ActivityHandler extends BaseHandler {
public ActivityHandler(ActivityRepository repository, ActivityMapper mapper) {
@@ -126,4 +127,4 @@ public void createUserBelong(long id, ObjectType type, long userId, String userT
}
}
}
-}
+}
\ No newline at end of file
diff --git a/src/main/java/com/javarush/jira/bugtracking/attachment/FileUtil.java b/src/main/java/com/javarush/jira/bugtracking/attachment/FileUtil.java
index 6cffbe175..d1a206485 100644
--- a/src/main/java/com/javarush/jira/bugtracking/attachment/FileUtil.java
+++ b/src/main/java/com/javarush/jira/bugtracking/attachment/FileUtil.java
@@ -7,14 +7,12 @@
import org.springframework.core.io.UrlResource;
import org.springframework.web.multipart.MultipartFile;
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.OutputStream;
+import java.io.*;
import java.net.MalformedURLException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
+import java.nio.file.StandardCopyOption;
@UtilityClass
public class FileUtil {
@@ -25,14 +23,24 @@ public static void upload(MultipartFile multipartFile, String directoryPath, Str
throw new IllegalRequestDataException("Select a file to upload.");
}
- File dir = new File(directoryPath);
- if (dir.exists() || dir.mkdirs()) {
- File file = new File(directoryPath + fileName);
- try (OutputStream outStream = new FileOutputStream(file)) {
- outStream.write(multipartFile.getBytes());
- } catch (IOException ex) {
- throw new IllegalRequestDataException("Failed to upload file" + multipartFile.getOriginalFilename());
+ if (directoryPath.isBlank()) {
+ throw new IllegalRequestDataException("Directory path is empty");
+ }
+
+ if (fileName.isBlank()) {
+ throw new IllegalRequestDataException("File name is empty");
+ }
+
+ try (InputStream in = multipartFile.getInputStream()) {
+ Path dir = Files.createDirectories(Paths.get(directoryPath));
+
+ Path file = dir.resolve(fileName);
+ if (!Files.exists(file)) {
+ Files.createFile(file);
}
+ Files.copy(in, file, StandardCopyOption.REPLACE_EXISTING);
+ } catch (IOException ex) {
+ throw new IllegalRequestDataException("Failed to upload file" + multipartFile.getOriginalFilename());
}
}
diff --git a/src/main/java/com/javarush/jira/bugtracking/task/ActivityService.java b/src/main/java/com/javarush/jira/bugtracking/task/ActivityService.java
index 7938541bb..8d00466af 100644
--- a/src/main/java/com/javarush/jira/bugtracking/task/ActivityService.java
+++ b/src/main/java/com/javarush/jira/bugtracking/task/ActivityService.java
@@ -3,11 +3,14 @@
import com.javarush.jira.bugtracking.Handlers;
import com.javarush.jira.bugtracking.task.to.ActivityTo;
import com.javarush.jira.common.error.DataConflictException;
+import com.javarush.jira.common.error.NotFoundException;
import com.javarush.jira.login.AuthUser;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
+import java.time.Duration;
+import java.time.LocalDateTime;
import java.util.List;
import static com.javarush.jira.bugtracking.task.TaskUtil.getLatestValue;
@@ -73,4 +76,55 @@ private void updateTaskIfRequired(long taskId, String activityStatus, String act
}
}
}
+
+ public Duration getTimeInWork(long taskId) {
+ Task task = taskRepository.getExisted(taskId);
+ List activities = handler.getRepository().findAllByTaskIdOrderByUpdatedDesc(task.id());
+
+ LocalDateTime timeInProgress = getTimeTaskByStatus("in_progress", activities);
+ if (timeInProgress == null) {
+ throw new NotFoundException(
+ "Task with id=" + task.id() + " does not have status 'in_progress'"
+ );
+ }
+
+ LocalDateTime timeReadyForReview = getTimeTaskByStatus("ready_for_review", activities);
+ if (timeReadyForReview == null) {
+ throw new NotFoundException(
+ "Task with id=" + task.id() + " does not have status 'ready_for_review'"
+ );
+ }
+
+ return Duration.between(timeInProgress, timeReadyForReview);
+ }
+
+ public Duration getTimeInTesting(long taskId) {
+ Task task = taskRepository.getExisted(taskId);
+ List activities = handler.getRepository().findAllByTaskIdOrderByUpdatedDesc(task.id());
+
+ LocalDateTime timeReadyForReview = getTimeTaskByStatus("ready_for_review", activities);
+ if (timeReadyForReview == null) {
+ throw new NotFoundException(
+ "Task with id=" + task.id() + " does not have status 'ready_for_review'"
+ );
+ }
+
+ LocalDateTime timeDone = getTimeTaskByStatus("done", activities);
+ if (timeDone == null) {
+ throw new NotFoundException(
+ "Task with id=" + task.id() + " does not have status 'done'"
+ );
+ }
+
+ return Duration.between(timeReadyForReview, timeDone);
+ }
+
+ private LocalDateTime getTimeTaskByStatus(String status, List activities) {
+ for (Activity activity : activities) {
+ if (status.equals(activity.getStatusCode())) {
+ return activity.getUpdated();
+ }
+ }
+ return null;
+ }
}
diff --git a/src/main/java/com/javarush/jira/bugtracking/task/TaskController.java b/src/main/java/com/javarush/jira/bugtracking/task/TaskController.java
index b53f7ff37..a37a2381a 100644
--- a/src/main/java/com/javarush/jira/bugtracking/task/TaskController.java
+++ b/src/main/java/com/javarush/jira/bugtracking/task/TaskController.java
@@ -3,16 +3,14 @@
import com.javarush.jira.bugtracking.Handlers;
import com.javarush.jira.bugtracking.UserBelong;
import com.javarush.jira.bugtracking.UserBelongRepository;
-import com.javarush.jira.bugtracking.task.to.ActivityTo;
-import com.javarush.jira.bugtracking.task.to.TaskTo;
-import com.javarush.jira.bugtracking.task.to.TaskToExt;
-import com.javarush.jira.bugtracking.task.to.TaskToFull;
+import com.javarush.jira.bugtracking.task.to.*;
import com.javarush.jira.bugtracking.tree.ITreeNode;
import com.javarush.jira.common.util.Util;
import com.javarush.jira.login.AuthUser;
import jakarta.annotation.Nullable;
import jakarta.validation.Valid;
import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.Size;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
@@ -156,4 +154,22 @@ public TaskTreeNode(TaskTo taskTo) {
this(taskTo, new LinkedList<>());
}
}
+
+ @PatchMapping("/{id}/tags")
+ public ResponseEntity addTag(
+ @PathVariable long id,
+ @RequestParam @Size(min = 1, max = 30) String tag) {
+ return ResponseEntity.ok(taskService.addTag(id, tag));
+ }
+
+ @PatchMapping("/{id}/tags/{tag}")
+ public ResponseEntity removeTag(@PathVariable long id, @PathVariable String tag) {
+ return ResponseEntity.ok(taskService.removeTag(id, tag));
+ }
+
+ @GetMapping("/{id}/tags")
+ public ResponseEntity getTaskWithTags(@PathVariable long id) {
+ return ResponseEntity.ok(taskService.getTaskTags(id));
+ }
+
}
diff --git a/src/main/java/com/javarush/jira/bugtracking/task/TaskService.java b/src/main/java/com/javarush/jira/bugtracking/task/TaskService.java
index e6f385548..53cc80e35 100644
--- a/src/main/java/com/javarush/jira/bugtracking/task/TaskService.java
+++ b/src/main/java/com/javarush/jira/bugtracking/task/TaskService.java
@@ -7,8 +7,10 @@
import com.javarush.jira.bugtracking.sprint.SprintRepository;
import com.javarush.jira.bugtracking.task.mapper.TaskExtMapper;
import com.javarush.jira.bugtracking.task.mapper.TaskFullMapper;
+import com.javarush.jira.bugtracking.task.mapper.TaskTagsMapper;
import com.javarush.jira.bugtracking.task.to.TaskToExt;
import com.javarush.jira.bugtracking.task.to.TaskToFull;
+import com.javarush.jira.bugtracking.task.to.TaskToTags;
import com.javarush.jira.common.error.DataConflictException;
import com.javarush.jira.common.error.NotFoundException;
import com.javarush.jira.common.util.Util;
@@ -20,7 +22,10 @@
import org.springframework.util.Assert;
import java.time.LocalDateTime;
+import java.util.Collections;
+import java.util.HashSet;
import java.util.List;
+import java.util.Set;
import static com.javarush.jira.bugtracking.ObjectType.TASK;
import static com.javarush.jira.bugtracking.task.TaskUtil.fillExtraFields;
@@ -33,17 +38,19 @@ public class TaskService {
static final String CANNOT_ASSIGN = "Cannot assign as %s to task with status=%s";
static final String CANNOT_UN_ASSIGN = "Cannot unassign as %s from task with status=%s";
- private final Handlers.TaskExtHandler handler;
+ private final Handlers.TaskExtHandler extHandler;
private final Handlers.ActivityHandler activityHandler;
+ private final Handlers.TaskTagsHandler tagsHandler;
private final TaskFullMapper fullMapper;
private final SprintRepository sprintRepository;
private final TaskExtMapper extMapper;
private final UserBelongRepository userBelongRepository;
+ private final TaskTagsMapper tagsMapper;
@Transactional
public void changeStatus(long taskId, String statusCode) {
Assert.notNull(statusCode, "statusCode must not be null");
- Task task = handler.getRepository().getExisted(taskId);
+ Task task = extHandler.getRepository().getExisted(taskId);
if (!statusCode.equals(task.getStatusCode())) {
task.checkAndSetStatusCode(statusCode);
Activity statusChangedActivity = new Activity(null, taskId, AuthUser.authId());
@@ -51,14 +58,14 @@ public void changeStatus(long taskId, String statusCode) {
activityHandler.create(statusChangedActivity);
String userType = getRefTo(RefType.TASK_STATUS, statusCode).getAux(1);
if (userType != null) {
- handler.createUserBelong(taskId, TASK, AuthUser.authId(), userType);
+ extHandler.createUserBelong(taskId, TASK, AuthUser.authId(), userType);
}
}
}
@Transactional
public void changeSprint(long taskId, Long sprintId) {
- Task task = handler.getRepository().getExisted(taskId);
+ Task task = extHandler.getRepository().getExisted(taskId);
if (task.getParentId() != null) {
throw new DataConflictException("Can't change subtask sprint");
}
@@ -68,12 +75,12 @@ public void changeSprint(long taskId, Long sprintId) {
throw new DataConflictException("Target sprint must belong to the same project");
}
}
- handler.getRepository().setTaskAndSubTasksSprint(taskId, sprintId);
+ extHandler.getRepository().setTaskAndSubTasksSprint(taskId, sprintId);
}
@Transactional
public Task create(TaskToExt taskTo) {
- Task created = handler.createWithBelong(taskTo, TASK, "task_author");
+ Task created = extHandler.createWithBelong(taskTo, TASK, "task_author");
activityHandler.create(makeActivity(created.id(), taskTo));
return created;
}
@@ -81,13 +88,13 @@ public Task create(TaskToExt taskTo) {
@Transactional
public void update(TaskToExt taskTo, long id) {
if (!taskTo.equals(get(taskTo.id()))) {
- handler.updateFromTo(taskTo, id);
+ extHandler.updateFromTo(taskTo, id);
activityHandler.create(makeActivity(id, taskTo));
}
}
public TaskToFull get(long id) {
- Task task = Util.checkExist(id, handler.getRepository().findFullById(id));
+ Task task = Util.checkExist(id, extHandler.getRepository().findFullById(id));
TaskToFull taskToFull = fullMapper.toTo(task);
List activities = activityHandler.getRepository().findAllByTaskIdOrderByUpdatedDesc(id);
fillExtraFields(taskToFull, activities);
@@ -110,7 +117,7 @@ public TaskToExt getNewWithProject(long projectId) {
}
public TaskToExt getNewWithParent(long parentId) {
- Task parent = handler.getRepository().getExisted(parentId);
+ Task parent = extHandler.getRepository().getExisted(parentId);
Task newTask = new Task();
newTask.setParentId(parentId);
newTask.setSprintId(parent.getSprintId());
@@ -120,7 +127,7 @@ public TaskToExt getNewWithParent(long parentId) {
public void assign(long id, String userType, long userId) {
checkAssignmentActionPossible(id, userType, true);
- handler.createUserBelong(id, TASK, userId, userType);
+ extHandler.createUserBelong(id, TASK, userId, userType);
}
@Transactional
@@ -134,10 +141,45 @@ public void unAssign(long id, String userType, long userId) {
private void checkAssignmentActionPossible(long id, String userType, boolean assign) {
Assert.notNull(userType, "userType must not be null");
- Task task = handler.getRepository().getExisted(id);
+ Task task = extHandler.getRepository().getExisted(id);
String possibleUserType = getRefTo(RefType.TASK_STATUS, task.getStatusCode()).getAux(1);
if (!userType.equals(possibleUserType)) {
throw new DataConflictException(String.format(assign ? CANNOT_ASSIGN : CANNOT_UN_ASSIGN, userType, task.getStatusCode()));
}
}
+
+ public TaskToTags getTaskTags(long taskId) {
+ Task task = tagsHandler.getRepository().getExisted(taskId);
+ return tagsMapper.toTo(task);
+ }
+
+ @Transactional
+ public TaskToTags addTag(long taskId, String tag) {
+ Assert.notNull(tag, "tag must not be null");
+
+ Task task = tagsHandler.getRepository().getExisted(taskId);
+
+ Set newTags = copyTaskTags(task);
+ newTags.add(tag);
+
+ task.setTags(Collections.unmodifiableSet(newTags));
+ return tagsMapper.toTo(task);
+ }
+
+ @Transactional
+ public TaskToTags removeTag(long taskId, String tag) {
+ Assert.notNull(tag, "tag must not be null");
+
+ Task task = tagsHandler.getRepository().getExisted(taskId);
+
+ Set newTags = copyTaskTags(task);
+ newTags.remove(tag);
+
+ task.setTags(Collections.unmodifiableSet(newTags));
+ return tagsMapper.toTo(task);
+ }
+
+ private Set copyTaskTags(Task task) {
+ return new HashSet<>(task.getTags());
+ }
}
diff --git a/src/main/java/com/javarush/jira/bugtracking/task/TaskUIController.java b/src/main/java/com/javarush/jira/bugtracking/task/TaskUIController.java
index fbcc46aa2..172907bb7 100644
--- a/src/main/java/com/javarush/jira/bugtracking/task/TaskUIController.java
+++ b/src/main/java/com/javarush/jira/bugtracking/task/TaskUIController.java
@@ -6,8 +6,10 @@
import com.javarush.jira.bugtracking.task.to.ActivityTo;
import com.javarush.jira.bugtracking.task.to.TaskToExt;
import com.javarush.jira.bugtracking.task.to.TaskToFull;
+import com.javarush.jira.bugtracking.task.to.TaskToTags;
import com.javarush.jira.ref.RefTo;
import jakarta.validation.Valid;
+import jakarta.validation.constraints.Size;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Controller;
@@ -103,6 +105,24 @@ public String createOrUpdate(@Valid @ModelAttribute("task") TaskToExt taskTo, Bi
}
return "redirect:/ui/tasks/" + taskId;
}
+
+ @PostMapping("/add-tag")
+ public String addTag(@RequestParam long taskId,
+ @RequestParam @Size(min = 1, max = 30) String tagName,
+ Model model) {
+ log.info("add tag {} to task {}", tagName, taskId);
+ TaskToTags taskToTags = service.addTag(taskId, tagName);
+ model.addAttribute("tags", taskToTags.getTags());
+ return "redirect:/ui/tasks/" + taskId;
+ }
+
+ @PostMapping("/remove-tag")
+ public String removeTag(@RequestParam long taskId, @RequestParam String tagName, Model model) {
+ log.info("remove tag {} from task {}", tagName, taskId);
+ TaskToTags taskToTags = service.removeTag(taskId, tagName);
+ model.addAttribute("tags", taskToTags.getTags());
+ return "redirect:/ui/tasks/" + taskId;
+ }
private void addTaskInfo(Model model, TaskToFull taskTo) {
List comments = getComments(taskTo.getActivityTos());
diff --git a/src/main/java/com/javarush/jira/bugtracking/task/mapper/TaskTagsMapper.java b/src/main/java/com/javarush/jira/bugtracking/task/mapper/TaskTagsMapper.java
new file mode 100644
index 000000000..50e9357f9
--- /dev/null
+++ b/src/main/java/com/javarush/jira/bugtracking/task/mapper/TaskTagsMapper.java
@@ -0,0 +1,14 @@
+package com.javarush.jira.bugtracking.task.mapper;
+
+import com.javarush.jira.bugtracking.task.Task;
+import com.javarush.jira.bugtracking.task.to.TaskToTags;
+import com.javarush.jira.common.BaseMapper;
+import com.javarush.jira.common.TimestampMapper;
+import org.mapstruct.Mapper;
+
+@Mapper(config = TimestampMapper.class)
+public interface TaskTagsMapper extends BaseMapper {
+
+ @Override
+ TaskToTags toTo(Task task);
+}
diff --git a/src/main/java/com/javarush/jira/bugtracking/task/to/TaskToTags.java b/src/main/java/com/javarush/jira/bugtracking/task/to/TaskToTags.java
new file mode 100644
index 000000000..060d60982
--- /dev/null
+++ b/src/main/java/com/javarush/jira/bugtracking/task/to/TaskToTags.java
@@ -0,0 +1,20 @@
+package com.javarush.jira.bugtracking.task.to;
+
+import lombok.Getter;
+
+import java.time.LocalDateTime;
+import java.util.Set;
+
+@Getter
+public class TaskToTags extends TaskToExt {
+ Set tags;
+
+ public TaskToTags(Long id, String code, String title, String description,
+ String typeCode, String statusCode, String priorityCode,
+ LocalDateTime updated, Integer estimate, Long parentId,
+ long projectId, Long sprintId, Set tags) {
+ super(id, code, title, description, typeCode, statusCode, priorityCode, updated, estimate, parentId, projectId, sprintId);
+
+ this.tags = (tags == null) ? Set.of() : Set.copyOf(tags);
+ }
+}
diff --git a/src/main/java/com/javarush/jira/common/internal/config/MvcConfig.java b/src/main/java/com/javarush/jira/common/internal/config/MvcConfig.java
index 8a434a807..b4f09f490 100644
--- a/src/main/java/com/javarush/jira/common/internal/config/MvcConfig.java
+++ b/src/main/java/com/javarush/jira/common/internal/config/MvcConfig.java
@@ -19,9 +19,14 @@
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.handler.SimpleUrlHandlerMapping;
import org.springframework.web.servlet.handler.WebRequestHandlerInterceptorAdapter;
+import org.springframework.web.servlet.i18n.CookieLocaleResolver;
+import org.springframework.web.servlet.i18n.LocaleChangeInterceptor;
+import org.springframework.web.servlet.i18n.SessionLocaleResolver;
import org.springframework.web.servlet.mvc.UrlFilenameViewController;
+import org.springframework.web.servlet.LocaleResolver;
import java.time.Duration;
+import java.util.Locale;
import java.util.Properties;
//@EnableWebMvc : http://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#boot-features-spring-mvc-auto-configuration
@@ -53,11 +58,6 @@ public void preHandle(WebRequest request) {
}
});
- @Override
- public void addInterceptors(InterceptorRegistry registry) {
- registry.addInterceptor(authInterceptor).excludePathPatterns("/api/**");
- }
-
// http://www.codejava.net/frameworks/spring/spring-mvc-url-based-view-resolution-with-urlfilenameviewcontroller-example
@Bean
public SimpleUrlHandlerMapping getUrlHandlerMapping() {
@@ -95,4 +95,31 @@ public RestTemplate restTemplate(RestTemplateBuilder restTemplateBuilder) {
.setReadTimeout(Duration.ofSeconds(10))
.build();
}
+
+ @Bean
+ public LocaleResolver localeResolver() {
+ SessionLocaleResolver resolver = new SessionLocaleResolver();
+ resolver.setDefaultLocale(Locale.ENGLISH);
+ return resolver;
+ }
+
+ @Bean
+ public LocaleChangeInterceptor localeChangeInterceptor() {
+ LocaleChangeInterceptor lci = new LocaleChangeInterceptor();
+ lci.setParamName("lang");
+ return lci;
+ }
+
+ @Override
+ public void addInterceptors(InterceptorRegistry registry) {
+ registry.addInterceptor(authInterceptor).excludePathPatterns("/api/**");
+ registry.addInterceptor(localeChangeInterceptor());
+ }
+
+// @Bean
+// public LocaleResolver localeResolver() {
+// CookieLocaleResolver resolver = new CookieLocaleResolver();
+// resolver.setDefaultLocale(Locale.ENGLISH);
+// return resolver;
+// }
}
diff --git a/src/main/resources/application.yaml b/src/main/resources/application.yaml
index 7fcba1570..8377720be 100644
--- a/src/main/resources/application.yaml
+++ b/src/main/resources/application.yaml
@@ -1,13 +1,18 @@
# https://docs.spring.io/spring-boot/docs/current/reference/html/common-application-properties.html
app:
host-url: http://localhost:8080
- test-mail: jira4jr@gmail.com
+ test-mail: ${MAIL_TEST}
templates-update-cache: 5s
mail-sending-props:
core-pool-size: 8
max-pool-size: 100
spring:
+ messages:
+ basename: messages
+ encoding: UTF-8
+ config:
+ import: optional:classpath:secrets.properties
init:
mode: never
jpa:
@@ -27,11 +32,12 @@ spring:
jdbc.batch_size: 20
datasource:
url: jdbc:postgresql://localhost:5432/jira
- username: jira
- password: JiraRush
+ username: ${DB_USERNAME}
+ password: ${DB_PASSWORD}
liquibase:
changeLog: "classpath:db/changelog.sql"
+# contexts: prod
# Jackson Fields Serialization
jackson:
@@ -51,48 +57,48 @@ spring:
client:
registration:
github:
- client-id: 3d0d8738e65881fff266
- client-secret: 0f97031ce6178b7dfb67a6af587f37e222a16120
+ client-id: ${OAUTH_GITHUB_CLIENT_ID}
+ client-secret: ${OAUTH_GITHUB_CLIENT_SECRET}
scope:
- email
google:
- client-id: 329113642700-f8if6pu68j2repq3ef6umd5jgiliup60.apps.googleusercontent.com
- client-secret: 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
+ client-id: ${OAUTH_EMAIL_GOOGLE_CLIENT_ID}
+ client-secret: ${OAUTH_EMAIL_GOOGLE_CLIENT_SECRET}
scope:
- email
- profile
- vk:
- client-id: 51562377
- client-secret: jNM1YHQy1362Mqs49wUN
- client-name: Vkontakte
- redirect-uri: "{baseUrl}/login/oauth2/code/{registrationId}"
- client-authentication-method: client_secret_post
- authorization-grant-type: authorization_code
- scope: email
- yandex:
- client-id: 2f3395214ba84075956b76a34b231985
- client-secret: ed236c501e444a609b0f419e5e88f1e1
- client-name: Yandex
- redirect-uri: "{baseUrl}/login/oauth2/code/{registrationId}"
- authorization-grant-type: authorization_code
+# vk:
+# client-id: ${OAUTH_EMAIL_GOOGLE_CLIENT_ID}
+# client-secret: ${OAUTH_EMAIL_GOOGLE_CLIENT_SECRET}
+# client-name: Vkontakte
+# redirect-uri: "{baseUrl}/login/oauth2/code/{registrationId}"
+# client-authentication-method: client_secret_post
+# authorization-grant-type: authorization_code
+# scope: email
+# yandex:
+# client-id: ${OAUTH_YANDEX_CLIENT_ID}
+# client-secret: ${OAUTH_YANDEX_CLIENT_SECRET}
+# client-name: Yandex
+# redirect-uri: "{baseUrl}/login/oauth2/code/{registrationId}"
+# authorization-grant-type: authorization_code
gitlab:
- client-id: b8520a3266089063c0d8261cce36971defa513f5ffd9f9b7a3d16728fc83a494
- client-secret: e72c65320cf9d6495984a37b0f9cc03ec46be0bb6f071feaebbfe75168117004
+ client-id: ${OAUTH_GITLAB_CLIENT_ID}
+ client-secret: ${OAUTH_GITLAB_CLIENT_SECRET}
client-name: GitLab
redirect-uri: "{baseUrl}/login/oauth2/code/{registrationId}"
authorization-grant-type: authorization_code
scope: read_user
provider:
- vk:
- authorization-uri: https://oauth.vk.com/authorize
- token-uri: https://oauth.vk.com/access_token
- user-info-uri: https://api.vk.com/method/users.get?v=8.1
- user-name-attribute: response
- yandex:
- authorization-uri: https://oauth.yandex.ru/authorize
- token-uri: https://oauth.yandex.ru/token
- user-info-uri: https://login.yandex.ru/info
- user-name-attribute: login
+# vk:
+# authorization-uri: https://oauth.vk.com/authorize
+# token-uri: https://oauth.vk.com/access_token
+# user-info-uri: https://api.vk.com/method/users.get?v=8.1
+# user-name-attribute: response
+# yandex:
+# authorization-uri: https://oauth.yandex.ru/authorize
+# token-uri: https://oauth.yandex.ru/token
+# user-info-uri: https://login.yandex.ru/info
+# user-name-attribute: login
gitlab:
authorization-uri: https://gitlab.com/oauth/authorize
token-uri: https://gitlab.com/oauth/token
@@ -111,8 +117,8 @@ spring:
enable: true
auth: true
host: smtp.gmail.com
- username: jira4jr@gmail.com
- password: zdfzsrqvgimldzyj
+ username: ${MAIL_USERNAME}
+ password: ${MAIL_PASSWORD}
port: 587
thymeleaf.check-template-location: false
diff --git a/src/main/resources/data4dev/data.sql b/src/main/resources/data4dev/data.sql
index a7d43cbad..4cdbd09b7 100644
--- a/src/main/resources/data4dev/data.sql
+++ b/src/main/resources/data4dev/data.sql
@@ -2,7 +2,7 @@
DELETE
FROM USERS;
alter
-sequence USERS_ID_SEQ restart with 1;
+ sequence USERS_ID_SEQ restart with 1;
insert into USERS (EMAIL, PASSWORD, FIRST_NAME, LAST_NAME, DISPLAY_NAME)
values ('user@gmail.com', '{noop}password', 'userFirstName', 'userLastName', 'userDisplayName'),
('admin@gmail.com', '{noop}admin', 'adminFirstName', 'adminLastName', 'adminDisplayName'),
@@ -60,7 +60,7 @@ values (1, 'skype', 'userSkype'),
delete
from ATTACHMENT;
alter
-sequence ATTACHMENT_ID_SEQ restart with 1;
+ sequence ATTACHMENT_ID_SEQ restart with 1;
insert into ATTACHMENT (name, file_link, object_id, object_type, user_id, date_time)
values ('Снимок экрана 1.png', './attachments/project/1_Снимок экрана 1.png', 2, 0, 4, '2023-05-04 22:28:50.215429'),
('Снимок экрана 2.png', './attachments/project/2_Снимок экрана 2.png', 2, 0, 4, '2023-05-04 22:28:53.687600'),
@@ -71,26 +71,26 @@ values ('Снимок экрана 1.png', './attachments/project/1_Снимок
('Ежедневный-чеклист.xlsx', './attachments/task/3_Ежедневный-чеклист.xlsx', 38, 2, 4,
'2023-05-04 22:28:50.215429');
alter
-sequence ATTACHMENT_ID_SEQ restart with 1000;
+ sequence ATTACHMENT_ID_SEQ restart with 1000;
-- populate tasks
delete
from TASK;
alter
-sequence TASK_ID_SEQ restart with 1;
+ sequence TASK_ID_SEQ restart with 1;
delete
from SPRINT;
alter
-sequence SPRINT_ID_SEQ restart with 1;
+ sequence SPRINT_ID_SEQ restart with 1;
delete
from PROJECT;
alter
-sequence PROJECT_ID_SEQ restart with 1;
+ sequence PROJECT_ID_SEQ restart with 1;
delete
from ACTIVITY;
alter
-sequence ACTIVITY_ID_SEQ restart with 1;
+ sequence ACTIVITY_ID_SEQ restart with 1;
insert into PROJECT (code, title, description, type_code, parent_id)
values ('JiraRush', 'JiraRush', '«Mini-JIRA» app : project management system tutorial app', 'task_tracker', null),
@@ -98,7 +98,7 @@ values ('JiraRush', 'JiraRush', '«Mini-JIRA» app : project management system t
('Test_Project_2', 'Test Project 2', 'Just test project 2', 'task_tracker', null),
('JiraRush sub', 'JiraRush subproject', 'subproject', 'task_tracker', 1);
alter
-sequence PROJECT_ID_SEQ restart with 1000;
+ sequence PROJECT_ID_SEQ restart with 1000;
insert into SPRINT (status_code, startpoint, endpoint, code, project_id)
values ('active', null, null, 'Sprint-2', 1),
@@ -107,7 +107,7 @@ values ('active', null, null, 'Sprint-2', 1),
('active', '2023-04-05 14:25:43', '2023-06-10 13:00:00', 'Sprint-3', 2),
('active', null, null, 'Sprint-1', 4);
alter
-sequence SPRINT_ID_SEQ restart with 1000;
+ sequence SPRINT_ID_SEQ restart with 1000;
---- project 1 -------------
INSERT INTO TASK (TITLE, TYPE_CODE, STATUS_CODE, PROJECT_ID, SPRINT_ID, STARTPOINT)
@@ -313,7 +313,7 @@ values ('Add role manager and filters in security', 'task', 'done', 1, 1, 1,
('Subproject backlog subtask', 'task', 'in_progress', 4, null, 88,
now() + random() * interval '5 minutes' + random() * interval '20 seconds');
alter
-sequence TASK_ID_SEQ restart with 1000;
+ sequence TASK_ID_SEQ restart with 1000;
---task 1------
INSERT INTO ACTIVITY(AUTHOR_ID, TASK_ID, UPDATED, COMMENT, TITLE, DESCRIPTION, ESTIMATE, TYPE_CODE, STATUS_CODE,
@@ -324,4 +324,3 @@ values (6, 1, '2023-05-15 09:05:10', null, 'Data', null, 3, 'epic', 'in_progress
(11, 118, '2023-05-16 10:05:10', null, 'UI tab of tasks', null, 4, 'task', 'in_progress', 'normal'),
(5, 118, '2023-05-16 11:10:10', null, 'UI tab of tasks', null, null, null, null, 'high'),
(11, 118, '2023-05-16 12:30:10', null, 'UI tab of tasks', null, 2, null, null, null);
-
diff --git a/src/main/resources/db/changelog.sql b/src/main/resources/db/changelog.sql
index 68591336d..171b980d5 100644
--- a/src/main/resources/db/changelog.sql
+++ b/src/main/resources/db/changelog.sql
@@ -5,33 +5,33 @@ DROP TABLE IF EXISTS USER_ROLE;
DROP TABLE IF EXISTS CONTACT;
DROP TABLE IF EXISTS MAIL_CASE;
DROP
-SEQUENCE IF EXISTS MAIL_CASE_ID_SEQ;
+ SEQUENCE IF EXISTS MAIL_CASE_ID_SEQ;
DROP TABLE IF EXISTS PROFILE;
DROP TABLE IF EXISTS TASK_TAG;
DROP TABLE IF EXISTS USER_BELONG;
DROP
-SEQUENCE IF EXISTS USER_BELONG_ID_SEQ;
+ SEQUENCE IF EXISTS USER_BELONG_ID_SEQ;
DROP TABLE IF EXISTS ACTIVITY;
DROP
-SEQUENCE IF EXISTS ACTIVITY_ID_SEQ;
+ SEQUENCE IF EXISTS ACTIVITY_ID_SEQ;
DROP TABLE IF EXISTS TASK;
DROP
-SEQUENCE IF EXISTS TASK_ID_SEQ;
+ SEQUENCE IF EXISTS TASK_ID_SEQ;
DROP TABLE IF EXISTS SPRINT;
DROP
-SEQUENCE IF EXISTS SPRINT_ID_SEQ;
+ SEQUENCE IF EXISTS SPRINT_ID_SEQ;
DROP TABLE IF EXISTS PROJECT;
DROP
-SEQUENCE IF EXISTS PROJECT_ID_SEQ;
+ SEQUENCE IF EXISTS PROJECT_ID_SEQ;
DROP TABLE IF EXISTS REFERENCE;
DROP
-SEQUENCE IF EXISTS REFERENCE_ID_SEQ;
+ SEQUENCE IF EXISTS REFERENCE_ID_SEQ;
DROP TABLE IF EXISTS ATTACHMENT;
DROP
-SEQUENCE IF EXISTS ATTACHMENT_ID_SEQ;
+ SEQUENCE IF EXISTS ATTACHMENT_ID_SEQ;
DROP TABLE IF EXISTS USERS;
DROP
-SEQUENCE IF EXISTS USERS_ID_SEQ;
+ SEQUENCE IF EXISTS USERS_ID_SEQ;
create table PROJECT
(
@@ -250,19 +250,19 @@ values ('assigned', 'Assigned', 6, '1'),
alter table SPRINT rename COLUMN TITLE to CODE;
alter table SPRINT
- alter column CODE type varchar (32);
+alter column CODE type varchar (32);
alter table SPRINT
alter column CODE set not null;
create unique index UK_SPRINT_PROJECT_CODE on SPRINT (PROJECT_ID, CODE);
ALTER TABLE TASK
- DROP COLUMN DESCRIPTION;
+DROP COLUMN DESCRIPTION;
ALTER TABLE TASK
- DROP COLUMN PRIORITY_CODE;
+DROP COLUMN PRIORITY_CODE;
ALTER TABLE TASK
- DROP COLUMN ESTIMATE;
+DROP COLUMN ESTIMATE;
ALTER TABLE TASK
- DROP COLUMN UPDATED;
+DROP COLUMN UPDATED;
--changeset ishlyakhtenkov:change_task_status_reference
@@ -282,15 +282,15 @@ values ('todo', 'ToDo', 3, 'in_progress,canceled'),
--changeset gkislin:users_add_on_delete_cascade
alter table ACTIVITY
- drop constraint FK_ACTIVITY_USERS,
+drop constraint FK_ACTIVITY_USERS,
add constraint FK_ACTIVITY_USERS foreign key (AUTHOR_ID) references USERS (ID) on delete cascade;
alter table USER_BELONG
- drop constraint FK_USER_BELONG,
+drop constraint FK_USER_BELONG,
add constraint FK_USER_BELONG foreign key (USER_ID) references USERS (ID) on delete cascade;
alter table ATTACHMENT
- drop constraint FK_ATTACHMENT,
+drop constraint FK_ATTACHMENT,
add constraint FK_ATTACHMENT foreign key (USER_ID) references USERS (ID) on delete cascade;
--changeset valeriyemelyanov:change_user_type_reference
@@ -329,3 +329,9 @@ values ('todo', 'ToDo', 3, 'in_progress,canceled|'),
drop index UK_USER_BELONG;
create unique index UK_USER_BELONG on USER_BELONG (OBJECT_ID, OBJECT_TYPE, USER_ID, USER_TYPE_CODE) where ENDPOINT is null;
+
+-- --changeset alex04:insert_activity
+-- INSERT INTO ACTIVITY (AUTHOR_ID, TASK_ID, UPDATED, STATUS_CODE)
+-- VALUES(11, 118, now() - interval '5 hours', 'in_progress'),
+-- (11, 118, now() - interval '2 hours', 'ready_for_review'),
+-- (11, 118, now() - interval '30 minutes', 'done');
diff --git a/src/main/resources/messages.properties b/src/main/resources/messages.properties
new file mode 100644
index 000000000..b91052c22
--- /dev/null
+++ b/src/main/resources/messages.properties
@@ -0,0 +1,15 @@
+index.title=JiraRush: mini bugtracking system
+index.heading=JiraRush Home page
+index.logout=Logout
+
+mail.confirm.title=JiraRush - Email confirmation
+mail.confirm.greeting=Hello, {0}.
+mail.confirm.text=To complete your account setup and start using JiraRush, please confirm that you entered your email correctly.
+mail.confirm.button=Confirm email
+
+mail.reset.title=JiraRush - Reset password
+mail.reset.greeting=Hello, {0}.
+mail.reset.text=We received a request to reset your JiraRush password for the account: {0}.
+mail.reset.button=Set new password
+
+language.text=Language:
\ No newline at end of file
diff --git a/src/main/resources/messages_ru.properties b/src/main/resources/messages_ru.properties
new file mode 100644
index 000000000..c00331afc
--- /dev/null
+++ b/src/main/resources/messages_ru.properties
@@ -0,0 +1,15 @@
+index.title=JiraRush: \u043C\u0438\u043D\u0438 \u0441\u0438\u0441\u0442\u0435\u043C\u0430 \u043E\u0442\u0441\u043B\u0435\u0436\u0438\u0432\u0430\u043D\u0438\u044F \u0431\u0430\u0433\u043E\u0432
+index.heading=\u0413\u043B\u0430\u0432\u043D\u0430\u044F \u0441\u0442\u0440\u0430\u043D\u0438\u0446\u0430 JiraRush
+index.logout=\u0412\u044B\u0439\u0442\u0438
+
+mail.confirm.title=JiraRush - \u043F\u043E\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0435\u043D\u0438\u0435 \u043F\u043E\u0447\u0442\u044B
+mail.confirm.greeting=\u041F\u0440\u0438\u0432\u0435\u0442, {0}.
+mail.confirm.text=\u0427\u0442\u043E\u0431\u044B \u0437\u0430\u0432\u0435\u0440\u0448\u0438\u0442\u044C \u043D\u0430\u0441\u0442\u0440\u043E\u0439\u043A\u0443 \u0443\u0447\u0435\u0442\u043D\u043E\u0439 \u0437\u0430\u043F\u0438\u0441\u0438 \u0438 \u043D\u0430\u0447\u0430\u0442\u044C \u043F\u043E\u043B\u044C\u0437\u043E\u0432\u0430\u0442\u044C\u0441\u044F JiraRush, \u043F\u043E\u0434\u0442\u0432\u0435\u0440\u0434\u0438\u0442\u0435, \u0447\u0442\u043E \u0432\u044B \u043F\u0440\u0430\u0432\u0438\u043B\u044C\u043D\u043E \u0443\u043A\u0430\u0437\u0430\u043B\u0438 \u0432\u0430\u0448\u0443 \u044D\u043B\u0435\u043A\u0442\u0440\u043E\u043D\u043D\u0443\u044E \u043F\u043E\u0447\u0442\u0443.
+mail.confirm.button=\u041F\u043E\u0434\u0442\u0432\u0435\u0440\u0434\u0438\u0442\u044C \u043F\u043E\u0447\u0442\u0443
+
+mail.reset.title=JiraRush - \u0443\u0441\u0442\u0430\u043D\u043E\u0432\u0438\u0442\u044C \u043D\u043E\u0432\u044B\u0439 \u043F\u0430\u0440\u043E\u043B\u044C
+mail.reset.greeting=\u041F\u0440\u0438\u0432\u0435\u0442, {0}.
+mail.reset.text=\u041C\u044B \u043F\u043E\u043B\u0443\u0447\u0438\u043B\u0438 \u0437\u0430\u043F\u0440\u043E\u0441 \u043D\u0430 \u0443\u0441\u0442\u0430\u043D\u043E\u0432\u043A\u0443 \u043D\u043E\u0432\u043E\u0433\u043E \u043F\u0430\u0440\u043E\u043B\u044F JiraRush \u0434\u043B\u044F \u0443\u0447\u0435\u0442\u043D\u043E\u0439 \u0437\u0430\u043F\u0438\u0441\u0438: {0}.
+mail.reset.button=\u0423\u0441\u0442\u0430\u043D\u043E\u0432\u0438\u0442\u044C \u043F\u0430\u0440\u043E\u043B\u044C
+
+language.text=\u042F\u0437\u044B\u043A:
\ No newline at end of file
diff --git a/src/main/resources/messages_uk.properties b/src/main/resources/messages_uk.properties
new file mode 100644
index 000000000..430c6fbb2
--- /dev/null
+++ b/src/main/resources/messages_uk.properties
@@ -0,0 +1,15 @@
+index.title=JiraRush: \u043C\u0456\u043D\u0456 \u0441\u0438\u0441\u0442\u0435\u043C\u0430 \u0432\u0456\u0434\u0441\u0442\u0435\u0436\u0435\u043D\u043D\u044F \u0431\u0430\u0433\u0456\u0432
+index.heading=\u0414\u043E\u043C\u0430\u0448\u043D\u044F \u0441\u0442\u043E\u0440\u0456\u043D\u043A\u0430 JiraRush
+index.logout=\u0412\u0438\u0439\u0442\u0438
+
+mail.confirm.title=JiraRush - \u041F\u0456\u0434\u0442\u0432\u0435\u0440\u0434\u0436\u0435\u043D\u043D\u044F \u043F\u043E\u0448\u0442\u0438
+mail.confirm.greeting=\u0412\u0456\u0442\u0430\u0454\u043C\u043E, {0}.
+mail.confirm.text=\u0429\u043E\u0431 \u0437\u0430\u0432\u0435\u0440\u0448\u0438\u0442\u0438 \u043D\u0430\u043B\u0430\u0448\u0442\u0443\u0432\u0430\u043D\u043D\u044F \u043E\u0431\u043B\u0456\u043A\u043E\u0432\u043E\u0433\u043E \u0437\u0430\u043F\u0438\u0441\u0443 \u0442\u0430 \u043F\u043E\u0447\u0430\u0442\u0438 \u043A\u043E\u0440\u0438\u0441\u0442\u0443\u0432\u0430\u0442\u0438\u0441\u044F JiraRush, \u043F\u0456\u0434\u0442\u0432\u0435\u0440\u0434\u044C\u0442\u0435, \u0449\u043E \u0432\u0438 \u0432\u0432\u0435\u043B\u0438 \u0430\u0434\u0440\u0435\u0441\u0443 \u0435\u043B\u0435\u043A\u0442\u0440\u043E\u043D\u043D\u043E\u0457 \u043F\u043E\u0448\u0442\u0438 \u043F\u0440\u0430\u0432\u0438\u043B\u044C\u043D\u043E.
+mail.confirm.button=\u041F\u0456\u0434\u0442\u0432\u0435\u0440\u0434\u0438\u0442\u0438 \u043F\u043E\u0448\u0442\u0443
+
+mail.reset.title=JiraRush - \u0412\u0441\u0442\u0430\u043D\u043E\u0432\u0438\u0442\u0438 \u043D\u043E\u0432\u0438\u0439 \u043F\u0430\u0440\u043E\u043B\u044C
+mail.reset.greeting=\u0412\u0456\u0442\u0430\u0454\u043C\u043E, {0}.
+mail.reset.text=\u041C\u0438 \u043E\u0442\u0440\u0438\u043C\u0430\u043B\u0438 \u0437\u0430\u043F\u0438\u0442 \u043D\u0430 \u0432\u0441\u0442\u0430\u043D\u043E\u0432\u043B\u0435\u043D\u043D\u044F \u043D\u043E\u0432\u043E\u0433\u043E \u043F\u0430\u0440\u043E\u043B\u044E JiraRush \u0434\u043B\u044F \u043E\u0431\u043B\u0456\u043A\u043E\u0432\u043E\u0433\u043E \u0437\u0430\u043F\u0438\u0441\u0443: {0}.
+mail.reset.button=\u0412\u0441\u0442\u0430\u043D\u043E\u0432\u0438\u0442\u0438 \u043F\u0430\u0440\u043E\u043B\u044C
+
+language.text=\u041C\u043E\u0432\u0430:
\ No newline at end of file
diff --git a/src/test/java/com/javarush/jira/AbstractControllerTest.java b/src/test/java/com/javarush/jira/AbstractControllerTest.java
index 5981bae53..0548d840c 100644
--- a/src/test/java/com/javarush/jira/AbstractControllerTest.java
+++ b/src/test/java/com/javarush/jira/AbstractControllerTest.java
@@ -9,7 +9,7 @@
import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder;
//https://docs.spring.io/spring-boot/docs/current/reference/html/spring-boot-features.html#boot-features-testing-spring-boot-applications
-@Sql(scripts = {"classpath:db/changelog.sql", "classpath:data.sql"}, config = @SqlConfig(encoding = "UTF-8"))
+@Sql(scripts = {"classpath:db/changelog.sql", "classpath:data-test.sql"}, config = @SqlConfig(encoding = "UTF-8"))
@AutoConfigureMockMvc
//https://docs.spring.io/spring-boot/docs/current/reference/html/spring-boot-features.html#boot-features-testing-spring-boot-applications-testing-with-mock-environment
public abstract class AbstractControllerTest extends BaseTests {
diff --git a/src/test/java/com/javarush/jira/profile/internal/web/ProfileRestControllerTest.java b/src/test/java/com/javarush/jira/profile/internal/web/ProfileRestControllerTest.java
index a6fd5e3bf..7d08bb618 100644
--- a/src/test/java/com/javarush/jira/profile/internal/web/ProfileRestControllerTest.java
+++ b/src/test/java/com/javarush/jira/profile/internal/web/ProfileRestControllerTest.java
@@ -1,8 +1,145 @@
package com.javarush.jira.profile.internal.web;
import com.javarush.jira.AbstractControllerTest;
+import com.javarush.jira.profile.ProfileTo;
+import com.javarush.jira.profile.internal.ProfileRepository;
+import com.javarush.jira.profile.internal.model.Profile;
+import lombok.extern.slf4j.Slf4j;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.MediaType;
+import org.springframework.security.test.context.support.WithUserDetails;
+import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
+import static com.javarush.jira.common.util.JsonUtil.writeValue;
+import static com.javarush.jira.login.internal.web.UserTestData.GUEST_MAIL;
+import static com.javarush.jira.login.internal.web.UserTestData.USER_MAIL;
+import static com.javarush.jira.profile.internal.web.ProfileRestController.REST_URL;
+import static com.javarush.jira.profile.internal.web.ProfileTestData.*;
+import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
+@Slf4j
class ProfileRestControllerTest extends AbstractControllerTest {
+ @Autowired
+ private ProfileRepository profileRepository;
+ @Test
+ @WithUserDetails(value = USER_MAIL)
+ void getUserProfile() throws Exception {
+ perform(MockMvcRequestBuilders.get(REST_URL))
+ .andDo(print())
+ .andExpect(status().isOk())
+ .andExpect(content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON))
+ .andExpect(PROFILE_TO_MATCHER.contentJson(USER_PROFILE_TO));
+ }
+
+ @Test
+ @WithUserDetails(value = GUEST_MAIL)
+ void getGuestProfile() throws Exception {
+ perform(MockMvcRequestBuilders.get(REST_URL))
+ .andDo(print())
+ .andExpect(status().isOk())
+ .andExpect(content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON))
+ .andExpect(PROFILE_TO_MATCHER.contentJson(GUEST_PROFILE_EMPTY_TO));
+ }
+
+ @Test
+ @WithUserDetails(value = USER_MAIL)
+ void updateProfile() throws Exception {
+ ProfileTo newTo = ProfileTestData.getNewTo();
+
+ perform(MockMvcRequestBuilders.put(REST_URL)
+ .contentType(MediaType.APPLICATION_JSON)
+ .content(writeValue(newTo)))
+ .andDo(print())
+ .andExpect(status().isNoContent());
+
+ Profile expected = ProfileTestData.getNew(USER_ID);
+ Profile actual = profileRepository.getExisted(USER_ID);
+ PROFILE_MATCHER.assertMatch(actual, expected);
+ }
+
+ @Test
+ void getUnauthorized() throws Exception {
+ perform(MockMvcRequestBuilders.get(REST_URL))
+ .andDo(print())
+ .andExpect(status().isUnauthorized());
+ }
+
+ @Test
+ @WithUserDetails(value = USER_MAIL)
+ void updateValid() throws Exception {
+ ProfileTo updatedTo = ProfileTestData.getUpdatedTo();
+ updatedTo.setId(ProfileTestData.USER_ID);
+
+ perform(MockMvcRequestBuilders.put(REST_URL)
+ .contentType(MediaType.APPLICATION_JSON)
+ .content(writeValue(updatedTo)))
+ .andDo(print())
+ .andExpect(status().isNoContent());
+
+ Profile updatedProfile = profileRepository.getExisted(ProfileTestData.USER_ID);
+ PROFILE_MATCHER.assertMatch(updatedProfile, ProfileTestData.getUpdated(ProfileTestData.USER_ID));
+ }
+
+ @Test
+ @WithUserDetails(value = USER_MAIL)
+ void updateInValid() throws Exception {
+ ProfileTo invalidTo = ProfileTestData.getInvalidTo();
+
+ perform(MockMvcRequestBuilders.put(REST_URL)
+ .contentType(MediaType.APPLICATION_JSON)
+ .content(writeValue(invalidTo)))
+ .andDo(print())
+ .andExpect(status().isUnprocessableEntity());
+ }
+
+ @Test
+ void updateUnauthorized() throws Exception {
+ ProfileTo updatedTo = ProfileTestData.getUpdatedTo();
+
+ perform(MockMvcRequestBuilders.put(REST_URL)
+ .contentType(MediaType.APPLICATION_JSON)
+ .content(writeValue(updatedTo)))
+ .andDo(print())
+ .andExpect(status().isUnauthorized());
+ }
+
+ @Test
+ @WithUserDetails(value = USER_MAIL)
+ void updateWithUnknownNotification() throws Exception {
+ ProfileTo invalidNotificationTo = ProfileTestData.getWithUnknownNotificationTo();
+
+ perform(MockMvcRequestBuilders.put(REST_URL)
+ .contentType(MediaType.APPLICATION_JSON)
+ .content(writeValue(invalidNotificationTo)))
+ .andDo(print())
+ .andExpect(status().isUnprocessableEntity());
+ }
+
+ @Test
+ @WithUserDetails(value = USER_MAIL)
+ void updateWithUnknownContact() throws Exception {
+ ProfileTo invalidContactTo = ProfileTestData.getWithUnknownContactTo();
+
+ perform(MockMvcRequestBuilders.put(REST_URL)
+ .contentType(MediaType.APPLICATION_JSON)
+ .content(writeValue(invalidContactTo)))
+ .andDo(print())
+ .andExpect(status().isUnprocessableEntity());
+ }
+
+ @Test
+ @WithUserDetails(value = USER_MAIL)
+ void updateWithHtmlUnsafeContact() throws Exception {
+ ProfileTo unsafeContactTo = ProfileTestData.getWithContactHtmlUnsafeTo();
+
+ perform(MockMvcRequestBuilders.put(REST_URL)
+ .contentType(MediaType.APPLICATION_JSON)
+ .content(writeValue(unsafeContactTo)))
+ .andDo(print())
+ .andExpect(status().isUnprocessableEntity());
+ }
}
\ No newline at end of file
diff --git a/src/test/java/com/javarush/jira/profile/internal/web/ProfileTestData.java b/src/test/java/com/javarush/jira/profile/internal/web/ProfileTestData.java
index fb4407268..f3359e211 100644
--- a/src/test/java/com/javarush/jira/profile/internal/web/ProfileTestData.java
+++ b/src/test/java/com/javarush/jira/profile/internal/web/ProfileTestData.java
@@ -10,6 +10,11 @@
import java.util.Set;
public class ProfileTestData {
+ public static final long USER_ID = 1L;
+
+ public static MatcherFactory.Matcher PROFILE_TO_MATCHER =
+ MatcherFactory.usingIgnoringFieldsComparator(ProfileTo.class, "id");
+
public static MatcherFactory.Matcher PROFILE_MATCHER =
MatcherFactory.usingIgnoringFieldsComparator(Profile.class, "user");
@@ -18,6 +23,7 @@ public class ProfileTestData {
Set.of(new ContactTo("skype", "userSkype"),
new ContactTo("mobile", "+01234567890"),
new ContactTo("website", "user.com")));
+
public static ProfileTo GUEST_PROFILE_EMPTY_TO = new ProfileTo(null,
Set.of(),
Set.of());
@@ -85,4 +91,4 @@ public static ProfileTo getWithContactHtmlUnsafeTo() {
Collections.emptySet(),
Set.of(new ContactTo("tg", "")));
}
-}
+}
\ No newline at end of file
diff --git a/src/test/resources/application-test.yaml b/src/test/resources/application-test.yaml
index 51137fd06..55a6b7906 100644
--- a/src/test/resources/application-test.yaml
+++ b/src/test/resources/application-test.yaml
@@ -1,8 +1,26 @@
spring.cache.type: none
spring:
+ config:
+ import: optional:classpath:secrets-test.properties
init:
mode: always
datasource:
url: jdbc:postgresql://localhost:5433/jira-test
- username: jira
- password: JiraRush
\ No newline at end of file
+ username: ${DB_USERNAME}
+ password: ${DB_PASSWORD}
+
+#spring:
+# datasource:
+# driver-class-name: org.h2.Driver
+# url: jdbc:h2:mem:testdb;MODE=PostgreSQL;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE
+# username: sa
+# password:
+# jpa:
+# hibernate:
+# ddl-auto: none
+# database-platform: org.hibernate.dialect.H2Dialect
+# liquibase:
+# change-log: classpath:changelog-test.sql
+# contexts: test
+# enabled: true
+
diff --git a/src/test/resources/changelog-test.sql b/src/test/resources/changelog-test.sql
new file mode 100644
index 000000000..43ac95c29
--- /dev/null
+++ b/src/test/resources/changelog-test.sql
@@ -0,0 +1,323 @@
+--liquibase formatted sql
+
+--changeset kmpk:init_schema
+DROP TABLE IF EXISTS USER_ROLE;
+DROP TABLE IF EXISTS CONTACT;
+
+DROP TABLE IF EXISTS MAIL_CASE;
+DROP SEQUENCE IF EXISTS MAIL_CASE_ID_SEQ;
+
+DROP TABLE IF EXISTS PROFILE;
+DROP TABLE IF EXISTS TASK_TAG;
+
+DROP TABLE IF EXISTS USER_BELONG;
+DROP SEQUENCE IF EXISTS USER_BELONG_ID_SEQ;
+
+DROP TABLE IF EXISTS ACTIVITY;
+DROP SEQUENCE IF EXISTS ACTIVITY_ID_SEQ;
+
+DROP TABLE IF EXISTS TASK;
+DROP SEQUENCE IF EXISTS TASK_ID_SEQ;
+
+DROP TABLE IF EXISTS SPRINT;
+DROP SEQUENCE IF EXISTS SPRINT_ID_SEQ;
+
+DROP TABLE IF EXISTS PROJECT;
+DROP SEQUENCE IF EXISTS PROJECT_ID_SEQ;
+
+DROP TABLE IF EXISTS REFERENCE;
+DROP SEQUENCE IF EXISTS REFERENCE_ID_SEQ;
+
+DROP TABLE IF EXISTS ATTACHMENT;
+DROP SEQUENCE IF EXISTS ATTACHMENT_ID_SEQ;
+
+DROP TABLE IF EXISTS USERS;
+DROP SEQUENCE IF EXISTS USERS_ID_SEQ;
+
+create table PROJECT
+(
+ ID bigint generated by default as identity primary key,
+ CODE varchar(32) not null
+ constraint UK_PROJECT_CODE unique,
+ TITLE varchar(1024) not null,
+ DESCRIPTION varchar(4096) not null,
+ TYPE_CODE varchar(32) not null,
+ STARTPOINT timestamp,
+ ENDPOINT timestamp,
+ PARENT_ID bigint,
+ constraint FK_PROJECT_PARENT foreign key (PARENT_ID) references PROJECT (ID) on delete cascade
+);
+
+create table MAIL_CASE
+(
+ ID bigint generated by default as identity primary key,
+ EMAIL varchar(255) not null,
+ NAME varchar(255) not null,
+ DATE_TIME timestamp not null,
+ RESULT varchar(255) not null,
+ TEMPLATE varchar(255) not null
+);
+
+create table SPRINT
+(
+ ID bigint generated by default as identity primary key,
+ STATUS_CODE varchar(32) not null,
+ STARTPOINT timestamp,
+ ENDPOINT timestamp,
+ TITLE varchar(1024) not null,
+ PROJECT_ID bigint not null,
+ constraint FK_SPRINT_PROJECT foreign key (PROJECT_ID) references PROJECT (ID) on delete cascade
+);
+
+create table REFERENCE
+(
+ ID bigint generated by default as identity primary key,
+ CODE varchar(32) not null,
+ REF_TYPE smallint not null,
+ ENDPOINT timestamp,
+ STARTPOINT timestamp,
+ TITLE varchar(1024) not null,
+ AUX varchar,
+ constraint UK_REFERENCE_REF_TYPE_CODE unique (REF_TYPE, CODE)
+);
+
+create table USERS
+(
+ ID bigint generated by default as identity primary key,
+ DISPLAY_NAME varchar(32) not null
+ constraint UK_USERS_DISPLAY_NAME unique,
+ EMAIL varchar(128) not null
+ constraint UK_USERS_EMAIL unique,
+ FIRST_NAME varchar(32) not null,
+ LAST_NAME varchar(32),
+ PASSWORD varchar(128) not null,
+ ENDPOINT timestamp,
+ STARTPOINT timestamp
+);
+
+create table PROFILE
+(
+ ID bigint primary key,
+ LAST_LOGIN timestamp,
+ LAST_FAILED_LOGIN timestamp,
+ MAIL_NOTIFICATIONS bigint,
+ constraint FK_PROFILE_USERS foreign key (ID) references USERS (ID) on delete cascade
+);
+
+create table CONTACT
+(
+ ID bigint not null,
+ CODE varchar(32) not null,
+ CONTACT_VALUE varchar(256) not null,
+ primary key (ID, CODE),
+ constraint FK_CONTACT_PROFILE foreign key (ID) references PROFILE (ID) on delete cascade
+);
+
+create table TASK
+(
+ ID bigint generated by default as identity primary key,
+ TITLE varchar(1024) not null,
+ DESCRIPTION varchar(4096), -- not null
+ TYPE_CODE varchar(32) not null,
+ STATUS_CODE varchar(32) not null,
+ PRIORITY_CODE varchar(32) not null,
+ ESTIMATE integer,
+ UPDATED timestamp,
+ PROJECT_ID bigint not null,
+ SPRINT_ID bigint,
+ PARENT_ID bigint,
+ STARTPOINT timestamp,
+ ENDPOINT timestamp,
+ constraint FK_TASK_SPRINT foreign key (SPRINT_ID) references SPRINT (ID) on delete set null,
+ constraint FK_TASK_PROJECT foreign key (PROJECT_ID) references PROJECT (ID) on delete cascade,
+ constraint FK_TASK_PARENT_TASK foreign key (PARENT_ID) references TASK (ID) on delete cascade
+);
+
+create table ACTIVITY
+(
+ ID bigint generated by default as identity primary key,
+ AUTHOR_ID bigint not null,
+ TASK_ID bigint not null,
+ UPDATED timestamp,
+ COMMENT varchar(4096),
+-- history of task field change
+ TITLE varchar(1024),
+ DESCRIPTION varchar(4096),
+ ESTIMATE integer,
+ TYPE_CODE varchar(32),
+ STATUS_CODE varchar(32),
+ PRIORITY_CODE varchar(32),
+ constraint FK_ACTIVITY_USERS foreign key (AUTHOR_ID) references USERS (ID),
+ constraint FK_ACTIVITY_TASK foreign key (TASK_ID) references TASK (ID) on delete cascade
+);
+
+create table TASK_TAG
+(
+ TASK_ID bigint not null,
+ TAG varchar(32) not null,
+ constraint UK_TASK_TAG unique (TASK_ID, TAG),
+ constraint FK_TASK_TAG foreign key (TASK_ID) references TASK (ID) on delete cascade
+);
+
+create table USER_BELONG
+(
+ ID bigint generated by default as identity primary key,
+ OBJECT_ID bigint not null,
+ OBJECT_TYPE smallint not null,
+ USER_ID bigint not null,
+ USER_TYPE_CODE varchar(32) not null,
+ STARTPOINT timestamp,
+ ENDPOINT timestamp,
+ constraint FK_USER_BELONG foreign key (USER_ID) references USERS (ID)
+);
+-- create unique index UK_USER_BELONG on USER_BELONG (OBJECT_ID, OBJECT_TYPE, USER_ID, USER_TYPE_CODE);
+-- create index IX_USER_BELONG_USER_ID on USER_BELONG (USER_ID);
+
+create table ATTACHMENT
+(
+ ID bigint generated by default as identity primary key,
+ NAME varchar(128) not null,
+ FILE_LINK varchar(2048) not null,
+ OBJECT_ID bigint not null,
+ OBJECT_TYPE smallint not null,
+ USER_ID bigint not null,
+ DATE_TIME timestamp,
+ constraint FK_ATTACHMENT foreign key (USER_ID) references USERS (ID)
+);
+
+create table USER_ROLE
+(
+ USER_ID bigint not null,
+ ROLE smallint not null,
+ constraint UK_USER_ROLE unique (USER_ID, ROLE),
+ constraint FK_USER_ROLE foreign key (USER_ID) references USERS (ID) on delete cascade
+);
+
+--changeset kmpk:populate_data
+--============ References =================
+insert into REFERENCE (CODE, TITLE, REF_TYPE)
+-- TASK
+values ('task', 'Task', 2),
+ ('story', 'Story', 2),
+ ('bug', 'Bug', 2),
+ ('epic', 'Epic', 2),
+-- SPRINT_STATUS
+ ('planning', 'Planning', 4),
+ ('active', 'Active', 4),
+ ('finished', 'Finished', 4),
+-- USER_TYPE
+ ('author', 'Author', 5),
+ ('developer', 'Developer', 5),
+ ('reviewer', 'Reviewer', 5),
+ ('tester', 'Tester', 5),
+-- PROJECT
+ ('scrum', 'Scrum', 1),
+ ('task_tracker', 'Task tracker', 1),
+-- CONTACT
+ ('skype', 'Skype', 0),
+ ('tg', 'Telegram', 0),
+ ('mobile', 'Mobile', 0),
+ ('phone', 'Phone', 0),
+ ('website', 'Website', 0),
+ ('vk', 'VK', 0),
+ ('linkedin', 'LinkedIn', 0),
+ ('github', 'GitHub', 0),
+-- PRIORITY
+ ('critical', 'Critical', 7),
+ ('high', 'High', 7),
+ ('normal', 'Normal', 7),
+ ('low', 'Low', 7),
+ ('neutral', 'Neutral', 7);
+
+insert into REFERENCE (CODE, TITLE, REF_TYPE, AUX)
+-- MAIL_NOTIFICATION
+values ('assigned', 'Assigned', 6, '1'),
+ ('three_days_before_deadline', 'Three days before deadline', 6, '2'),
+ ('two_days_before_deadline', 'Two days before deadline', 6, '4'),
+ ('one_day_before_deadline', 'One day before deadline', 6, '8'),
+ ('deadline', 'Deadline', 6, '16'),
+ ('overdue', 'Overdue', 6, '32'),
+-- TASK_STATUS
+ ('todo', 'ToDo', 3, 'in_progress,canceled'),
+ ('in_progress', 'In progress', 3, 'ready_for_review,canceled'),
+ ('ready_for_review', 'Ready for review', 3, 'review,canceled'),
+ ('review', 'Review', 3, 'in_progress,ready_for_test,canceled'),
+ ('ready_for_test', 'Ready for test', 3, 'test,canceled'),
+ ('test', 'Test', 3, 'done,in_progress,canceled'),
+ ('done', 'Done', 3, 'canceled'),
+ ('canceled', 'Canceled', 3, null);
+
+--changeset gkislin:change_backtracking_tables
+
+alter table SPRINT drop column TITLE;
+alter table SPRINT add column CODE varchar(32);
+alter table SPRINT alter column CODE set not null;
+create unique index UK_SPRINT_PROJECT_CODE on SPRINT (PROJECT_ID, CODE);
+
+ALTER TABLE TASK DROP COLUMN DESCRIPTION;
+ALTER TABLE TASK DROP COLUMN PRIORITY_CODE;
+ALTER TABLE TASK DROP COLUMN ESTIMATE;
+ALTER TABLE TASK DROP COLUMN UPDATED;
+
+--changeset ishlyakhtenkov:change_task_status_reference
+
+delete
+from REFERENCE
+where REF_TYPE = 3;
+insert into REFERENCE (CODE, TITLE, REF_TYPE, AUX)
+values ('todo', 'ToDo', 3, 'in_progress,canceled'),
+ ('in_progress', 'In progress', 3, 'ready_for_review,canceled'),
+ ('ready_for_review', 'Ready for review', 3, 'in_progress,review,canceled'),
+ ('review', 'Review', 3, 'in_progress,ready_for_test,canceled'),
+ ('ready_for_test', 'Ready for test', 3, 'review,test,canceled'),
+ ('test', 'Test', 3, 'done,in_progress,canceled'),
+ ('done', 'Done', 3, 'canceled'),
+ ('canceled', 'Canceled', 3, null);
+
+--changeset gkislin:users_add_on_delete_cascade
+
+alter table ACTIVITY drop constraint FK_ACTIVITY_USERS;
+alter table ACTIVITY add constraint FK_ACTIVITY_USERS foreign key (AUTHOR_ID) references USERS (ID) on delete cascade;
+
+alter table USER_BELONG drop constraint FK_USER_BELONG;
+alter table USER_BELONG add constraint FK_USER_BELONG foreign key (USER_ID) references USERS (ID) on delete cascade;
+
+alter table ATTACHMENT drop constraint FK_ATTACHMENT;
+alter table ATTACHMENT add constraint FK_ATTACHMENT foreign key (USER_ID) references USERS (ID) on delete cascade;
+
+--changeset valeriyemelyanov:change_user_type_reference
+
+delete
+from REFERENCE
+where REF_TYPE = 5;
+insert into REFERENCE (CODE, TITLE, REF_TYPE)
+-- USER_TYPE
+values ('project_author', 'Author', 5),
+ ('project_manager', 'Manager', 5),
+ ('sprint_author', 'Author', 5),
+ ('sprint_manager', 'Manager', 5),
+ ('task_author', 'Author', 5),
+ ('task_developer', 'Developer', 5),
+ ('task_reviewer', 'Reviewer', 5),
+ ('task_tester', 'Tester', 5);
+
+--changeset apolik:refactor_reference_aux
+
+-- TASK_TYPE
+delete
+from REFERENCE
+where REF_TYPE = 3;
+insert into REFERENCE (CODE, TITLE, REF_TYPE, AUX)
+values ('todo', 'ToDo', 3, 'in_progress,canceled|'),
+ ('in_progress', 'In progress', 3, 'ready_for_review,canceled|task_developer'),
+ ('ready_for_review', 'Ready for review', 3, 'in_progress,review,canceled|'),
+ ('review', 'Review', 3, 'in_progress,ready_for_test,canceled|task_reviewer'),
+ ('ready_for_test', 'Ready for test', 3, 'review,test,canceled|'),
+ ('test', 'Test', 3, 'done,in_progress,canceled|task_tester'),
+ ('done', 'Done', 3, 'canceled|'),
+ ('canceled', 'Canceled', 3, null);
+
+-- --changeset ishlyakhtenkov:change_UK_USER_BELONG
+
+-- drop index UK_USER_BELONG;
+-- create unique index UK_USER_BELONG on USER_BELONG (OBJECT_ID, OBJECT_TYPE, USER_ID, USER_TYPE_CODE) where ENDPOINT is null;
diff --git a/src/test/resources/data.sql b/src/test/resources/data-test.sql
similarity index 82%
rename from src/test/resources/data.sql
rename to src/test/resources/data-test.sql
index 5087dbddc..b855ecd48 100644
--- a/src/test/resources/data.sql
+++ b/src/test/resources/data-test.sql
@@ -1,32 +1,27 @@
--------- users ----------------------
-delete
-from USER_ROLE;
-delete
-from CONTACT;
-delete
-from PROFILE;
-
-delete
-from ACTIVITY;
-alter
-sequence ACTIVITY_ID_SEQ restart with 1;
-delete
-from TASK;
-alter
-sequence TASK_ID_SEQ restart with 1;
-delete
-from SPRINT;
-alter
-sequence SPRINT_ID_SEQ restart with 1;
-delete
-from PROJECT;
-alter
-sequence PROJECT_ID_SEQ restart with 1;
-
-delete
-from USERS;
-alter
-sequence USERS_ID_SEQ restart with 1;
+delete from USER_ROLE;
+delete from CONTACT;
+delete from PROFILE;
+
+delete from ACTIVITY;
+alter sequence ACTIVITY_ID_SEQ restart with 1;
+-- ALTER TABLE ACTIVITY ALTER COLUMN ID RESTART WITH 1;
+
+delete from TASK;
+alter sequence TASK_ID_SEQ restart with 1;
+-- ALTER TABLE TASK ALTER COLUMN ID RESTART WITH 1;
+
+delete from SPRINT;
+alter sequence SPRINT_ID_SEQ restart with 1;
+-- ALTER TABLE SPRINT ALTER COLUMN ID RESTART WITH 1;
+
+delete from PROJECT;
+alter sequence PROJECT_ID_SEQ restart with 1;
+-- ALTER TABLE PROJECT ALTER COLUMN ID RESTART WITH 1;
+
+delete from USERS;
+alter sequence USERS_ID_SEQ restart with 1;
+-- ALTER TABLE USERS ALTER COLUMN ID RESTART WITH 1;
insert into USERS (EMAIL, PASSWORD, FIRST_NAME, LAST_NAME, DISPLAY_NAME)
values ('user@gmail.com', '{noop}password', 'userFirstName', 'userLastName', 'userDisplayName'),
@@ -95,4 +90,4 @@ values (1, 2, 2, 'task_developer', '2023-06-14 08:35:10', '2023-06-14 08:55:00')
(1, 2, 1, 'task_tester', '2023-06-14 15:20:00', null),
(2, 2, 2, 'task_developer', '2023-06-08 07:10:00', null),
(2, 2, 1, 'task_developer', '2023-06-09 14:48:00', null),
- (2, 2, 1, 'task_tester', '2023-06-10 16:37:00', null);
+ (2, 2, 1, 'task_tester', '2023-06-10 16:37:00', null);
\ No newline at end of file
diff --git a/src/test/resources/secrets-test.properties b/src/test/resources/secrets-test.properties
new file mode 100644
index 000000000..fd8aa8e33
--- /dev/null
+++ b/src/test/resources/secrets-test.properties
@@ -0,0 +1,3 @@
+# DB
+DB_USERNAME=jira
+DB_PASSWORD=jira-test
\ No newline at end of file