feat: add allowed-users sender filtering for GitHub webhook

Only issues submitted by users in the allowed-users list are processed.
An empty or null list allows all senders (no filtering). Checks
sender.login from the webhook payload against the configured list.
This commit is contained in:
2026-06-01 16:30:46 +08:00
parent 8a9cf110af
commit 0530c1f633
3 changed files with 39 additions and 3 deletions
@@ -9,6 +9,7 @@ import com.fasterxml.jackson.databind.annotation.JsonNaming;
public record GitHubIssueRequest( public record GitHubIssueRequest(
String action, String action,
GitHubWebhookIssue issue, GitHubWebhookIssue issue,
GitHubWebhookRepository repository GitHubWebhookRepository repository,
GitHubWebhookSender sender
) { ) {
} }
@@ -0,0 +1,12 @@
package com.onixbyte.deltaforceguide.domain.dto;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.databind.PropertyNamingStrategies;
import com.fasterxml.jackson.databind.annotation.JsonNaming;
@JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class)
@JsonIgnoreProperties(ignoreUnknown = true)
public record GitHubWebhookSender(
String login
) {
}
@@ -1,11 +1,11 @@
package com.onixbyte.deltaforceguide.service; package com.onixbyte.deltaforceguide.service;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.onixbyte.deltaforceguide.domain.dto.AccessoryRequest; import com.onixbyte.deltaforceguide.domain.dto.AccessoryRequest;
import com.onixbyte.deltaforceguide.domain.dto.GitHubIssueRequest; import com.onixbyte.deltaforceguide.domain.dto.GitHubIssueRequest;
import com.onixbyte.deltaforceguide.domain.dto.ModificationRequest; import com.onixbyte.deltaforceguide.domain.dto.ModificationRequest;
import com.onixbyte.deltaforceguide.domain.dto.TuningRequest; import com.onixbyte.deltaforceguide.domain.dto.TuningRequest;
import com.onixbyte.deltaforceguide.manager.ModificationManager; import com.onixbyte.deltaforceguide.manager.ModificationManager;
import com.onixbyte.deltaforceguide.manager.WebhookManager;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.core.RedisTemplate;
@@ -29,20 +29,30 @@ public class WebhookService {
private final ModificationManager modificationManager; private final ModificationManager modificationManager;
private final RedisTemplate<String, Object> redisTemplate; private final RedisTemplate<String, Object> redisTemplate;
private final WebhookManager webhookManager;
private final Yaml yaml; private final Yaml yaml;
public WebhookService( public WebhookService(
ModificationManager modificationManager, ModificationManager modificationManager,
RedisTemplate<String, Object> redisTemplate RedisTemplate<String, Object> redisTemplate,
WebhookManager webhookManager
) { ) {
this.modificationManager = modificationManager; this.modificationManager = modificationManager;
this.redisTemplate = redisTemplate; this.redisTemplate = redisTemplate;
this.webhookManager = webhookManager;
this.yaml = new Yaml(); this.yaml = new Yaml();
} }
public void processIssueEvent(GitHubIssueRequest request) { public void processIssueEvent(GitHubIssueRequest request) {
var issue = request.issue(); var issue = request.issue();
var repository = request.repository(); var repository = request.repository();
var sender = request.sender();
if (!isAllowedSender(sender)) {
log.info("Issue #{} sender={} not in allowed-users, skipping",
issue.number(), sender != null ? sender.login() : "null");
return;
}
if (!hasTriggerLabel(issue.labels())) { if (!hasTriggerLabel(issue.labels())) {
log.debug("Issue #{} lacks trigger label, skipping", issue.number()); log.debug("Issue #{} lacks trigger label, skipping", issue.number());
@@ -155,6 +165,19 @@ public class WebhookService {
return new ArrayList<>(); return new ArrayList<>();
} }
private boolean isAllowedSender(
com.onixbyte.deltaforceguide.domain.dto.GitHubWebhookSender sender
) {
var allowedUsers = webhookManager.github().allowedUsers();
if (allowedUsers == null || allowedUsers.isEmpty()) {
return true;
}
if (sender == null || sender.login() == null) {
return false;
}
return allowedUsers.contains(sender.login());
}
private boolean hasTriggerLabel(List<com.onixbyte.deltaforceguide.domain.dto.GitHubWebhookLabel> labels) { private boolean hasTriggerLabel(List<com.onixbyte.deltaforceguide.domain.dto.GitHubWebhookLabel> labels) {
if (labels == null) { if (labels == null) {
return false; return false;