diff --git a/.github/workflows/frontend.yaml b/.github/workflows/frontend.yaml
index 02ccd4e135..050779a0b2 100644
--- a/.github/workflows/frontend.yaml
+++ b/.github/workflows/frontend.yaml
@@ -23,7 +23,7 @@ jobs:
# Disabling shallow clone is recommended for improving relevancy of reporting
fetch-depth: 0
ref: ${{ github.event.pull_request.head.sha }}
- - uses: pnpm/action-setup@v2.2.4
+ - uses: pnpm/action-setup@v2.4.0
with:
version: 7.4.0
- name: Install node
@@ -49,7 +49,7 @@ jobs:
cd kafka-ui-react-app/
pnpm test:CI
- name: SonarCloud Scan
- uses: workshur/sonarcloud-github-action@improved_basedir
+ uses: sonarsource/sonarcloud-github-action@master
with:
projectBaseDir: ./kafka-ui-react-app
args: -Dsonar.pullrequest.key=${{ github.event.pull_request.number }} -Dsonar.pullrequest.branch=${{ github.head_ref }} -Dsonar.pullrequest.base=${{ github.base_ref }}
diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml
index b927806f14..4c2837f1af 100644
--- a/.github/workflows/release.yaml
+++ b/.github/workflows/release.yaml
@@ -34,7 +34,7 @@ jobs:
echo "version=${VERSION}" >> $GITHUB_OUTPUT
- name: Upload files to a GitHub release
- uses: svenstaro/upload-release-action@2.6.1
+ uses: svenstaro/upload-release-action@2.7.0
with:
repo_token: ${{ secrets.GITHUB_TOKEN }}
file: kafka-ui-api/target/kafka-ui-api-${{ steps.build.outputs.version }}.jar
diff --git a/README.md b/README.md
index b276e2756f..e3fa2ab9d2 100644
--- a/README.md
+++ b/README.md
@@ -18,6 +18,10 @@
ProductHunt
+
+
+
+
#### UI for Apache Kafka is a free, open-source web UI to monitor and manage Apache Kafka clusters.
UI for Apache Kafka is a simple tool that makes your data flows observable, helps find and troubleshoot issues faster and deliver optimal performance. Its lightweight dashboard makes it easy to track key metrics of your Kafka clusters - Brokers, Topics, Partitions, Production, and Consumption.
diff --git a/kafka-ui-api/Dockerfile b/kafka-ui-api/Dockerfile
index d969ec7631..98dcdb46ac 100644
--- a/kafka-ui-api/Dockerfile
+++ b/kafka-ui-api/Dockerfile
@@ -1,7 +1,11 @@
#FROM azul/zulu-openjdk-alpine:17-jre-headless
FROM azul/zulu-openjdk-alpine@sha256:a36679ac0d28cb835e2a8c00e1e0d95509c6c51c5081c7782b85edb1f37a771a
-RUN apk add --no-cache gcompat # need to make snappy codec work
+RUN apk add --no-cache \
+ # snappy codec
+ gcompat \
+ # configuring timezones
+ tzdata
RUN addgroup -S kafkaui && adduser -S kafkaui -G kafkaui
# creating folder for dynamic config usage (certificates uploads, etc)
diff --git a/kafka-ui-api/pom.xml b/kafka-ui-api/pom.xml
index 6b22d6a662..a964a5ebe7 100644
--- a/kafka-ui-api/pom.xml
+++ b/kafka-ui-api/pom.xml
@@ -114,6 +114,11 @@
json
${org.json.version}
+
+ io.micrometer
+ micrometer-registry-prometheus
+ runtime
+
org.springframework.boot
diff --git a/kafka-ui-api/src/main/java/com/provectus/kafka/ui/config/ClustersProperties.java b/kafka-ui-api/src/main/java/com/provectus/kafka/ui/config/ClustersProperties.java
index 00e2c7e5b4..ed91fc3515 100644
--- a/kafka-ui-api/src/main/java/com/provectus/kafka/ui/config/ClustersProperties.java
+++ b/kafka-ui-api/src/main/java/com/provectus/kafka/ui/config/ClustersProperties.java
@@ -58,8 +58,6 @@ public class ClustersProperties {
@Data
public static class PollingProperties {
Integer pollTimeoutMs;
- Integer partitionPollTimeout;
- Integer noDataEmptyPolls;
Integer maxPageSize;
Integer defaultPageSize;
}
@@ -178,7 +176,13 @@ public class ClustersProperties {
Integer auditTopicsPartitions;
Boolean topicAuditEnabled;
Boolean consoleAuditEnabled;
+ LogLevel level;
Map auditTopicProperties;
+
+ public enum LogLevel {
+ ALL,
+ ALTER_ONLY //default
+ }
}
@PostConstruct
diff --git a/kafka-ui-api/src/main/java/com/provectus/kafka/ui/config/auth/AbstractAuthSecurityConfig.java b/kafka-ui-api/src/main/java/com/provectus/kafka/ui/config/auth/AbstractAuthSecurityConfig.java
index 0d92b257ed..70807295cb 100644
--- a/kafka-ui-api/src/main/java/com/provectus/kafka/ui/config/auth/AbstractAuthSecurityConfig.java
+++ b/kafka-ui-api/src/main/java/com/provectus/kafka/ui/config/auth/AbstractAuthSecurityConfig.java
@@ -13,6 +13,7 @@ abstract class AbstractAuthSecurityConfig {
"/resources/**",
"/actuator/health/**",
"/actuator/info",
+ "/actuator/prometheus",
"/auth",
"/login",
"/logout",
diff --git a/kafka-ui-api/src/main/java/com/provectus/kafka/ui/config/auth/BasicAuthSecurityConfig.java b/kafka-ui-api/src/main/java/com/provectus/kafka/ui/config/auth/BasicAuthSecurityConfig.java
index ae98dfdd7a..c62e83e665 100644
--- a/kafka-ui-api/src/main/java/com/provectus/kafka/ui/config/auth/BasicAuthSecurityConfig.java
+++ b/kafka-ui-api/src/main/java/com/provectus/kafka/ui/config/auth/BasicAuthSecurityConfig.java
@@ -6,13 +6,13 @@ import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
+import org.springframework.http.HttpMethod;
import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity;
-import org.springframework.security.config.web.server.SecurityWebFiltersOrder;
import org.springframework.security.config.web.server.ServerHttpSecurity;
import org.springframework.security.web.server.SecurityWebFilterChain;
import org.springframework.security.web.server.authentication.RedirectServerAuthenticationSuccessHandler;
import org.springframework.security.web.server.authentication.logout.RedirectServerLogoutSuccessHandler;
-import org.springframework.security.web.server.ui.LogoutPageGeneratingWebFilter;
+import org.springframework.security.web.server.util.matcher.ServerWebExchangeMatchers;
@Configuration
@EnableWebFluxSecurity
@@ -33,15 +33,19 @@ public class BasicAuthSecurityConfig extends AbstractAuthSecurityConfig {
final var logoutSuccessHandler = new RedirectServerLogoutSuccessHandler();
logoutSuccessHandler.setLogoutSuccessUrl(URI.create(LOGOUT_URL));
- return http
- .addFilterAfter(new LogoutPageGeneratingWebFilter(), SecurityWebFiltersOrder.REACTOR_CONTEXT)
- .csrf().disable()
- .authorizeExchange()
- .pathMatchers(AUTH_WHITELIST).permitAll()
- .anyExchange().authenticated()
- .and().formLogin().loginPage(LOGIN_URL).authenticationSuccessHandler(authHandler)
- .and().logout().logoutSuccessHandler(logoutSuccessHandler)
- .and().build();
+
+ return http.authorizeExchange(spec -> spec
+ .pathMatchers(AUTH_WHITELIST)
+ .permitAll()
+ .anyExchange()
+ .authenticated()
+ )
+ .formLogin(spec -> spec.loginPage(LOGIN_URL).authenticationSuccessHandler(authHandler))
+ .logout(spec -> spec
+ .logoutSuccessHandler(logoutSuccessHandler)
+ .requiresLogout(ServerWebExchangeMatchers.pathMatchers(HttpMethod.GET, "/logout")))
+ .csrf(ServerHttpSecurity.CsrfSpec::disable)
+ .build();
}
}
diff --git a/kafka-ui-api/src/main/java/com/provectus/kafka/ui/config/auth/DisabledAuthSecurityConfig.java b/kafka-ui-api/src/main/java/com/provectus/kafka/ui/config/auth/DisabledAuthSecurityConfig.java
index 4b1cc9a933..39d56a05bf 100644
--- a/kafka-ui-api/src/main/java/com/provectus/kafka/ui/config/auth/DisabledAuthSecurityConfig.java
+++ b/kafka-ui-api/src/main/java/com/provectus/kafka/ui/config/auth/DisabledAuthSecurityConfig.java
@@ -27,10 +27,12 @@ public class DisabledAuthSecurityConfig extends AbstractAuthSecurityConfig {
System.exit(1);
}
log.warn("Authentication is disabled. Access will be unrestricted.");
- return http.authorizeExchange()
- .anyExchange().permitAll()
- .and()
- .csrf().disable()
+
+ return http.authorizeExchange(spec -> spec
+ .anyExchange()
+ .permitAll()
+ )
+ .csrf(ServerHttpSecurity.CsrfSpec::disable)
.build();
}
diff --git a/kafka-ui-api/src/main/java/com/provectus/kafka/ui/config/auth/LdapSecurityConfig.java b/kafka-ui-api/src/main/java/com/provectus/kafka/ui/config/auth/LdapSecurityConfig.java
index b7750d528b..20ce2aaa58 100644
--- a/kafka-ui-api/src/main/java/com/provectus/kafka/ui/config/auth/LdapSecurityConfig.java
+++ b/kafka-ui-api/src/main/java/com/provectus/kafka/ui/config/auth/LdapSecurityConfig.java
@@ -24,6 +24,7 @@ import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.ProviderManager;
import org.springframework.security.authentication.ReactiveAuthenticationManager;
import org.springframework.security.authentication.ReactiveAuthenticationManagerAdapter;
+import org.springframework.security.config.Customizer;
import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity;
import org.springframework.security.config.web.server.ServerHttpSecurity;
import org.springframework.security.core.GrantedAuthority;
@@ -126,21 +127,15 @@ public class LdapSecurityConfig {
log.info("Active Directory support for LDAP has been enabled.");
}
- return http
- .authorizeExchange()
- .pathMatchers(AUTH_WHITELIST)
- .permitAll()
- .anyExchange()
- .authenticated()
-
- .and()
- .formLogin()
-
- .and()
- .logout()
-
- .and()
- .csrf().disable()
+ return http.authorizeExchange(spec -> spec
+ .pathMatchers(AUTH_WHITELIST)
+ .permitAll()
+ .anyExchange()
+ .authenticated()
+ )
+ .formLogin(Customizer.withDefaults())
+ .logout(Customizer.withDefaults())
+ .csrf(ServerHttpSecurity.CsrfSpec::disable)
.build();
}
diff --git a/kafka-ui-api/src/main/java/com/provectus/kafka/ui/config/auth/OAuthSecurityConfig.java b/kafka-ui-api/src/main/java/com/provectus/kafka/ui/config/auth/OAuthSecurityConfig.java
index d170a7338c..797b41c6df 100644
--- a/kafka-ui-api/src/main/java/com/provectus/kafka/ui/config/auth/OAuthSecurityConfig.java
+++ b/kafka-ui-api/src/main/java/com/provectus/kafka/ui/config/auth/OAuthSecurityConfig.java
@@ -12,10 +12,11 @@ import lombok.extern.log4j.Log4j2;
import org.jetbrains.annotations.Nullable;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.autoconfigure.security.oauth2.client.OAuth2ClientProperties;
-import org.springframework.boot.autoconfigure.security.oauth2.client.OAuth2ClientPropertiesRegistrationAdapter;
+import org.springframework.boot.autoconfigure.security.oauth2.client.OAuth2ClientPropertiesMapper;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
+import org.springframework.security.config.Customizer;
import org.springframework.security.config.annotation.method.configuration.EnableReactiveMethodSecurity;
import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity;
import org.springframework.security.config.web.server.ServerHttpSecurity;
@@ -49,21 +50,15 @@ public class OAuthSecurityConfig extends AbstractAuthSecurityConfig {
public SecurityWebFilterChain configure(ServerHttpSecurity http, OAuthLogoutSuccessHandler logoutHandler) {
log.info("Configuring OAUTH2 authentication.");
- return http.authorizeExchange()
- .pathMatchers(AUTH_WHITELIST)
- .permitAll()
- .anyExchange()
- .authenticated()
-
- .and()
- .oauth2Login()
-
- .and()
- .logout()
- .logoutSuccessHandler(logoutHandler)
-
- .and()
- .csrf().disable()
+ return http.authorizeExchange(spec -> spec
+ .pathMatchers(AUTH_WHITELIST)
+ .permitAll()
+ .anyExchange()
+ .authenticated()
+ )
+ .oauth2Login(Customizer.withDefaults())
+ .logout(spec -> spec.logoutSuccessHandler(logoutHandler))
+ .csrf(ServerHttpSecurity.CsrfSpec::disable)
.build();
}
@@ -103,7 +98,10 @@ public class OAuthSecurityConfig extends AbstractAuthSecurityConfig {
public InMemoryReactiveClientRegistrationRepository clientRegistrationRepository() {
final OAuth2ClientProperties props = OAuthPropertiesConverter.convertProperties(properties);
final List registrations =
- new ArrayList<>(OAuth2ClientPropertiesRegistrationAdapter.getClientRegistrations(props).values());
+ new ArrayList<>(new OAuth2ClientPropertiesMapper(props).asClientRegistrations().values());
+ if (registrations.isEmpty()) {
+ throw new IllegalArgumentException("OAuth2 authentication is enabled but no providers specified.");
+ }
return new InMemoryReactiveClientRegistrationRepository(registrations);
}
diff --git a/kafka-ui-api/src/main/java/com/provectus/kafka/ui/config/auth/condition/CognitoCondition.java b/kafka-ui-api/src/main/java/com/provectus/kafka/ui/config/auth/condition/CognitoCondition.java
index dc56195ecc..c369985872 100644
--- a/kafka-ui-api/src/main/java/com/provectus/kafka/ui/config/auth/condition/CognitoCondition.java
+++ b/kafka-ui-api/src/main/java/com/provectus/kafka/ui/config/auth/condition/CognitoCondition.java
@@ -1,13 +1,14 @@
package com.provectus.kafka.ui.config.auth.condition;
import com.provectus.kafka.ui.service.rbac.AbstractProviderCondition;
+import org.jetbrains.annotations.NotNull;
import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.type.AnnotatedTypeMetadata;
public class CognitoCondition extends AbstractProviderCondition implements Condition {
@Override
- public boolean matches(final ConditionContext context, final AnnotatedTypeMetadata metadata) {
+ public boolean matches(final ConditionContext context, final @NotNull AnnotatedTypeMetadata metadata) {
return getRegisteredProvidersTypes(context.getEnvironment()).stream().anyMatch(a -> a.equalsIgnoreCase("cognito"));
}
-}
\ No newline at end of file
+}
diff --git a/kafka-ui-api/src/main/java/com/provectus/kafka/ui/controller/AbstractController.java b/kafka-ui-api/src/main/java/com/provectus/kafka/ui/controller/AbstractController.java
index ec7b229783..e4dbb3cfcf 100644
--- a/kafka-ui-api/src/main/java/com/provectus/kafka/ui/controller/AbstractController.java
+++ b/kafka-ui-api/src/main/java/com/provectus/kafka/ui/controller/AbstractController.java
@@ -2,12 +2,19 @@ package com.provectus.kafka.ui.controller;
import com.provectus.kafka.ui.exception.ClusterNotFoundException;
import com.provectus.kafka.ui.model.KafkaCluster;
+import com.provectus.kafka.ui.model.rbac.AccessContext;
import com.provectus.kafka.ui.service.ClustersStorage;
+import com.provectus.kafka.ui.service.audit.AuditService;
+import com.provectus.kafka.ui.service.rbac.AccessControlService;
import org.springframework.beans.factory.annotation.Autowired;
+import reactor.core.publisher.Mono;
+import reactor.core.publisher.Signal;
public abstract class AbstractController {
protected ClustersStorage clustersStorage;
+ protected AccessControlService accessControlService;
+ protected AuditService auditService;
protected KafkaCluster getCluster(String name) {
return clustersStorage.getClusterByName(name)
@@ -15,8 +22,26 @@ public abstract class AbstractController {
String.format("Cluster with name '%s' not found", name)));
}
+ protected Mono validateAccess(AccessContext context) {
+ return accessControlService.validateAccess(context);
+ }
+
+ protected void audit(AccessContext acxt, Signal> sig) {
+ auditService.audit(acxt, sig);
+ }
+
@Autowired
public void setClustersStorage(ClustersStorage clustersStorage) {
this.clustersStorage = clustersStorage;
}
+
+ @Autowired
+ public void setAccessControlService(AccessControlService accessControlService) {
+ this.accessControlService = accessControlService;
+ }
+
+ @Autowired
+ public void setAuditService(AuditService auditService) {
+ this.auditService = auditService;
+ }
}
diff --git a/kafka-ui-api/src/main/java/com/provectus/kafka/ui/controller/AclsController.java b/kafka-ui-api/src/main/java/com/provectus/kafka/ui/controller/AclsController.java
index 1de8f4d71b..2ba0add5be 100644
--- a/kafka-ui-api/src/main/java/com/provectus/kafka/ui/controller/AclsController.java
+++ b/kafka-ui-api/src/main/java/com/provectus/kafka/ui/controller/AclsController.java
@@ -2,14 +2,15 @@ package com.provectus.kafka.ui.controller;
import com.provectus.kafka.ui.api.AclsApi;
import com.provectus.kafka.ui.mapper.ClusterMapper;
+import com.provectus.kafka.ui.model.CreateConsumerAclDTO;
+import com.provectus.kafka.ui.model.CreateProducerAclDTO;
+import com.provectus.kafka.ui.model.CreateStreamAppAclDTO;
import com.provectus.kafka.ui.model.KafkaAclDTO;
import com.provectus.kafka.ui.model.KafkaAclNamePatternTypeDTO;
import com.provectus.kafka.ui.model.KafkaAclResourceTypeDTO;
import com.provectus.kafka.ui.model.rbac.AccessContext;
import com.provectus.kafka.ui.model.rbac.permission.AclAction;
import com.provectus.kafka.ui.service.acl.AclsService;
-import com.provectus.kafka.ui.service.audit.AuditService;
-import com.provectus.kafka.ui.service.rbac.AccessControlService;
import java.util.Optional;
import lombok.RequiredArgsConstructor;
import org.apache.kafka.common.resource.PatternType;
@@ -26,8 +27,6 @@ import reactor.core.publisher.Mono;
public class AclsController extends AbstractController implements AclsApi {
private final AclsService aclsService;
- private final AccessControlService accessControlService;
- private final AuditService auditService;
@Override
public Mono> createAcl(String clusterName, Mono kafkaAclDto,
@@ -38,11 +37,11 @@ public class AclsController extends AbstractController implements AclsApi {
.operationName("createAcl")
.build();
- return accessControlService.validateAccess(context)
+ return validateAccess(context)
.then(kafkaAclDto)
.map(ClusterMapper::toAclBinding)
.flatMap(binding -> aclsService.createAcl(getCluster(clusterName), binding))
- .doOnEach(sig -> auditService.audit(context, sig))
+ .doOnEach(sig -> audit(context, sig))
.thenReturn(ResponseEntity.ok().build());
}
@@ -55,11 +54,11 @@ public class AclsController extends AbstractController implements AclsApi {
.operationName("deleteAcl")
.build();
- return accessControlService.validateAccess(context)
+ return validateAccess(context)
.then(kafkaAclDto)
.map(ClusterMapper::toAclBinding)
.flatMap(binding -> aclsService.deleteAcl(getCluster(clusterName), binding))
- .doOnEach(sig -> auditService.audit(context, sig))
+ .doOnEach(sig -> audit(context, sig))
.thenReturn(ResponseEntity.ok().build());
}
@@ -85,12 +84,12 @@ public class AclsController extends AbstractController implements AclsApi {
var filter = new ResourcePatternFilter(resourceType, resourceName, namePatternType);
- return accessControlService.validateAccess(context).then(
+ return validateAccess(context).then(
Mono.just(
ResponseEntity.ok(
aclsService.listAcls(getCluster(clusterName), filter)
.map(ClusterMapper::toKafkaAclDto)))
- ).doOnEach(sig -> auditService.audit(context, sig));
+ ).doOnEach(sig -> audit(context, sig));
}
@Override
@@ -101,11 +100,11 @@ public class AclsController extends AbstractController implements AclsApi {
.operationName("getAclAsCsv")
.build();
- return accessControlService.validateAccess(context).then(
+ return validateAccess(context).then(
aclsService.getAclAsCsvString(getCluster(clusterName))
.map(ResponseEntity::ok)
.flatMap(Mono::just)
- .doOnEach(sig -> auditService.audit(context, sig))
+ .doOnEach(sig -> audit(context, sig))
);
}
@@ -117,10 +116,61 @@ public class AclsController extends AbstractController implements AclsApi {
.operationName("syncAclsCsv")
.build();
- return accessControlService.validateAccess(context)
+ return validateAccess(context)
.then(csvMono)
.flatMap(csv -> aclsService.syncAclWithAclCsv(getCluster(clusterName), csv))
- .doOnEach(sig -> auditService.audit(context, sig))
+ .doOnEach(sig -> audit(context, sig))
+ .thenReturn(ResponseEntity.ok().build());
+ }
+
+ @Override
+ public Mono> createConsumerAcl(String clusterName,
+ Mono createConsumerAclDto,
+ ServerWebExchange exchange) {
+ AccessContext context = AccessContext.builder()
+ .cluster(clusterName)
+ .aclActions(AclAction.EDIT)
+ .operationName("createConsumerAcl")
+ .build();
+
+ return validateAccess(context)
+ .then(createConsumerAclDto)
+ .flatMap(req -> aclsService.createConsumerAcl(getCluster(clusterName), req))
+ .doOnEach(sig -> audit(context, sig))
+ .thenReturn(ResponseEntity.ok().build());
+ }
+
+ @Override
+ public Mono> createProducerAcl(String clusterName,
+ Mono createProducerAclDto,
+ ServerWebExchange exchange) {
+ AccessContext context = AccessContext.builder()
+ .cluster(clusterName)
+ .aclActions(AclAction.EDIT)
+ .operationName("createProducerAcl")
+ .build();
+
+ return validateAccess(context)
+ .then(createProducerAclDto)
+ .flatMap(req -> aclsService.createProducerAcl(getCluster(clusterName), req))
+ .doOnEach(sig -> audit(context, sig))
+ .thenReturn(ResponseEntity.ok().build());
+ }
+
+ @Override
+ public Mono> createStreamAppAcl(String clusterName,
+ Mono createStreamAppAclDto,
+ ServerWebExchange exchange) {
+ AccessContext context = AccessContext.builder()
+ .cluster(clusterName)
+ .aclActions(AclAction.EDIT)
+ .operationName("createStreamAppAcl")
+ .build();
+
+ return validateAccess(context)
+ .then(createStreamAppAclDto)
+ .flatMap(req -> aclsService.createStreamAppAcl(getCluster(clusterName), req))
+ .doOnEach(sig -> audit(context, sig))
.thenReturn(ResponseEntity.ok().build());
}
}
diff --git a/kafka-ui-api/src/main/java/com/provectus/kafka/ui/controller/ApplicationConfigController.java b/kafka-ui-api/src/main/java/com/provectus/kafka/ui/controller/ApplicationConfigController.java
index 5f03c9ab5c..480d62b178 100644
--- a/kafka-ui-api/src/main/java/com/provectus/kafka/ui/controller/ApplicationConfigController.java
+++ b/kafka-ui-api/src/main/java/com/provectus/kafka/ui/controller/ApplicationConfigController.java
@@ -15,8 +15,6 @@ import com.provectus.kafka.ui.model.UploadedFileInfoDTO;
import com.provectus.kafka.ui.model.rbac.AccessContext;
import com.provectus.kafka.ui.service.ApplicationInfoService;
import com.provectus.kafka.ui.service.KafkaClusterFactory;
-import com.provectus.kafka.ui.service.audit.AuditService;
-import com.provectus.kafka.ui.service.rbac.AccessControlService;
import com.provectus.kafka.ui.util.ApplicationRestarter;
import com.provectus.kafka.ui.util.DynamicConfigOperations;
import com.provectus.kafka.ui.util.DynamicConfigOperations.PropertiesStructure;
@@ -39,7 +37,7 @@ import reactor.util.function.Tuples;
@Slf4j
@RestController
@RequiredArgsConstructor
-public class ApplicationConfigController implements ApplicationConfigApi {
+public class ApplicationConfigController extends AbstractController implements ApplicationConfigApi {
private static final PropertiesMapper MAPPER = Mappers.getMapper(PropertiesMapper.class);
@@ -51,12 +49,10 @@ public class ApplicationConfigController implements ApplicationConfigApi {
ApplicationConfigPropertiesDTO toDto(PropertiesStructure propertiesStructure);
}
- private final AccessControlService accessControlService;
private final DynamicConfigOperations dynamicConfigOperations;
private final ApplicationRestarter restarter;
private final KafkaClusterFactory kafkaClusterFactory;
private final ApplicationInfoService applicationInfoService;
- private final AuditService auditService;
@Override
public Mono> getApplicationInfo(ServerWebExchange exchange) {
@@ -69,12 +65,12 @@ public class ApplicationConfigController implements ApplicationConfigApi {
.applicationConfigActions(VIEW)
.operationName("getCurrentConfig")
.build();
- return accessControlService.validateAccess(context)
+ return validateAccess(context)
.then(Mono.fromSupplier(() -> ResponseEntity.ok(
new ApplicationConfigDTO()
.properties(MAPPER.toDto(dynamicConfigOperations.getCurrentProperties()))
)))
- .doOnEach(sig -> auditService.audit(context, sig));
+ .doOnEach(sig -> audit(context, sig));
}
@Override
@@ -84,14 +80,14 @@ public class ApplicationConfigController implements ApplicationConfigApi {
.applicationConfigActions(EDIT)
.operationName("restartWithConfig")
.build();
- return accessControlService.validateAccess(context)
+ return validateAccess(context)
.then(restartRequestDto)
.>map(dto -> {
dynamicConfigOperations.persist(MAPPER.fromDto(dto.getConfig().getProperties()));
restarter.requestRestart();
return ResponseEntity.ok().build();
})
- .doOnEach(sig -> auditService.audit(context, sig));
+ .doOnEach(sig -> audit(context, sig));
}
@Override
@@ -101,13 +97,13 @@ public class ApplicationConfigController implements ApplicationConfigApi {
.applicationConfigActions(EDIT)
.operationName("uploadConfigRelatedFile")
.build();
- return accessControlService.validateAccess(context)
+ return validateAccess(context)
.then(fileFlux.single())
.flatMap(file ->
dynamicConfigOperations.uploadConfigRelatedFile((FilePart) file)
.map(path -> new UploadedFileInfoDTO().location(path.toString()))
.map(ResponseEntity::ok))
- .doOnEach(sig -> auditService.audit(context, sig));
+ .doOnEach(sig -> audit(context, sig));
}
@Override
@@ -117,7 +113,7 @@ public class ApplicationConfigController implements ApplicationConfigApi {
.applicationConfigActions(EDIT)
.operationName("validateConfig")
.build();
- return accessControlService.validateAccess(context)
+ return validateAccess(context)
.then(configDto)
.flatMap(config -> {
PropertiesStructure propertiesStructure = MAPPER.fromDto(config.getProperties());
@@ -126,7 +122,7 @@ public class ApplicationConfigController implements ApplicationConfigApi {
.map(validations -> new ApplicationConfigValidationDTO().clusters(validations));
})
.map(ResponseEntity::ok)
- .doOnEach(sig -> auditService.audit(context, sig));
+ .doOnEach(sig -> audit(context, sig));
}
private Mono