Skip to content

Commit 096728d

Browse files
authored
fix(integrations): add fallback for missing catalog connector icons (#6474)
1 parent 6bcd87f commit 096728d

11 files changed

Lines changed: 159 additions & 22 deletions

File tree

.github/skills/review-code/SKILL.md

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,17 @@ grep -rn "TenantBase\|tenant_id\|TenantContext" --include="*.java" $(git diff --
9898
git diff --name-only HEAD~1 | grep -E "\.tsx$|\.ts$" | head -10
9999
```
100100

101-
## Step 8 — Compile review
101+
## Step 8 — Check common anti-patterns (learned from reviews)
102+
103+
Apply these checks based on past review feedback:
104+
105+
- **Root cause vs workaround**: If a bug is backend-originated, don't add frontend workarounds (onError handlers, fallback states). Fix the root cause in the correct layer.
106+
- **String/value duplication**: When introducing new methods that share data with existing methods (e.g., logo filenames, config keys), extract the shared value to a private method or constant — never compute the same formatted string in multiple places.
107+
- **Non-critical operations**: Startup operations that interact with external services (MinIO, S3, etc.) for non-critical assets (logos, thumbnails) should be best-effort: wrap in try-catch with `log.warn` so failures don't block application startup.
108+
- **Test proportionality**: Don't require tests for small mechanical changes (1-line additions, parameter threading). Tests should be proportionate to the risk and complexity of the change.
109+
- **Pre-existing issues**: Don't fix unrelated pre-existing issues (e.g., alt text, parameter naming) in a bug fix PR. Track them as follow-up.
110+
111+
## Step 9 — Compile review
102112

103113
Generate the Code Review Summary following the output format
104114
defined in `code-reviewer.agent.md`.

openaev-api/src/main/java/io/openaev/integration/IntegrationFactory.java

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,29 @@ public abstract class IntegrationFactory {
2525

2626
protected abstract String getClassName();
2727

28+
/**
29+
* Ensures the catalog logo exists in MinIO. Called on every startup (best-effort), even when the
30+
* catalog entry already exists in the database. Override in subclasses that upload a logo during
31+
* {@link #insertCatalogEntry()}.
32+
*
33+
* <p>Default implementation is a no-op for factories that do not manage a catalog logo (e.g.
34+
* built-in executors).
35+
*/
36+
protected void ensureCatalogLogo() throws Exception {
37+
// no-op by default
38+
}
39+
2840
@Transactional(rollbackFor = Exception.class)
2941
public void initialise() throws Exception {
3042
String className = this.getClassName();
3143
if (catalogConnectorService.findByFactoryClassName(className).isEmpty()) {
3244
insertCatalogEntry();
45+
} else {
46+
try {
47+
ensureCatalogLogo();
48+
} catch (Exception e) {
49+
log.warn("Failed to ensure catalog logo for {}: {}", className, e.getMessage());
50+
}
3351
}
3452

3553
runMigrations();

openaev-api/src/main/java/io/openaev/integration/impl/executors/caldera/CalderaExecutorIntegrationFactory.java

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -83,13 +83,26 @@ protected void runMigrations() throws Exception {
8383
calderaExecutorConfigurationMigration.migrate();
8484
}
8585

86+
private String getLogoFilename() {
87+
return "%s-logo.png".formatted(CALDERA_EXECUTOR_TYPE);
88+
}
89+
8690
@Override
87-
protected void insertCatalogEntry() throws Exception {
88-
String logoFilename = "%s-logo.png".formatted(CALDERA_EXECUTOR_TYPE);
91+
protected void ensureCatalogLogo() throws Exception {
92+
ensureCatalogLogo(getLogoFilename());
93+
}
94+
95+
private void ensureCatalogLogo(String logoFilename) throws Exception {
8996
fileService.uploadCatalogLogo(
9097
FileService.CONNECTORS_LOGO_PATH,
9198
logoFilename,
9299
getClass().getResourceAsStream("/img/icon-caldera.png"));
100+
}
101+
102+
@Override
103+
protected void insertCatalogEntry() throws Exception {
104+
String logoFilename = getLogoFilename();
105+
ensureCatalogLogo(logoFilename);
93106
CatalogConnector connector = new CatalogConnector();
94107
connector.setTitle("Caldera Executor");
95108
connector.setSlug(CALDERA_EXECUTOR_TYPE);

openaev-api/src/main/java/io/openaev/integration/impl/executors/crowdstrike/CrowdStrikeExecutorIntegrationFactory.java

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -86,13 +86,26 @@ protected void runMigrations() throws Exception {
8686
crowdStrikeExecutorConfigurationMigration.migrate();
8787
}
8888

89+
private String getLogoFilename() {
90+
return "%s-logo.png".formatted(CROWDSTRIKE_EXECUTOR_TYPE);
91+
}
92+
8993
@Override
90-
protected void insertCatalogEntry() throws Exception {
91-
String logoFilename = "%s-logo.png".formatted(CROWDSTRIKE_EXECUTOR_TYPE);
94+
protected void ensureCatalogLogo() throws Exception {
95+
ensureCatalogLogo(getLogoFilename());
96+
}
97+
98+
private void ensureCatalogLogo(String logoFilename) throws Exception {
9299
fileService.uploadCatalogLogo(
93100
FileService.CONNECTORS_LOGO_PATH,
94101
logoFilename,
95102
getClass().getResourceAsStream("/img/icon-crowdstrike.png"));
103+
}
104+
105+
@Override
106+
protected void insertCatalogEntry() throws Exception {
107+
String logoFilename = getLogoFilename();
108+
ensureCatalogLogo(logoFilename);
96109
CatalogConnector connector = new CatalogConnector();
97110
connector.setTitle("CrowdStrike Executor");
98111
connector.setSlug(CROWDSTRIKE_EXECUTOR_TYPE);

openaev-api/src/main/java/io/openaev/integration/impl/executors/paloaltocortex/PaloAltoCortexExecutorIntegrationFactory.java

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -80,13 +80,26 @@ protected void runMigrations() throws Exception {
8080
// No
8181
}
8282

83+
private String getLogoFilename() {
84+
return "%s-logo.png".formatted(PALOALTOCORTEX_EXECUTOR_TYPE);
85+
}
86+
8387
@Override
84-
protected void insertCatalogEntry() throws Exception {
85-
String logoFilename = "%s-logo.png".formatted(PALOALTOCORTEX_EXECUTOR_TYPE);
88+
protected void ensureCatalogLogo() throws Exception {
89+
ensureCatalogLogo(getLogoFilename());
90+
}
91+
92+
private void ensureCatalogLogo(String logoFilename) throws Exception {
8693
fileService.uploadCatalogLogo(
8794
FileService.CONNECTORS_LOGO_PATH,
8895
logoFilename,
8996
getClass().getResourceAsStream("/img/icon-paloaltocortex.png"));
97+
}
98+
99+
@Override
100+
protected void insertCatalogEntry() throws Exception {
101+
String logoFilename = getLogoFilename();
102+
ensureCatalogLogo(logoFilename);
90103
CatalogConnector connector = new CatalogConnector();
91104
connector.setTitle("Palo Alto Cortex Executor");
92105
connector.setSlug(PALOALTOCORTEX_EXECUTOR_TYPE);

openaev-api/src/main/java/io/openaev/integration/impl/executors/sentinelone/SentinelOneExecutorIntegrationFactory.java

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -84,13 +84,26 @@ protected void runMigrations() throws Exception {
8484
sentinelOneExecutorConfigurationMigration.migrate();
8585
}
8686

87+
private String getLogoFilename() {
88+
return "%s-logo.png".formatted(SENTINELONE_EXECUTOR_TYPE);
89+
}
90+
8791
@Override
88-
protected void insertCatalogEntry() throws Exception {
89-
String logoFilename = "%s-logo.png".formatted(SENTINELONE_EXECUTOR_TYPE);
92+
protected void ensureCatalogLogo() throws Exception {
93+
ensureCatalogLogo(getLogoFilename());
94+
}
95+
96+
private void ensureCatalogLogo(String logoFilename) throws Exception {
9097
fileService.uploadCatalogLogo(
9198
FileService.CONNECTORS_LOGO_PATH,
9299
logoFilename,
93100
getClass().getResourceAsStream("/img/icon-sentinelone.png"));
101+
}
102+
103+
@Override
104+
protected void insertCatalogEntry() throws Exception {
105+
String logoFilename = getLogoFilename();
106+
ensureCatalogLogo(logoFilename);
94107
CatalogConnector connector = new CatalogConnector();
95108
connector.setTitle("SentinelOne Executor");
96109
connector.setSlug(SENTINELONE_EXECUTOR_TYPE);

openaev-api/src/main/java/io/openaev/integration/impl/executors/tanium/TaniumExecutorIntegrationFactory.java

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -87,13 +87,26 @@ protected void runMigrations() throws Exception {
8787
taniumExecutorConfigurationMigration.migrate();
8888
}
8989

90+
private String getLogoFilename() {
91+
return "%s-logo.png".formatted(TANIUM_EXECUTOR_TYPE);
92+
}
93+
9094
@Override
91-
protected void insertCatalogEntry() throws Exception {
92-
String logoFilename = "%s-logo.png".formatted(TANIUM_EXECUTOR_TYPE);
95+
protected void ensureCatalogLogo() throws Exception {
96+
ensureCatalogLogo(getLogoFilename());
97+
}
98+
99+
private void ensureCatalogLogo(String logoFilename) throws Exception {
93100
fileService.uploadCatalogLogo(
94101
FileService.CONNECTORS_LOGO_PATH,
95102
logoFilename,
96103
getClass().getResourceAsStream("/img/icon-tanium.png"));
104+
}
105+
106+
@Override
107+
protected void insertCatalogEntry() throws Exception {
108+
String logoFilename = getLogoFilename();
109+
ensureCatalogLogo(logoFilename);
97110
CatalogConnector connector = new CatalogConnector();
98111
connector.setTitle("Tanium Executor");
99112
connector.setSlug(TANIUM_EXECUTOR_TYPE);

openaev-api/src/main/java/io/openaev/integration/impl/injectors/opencti/OpenCTIInjectorIntegrationFactory.java

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -79,13 +79,26 @@ protected void runMigrations() throws Exception {
7979
openctiInjectorConfigurationMigration.migrate();
8080
}
8181

82+
private String getLogoFilename() {
83+
return "%s-logo.png".formatted(openCTIContract.TYPE);
84+
}
85+
8286
@Override
83-
protected void insertCatalogEntry() throws Exception {
84-
String logoFilename = "%s-logo.png".formatted(openCTIContract.TYPE);
87+
protected void ensureCatalogLogo() throws Exception {
88+
ensureCatalogLogo(getLogoFilename());
89+
}
90+
91+
private void ensureCatalogLogo(String logoFilename) throws Exception {
8592
fileService.uploadCatalogLogo(
8693
FileService.CONNECTORS_LOGO_PATH,
8794
logoFilename,
8895
getClass().getResourceAsStream("/img/icon-opencti.png"));
96+
}
97+
98+
@Override
99+
protected void insertCatalogEntry() throws Exception {
100+
String logoFilename = getLogoFilename();
101+
ensureCatalogLogo(logoFilename);
89102
CatalogConnector connector = new CatalogConnector();
90103
connector.setTitle(OPENCTI_INJECTOR_NAME);
91104
connector.setSlug(openCTIContract.TYPE);

openaev-api/src/main/java/io/openaev/integration/impl/injectors/ovh/OvhInjectorIntegrationFactory.java

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -75,14 +75,27 @@ protected void runMigrations() throws Exception {
7575
ovhInjectorConfigurationMigration.migrate();
7676
}
7777

78+
private String getLogoFilename() {
79+
return "%s-logo.png".formatted(ovhSmsContract.getType());
80+
}
81+
7882
@Override
79-
protected void insertCatalogEntry() throws Exception {
80-
CatalogConnector connector = new CatalogConnector();
81-
String logoFilename = "%s-logo.png".formatted(ovhSmsContract.getType());
83+
protected void ensureCatalogLogo() throws Exception {
84+
ensureCatalogLogo(getLogoFilename());
85+
}
86+
87+
private void ensureCatalogLogo(String logoFilename) throws Exception {
8288
fileService.uploadCatalogLogo(
8389
FileService.CONNECTORS_LOGO_PATH,
8490
logoFilename,
8591
getClass().getResourceAsStream("/img/icon-ovh-sms.png"));
92+
}
93+
94+
@Override
95+
protected void insertCatalogEntry() throws Exception {
96+
String logoFilename = getLogoFilename();
97+
ensureCatalogLogo(logoFilename);
98+
CatalogConnector connector = new CatalogConnector();
8699
connector.setTitle("OVHCloud SMS Platform");
87100
connector.setSlug(ovhSmsContract.getType());
88101
connector.setLogoUrl(logoFilename);

openaev-api/src/test/java/io/openaev/integration/local_fixtures/factory_throws/TestIntegrationFactoryInitThrows.java

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -51,13 +51,22 @@ protected void runMigrations() throws Exception {
5151
throw new RuntimeException("%s: deliberate throw!".formatted(this.getClassName()));
5252
}
5353

54+
private String getLogoFilename() {
55+
return "%s-logo.png".formatted(getClassName());
56+
}
57+
5458
@Override
55-
protected void insertCatalogEntry() throws Exception {
56-
String logoFilename = "%s-logo.png".formatted(getClassName());
59+
protected void ensureCatalogLogo() throws Exception {
5760
fileService.uploadCatalogLogo(
5861
FileService.CONNECTORS_LOGO_PATH,
59-
logoFilename,
62+
getLogoFilename(),
6063
getClass().getResourceAsStream("/img/icon-default.png"));
64+
}
65+
66+
@Override
67+
protected void insertCatalogEntry() throws Exception {
68+
ensureCatalogLogo();
69+
String logoFilename = getLogoFilename();
6170
CatalogConnector connector = new CatalogConnector();
6271
connector.setTitle("Test Integration Init Throws");
6372
connector.setSlug(getClassName());

0 commit comments

Comments
 (0)