From aa3c9e62d8cf2c32ec3d8795a12dc7c34df64571 Mon Sep 17 00:00:00 2001 From: Martin Lowe <martin.lowe@eclipse-foundation.org> Date: Thu, 9 Mar 2023 14:25:38 -0500 Subject: [PATCH 1/3] Iss #123 - Update status UI page to handle revalidation more intuitively Adds blocking form processing on the page for revalidation form so that we can more naturally handle errors. Resolves #123 --- pom.xml | 4 +- .../templates/simple_fingerprint_ui.html | 40 ++++++++++++++++++- 2 files changed, 40 insertions(+), 4 deletions(-) diff --git a/pom.xml b/pom.xml index 3baf3ec6..9db3d20b 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ <artifactId>git-eca</artifactId> <version>1.1.0</version> <properties> - <eclipse-api-version>0.6.10</eclipse-api-version> + <eclipse-api-version>0.7.1</eclipse-api-version> <compiler-plugin.version>3.8.1</compiler-plugin.version> <maven.compiler.parameters>true</maven.compiler.parameters> <maven.compiler.source>11</maven.compiler.source> @@ -14,7 +14,7 @@ <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <quarkus.platform.artifact-id>quarkus-universe-bom</quarkus.platform.artifact-id> <quarkus.platform.group-id>io.quarkus</quarkus.platform.group-id> - <quarkus.platform.version>2.9.2.Final</quarkus.platform.version> + <quarkus.platform.version>2.14.2.Final</quarkus.platform.version> <surefire-plugin.version>2.22.1</surefire-plugin.version> <auto-value.version>1.8.2</auto-value.version> <org.mapstruct.version>1.4.1.Final</org.mapstruct.version> diff --git a/src/main/resources/templates/simple_fingerprint_ui.html b/src/main/resources/templates/simple_fingerprint_ui.html index 497698c4..6347fc72 100644 --- a/src/main/resources/templates/simple_fingerprint_ui.html +++ b/src/main/resources/templates/simple_fingerprint_ui.html @@ -1,4 +1,6 @@ -{#include eclipse_header /} +{#include eclipse_header} + {#title}Git ECA Validation{/} +{/include} {#include eclipse_breadcrumb /} {|<style> .panel.list-group>div { @@ -140,7 +142,7 @@ {/if} {#if statuses.0.provider == ProviderType:GITHUB} <div> - <form action="/git/webhooks/github/revalidate/{fingerprint}" method="POST"> + <form id="git-eca-hook-revalidation" data-request-id="{fingerprint}"> <div class="captcha"> <div class="h-captcha" data-sitekey="{config:['eclipse.hcaptcha.sitekey']}"></div> </div> @@ -218,8 +220,10 @@ $newToast.fadeOut("slow"); }, 10000); } + // set up accordion $('#accordion').on('hidden.bs.collapse', toggleIcon); $('#accordion').on('shown.bs.collapse', toggleIcon); + // bind to ECA status lookup submit document.getElementById("eclipse-eca-lookup-form").addEventListener("submit", function (e) { // don't submit the form as we will handle it w/ ajax e.preventDefault(); @@ -250,6 +254,38 @@ } }); }); + + // Revalidation button binding + const revalidationForm = document.getElementById("git-eca-hook-revalidation"); + if (revalidationForm !== null) { + revalidationForm.addEventListener("submit", function (e) { + // don't submit the form as we will handle it w/ ajax + e.preventDefault(); + // grab the constants from the form and perform a check + const $form = $(e.target); + const $submitButton = $form.find('button'); + // disable the button so that requests won't be spammed + $submitButton.attr("disabled", "disabled"); + // use ajax to check the ECA status of the user + $.ajax({ + url: `/git/webhooks/github/revalidate/${$form.data('request-id')}`, + data: $form.serialize(), + type: 'POST', + success: function (data, status, xhr) { + toast(`Revalidation complete! Forwarding to pull request.`, 'success'); + window.location(xhr.getResponseHeader('Location')); + }, + error: function (xhr) { + const json = JSON.parse(xhr.responseText); + console.log('Error encountered while revalidating: ' + json.message); + toast(json.message, 'danger'); + }, + complete: function () { + $submitButton.removeAttr("disabled"); + } + }); + }); + } }); </script>|} -- GitLab From 60d611d36f9afcd2f755738ff225fea7567b60bd Mon Sep 17 00:00:00 2001 From: Martin Lowe <martin.lowe@eclipse-foundation.org> Date: Thu, 9 Mar 2023 15:14:15 -0500 Subject: [PATCH 2/3] Update revalidation response to not immediately redirect Immediate redirects rightfully triggered CORS exceptions when used in conjunction with AJAX. To get around this, we will return the new location as the only property in the response and redirect manually on success. --- spec/openapi.yaml | 112 ++++++++++++++++++ .../git/eca/model/RevalidationResponse.java | 44 +++++++ .../eca/resource/GithubWebhooksResource.java | 6 +- .../templates/simple_fingerprint_ui.html | 8 +- 4 files changed, 164 insertions(+), 6 deletions(-) create mode 100644 src/main/java/org/eclipsefoundation/git/eca/model/RevalidationResponse.java diff --git a/spec/openapi.yaml b/spec/openapi.yaml index 8759e982..93e49e58 100644 --- a/spec/openapi.yaml +++ b/spec/openapi.yaml @@ -51,6 +51,13 @@ paths: description: Error while retrieving data /eca/status/{fingerprint}/ui: + parameters: + - name: fingerprint + in: path + description: Unique ID for the request group + required: true + schema: + type: string get: summary: Historic ECA validation status in a HTML format description: Returns an HTMl page containing validation messages @@ -76,6 +83,78 @@ paths: 500: description: Error while retrieving data + /webhooks/github: + parameters: + - name: fingerprint + in: path + description: Unique ID for the request group + required: true + schema: + type: string + post: + tags: + - Github validation processing + summary: Github incoming hook event processing + description: Process incoming pull request hook events from Github + parameters: + - in: header + name: X-GitHub-Delivery + schema: + type: string + required: true + - in: header + name: X-GitHub-Event + schema: + type: string + required: true + - in: header + name: X-GitHub-Hook-ID + schema: + type: string + required: true + requestBody: + content: + application/json: + schema: + $ref: "#/components/schemas/SystemHook" + responses: + 200: + description: Success + 500: + description: Error while processing data + /webhooks/github/revalidate/{fingerprint}: + parameters: + - name: fingerprint + in: path + description: Unique ID for the request group + required: true + schema: + type: string + post: + tags: + - Github validation processing + summary: Gitlab webhook revalidation request + description: Process incoming system hooks from GitLab + parameters: + - in: header + name: X-Gitlab-Event + schema: + type: string + required: true + requestBody: + content: + application/json: + schema: + $ref: "#/components/schemas/SystemHook" + responses: + 200: + description: Success + 400: + description: Bad request + content: + application/json: + schema: + $ref: "#/components/schemas/Error" /webhooks/gitlab/system: post: tags: @@ -429,6 +508,39 @@ components: - "null" description: the project deletion date if it was deleted + GithubWebhookEvent: + type: object + properties: + installation: + type: object + description: Information about the Github App installation making this request + properties: + id: + type: string + description: The ID of the app installation that is making the validation request on behalf of the repository/user. + repository: + type: object + description: Information about the repository that triggered this request + properties: + full_name: + type: string + description: The full name of the repository, including organization. + html_url: + type: string + description: The link to the repository the event was triggered by + pull_request: + type: object + description: Information on the pull request that triggered this workflow. + properties: + number: + type: int + description: The numeric ID of the pull request that triggered the flow + head: + type: object + properties: + sha: + type: string + description: The SHA hash of the head of the pull request. Error: type: object properties: diff --git a/src/main/java/org/eclipsefoundation/git/eca/model/RevalidationResponse.java b/src/main/java/org/eclipsefoundation/git/eca/model/RevalidationResponse.java new file mode 100644 index 00000000..9f04d7fe --- /dev/null +++ b/src/main/java/org/eclipsefoundation/git/eca/model/RevalidationResponse.java @@ -0,0 +1,44 @@ +/********************************************************************* +* Copyright (c) 2020 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: Martin Lowe <martin.lowe@eclipse-foundation.org> +* +* SPDX-License-Identifier: EPL-2.0 +**********************************************************************/ +package org.eclipsefoundation.git.eca.model; + +import java.net.URI; + +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder; +import com.google.auto.value.AutoValue; + +/** + * Basic object representing a revalidation location post request. This was done to better integrate with the UI which + * fails on CORS requests when attempting to use natural redirects in AJAX. + * + * @author Martin Lowe + * + */ +@AutoValue +@JsonDeserialize(builder = AutoValue_RevalidationResponse.Builder.class) +public abstract class RevalidationResponse { + + public abstract URI getLocation(); + + public static Builder builder() { + return new AutoValue_RevalidationResponse.Builder(); + } + + @AutoValue.Builder + @JsonPOJOBuilder(withPrefix = "set") + public abstract static class Builder { + public abstract Builder setLocation(URI location); + + public abstract RevalidationResponse build(); + } +} \ No newline at end of file diff --git a/src/main/java/org/eclipsefoundation/git/eca/resource/GithubWebhooksResource.java b/src/main/java/org/eclipsefoundation/git/eca/resource/GithubWebhooksResource.java index fd87bdf7..088f3659 100644 --- a/src/main/java/org/eclipsefoundation/git/eca/resource/GithubWebhooksResource.java +++ b/src/main/java/org/eclipsefoundation/git/eca/resource/GithubWebhooksResource.java @@ -26,7 +26,6 @@ import javax.ws.rs.Path; import javax.ws.rs.PathParam; import javax.ws.rs.core.MultivaluedMap; import javax.ws.rs.core.Response; -import javax.ws.rs.core.Response.Status; import org.eclipse.microprofile.config.inject.ConfigProperty; import org.eclipse.microprofile.rest.client.inject.RestClient; @@ -43,6 +42,7 @@ import org.eclipsefoundation.git.eca.helper.CaptchaHelper; import org.eclipsefoundation.git.eca.helper.JwtHelper; import org.eclipsefoundation.git.eca.model.Commit; import org.eclipsefoundation.git.eca.model.GitUser; +import org.eclipsefoundation.git.eca.model.RevalidationResponse; import org.eclipsefoundation.git.eca.model.ValidationRequest; import org.eclipsefoundation.git.eca.model.ValidationResponse; import org.eclipsefoundation.git.eca.namespace.GitEcaParameterNames; @@ -170,8 +170,8 @@ public class GithubWebhooksResource { sb.append(tracking.getRepositoryFullName()); sb.append("/pull/"); sb.append(tracking.getPullRequestNumber()); - // redirect to the pull request page on successful trigger of the webhook - return Response.status(Status.FOUND).location(URI.create(sb.toString())).build(); + // respond with a URL to the new location in a standard request + return Response.ok(RevalidationResponse.builder().setLocation(URI.create(sb.toString())).build()).build(); } /** diff --git a/src/main/resources/templates/simple_fingerprint_ui.html b/src/main/resources/templates/simple_fingerprint_ui.html index 6347fc72..69af38b8 100644 --- a/src/main/resources/templates/simple_fingerprint_ui.html +++ b/src/main/resources/templates/simple_fingerprint_ui.html @@ -266,14 +266,16 @@ const $submitButton = $form.find('button'); // disable the button so that requests won't be spammed $submitButton.attr("disabled", "disabled"); - // use ajax to check the ECA status of the user + // use ajax to revalidate the commit with GH $.ajax({ url: `/git/webhooks/github/revalidate/${$form.data('request-id')}`, data: $form.serialize(), type: 'POST', - success: function (data, status, xhr) { + success: function (data) { toast(`Revalidation complete! Forwarding to pull request.`, 'success'); - window.location(xhr.getResponseHeader('Location')); + setTimeout(() => { + window.location.replace(data.location); + }, '2500'); }, error: function (xhr) { const json = JSON.parse(xhr.responseText); -- GitLab From f0f185f100b301c5ba808cdbf43dd5b8431075e2 Mon Sep 17 00:00:00 2001 From: Martin Lowe <martin.lowe@eclipse-foundation.org> Date: Fri, 10 Mar 2023 10:55:55 -0500 Subject: [PATCH 3/3] Fix spec according to feedback --- spec/openapi.yaml | 27 +++++++++++---------------- 1 file changed, 11 insertions(+), 16 deletions(-) diff --git a/spec/openapi.yaml b/spec/openapi.yaml index 93e49e58..c1b7bcec 100644 --- a/spec/openapi.yaml +++ b/spec/openapi.yaml @@ -84,13 +84,6 @@ paths: description: Error while retrieving data /webhooks/github: - parameters: - - name: fingerprint - in: path - description: Unique ID for the request group - required: true - schema: - type: string post: tags: - Github validation processing @@ -116,7 +109,7 @@ paths: content: application/json: schema: - $ref: "#/components/schemas/SystemHook" + $ref: "#/components/schemas/GithubWebhookEvent" responses: 200: description: Success @@ -135,17 +128,11 @@ paths: - Github validation processing summary: Gitlab webhook revalidation request description: Process incoming system hooks from GitLab - parameters: - - in: header - name: X-Gitlab-Event - schema: - type: string - required: true requestBody: content: - application/json: + application/x-www-form-urlencoded: schema: - $ref: "#/components/schemas/SystemHook" + $ref: '#/components/schemas/RevalidationRequest' responses: 200: description: Success @@ -155,6 +142,8 @@ paths: application/json: schema: $ref: "#/components/schemas/Error" + 404: + description: Not found /webhooks/gitlab/system: post: tags: @@ -541,6 +530,12 @@ components: sha: type: string description: The SHA hash of the head of the pull request. + RevalidationRequest: + type: object + properties: + h-form-captcha-response: + type: string + description: the hCaptcha challenge response. Error: type: object properties: -- GitLab