From b987e5fe3aec5b4c8c3994348bfb8419b9727e24 Mon Sep 17 00:00:00 2001 From: Siarhei Hrabko <45555481+grabsefx@users.noreply.github.com> Date: Wed, 19 Jun 2024 13:00:02 +0300 Subject: [PATCH] EPMRPP-91394 implement dao for project team endpoint (#1014) --- .../commons/querygen/FilterTarget.java | 11 ++++---- .../dao/UserRepositoryCustom.java | 3 +++ .../dao/UserRepositoryCustomImpl.java | 25 +++++++++++++++-- .../reportportal/dao/util/RecordMappers.java | 21 +++++++++++++++ .../reportportal/dao/util/ResultFetchers.java | 27 ++++++++++++++++--- .../reportportal/dao/UserRepositoryTest.java | 24 +++++++++++++++++ .../migration/V001003__test_project_init.sql | 3 +++ 7 files changed, 103 insertions(+), 11 deletions(-) diff --git a/src/main/java/com/epam/ta/reportportal/commons/querygen/FilterTarget.java b/src/main/java/com/epam/ta/reportportal/commons/querygen/FilterTarget.java index e4045bd67..f4e3189f5 100644 --- a/src/main/java/com/epam/ta/reportportal/commons/querygen/FilterTarget.java +++ b/src/main/java/com/epam/ta/reportportal/commons/querygen/FilterTarget.java @@ -383,10 +383,8 @@ protected Field idField() { new CriteriaHolderBuilder().newBuilder(CRITERIA_PROJECT, PROJECT.NAME, List.class) .withAggregateCriteria(DSL.arrayAgg(PROJECT.NAME).toString()) .get(), - new CriteriaHolderBuilder().newBuilder(CRITERIA_PROJECT, PROJECT.KEY, List.class) - .withAggregateCriteria(DSL.arrayAgg(PROJECT.KEY).toString()) - .get(), - new CriteriaHolderBuilder().newBuilder(CRITERIA_PROJECT, PROJECT.ORGANIZATION_ID, List.class) + new CriteriaHolderBuilder().newBuilder(CRITERIA_PROJECT_KEY, PROJECT.KEY, String.class).get(), + new CriteriaHolderBuilder().newBuilder(CRITERIA_PROJECT_ORGANIZATION_ID, PROJECT.ORGANIZATION_ID, List.class) .withAggregateCriteria(DSL.arrayAgg(PROJECT.ORGANIZATION_ID).toString()) .get(), new CriteriaHolderBuilder().newBuilder(CRITERIA_LAST_LOGIN, @@ -422,7 +420,8 @@ protected Collection selectFields() { PROJECT_USER.USER_ID, ORGANIZATION.ID, ORGANIZATION.SLUG, - ORGANIZATION.NAME + ORGANIZATION.NAME, + ORGANIZATION_USER.ORGANIZATION_ROLE ); } @@ -436,6 +435,8 @@ protected void joinTables(QuerySupplier query) { query.addJoin(PROJECT_USER, JoinType.LEFT_OUTER_JOIN, USERS.ID.eq(PROJECT_USER.USER_ID)); query.addJoin(PROJECT, JoinType.LEFT_OUTER_JOIN, PROJECT_USER.PROJECT_ID.eq(PROJECT.ID)); query.addJoin(ORGANIZATION, JoinType.LEFT_OUTER_JOIN, ORGANIZATION.ID.eq(PROJECT.ORGANIZATION_ID)); + query.addJoin(ORGANIZATION_USER, JoinType.LEFT_OUTER_JOIN, + ORGANIZATION_USER.ORGANIZATION_ID.eq(PROJECT.ORGANIZATION_ID).and(USERS.ID.eq(ORGANIZATION_USER.USER_ID))); } @Override diff --git a/src/main/java/com/epam/ta/reportportal/dao/UserRepositoryCustom.java b/src/main/java/com/epam/ta/reportportal/dao/UserRepositoryCustom.java index 08b1d5924..0affe7739 100644 --- a/src/main/java/com/epam/ta/reportportal/dao/UserRepositoryCustom.java +++ b/src/main/java/com/epam/ta/reportportal/dao/UserRepositoryCustom.java @@ -44,6 +44,9 @@ public interface UserRepositoryCustom extends FilterableRepository { */ Page findByFilterExcluding(Queryable filter, Pageable pageable, String... exclude); + Page findProjectUsersByFilterExcluding(String projectKey, Queryable filter, + Pageable pageable, String... exclude); + Map findUsernamesWithProjectRolesByProjectId(Long projectId); /** diff --git a/src/main/java/com/epam/ta/reportportal/dao/UserRepositoryCustomImpl.java b/src/main/java/com/epam/ta/reportportal/dao/UserRepositoryCustomImpl.java index 2613e4e99..fa48559d7 100644 --- a/src/main/java/com/epam/ta/reportportal/dao/UserRepositoryCustomImpl.java +++ b/src/main/java/com/epam/ta/reportportal/dao/UserRepositoryCustomImpl.java @@ -86,8 +86,29 @@ public Optional findRawById(Long id) { public Page findByFilterExcluding(Queryable filter, Pageable pageable, String... exclude) { return PageableExecutionUtils.getPage( USER_FETCHER.apply(dsl.fetch( - QueryBuilder.newBuilder(filter).with(pageable).wrapExcludingFields(exclude) - .withWrapperSort(pageable.getSort()).build())), pageable, + QueryBuilder.newBuilder(filter) + .with(pageable) + .wrapExcludingFields(exclude) + .withWrapperSort(pageable.getSort()) + .build())), + pageable, + () -> dsl.fetchCount(QueryBuilder.newBuilder(filter).build()) + ); + } + + + @Override + public Page findProjectUsersByFilterExcluding(String projectKey, Queryable filter, + Pageable pageable, String... exclude) { + return PageableExecutionUtils.getPage( + USER_FETCHER.apply(dsl.fetch( + QueryBuilder.newBuilder(filter) + .with(pageable) + .wrapExcludingFields(exclude) + .addCondition(PROJECT.KEY.eq(projectKey)) + .withWrapperSort(pageable.getSort()) + .build())), + pageable, () -> dsl.fetchCount(QueryBuilder.newBuilder(filter).build()) ); } diff --git a/src/main/java/com/epam/ta/reportportal/dao/util/RecordMappers.java b/src/main/java/com/epam/ta/reportportal/dao/util/RecordMappers.java index b3311c61b..19823095c 100644 --- a/src/main/java/com/epam/ta/reportportal/dao/util/RecordMappers.java +++ b/src/main/java/com/epam/ta/reportportal/dao/util/RecordMappers.java @@ -71,6 +71,7 @@ import com.epam.ta.reportportal.entity.dashboard.DashboardWidgetId; import com.epam.ta.reportportal.entity.enums.IntegrationAuthFlowEnum; import com.epam.ta.reportportal.entity.enums.IntegrationGroupEnum; +import com.epam.ta.reportportal.entity.enums.OrganizationType; import com.epam.ta.reportportal.entity.enums.ProjectType; import com.epam.ta.reportportal.entity.enums.StatusEnum; import com.epam.ta.reportportal.entity.enums.TestItemTypeEnum; @@ -95,6 +96,8 @@ import com.epam.ta.reportportal.entity.project.ProjectRole; import com.epam.ta.reportportal.entity.statistics.Statistics; import com.epam.ta.reportportal.entity.statistics.StatisticsField; +import com.epam.ta.reportportal.entity.user.OrganizationUser; +import com.epam.ta.reportportal.entity.user.OrganizationUserId; import com.epam.ta.reportportal.entity.user.ProjectUser; import com.epam.ta.reportportal.entity.user.User; import com.epam.ta.reportportal.entity.user.UserRole; @@ -440,6 +443,24 @@ public class RecordMappers { return projectUser; }; + public static final RecordMapper ORGANIZATION_USER_MAPPER = r -> { + OrganizationUser orgUser = new OrganizationUser(); + + OrganizationUserId organizationUserId = new OrganizationUserId(); + organizationUserId.setOrganizationId(r.get(ORGANIZATION.ID)); + organizationUserId.setUserId(r.get(USERS.ID)); + + Organization organization = new Organization(); + organization.setId(r.get(ORGANIZATION.ID)); + organization.setSlug(r.get(ORGANIZATION.SLUG)); + organization.setName(r.get(ORGANIZATION.NAME)); + + orgUser.setId(organizationUserId); + orgUser.setOrganizationRole(r.into(ORGANIZATION_USER.ORGANIZATION_ROLE).into(OrganizationRole.class)); + orgUser.setOrganization(organization); + return orgUser; + }; + public static final RecordMapper ASSIGNMENT_DETAILS_MAPPER = r -> { MembershipDetails md = new MembershipDetails(); diff --git a/src/main/java/com/epam/ta/reportportal/dao/util/ResultFetchers.java b/src/main/java/com/epam/ta/reportportal/dao/util/ResultFetchers.java index bd1c92031..659b694d0 100644 --- a/src/main/java/com/epam/ta/reportportal/dao/util/ResultFetchers.java +++ b/src/main/java/com/epam/ta/reportportal/dao/util/ResultFetchers.java @@ -25,6 +25,7 @@ import static com.epam.ta.reportportal.dao.util.RecordMappers.DASHBOARD_WIDGET_MAPPER; import static com.epam.ta.reportportal.dao.util.RecordMappers.ITEM_ATTRIBUTE_MAPPER; import static com.epam.ta.reportportal.dao.util.RecordMappers.LOG_MAPPER; +import static com.epam.ta.reportportal.dao.util.RecordMappers.ORGANIZATION_USER_MAPPER; import static com.epam.ta.reportportal.dao.util.RecordMappers.PATTERN_TEMPLATE_NAME_RECORD_MAPPER; import static com.epam.ta.reportportal.dao.util.RecordMappers.PROJECT_USER_MAPPER; import static com.epam.ta.reportportal.dao.util.RecordMappers.TICKET_MAPPER; @@ -65,6 +66,7 @@ import com.epam.ta.reportportal.entity.pattern.PatternTemplateTestItem; import com.epam.ta.reportportal.entity.project.Project; import com.epam.ta.reportportal.entity.project.ProjectAttribute; +import com.epam.ta.reportportal.entity.user.OrganizationUser; import com.epam.ta.reportportal.entity.user.ProjectUser; import com.epam.ta.reportportal.entity.user.User; import com.epam.ta.reportportal.entity.user.UserRole; @@ -212,7 +214,7 @@ private ResultFetchers() { Long id = row.get(TEST_ITEM.ITEM_ID); TestItem testItem = testItems.computeIfAbsent(id, key -> RecordMappers.TEST_ITEM_RECORD_MAPPER.map(row)); - ofNullable(row.get(PARAMETER.ITEM_ID)).ifPresent( + ofNullable(row.field(PARAMETER.ITEM_ID)).ifPresent( it -> testItem.getParameters().add(row.into(Parameter.class))); testItems.put(id, testItem); }); @@ -281,8 +283,25 @@ private ResultFetchers() { } else { user = users.get(id); } - if (ofNullable(row.get(PROJECT_USER.PROJECT_ROLE)).isPresent()) { - user.getProjects().add(PROJECT_USER_MAPPER.map(row)); + if (ofNullable(row.field(PROJECT_USER.PROJECT_ROLE)).isPresent()) { + boolean isProjectAdded = user.getProjects().stream() + .map(ProjectUser::getProject) + .map(Project::getKey) + .anyMatch(prjKey -> prjKey.equals(row.get(PROJECT.KEY))); + if (!isProjectAdded) { + user.getProjects().add(PROJECT_USER_MAPPER.map(row)); + } + } + + if (ofNullable(row.field(ORGANIZATION_USER.ORGANIZATION_ROLE)).isPresent()) { + boolean isOrgAdded = user.getOrganizationUsers().stream() + .map(OrganizationUser::getOrganization) + .map(Organization::getId) + .anyMatch(orgId -> orgId.equals(row.get(ORGANIZATION.ID))); + if (!isOrgAdded) { + user.getOrganizationUsers() + .add(ORGANIZATION_USER_MAPPER.map(row)); + } } users.put(id, user); @@ -397,7 +416,7 @@ private ResultFetchers() { rows.forEach( row -> - ofNullable(row.get(ORGANIZATION_USER.ORGANIZATION_ID, Long.class)) + ofNullable(row.field(ORGANIZATION_USER.ORGANIZATION_ID)) .ifPresent(orgId -> { String orgName = row.get(ORGANIZATION.NAME, String.class); diff --git a/src/test/java/com/epam/ta/reportportal/dao/UserRepositoryTest.java b/src/test/java/com/epam/ta/reportportal/dao/UserRepositoryTest.java index dcd14e748..726c6b645 100644 --- a/src/test/java/com/epam/ta/reportportal/dao/UserRepositoryTest.java +++ b/src/test/java/com/epam/ta/reportportal/dao/UserRepositoryTest.java @@ -19,6 +19,7 @@ import static com.epam.ta.reportportal.commons.querygen.constant.GeneralCriteriaConstant.CRITERIA_ID; import static com.epam.ta.reportportal.commons.querygen.constant.GeneralCriteriaConstant.CRITERIA_PROJECT; import static com.epam.ta.reportportal.commons.querygen.constant.GeneralCriteriaConstant.CRITERIA_PROJECT_ID; +import static com.epam.ta.reportportal.commons.querygen.constant.ProjectCriteriaConstant.CRITERIA_PROJECT_KEY; import static com.epam.ta.reportportal.commons.querygen.constant.UserCriteriaConstant.CRITERIA_EMAIL; import static com.epam.ta.reportportal.commons.querygen.constant.UserCriteriaConstant.CRITERIA_FULL_NAME; import static com.epam.ta.reportportal.commons.querygen.constant.UserCriteriaConstant.CRITERIA_LAST_LOGIN; @@ -51,6 +52,7 @@ import java.util.Map; import java.util.Optional; import java.util.Set; +import org.assertj.core.util.Lists; import org.assertj.core.util.Sets; import org.hamcrest.Matchers; import org.jooq.Operator; @@ -416,6 +418,28 @@ void findAllMembersByProject() { assertEquals(1, emails.size()); } + + @Test + void findProjectUsers() { + PageRequest pageRequest = PageRequest.of(0, 300); + Filter filter = new Filter(User.class, Lists.newArrayList()); + filter.withCondition( + new FilterCondition(Condition.EQUALS, false, "millennium_falcon", CRITERIA_PROJECT_KEY)); + Page result = userRepository.findProjectUsersByFilterExcluding("millennium_falcon", + filter, pageRequest, "email"); + assertEquals(3, result.getTotalElements()); + + result.getContent().forEach(user -> assertFalse(user.getOrganizationUsers().isEmpty())); + + result.getContent().stream().flatMap(user -> user.getOrganizationUsers().stream()) + .forEach(orgUser -> { + assertNotNull(orgUser.getOrganizationRole()); + }); + + result.getContent().forEach(user -> assertNull(user.getEmail())); + } + + private Filter buildDefaultUserFilter() { return Filter.builder() .withTarget(User.class) diff --git a/src/test/resources/db/migration/V001003__test_project_init.sql b/src/test/resources/db/migration/V001003__test_project_init.sql index 589a86d61..ba458787d 100644 --- a/src/test/resources/db/migration/V001003__test_project_init.sql +++ b/src/test/resources/db/migration/V001003__test_project_init.sql @@ -50,6 +50,9 @@ BEGIN '{"metadata": {"last_login": "1551187023768"}}'); fake_chubaka := (SELECT currval(pg_get_serial_sequence('users', 'id'))); + INSERT INTO organization_user (user_id, organization_id, organization_role) + VALUES (fake_chubaka, org_id, (SELECT 'MEMBER'::public."organization_role_enum")); + INSERT INTO project_user (user_id, project_id, project_role) VALUES (fake_chubaka, falcon, 'VIEWER');