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

Merge branch 'zacharysabourin/main/21' into 'main'

fix: Fix Agreement return format + fixed date format issues

Closes #21

See merge request !10
parents 1d3d35bb 36d5bfdd
No related branches found
No related tags found
1 merge request!10fix: Fix Agreement return format + fixed date format issues
Pipeline #17666 passed
Showing with 172 additions and 21 deletions
......@@ -118,7 +118,7 @@ paths:
content:
application/json:
schema:
$ref: "#/components/schemas/EfUser"
$ref: "#/components/schemas/EfUsers"
403:
description: Invalid credentials
500:
......@@ -198,6 +198,11 @@ components:
- type: "null"
description: The URL
EfUsers:
type: array
items:
$ref: "#/components/schemas/EfUser"
EfUser:
type: object
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 @@
**********************************************************************/
package org.eclipsefoundation.openvsx.resources;
import java.util.Arrays;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.core.Response;
......@@ -21,6 +23,6 @@ public class ProfileResource extends OpenvsxResource {
@GET
public Response getProfileInfo() {
// 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;
import org.eclipsefoundation.foundationdb.client.model.PeopleDocumentData;
import org.eclipsefoundation.openvsx.api.models.EfUser;
import org.eclipsefoundation.openvsx.models.AgreementSigningRequest;
import org.eclipsefoundation.openvsx.models.PublisherAgreementData;
import org.eclipsefoundation.openvsx.services.FoundationOperationService;
import org.eclipsefoundation.openvsx.services.PublisherAgreementService;
......@@ -54,7 +55,7 @@ public class PublisherAgreementResource extends OpenvsxResource {
// Uses currently logged in user. Only an onwer can fetch their agreement
String username = getTokenUser().getName();
Optional<PeopleDocumentData> result = agreementService.getPublisherAgreementByUsername(username);
Optional<PublisherAgreementData> result = agreementService.getPublisherAgreementByUsername(username);
if (result.isEmpty()) {
throw new NotFoundException(String.format(NOT_FOUND_MSG_FORMAT, username));
}
......@@ -83,7 +84,7 @@ public class PublisherAgreementResource extends OpenvsxResource {
throw new ServerErrorException("Internal Server Error", 500);
}
Optional<PeopleDocumentData> result = agreementService.createPublisherAgreement(user);
Optional<PublisherAgreementData> result = agreementService.createPublisherAgreement(user);
if (result.isEmpty()) {
throw new BadRequestException("Unable to create Publisher Agreement with current request parameters");
}
......@@ -98,7 +99,7 @@ public class PublisherAgreementResource extends OpenvsxResource {
// The owner or admin can retrieve a specific agreement
checkIfAdminOrSelf(username);
Optional<PeopleDocumentData> result = agreementService.getPublisherAgreementByUsername(username);
Optional<PublisherAgreementData> result = agreementService.getPublisherAgreementByUsername(username);
if (result.isEmpty()) {
throw new NotFoundException(String.format(NOT_FOUND_MSG_FORMAT, username));
}
......@@ -113,7 +114,7 @@ public class PublisherAgreementResource extends OpenvsxResource {
// The owner or admin can retrieve a specific agreement
checkIfAdminOrSelf(username);
Optional<PeopleDocumentData> fetchResult = agreementService.getPublisherAgreementByUsername(username);
Optional<PeopleDocumentData> fetchResult = foundationService.fetchMostRecentDocument(username);
if (fetchResult.isEmpty()) {
throw new NotFoundException(String.format(NOT_FOUND_MSG_FORMAT, username));
}
......
......@@ -15,6 +15,7 @@ import java.util.Optional;
import org.eclipsefoundation.foundationdb.client.model.PeopleDocumentData;
import org.eclipsefoundation.openvsx.api.models.EfUser;
import org.eclipsefoundation.openvsx.models.PublisherAgreementData;
/**
* Defines the service for fetching, creating and revoking openvsx publisher
......@@ -27,9 +28,9 @@ public interface PublisherAgreementService {
* agreement for the given user.
*
* @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
......@@ -37,17 +38,17 @@ public interface PublisherAgreementService {
* event on fail or pass. Returns an empty Optional if it encounters an error.
*
* @param user The current logged in user
* @return An Optional containing the created PeopleDocumentData entity if it
* exists
* @return An Optional containing the created PublisherAgreementData entity if
* 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
* modLog event on fail or pass. Returns an empty Optional if it encounters an
* error.
*
* @param document The current signed document
* @param document The current signed publisher agreement
* @param currentUser The user bound to the token
* @return An Optional containing the updated PeopleDocumentData if it exists
*/
......
......@@ -11,7 +11,9 @@
**********************************************************************/
package org.eclipsefoundation.openvsx.services.impl;
import java.text.SimpleDateFormat;
import java.time.Instant;
import java.time.ZonedDateTime;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
......@@ -22,10 +24,12 @@ import javax.inject.Inject;
import org.apache.commons.lang3.ArrayUtils;
import org.eclipse.microprofile.config.inject.ConfigProperty;
import org.eclipsefoundation.core.helper.DateTimeHelper;
import org.eclipsefoundation.foundationdb.client.model.PeopleDocumentData;
import org.eclipsefoundation.openvsx.api.models.EfUser;
import org.eclipsefoundation.openvsx.api.models.ModLogHeaders;
import org.eclipsefoundation.openvsx.models.DocumentBody;
import org.eclipsefoundation.openvsx.models.PublisherAgreementData;
import org.eclipsefoundation.openvsx.namespace.OpenvsxModLogActions;
import org.eclipsefoundation.openvsx.services.FoundationOperationService;
import org.eclipsefoundation.openvsx.services.PublisherAgreementService;
......@@ -41,7 +45,7 @@ public class DefaultPublisherAgreementService implements PublisherAgreementServi
@ConfigProperty(name = "eclipse.openvsx.doc-id")
String openvsxDocId;
@ConfigProperty(name = "eclipse.openvsx.document-version", defaultValue = "1")
Double docVersion;
Integer docVersion;
@Inject
FoundationOperationService foundationService;
......@@ -50,13 +54,14 @@ public class DefaultPublisherAgreementService implements PublisherAgreementServi
ObjectMapper objectMapper;
@Override
public Optional<PeopleDocumentData> getPublisherAgreementByUsername(String username) {
public Optional<PublisherAgreementData> getPublisherAgreementByUsername(String 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
public Optional<PeopleDocumentData> createPublisherAgreement(EfUser user) {
public Optional<PublisherAgreementData> createPublisherAgreement(EfUser user) {
try {
LOGGER.debug("Creating publisher agreement for user: {}", user.getName());
......@@ -77,9 +82,13 @@ public class DefaultPublisherAgreementService implements PublisherAgreementServi
.setMail(user.getMail())
.build());
return foundationService.persistDocumentWithModLog(headers,
Optional<PeopleDocumentData> creationResult = foundationService.persistDocumentWithModLog(headers,
createDocumentSigningRequest(jsonDoc, user.getName()));
// Convert to PublisherAgreementData if persistence successful
return creationResult.isEmpty() ? Optional.empty()
: Optional.of(buildPublisherAgreement(creationResult.get(), false));
} catch (Exception e) {
LOGGER.error("Error while creating publisher agreement", e);
foundationService.insertErrorSysModLog("_openvsx_publisher_agreement_create", user.getName());
......@@ -150,12 +159,15 @@ public class DefaultPublisherAgreementService implements PublisherAgreementServi
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()
.setPersonID(username)
.setDocumentID(openvsxDocId)
.setVersion(docVersion)
.setEffectiveDate(new Date())
.setReceivedDate(new Date())
.setEffectiveDate(now)
.setReceivedDate(now)
.setScannedDocumentFileName("openvsx-publisher-agreement.json")
.setScannedDocumentMime("application/json")
.setScannedDocumentBLOB(docAsBytes)
......@@ -163,4 +175,49 @@ public class DefaultPublisherAgreementService implements PublisherAgreementServi
.setComments("Generated by api.eclipse.org/openvsx/publisher_agreement")
.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 {
.of(Map.of("Authorization", "Bearer token1"));
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();
/*
......
......@@ -24,6 +24,7 @@ import javax.enterprise.context.ApplicationScoped;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.core.Response;
import org.apache.commons.lang3.ArrayUtils;
import org.eclipse.microprofile.rest.client.inject.RestClient;
import org.eclipsefoundation.foundationdb.client.model.PeopleData;
import org.eclipsefoundation.foundationdb.client.model.PeopleDocumentData;
......@@ -119,7 +120,7 @@ public class MockPeopleAPI implements PeopleAPI {
.setReceivedDate(new Date())
.setScannedDocumentFileName("name")
.setScannedDocumentMime("application/json")
.setScannedDocumentBLOB(null)
.setScannedDocumentBLOB(Arrays.asList(ArrayUtils.toObject("test blob".getBytes())))
.setScannedDocumentBytes(100)
.setComments("Some comments")
.build();
......
......@@ -20,5 +20,6 @@ public class SchemaNamespaceHelper {
public static final String PUBLISHER_AGREEMENT_SCHEMA_PATH = BASE_SCHEMA_PATH + "publisher-agreement"
+ 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;
}
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