From 4898b4e50d97e1aee8253cf56e410a78559412b2 Mon Sep 17 00:00:00 2001 From: malyniak Date: Mon, 13 May 2024 10:21:41 +0300 Subject: [PATCH 1/9] delete vk from changelog --- src/main/resources/db/changelog.sql | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/resources/db/changelog.sql b/src/main/resources/db/changelog.sql index 68591336d..1595f97d3 100644 --- a/src/main/resources/db/changelog.sql +++ b/src/main/resources/db/changelog.sql @@ -218,7 +218,6 @@ values ('task', 'Task', 2), ('mobile', 'Mobile', 0), ('phone', 'Phone', 0), ('website', 'Website', 0), - ('vk', 'VK', 0), ('linkedin', 'LinkedIn', 0), ('github', 'GitHub', 0), -- PRIORITY From 0135add548e98fe7158ced0dcd7f75aff26c0e04 Mon Sep 17 00:00:00 2001 From: malyniak Date: Mon, 13 May 2024 21:38:12 +0300 Subject: [PATCH 2/9] task2, add secret.yaml --- .gitignore | 2 +- src/main/resources/application.yaml | 71 ++--------------------------- src/main/resources/secrets.yaml | 67 +++++++++++++++++++++++++++ 3 files changed, 72 insertions(+), 68 deletions(-) create mode 100644 src/main/resources/secrets.yaml diff --git a/.gitignore b/.gitignore index cd38e2e7b..042bb0c0d 100644 --- a/.gitignore +++ b/.gitignore @@ -5,5 +5,5 @@ target logs attachments *.patch - +resources/secrets.yaml diff --git a/src/main/resources/application.yaml b/src/main/resources/application.yaml index 7fcba1570..aa3404bb6 100644 --- a/src/main/resources/application.yaml +++ b/src/main/resources/application.yaml @@ -27,8 +27,6 @@ spring: jdbc.batch_size: 20 datasource: url: jdbc:postgresql://localhost:5432/jira - username: jira - password: JiraRush liquibase: changeLog: "classpath:db/changelog.sql" @@ -45,75 +43,14 @@ spring: cache: cache-names: users caffeine.spec: maximumSize=10000,expireAfterAccess=5m - - security: - oauth2: - client: - registration: - github: - client-id: 3d0d8738e65881fff266 - client-secret: 0f97031ce6178b7dfb67a6af587f37e222a16120 - scope: - - email - google: - client-id: 329113642700-f8if6pu68j2repq3ef6umd5jgiliup60.apps.googleusercontent.com - client-secret: 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 - 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 - gitlab: - client-id: b8520a3266089063c0d8261cce36971defa513f5ffd9f9b7a3d16728fc83a494 - client-secret: e72c65320cf9d6495984a37b0f9cc03ec46be0bb6f071feaebbfe75168117004 - 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 - gitlab: - authorization-uri: https://gitlab.com/oauth/authorize - token-uri: https://gitlab.com/oauth/token - user-info-uri: https://gitlab.com/api/v4/user - user-name-attribute: email - + config: + import : classpath:secrets.yaml sql: init: mode: always - mail: - properties: - mail: - smtp: - starttls: - enable: true - auth: true - host: smtp.gmail.com - username: jira4jr@gmail.com - password: zdfzsrqvgimldzyj - port: 587 + + thymeleaf.check-template-location: false mvc.throw-exception-if-no-handler-found: true diff --git a/src/main/resources/secrets.yaml b/src/main/resources/secrets.yaml new file mode 100644 index 000000000..da91f53a5 --- /dev/null +++ b/src/main/resources/secrets.yaml @@ -0,0 +1,67 @@ +spring: + datasource: + username: jira + security : + oauth2 : + client : + registration : + github : + client-id : 3d0d8738e65881fff266 + client-secret : 0f97031ce6178b7dfb67a6af587f37e222a16120 + scope : + - email + google : + client-id : 329113642700-f8if6pu68j2repq3ef6umd5jgiliup60.apps.googleusercontent.com + client-secret : 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 + 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 + gitlab : + client-id : b8520a3266089063c0d8261cce36971defa513f5ffd9f9b7a3d16728fc83a494 + client-secret : e72c65320cf9d6495984a37b0f9cc03ec46be0bb6f071feaebbfe75168117004 + 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 + gitlab : + authorization-uri : https://gitlab.com/oauth/authorize + token-uri : https://gitlab.com/oauth/token + user-info-uri : https://gitlab.com/api/v4/user + user-name-attribute : email + + mail : + properties : + mail : + smtp : + starttls : + enable : true + auth : true + + host : smtp.gmail.com + username : jira4jr@gmail.com + port : 587 From c0838eb2aaa657de0baa0b1d3bdedd39456fd354 Mon Sep 17 00:00:00 2001 From: malyniak Date: Sun, 19 May 2024 21:34:28 +0300 Subject: [PATCH 3/9] add several profileRestControllerTests --- pom.xml | 5 + .../javarush/jira/JiraRushApplication.java | 2 +- src/main/resources/application.yaml | 1 - .../javarush/jira/AbstractControllerTest.java | 2 +- .../jira/JiraRushApplicationTests.java | 2 + .../web/ProfileRestControllerTest.java | 86 +++++++- .../profile/internal/web/ProfileTestData.java | 2 - .../internal/web/ProjectControllerTest.java | 2 + src/test/resources/application-test.yaml | 20 +- src/test/resources/data.sql | 196 +++++++++--------- src/test/resources/db/changelog-h2.sql | 142 +++++++++++++ src/test/resources/db/data-h2.sql | 95 +++++++++ 12 files changed, 447 insertions(+), 108 deletions(-) create mode 100644 src/test/resources/db/changelog-h2.sql create mode 100644 src/test/resources/db/data-h2.sql diff --git a/pom.xml b/pom.xml index f6c152c68..1ea9d4410 100644 --- a/pom.xml +++ b/pom.xml @@ -142,6 +142,11 @@ junit-platform-launcher test + + com.h2database + h2 + test + diff --git a/src/main/java/com/javarush/jira/JiraRushApplication.java b/src/main/java/com/javarush/jira/JiraRushApplication.java index 58be49fe7..7966b92a6 100644 --- a/src/main/java/com/javarush/jira/JiraRushApplication.java +++ b/src/main/java/com/javarush/jira/JiraRushApplication.java @@ -5,12 +5,12 @@ import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.cache.annotation.EnableCaching; +import org.springframework.context.annotation.Profile; @SpringBootApplication @EnableConfigurationProperties(AppProperties.class) @EnableCaching public class JiraRushApplication { - public static void main(String[] args) { SpringApplication.run(JiraRushApplication.class, args); } diff --git a/src/main/resources/application.yaml b/src/main/resources/application.yaml index aa3404bb6..c40950186 100644 --- a/src/main/resources/application.yaml +++ b/src/main/resources/application.yaml @@ -17,7 +17,6 @@ spring: # validate db by model hibernate: ddl-auto: validate - properties: # http://docs.jboss.org/hibernate/orm/5.3/userguide/html_single/Hibernate_User_Guide.html#configurations hibernate: diff --git a/src/test/java/com/javarush/jira/AbstractControllerTest.java b/src/test/java/com/javarush/jira/AbstractControllerTest.java index 5981bae53..254282929 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")) + @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/JiraRushApplicationTests.java b/src/test/java/com/javarush/jira/JiraRushApplicationTests.java index 287178598..222a0e020 100644 --- a/src/test/java/com/javarush/jira/JiraRushApplicationTests.java +++ b/src/test/java/com/javarush/jira/JiraRushApplicationTests.java @@ -1,6 +1,8 @@ package com.javarush.jira; import org.junit.jupiter.api.Test; +import org.springframework.test.context.ActiveProfiles; + class JiraRushApplicationTests extends BaseTests { @Test 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..112fcc85f 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,92 @@ package com.javarush.jira.profile.internal.web; +import com.fasterxml.jackson.databind.ObjectMapper; import com.javarush.jira.AbstractControllerTest; +import com.javarush.jira.login.AuthUser; +import com.javarush.jira.login.Role; +import com.javarush.jira.login.User; +import com.javarush.jira.login.internal.UserRepository; +import com.javarush.jira.profile.ProfileTo; +import com.javarush.jira.profile.internal.ProfileMapper; +import com.javarush.jira.profile.internal.ProfileRepository; +import com.javarush.jira.profile.internal.model.Profile; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.http.MediaType; +import org.springframework.security.authentication.TestingAuthenticationToken; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.context.SecurityContextHolder; +import java.util.Arrays; +import java.util.List; +import java.util.Optional; + +import static com.javarush.jira.login.Role.ADMIN; +import static com.javarush.jira.login.Role.DEV; +import static com.javarush.jira.profile.internal.web.ProfileRestController.*; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyLong; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; +import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.anonymous; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put; +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; class ProfileRestControllerTest extends AbstractControllerTest { + private final static Long USER_ID = 1L; + private final static Long PROFILE_ID=1L; + @MockBean + private ProfileRepository profileRepository; + @MockBean + private ProfileMapper mapper; + + @BeforeEach + void init() { + List roles = Arrays.asList(Role.ADMIN, Role.DEV); + var user = new User(); + user.setId(USER_ID); + user.setPassword("pass"); + user.setEmail("user@gmail.com"); + user.setRoles(List.of(ADMIN, DEV)); + AuthUser authUser = new AuthUser(user); + var testingAuthenticationToken = new TestingAuthenticationToken(authUser, authUser.getPassword(), roles); + var context = SecurityContextHolder.getContext(); + context.setAuthentication(testingAuthenticationToken); + SecurityContextHolder.setContext(context); + } + + @Test + void getProfile() throws Exception { + var profile = new Profile(); + profile.setId(PROFILE_ID); + var profileTo = new ProfileTo(PROFILE_ID, null, null); + when(mapper.toTo(profile)).thenReturn(profileTo); + perform(get(REST_URL)) + .andExpect(status().isOk()) + .andDo(print()); + } + @Test + void givenRequestIsAnonymous() throws Exception { + perform(get(REST_URL).with(anonymous())) + .andExpect(status().isUnauthorized()); + } + + @Test + void updateProfile() throws Exception { + var updatedProfileTo = ProfileTestData.getUpdatedTo(); + var updatedProfile = ProfileTestData.getUpdated(PROFILE_ID); + when(profileRepository.getOrCreate(anyLong())).thenReturn(updatedProfile); + when(mapper.updateFromTo(any(Profile.class), any(ProfileTo.class))).thenReturn(updatedProfile); + perform(put(REST_URL) + .contentType(MediaType.APPLICATION_JSON) + .content(new ObjectMapper().writeValueAsString(updatedProfileTo))) + .andExpect(status().isNoContent()); + verify(profileRepository).save(any(Profile.class)); + } +} + -} \ 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..cc0513971 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 @@ -44,7 +44,6 @@ public static ProfileTo getUpdatedTo() { new ContactTo("website", "new.com"), new ContactTo("github", "newGitHub"), new ContactTo("tg", "newTg"), - new ContactTo("vk", "newVk"), new ContactTo("linkedin", "newLinkedin"))); } @@ -57,7 +56,6 @@ public static Profile getUpdated(long id) { new Contact(id, "website", "new.com"), new Contact(id, "github", "newGitHub"), new Contact(id, "tg", "newTg"), - new Contact(id, "vk", "newVk"), new Contact(id, "linkedin", "newLinkedin"))); return profile; } diff --git a/src/test/java/com/javarush/jira/project/internal/web/ProjectControllerTest.java b/src/test/java/com/javarush/jira/project/internal/web/ProjectControllerTest.java index 4e49e9beb..b7c91184f 100644 --- a/src/test/java/com/javarush/jira/project/internal/web/ProjectControllerTest.java +++ b/src/test/java/com/javarush/jira/project/internal/web/ProjectControllerTest.java @@ -4,6 +4,7 @@ import com.javarush.jira.bugtracking.project.Project; import com.javarush.jira.bugtracking.project.ProjectRepository; import com.javarush.jira.common.BaseHandler; +import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.MediaType; @@ -19,6 +20,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + public class ProjectControllerTest extends AbstractControllerTest { private static final String REST_URL_PROJECT = BaseHandler.REST_URL + "/projects"; private static final String REST_URL_MNGR_PROJECT = BaseHandler.REST_URL + "/mngr/projects"; diff --git a/src/test/resources/application-test.yaml b/src/test/resources/application-test.yaml index 51137fd06..317269f08 100644 --- a/src/test/resources/application-test.yaml +++ b/src/test/resources/application-test.yaml @@ -2,7 +2,19 @@ spring.cache.type: none spring: init: mode: always - datasource: - url: jdbc:postgresql://localhost:5433/jira-test - username: jira - password: JiraRush \ No newline at end of file + datasource : + url : jdbc:h2:mem:test + username : sa + password : + driver-class-name : org.h2.Driver + jpa : + hibernate : + ddl-auto : update + liquibase: + change-log : db/changelog-h2.sql + flyway : + enabled : false + sql : + init : + schema-locations : classpath:db/changelog-h2.sql + data-locations : classpath:db/data-h2.sql \ No newline at end of file diff --git a/src/test/resources/data.sql b/src/test/resources/data.sql index 5087dbddc..a6d3b1134 100644 --- a/src/test/resources/data.sql +++ b/src/test/resources/data.sql @@ -1,98 +1,98 @@ ---------- 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; - -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'), - ('guest@gmail.com', '{noop}guest', 'guestFirstName', 'guestLastName', 'guestDisplayName'), - ('manager@gmail.com', '{noop}manager', 'managerFirstName', 'managerLastName', 'managerDisplayName'); - --- 0 DEV --- 1 ADMIN --- 2 MANAGER - -insert into USER_ROLE (USER_ID, ROLE) -values (1, 0), - (2, 0), - (2, 1), - (4, 2); - -insert into PROFILE (ID, LAST_FAILED_LOGIN, LAST_LOGIN, MAIL_NOTIFICATIONS) -values (1, null, null, 49), - (2, null, null, 14); - -insert into CONTACT (ID, CODE, VALUE) -values (1, 'skype', 'userSkype'), - (1, 'mobile', '+01234567890'), - (1, 'website', 'user.com'), - (2, 'github', 'adminGitHub'), - (2, 'tg', 'adminTg'), - (2, 'vk', 'adminVk'); - - -insert into PROJECT (code, title, description, type_code, parent_id) -values ('PR1', 'PROJECT-1', 'test project 1', 'task_tracker', null), - ('PR2', 'PROJECT-2', 'test project 2', 'task_tracker', 1); - -insert into SPRINT (status_code, startpoint, endpoint, code, project_id) -values ('finished', '2023-05-01 08:05:10', '2023-05-07 17:10:01', 'SP-1.001', 1), - ('active', '2023-05-01 08:06:00', null, 'SP-1.002', 1), - ('active', '2023-05-01 08:07:00', null, 'SP-1.003', 1), - ('planning', '2023-05-01 08:08:00', null, 'SP-1.004', 1), - ('active', '2023-05-10 08:06:00', null, 'SP-2.001', 2), - ('planning', '2023-05-10 08:07:00', null, 'SP-2.002', 2), - ('planning', '2023-05-10 08:08:00', null, 'SP-2.003', 2); - -insert into TASK (TITLE, TYPE_CODE, STATUS_CODE, PROJECT_ID, SPRINT_ID, STARTPOINT) -values ('Data', 'epic', 'in_progress', 1, 1, '2023-05-15 09:05:10'), - ('Trees', 'epic', 'in_progress', 1, 1, '2023-05-15 12:05:10'), - ('task-3', 'task', 'ready_for_test', 2, 5, '2023-06-14 09:28:10'), - ('task-4', 'task', 'ready_for_review', 2, 5, '2023-06-14 09:28:10'), - ('task-5', 'task', 'todo', 2, 5, '2023-06-14 09:28:10'), - ('task-6', 'task', 'done', 2, 5, '2023-06-14 09:28:10'), - ('task-7', 'task', 'canceled', 2, 5, '2023-06-14 09:28:10'); - - -insert into ACTIVITY(AUTHOR_ID, TASK_ID, UPDATED, COMMENT, TITLE, DESCRIPTION, ESTIMATE, TYPE_CODE, STATUS_CODE, - PRIORITY_CODE) -values (1, 1, '2023-05-15 09:05:10', null, 'Data', null, 3, 'epic', 'in_progress', 'low'), - (2, 1, '2023-05-15 12:25:10', null, 'Data', null, null, null, null, 'normal'), - (1, 1, '2023-05-15 14:05:10', null, 'Data', null, 4, null, null, null), - (1, 2, '2023-05-15 12:05:10', null, 'Trees', 'Trees desc', 4, 'epic', 'in_progress', 'normal'); - -insert into USER_BELONG (OBJECT_ID, OBJECT_TYPE, USER_ID, USER_TYPE_CODE, STARTPOINT, ENDPOINT) -values (1, 2, 2, 'task_developer', '2023-06-14 08:35:10', '2023-06-14 08:55:00'), - (1, 2, 2, 'task_reviewer', '2023-06-14 09:35:10', null), - (1, 2, 1, 'task_developer', '2023-06-12 11:40:00', '2023-06-12 12:35:00'), - (1, 2, 1, 'task_developer', '2023-06-13 12:35:00', null), - (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); +-- --------- 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; +-- +-- 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'), +-- ('guest@gmail.com', '{noop}guest', 'guestFirstName', 'guestLastName', 'guestDisplayName'), +-- ('manager@gmail.com', '{noop}manager', 'managerFirstName', 'managerLastName', 'managerDisplayName'); +-- +-- -- 0 DEV +-- -- 1 ADMIN +-- -- 2 MANAGER +-- +-- insert into USER_ROLE (USER_ID, ROLE) +-- values (1, 0), +-- (2, 0), +-- (2, 1), +-- (4, 2); +-- +-- insert into PROFILE (ID, LAST_FAILED_LOGIN, LAST_LOGIN, MAIL_NOTIFICATIONS) +-- values (1, null, null, 49), +-- (2, null, null, 14); +-- +-- -- insert into CONTACT (ID, CODE, VALUE) +-- -- values (1, 'skype', 'userSkype'), +-- -- (1, 'mobile', '+01234567890'), +-- -- (1, 'website', 'user.com'), +-- -- (2, 'github', 'adminGitHub'), +-- -- (2, 'tg', 'adminTg'), +-- -- (2, 'vk', 'adminVk'); +-- +-- +-- -- insert into PROJECT (code, title, description, type_code, parent_id) +-- -- values ('PR1', 'PROJECT-1', 'test project 1', 'task_tracker', null), +-- -- ('PR2', 'PROJECT-2', 'test project 2', 'task_tracker', 1); +-- +-- insert into SPRINT (status_code, startpoint, endpoint, code, project_id) +-- values ('finished', '2023-05-01 08:05:10', '2023-05-07 17:10:01', 'SP-1.001', 1), +-- ('active', '2023-05-01 08:06:00', null, 'SP-1.002', 1), +-- ('active', '2023-05-01 08:07:00', null, 'SP-1.003', 1), +-- ('planning', '2023-05-01 08:08:00', null, 'SP-1.004', 1), +-- ('active', '2023-05-10 08:06:00', null, 'SP-2.001', 2), +-- ('planning', '2023-05-10 08:07:00', null, 'SP-2.002', 2), +-- ('planning', '2023-05-10 08:08:00', null, 'SP-2.003', 2); +-- +-- insert into TASK (TITLE, TYPE_CODE, STATUS_CODE, PROJECT_ID, SPRINT_ID, STARTPOINT) +-- values ('Data', 'epic', 'in_progress', 1, 1, '2023-05-15 09:05:10'), +-- ('Trees', 'epic', 'in_progress', 1, 1, '2023-05-15 12:05:10'), +-- ('task-3', 'task', 'ready_for_test', 2, 5, '2023-06-14 09:28:10'), +-- ('task-4', 'task', 'ready_for_review', 2, 5, '2023-06-14 09:28:10'), +-- ('task-5', 'task', 'todo', 2, 5, '2023-06-14 09:28:10'), +-- ('task-6', 'task', 'done', 2, 5, '2023-06-14 09:28:10'), +-- ('task-7', 'task', 'canceled', 2, 5, '2023-06-14 09:28:10'); +-- +-- +-- insert into ACTIVITY(AUTHOR_ID, TASK_ID, UPDATED, COMMENT, TITLE, DESCRIPTION, ESTIMATE, TYPE_CODE, STATUS_CODE, +-- PRIORITY_CODE) +-- values (1, 1, '2023-05-15 09:05:10', null, 'Data', null, 3, 'epic', 'in_progress', 'low'), +-- (2, 1, '2023-05-15 12:25:10', null, 'Data', null, null, null, null, 'normal'), +-- (1, 1, '2023-05-15 14:05:10', null, 'Data', null, 4, null, null, null), +-- (1, 2, '2023-05-15 12:05:10', null, 'Trees', 'Trees desc', 4, 'epic', 'in_progress', 'normal'); +-- +-- insert into USER_BELONG (OBJECT_ID, OBJECT_TYPE, USER_ID, USER_TYPE_CODE, STARTPOINT, ENDPOINT) +-- values (1, 2, 2, 'task_developer', '2023-06-14 08:35:10', '2023-06-14 08:55:00'), +-- (1, 2, 2, 'task_reviewer', '2023-06-14 09:35:10', null), +-- (1, 2, 1, 'task_developer', '2023-06-12 11:40:00', '2023-06-12 12:35:00'), +-- (1, 2, 1, 'task_developer', '2023-06-13 12:35:00', null), +-- (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); diff --git a/src/test/resources/db/changelog-h2.sql b/src/test/resources/db/changelog-h2.sql new file mode 100644 index 000000000..1391b049b --- /dev/null +++ b/src/test/resources/db/changelog-h2.sql @@ -0,0 +1,142 @@ +--liquibase formatted sql + +--changeset kmpk:init +CREATE TABLE IF NOT EXISTS PROJECT ( + ID BIGINT AUTO_INCREMENT PRIMARY KEY, + CODE VARCHAR(32) NOT NULL 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 IF NOT EXISTS MAIL_CASE ( + ID BIGINT AUTO_INCREMENT 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 IF NOT EXISTS SPRINT ( + ID BIGINT AUTO_INCREMENT 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 IF NOT EXISTS REFERENCE ( + ID BIGINT AUTO_INCREMENT 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 IF NOT EXISTS USERS ( + ID BIGINT AUTO_INCREMENT PRIMARY KEY, + DISPLAY_NAME VARCHAR(32) NOT NULL UNIQUE, + EMAIL VARCHAR(128) NOT NULL UNIQUE, + FIRST_NAME VARCHAR(32) NOT NULL, + LAST_NAME VARCHAR(32), + PASSWORD VARCHAR(128) NOT NULL, + ENDPOINT TIMESTAMP, + STARTPOINT TIMESTAMP +); + +CREATE TABLE IF NOT EXISTS 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 IF NOT EXISTS CONTACT ( +-- ID BIGINT NOT NULL, +-- CODE VARCHAR(32) NOT NULL, +-- VALUE VARCHAR(256) NOT NULL, +-- PRIMARY KEY (ID, CODE), +-- CONSTRAINT FK_CONTACT_PROFILE FOREIGN KEY (ID) REFERENCES PROFILE (ID) ON DELETE CASCADE +-- ); + +CREATE TABLE IF NOT EXISTS TASK ( + ID BIGINT AUTO_INCREMENT 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 IF NOT EXISTS ACTIVITY ( + ID BIGINT AUTO_INCREMENT PRIMARY KEY, + AUTHOR_ID BIGINT NOT NULL, + TASK_ID BIGINT NOT NULL, + UPDATED TIMESTAMP, + COMMENT VARCHAR(4096), + 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 IF NOT EXISTS 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 IF NOT EXISTS USER_BELONG ( + ID BIGINT AUTO_INCREMENT 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 TABLE IF NOT EXISTS ATTACHMENT ( + ID BIGINT AUTO_INCREMENT 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 IF NOT EXISTS 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 +); \ No newline at end of file diff --git a/src/test/resources/db/data-h2.sql b/src/test/resources/db/data-h2.sql new file mode 100644 index 000000000..d3d4fdb3f --- /dev/null +++ b/src/test/resources/db/data-h2.sql @@ -0,0 +1,95 @@ +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), + ('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); + +CREATE TABLE IF NOT EXISTS USERS ( + ID BIGINT AUTO_INCREMENT PRIMARY KEY, + DISPLAY_NAME VARCHAR(32) NOT NULL UNIQUE, + EMAIL VARCHAR(128) NOT NULL UNIQUE, + FIRST_NAME VARCHAR(32) NOT NULL, + LAST_NAME VARCHAR(32), + PASSWORD VARCHAR(128) NOT NULL, + ENDPOINT TIMESTAMP, + STARTPOINT TIMESTAMP +); + + + +insert into USERS (EMAIL, PASSWORD, FIRST_NAME, LAST_NAME, DISPLAY_NAME) +values ('user@gmail.com', 'testPassword', 'userFirstName', 'userLastName', 'userDisplayName'), + ('admin@gmail.com', 'testPassword', 'adminFirstName', 'adminLastName', 'adminDisplayName'), + ('guest@gmail.com', 'testPassword', 'guestFirstName', 'guestLastName', 'guestDisplayName'), + ('manager@gmail.com', 'testPassword', 'managerFirstName', 'managerLastName', 'managerDisplayName'), + ('taras@gmail.com', 'testPassword', 'Тарас', 'Шевченко', '@taras'), + ('petlura@gmail.com', 'testPassword', 'Симон', 'Петлюра', '@epetl'), + ('moroz_a@gmail.com', 'testPassword', 'Александр', 'Мороз', '@Moroz93'), + ('antonio.nest@gmail.com', 'testPassword', 'Антон', 'Нестеров', '@antonio_nest'), + ('i.franko@gmail.com', 'testPassword', 'Иван', 'Франко', '@ifranko'), + ('g.skovoroda@gmail.com', 'testPassword', 'Григорий', 'Сковорода', '@Gregory24'), + ('arsh.and@gmail.com', 'testPassword', 'Андрей', 'Арш', '@arsh01'), + ('squirrel2011@gmail.com', 'testPassword', 'Леся', 'Иванюк', '@SmallSquirrel'), + ('nikk24@gmail.com', 'testPassword', 'Николай', 'Никулин', '@nikk'), + ('artem711@gmail.com', 'testPassword', 'Артем', 'Запорожец', '@Artt'), + ('max.pain@gmail.com', 'testPassword', 'Максим', 'Дудник', '@MaxPain'), + ('admin@aws.co', 'testPassword', 'test', 'admin', '@testAdmin'); + + + +CREATE TABLE IF NOT EXISTS 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 +); + +insert into PROFILE (ID, LAST_FAILED_LOGIN, LAST_LOGIN, MAIL_NOTIFICATIONS) +values (1, null, null, 49), + (2, null, null, 14); From 6d8e9d56aaef878e871d334a761a81e0435b7ef3 Mon Sep 17 00:00:00 2001 From: malyniak Date: Mon, 20 May 2024 19:19:40 +0300 Subject: [PATCH 4/9] change fileutil, use java.nio --- .../jira/bugtracking/attachment/FileUtil.java | 25 ++++++++++--------- .../web/ProfileRestControllerTest.java | 4 --- 2 files changed, 13 insertions(+), 16 deletions(-) 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..13b76d56b 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,14 @@ 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.net.MalformedURLException; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; +import java.nio.file.*; +import java.nio.file.StandardOpenOption; + +import static java.nio.file.Files.createDirectories; +import static java.nio.file.Files.createFile; @UtilityClass public class FileUtil { @@ -24,15 +24,16 @@ public static void upload(MultipartFile multipartFile, String directoryPath, Str if (multipartFile.isEmpty()) { 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)) { + var dir = Paths.get(directoryPath); + Path file = null; + try { + createDirectories(dir); + file = createFile(Path.of(fileName)); + try (OutputStream outStream = Files.newOutputStream(file, StandardOpenOption.CREATE)) { outStream.write(multipartFile.getBytes()); - } catch (IOException ex) { - throw new IllegalRequestDataException("Failed to upload file" + multipartFile.getOriginalFilename()); } + } catch (IOException ex) { + throw new IllegalRequestDataException("Failed to upload file" + multipartFile.getOriginalFilename()); } } 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 112fcc85f..68e030a50 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 @@ -5,7 +5,6 @@ import com.javarush.jira.login.AuthUser; import com.javarush.jira.login.Role; import com.javarush.jira.login.User; -import com.javarush.jira.login.internal.UserRepository; import com.javarush.jira.profile.ProfileTo; import com.javarush.jira.profile.internal.ProfileMapper; import com.javarush.jira.profile.internal.ProfileRepository; @@ -17,10 +16,8 @@ import org.springframework.security.authentication.TestingAuthenticationToken; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.context.SecurityContextHolder; - import java.util.Arrays; import java.util.List; -import java.util.Optional; import static com.javarush.jira.login.Role.ADMIN; import static com.javarush.jira.login.Role.DEV; @@ -33,7 +30,6 @@ import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put; 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; class ProfileRestControllerTest extends AbstractControllerTest { From 0169047dd27d28432109027ba9e12d4904c437e4 Mon Sep 17 00:00:00 2001 From: malyniak Date: Tue, 21 May 2024 21:34:59 +0300 Subject: [PATCH 5/9] add tag to tasks --- .../jira/bugtracking/task/TaskController.java | 6 ++ .../jira/bugtracking/task/TaskService.java | 8 +++ .../bugtracking/task/TaskControllerTest.java | 8 +++ src/test/resources/db/changelog-h2.sql | 1 + src/test/resources/db/data-h2.sql | 65 +++++++++++++++++++ 5 files changed, 88 insertions(+) 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..ebdbe0c31 100644 --- a/src/main/java/com/javarush/jira/bugtracking/task/TaskController.java +++ b/src/main/java/com/javarush/jira/bugtracking/task/TaskController.java @@ -156,4 +156,10 @@ public TaskTreeNode(TaskTo taskTo) { this(taskTo, new LinkedList<>()); } } + + @PostMapping("/{id}/tags") + @ResponseStatus(HttpStatus.CREATED) + public void createTag(@PathVariable long id, @RequestParam String tag) { + taskService.createTag(id, tag); + } } 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..aa5ab6d76 100644 --- a/src/main/java/com/javarush/jira/bugtracking/task/TaskService.java +++ b/src/main/java/com/javarush/jira/bugtracking/task/TaskService.java @@ -39,6 +39,7 @@ public class TaskService { private final SprintRepository sprintRepository; private final TaskExtMapper extMapper; private final UserBelongRepository userBelongRepository; + private final TaskRepository taskRepository; @Transactional public void changeStatus(long taskId, String statusCode) { @@ -132,6 +133,13 @@ public void unAssign(long id, String userType, long userId) { assignment.setEndpoint(LocalDateTime.now()); } + @Transactional + public void createTag(long id, String tag) { + var task = Util.checkExist(id, handler.getRepository().findFullById(id)); + task.getTags().add(tag); + taskRepository.save(task); + } + private void checkAssignmentActionPossible(long id, String userType, boolean assign) { Assert.notNull(userType, "userType must not be null"); Task task = handler.getRepository().getExisted(id); diff --git a/src/test/java/com/javarush/jira/bugtracking/task/TaskControllerTest.java b/src/test/java/com/javarush/jira/bugtracking/task/TaskControllerTest.java index b5c25e992..ad4ebb4c4 100644 --- a/src/test/java/com/javarush/jira/bugtracking/task/TaskControllerTest.java +++ b/src/test/java/com/javarush/jira/bugtracking/task/TaskControllerTest.java @@ -590,4 +590,12 @@ void unAssignFromTaskWhenNotAssigned() throws Exception { .andExpect(jsonPath("$.detail", is(String .format("Not found assignment with userType=%s for task {%d} for user {%d}", TASK_DEVELOPER, TASK1_ID, ADMIN_ID)))); } + + @Test + @WithUserDetails(value = USER_MAIL) + void createTag() throws Exception { + perform(MockMvcRequestBuilders.post("/api/tasks/1/tags") + .param("tag", "testTag")) + .andExpect(status().isCreated()); + } } diff --git a/src/test/resources/db/changelog-h2.sql b/src/test/resources/db/changelog-h2.sql index 1391b049b..4f251f40d 100644 --- a/src/test/resources/db/changelog-h2.sql +++ b/src/test/resources/db/changelog-h2.sql @@ -27,6 +27,7 @@ CREATE TABLE IF NOT EXISTS SPRINT ( STATUS_CODE VARCHAR(32) NOT NULL, STARTPOINT TIMESTAMP, ENDPOINT TIMESTAMP, + CODE varchar (512) not null, TITLE VARCHAR(1024) NOT NULL, PROJECT_ID BIGINT NOT NULL, CONSTRAINT FK_SPRINT_PROJECT FOREIGN KEY (PROJECT_ID) REFERENCES PROJECT(ID) ON DELETE CASCADE diff --git a/src/test/resources/db/data-h2.sql b/src/test/resources/db/data-h2.sql index d3d4fdb3f..357f4f09d 100644 --- a/src/test/resources/db/data-h2.sql +++ b/src/test/resources/db/data-h2.sql @@ -93,3 +93,68 @@ CREATE TABLE IF NOT EXISTS PROFILE ( insert into PROFILE (ID, LAST_FAILED_LOGIN, LAST_LOGIN, MAIL_NOTIFICATIONS) values (1, null, null, 49), (2, null, null, 14); + +create table IF NOT EXISTS PROJECT +( + ID bigint 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 +); + +insert into PROJECT (code, title, description, type_code, parent_id) +values ('JiraRush', 'JiraRush', '«Mini-JIRA» app : project management system tutorial app', 'task_tracker', null), + ('Test_Project', 'Test Project', 'Just test project', 'task_tracker', null), + ('Test_Project_2', 'Test Project 2', 'Just test project 2', 'task_tracker', null), + ('JiraRush sub', 'JiraRush subproject', 'subproject', 'task_tracker', 1); + +create table IF NOT EXISTS SPRINT +( + ID bigint primary key, + STATUS_CODE varchar(32) not null, + STARTPOINT timestamp, + ENDPOINT timestamp, + CODE varchar(512) not null, + TITLE varchar(1024) not null, + PROJECT_ID bigint not null, + constraint FK_SPRINT_PROJECT foreign key (PROJECT_ID) references PROJECT (ID) on delete cascade + + +); + +insert into SPRINT (status_code, startpoint, endpoint, code, TITLE, project_id) +values ('active', null, null, 'code', 'Sprint-2', 1), + ('finished', '2023-04-09 08:05:10', '2023-04-29 16:48:34', 'code', 'Sprint-1', 2), + ('finished', '2023-04-03 12:14:11', '2023-04-18 17:03:41', 'code', 'Sprint-2', 2), + ('active', '2023-04-05 14:25:43', '2023-06-10 13:00:00', 'code', 'Sprint-3', 2), + ('active', null, null, 'code', 'Sprint-1', 4); + +CREATE TABLE IF NOT EXISTS TASK ( + ID BIGINT AUTO_INCREMENT 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 +); + + +INSERT INTO TASK (TITLE, TYPE_CODE, DESCRIPTION, STATUS_CODE, PRIORITY_CODE, PROJECT_ID, SPRINT_ID, STARTPOINT) +values ('Data', 'epic', 'desc', 'in_progress', 1, 1, 1, + TIMESTAMPADD(SECOND, CAST((RANDOM() * 5 * 60) AS INT) + CAST((RANDOM() * 20) AS INT), CURRENT_TIMESTAMP)); \ No newline at end of file From 67734f66aefaae94c8c8923f4641d3d710811b6a Mon Sep 17 00:00:00 2001 From: malyniak Date: Thu, 23 May 2024 20:23:52 +0300 Subject: [PATCH 6/9] add docker-compose.yml and fix profileController test --- docker-compose.yml | 40 +++++++++++++++++++ .../jira/bugtracking/task/TaskRepository.java | 8 +++- .../jira/bugtracking/task/TaskService.java | 13 +++++- src/main/resources/db/changelog.sql | 3 ++ .../bugtracking/task/TaskControllerTest.java | 3 +- .../web/ProfileRestControllerTest.java | 3 +- src/test/resources/db/data-h2.sql | 30 +++++++++++++- 7 files changed, 94 insertions(+), 6 deletions(-) create mode 100644 docker-compose.yml diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 000000000..49be0e733 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,40 @@ +version: '3' + +services: + postgres-db: + image: postgres:latest + environment: + POSTGRES_DB: jira + POSTGRES_USER: jira + POSTGRES_PASSWORD: JiraRush + ports: + - "5432:5432" + networks: + - mynetwork + + postgres-db-test: + image: postgres:latest + environment: + POSTGRES_DB: jira_test + POSTGRES_USER: jira + POSTGRES_PASSWORD: JiraRush + ports: + - "5433:5432" + networks: + - mynetwork + + myapp: + image: jira-1.0 + ports: + - "8080:8080" + environment: + SPRING_DATASOURCE_URL: jdbc:postgresql://localhost:5432/jira + SPRING_DATASOURCE_USERNAME: jira + depends_on: + - postgres-db + networks: + - mynetwork + +networks: + mynetwork: + driver: bridge diff --git a/src/main/java/com/javarush/jira/bugtracking/task/TaskRepository.java b/src/main/java/com/javarush/jira/bugtracking/task/TaskRepository.java index 982c4be8b..d7ffdcb7f 100644 --- a/src/main/java/com/javarush/jira/bugtracking/task/TaskRepository.java +++ b/src/main/java/com/javarush/jira/bugtracking/task/TaskRepository.java @@ -3,8 +3,10 @@ import com.javarush.jira.common.BaseRepository; import org.springframework.data.jpa.repository.Modifying; import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; import org.springframework.transaction.annotation.Transactional; +import java.time.LocalDateTime; import java.util.List; import java.util.Optional; @@ -37,4 +39,8 @@ WITH RECURSIVE task_with_subtasks AS ( WHERE id IN (SELECT child FROM task_with_subtasks) """, nativeQuery = true) void setTaskAndSubTasksSprint(long taskId, Long sprintId); -} + + // + @Query("SELECT a.updated FROM Task t JOIN t.activities a WHERE a.statusCode = :statusCode") + LocalDateTime findByStatusCode(String statusCode); +} \ No newline at end of file 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 aa5ab6d76..53d73b8d3 100644 --- a/src/main/java/com/javarush/jira/bugtracking/task/TaskService.java +++ b/src/main/java/com/javarush/jira/bugtracking/task/TaskService.java @@ -20,6 +20,8 @@ import org.springframework.util.Assert; import java.time.LocalDateTime; +import java.time.Period; +import java.time.temporal.ChronoUnit; import java.util.List; import static com.javarush.jira.bugtracking.ObjectType.TASK; @@ -140,12 +142,21 @@ public void createTag(long id, String tag) { taskRepository.save(task); } + @Transactional + public long timeInWork(long id) { + var task = Util.checkExist(id, handler.getRepository().findFullById(id)); + var inProgress = taskRepository.findByStatusCode("in_progress"); + var readyForReview = taskRepository.findByStatusCode("ready_for_review"); + return ChronoUnit.HOURS.between(readyForReview, inProgress); + } + private void checkAssignmentActionPossible(long id, String userType, boolean assign) { Assert.notNull(userType, "userType must not be null"); Task task = handler.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())); + } } -} +} \ No newline at end of file diff --git a/src/main/resources/db/changelog.sql b/src/main/resources/db/changelog.sql index 1595f97d3..fdfb1d97a 100644 --- a/src/main/resources/db/changelog.sql +++ b/src/main/resources/db/changelog.sql @@ -328,3 +328,6 @@ 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; + + + diff --git a/src/test/java/com/javarush/jira/bugtracking/task/TaskControllerTest.java b/src/test/java/com/javarush/jira/bugtracking/task/TaskControllerTest.java index ad4ebb4c4..8421e00a3 100644 --- a/src/test/java/com/javarush/jira/bugtracking/task/TaskControllerTest.java +++ b/src/test/java/com/javarush/jira/bugtracking/task/TaskControllerTest.java @@ -5,6 +5,7 @@ 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 org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.MediaType; @@ -579,7 +580,6 @@ private void unAssignFromTaskWhenStatusForbidUnAssignment(long taskId, String ta .andExpect(status().isConflict()) .andExpect(jsonPath("$.detail", is(String.format(CANNOT_UN_ASSIGN, TASK_DEVELOPER, taskStatus)))); } - @Test @WithUserDetails(value = ADMIN_MAIL) void unAssignFromTaskWhenNotAssigned() throws Exception { @@ -590,7 +590,6 @@ void unAssignFromTaskWhenNotAssigned() throws Exception { .andExpect(jsonPath("$.detail", is(String .format("Not found assignment with userType=%s for task {%d} for user {%d}", TASK_DEVELOPER, TASK1_ID, ADMIN_ID)))); } - @Test @WithUserDetails(value = USER_MAIL) void createTag() throws Exception { 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 68e030a50..709d3a516 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 @@ -10,6 +10,7 @@ import com.javarush.jira.profile.internal.ProfileRepository; import com.javarush.jira.profile.internal.model.Profile; import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.http.MediaType; @@ -32,6 +33,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + class ProfileRestControllerTest extends AbstractControllerTest { private final static Long USER_ID = 1L; private final static Long PROFILE_ID=1L; @@ -54,7 +56,6 @@ void init() { context.setAuthentication(testingAuthenticationToken); SecurityContextHolder.setContext(context); } - @Test void getProfile() throws Exception { var profile = new Profile(); diff --git a/src/test/resources/db/data-h2.sql b/src/test/resources/db/data-h2.sql index 357f4f09d..594286f63 100644 --- a/src/test/resources/db/data-h2.sql +++ b/src/test/resources/db/data-h2.sql @@ -157,4 +157,32 @@ CREATE TABLE IF NOT EXISTS TASK ( INSERT INTO TASK (TITLE, TYPE_CODE, DESCRIPTION, STATUS_CODE, PRIORITY_CODE, PROJECT_ID, SPRINT_ID, STARTPOINT) values ('Data', 'epic', 'desc', 'in_progress', 1, 1, 1, - TIMESTAMPADD(SECOND, CAST((RANDOM() * 5 * 60) AS INT) + CAST((RANDOM() * 20) AS INT), CURRENT_TIMESTAMP)); \ No newline at end of file + TIMESTAMPADD(SECOND, CAST((RANDOM() * 5 * 60) AS INT) + CAST((RANDOM() * 20) AS INT), CURRENT_TIMESTAMP)); + +create table if not exists ACTIVITY +( + ID bigint primary key, + AUTHOR_ID bigint not null, + TASK_ID bigint not null, + UPDATED timestamp, + COMMENT varchar(4096), + 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 +); + + +INSERT INTO ACTIVITY(AUTHOR_ID, TASK_ID, UPDATED, COMMENT, TITLE, DESCRIPTION, ESTIMATE, TYPE_CODE, STATUS_CODE, + PRIORITY_CODE) +values (6, 1, '2023-05-15 09:05:10', null, 'Data', + null, 3, 'epic', 'in_progress', 'low'), + (5, 1, '2023-05-15 12:25:10', null, 'Data', + null, null, null, 'ready_for_review', 'normal'), + (6, 1, '2023-05-15 14:05:10', null, 'Data', + null, 4, null, 'done', null); + From ee82aadf0afa6f9ff16f67743d3d467e701d767f Mon Sep 17 00:00:00 2001 From: malyniak Date: Fri, 24 May 2024 16:50:17 +0300 Subject: [PATCH 7/9] add locales in index.html and for mails --- resources/mails/email-confirmation.html | 9 ++--- resources/mails/password-reset.html | 8 ++--- resources/view/fragments.html | 21 ++++++++++++ resources/view/index.html | 7 ++-- .../jira/common/internal/web/WebConfig.java | 34 +++++++++++++++++++ .../locale/message/MessageRestController.java | 23 +++++++++++++ src/main/resources/application.yaml | 2 +- src/main/resources/messages.properties | 9 +++++ src/main/resources/messages_ru.properties | 9 +++++ src/main/resources/messages_ua.properties | 9 +++++ 10 files changed, 120 insertions(+), 11 deletions(-) create mode 100644 resources/view/fragments.html create mode 100644 src/main/java/com/javarush/jira/common/internal/web/WebConfig.java create mode 100644 src/main/java/com/javarush/jira/locale/message/MessageRestController.java create mode 100644 src/main/resources/messages.properties create mode 100644 src/main/resources/messages_ru.properties create mode 100644 src/main/resources/messages_ua.properties diff --git a/resources/mails/email-confirmation.html b/resources/mails/email-confirmation.html index 106e6129a..e88ecf69a 100644 --- a/resources/mails/email-confirmation.html +++ b/resources/mails/email-confirmation.html @@ -5,9 +5,10 @@ -

-

Чтобы завершить настройку учетной записи и начать пользоваться JiraRush, подтвердите, что вы правильно указали вашу - электронную почту.

-Подтвердить почту +

+

+ + + \ No newline at end of file diff --git a/resources/mails/password-reset.html b/resources/mails/password-reset.html index b37a49007..16958fc6c 100644 --- a/resources/mails/password-reset.html +++ b/resources/mails/password-reset.html @@ -1,12 +1,12 @@ - JiraRush - установить новый пароль + JiraRush - set new password -

-

-Установить пароль +

+

+Set password \ No newline at end of file diff --git a/resources/view/fragments.html b/resources/view/fragments.html new file mode 100644 index 000000000..3f39a56b3 --- /dev/null +++ b/resources/view/fragments.html @@ -0,0 +1,21 @@ + + + + + Fragment + + +

+
+ +
+
+ + \ No newline at end of file diff --git a/resources/view/index.html b/resources/view/index.html index e8656ef96..303b6c26a 100644 --- a/resources/view/index.html +++ b/resources/view/index.html @@ -4,11 +4,14 @@ -

JiraRush Home page

+

+ JiraRush Home page +

- +
+
diff --git a/src/main/java/com/javarush/jira/common/internal/web/WebConfig.java b/src/main/java/com/javarush/jira/common/internal/web/WebConfig.java new file mode 100644 index 000000000..5a855caef --- /dev/null +++ b/src/main/java/com/javarush/jira/common/internal/web/WebConfig.java @@ -0,0 +1,34 @@ +package com.javarush.jira.common.internal.web; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.servlet.LocaleResolver; +import org.springframework.web.servlet.config.annotation.InterceptorRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; +import org.springframework.web.servlet.i18n.LocaleChangeInterceptor; +import org.springframework.web.servlet.i18n.SessionLocaleResolver; + +import java.util.Locale; + +@Configuration +public class WebConfig implements WebMvcConfigurer { + + @Bean + public LocaleResolver localeResolver() { + SessionLocaleResolver slr = new SessionLocaleResolver(); + slr.setDefaultLocale(Locale.ENGLISH); + return slr; + } + + @Bean + public LocaleChangeInterceptor localeChangeInterceptor() { + LocaleChangeInterceptor lci = new LocaleChangeInterceptor(); + lci.setParamName("lang"); + return lci; + } + + @Override + public void addInterceptors(InterceptorRegistry registry) { + registry.addInterceptor(localeChangeInterceptor()); + } +} \ No newline at end of file diff --git a/src/main/java/com/javarush/jira/locale/message/MessageRestController.java b/src/main/java/com/javarush/jira/locale/message/MessageRestController.java new file mode 100644 index 000000000..db7157033 --- /dev/null +++ b/src/main/java/com/javarush/jira/locale/message/MessageRestController.java @@ -0,0 +1,23 @@ +package com.javarush.jira.locale.message; + +import lombok.RequiredArgsConstructor; +import org.springframework.context.MessageSource; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +import java.util.Locale; + +@RestController +@RequestMapping("/api/v1/messages") +@RequiredArgsConstructor +public class MessageRestController { + + private final MessageSource messageSource; + + @GetMapping + public String getMessage(@RequestParam String key, @RequestParam String lang) { + return messageSource.getMessage(key, null, Locale.forLanguageTag(lang)); + } +} diff --git a/src/main/resources/application.yaml b/src/main/resources/application.yaml index c40950186..db08019bb 100644 --- a/src/main/resources/application.yaml +++ b/src/main/resources/application.yaml @@ -49,7 +49,6 @@ spring: mode: always - thymeleaf.check-template-location: false mvc.throw-exception-if-no-handler-found: true @@ -70,4 +69,5 @@ server: charset: UTF-8 # Charset of HTTP requests and responses. Added to the "Content-Type" header if not set explicitly enabled: true # Enable http encoding support force: true + springdoc.swagger-ui.path: /doc diff --git a/src/main/resources/messages.properties b/src/main/resources/messages.properties new file mode 100644 index 000000000..d05ead76b --- /dev/null +++ b/src/main/resources/messages.properties @@ -0,0 +1,9 @@ +hello=Hello +email-confirmation.info_end_registration=To complete your account setup and start using JiraRush, please confirm that you have entered your account name correctly email. +email-confirmation.confirm_mail=Confirm mail + +password-reset.infoPasswordRequest=We have received a request to set a new JiraRush account password +password-reset.setPassword=Set password + +index.homePage=JiraRush Home page +index.logout=Logout \ 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..5066c4c1f --- /dev/null +++ b/src/main/resources/messages_ru.properties @@ -0,0 +1,9 @@ +hello=\u041F\u0440\u0438\u0432\u0435\u0442 +email-confirmation.info_end_registration=\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 +email-confirmation.confirm_mail=\u041F\u043E\u0434\u0442\u0432\u0435\u0440\u0434\u0438\u0442\u044C \u043F\u043E\u0447\u0442\u0443 + +password-reset.infoPasswordRequest=\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 +password-reset.setPassword=\u0423\u0441\u0442\u0430\u043D\u043E\u0432\u0438\u0442\u044C \u043F\u0430\u0440\u043E\u043B\u044C. + +index.homePage=JiraRush \u0414\u043E\u043C\u0430\u0448\u043D\u044F\u044F \u0441\u0442\u0440\u0430\u043D\u0438\u0446\u0430 +index.logout=\u0412\u044B\u0439\u0442\u0438 \ No newline at end of file diff --git a/src/main/resources/messages_ua.properties b/src/main/resources/messages_ua.properties new file mode 100644 index 000000000..5c1b8147f --- /dev/null +++ b/src/main/resources/messages_ua.properties @@ -0,0 +1,9 @@ +hello=\u041F\u0440\u0438\u0432\u0456\u0442 +email-confirmation.info_end_registration=\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 \u043F\u0440\u0430\u0432\u0438\u043B\u044C\u043D\u043E \u0432\u043A\u0430\u0437\u0430\u043B\u0438 \u0432\u0430\u0448\u0443 \u0435\u043B\u0435\u043A\u0442\u0440\u043E\u043D\u043D\u0443 \u043F\u043E\u0448\u0442\u0443 +email-confirmation.confirm_mail=\u041F\u0456\u0434\u0442\u0432\u0435\u0440\u0434\u0438\u0442\u0438 \u043F\u043E\u0448\u0442\u0443 + +password-reset.infoPasswordRequest=\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\u044F JiraRush \u0434\u043B\u044F \u043E\u0431\u043B\u0456\u043A\u043E\u0432\u043E\u0433\u043E \u0437\u0430\u043F\u0438\u0441\u0443 +password-reset.setPassword=\u0412\u0441\u0442\u0430\u043D\u043E\u0432\u0438\u0442\u0438 \u043F\u0430\u0440\u043E\u043B\u044C. + +index.homePage=JiraRush \u0414\u043E\u043C\u0430\u0448\u043D\u044F \u0441\u0442\u043E\u0440\u0456\u043D\u043A\u0430 +index.logout=\u0412\u0438\u0439\u0442\u0438 \ No newline at end of file From 1781350604218befbd01105371d1c82fa10a6160 Mon Sep 17 00:00:00 2001 From: malyniak Date: Fri, 24 May 2024 17:46:23 +0300 Subject: [PATCH 8/9] delete connection with enemies sites --- README.md | 2 +- resources/mails/email-confirmation.html | 1 + resources/mails/password-reset.html | 1 + resources/view/login.html | 8 ----- .../handler/VkOAuth2UserDataHandler.java | 35 ------------------- .../handler/YandexOAuth2UserDataHandler.java | 21 ----------- src/main/resources/data4dev/data.sql | 3 +- 7 files changed, 4 insertions(+), 67 deletions(-) delete mode 100644 src/main/java/com/javarush/jira/login/internal/sociallogin/handler/VkOAuth2UserDataHandler.java delete mode 100644 src/main/java/com/javarush/jira/login/internal/sociallogin/handler/YandexOAuth2UserDataHandler.java diff --git a/README.md b/README.md index 719b268f5..fdfe8d9d1 100644 --- a/README.md +++ b/README.md @@ -27,4 +27,4 @@ - https://habr.com/ru/articles/259055/ Список выполненных задач: -... \ No newline at end of file +1-9, 11 \ No newline at end of file diff --git a/resources/mails/email-confirmation.html b/resources/mails/email-confirmation.html index e88ecf69a..5da4a3a2d 100644 --- a/resources/mails/email-confirmation.html +++ b/resources/mails/email-confirmation.html @@ -10,5 +10,6 @@ +
\ No newline at end of file diff --git a/resources/mails/password-reset.html b/resources/mails/password-reset.html index 16958fc6c..083702245 100644 --- a/resources/mails/password-reset.html +++ b/resources/mails/password-reset.html @@ -8,5 +8,6 @@

Set password +

\ No newline at end of file diff --git a/resources/view/login.html b/resources/view/login.html index 8765ca8ff..d49ce5691 100644 --- a/resources/view/login.html +++ b/resources/view/login.html @@ -48,14 +48,6 @@

Sign in

type="button"> - - - - - - diff --git a/src/main/java/com/javarush/jira/login/internal/sociallogin/handler/VkOAuth2UserDataHandler.java b/src/main/java/com/javarush/jira/login/internal/sociallogin/handler/VkOAuth2UserDataHandler.java deleted file mode 100644 index e8e05be05..000000000 --- a/src/main/java/com/javarush/jira/login/internal/sociallogin/handler/VkOAuth2UserDataHandler.java +++ /dev/null @@ -1,35 +0,0 @@ -package com.javarush.jira.login.internal.sociallogin.handler; - -import org.springframework.stereotype.Component; - -import java.util.List; -import java.util.Map; - -@Component("vk") -public class VkOAuth2UserDataHandler implements OAuth2UserDataHandler { - @Override - public String getFirstName(OAuth2UserData oAuth2UserData) { - return getAttribute(oAuth2UserData, "first_name"); - } - - @Override - public String getLastName(OAuth2UserData oAuth2UserData) { - return getAttribute(oAuth2UserData, "last_name"); - } - - @Override - public String getEmail(OAuth2UserData oAuth2UserData) { - return oAuth2UserData.getData("email"); - } - - private String getAttribute(OAuth2UserData oAuth2UserData, String name) { - List> attributesResponse = oAuth2UserData.getData("response"); - if (attributesResponse != null) { - Map attributes = attributesResponse.get(0); - if (attributes != null) { - return (String) attributes.get(name); - } - } - return null; - } -} diff --git a/src/main/java/com/javarush/jira/login/internal/sociallogin/handler/YandexOAuth2UserDataHandler.java b/src/main/java/com/javarush/jira/login/internal/sociallogin/handler/YandexOAuth2UserDataHandler.java deleted file mode 100644 index e8ea1ac1d..000000000 --- a/src/main/java/com/javarush/jira/login/internal/sociallogin/handler/YandexOAuth2UserDataHandler.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.javarush.jira.login.internal.sociallogin.handler; - -import org.springframework.stereotype.Component; - -@Component("yandex") -public class YandexOAuth2UserDataHandler implements OAuth2UserDataHandler { - @Override - public String getFirstName(OAuth2UserData oAuth2UserData) { - return oAuth2UserData.getData("first_name"); - } - - @Override - public String getLastName(OAuth2UserData oAuth2UserData) { - return oAuth2UserData.getData("last_name"); - } - - @Override - public String getEmail(OAuth2UserData oAuth2UserData) { - return oAuth2UserData.getData("default_email"); - } -} diff --git a/src/main/resources/data4dev/data.sql b/src/main/resources/data4dev/data.sql index a7d43cbad..28b494155 100644 --- a/src/main/resources/data4dev/data.sql +++ b/src/main/resources/data4dev/data.sql @@ -54,8 +54,7 @@ values (1, 'skype', 'userSkype'), (1, 'mobile', '+01234567890'), (1, 'website', 'user.com'), (2, 'github', 'adminGitHub'), - (2, 'tg', 'adminTg'), - (2, 'vk', 'adminVk'); + (2, 'tg', 'adminTg'); delete from ATTACHMENT; From af669c60d89af67fd18350719b21f7aa0cfd4203 Mon Sep 17 00:00:00 2001 From: malyniak Date: Sat, 1 Jun 2024 09:15:17 +0300 Subject: [PATCH 9/9] fix nginx bug --- config/nginx.conf | 21 ++++--- docker-compose.yml | 62 +++++++++++++------ .../jira/bugtracking/task/TaskRepository.java | 1 - src/main/resources/application.yaml | 3 +- src/main/resources/secrets.yaml | 25 +------- 5 files changed, 56 insertions(+), 56 deletions(-) diff --git a/config/nginx.conf b/config/nginx.conf index 82b9e234d..26e4a2b70 100644 --- a/config/nginx.conf +++ b/config/nginx.conf @@ -1,22 +1,22 @@ # https://losst.ru/ustanovka-nginx-ubuntu-16-04 # https://pai-bx.com/wiki/nginx/2332-useful-redirects-in-nginx/#1 # sudo iptables -A INPUT ! -s 127.0.0.1 -p tcp -m tcp --dport 8080 -j DROP +events { +} + +http { server { - listen 80; + listen 80; - # https://www.digitalocean.com/community/tutorials/how-to-optimize-nginx-configuration - gzip on; + gzip on; gzip_types text/css application/javascript application/json; gzip_min_length 2048; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - root /opt/jirarush/resources; - - if ($request_uri ~ ';') {return 404;} + root /opt/jirarush/resources; - # proxy_cookie_flags ~ secure samesite=none; + if ($request_uri ~ ';') { return 404; } - # static location /static/ { expires 30d; access_log off; @@ -28,13 +28,14 @@ server { location ~ (/$|/view/|/ui/|/oauth2/) { expires 0m; proxy_pass http://localhost:8080; - proxy_connect_timeout 30s; + proxy_connect_timeout 30s; } location ~ (/api/|/doc|/swagger-ui/|/v3/api-docs/) { proxy_pass http://localhost:8080; - proxy_connect_timeout 150s; + proxy_connect_timeout 150s; } location / { try_files /view/404.html = 404; } +} } \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml index 49be0e733..8e1832b24 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,40 +1,64 @@ version: '3' services: - postgres-db: - image: postgres:latest - environment: - POSTGRES_DB: jira - POSTGRES_USER: jira - POSTGRES_PASSWORD: JiraRush - ports: + postgres-db : + image : postgres + environment : + POSTGRES_USER : jira + POSTGRES_PASSWORD : JiraRush + ports : - "5432:5432" + volumes : + - ./pgdata:/var/lib/postgresql/data + healthcheck : + test : [ "CMD-SHELL", "pg_isready -U postgres" ] networks: - mynetwork - postgres-db-test: - image: postgres:latest - environment: - POSTGRES_DB: jira_test - POSTGRES_USER: jira - POSTGRES_PASSWORD: JiraRush - ports: + postgres-db-test : + image : postgres + environment : + POSTGRES_USER : jira + POSTGRES_PASSWORD : JiraRush + ports : - "5433:5432" + volumes : + - ./pgdata-test:/var/lib/postgresql/data + healthcheck : + test : [ "CMD-SHELL", "pg_isready -U postgres" ] networks: - mynetwork myapp: - image: jira-1.0 + image: sha256:1893d8fe5a20 ports: - "8080:8080" + extra_hosts : + - "host.docker.internal:host-gateway" + build : + context : . + dockerfile : Dockerfile environment: - SPRING_DATASOURCE_URL: jdbc:postgresql://localhost:5432/jira + SPRING_DATASOURCE_URL: jdbc:postgresql://postgres-db:5432/jira SPRING_DATASOURCE_USERNAME: jira - depends_on: - - postgres-db + SPRING_DATASOURCE_PASSWORD: JiraRush + depends_on : + postgres-db : + condition : service_healthy + postgres-db-test : + condition : service_healthy networks: - mynetwork - + nginx : + image : nginx + volumes : + - ./config/nginx.conf:/etc/nginx/nginx.conf + ports : + - "80:80" + depends_on : + - myapp + networks : + - mynetwork networks: mynetwork: driver: bridge diff --git a/src/main/java/com/javarush/jira/bugtracking/task/TaskRepository.java b/src/main/java/com/javarush/jira/bugtracking/task/TaskRepository.java index d7ffdcb7f..06199e5d7 100644 --- a/src/main/java/com/javarush/jira/bugtracking/task/TaskRepository.java +++ b/src/main/java/com/javarush/jira/bugtracking/task/TaskRepository.java @@ -40,7 +40,6 @@ WHERE id IN (SELECT child FROM task_with_subtasks) """, nativeQuery = true) void setTaskAndSubTasksSprint(long taskId, Long sprintId); - // @Query("SELECT a.updated FROM Task t JOIN t.activities a WHERE a.statusCode = :statusCode") LocalDateTime findByStatusCode(String statusCode); } \ No newline at end of file diff --git a/src/main/resources/application.yaml b/src/main/resources/application.yaml index db08019bb..a0c4828e1 100644 --- a/src/main/resources/application.yaml +++ b/src/main/resources/application.yaml @@ -49,8 +49,7 @@ spring: mode: always - thymeleaf.check-template-location: false - + thymeleaf.check-template-location: true mvc.throw-exception-if-no-handler-found: true web.resources.add-mappings: false diff --git a/src/main/resources/secrets.yaml b/src/main/resources/secrets.yaml index da91f53a5..78696c49d 100644 --- a/src/main/resources/secrets.yaml +++ b/src/main/resources/secrets.yaml @@ -16,20 +16,6 @@ spring: 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 gitlab : client-id : b8520a3266089063c0d8261cce36971defa513f5ffd9f9b7a3d16728fc83a494 client-secret : e72c65320cf9d6495984a37b0f9cc03ec46be0bb6f071feaebbfe75168117004 @@ -38,16 +24,7 @@ spring: 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 + gitlab : authorization-uri : https://gitlab.com/oauth/authorize token-uri : https://gitlab.com/oauth/token