Skip to content

Commit

Permalink
test fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
devonbush committed Jun 30, 2024
1 parent eb94104 commit f3205d9
Show file tree
Hide file tree
Showing 3 changed files with 143 additions and 119 deletions.
111 changes: 35 additions & 76 deletions api-admin/src/test/java/bio/terra/pearl/api/admin/AuthTestUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,82 +13,6 @@
import org.springframework.core.annotation.AnnotationUtils;

public class AuthTestUtils {

public static void assertHasAnnotation(
Object service, String methodName, Class<? extends Annotation> annotationClass) {
List<Method> targetMethods =
Arrays.stream(service.getClass().getDeclaredMethods())
.filter(method -> method.getName().equals(methodName))
.toList();
assertThat(targetMethods.size(), greaterThan(0));
targetMethods
.stream() // we need to check all methods with the same name in case they are overloaded
.forEach(
targetMethod ->
assertThat(
AnnotationUtils.findAnnotation(targetMethod, annotationClass), notNullValue()));
}

public static void assertHasPermissionEnforced(
Object service,
String methodName,
Class<? extends Annotation> annotationClass,
String permissionName) {
List<Method> targetMethods =
Arrays.stream(service.getClass().getDeclaredMethods())
.filter(method -> method.getName().equals(methodName))
.toList();
assertThat(targetMethods.size(), greaterThan(0));
targetMethods
.stream() // we need to check all methods with the same name in case they are overloaded
.forEach(
targetMethod -> {
Annotation annotation = AnnotationUtils.findAnnotation(targetMethod, annotationClass);
try {
String permission =
(String) MethodUtils.invokeMethod(annotation, "permission", null);
assertThat(permission, equalTo(permissionName));
} catch (Exception e) {
throw new RuntimeException(e);
}
});
}

/** methods we don't validate annotations on -- base Object methods and methods added by Spring */
private static final List<String> excludedMethodNames =
List.of(
"equals",
"toString",
"hashCode",
"indexOf",
"newInstance",
"isFrozen",
"addAdvisor",
"setCallback",
"getTargetClass",
"CGLIB$findMethodProxy",
"getCallback",
"getCallbacks",
"CGLIB$SET_THREAD_CALLBACKS",
"CGLIB$SET_STATIC_CALLBACKS",
"setCallbacks",
"getTargetSource",
"getProxiedInterfaces",
"isInterfaceProxied",
"getAdvisorCount",
"getAdvisors",
"isProxyTargetClass",
"setTargetSource",
"setExposeProxy",
"isExposeProxy",
"setPreFiltered",
"isPreFiltered",
"removeAdvisor",
"replaceAdvisor",
"removeAdvice",
"toProxyConfigString",
"addAdvice");

/** confirms all public methods of the given class are annotated according to the specs */
public static void assertAllMethodsAnnotated(
Object service, Map<String, AuthAnnotationSpec> annotationSpecs) {
Expand Down Expand Up @@ -147,4 +71,39 @@ public static void validateMethodToSpec(Method method, AuthAnnotationSpec annota
notNullValue());
}
}

/** methods we don't validate annotations on -- base Object methods and methods added by Spring */
private static final List<String> excludedMethodNames =
List.of(
"equals",
"toString",
"hashCode",
"indexOf",
"newInstance",
"isFrozen",
"addAdvisor",
"setCallback",
"getTargetClass",
"CGLIB$findMethodProxy",
"getCallback",
"getCallbacks",
"CGLIB$SET_THREAD_CALLBACKS",
"CGLIB$SET_STATIC_CALLBACKS",
"setCallbacks",
"getTargetSource",
"getProxiedInterfaces",
"isInterfaceProxied",
"getAdvisorCount",
"getAdvisors",
"isProxyTargetClass",
"setTargetSource",
"setExposeProxy",
"isExposeProxy",
"setPreFiltered",
"isPreFiltered",
"removeAdvisor",
"replaceAdvisor",
"removeAdvice",
"toProxyConfigString",
"addAdvice");
}
Original file line number Diff line number Diff line change
@@ -1,2 +1,81 @@
package bio.terra.pearl.api.admin;public class AuthTestUtilsTest {
package bio.terra.pearl.api.admin;

import bio.terra.pearl.api.admin.service.auth.EnforcePortalPermission;
import bio.terra.pearl.api.admin.service.auth.SandboxOnly;
import java.util.List;
import java.util.Map;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;

public class AuthTestUtilsTest {
@Test
public void testChecksAnnotatedMethod() {
AuthTestUtils.assertAllMethodsAnnotated(
new MethodAnnotatedClass(),
Map.of("doSomethingSecure", AuthAnnotationSpec.withPortalPerm("BASE")));

// fails if the wrong permission is specced
Assertions.assertThrows(
AssertionError.class,
() -> {
AuthTestUtils.assertAllMethodsAnnotated(
new MethodAnnotatedClass(),
Map.of("doSomethingSecure", AuthAnnotationSpec.withPortalPerm("wrongPerm")));
});

// fails if the spec also expects a SandboxOnly annotation
Assertions.assertThrows(
AssertionError.class,
() -> {
AuthTestUtils.assertAllMethodsAnnotated(
new MethodAnnotatedClass(),
Map.of(
"doSomethingSecure",
AuthAnnotationSpec.withPortalPerm("wrongPerm", List.of(SandboxOnly.class))));
});
}

@Test
public void testFailsUnspecifiedMethod() {
Assertions.assertThrows(
IllegalArgumentException.class,
() -> {
AuthTestUtils.assertAllMethodsAnnotated(new MethodAnnotatedClass(), Map.of());
});
}

@Test
public void testFailsMethodNotAnnotated() {
Assertions.assertThrows(
AssertionError.class,
() -> {
AuthTestUtils.assertAllMethodsAnnotated(
new MethodNotAnnotatedClass(),
Map.of("doSomethingSecure", AuthAnnotationSpec.withPortalPerm("BASE")));
});
}

@Test
public void testChecksSandboxAnnotated() {
AuthTestUtils.assertAllMethodsAnnotated(
new SandboxMethodAnnotatedClass(),
Map.of(
"doSomethingSecure",
AuthAnnotationSpec.withPortalPerm("BASE", List.of(SandboxOnly.class))));
}

public static class MethodAnnotatedClass {
@EnforcePortalPermission(permission = "BASE")
public void doSomethingSecure() {}
}

public static class MethodNotAnnotatedClass {
public void doSomethingSecure() {}
}

public static class SandboxMethodAnnotatedClass {
@SandboxOnly
@EnforcePortalPermission(permission = "BASE")
public void doSomethingSecure() {}
}
}
Original file line number Diff line number Diff line change
@@ -1,41 +1,36 @@
package bio.terra.pearl.api.admin.service.forms;

import static org.hamcrest.CoreMatchers.notNullValue;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.mockito.Mockito.when;

import bio.terra.pearl.api.admin.AuthAnnotationSpec;
import bio.terra.pearl.api.admin.AuthTestUtils;
import bio.terra.pearl.api.admin.BaseSpringBootTest;
import bio.terra.pearl.api.admin.service.auth.AuthUtilService;
import bio.terra.pearl.api.admin.service.auth.EnforcePortalPermission;
import bio.terra.pearl.api.admin.service.auth.EnforcePortalStudyEnvPermission;
import bio.terra.pearl.api.admin.service.auth.SandboxOnly;
import bio.terra.pearl.api.admin.service.auth.context.PortalAuthContext;
import bio.terra.pearl.core.model.admin.AdminUser;
import bio.terra.pearl.core.factory.admin.AdminUserBundle;
import bio.terra.pearl.core.factory.admin.AdminUserFactory;
import bio.terra.pearl.core.factory.admin.PortalAdminUserFactory;
import bio.terra.pearl.core.factory.portal.PortalFactory;
import bio.terra.pearl.core.factory.survey.SurveyFactory;
import bio.terra.pearl.core.model.portal.Portal;
import bio.terra.pearl.core.model.survey.Survey;
import bio.terra.pearl.core.service.exception.NotFoundException;
import bio.terra.pearl.core.service.study.StudyEnvironmentService;
import bio.terra.pearl.core.service.study.StudyEnvironmentSurveyService;
import bio.terra.pearl.core.service.survey.SurveyService;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.UUID;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.transaction.annotation.Transactional;

public class SurveyExtServiceAuthTests extends BaseSpringBootTest {

@Autowired private SurveyExtService surveyExtService;

@MockBean private AuthUtilService mockAuthUtilService;
@MockBean private SurveyService mockSurveyService;
@MockBean private StudyEnvironmentSurveyService mockStudyEnvironmentSurveyService;
@MockBean private StudyEnvironmentService mockStudyEnvironmentService;
@Autowired private PortalFactory portalFactory;
@Autowired private SurveyFactory surveyFactory;
@Autowired private AdminUserFactory adminUserFactory;
@Autowired private PortalAdminUserFactory portalAdminUserFactory;

@Test
public void assertAllMethods() {
Expand Down Expand Up @@ -63,37 +58,28 @@ public void assertAllMethods() {
}

@Test
public void getRequiresSurveyMatchedToPortal() {
AdminUser user = AdminUser.builder().superuser(false).build();
Portal portal = Portal.builder().shortcode("testSurveyGet").id(UUID.randomUUID()).build();
Survey matchedSurvey = configureMockSurvey("testMatchedToPortal", 1, portal.getId());
Survey unmatchedSurvey = configureMockSurvey("testUnmatchedToPortal", 1, UUID.randomUUID());
when(mockAuthUtilService.authUserToPortal(user, portal.getShortcode())).thenReturn(portal);
when(mockAuthUtilService.authSurveyToPortal(portal, "testMatchedToPortal", 1))
.thenReturn(matchedSurvey);
when(mockAuthUtilService.authSurveyToPortal(portal, "testUnmatchedToPortal", 1))
.thenThrow(new NotFoundException("not found"));

@Transactional
public void getRequiresSurveyMatchedToPortal(TestInfo info) {
Portal portal = portalFactory.buildPersisted(getTestName(info));
AdminUserBundle userBundle =
portalAdminUserFactory.buildPersistedWithPortals(getTestName(info), List.of(portal));
Portal otherPortal = portalFactory.buildPersisted(getTestName(info));
Survey survey = surveyFactory.buildPersisted(getTestName(info), portal.getId());
assertThat(
surveyExtService.get(
PortalAuthContext.of(user, portal.getShortcode()),
matchedSurvey.getStableId(),
matchedSurvey.getVersion()),
notNullValue());
PortalAuthContext.of(userBundle.user(), portal.getShortcode()),
survey.getStableId(),
survey.getVersion()),
equalTo(survey));

// not found if attempted to retrieve via the other portal
Assertions.assertThrows(
NotFoundException.class,
() ->
surveyExtService.get(
PortalAuthContext.of(user, portal.getShortcode()),
unmatchedSurvey.getStableId(),
unmatchedSurvey.getVersion()));
}

private Survey configureMockSurvey(String stableId, int version, UUID portalId) {
Survey survey = Survey.builder().stableId(stableId).version(1).portalId(portalId).build();
when(mockSurveyService.findByStableId(stableId, version, portalId))
.thenReturn(Optional.of(survey));
return survey;
PortalAuthContext.of(userBundle.user(), otherPortal.getShortcode()),
survey.getStableId(),
survey.getVersion()));
}

public record AuthTestSpec(
Expand Down

0 comments on commit f3205d9

Please sign in to comment.