Skip to content

Commit f6d70a9

Browse files
authored
Merge branch 'main' into feature/search_acl
2 parents 7ea9092 + 3c0cd73 commit f6d70a9

File tree

21 files changed

+122
-33
lines changed

21 files changed

+122
-33
lines changed

.github/dependabot.yml

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,23 @@ updates:
1414
- "type/dependencies"
1515
- "scope/backend"
1616

17+
- package-ecosystem: docker
18+
directory: "/api"
19+
schedule:
20+
interval: weekly
21+
time: "10:00"
22+
timezone: Europe/London
23+
reviewers:
24+
- "kafbat/backend"
25+
open-pull-requests-limit: 10
26+
ignore:
27+
- dependency-name: "azul/zulu-openjdk-alpine"
28+
# Limit dependabot pull requests to minor Java upgrades
29+
update-types: ["version-update:semver-major"]
30+
labels:
31+
- "type/dependencies"
32+
- "scope/backend"
33+
1734
- package-ecosystem: npm
1835
directory: "/frontend"
1936
schedule:

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ We extend our gratitude to Provectus for their past support in groundbreaking wo
5050
* **View Consumer Groups** — view per-partition parked offsets, combined and per-partition lag
5151
* **Browse Messages** — browse messages with JSON, plain text, and Avro encoding
5252
* **Dynamic Topic Configuration** — create and configure new topics with dynamic configuration
53-
* **Configurable Authentification**[secure](https://ui.docs.kafbat.io/configuration/authentication) your installation with optional Github/Gitlab/Google OAuth 2.0
53+
* **Configurable Authentication**[secure](https://ui.docs.kafbat.io/configuration/authentication) your installation with optional Github/Gitlab/Google OAuth 2.0
5454
* **Custom serialization/deserialization plugins** - [use](https://ui.docs.kafbat.io/configuration/serialization-serde) a ready-to-go serde for your data like AWS Glue or Smile, or code your own!
5555
* **Role based access control** - [manage permissions](https://ui.docs.kafbat.io/configuration/rbac-role-based-access-control) to access the UI with granular precision
5656
* **Data masking** - [obfuscate](https://ui.docs.kafbat.io/configuration/data-masking) sensitive data in topic messages

api/Dockerfile

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
1-
FROM azul/zulu-openjdk-alpine:17.0.11-jre-headless
1+
# The tag is ignored when a sha is included but the reason to add it are:
2+
# 1. Self Documentation: It is difficult to find out what the expected tag is given a sha alone
3+
# 2. Helps dependabot during discovery of upgrades
4+
FROM azul/zulu-openjdk-alpine:17-jre-headless-latest@sha256:af4df00adaec356d092651af50d9e80fd179f96722d267e79acb564aede10fda
25

36
RUN apk add --no-cache \
47
# snappy codec

api/pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@
9797
<dependency>
9898
<groupId>com.azure</groupId>
9999
<artifactId>azure-identity</artifactId>
100-
<version>1.13.3</version>
100+
<version>1.14.2</version>
101101
<exclusions>
102102
<exclusion>
103103
<groupId>io.netty</groupId>

api/src/main/java/io/kafbat/ui/config/auth/OAuthSecurityConfig.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
import java.util.Map;
99
import java.util.Optional;
1010
import lombok.RequiredArgsConstructor;
11-
import lombok.extern.log4j.Log4j2;
11+
import lombok.extern.slf4j.Slf4j;
1212
import org.jetbrains.annotations.Nullable;
1313
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
1414
import org.springframework.boot.autoconfigure.security.oauth2.client.OAuth2ClientProperties;
@@ -41,7 +41,7 @@
4141
@EnableWebFluxSecurity
4242
@EnableReactiveMethodSecurity
4343
@RequiredArgsConstructor
44-
@Log4j2
44+
@Slf4j
4545
public class OAuthSecurityConfig extends AbstractAuthSecurityConfig {
4646

4747
private final OAuthProperties properties;

api/src/main/java/io/kafbat/ui/controller/MessagesController.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,10 +118,11 @@ public Mono<ResponseEntity<Flux<TopicMessageEventDTO>>> getTopicMessagesV2(Strin
118118
if (cursor != null) {
119119
messagesFlux = messagesService.loadMessages(getCluster(clusterName), topicName, cursor);
120120
} else {
121+
var pollingMode = mode == null ? PollingModeDTO.LATEST : mode;
121122
messagesFlux = messagesService.loadMessages(
122123
getCluster(clusterName),
123124
topicName,
124-
ConsumerPosition.create(checkNotNull(mode), checkNotNull(topicName), partitions, timestamp, offset),
125+
ConsumerPosition.create(pollingMode, checkNotNull(topicName), partitions, timestamp, offset),
125126
stringFilter,
126127
smartFilterId,
127128
limit,

api/src/main/java/io/kafbat/ui/emitter/MessageFilters.java

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,23 @@ public static Predicate<TopicMessageDTO> noop() {
5252

5353
public static Predicate<TopicMessageDTO> containsStringFilter(String string) {
5454
return msg -> StringUtils.contains(msg.getKey(), string)
55-
|| StringUtils.contains(msg.getContent(), string);
55+
|| StringUtils.contains(msg.getContent(), string) || headersContains(msg, string);
56+
}
57+
58+
private static boolean headersContains(TopicMessageDTO msg, String searchString) {
59+
final var headers = msg.getHeaders();
60+
61+
if (headers == null) {
62+
return false;
63+
}
64+
65+
for (final var entry : headers.entrySet()) {
66+
if (StringUtils.contains(entry.getKey(), searchString) || StringUtils.contains(entry.getValue(), searchString)) {
67+
return true;
68+
}
69+
}
70+
71+
return false;
5672
}
5773

5874
public static Predicate<TopicMessageDTO> celScriptFilter(String script) {

api/src/main/java/io/kafbat/ui/model/rbac/Role.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package io.kafbat.ui.model.rbac;
22

3+
import com.google.common.base.Preconditions;
34
import java.util.List;
45
import lombok.Data;
56

@@ -12,6 +13,7 @@ public class Role {
1213
List<Permission> permissions;
1314

1415
public void validate() {
16+
Preconditions.checkArgument(!clusters.isEmpty(), "Role clusters cannot be empty");
1517
permissions.forEach(Permission::transform);
1618
permissions.forEach(Permission::validate);
1719
}

api/src/main/java/io/kafbat/ui/serdes/ProducerRecordCreator.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ public ProducerRecord<byte[], byte[]> create(String topic,
3131

3232
private Iterable<Header> createHeaders(Map<String, String> clientHeaders) {
3333
RecordHeaders headers = new RecordHeaders();
34-
clientHeaders.forEach((k, v) -> headers.add(new RecordHeader(k, v.getBytes())));
34+
clientHeaders.forEach((k, v) -> headers.add(new RecordHeader(k, v == null ? null : v.getBytes())));
3535
return headers;
3636
}
3737

api/src/main/java/io/kafbat/ui/service/rbac/AccessControlService.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -113,11 +113,11 @@ private boolean isAccessible(AuthenticatedUser user, AccessContext context) {
113113
return context.isAccessible(getUserPermissions(user, context.cluster()));
114114
}
115115

116-
private List<Permission> getUserPermissions(AuthenticatedUser user, String clusterName) {
116+
private List<Permission> getUserPermissions(AuthenticatedUser user, @Nullable String clusterName) {
117117
return properties.getRoles()
118118
.stream()
119119
.filter(filterRole(user))
120-
.filter(role -> role.getClusters().stream().anyMatch(clusterName::equalsIgnoreCase))
120+
.filter(role -> clusterName == null || role.getClusters().stream().anyMatch(clusterName::equalsIgnoreCase))
121121
.flatMap(role -> role.getPermissions().stream())
122122
.toList();
123123
}

0 commit comments

Comments
 (0)