Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions src/main/java/org/hibernate/infra/replicate/jira/JiraConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -253,6 +253,20 @@ interface UserValueMapping extends ValueMapping {
* Jira.
*/
Optional<String> notMappedAssignee();

/**
* Allows specifying an URL template that will be passed exactly 1 argument
* (mapped user value). E.g. a template can look like
* {@code https://my-jira-server/secure/ViewProfile.jspa?name={arg1}}, where
* {@code arg1} is the mapped user value from {@link #mapping()}. If not
* specified the link to the upstream profile will be created with a template of
* {@code https://my-upstream-jira-server/jira/people/{arg1}}, where
* {@code arg1} is the original user id i.e. the {@link #mapping() mapping key}.
* <p>
* Note, this profile URL only applies to the profiles that have a defined
* {@link #mapping() mapping}.
*/
Optional<String> profileUrl();
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -194,10 +194,10 @@ public void registerManagementRoutes(@Observes ManagementInterface mi) {
});
rc.end();
});
mi.router().post("/sync/issues/query").consumes(MediaType.APPLICATION_JSON).blockingHandler(rc -> {
JsonObject request = rc.body().asJsonObject();
String project = request.getString("project");
String query = request.getString("query");
mi.router().get("/sync/issues/query/full/:project").blockingHandler(rc -> {
// syncs issue with comments, links etc.
String project = rc.pathParam("project");
String query = rc.queryParam("query").getFirst();

HandlerProjectContext context = contextPerProject.get(project);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
import org.hibernate.infra.replicate.jira.service.jira.model.rest.JiraComment;
import org.hibernate.infra.replicate.jira.service.jira.model.rest.JiraComments;
import org.hibernate.infra.replicate.jira.service.jira.model.rest.JiraIssue;
import org.hibernate.infra.replicate.jira.service.jira.model.rest.JiraTextContent;
import org.hibernate.infra.replicate.jira.service.reporting.ReportingConfig;

public class JiraCommentUpsertEventHandler extends JiraCommentEventHandler {
Expand Down Expand Up @@ -57,12 +56,12 @@ private JiraComment prepareComment(JiraIssue issue, JiraComment source) {

private String prepareCommentQuote(JiraIssue issue, JiraComment comment) {
URI jiraCommentUri = createJiraCommentUri(issue, comment);
URI jiraUserUri = createJiraUserUri(comment.self, comment.author);
UserData userData = userData(comment.self, comment.author, "the user %s");
String content = """
{quote}This [comment|%s] was posted by the [user %s|%s].{quote}
{quote}This [comment|%s] was posted by [%s|%s].{quote}


""".formatted(jiraCommentUri, JiraTextContent.userIdPart(comment.author), jiraUserUri);
""".formatted(jiraCommentUri, userData.name(), userData.uri());
return truncateContent(content);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import org.hibernate.infra.replicate.jira.service.jira.model.rest.JiraComment;
import org.hibernate.infra.replicate.jira.service.jira.model.rest.JiraIssue;
import org.hibernate.infra.replicate.jira.service.jira.model.rest.JiraSimpleObject;
import org.hibernate.infra.replicate.jira.service.jira.model.rest.JiraTextContent;
import org.hibernate.infra.replicate.jira.service.jira.model.rest.JiraUser;
import org.hibernate.infra.replicate.jira.service.reporting.FailureCollector;
import org.hibernate.infra.replicate.jira.service.reporting.ReportingConfig;
Expand Down Expand Up @@ -133,6 +134,38 @@ protected Optional<String> user(JiraUser sourceUser) {
userId -> context.projectGroup().users().mapping().get(sourceUser.accountId)));
}

protected UserData userData(URI someUpstreamUri, JiraUser user) {
return userData(someUpstreamUri, user, "user %s");
}

protected UserData userData(URI someUpstreamUri, JiraUser user, String unmappedUserPattern) {
if (user == null) {
return null;
}
Optional<String> mappedUser = user(user);
URI jiraUserUri;
String userName;
if (mappedUser.isPresent()) {
// means it is one of the users that we've mapped so we would want to point it
// to the user on the "downstream" side and also add a name:
Optional<String> template = context.projectGroup().users().profileUrl();
if (template.isPresent()) {
jiraUserUri = UriBuilder.fromUri(template.get()).build(mappedUser.get());
} else {
jiraUserUri = createJiraUserUri(someUpstreamUri, user);
}
// NOTE: we are using the upstream username here, so that we do not make an
// extra call to get the downstream name. We probably can do that once at the
// start and cache it, but for now this should be a "good-enough-approximation".
userName = user.displayName;

} else {
jiraUserUri = createJiraUserUri(someUpstreamUri, user);
userName = unmappedUserPattern.formatted(JiraTextContent.userIdPart(user));
}
return new UserData(userName, jiraUserUri);
}

private static Map<String, String> createMapping(List<JiraSimpleObject> source,
List<JiraSimpleObject> destination) {
Map<String, String> mapping = new HashMap<>();
Expand Down Expand Up @@ -189,4 +222,7 @@ protected String toDestinationKey(String key) {
}

public abstract String toString();

protected record UserData(String name, URI uri) {
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
import org.hibernate.infra.replicate.jira.service.jira.model.rest.JiraIssueLink;
import org.hibernate.infra.replicate.jira.service.jira.model.rest.JiraRemoteLink;
import org.hibernate.infra.replicate.jira.service.jira.model.rest.JiraSimpleObject;
import org.hibernate.infra.replicate.jira.service.jira.model.rest.JiraTextContent;
import org.hibernate.infra.replicate.jira.service.jira.model.rest.JiraTransition;
import org.hibernate.infra.replicate.jira.service.jira.model.rest.JiraUser;
import org.hibernate.infra.replicate.jira.service.reporting.ReportingConfig;
Expand Down Expand Up @@ -161,8 +160,10 @@ protected Optional<JiraIssueLink> prepareParentLink(String destinationKey, JiraI

private String prepareDescriptionQuote(JiraIssue issue) {
URI issueUri = createJiraIssueUri(issue);
URI reporterUri = createJiraUserUri(issue.self, issue.fields.reporter);
URI assigneeUri = createJiraUserUri(issue.self, issue.fields.assignee);

UserData assignee = userData(issue.self, issue.fields.assignee);
UserData reporter = userData(issue.self, issue.fields.reporter);

return """
{quote}This issue is created as a copy of [%s|%s].

Expand All @@ -172,12 +173,8 @@ private String prepareDescriptionQuote(JiraIssue issue) {


""".formatted(issue.key, issueUri,
assigneeUri == null
? " Unassigned"
: "[user %s|%s]".formatted(JiraTextContent.userIdPart(issue.fields.assignee), assigneeUri),
reporterUri == null
? " Unknown"
: "[user %s|%s]".formatted(JiraTextContent.userIdPart(issue.fields.reporter), reporterUri));
assignee == null ? " Unassigned" : "[%s|%s]".formatted(assignee.name(), assignee.uri()),
reporter == null ? " Unknown" : "[%s|%s]".formatted(reporter.name(), reporter.uri()));
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import org.jboss.resteasy.reactive.server.ServerRequestFilter;
import org.jboss.resteasy.reactive.server.WithFormRead;

import io.quarkus.logging.Log;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Inject;
import jakarta.ws.rs.container.ContainerRequestContext;
Expand Down Expand Up @@ -63,13 +64,15 @@ public Response checkSignature(ContainerRequestContext requestContext) throws IO
String signature = requestContext.getHeaderString("x-hub-signature");

if (signature == null || !requestContext.hasEntity()) {
Log.warnf("Rejecting a web hook event because of the missing signature. Posted to %s", path);
return Response.status(401).entity("Invalid request. Missing x-hub-signature header.").build();
}
try (InputStream entityStream = requestContext.getEntityStream()) {
byte[] payload = entityStream.readAllBytes();

final String calculatedSignature = sign(mac, payload);
if (!calculatedSignature.equals(signature)) {
Log.warnf("Rejecting a web hook event because of the signature mismatch. Posted to %s", path);
return Response.status(401).entity("Signatures do not match.").build();
}
requestContext.setEntityStream(new ByteArrayInputStream(payload));
Expand Down
Loading