Skip to content

Commit e3c8484

Browse files
committed
feat: Enhance VcsRepoBindingRepository with slug-based lookup and improve token handling in ProjectService
1 parent 6dde76e commit e3c8484

3 files changed

Lines changed: 37 additions & 10 deletions

File tree

java-ecosystem/libs/core/src/main/java/org/rostilos/codecrow/core/persistence/repository/vcs/VcsRepoBindingRepository.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,15 @@ Optional<VcsRepoBinding> findByProviderAndExternalRepoIdWithDetails(
3838
@Param("externalRepoId") String externalRepoId
3939
);
4040

41+
@Query("SELECT b FROM VcsRepoBinding b " +
42+
"LEFT JOIN FETCH b.project " +
43+
"LEFT JOIN FETCH b.vcsConnection " +
44+
"WHERE b.provider = :provider AND b.externalRepoSlug = :repoSlug")
45+
Optional<VcsRepoBinding> findByProviderAndExternalRepoSlugWithDetails(
46+
@Param("provider") EVcsProvider provider,
47+
@Param("repoSlug") String repoSlug
48+
);
49+
4150
@Query("SELECT b FROM VcsRepoBinding b " +
4251
"LEFT JOIN FETCH b.project " +
4352
"WHERE b.vcsConnection.id = :connectionId")

java-ecosystem/services/pipeline-agent/src/main/java/org/rostilos/codecrow/pipelineagent/generic/webhookhandler/WebhookProjectResolver.java

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010
import org.slf4j.LoggerFactory;
1111
import org.springframework.stereotype.Service;
1212

13-
import java.security.GeneralSecurityException;
1413
import java.util.Optional;
1514

1615
/**
@@ -47,7 +46,20 @@ public WebhookProjectResolver(
4746
public Optional<Project> findProjectByExternalRepo(EVcsProvider provider, String externalRepoId) {
4847
log.debug("Looking up project for provider={}, externalRepoId={}", provider, externalRepoId);
4948

50-
return bindingRepository.findByProviderAndExternalRepoIdWithDetails(provider, externalRepoId)
49+
// Primary lookup by UUID-based external repo ID
50+
Optional<Project> result = bindingRepository.findByProviderAndExternalRepoIdWithDetails(provider, externalRepoId)
51+
.flatMap(binding -> {
52+
Long projectId = binding.getProject().getId();
53+
return projectRepository.findByIdWithFullDetails(projectId);
54+
});
55+
56+
if (result.isPresent()) {
57+
return result;
58+
}
59+
60+
// Fallback: try slug-based lookup for older bindings that stored slug as externalRepoId
61+
log.debug("UUID lookup failed, trying slug-based fallback for provider={}, repoId={}", provider, externalRepoId);
62+
return bindingRepository.findByProviderAndExternalRepoSlugWithDetails(provider, externalRepoId)
5163
.flatMap(binding -> {
5264
Long projectId = binding.getProject().getId();
5365
return projectRepository.findByIdWithFullDetails(projectId);
@@ -77,12 +89,17 @@ public boolean validateWebhookAuth(Project project, String authToken) {
7789
if (project.getAuthToken() == null || authToken == null) {
7890
return false;
7991
}
92+
String storedToken = project.getAuthToken();
93+
94+
// Try decrypting first (new encrypted tokens)
8095
try {
81-
String decryptedToken = tokenEncryptionService.decrypt(project.getAuthToken());
96+
String decryptedToken = tokenEncryptionService.decrypt(storedToken);
8297
return decryptedToken.equals(authToken);
83-
} catch (GeneralSecurityException e) {
84-
log.error("Failed to decrypt auth token for project {}", project.getId(), e);
85-
return false;
98+
} catch (Exception e) {
99+
// Decryption failed — token is likely stored as plaintext (legacy).
100+
// Fall back to direct comparison.
101+
log.debug("Token decryption failed for project {} — trying plaintext comparison", project.getId());
102+
return storedToken.equals(authToken);
86103
}
87104
}
88105

java-ecosystem/services/web-server/src/main/java/org/rostilos/codecrow/webserver/project/service/ProjectService.java

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1014,13 +1014,14 @@ private String generateWebhookUrl(EVcsProvider provider, Project project) {
10141014
String base = (urls.webhookBaseUrl() != null && !urls.webhookBaseUrl().isBlank())
10151015
? urls.webhookBaseUrl()
10161016
: urls.baseUrl();
1017-
// Decrypt the stored token to get the URL-safe plaintext for the webhook path
1017+
// Try decrypting the stored token; fall back to raw value for legacy plaintext tokens
10181018
String plainToken;
10191019
try {
10201020
plainToken = tokenEncryptionService.decrypt(project.getAuthToken());
1021-
} catch (GeneralSecurityException e) {
1022-
log.error("Failed to decrypt auth token for project {}", project.getId(), e);
1023-
throw new IllegalStateException("Cannot generate webhook URL: auth token decryption failed");
1021+
} catch (Exception e) {
1022+
// Token is likely already plaintext (legacy) — use as-is
1023+
log.debug("Token decryption failed for project {} — using raw token", project.getId());
1024+
plainToken = project.getAuthToken();
10241025
}
10251026
return base + "/api/webhooks/" + provider.getId() + "/" + plainToken;
10261027
}

0 commit comments

Comments
 (0)