package eu.europeana.cloud.service.uis.security;
import java.net.URI;
import java.net.URISyntaxException;
import javax.validation.constraints.NotNull;
import javax.ws.rs.core.UriBuilder;
import javax.ws.rs.core.UriInfo;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mockito;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.authentication.AuthenticationCredentialsNotFoundException;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import eu.europeana.cloud.common.exceptions.ProviderDoesNotExistException;
import eu.europeana.cloud.common.model.CloudId;
import eu.europeana.cloud.common.model.DataProvider;
import eu.europeana.cloud.common.model.DataProviderProperties;
import eu.europeana.cloud.common.model.LocalId;
import eu.europeana.cloud.service.uis.DataProviderService;
import eu.europeana.cloud.service.uis.UniqueIdentifierService;
import eu.europeana.cloud.service.uis.exception.CloudIdAlreadyExistException;
import eu.europeana.cloud.service.uis.exception.CloudIdDoesNotExistException;
import eu.europeana.cloud.service.uis.exception.DatabaseConnectionException;
import eu.europeana.cloud.service.uis.exception.IdHasBeenMappedException;
import eu.europeana.cloud.service.uis.exception.ProviderAlreadyExistsException;
import eu.europeana.cloud.service.uis.exception.RecordDatasetEmptyException;
import eu.europeana.cloud.service.uis.exception.RecordIdDoesNotExistException;
import eu.europeana.cloud.service.uis.rest.DataProviderResource;
import eu.europeana.cloud.service.uis.rest.DataProvidersResource;
/**
* DataProviderResource + DataProvidersResource: Authentication - Authorization
* tests.
*
* @author manos
*
*/
@RunWith(SpringJUnit4ClassRunner.class)
public class DataProviderAATest extends AbstractSecurityTest {
@Autowired
@NotNull
private DataProviderResource dataProviderResource;
@Autowired
@NotNull
private DataProvidersResource dataProvidersResource;
@Autowired
@NotNull
private DataProviderService dataProviderService;
@Autowired
@NotNull
private UniqueIdentifierService uis;
private UriInfo uriInfo;
private final static String PROVIDER_ID = "Russell_Stringer_Bell";
private final static String RECORD_ID = "RECORD_ID";
private final static String CLOUD_ID = "CLOUD_ID";
private final static DataProviderProperties DATA_PROVIDER_PROPERTIES = new DataProviderProperties(
"Name", "Address", "website", "url", "url", "url", "person",
"remarks");
/**
* Pre-defined users
*/
private final static String RANDOM_PERSON = "Cristiano";
private final static String RANDOM_PASSWORD = "Ronaldo";
private final static String VAN_PERSIE = "Robin_Van_Persie";
private final static String VAN_PERSIE_PASSWORD = "Feyenoord";
private final static String RONALDO = "Cristiano";
private final static String RONALD_PASSWORD = "Ronaldo";
private final static String ADMIN = "admin";
private final static String ADMIN_PASSWORD = "admin";
private CloudId cId;
private LocalId lId;
/**
* Prepare the unit tests
* @throws CloudIdAlreadyExistException
* @throws RecordDatasetEmptyException
* @throws IdHasBeenMappedException
* @throws CloudIdDoesNotExistException
* @throws DatabaseConnectionException
*/
@Before
public void prepare() throws
ProviderAlreadyExistsException,
ProviderDoesNotExistException, URISyntaxException,
DatabaseConnectionException, CloudIdDoesNotExistException,
IdHasBeenMappedException, RecordDatasetEmptyException, CloudIdAlreadyExistException {
DataProvider dp = new DataProvider();
dp.setId("");
dp.setProperties(DATA_PROVIDER_PROPERTIES);
cId = new CloudId();
cId.setId(CLOUD_ID);
lId = new LocalId();
lId.setProviderId(PROVIDER_ID);
lId.setRecordId(RECORD_ID);
cId.setLocalId(lId);
Mockito.when(
dataProviderService.createProvider(Mockito.anyString(),
(DataProviderProperties) Mockito.any())).thenReturn(dp);
Mockito.when(
dataProviderService.updateProvider(Mockito.anyString(),
(DataProviderProperties) Mockito.any())).thenReturn(dp);
uriInfo = Mockito.mock(UriInfo.class);
UriBuilder uriBuilder = Mockito.mock(UriBuilder.class);
Mockito.doReturn(uriBuilder).when(uriInfo).getBaseUriBuilder();
Mockito.doReturn(uriBuilder).when(uriInfo).getBaseUriBuilder();
Mockito.doReturn(uriBuilder).when(uriBuilder).path((Class) Mockito.anyObject());
Mockito.doReturn(new URI("")).when(uriBuilder).buildFromMap(Mockito.anyMap());
Mockito.doReturn(new URI("")).when(uriInfo).resolve((URI) Mockito.anyObject());
Mockito.when(
uis.createIdMapping(Mockito.anyString(), Mockito.anyString(), Mockito.anyString())).thenReturn(cId);
Mockito.when(
uis.createIdMapping(Mockito.anyString(), Mockito.anyString())).thenReturn(cId);
}
/**
* Makes sure these methods can run even if noone is logged in. No special
* permissions are required.
*
* @throws IdHasBeenMappedException
* @throws CloudIdDoesNotExistException
* @throws RecordIdDoesNotExistException
*/
@Test
public void testMethodsThatDontNeedAnyAuthentication()
throws ProviderDoesNotExistException, DatabaseConnectionException,
RecordDatasetEmptyException, CloudIdDoesNotExistException,
IdHasBeenMappedException, RecordIdDoesNotExistException,
CloudIdAlreadyExistException {
dataProviderResource.getProvider(PROVIDER_ID);
dataProviderResource.getLocalIdsByProvider(PROVIDER_ID, PROVIDER_ID,
100);
dataProviderResource.getCloudIdsByProvider(PROVIDER_ID, PROVIDER_ID,
100);
dataProvidersResource.getProviders(PROVIDER_ID);
}
/**
* Makes sure any random person can just call these methods. No special
* permissions are required.
*
* @throws IdHasBeenMappedException
* @throws CloudIdDoesNotExistException
* @throws RecordIdDoesNotExistException
*/
@Test
public void shouldBeAbleToCallMethodsThatDontNeedAnyAuthenticationWithSomeRandomPersonLoggedIn()
throws ProviderDoesNotExistException, DatabaseConnectionException,
RecordDatasetEmptyException, CloudIdDoesNotExistException,
IdHasBeenMappedException, RecordIdDoesNotExistException,
CloudIdAlreadyExistException {
login(RANDOM_PERSON, RANDOM_PASSWORD);
dataProviderResource.getProvider(PROVIDER_ID);
dataProviderResource.getLocalIdsByProvider(PROVIDER_ID, PROVIDER_ID,
100);
dataProviderResource.getCloudIdsByProvider(PROVIDER_ID, PROVIDER_ID,
100);
dataProviderResource.createIdMapping(PROVIDER_ID, CLOUD_ID,
RECORD_ID);
dataProvidersResource.getProviders(PROVIDER_ID);
}
/**
* Makes sure that a random person cannot just update a Provider. Simple
* authentication test to make sure spring security annotations are in
* place.
*/
@Test(expected = AccessDeniedException.class)
public void shouldThrowAccessDeniedExceptionWhenRandomPersonTriesToUpdateProvider()
throws ProviderDoesNotExistException {
login(RANDOM_PERSON, RANDOM_PASSWORD);
dataProviderResource.updateProvider(DATA_PROVIDER_PROPERTIES,
PROVIDER_ID, null);
}
@Test(expected = AccessDeniedException.class)
public void shouldThrowAccessDeniedExceptionWhenRandomPersonTriesToRemoveMapping()
throws DatabaseConnectionException,
ProviderDoesNotExistException, RecordIdDoesNotExistException {
login(RANDOM_PERSON, RANDOM_PASSWORD);
dataProviderResource.removeIdMapping(PROVIDER_ID, CLOUD_ID);
}
@Test(expected = AuthenticationCredentialsNotFoundException.class)
public void shouldThrowExceptionWhenUnknowUserTriesToCreateIdMapping()
throws DatabaseConnectionException, CloudIdDoesNotExistException, IdHasBeenMappedException,
ProviderDoesNotExistException, RecordDatasetEmptyException, CloudIdAlreadyExistException {
dataProviderResource.createIdMapping(PROVIDER_ID, CLOUD_ID, RECORD_ID);
}
@Test(expected = AuthenticationCredentialsNotFoundException.class)
public void shouldThrowAccessDeniedExceptionWhenUnknownUserTriesToRemoveMapping()
throws DatabaseConnectionException,
ProviderDoesNotExistException, RecordIdDoesNotExistException {
dataProviderResource.removeIdMapping(PROVIDER_ID, CLOUD_ID);
}
/**
* Makes sure the person who created a provider has update permissions as
* well.
*/
@Test
public void shouldBeAbleToPerformUpdateIfHeIsTheOwner()
throws ProviderDoesNotExistException,
ProviderAlreadyExistsException, URISyntaxException {
login(RANDOM_PERSON, RANDOM_PASSWORD);
dataProvidersResource.createProvider(uriInfo, DATA_PROVIDER_PROPERTIES,
PROVIDER_ID);
dataProviderResource.updateProvider(DATA_PROVIDER_PROPERTIES,
PROVIDER_ID, uriInfo);
}
/**
* Makes sure Van Persie cannot update a provider that belongs to Christiano
* Ronaldo.
*/
@Test(expected = AccessDeniedException.class)
public void shouldThrowExceptionWhenVanPersieTriesToUpdateRonaldosStuff()
throws ProviderDoesNotExistException,
ProviderAlreadyExistsException, URISyntaxException {
login(RONALDO, RONALD_PASSWORD);
dataProvidersResource.createProvider(uriInfo, DATA_PROVIDER_PROPERTIES,
PROVIDER_ID);
login(VAN_PERSIE, VAN_PERSIE_PASSWORD);
dataProviderResource.updateProvider(DATA_PROVIDER_PROPERTIES,
PROVIDER_ID, uriInfo);
}
@Test(expected = AccessDeniedException.class)
public void shouldThrowExceptionWhenVanPersieTriesToRemoveRonaldosStuff() throws DatabaseConnectionException, CloudIdDoesNotExistException,
IdHasBeenMappedException, ProviderDoesNotExistException,
RecordDatasetEmptyException, CloudIdAlreadyExistException,
RecordIdDoesNotExistException {
login(RONALDO, RONALD_PASSWORD);
dataProviderResource.createIdMapping(PROVIDER_ID, CLOUD_ID, RECORD_ID);
login(VAN_PERSIE, VAN_PERSIE_PASSWORD);
dataProviderResource.removeIdMapping(PROVIDER_ID, CLOUD_ID);
}
@Test
public void shouldBeAbleToRemoveMappingIfHeIsTheOwner() throws DatabaseConnectionException, CloudIdDoesNotExistException,
IdHasBeenMappedException, ProviderDoesNotExistException,
RecordDatasetEmptyException, CloudIdAlreadyExistException,
RecordIdDoesNotExistException {
login(RONALDO, RONALD_PASSWORD);
dataProviderResource.createIdMapping(PROVIDER_ID, CLOUD_ID, RECORD_ID);
dataProviderResource.removeIdMapping(PROVIDER_ID, RECORD_ID);
}
/**
* Same as shouldBeAbleToRemoveMappingIfHeIsTheOwner()
* but without passing a LOCAL_ID as a parameter (local id is autogenerated).
*/
@Test
public void shouldBeAbleToRemoveMappingIfHeIsTheOwner_2() throws DatabaseConnectionException, CloudIdDoesNotExistException,
IdHasBeenMappedException, ProviderDoesNotExistException,
RecordDatasetEmptyException, CloudIdAlreadyExistException,
RecordIdDoesNotExistException {
login(RONALDO, RONALD_PASSWORD);
dataProviderResource.createIdMapping(PROVIDER_ID, CLOUD_ID, null); // lId is autogenerated
dataProviderResource.removeIdMapping(PROVIDER_ID, RECORD_ID);
}
}