Skip to content
Snippets Groups Projects
Commit 408accfb authored by Martin Lowe's avatar Martin Lowe :flag_ca:
Browse files

fix: Add blocked user message to Qute template calls

parent 843f7742
Branches
No related tags found
1 merge request!227feat: Add handling for blocked users in validation and lookups
Pipeline #81605 passed
......@@ -24,176 +24,180 @@ import io.quarkus.qute.TemplateExtension;
@TemplateExtension
public class EclipseQuteTemplateExtensions {
private static final int EMAIL_ADDRESS_PARTS = 2;
private static final int DOMAIN_PARTS_MINIMUM = 2;
// division point where a character gets obfuscated in the email domain
private static final int OBFUSCATION_DIVISION_POINT = 2;
/**
* Made to count nested errors in a list of commit status objects.
*
* @param statuses the statuses to expand and count errors for
* @return the number of errors in the list of statuses
*/
static int getErrorCount(List<CommitValidationStatus> statuses) {
return statuses.stream().mapToInt(s -> s.getErrors().size()).sum();
private static final int EMAIL_ADDRESS_PARTS = 2;
private static final int DOMAIN_PARTS_MINIMUM = 2;
// division point where a character gets obfuscated in the email domain
private static final int OBFUSCATION_DIVISION_POINT = 2;
/**
* Made to count nested errors in a list of commit status objects.
*
* @param statuses the statuses to expand and count errors for
* @return the number of errors in the list of statuses
*/
static int getErrorCount(List<CommitValidationStatus> statuses) {
return statuses.stream().mapToInt(s -> s.getErrors().size()).sum();
}
/**
* Formats and flattens a list of statuses to a list of errors encountered while validation a set of commits.
*
* @param statuses a list of commit validation statuses to retrieve errors from
* @return a list of flattened errors, or an empty list if (none are found.
*/
static List<CommitValidationMessage> getValidationErrors(List<CommitValidationStatus> statuses) {
return statuses.stream().flatMap(s -> s.getErrors().stream()).toList();
}
/**
* Sorts list and retrieves the most recently modified status, and returns a human readable format of the time.
*
* @param statuses a list of commit validation statuses to retrieve a modification time from
* @return the most recent modification time for any of the passed statuses.
*/
static String getLastKnownValidationTime(List<CommitValidationStatus> statuses) {
CommitValidationStatus latestStatus = statuses
.stream()
.sorted((o1, o2) -> o2.getLastModified().compareTo(o1.getLastModified()))
.findFirst()
.orElse(null);
if (latestStatus == null) {
return "Unknown";
}
/**
* Formats and flattens a list of statuses to a list of errors encountered while validation a set of commits.
*
* @param statuses a list of commit validation statuses to retrieve errors from
* @return a list of flattened errors, or an empty list if (none are found.
*/
static List<CommitValidationMessage> getValidationErrors(List<CommitValidationStatus> statuses) {
return statuses.stream().flatMap(s -> s.getErrors().stream()).toList();
return latestStatus.getLastModified().format(DateTimeFormatter.RFC_1123_DATE_TIME);
}
/**
* Converts the status list to a list of email addresses that were associated with validated commits.
*
* @param statuses the list of commit statuses for the current validation.
* @return list of email addresses associated with valid requests
*/
static List<String> getUniquePassedMails(List<CommitValidationStatus> statuses) {
return statuses
.stream()
.filter(s -> s.getErrors().isEmpty())
.map(CommitValidationStatus::getUserMail)
.distinct()
.filter(StringUtils::isNotBlank)
.toList();
}
/**
* <p>
* Obfuscates an email for public consumption, showing the first letter of the email address, and the domain of the address for
* identification, and stripping out the rest of the address.
* </p>
*
* <p>
* <strong>Example:</strong> <br />
* Source: sample.address+123@eclipse.org <br />
* Output: sample.address+123@ecl*pse DOT org
* </p>
*
* @param email the address to obfuscate
* @return the obfuscated address, or empty string if (the string could not be parsed as an email address.
*/
public static String obfuscateEmail(String email) {
if (StringUtils.isBlank(email)) {
return "";
}
/**
* Sorts list and retrieves the most recently modified status, and returns a human readable format of the time.
*
* @param statuses a list of commit validation statuses to retrieve a modification time from
* @return the most recent modification time for any of the passed statuses.
*/
static String getLastKnownValidationTime(List<CommitValidationStatus> statuses) {
CommitValidationStatus latestStatus = statuses
.stream()
.sorted((o1, o2) -> o2.getLastModified().compareTo(o1.getLastModified()))
.findFirst()
.orElse(null);
if (latestStatus == null) {
return "Unknown";
}
return latestStatus.getLastModified().format(DateTimeFormatter.RFC_1123_DATE_TIME);
// split on the @ symbol
String[] emailParts = email.split("\\@");
if (emailParts.length != EMAIL_ADDRESS_PARTS) {
// valid emails will have 2 sections when split this way
return "";
}
/**
* Converts the status list to a list of email addresses that were associated with validated commits.
*
* @param statuses the list of commit statuses for the current validation.
* @return list of email addresses associated with valid requests
*/
static List<String> getUniquePassedMails(List<CommitValidationStatus> statuses) {
return statuses
.stream()
.filter(s -> s.getErrors().isEmpty())
.map(CommitValidationStatus::getUserMail)
.distinct()
.filter(StringUtils::isNotBlank)
.toList();
String[] domainParts = emailParts[1].split("\\.");
if (domainParts.length < DOMAIN_PARTS_MINIMUM) {
// emails should have at least 2 parts here
return "";
}
/**
* <p>
* Obfuscates an email for public consumption, showing the first letter of the email address, and the domain of the address for
* identification, and stripping out the rest of the address.
* </p>
*
* <p>
* <strong>Example:</strong> <br />
* Source: sample.address+123@eclipse.org <br />
* Output: sample.address+123@ecl*pse DOT org
* </p>
*
* @param email the address to obfuscate
* @return the obfuscated address, or empty string if (the string could not be parsed as an email address.
*/
public static String obfuscateEmail(String email) {
if (StringUtils.isBlank(email)) {
return "";
}
// split on the @ symbol
String[] emailParts = email.split("\\@");
if (emailParts.length != EMAIL_ADDRESS_PARTS) {
// valid emails will have 2 sections when split this way
return "";
}
String[] domainParts = emailParts[1].split("\\.");
if (domainParts.length < DOMAIN_PARTS_MINIMUM) {
// emails should have at least 2 parts here
return "";
}
// the index in the middle of the first domain part of the email address
int middleIndexDomain = Math.floorDiv(domainParts[0].length(), OBFUSCATION_DIVISION_POINT);
// build the obfuscated email address in the pattern defined in the block comment
StringBuilder sb = new StringBuilder();
sb.append(emailParts[0]);
sb.append("@");
sb.append(domainParts[0].substring(0, middleIndexDomain));
sb.append('*');
sb.append(domainParts[0].substring(middleIndexDomain + 1));
for (int i = 1; i < domainParts.length; i++) {
sb.append(" DOT ");
sb.append(domainParts[i]);
}
return sb.toString();
// the index in the middle of the first domain part of the email address
int middleIndexDomain = Math.floorDiv(domainParts[0].length(), OBFUSCATION_DIVISION_POINT);
// build the obfuscated email address in the pattern defined in the block comment
StringBuilder sb = new StringBuilder();
sb.append(emailParts[0]);
sb.append("@");
sb.append(domainParts[0].substring(0, middleIndexDomain));
sb.append('*');
sb.append(domainParts[0].substring(middleIndexDomain + 1));
for (int i = 1; i < domainParts.length; i++) {
sb.append(" DOT ");
sb.append(domainParts[i]);
}
/**
* Standardized conversion of error codes into messages to be consumed downstream.
*
* @param message the validation error to convert into a meaningful message
* @return the message string for the given validation error.
*/
static String getMessageForError(CommitValidationMessage message) {
String out = "";
if (message.getStatusCode() == APIStatusCode.ERROR_PROXY_PUSH.getValue()) {
out = String
.format("Committer does not have permission to push on behalf of another user (Legacy).%s",
EclipseQuteTemplateExtensions.getUserInfoForMessage(message));
} else if (message.getStatusCode() == APIStatusCode.ERROR_COMMITTER.getValue()) {
out = String
.format("Committer did not have a signed ECA on file.%s", EclipseQuteTemplateExtensions.getUserInfoForMessage(message));
} else if (message.getStatusCode() == APIStatusCode.ERROR_AUTHOR.getValue()) {
out = String
.format("Author did not have a signed ECA on file.%s", EclipseQuteTemplateExtensions.getUserInfoForMessage(message));
} else if (message.getStatusCode() == APIStatusCode.ERROR_COMMITTER_NOT_FOUND.getValue()) {
out = String
.format("Committer Eclipse account cannot be found.%s", EclipseQuteTemplateExtensions.getUserInfoForMessage(message));
} else if (message.getStatusCode() == APIStatusCode.ERROR_AUTHOR_NOT_FOUND.getValue()) {
out = String.format("Author Eclipse account cannot be found.%s", EclipseQuteTemplateExtensions.getUserInfoForMessage(message));
} else if (message.getStatusCode() == APIStatusCode.ERROR_SPEC_PROJECT.getValue()) {
out = String
.format("Committer does not have permission to commit on specification projects.%s",
EclipseQuteTemplateExtensions.getUserInfoForMessage(message));
} else if (message.getStatusCode() == APIStatusCode.ERROR_SIGN_OFF.getValue()) {
out = "Sign-off not detected in the commit message (Legacy).";
} else if (message.getStatusCode() == APIStatusCode.ERROR_DEFAULT.getValue()) {
out = "Request format/state error detected.";
} else {
out = "Unaccounted for error detected, please contact administrators.";
}
return out;
return sb.toString();
}
/**
* Standardized conversion of error codes into messages to be consumed downstream.
*
* @param message the validation error to convert into a meaningful message
* @return the message string for the given validation error.
*/
static String getMessageForError(CommitValidationMessage message) {
String out = "";
if (message.getStatusCode() == APIStatusCode.ERROR_PROXY_PUSH.getValue()) {
out = String
.format("Committer does not have permission to push on behalf of another user (Legacy).%s",
EclipseQuteTemplateExtensions.getUserInfoForMessage(message));
} else if (message.getStatusCode() == APIStatusCode.ERROR_COMMITTER.getValue()) {
out = String.format("Committer did not have a signed ECA on file.%s", EclipseQuteTemplateExtensions.getUserInfoForMessage(message));
} else if (message.getStatusCode() == APIStatusCode.ERROR_COMMITTER_BLOCKED.getValue()) {
out = String
.format("Committer has been blocked from Eclipse Foundation services.%s",
EclipseQuteTemplateExtensions.getUserInfoForMessage(message));
} else if (message.getStatusCode() == APIStatusCode.ERROR_AUTHOR.getValue()) {
out = String.format("Author did not have a signed ECA on file.%s", EclipseQuteTemplateExtensions.getUserInfoForMessage(message));
} else if (message.getStatusCode() == APIStatusCode.ERROR_AUTHOR_BLOCKED.getValue()) {
out = String
.format("Author has been blocked from Eclipse Foundation services.%s",
EclipseQuteTemplateExtensions.getUserInfoForMessage(message));
} else if (message.getStatusCode() == APIStatusCode.ERROR_COMMITTER_NOT_FOUND.getValue()) {
out = String.format("Committer Eclipse account cannot be found.%s", EclipseQuteTemplateExtensions.getUserInfoForMessage(message));
} else if (message.getStatusCode() == APIStatusCode.ERROR_AUTHOR_NOT_FOUND.getValue()) {
out = String.format("Author Eclipse account cannot be found.%s", EclipseQuteTemplateExtensions.getUserInfoForMessage(message));
} else if (message.getStatusCode() == APIStatusCode.ERROR_SPEC_PROJECT.getValue()) {
out = String
.format("Committer does not have permission to commit on specification projects.%s",
EclipseQuteTemplateExtensions.getUserInfoForMessage(message));
} else if (message.getStatusCode() == APIStatusCode.ERROR_SIGN_OFF.getValue()) {
out = "Sign-off not detected in the commit message (Legacy).";
} else if (message.getStatusCode() == APIStatusCode.ERROR_DEFAULT.getValue()) {
out = "Request format/state error detected.";
} else {
out = "Unaccounted for error detected, please contact administrators.";
}
/**
* Generate the info list stored with the validation message to be appended to the actual status message for more information.
*
* @param message the validation message being printed
* @return HTML containing the user details
*/
private static String getUserInfoForMessage(CommitValidationMessage message) {
StringBuilder sb = new StringBuilder();
sb.append("<ul><li>Email: ");
// switch on email depending on error code
sb
.append(EclipseQuteTemplateExtensions
.obfuscateEmail(
APIStatusCode.getValueForCode(message.getStatusCode()).isCommitterError() ? message.getCommitterEmail()
: message.getAuthorEmail()));
// only add a provider ID section if it is set
if (StringUtils.isNotBlank(message.getProviderId()) && message.getCommit().getProvider() != null) {
sb.append("</li><li>").append(message.getCommit().getProvider().getLegalName()).append(" ID: ");
sb.append(message.getProviderId());
}
sb.append("</li></ul>");
return sb.toString();
return out;
}
/**
* Generate the info list stored with the validation message to be appended to the actual status message for more information.
*
* @param message the validation message being printed
* @return HTML containing the user details
*/
private static String getUserInfoForMessage(CommitValidationMessage message) {
StringBuilder sb = new StringBuilder();
sb.append("<ul><li>Email: ");
// switch on email depending on error code
sb
.append(EclipseQuteTemplateExtensions
.obfuscateEmail(APIStatusCode.getValueForCode(message.getStatusCode()).isCommitterError() ? message.getCommitterEmail()
: message.getAuthorEmail()));
// only add a provider ID section if it is set
if (StringUtils.isNotBlank(message.getProviderId()) && message.getCommit().getProvider() != null) {
sb.append("</li><li>").append(message.getCommit().getProvider().getLegalName()).append(" ID: ");
sb.append(message.getProviderId());
}
sb.append("</li></ul>");
return sb.toString();
}
private EclipseQuteTemplateExtensions() {
private EclipseQuteTemplateExtensions() {
}
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment