Skip to content
Snippets Groups Projects
Commit 36d5bfdd authored by Zachary Sabourin's avatar Zachary Sabourin
Browse files

fix: Fix Agreement return format + fixed date format issues

parent 1d3d35bb
No related branches found
No related tags found
1 merge request!10fix: Fix Agreement return format + fixed date format issues
Showing with 172 additions and 21 deletions
...@@ -118,7 +118,7 @@ paths: ...@@ -118,7 +118,7 @@ paths:
content: content:
application/json: application/json:
schema: schema:
$ref: "#/components/schemas/EfUser" $ref: "#/components/schemas/EfUsers"
403: 403:
description: Invalid credentials description: Invalid credentials
500: 500:
...@@ -198,6 +198,11 @@ components: ...@@ -198,6 +198,11 @@ components:
- type: "null" - type: "null"
description: The URL description: The URL
EfUsers:
type: array
items:
$ref: "#/components/schemas/EfUser"
EfUser: EfUser:
type: object type: object
properties: properties:
......
/*********************************************************************
* Copyright (c) 2023 Eclipse Foundation.
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* Author: Zachary Sabourin <zachary.sabourin@eclipse-foundation.org>
*
* SPDX-License-Identifier: EPL-2.0
**********************************************************************/
package org.eclipsefoundation.openvsx.models;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder;
import com.google.auto.value.AutoValue;
@AutoValue
@JsonDeserialize(builder = AutoValue_PublisherAgreementData.Builder.class)
public abstract class PublisherAgreementData {
@JsonProperty("PersonID")
public abstract String getPersonID();
@JsonProperty("DocumentID")
public abstract String getDocumentID();
@JsonProperty("Version")
public abstract String getVersion();
@JsonProperty("EffectiveDate")
public abstract String getEffectiveDate();
@JsonProperty("ReceivedDate")
public abstract String getReceivedDate();
@JsonProperty("ScannedDocumentBLOB")
public abstract String getScannedDocumentBlob();
@JsonProperty("ScannedDocumentMime")
public abstract String getScannedDocumentMime();
@JsonProperty("ScannedDocumentBytes")
public abstract String getScannedDocumentBytes();
@JsonProperty("ScannedDocumentFileName")
public abstract String getScannedDocumentFileName();
@JsonProperty("Comments")
public abstract String getComments();
public static Builder builder() {
return new AutoValue_PublisherAgreementData.Builder();
}
@AutoValue.Builder
@JsonPOJOBuilder(withPrefix = "set")
public abstract static class Builder {
public abstract Builder setPersonID(String id);
public abstract Builder setDocumentID(String id);
public abstract Builder setVersion(String version);
public abstract Builder setEffectiveDate(String date);
public abstract Builder setReceivedDate(String date);
public abstract Builder setScannedDocumentBlob(String blob);
public abstract Builder setScannedDocumentMime(String mime);
public abstract Builder setScannedDocumentBytes(String bytes);
public abstract Builder setScannedDocumentFileName(String name);
public abstract Builder setComments(String commetns);
public abstract PublisherAgreementData build();
}
}
...@@ -11,6 +11,8 @@ ...@@ -11,6 +11,8 @@
**********************************************************************/ **********************************************************************/
package org.eclipsefoundation.openvsx.resources; package org.eclipsefoundation.openvsx.resources;
import java.util.Arrays;
import javax.ws.rs.GET; import javax.ws.rs.GET;
import javax.ws.rs.Path; import javax.ws.rs.Path;
import javax.ws.rs.core.Response; import javax.ws.rs.core.Response;
...@@ -21,6 +23,6 @@ public class ProfileResource extends OpenvsxResource { ...@@ -21,6 +23,6 @@ public class ProfileResource extends OpenvsxResource {
@GET @GET
public Response getProfileInfo() { public Response getProfileInfo() {
// Returns the public profile data tied to the current token // Returns the public profile data tied to the current token
return Response.ok(getTokenUser().toBuilder().setMail("").build()).build(); return Response.ok(Arrays.asList(getTokenUser().toBuilder().setMail("").build())).build();
} }
} }
...@@ -31,6 +31,7 @@ import org.eclipsefoundation.core.model.Error; ...@@ -31,6 +31,7 @@ import org.eclipsefoundation.core.model.Error;
import org.eclipsefoundation.foundationdb.client.model.PeopleDocumentData; import org.eclipsefoundation.foundationdb.client.model.PeopleDocumentData;
import org.eclipsefoundation.openvsx.api.models.EfUser; import org.eclipsefoundation.openvsx.api.models.EfUser;
import org.eclipsefoundation.openvsx.models.AgreementSigningRequest; import org.eclipsefoundation.openvsx.models.AgreementSigningRequest;
import org.eclipsefoundation.openvsx.models.PublisherAgreementData;
import org.eclipsefoundation.openvsx.services.FoundationOperationService; import org.eclipsefoundation.openvsx.services.FoundationOperationService;
import org.eclipsefoundation.openvsx.services.PublisherAgreementService; import org.eclipsefoundation.openvsx.services.PublisherAgreementService;
...@@ -54,7 +55,7 @@ public class PublisherAgreementResource extends OpenvsxResource { ...@@ -54,7 +55,7 @@ public class PublisherAgreementResource extends OpenvsxResource {
// Uses currently logged in user. Only an onwer can fetch their agreement // Uses currently logged in user. Only an onwer can fetch their agreement
String username = getTokenUser().getName(); String username = getTokenUser().getName();
Optional<PeopleDocumentData> result = agreementService.getPublisherAgreementByUsername(username); Optional<PublisherAgreementData> result = agreementService.getPublisherAgreementByUsername(username);
if (result.isEmpty()) { if (result.isEmpty()) {
throw new NotFoundException(String.format(NOT_FOUND_MSG_FORMAT, username)); throw new NotFoundException(String.format(NOT_FOUND_MSG_FORMAT, username));
} }
...@@ -83,7 +84,7 @@ public class PublisherAgreementResource extends OpenvsxResource { ...@@ -83,7 +84,7 @@ public class PublisherAgreementResource extends OpenvsxResource {
throw new ServerErrorException("Internal Server Error", 500); throw new ServerErrorException("Internal Server Error", 500);
} }
Optional<PeopleDocumentData> result = agreementService.createPublisherAgreement(user); Optional<PublisherAgreementData> result = agreementService.createPublisherAgreement(user);
if (result.isEmpty()) { if (result.isEmpty()) {
throw new BadRequestException("Unable to create Publisher Agreement with current request parameters"); throw new BadRequestException("Unable to create Publisher Agreement with current request parameters");
} }
...@@ -98,7 +99,7 @@ public class PublisherAgreementResource extends OpenvsxResource { ...@@ -98,7 +99,7 @@ public class PublisherAgreementResource extends OpenvsxResource {
// The owner or admin can retrieve a specific agreement // The owner or admin can retrieve a specific agreement
checkIfAdminOrSelf(username); checkIfAdminOrSelf(username);
Optional<PeopleDocumentData> result = agreementService.getPublisherAgreementByUsername(username); Optional<PublisherAgreementData> result = agreementService.getPublisherAgreementByUsername(username);
if (result.isEmpty()) { if (result.isEmpty()) {
throw new NotFoundException(String.format(NOT_FOUND_MSG_FORMAT, username)); throw new NotFoundException(String.format(NOT_FOUND_MSG_FORMAT, username));
} }
...@@ -113,7 +114,7 @@ public class PublisherAgreementResource extends OpenvsxResource { ...@@ -113,7 +114,7 @@ public class PublisherAgreementResource extends OpenvsxResource {
// The owner or admin can retrieve a specific agreement // The owner or admin can retrieve a specific agreement
checkIfAdminOrSelf(username); checkIfAdminOrSelf(username);
Optional<PeopleDocumentData> fetchResult = agreementService.getPublisherAgreementByUsername(username); Optional<PeopleDocumentData> fetchResult = foundationService.fetchMostRecentDocument(username);
if (fetchResult.isEmpty()) { if (fetchResult.isEmpty()) {
throw new NotFoundException(String.format(NOT_FOUND_MSG_FORMAT, username)); throw new NotFoundException(String.format(NOT_FOUND_MSG_FORMAT, username));
} }
......
...@@ -15,6 +15,7 @@ import java.util.Optional; ...@@ -15,6 +15,7 @@ import java.util.Optional;
import org.eclipsefoundation.foundationdb.client.model.PeopleDocumentData; import org.eclipsefoundation.foundationdb.client.model.PeopleDocumentData;
import org.eclipsefoundation.openvsx.api.models.EfUser; import org.eclipsefoundation.openvsx.api.models.EfUser;
import org.eclipsefoundation.openvsx.models.PublisherAgreementData;
/** /**
* Defines the service for fetching, creating and revoking openvsx publisher * Defines the service for fetching, creating and revoking openvsx publisher
...@@ -27,9 +28,9 @@ public interface PublisherAgreementService { ...@@ -27,9 +28,9 @@ public interface PublisherAgreementService {
* agreement for the given user. * agreement for the given user.
* *
* @param username The desired user's EF username. * @param username The desired user's EF username.
* @return An Optional containing a PeopleDocumentData entity if it exists. * @return An Optional containing a PublisherAgreementData entity if it exists.
*/ */
public Optional<PeopleDocumentData> getPublisherAgreementByUsername(String username); public Optional<PublisherAgreementData> getPublisherAgreementByUsername(String username);
/** /**
* Creates a publisher agreement for the given user using the request * Creates a publisher agreement for the given user using the request
...@@ -37,17 +38,17 @@ public interface PublisherAgreementService { ...@@ -37,17 +38,17 @@ public interface PublisherAgreementService {
* event on fail or pass. Returns an empty Optional if it encounters an error. * event on fail or pass. Returns an empty Optional if it encounters an error.
* *
* @param user The current logged in user * @param user The current logged in user
* @return An Optional containing the created PeopleDocumentData entity if it * @return An Optional containing the created PublisherAgreementData entity if
* exists * it exists
*/ */
public Optional<PeopleDocumentData> createPublisherAgreement(EfUser user); public Optional<PublisherAgreementData> createPublisherAgreement(EfUser user);
/** /**
* Expires a Publisher agreement and updates it in the foundationdb. Inserts a * Expires a Publisher agreement and updates it in the foundationdb. Inserts a
* modLog event on fail or pass. Returns an empty Optional if it encounters an * modLog event on fail or pass. Returns an empty Optional if it encounters an
* error. * error.
* *
* @param document The current signed document * @param document The current signed publisher agreement
* @param currentUser The user bound to the token * @param currentUser The user bound to the token
* @return An Optional containing the updated PeopleDocumentData if it exists * @return An Optional containing the updated PeopleDocumentData if it exists
*/ */
......
...@@ -11,7 +11,9 @@ ...@@ -11,7 +11,9 @@
**********************************************************************/ **********************************************************************/
package org.eclipsefoundation.openvsx.services.impl; package org.eclipsefoundation.openvsx.services.impl;
import java.text.SimpleDateFormat;
import java.time.Instant; import java.time.Instant;
import java.time.ZonedDateTime;
import java.util.Arrays; import java.util.Arrays;
import java.util.Date; import java.util.Date;
import java.util.List; import java.util.List;
...@@ -22,10 +24,12 @@ import javax.inject.Inject; ...@@ -22,10 +24,12 @@ import javax.inject.Inject;
import org.apache.commons.lang3.ArrayUtils; import org.apache.commons.lang3.ArrayUtils;
import org.eclipse.microprofile.config.inject.ConfigProperty; import org.eclipse.microprofile.config.inject.ConfigProperty;
import org.eclipsefoundation.core.helper.DateTimeHelper;
import org.eclipsefoundation.foundationdb.client.model.PeopleDocumentData; import org.eclipsefoundation.foundationdb.client.model.PeopleDocumentData;
import org.eclipsefoundation.openvsx.api.models.EfUser; import org.eclipsefoundation.openvsx.api.models.EfUser;
import org.eclipsefoundation.openvsx.api.models.ModLogHeaders; import org.eclipsefoundation.openvsx.api.models.ModLogHeaders;
import org.eclipsefoundation.openvsx.models.DocumentBody; import org.eclipsefoundation.openvsx.models.DocumentBody;
import org.eclipsefoundation.openvsx.models.PublisherAgreementData;
import org.eclipsefoundation.openvsx.namespace.OpenvsxModLogActions; import org.eclipsefoundation.openvsx.namespace.OpenvsxModLogActions;
import org.eclipsefoundation.openvsx.services.FoundationOperationService; import org.eclipsefoundation.openvsx.services.FoundationOperationService;
import org.eclipsefoundation.openvsx.services.PublisherAgreementService; import org.eclipsefoundation.openvsx.services.PublisherAgreementService;
...@@ -41,7 +45,7 @@ public class DefaultPublisherAgreementService implements PublisherAgreementServi ...@@ -41,7 +45,7 @@ public class DefaultPublisherAgreementService implements PublisherAgreementServi
@ConfigProperty(name = "eclipse.openvsx.doc-id") @ConfigProperty(name = "eclipse.openvsx.doc-id")
String openvsxDocId; String openvsxDocId;
@ConfigProperty(name = "eclipse.openvsx.document-version", defaultValue = "1") @ConfigProperty(name = "eclipse.openvsx.document-version", defaultValue = "1")
Double docVersion; Integer docVersion;
@Inject @Inject
FoundationOperationService foundationService; FoundationOperationService foundationService;
...@@ -50,13 +54,14 @@ public class DefaultPublisherAgreementService implements PublisherAgreementServi ...@@ -50,13 +54,14 @@ public class DefaultPublisherAgreementService implements PublisherAgreementServi
ObjectMapper objectMapper; ObjectMapper objectMapper;
@Override @Override
public Optional<PeopleDocumentData> getPublisherAgreementByUsername(String username) { public Optional<PublisherAgreementData> getPublisherAgreementByUsername(String username) {
Optional<PeopleDocumentData> mostRecent = foundationService.fetchMostRecentDocument(username); Optional<PeopleDocumentData> mostRecent = foundationService.fetchMostRecentDocument(username);
return mostRecent.isEmpty() || isdocumentExpired(mostRecent.get()) ? Optional.empty() : mostRecent; return mostRecent.isEmpty() || isdocumentExpired(mostRecent.get()) ? Optional.empty()
: Optional.of(buildPublisherAgreement(mostRecent.get(), true));
} }
@Override @Override
public Optional<PeopleDocumentData> createPublisherAgreement(EfUser user) { public Optional<PublisherAgreementData> createPublisherAgreement(EfUser user) {
try { try {
LOGGER.debug("Creating publisher agreement for user: {}", user.getName()); LOGGER.debug("Creating publisher agreement for user: {}", user.getName());
...@@ -77,9 +82,13 @@ public class DefaultPublisherAgreementService implements PublisherAgreementServi ...@@ -77,9 +82,13 @@ public class DefaultPublisherAgreementService implements PublisherAgreementServi
.setMail(user.getMail()) .setMail(user.getMail())
.build()); .build());
return foundationService.persistDocumentWithModLog(headers, Optional<PeopleDocumentData> creationResult = foundationService.persistDocumentWithModLog(headers,
createDocumentSigningRequest(jsonDoc, user.getName())); createDocumentSigningRequest(jsonDoc, user.getName()));
// Convert to PublisherAgreementData if persistence successful
return creationResult.isEmpty() ? Optional.empty()
: Optional.of(buildPublisherAgreement(creationResult.get(), false));
} catch (Exception e) { } catch (Exception e) {
LOGGER.error("Error while creating publisher agreement", e); LOGGER.error("Error while creating publisher agreement", e);
foundationService.insertErrorSysModLog("_openvsx_publisher_agreement_create", user.getName()); foundationService.insertErrorSysModLog("_openvsx_publisher_agreement_create", user.getName());
...@@ -150,12 +159,15 @@ public class DefaultPublisherAgreementService implements PublisherAgreementServi ...@@ -150,12 +159,15 @@ public class DefaultPublisherAgreementService implements PublisherAgreementServi
List<Byte> docAsBytes = Arrays.asList(ArrayUtils.toObject(jsonDoc.getBytes())); List<Byte> docAsBytes = Arrays.asList(ArrayUtils.toObject(jsonDoc.getBytes()));
// Set date to UTC timezone when creating
Date now = Date.from(DateTimeHelper.now().toInstant());
return PeopleDocumentData.builder() return PeopleDocumentData.builder()
.setPersonID(username) .setPersonID(username)
.setDocumentID(openvsxDocId) .setDocumentID(openvsxDocId)
.setVersion(docVersion) .setVersion(docVersion)
.setEffectiveDate(new Date()) .setEffectiveDate(now)
.setReceivedDate(new Date()) .setReceivedDate(now)
.setScannedDocumentFileName("openvsx-publisher-agreement.json") .setScannedDocumentFileName("openvsx-publisher-agreement.json")
.setScannedDocumentMime("application/json") .setScannedDocumentMime("application/json")
.setScannedDocumentBLOB(docAsBytes) .setScannedDocumentBLOB(docAsBytes)
...@@ -163,4 +175,49 @@ public class DefaultPublisherAgreementService implements PublisherAgreementServi ...@@ -163,4 +175,49 @@ public class DefaultPublisherAgreementService implements PublisherAgreementServi
.setComments("Generated by api.eclipse.org/openvsx/publisher_agreement") .setComments("Generated by api.eclipse.org/openvsx/publisher_agreement")
.build(); .build();
} }
/**
* Builds a PublisherAgreementData object using the given PeopleDocumentData
* entity. Has a flag to offset the received date by one day to compensate for
* the modification made by fdndb-api.
*
* @param document The given PeopleDocumentData entity
* @param adjustTime A Flag to increment the received date by a day
* @return A populated PublisherAgreementData object
*/
private PublisherAgreementData buildPublisherAgreement(PeopleDocumentData document, boolean adjustTime) {
// Conversion of List<Byte> to byte[] to allow conversion to string
byte[] blob = document.getScannedDocumentBLOB() == null ? new byte[0]
: ArrayUtils.toPrimitive(
document.getScannedDocumentBLOB().toArray(new Byte[document.getScannedDocumentBLOB().size()]));
SimpleDateFormat effectiveDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
SimpleDateFormat receivedDateFormat = new SimpleDateFormat("yyyy-MM-dd");
String receivedDate = "";
// The 'received_date' column is only a 'date' type and gets rewinded a day when
// adjusted for UTC time by fdndb-api. Flag should onlybe set on fetch requests
if (adjustTime) {
ZonedDateTime adjustedTime = ZonedDateTime.parse(DateTimeHelper.toRFC3339(document.getReceivedDate()))
.plusDays(1);
receivedDate = receivedDateFormat.format(Date.from(adjustedTime.toInstant()));
} else {
receivedDate = receivedDateFormat.format(document.getReceivedDate());
}
return PublisherAgreementData.builder()
.setPersonID(document.getPersonID())
.setDocumentID(document.getDocumentID())
.setVersion(Integer.toString((int) document.getVersion()))
.setEffectiveDate(effectiveDateFormat.format(document.getEffectiveDate()))
.setReceivedDate(receivedDate)
.setScannedDocumentBlob(new String(blob))
.setScannedDocumentMime(document.getScannedDocumentMime())
.setScannedDocumentBytes(Integer.toString(blob.length))
.setScannedDocumentFileName(document.getScannedDocumentFileName())
.setComments(document.getComments())
.build();
}
} }
...@@ -36,7 +36,7 @@ public class ProfileResourceTest { ...@@ -36,7 +36,7 @@ public class ProfileResourceTest {
.of(Map.of("Authorization", "Bearer token1")); .of(Map.of("Authorization", "Bearer token1"));
public static final EndpointTestCase GET_CURRENT_SUCCESS = TestCaseHelper public static final EndpointTestCase GET_CURRENT_SUCCESS = TestCaseHelper
.prepareTestCase(BASE_URL, new String[] {}, SchemaNamespaceHelper.EF_USER_SCHEMA_PATH) .prepareTestCase(BASE_URL, new String[] {}, SchemaNamespaceHelper.EF_USERS_SCHEMA_PATH)
.setHeaderParams(userCreds).build(); .setHeaderParams(userCreds).build();
/* /*
......
...@@ -24,6 +24,7 @@ import javax.enterprise.context.ApplicationScoped; ...@@ -24,6 +24,7 @@ import javax.enterprise.context.ApplicationScoped;
import javax.ws.rs.core.MultivaluedMap; import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.core.Response; import javax.ws.rs.core.Response;
import org.apache.commons.lang3.ArrayUtils;
import org.eclipse.microprofile.rest.client.inject.RestClient; import org.eclipse.microprofile.rest.client.inject.RestClient;
import org.eclipsefoundation.foundationdb.client.model.PeopleData; import org.eclipsefoundation.foundationdb.client.model.PeopleData;
import org.eclipsefoundation.foundationdb.client.model.PeopleDocumentData; import org.eclipsefoundation.foundationdb.client.model.PeopleDocumentData;
...@@ -119,7 +120,7 @@ public class MockPeopleAPI implements PeopleAPI { ...@@ -119,7 +120,7 @@ public class MockPeopleAPI implements PeopleAPI {
.setReceivedDate(new Date()) .setReceivedDate(new Date())
.setScannedDocumentFileName("name") .setScannedDocumentFileName("name")
.setScannedDocumentMime("application/json") .setScannedDocumentMime("application/json")
.setScannedDocumentBLOB(null) .setScannedDocumentBLOB(Arrays.asList(ArrayUtils.toObject("test blob".getBytes())))
.setScannedDocumentBytes(100) .setScannedDocumentBytes(100)
.setComments("Some comments") .setComments("Some comments")
.build(); .build();
......
...@@ -20,5 +20,6 @@ public class SchemaNamespaceHelper { ...@@ -20,5 +20,6 @@ public class SchemaNamespaceHelper {
public static final String PUBLISHER_AGREEMENT_SCHEMA_PATH = BASE_SCHEMA_PATH + "publisher-agreement" public static final String PUBLISHER_AGREEMENT_SCHEMA_PATH = BASE_SCHEMA_PATH + "publisher-agreement"
+ BASE_SCHEMA_PATH_SUFFIX; + BASE_SCHEMA_PATH_SUFFIX;
public static final String EF_USER_SCHEMA_PATH = BASE_SCHEMA_PATH + "ef-user" + BASE_SCHEMA_PATH_SUFFIX; public static final String EF_USER_SCHEMA_PATH = BASE_SCHEMA_PATH + "ef-user" + BASE_SCHEMA_PATH_SUFFIX;
public static final String EF_USERS_SCHEMA_PATH = BASE_SCHEMA_PATH + "ef-users" + BASE_SCHEMA_PATH_SUFFIX;
public static final String ERROR_SCHEMA_PATH = BASE_SCHEMA_PATH + "error" + BASE_SCHEMA_PATH_SUFFIX; public static final String ERROR_SCHEMA_PATH = BASE_SCHEMA_PATH + "error" + BASE_SCHEMA_PATH_SUFFIX;
} }
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment