Skip to content

Commit c9ea1f1

Browse files
committed
feat: add property imageRecommendation refactor to programmatically get brandingConfig and update README
1 parent bfaf296 commit c9ea1f1

File tree

6 files changed

+158
-194
lines changed

6 files changed

+158
-194
lines changed

src/main/java/io/github/guacsec/trustifyda/integration/report/BrandingConfig.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,4 +28,6 @@ public interface BrandingConfig {
2828
String exploreTitle();
2929

3030
String exploreDescription();
31+
32+
String imageRecommendation();
3133
}

src/main/java/io/github/guacsec/trustifyda/integration/report/ReportTemplate.java

Lines changed: 75 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@
2626
import org.apache.camel.Body;
2727
import org.apache.camel.Exchange;
2828
import org.apache.camel.ExchangeProperty;
29+
import org.eclipse.microprofile.config.Config;
30+
import org.eclipse.microprofile.config.ConfigProvider;
2931
import org.eclipse.microprofile.config.inject.ConfigProperty;
3032

3133
import com.fasterxml.jackson.core.JsonProcessingException;
@@ -58,9 +60,6 @@ public class ReportTemplate {
5860
@ConfigProperty(name = "telemetry.disabled", defaultValue = "false")
5961
Boolean disabled;
6062

61-
// Branding configuration
62-
@Inject Optional<BrandingConfig> brandingConfig;
63-
6463
@Inject ObjectMapper mapper;
6564

6665
public Map<String, Object> setVariables(
@@ -77,8 +76,8 @@ public Map<String, Object> setVariables(
7776
params.put("cveIssueTemplate", cveIssuePathRegex);
7877
params.put("imageMapping", getImageMapping());
7978
params.put("rhdaSource", rhdaSource);
80-
// Only include branding config if it's present
81-
brandingConfig.ifPresent(config -> params.put("brandingConfig", getBrandingConfigMap(config)));
79+
getBrandingConfig()
80+
.ifPresent(config -> params.put("brandingConfig", getBrandingConfigMap(config)));
8281
if (!disabled && writeKey.isPresent()) {
8382
params.put("userId", userId);
8483
params.put("anonymousId", anonymousId);
@@ -113,15 +112,86 @@ private String getImageMapping() throws JsonProcessingException {
113112
return objectWriter.writeValueAsString(urlMapping);
114113
}
115114

115+
private Optional<BrandingConfig> getBrandingConfig() {
116+
try {
117+
Config config = ConfigProvider.getConfig();
118+
return config
119+
.getOptionalValue("branding.display-name", String.class)
120+
.filter(displayName -> !displayName.isEmpty())
121+
.map(
122+
displayName ->
123+
new BrandingConfigImpl(
124+
displayName,
125+
config.getOptionalValue("branding.explore-url", String.class).orElse(""),
126+
config.getOptionalValue("branding.explore-title", String.class).orElse(""),
127+
config
128+
.getOptionalValue("branding.explore-description", String.class)
129+
.orElse(""),
130+
config
131+
.getOptionalValue("branding.image-recommendation", String.class)
132+
.orElse("")));
133+
} catch (Exception e) {
134+
return Optional.empty();
135+
}
136+
}
137+
116138
private Map<String, String> getBrandingConfigMap(BrandingConfig config) {
117139
Map<String, String> branding = new HashMap<>();
118140
branding.put("displayName", config.displayName());
119141
branding.put("exploreUrl", config.exploreUrl());
120142
branding.put("exploreTitle", config.exploreTitle());
121143
branding.put("exploreDescription", config.exploreDescription());
144+
branding.put("imageRecommendation", config.imageRecommendation());
122145
return branding;
123146
}
124147

148+
@RegisterForReflection
149+
private static class BrandingConfigImpl implements BrandingConfig {
150+
private final String displayName;
151+
private final String exploreUrl;
152+
private final String exploreTitle;
153+
private final String exploreDescription;
154+
private final String imageRecommendation;
155+
156+
public BrandingConfigImpl(
157+
String displayName,
158+
String exploreUrl,
159+
String exploreTitle,
160+
String exploreDescription,
161+
String imageRecommendation) {
162+
this.displayName = displayName;
163+
this.exploreUrl = exploreUrl;
164+
this.exploreTitle = exploreTitle;
165+
this.exploreDescription = exploreDescription;
166+
this.imageRecommendation = imageRecommendation;
167+
}
168+
169+
@Override
170+
public String displayName() {
171+
return displayName;
172+
}
173+
174+
@Override
175+
public String exploreUrl() {
176+
return exploreUrl;
177+
}
178+
179+
@Override
180+
public String exploreTitle() {
181+
return exploreTitle;
182+
}
183+
184+
@Override
185+
public String exploreDescription() {
186+
return exploreDescription;
187+
}
188+
189+
@Override
190+
public String imageRecommendation() {
191+
return imageRecommendation;
192+
}
193+
}
194+
125195
@RegisterForReflection
126196
public static record IssueLinkFormatter(String issuePathRegex) {
127197

src/main/resources/freemarker/templates/generated/main.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

ui/BRANDING.md

Lines changed: 20 additions & 132 deletions
Original file line numberDiff line numberDiff line change
@@ -2,137 +2,6 @@
22

33
This project supports flexible branding through backend environment variables. The system uses **default** branding and allows you to override specific elements as needed.
44

5-
## Quick Start
6-
7-
### Using Predefined Profiles
8-
9-
**Default branding:**
10-
```bash
11-
# Default profile - no additional flags needed
12-
./mvnw quarkus:dev
13-
```
14-
15-
**Custom organization branding:**
16-
```bash
17-
# Example using a custom profile (e.g., myorg)
18-
./mvnw quarkus:dev -Dquarkus.profile=myorg
19-
```
20-
21-
### Using Environment Variables (Alternative)
22-
```bash
23-
# Start development server (branding controlled by backend environment variables)
24-
npm start
25-
```
26-
27-
### Production Build
28-
```bash
29-
# Build for production (branding controlled by backend environment variables)
30-
npm run build
31-
```
32-
33-
## How It Works
34-
35-
1. **Backend Configuration**: Java backend reads `BRANDING_XXX` environment variables
36-
2. **Runtime Injection**: Branding configuration is passed to the React app through `appData`
37-
3. **Component Usage**: React components read branding configuration from the app context
38-
4. **Default-First**: All defaults are set to standard values, specific brands override as needed
39-
40-
## Available Environment Variables
41-
42-
Configure branding by setting these environment variables for the Java backend:
43-
44-
```bash
45-
# Brand identity
46-
BRANDING_DISPLAY_NAME=Your Brand Name # Used for conditional logic and remediation title
47-
48-
# Explore section
49-
BRANDING_EXPLORE_URL=https://your-url.com # URL for "Take me there" button
50-
BRANDING_EXPLORE_TITLE=Your Explore Title # Title for explore section
51-
BRANDING_EXPLORE_DESCRIPTION=Your description text # Description text
52-
```
53-
54-
## Branding Logic
55-
56-
The system uses `displayName` for all branding decisions:
57-
58-
- **Custom organization branding**: Uses the provided `displayName` (e.g., "MyOrg" shows "MyOrg Remediations")
59-
- **Default branding**: Used when no custom branding is configured
60-
61-
## Icon System
62-
63-
The system uses a CSS-based icon override approach:
64-
65-
- **Default icon**: Built-in Trustify logo (PNG)
66-
- **Custom icons**: Organizations can override the default icon using CSS in their private projects
67-
68-
## Examples
69-
70-
### Method 1: Using Predefined Profile
71-
72-
**Default branding:**
73-
```bash
74-
# Default behavior (no profile needed)
75-
./mvnw quarkus:dev
76-
```
77-
78-
**Custom organization branding:**
79-
```bash
80-
# Example using a custom profile
81-
./mvnw quarkus:dev -Dquarkus.profile=myorg
82-
```
83-
84-
**Production builds with profiles:**
85-
```bash
86-
# Default production build
87-
./mvnw clean package
88-
89-
# Custom organization production build
90-
./mvnw clean package -Dquarkus.profile=myorg
91-
```
92-
93-
### Method 2: Using Environment Variables
94-
95-
**Default Configuration (no environment variables needed):**
96-
```bash
97-
# No environment variables needed - uses default Trustify branding
98-
./mvnw quarkus:dev
99-
```
100-
101-
**Custom Organization Configuration:**
102-
```bash
103-
export BRANDING_DISPLAY_NAME="MyOrg"
104-
export BRANDING_EXPLORE_URL="https://example.com/security-tools"
105-
export BRANDING_EXPLORE_TITLE="Learn about MyOrg Security"
106-
export BRANDING_EXPLORE_DESCRIPTION="Explore our comprehensive security analysis tools and vulnerability management platform."
107-
108-
./mvnw quarkus:dev
109-
```
110-
111-
## Backend Integration
112-
113-
The branding configuration is handled using Quarkus `@ConfigMapping`:
114-
115-
**BrandingConfig.java:**
116-
```java
117-
@ConfigMapping(prefix = "branding")
118-
public interface BrandingConfig {
119-
String displayName();
120-
String exploreUrl();
121-
String exploreTitle();
122-
String exploreDescription();
123-
}
124-
```
125-
126-
**ReportTemplate.java:**
127-
```java
128-
@Inject Optional<BrandingConfig> brandingConfig;
129-
130-
// Only include branding config if it's present
131-
brandingConfig.ifPresent(config -> params.put("brandingConfig", getBrandingConfigMap(config)));
132-
```
133-
134-
The configuration is then passed to the frontend via the `appData` object in the Freemarker template.
135-
1365
## Profile Configuration
1376

1387
The branding profiles are defined in `src/main/resources/application.properties`:
@@ -143,15 +12,19 @@ branding.display.name=Trustify
14312
branding.explore.url=https://guac.sh/trustify/
14413
branding.explore.title=Learn more about Trustify
14514
branding.explore.description=The Trustify project is a collection of software components that enables you to store and retrieve Software Bill of Materials (SBOMs), and advisory documents.
15+
branding.image.recommendation=
14616

14717
# Example: Custom organization branding profile
14818
%myorg.branding.display.name=MyOrg
14919
%myorg.branding.explore.url=https://example.com/security-tools
15020
%myorg.branding.explore.title=Learn about MyOrg Security
15121
%myorg.branding.explore.description=Explore our comprehensive security analysis tools and vulnerability management platform.
22+
%myorg.branding.image.recommendation=Custom container image recommendations for enhanced security.
15223
```
15324

154-
## Creating Custom Branding Profiles
25+
## Examples
26+
27+
### Method 1: Using Predefined Profile
15528

15629
To create a new branding profile for your organization:
15730

@@ -162,6 +35,7 @@ To create a new branding profile for your organization:
16235
%myorg.branding.explore.url=https://your-org.com/security
16336
%myorg.branding.explore.title=Learn about Your Org Security
16437
%myorg.branding.explore.description=Your custom description here.
38+
%myorg.branding.image.recommendation=Your custom container image recommendation text.
16539
```
16640

16741
2. **Use the profile** when running the application:
@@ -171,6 +45,19 @@ To create a new branding profile for your organization:
17145

17246
3. **Override icons in private projects** using CSS to provide custom organization icons
17347

48+
### Method 2: Using Environment Variables
49+
50+
**Custom Organization Configuration:**
51+
```bash
52+
export BRANDING_DISPLAY_NAME="MyOrg"
53+
export BRANDING_EXPLORE_URL="https://example.com/security-tools"
54+
export BRANDING_EXPLORE_TITLE="Learn about MyOrg Security"
55+
export BRANDING_EXPLORE_DESCRIPTION="Explore our comprehensive security analysis tools and vulnerability management platform."
56+
export BRANDING_IMAGE_RECOMMENDATION="Custom container image recommendations for enhanced security."
57+
58+
./mvnw quarkus:dev
59+
```
60+
17461
Environment variables will override profile settings if both are provided.
17562

17663
## Custom Icon Implementation
@@ -202,6 +89,7 @@ Add to `/src/main/resources/application.properties`:
20289
%myorg.branding.explore.url=https://myorg.com/security
20390
%myorg.branding.explore.title=Learn about MyOrg Security
20491
%myorg.branding.explore.description=Explore our comprehensive security analysis tools and vulnerability management platform.
92+
%myorg.branding.image.recommendation=Custom container image recommendations for enhanced security.
20593
```
20694

20795
**Step 4: Build with your changes**

ui/src/api/report.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ export interface BrandingConfig {
1818
exploreUrl: string;
1919
exploreTitle: string;
2020
exploreDescription: string;
21+
imageRecommendation: string;
2122
}
2223

2324
export interface ReportMap {

0 commit comments

Comments
 (0)