Skip to content

Commit 616d04d

Browse files
committed
WIP
1 parent 29d18ba commit 616d04d

File tree

2 files changed

+209
-9
lines changed

2 files changed

+209
-9
lines changed

services-api/src/main/java/io/scalecube/services/Reflect.java

Lines changed: 39 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
import io.scalecube.services.annotations.ServiceMethod;
1313
import io.scalecube.services.annotations.Tag;
1414
import io.scalecube.services.api.ServiceMessage;
15+
import io.scalecube.services.auth.AllowedRoles;
1516
import io.scalecube.services.auth.Secured;
1617
import io.scalecube.services.methods.MethodInfo;
1718
import io.scalecube.services.methods.ServiceRoleDefinition;
@@ -400,7 +401,41 @@ public static boolean isSecured(Method method) {
400401
* @return {@link ServiceRoleDefinition} objects
401402
*/
402403
public static Collection<ServiceRoleDefinition> serviceRoles(Method method) {
403-
return null; // TODO ...
404+
if (method.isAnnotationPresent(AllowedRoles.class)) {
405+
final var allowedRolesAnnotation = method.getAnnotation(AllowedRoles.class);
406+
final var allowedRoles = allowedRolesAnnotation.value();
407+
return Arrays.stream(allowedRoles)
408+
.map(
409+
allowedRole ->
410+
new ServiceRoleDefinition(
411+
allowedRole.name(), new HashSet<>(Arrays.asList(allowedRole.permissions()))))
412+
.collect(Collectors.toSet());
413+
}
414+
415+
// If @AllowedRoles/@AllowedRole annotations is not present on service method, then find it on
416+
// service class
417+
418+
Class<?> clazz = method.getDeclaringClass();
419+
420+
AllowedRoles allowedRolesAnnotation = null;
421+
for (; clazz != null; clazz = clazz.getSuperclass()) {
422+
allowedRolesAnnotation = clazz.getAnnotation(AllowedRoles.class);
423+
if (allowedRolesAnnotation != null) {
424+
break;
425+
}
426+
}
427+
428+
if (allowedRolesAnnotation != null) {
429+
final var allowedRoles = allowedRolesAnnotation.value();
430+
return Arrays.stream(allowedRoles)
431+
.map(
432+
allowedRole ->
433+
new ServiceRoleDefinition(
434+
allowedRole.name(), new HashSet<>(Arrays.asList(allowedRole.permissions()))))
435+
.collect(Collectors.toSet());
436+
}
437+
438+
return Set.of();
404439
}
405440

406441
/**
@@ -410,7 +445,9 @@ public static Collection<ServiceRoleDefinition> serviceRoles(Method method) {
410445
* @return service role names
411446
*/
412447
public static Collection<String> allowedRoles(Method method) {
413-
return null; // TODO ...
448+
return serviceRoles(method).stream()
449+
.map(ServiceRoleDefinition::role)
450+
.collect(Collectors.toSet());
414451
}
415452

416453
/**

services-api/src/test/java/io/scalecube/services/methods/ReflectTest.java

Lines changed: 170 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,23 @@
33
import static io.scalecube.services.CommunicationMode.REQUEST_CHANNEL;
44
import static io.scalecube.services.CommunicationMode.REQUEST_RESPONSE;
55
import static io.scalecube.services.CommunicationMode.REQUEST_STREAM;
6+
import static org.hamcrest.MatcherAssert.assertThat;
7+
import static org.hamcrest.Matchers.hasItem;
8+
import static org.junit.jupiter.api.Assertions.assertEquals;
9+
import static org.junit.jupiter.api.Assertions.assertNotNull;
610

711
import io.scalecube.services.CommunicationMode;
812
import io.scalecube.services.Reflect;
913
import io.scalecube.services.annotations.Service;
14+
import io.scalecube.services.annotations.ServiceMethod;
1015
import io.scalecube.services.api.ServiceMessage;
16+
import io.scalecube.services.auth.AllowedRole;
17+
import io.scalecube.services.auth.AllowedRoles;
1118
import java.lang.reflect.Method;
1219
import java.util.Arrays;
20+
import java.util.List;
21+
import java.util.Set;
1322
import java.util.stream.Stream;
14-
import org.junit.jupiter.api.Assertions;
1523
import org.junit.jupiter.api.Test;
1624
import org.junit.jupiter.params.ParameterizedTest;
1725
import org.junit.jupiter.params.provider.Arguments;
@@ -26,14 +34,14 @@ public class ReflectTest {
2634
public void testCommunicationMode(String methodName, CommunicationMode expectedMode) {
2735
// Given:
2836
Method m =
29-
Arrays.stream(TestService.class.getMethods())
37+
Arrays.stream(JustService.class.getMethods())
3038
.filter(meth -> meth.getName().equals(methodName))
3139
.findFirst()
3240
.get();
3341
// When:
3442
CommunicationMode communicationMode = Reflect.communicationMode(m);
3543
// Then:
36-
Assertions.assertEquals(expectedMode, communicationMode, "Invalid communicationMode");
44+
assertEquals(expectedMode, communicationMode, "Invalid communicationMode");
3745
}
3846

3947
private static Stream<Arguments> argsCommunicationModeProvider() {
@@ -55,14 +63,14 @@ private static Stream<Arguments> argsCommunicationModeProvider() {
5563
public void testIsRequestTypeServiceMessage(String methodName, boolean expect) {
5664
// Given:
5765
Method method =
58-
Arrays.stream(ReflectTest.TestService.class.getMethods())
66+
Arrays.stream(JustService.class.getMethods())
5967
.filter(meth -> meth.getName().equals(methodName))
6068
.findFirst()
6169
.get();
6270
// When:
6371
boolean actual = Reflect.isRequestTypeServiceMessage(method);
6472
// Then:
65-
Assertions.assertEquals(
73+
assertEquals(
6674
expect,
6775
actual,
6876
String.format("isRequestTypeServiceMessage(%s) should be %b", methodName, expect));
@@ -88,11 +96,61 @@ public void testSubServiceInterfaces() {
8896
// When:
8997
Stream<Class<?>> interfaces = Reflect.serviceInterfaces(new SubServiceImpl());
9098
// Then:
91-
Assertions.assertEquals(
99+
assertEquals(
92100
1, interfaces.count(), "serviceInterfaces(..) should detect interfaces in SubServiceImpl");
93101
}
94102

95-
private interface TestService {
103+
@ParameterizedTest(name = "[{index}] {0}")
104+
@MethodSource("testServiceRolesMethodSource")
105+
public void testServiceRoles(String test, SuccessArgs args) throws Exception {
106+
final var method = args.serviceInstance.getClass().getMethod("hello");
107+
final var serviceRoles = Reflect.serviceRoles(method);
108+
assertNotNull(serviceRoles, "serviceRoles");
109+
assertEquals(args.list.size(), serviceRoles.size(), "serviceRoles.size");
110+
for (var expectedServiceRole : args.list) {
111+
assertThat(serviceRoles, hasItem(expectedServiceRole));
112+
}
113+
}
114+
115+
private record SuccessArgs(Object serviceInstance, List<ServiceRoleDefinition> list) {}
116+
117+
private static Stream<Arguments> testServiceRolesMethodSource() {
118+
return Stream.of(
119+
Arguments.of(
120+
"@AllowedRoles declared on class",
121+
new SuccessArgs(
122+
new ServiceRoleService1Impl(),
123+
List.of(
124+
new ServiceRoleDefinition("user", Set.of("read", "write")),
125+
new ServiceRoleDefinition("admin", Set.of("*"))))),
126+
Arguments.of(
127+
"Repeatable @AllowedRole declared on class",
128+
new SuccessArgs(
129+
new ServiceRoleService2Impl(),
130+
List.of(
131+
new ServiceRoleDefinition("user", Set.of("read", "write")),
132+
new ServiceRoleDefinition("admin", Set.of("*"))))),
133+
Arguments.of(
134+
"@AllowedRoles declared on method",
135+
new SuccessArgs(
136+
new ServiceRoleService3Impl(),
137+
List.of(
138+
new ServiceRoleDefinition("user", Set.of("read", "write")),
139+
new ServiceRoleDefinition("admin", Set.of("*"))))),
140+
Arguments.of(
141+
"Repeatable @AllowedRole declared on method",
142+
new SuccessArgs(
143+
new ServiceRoleService4Impl(),
144+
List.of(
145+
new ServiceRoleDefinition("user", Set.of("read", "write")),
146+
new ServiceRoleDefinition("admin", Set.of("*"))))),
147+
Arguments.of(
148+
"No @AllowedRoles/@AllowedRole annotations declared anywhere",
149+
new SuccessArgs(new ServiceRoleService5Impl(), List.of())));
150+
}
151+
152+
private interface JustService {
153+
96154
void fireAndForget(Integer i);
97155

98156
Mono<Void> emptyResponse(Integer i);
@@ -129,4 +187,109 @@ public String name() {
129187
}
130188

131189
private static class SubServiceImpl extends ServiceImpl {}
190+
191+
@Service
192+
private interface ServiceRoleService1 {
193+
194+
@ServiceMethod
195+
Mono<Void> hello();
196+
}
197+
198+
@AllowedRoles(
199+
value = {
200+
@AllowedRole(
201+
name = "user",
202+
permissions = {"read", "write"}),
203+
@AllowedRole(
204+
name = "admin",
205+
permissions = {"*"})
206+
})
207+
public static class ServiceRoleService1Impl implements ServiceRoleService1 {
208+
209+
@Override
210+
public Mono<Void> hello() {
211+
return null;
212+
}
213+
}
214+
215+
@Service
216+
private interface ServiceRoleService2 {
217+
218+
@ServiceMethod
219+
Mono<Void> hello();
220+
}
221+
222+
@AllowedRole(
223+
name = "user",
224+
permissions = {"read", "write"})
225+
@AllowedRole(
226+
name = "admin",
227+
permissions = {"*"})
228+
public static class ServiceRoleService2Impl implements ServiceRoleService2 {
229+
230+
@Override
231+
public Mono<Void> hello() {
232+
return null;
233+
}
234+
}
235+
236+
@Service
237+
private interface ServiceRoleService3 {
238+
239+
@ServiceMethod
240+
Mono<Void> hello();
241+
}
242+
243+
public static class ServiceRoleService3Impl implements ServiceRoleService3 {
244+
245+
@AllowedRoles(
246+
value = {
247+
@AllowedRole(
248+
name = "user",
249+
permissions = {"read", "write"}),
250+
@AllowedRole(
251+
name = "admin",
252+
permissions = {"*"})
253+
})
254+
@Override
255+
public Mono<Void> hello() {
256+
return null;
257+
}
258+
}
259+
260+
@Service
261+
private interface ServiceRoleService4 {
262+
263+
@ServiceMethod
264+
Mono<Void> hello();
265+
}
266+
267+
public static class ServiceRoleService4Impl implements ServiceRoleService4 {
268+
269+
@AllowedRole(
270+
name = "user",
271+
permissions = {"read", "write"})
272+
@AllowedRole(
273+
name = "admin",
274+
permissions = {"*"})
275+
@Override
276+
public Mono<Void> hello() {
277+
return null;
278+
}
279+
}
280+
281+
@Service
282+
private interface ServiceRoleService5 {
283+
284+
@ServiceMethod
285+
Mono<Void> hello();
286+
}
287+
288+
public static class ServiceRoleService5Impl implements ServiceRoleService5 {
289+
290+
@Override
291+
public Mono<Void> hello() {
292+
return null;
293+
}
294+
}
132295
}

0 commit comments

Comments
 (0)