Skip to content

Commit f4098a1

Browse files
committed
added more test, closes #729
1 parent f868570 commit f4098a1

File tree

3 files changed

+243
-4
lines changed

3 files changed

+243
-4
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
package io.kafbat.ui.service.rbac;
2+
3+
import static org.assertj.core.api.Assertions.assertThat;
4+
import static org.junit.jupiter.api.Assertions.assertTrue;
5+
6+
import io.kafbat.ui.AbstractIntegrationTest;
7+
import io.kafbat.ui.service.rbac.extractor.GoogleAuthorityExtractor;
8+
import io.kafbat.ui.service.rbac.extractor.ProviderAuthorityExtractor;
9+
import java.util.Set;
10+
import org.jetbrains.annotations.NotNull;
11+
import org.junit.jupiter.api.Test;
12+
import org.springframework.beans.factory.annotation.Autowired;
13+
import org.springframework.context.ApplicationContextInitializer;
14+
import org.springframework.context.ConfigurableApplicationContext;
15+
import org.springframework.test.annotation.DirtiesContext;
16+
import org.springframework.test.context.ContextConfiguration;
17+
18+
/**
19+
* Test case for Properties initializer.
20+
*/
21+
@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_CLASS)
22+
@ContextConfiguration(initializers = AccessControlServiceInitPropertiesTest.PropertiesInitializer.class)
23+
class AccessControlServiceInitPropertiesTest extends AbstractIntegrationTest {
24+
25+
public static class PropertiesInitializer extends AbstractIntegrationTest.Initializer
26+
implements ApplicationContextInitializer<ConfigurableApplicationContext> {
27+
28+
@Override
29+
public void initialize(@NotNull ConfigurableApplicationContext applicationContext) {
30+
System.setProperty("rbac.roles[0].name", "memelords");
31+
System.setProperty("rbac.roles[0].clusters[0]", "local");
32+
33+
System.setProperty("rbac.roles[0].subjects[0].provider", "oauth_google");
34+
System.setProperty("rbac.roles[0].subjects[0].type", "domain");
35+
System.setProperty("rbac.roles[0].subjects[0].value", "katbat.dev");
36+
37+
System.setProperty("rbac.roles[0].subjects[1].provider", "oauth_google");
38+
System.setProperty("rbac.roles[0].subjects[1].type", "user");
39+
System.setProperty("rbac.roles[0].subjects[1].value", "name@kafbat.dev");
40+
41+
System.setProperty("rbac.roles[0].permissions[0].resource", "applicationconfig");
42+
System.setProperty("rbac.roles[0].permissions[0].actions", "all");
43+
}
44+
}
45+
46+
@Autowired
47+
AccessControlService accessControlService;
48+
49+
@Test
50+
void rbacEnabled() {
51+
assertTrue(accessControlService.isRbacEnabled());
52+
53+
Set<ProviderAuthorityExtractor> oauthExtractors = accessControlService.getOauthExtractors();
54+
assertThat(oauthExtractors)
55+
.hasSize(1)
56+
.anyMatch(ext -> ext instanceof GoogleAuthorityExtractor);
57+
}
58+
59+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,173 @@
1+
package io.kafbat.ui.service.rbac;
2+
3+
import static io.kafbat.ui.service.rbac.MockedRbacUtils.CONNECT_NAME;
4+
import static io.kafbat.ui.service.rbac.MockedRbacUtils.CONSUMER_GROUP_NAME;
5+
import static io.kafbat.ui.service.rbac.MockedRbacUtils.DEV_ROLE;
6+
import static io.kafbat.ui.service.rbac.MockedRbacUtils.PROD_CLUSTER;
7+
import static io.kafbat.ui.service.rbac.MockedRbacUtils.SCHEMA_NAME;
8+
import static io.kafbat.ui.service.rbac.MockedRbacUtils.TOPIC_NAME;
9+
import static io.kafbat.ui.service.rbac.MockedRbacUtils.getAccessContext;
10+
import static org.assertj.core.api.Assertions.assertThat;
11+
import static org.mockito.Mockito.when;
12+
13+
import io.kafbat.ui.AbstractIntegrationTest;
14+
import io.kafbat.ui.config.auth.RbacUser;
15+
import io.kafbat.ui.model.ClusterDTO;
16+
import io.kafbat.ui.model.ConnectDTO;
17+
import io.kafbat.ui.model.InternalTopic;
18+
import io.kafbat.ui.model.rbac.AccessContext;
19+
import io.kafbat.ui.model.rbac.Role;
20+
import java.util.List;
21+
import org.junit.jupiter.api.BeforeEach;
22+
import org.junit.jupiter.api.Test;
23+
import org.mockito.Mock;
24+
import org.mockito.MockedStatic;
25+
import org.mockito.Mockito;
26+
import org.springframework.beans.factory.annotation.Autowired;
27+
import org.springframework.security.core.Authentication;
28+
import org.springframework.security.core.context.ReactiveSecurityContextHolder;
29+
import org.springframework.security.core.context.SecurityContext;
30+
import org.springframework.test.annotation.DirtiesContext;
31+
import reactor.core.publisher.Mono;
32+
import reactor.test.StepVerifier;
33+
34+
/**
35+
* Test cases for AccessControlService when RBAC is disabled.
36+
* Using PROD cluster and user DEV role for all tests.
37+
*/
38+
@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_CLASS)
39+
class AccessControlServiceRbacDisabledTest extends AbstractIntegrationTest {
40+
41+
@Autowired
42+
AccessControlService accessControlService;
43+
44+
@Mock
45+
SecurityContext securityContext;
46+
47+
@Mock
48+
Authentication authentication;
49+
50+
@Mock
51+
RbacUser user;
52+
53+
@BeforeEach
54+
void setUp() {
55+
// Mock security context
56+
when(securityContext.getAuthentication()).thenReturn(authentication);
57+
when(authentication.getPrincipal()).thenReturn(user);
58+
}
59+
60+
public void withSecurityContext(Runnable runnable) {
61+
try (MockedStatic<ReactiveSecurityContextHolder> ctxHolder = Mockito.mockStatic(
62+
ReactiveSecurityContextHolder.class)) {
63+
// Mock static method to get security context
64+
ctxHolder.when(ReactiveSecurityContextHolder::getContext).thenReturn(Mono.just(securityContext));
65+
runnable.run();
66+
}
67+
}
68+
69+
@Test
70+
void validateAccess() {
71+
withSecurityContext(() -> {
72+
when(user.groups()).thenReturn(List.of(DEV_ROLE));
73+
AccessContext context = getAccessContext(PROD_CLUSTER, true);
74+
Mono<Void> validateAccessMono = accessControlService.validateAccess(context);
75+
StepVerifier.create(validateAccessMono)
76+
.expectComplete()
77+
.verify();
78+
});
79+
}
80+
81+
@Test
82+
void isClusterAccessible() {
83+
withSecurityContext(() -> {
84+
when(user.groups()).thenReturn(List.of(DEV_ROLE));
85+
ClusterDTO clusterDto = new ClusterDTO();
86+
clusterDto.setName(PROD_CLUSTER);
87+
Mono<Boolean> clusterAccessibleMono = accessControlService.isClusterAccessible(clusterDto);
88+
StepVerifier.create(clusterAccessibleMono)
89+
.expectNext(true)
90+
.expectComplete()
91+
.verify();
92+
});
93+
}
94+
95+
@Test
96+
void filterViewableTopics() {
97+
withSecurityContext(() -> {
98+
when(user.groups()).thenReturn(List.of(DEV_ROLE));
99+
List<InternalTopic> topics = List.of(
100+
InternalTopic.builder()
101+
.name(TOPIC_NAME)
102+
.build()
103+
);
104+
Mono<List<InternalTopic>> filterTopicsMono = accessControlService.filterViewableTopics(topics, PROD_CLUSTER);
105+
StepVerifier.create(filterTopicsMono)
106+
.expectNextMatches(responseTopics -> responseTopics.stream().anyMatch(t -> t.getName().equals(TOPIC_NAME)))
107+
.expectComplete()
108+
.verify();
109+
});
110+
}
111+
112+
@Test
113+
void isConsumerGroupAccessible() {
114+
withSecurityContext(() -> {
115+
when(user.groups()).thenReturn(List.of(DEV_ROLE));
116+
Mono<Boolean> consumerGroupAccessibleMono =
117+
accessControlService.isConsumerGroupAccessible(CONSUMER_GROUP_NAME, PROD_CLUSTER);
118+
StepVerifier.create(consumerGroupAccessibleMono)
119+
.expectNext(true)
120+
.expectComplete()
121+
.verify();
122+
});
123+
}
124+
125+
@Test
126+
void isSchemaAccessible() {
127+
withSecurityContext(() -> {
128+
when(user.groups()).thenReturn(List.of(DEV_ROLE));
129+
Mono<Boolean> consumerGroupAccessibleMono =
130+
accessControlService.isSchemaAccessible(SCHEMA_NAME, PROD_CLUSTER);
131+
StepVerifier.create(consumerGroupAccessibleMono)
132+
.expectNext(true)
133+
.expectComplete()
134+
.verify();
135+
});
136+
}
137+
138+
@Test
139+
void isConnectAccessible() {
140+
withSecurityContext(() -> {
141+
when(user.groups()).thenReturn(List.of(DEV_ROLE));
142+
Mono<Boolean> consumerGroupAccessibleMono =
143+
accessControlService.isConnectAccessible(CONNECT_NAME, PROD_CLUSTER);
144+
StepVerifier.create(consumerGroupAccessibleMono)
145+
.expectNext(true)
146+
.expectComplete()
147+
.verify();
148+
});
149+
}
150+
151+
@Test
152+
void isConnectAccessibleDto() {
153+
withSecurityContext(() -> {
154+
when(user.groups()).thenReturn(List.of(DEV_ROLE));
155+
ConnectDTO connectDto = ConnectDTO.builder()
156+
.name(CONNECT_NAME)
157+
.build();
158+
Mono<Boolean> consumerGroupAccessibleMono =
159+
accessControlService.isConnectAccessible(connectDto, PROD_CLUSTER);
160+
StepVerifier.create(consumerGroupAccessibleMono)
161+
.expectNext(true)
162+
.expectComplete()
163+
.verify();
164+
});
165+
}
166+
167+
@Test
168+
void getRoles() {
169+
List<Role> roles = accessControlService.getRoles();
170+
assertThat(roles).isEmpty();
171+
}
172+
173+
}

api/src/test/java/io/kafbat/ui/service/rbac/AccessControlServiceRbacEnabledTest.java

+11-4
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import static io.kafbat.ui.service.rbac.MockedRbacUtils.SCHEMA_NAME;
1010
import static io.kafbat.ui.service.rbac.MockedRbacUtils.TOPIC_NAME;
1111
import static io.kafbat.ui.service.rbac.MockedRbacUtils.getAccessContext;
12+
import static org.assertj.core.api.Assertions.assertThat;
1213
import static org.mockito.Mockito.mock;
1314
import static org.mockito.Mockito.when;
1415

@@ -31,13 +32,15 @@
3132
import org.springframework.security.core.Authentication;
3233
import org.springframework.security.core.context.ReactiveSecurityContextHolder;
3334
import org.springframework.security.core.context.SecurityContext;
35+
import org.springframework.test.annotation.DirtiesContext;
3436
import org.springframework.test.util.ReflectionTestUtils;
3537
import reactor.core.publisher.Mono;
3638
import reactor.test.StepVerifier;
3739

3840
/**
3941
* Test cases for AccessControlService when RBAC is enabled.
4042
*/
43+
@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_CLASS)
4144
class AccessControlServiceRbacEnabledTest extends AbstractIntegrationTest {
4245

4346
@Autowired
@@ -147,8 +150,6 @@ void isClusterAccessible_deniedCluster() {
147150
void filterViewableTopics() {
148151
withSecurityContext(() -> {
149152
when(user.groups()).thenReturn(List.of(DEV_ROLE));
150-
ClusterDTO clusterDto = new ClusterDTO();
151-
clusterDto.setName(DEV_CLUSTER);
152153
List<InternalTopic> topics = List.of(
153154
InternalTopic.builder()
154155
.name(TOPIC_NAME)
@@ -166,8 +167,6 @@ void filterViewableTopics() {
166167
void filterViewableTopics_notAccessibleTopic() {
167168
withSecurityContext(() -> {
168169
when(user.groups()).thenReturn(List.of(DEV_ROLE));
169-
ClusterDTO clusterDto = new ClusterDTO();
170-
clusterDto.setName(DEV_CLUSTER);
171170
List<InternalTopic> topics = List.of(
172171
InternalTopic.builder()
173172
.name("some other topic")
@@ -291,4 +290,12 @@ void isConnectAccessibleDto_notAccessible() {
291290
});
292291
}
293292

293+
@Test
294+
void getRoles() {
295+
List<Role> roles = accessControlService.getRoles();
296+
assertThat(roles).hasSize(2)
297+
.anyMatch(role -> role.getName().equals(DEV_ROLE))
298+
.anyMatch(role -> role.getName().equals(ADMIN_ROLE));
299+
}
300+
294301
}

0 commit comments

Comments
 (0)