diff --git a/spec/openapi.yaml b/spec/openapi.yaml index 8e9829bd14614c21cb940e1737be6771d60fecfd..0196445fca922dbd9234d293f2a268c26e340e0d 100644 --- a/spec/openapi.yaml +++ b/spec/openapi.yaml @@ -519,7 +519,7 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/OrganizationContacts' + $ref: '#/components/schemas/People' 401: description: Unauthorized 403: @@ -553,7 +553,7 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/OrganizationContact' + $ref: '#/components/schemas/People' 401: description: Unauthorized 403: @@ -648,7 +648,7 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/OrganizationContact' + $ref: '#/components/schemas/Person' 401: description: Unauthorized 403: diff --git a/src/main/java/org/eclipsefoundation/api/FoundationDBParameterNames.java b/src/main/java/org/eclipsefoundation/api/FoundationDBParameterNames.java index 9f1145161af9a3aa188f6904eb1851e1349b4ef3..7ff3033a4d1fcf766a4f5ffc042c43fafb5c7646 100644 --- a/src/main/java/org/eclipsefoundation/api/FoundationDBParameterNames.java +++ b/src/main/java/org/eclipsefoundation/api/FoundationDBParameterNames.java @@ -14,6 +14,7 @@ public class FoundationDBParameterNames implements UrlParameterNamespace { public static final UrlParameter USER_NAME = new UrlParameter("username"); public static final UrlParameter RELATION = new UrlParameter("relation"); + public static final UrlParameter PROJECT_RELATION = new UrlParameter("project_relation"); private static final List params = Collections.unmodifiableList(Arrays.asList(USER_NAME, RELATION)); diff --git a/src/main/java/org/eclipsefoundation/api/PeopleAPI.java b/src/main/java/org/eclipsefoundation/api/PeopleAPI.java index 423326613a1011c87ca56c641157137296a45903..77b1bb3c1b4002224108650ddbf61a4deabb02d3 100644 --- a/src/main/java/org/eclipsefoundation/api/PeopleAPI.java +++ b/src/main/java/org/eclipsefoundation/api/PeopleAPI.java @@ -2,7 +2,9 @@ package org.eclipsefoundation.api; import java.util.List; +import javax.annotation.Nullable; import javax.annotation.security.RolesAllowed; +import javax.ws.rs.BeanParam; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.Produces; @@ -12,6 +14,10 @@ import javax.ws.rs.core.Response; import org.eclipse.microprofile.rest.client.inject.RegisterRestClient; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder; +import com.google.auto.value.AutoValue; + import io.quarkus.oidc.client.filter.OidcClientFilter; @OidcClientFilter @@ -22,7 +28,61 @@ public interface PeopleAPI { @GET @RolesAllowed("fdb_read_people") - Response getPeople(@QueryParam("page") Integer page, @QueryParam("organizationID") String organizationID, - @QueryParam("project_relation") String relation, @QueryParam("ids") List ids); + Response getPeople(@QueryParam("page") Integer page, @BeanParam PeopleRequestParams params); + + @AutoValue + @JsonDeserialize(builder = AutoValue_PeopleAPI_PeopleRequestParams.Builder.class) + public abstract static class PeopleRequestParams { + @Nullable + @QueryParam("email") + public abstract String getEmail(); + + @Nullable + @QueryParam("id") + public abstract String getUsername(); + + @Nullable + @QueryParam("first_name") + public abstract String getFirstName(); + + @Nullable + @QueryParam("last_name") + public abstract String getLastName(); + + @Nullable + @QueryParam("organizationID") + public abstract String getOrganizationID(); + + @Nullable + @QueryParam("project_relation") + public abstract String getRelation(); + + @Nullable + @QueryParam("ids") + public abstract List getIds(); + + public static Builder builder() { + return new AutoValue_PeopleAPI_PeopleRequestParams.Builder(); + } + + @AutoValue.Builder + @JsonPOJOBuilder(withPrefix = "set") + public abstract static class Builder { + public abstract Builder setEmail(@Nullable String email); + + public abstract Builder setUsername(@Nullable String username); + + public abstract Builder setFirstName(@Nullable String firstName); + + public abstract Builder setLastName(@Nullable String lastName); + + public abstract Builder setOrganizationID(@Nullable String organizationID); + + public abstract Builder setRelation(@Nullable String relation); + + public abstract Builder setIds(@Nullable List ids); + public abstract PeopleRequestParams build(); + } + } } diff --git a/src/main/java/org/eclipsefoundation/react/resources/OrganizationResource.java b/src/main/java/org/eclipsefoundation/react/resources/OrganizationResource.java index 842ecfa114fc1cacbebaf66859e57f895ed9a089..c332a2dee1e9239d7d1c0b6a5a17a6884b8309ff 100644 --- a/src/main/java/org/eclipsefoundation/react/resources/OrganizationResource.java +++ b/src/main/java/org/eclipsefoundation/react/resources/OrganizationResource.java @@ -226,7 +226,7 @@ public class OrganizationResource extends AbstractRESTResource { @HeaderParam(value = CSRFHelper.CSRF_HEADER_NAME) String csrf) { // ensure csrf csrfHelper.compareCSRF(aud, csrf); - Optional> contacts = orgService.getOrganizationContacts(organizationID, + Optional> contacts = orgService.getOrganizationPeople(organizationID, Optional.ofNullable(mail), Optional.ofNullable(role), Optional.ofNullable(fName), Optional.ofNullable(lName)); if (contacts.isEmpty()) { @@ -243,7 +243,7 @@ public class OrganizationResource extends AbstractRESTResource { @HeaderParam(value = CSRFHelper.CSRF_HEADER_NAME) String csrf) { // ensure csrf csrfHelper.compareCSRF(aud, csrf); - Optional> contacts = orgService.getOrganizationContacts(organizationID, username); + Optional> contacts = orgService.getOrganizationPerson(organizationID, username); if (contacts.isEmpty()) { return Response.ok(Collections.emptyList()).build(); } @@ -273,7 +273,7 @@ public class OrganizationResource extends AbstractRESTResource { @PathParam("relation") String relation, @HeaderParam(value = CSRFHelper.CSRF_HEADER_NAME) String csrf) { // ensure csrf csrfHelper.compareCSRF(aud, csrf); - Optional> contacts = orgService.getOrganizationContacts(organizationID, username); + Optional> contacts = orgService.getOrganizationPerson(organizationID, username); if (contacts.isEmpty()) { return Response.ok(Collections.emptyList()).build(); } diff --git a/src/main/java/org/eclipsefoundation/react/service/OrganizationsService.java b/src/main/java/org/eclipsefoundation/react/service/OrganizationsService.java index d5d18b42aee83357b1a1363591e24d0bd4c1065b..21e9227eaa028088c365205dc22e0fe997fe9756 100644 --- a/src/main/java/org/eclipsefoundation/react/service/OrganizationsService.java +++ b/src/main/java/org/eclipsefoundation/react/service/OrganizationsService.java @@ -67,7 +67,7 @@ public interface OrganizationsService { * @param lName the last name of the user (no fuzzy). * @return a list of organization contacts that match the given parameters. */ - Optional> getOrganizationContacts(String orgID, Optional mail, + Optional> getOrganizationPeople(String orgID, Optional mail, Optional role, Optional fName, Optional lName); /** @@ -77,7 +77,7 @@ public interface OrganizationsService { * @param userName the username of the contact to retrieve entries for. * @return list of user relations for the given user in organization if they exist */ - Optional> getOrganizationContacts(String orgID, String userName); + Optional> getOrganizationPerson(String orgID, String userName); /** * Retrieves all user relations of organzations for a user. diff --git a/src/main/java/org/eclipsefoundation/react/service/impl/FoundationDBOrganizationService.java b/src/main/java/org/eclipsefoundation/react/service/impl/FoundationDBOrganizationService.java index 9c36bea292f0ed9320b152d091bbf4f8d97b229b..81083c369c862dac13709df82a66a4495e83dd71 100644 --- a/src/main/java/org/eclipsefoundation/react/service/impl/FoundationDBOrganizationService.java +++ b/src/main/java/org/eclipsefoundation/react/service/impl/FoundationDBOrganizationService.java @@ -38,6 +38,7 @@ import org.eclipsefoundation.api.OrganizationAPI; import org.eclipsefoundation.api.PeopleAPI; import org.eclipsefoundation.api.ProjectAPI; import org.eclipsefoundation.api.SysAPI; +import org.eclipsefoundation.api.PeopleAPI.PeopleRequestParams; import org.eclipsefoundation.api.model.OrganizationContactData; import org.eclipsefoundation.api.model.OrganizationData; import org.eclipsefoundation.api.model.OrganizationDocumentData; @@ -165,8 +166,8 @@ public class FoundationDBOrganizationService implements OrganizationsService { } @Override - public Optional> getOrganizationContacts(String orgID, Optional mail, - Optional role, Optional fName, Optional lName) { + public Optional> getOrganizationPeople(String orgID, Optional mail, Optional role, + Optional fName, Optional lName) { // create param map to properly generate a cache key MultivaluedMap params = new MultivaluedMapImpl<>(); params.add("mail", mail.orElse(null)); @@ -174,18 +175,21 @@ public class FoundationDBOrganizationService implements OrganizationsService { params.add("fName", fName.orElse(null)); params.add("lName", lName.orElse(null)); - return cache - .get(orgID, params, OrganizationContactData.class, - () -> middleware.getAll( - i -> orgAPI.getOrganizationContactsWithSearch(orgID, i, mail.orElse(null), - role.orElse(null), fName.orElse(null), lName.orElse(null)), - OrganizationContactData.class)); + return cache.get(orgID, params, PeopleData.class, () -> middleware.getAll(i -> peopleAPI.getPeople(i, + PeopleRequestParams.builder().setFirstName(fName.orElse(null)).setLastName(lName.orElse(null)) + .setRelation(role.orElse(null)).setEmail(mail.orElse(null)).setOrganizationID(orgID).build()), + PeopleData.class)); } @Override - public Optional> getOrganizationContacts(String orgID, String userName) { - return cache.get(orgID, new MultivaluedMapImpl<>(), OrganizationContactData.class, () -> middleware - .getAll(i -> orgAPI.getOrganizationContact(orgID, i, userName, null), OrganizationContactData.class)); + public Optional> getOrganizationPerson(String orgID, String userName) { + MultivaluedMap params = new MultivaluedMapImpl<>(); + params.add("organizationID", orgID); + return cache + .get(userName, params, PeopleData.class, + () -> middleware.getAll(i -> peopleAPI.getPeople(i, + PeopleRequestParams.builder().setUsername(userName).setOrganizationID(orgID).build()), + PeopleData.class)); } @Override @@ -229,7 +233,10 @@ public class FoundationDBOrganizationService implements OrganizationsService { MultivaluedMap params = new MultivaluedMapImpl<>(); params.add(FoundationDBParameterNames.RELATION.getName(), "CM"); return cache.get(id, params, PeopleData.class, - () -> middleware.getAll(i -> peopleAPI.getPeople(i, id, "CM", null), PeopleData.class)); + () -> middleware.getAll( + i -> peopleAPI.getPeople(i, + PeopleRequestParams.builder().setRelation("CM").setOrganizationID(id).build()), + PeopleData.class)); } @Override @@ -249,7 +256,10 @@ public class FoundationDBOrganizationService implements OrganizationsService { MultivaluedMap projectParams = new MultivaluedMapImpl<>(); projectParams.add(FoundationDBParameterNames.RELATION.getName(), "CM"); Optional> committers = cache.get(id, projectParams, PeopleData.class, - () -> middleware.getAll(i -> peopleAPI.getPeople(i, id, "CM", null), PeopleData.class)); + () -> middleware.getAll( + i -> peopleAPI.getPeople(i, + PeopleRequestParams.builder().setRelation("CM").setOrganizationID(id).build()), + PeopleData.class)); List peopleIDs; // if there are no people projects for org, then all members are contributors @@ -269,8 +279,11 @@ public class FoundationDBOrganizationService implements OrganizationsService { LOGGER.info("Organization {} has {} contributors, retrieving People entries", id, peopleIDs.size()); MultivaluedMap params = new MultivaluedMapImpl<>(); params.addAll(DefaultUrlParameterNames.IDS.getName(), peopleIDs); - return cache.get(id, params, PeopleData.class, - () -> middleware.getAll(i -> peopleAPI.getPeople(i, null, null, peopleIDs), PeopleData.class)); + return cache.get(id + "-contrib", params, PeopleData.class, + () -> middleware.getAll( + i -> peopleAPI.getPeople(i, + PeopleRequestParams.builder().setIds(peopleIDs).setOrganizationID(id).build()), + PeopleData.class)); } /**