Skip to content

Commit

Permalink
EPMRPP-89699 implement OrganizationInfo endpoint (#1942)
Browse files Browse the repository at this point in the history
  • Loading branch information
grabsefx authored Mar 20, 2024
1 parent e828280 commit 3af9f27
Show file tree
Hide file tree
Showing 13 changed files with 199 additions and 18 deletions.
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ dependencies {
implementation 'com.epam.reportportal:plugin-api'
} else {
implementation 'com.github.reportportal:commons-events:e337f8b7be'
implementation 'com.github.reportportal:commons-dao:f6c9669'
implementation 'com.github.reportportal:commons-dao:c274f1d'
implementation 'com.github.reportportal:commons-rules:1f6bfed'
implementation 'com.github.reportportal:commons-model:38a52fb'
implementation 'com.github.reportportal:commons-reporting:5c74bb2'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@

import com.epam.ta.reportportal.commons.ReportPortalUser;
import com.epam.ta.reportportal.commons.querygen.Queryable;
import com.epam.ta.reportportal.model.OrganizationResource;
import com.epam.ta.reportportal.model.organization.OrganizationInfoResource;
import com.epam.ta.reportportal.model.organization.OrganizationResource;
import org.springframework.data.domain.Pageable;

/**
Expand All @@ -44,4 +45,15 @@ public interface GetOrganizationHandler {
* projects
*/
Iterable<OrganizationResource> getOrganizations(Queryable filter, Pageable pageable);

/**
* Get Organizations aggregated info by query parameters
*
* @param filter Queryable filter to apply on organizations
* @param pageable Pagination information for the results
* @return An {@link Iterable} of {@link OrganizationInfoResource} containing information about
* all projects
*/
Iterable<OrganizationInfoResource> getOrganizationsInfo(Queryable filter, Pageable pageable);

}
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@
import com.epam.ta.reportportal.dao.organization.OrganizationRepositoryCustom;
import com.epam.ta.reportportal.entity.organization.Organization;
import com.epam.ta.reportportal.exception.ReportPortalException;
import com.epam.ta.reportportal.model.OrganizationResource;
import com.epam.ta.reportportal.model.organization.OrganizationInfoResource;
import com.epam.ta.reportportal.model.organization.OrganizationResource;
import com.epam.ta.reportportal.ws.converter.PagedResourcesAssembler;
import com.epam.ta.reportportal.ws.converter.converters.OrganizationConverter;
import com.epam.ta.reportportal.ws.reporting.ErrorType;
Expand Down Expand Up @@ -58,4 +59,12 @@ public Iterable<OrganizationResource> getOrganizations(Queryable filter, Pageabl
.apply(organizationRepositoryCustom.findByFilter(filter, pageable));
}

@Override
public Iterable<OrganizationInfoResource> getOrganizationsInfo(Queryable filter,
Pageable pageable) {
return PagedResourcesAssembler
.pageConverter(OrganizationConverter.TO_ORGANIZATION_INFO_RESOURCE)
.apply(organizationRepositoryCustom.findOrganizationInfoByFilter(filter, pageable));
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
package com.epam.ta.reportportal.model.organization;

/*
* Copyright 2024 EPAM Systems
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/


import com.epam.ta.reportportal.entity.enums.OrganizationType;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import java.time.LocalDateTime;
import java.util.Date;
import javax.validation.constraints.NotNull;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;

/**
* Basic JSON representation of Organization.
*
* @author Andrei Piankouski
*/
@JsonInclude(JsonInclude.Include.NON_NULL)
@Getter
@Setter
@ToString
public class OrganizationInfoResource {

@NotNull
@JsonProperty(value = "id", required = true)
private Long id;

@NotNull
@JsonProperty(value = "name", required = true)
private String name;

@NotNull
@JsonProperty(value = "slug", required = true)
private String slug;

@NotNull
@JsonProperty(value = "type", required = true)
private OrganizationType type;

@NotNull
@JsonProperty(value = "creationDate", required = true)
private Date creationDate;

@JsonProperty(value = "usersQuantity", required = true)
private int usersQuantity;

@JsonProperty(value = "projectsQuantity", required = true)
private int projectsQuantity;

@JsonProperty(value = "launchesQuantity", required = true)
private int launchesQuantity;

@JsonProperty(value = "lastRun", required = true)
private LocalDateTime lastRun;

}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.epam.ta.reportportal.model;
package com.epam.ta.reportportal.model.organization;

/*
* Copyright 2024 EPAM Systems
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@
* @author Konstantin Antipin
*/
@RestController
@RequestMapping("/v2/{projectName}/launch")
@RequestMapping("/v2/{projectKey}/launch")
@Tag(name = "launch-async-controller", description = "Launch Async Controller")
public class LaunchAsyncController {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,20 @@

package com.epam.ta.reportportal.ws.controller;

import static com.epam.ta.reportportal.core.widget.content.constant.ContentLoaderConstants.USER;

import com.epam.ta.reportportal.commons.ReportPortalUser;
import com.epam.ta.reportportal.commons.querygen.CompositeFilter;
import com.epam.ta.reportportal.commons.querygen.Condition;
import com.epam.ta.reportportal.commons.querygen.Filter;
import com.epam.ta.reportportal.commons.querygen.FilterCondition;
import com.epam.ta.reportportal.commons.querygen.Queryable;
import com.epam.ta.reportportal.core.organization.GetOrganizationHandler;
import com.epam.ta.reportportal.entity.organization.Organization;
import com.epam.ta.reportportal.model.OrganizationResource;
import com.epam.ta.reportportal.entity.organization.OrganizationInfo;
import com.epam.ta.reportportal.entity.user.UserRole;
import com.epam.ta.reportportal.model.organization.OrganizationInfoResource;
import com.epam.ta.reportportal.model.organization.OrganizationResource;
import com.epam.ta.reportportal.ws.resolver.FilterFor;
import com.epam.ta.reportportal.ws.resolver.SortFor;
import io.swagger.v3.oas.annotations.Operation;
Expand All @@ -41,7 +48,7 @@
* @author Andrei Piankouski
*/
@RestController
@RequestMapping("/v1/organization")
@RequestMapping("/v1")
@Tag(name = "organizations-controller", description = "Organizations Controller")
public class OrganizationController {

Expand All @@ -53,24 +60,59 @@ public OrganizationController(GetOrganizationHandler getOrganizationHandler) {
}

@Transactional
@GetMapping("/{organizationId}")
@GetMapping("/organizations/{organizationId}")
@Operation(summary = "Get information about organization")
public OrganizationResource getOrganization(@PathVariable Long organizationId,
@AuthenticationPrincipal ReportPortalUser user) {
return getOrganizationHandler.getResource(organizationId, user);
}

@Transactional
@GetMapping("/list")
@Operation(summary = "Get list of all organizations")
@GetMapping("/organizations")
@Operation(summary = "Get list of organizations associated with the user")
public Iterable<OrganizationResource> getAllOrganizations(
@AuthenticationPrincipal ReportPortalUser user,
@FilterFor(Organization.class) Filter filter,
@FilterFor(Organization.class) Queryable predefinedFilter,
@SortFor(Organization.class) Pageable pageable
) {
@SortFor(Organization.class) Pageable pageable) {

modifyFilterWithUserCriteria(filter, user);

return getOrganizationHandler.getOrganizations(
new CompositeFilter(Operator.AND, filter, predefinedFilter),
pageable);
}


@Transactional
@GetMapping("/organizations-info")
@Operation(summary = "Get list of organizations aggregated info associated with the user")
public Iterable<OrganizationInfoResource> getOrganizationsInfo(
@AuthenticationPrincipal ReportPortalUser user,
@FilterFor(OrganizationInfo.class) Filter filter,
@FilterFor(OrganizationInfo.class) Queryable predefinedFilter,
@SortFor(OrganizationInfo.class) Pageable pageable) {

modifyFilterWithUserCriteria(filter, user);

return getOrganizationHandler.getOrganizationsInfo(
new CompositeFilter(Operator.AND, filter, predefinedFilter),
pageable);
}

/**
* By security reasons "filter.*.user" should always be replaced with filter by current user.
* Only Admin users can retrieve all organizations regardless organization membership
*/
private void modifyFilterWithUserCriteria(Filter filter, ReportPortalUser user) {
// always remove user filter
filter.getFilterConditions()
.removeIf(cc -> cc.getAllConditions().stream()
.anyMatch(fc -> fc.getSearchCriteria().equalsIgnoreCase(USER)));

if (UserRole.ADMINISTRATOR != user.getUserRole()) {
filter.withCondition(
new FilterCondition(Condition.EQUALS, false, user.getUsername(), USER));
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@
* @author Konstantin Antipin
*/
@RestController
@RequestMapping("/v2/{projectName}/item")
@RequestMapping("/v2/{projectKey}/item")
@PreAuthorize(ASSIGNED_TO_PROJECT)
@Tag(name = "test-item-async-controller", description = "Test Item Async Controller")
public class TestItemAsyncController {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,9 @@
import static com.epam.ta.reportportal.commons.EntityUtils.TO_DATE;

import com.epam.ta.reportportal.entity.organization.Organization;
import com.epam.ta.reportportal.model.OrganizationResource;
import com.epam.ta.reportportal.entity.organization.OrganizationInfo;
import com.epam.ta.reportportal.model.organization.OrganizationInfoResource;
import com.epam.ta.reportportal.model.organization.OrganizationResource;
import java.util.function.Function;

/**
Expand All @@ -43,4 +45,19 @@ private OrganizationConverter() {

return orgResource;
};

public static final Function<OrganizationInfo, OrganizationInfoResource> TO_ORGANIZATION_INFO_RESOURCE = org -> {
OrganizationInfoResource orgInfoResource = new OrganizationInfoResource();
orgInfoResource.setId(org.getId());
orgInfoResource.setName(org.getName());
orgInfoResource.setSlug(org.getSlug());
orgInfoResource.setType(org.getOrganizationType());
orgInfoResource.setCreationDate(TO_DATE.apply(org.getCreationDate()));
orgInfoResource.setLastRun(org.getLastRun());
orgInfoResource.setLaunchesQuantity(org.getLaunchesQuantity());
orgInfoResource.setProjectsQuantity(org.getProjectsQuantity());
orgInfoResource.setUsersQuantity(org.getUsersQuantity());

return orgInfoResource;
};
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
package com.epam.ta.reportportal.ws.converter.converters;

import com.epam.ta.reportportal.commons.MoreCollectors;
import com.epam.ta.reportportal.entity.organization.OrganizationUser;
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.UserType;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,36 @@ class OrganizationControllerTest extends BaseMvcTest {

@Test
void getOrganization() throws Exception {
mockMvc.perform(get("/v1/organization/1").with(token(oAuthHelper.getSuperadminToken())))
mockMvc.perform(get("/v1/organizations/1")
.with(token(oAuthHelper.getSuperadminToken())))
.andExpect(status().isOk());
}

@Test
void getAllOrganizations() throws Exception {
mockMvc.perform(get("/v1/organization/list").with(token(oAuthHelper.getSuperadminToken())))
mockMvc.perform(get("/v1/organizations")
.with(token(oAuthHelper.getSuperadminToken())))
.andExpect(status().isOk());
}

@Test
void getAllOrganizationsInfo() throws Exception {
mockMvc.perform(get("/v1/organizations-info")
.with(token(oAuthHelper.getSuperadminToken())))
.andExpect(status().isOk());
}

@Test
void getAllOrganizationsInfoFilterByDifferentUser() throws Exception {
mockMvc.perform(get("/v1/organizations-info?filter.eq.user=default")
.with(token(oAuthHelper.getSuperadminToken())))
.andExpect(status().isOk());
}

@Test
void getAllOrganizationsInfoFilterByAdminUser() throws Exception {
mockMvc.perform(get("/v1/organizations-info?filter.eq.user=superadmin")
.with(token(oAuthHelper.getDefaultToken())))
.andExpect(status().isOk());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@

import com.epam.ta.reportportal.entity.enums.OrganizationType;
import com.epam.ta.reportportal.entity.organization.Organization;
import com.epam.ta.reportportal.model.OrganizationResource;
import com.epam.ta.reportportal.model.organization.OrganizationResource;
import java.time.LocalDateTime;
import org.junit.jupiter.api.Test;

Expand Down
5 changes: 5 additions & 0 deletions src/test/resources/db/project/project-fill.sql
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,11 @@ values (3, 3, 'MEMBER');
insert into project_user(user_id, project_id, project_role)
values (1, 3, 'PROJECT_MANAGER');

insert into organization_user (user_id, organization_id, organization_role)
values (1, 101, (select 'MANAGER'::public."organization_role_enum"));
insert into organization_user (user_id, organization_id, organization_role)
values (3, 101, (select 'MEMBER'::public."organization_role_enum"));

insert into owned_entity(id, owner, project_id)
values (1, 'superadmin', 3);
insert into filter(id, name, target, description)
Expand Down

0 comments on commit 3af9f27

Please sign in to comment.