blob: f2996b62c2aa45d1c70c858dd6561c9cd9c694b1 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.directory.scim.server.rest;
import static com.googlecode.catchexception.CatchException.catchException;
import static com.googlecode.catchexception.CatchException.caughtException;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.sameInstance;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.jupiter.api.Assertions.fail;
import static org.mockito.Mockito.*;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import jakarta.ws.rs.WebApplicationException;
import jakarta.ws.rs.core.MultivaluedMap;
import jakarta.ws.rs.core.Response;
import jakarta.ws.rs.core.Response.Status;
import jakarta.ws.rs.core.UriInfo;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.apache.directory.scim.server.exception.ScimServerException;
import org.apache.directory.scim.core.repository.Repository;
import org.apache.directory.scim.server.utility.ExampleObjectExtension;
import org.apache.directory.scim.server.utility.ExampleObjectExtension.ComplexObject;
import org.apache.directory.scim.spec.extension.EnterpriseExtension;
import org.apache.directory.scim.spec.extension.EnterpriseExtension.Manager;
import org.apache.directory.scim.spec.phonenumber.PhoneNumberParseException;
import org.apache.directory.scim.spec.filter.attribute.AttributeReferenceListWrapper;
import org.apache.directory.scim.protocol.data.ErrorResponse;
import org.apache.directory.scim.protocol.data.PatchRequest;
import org.apache.directory.scim.protocol.data.SearchRequest;
import org.apache.directory.scim.spec.resources.Address;
import org.apache.directory.scim.spec.resources.Name;
import org.apache.directory.scim.spec.resources.PhoneNumber;
import org.apache.directory.scim.spec.resources.ScimUser;
import org.apache.directory.scim.spec.resources.PhoneNumber.GlobalPhoneNumberBuilder;
import org.apache.directory.scim.spec.resources.PhoneNumber.LocalPhoneNumberBuilder;
import org.mockito.junit.jupiter.MockitoExtension;
@ExtendWith(MockitoExtension.class)
public class BaseResourceTypeResourceImplTest {
@Mock
Repository<ScimUser> repository;
AttributeReferenceListWrapper includedAttributeList = new AttributeReferenceListWrapper("name.givenName, name.familyName");
AttributeReferenceListWrapper excludedAttributeList = new AttributeReferenceListWrapper("emails, phoneNumbers");
@Test
public void testGetProviderInternal_ScimServerExceptionThrownWhenNoProvider() throws ScimServerException {
// given
@SuppressWarnings("rawtypes")
BaseResourceTypeResourceImpl baseResourceImpl = Mockito.mock(BaseResourceTypeResourceImpl.class);
when(baseResourceImpl.getRepositoryInternal()).thenCallRealMethod();
// when
assertThrows(ScimServerException.class, () -> baseResourceImpl.getRepositoryInternal());
}
@SuppressWarnings("unchecked")
@Test
public void testGetById_ForbiddenIfNoFilter() {
// given
@SuppressWarnings("rawtypes")
BaseResourceTypeResourceImpl baseResourceImpl = Mockito.mock(BaseResourceTypeResourceImpl.class);
UriInfo uriInfo = mock(UriInfo.class);
MultivaluedMap queryParams = mock(MultivaluedMap.class);
baseResourceImpl.requestContext = new RequestContext().setUriInfo(uriInfo);
when(uriInfo.getQueryParameters()).thenReturn(queryParams);
when(queryParams.getFirst("filter")).thenReturn("not null");
when(baseResourceImpl.getById("1", includedAttributeList, excludedAttributeList)).thenCallRealMethod();
// when
Response response = baseResourceImpl.getById("1", includedAttributeList, excludedAttributeList);
// then
assertTrue(response != null);
assertTrue(response.getStatus() == Status.FORBIDDEN.getStatusCode());
}
@Test
public void testQuery_NullParametersValid() {
// given
@SuppressWarnings("rawtypes")
BaseResourceTypeResourceImpl baseResourceImpl = Mockito.mock(BaseResourceTypeResourceImpl.class);
SearchRequest searchRequest = new SearchRequest();
searchRequest.setAttributes(Collections.emptySet());
searchRequest.setExcludedAttributes(Collections.emptySet());
when(baseResourceImpl.find(searchRequest)).thenReturn(Response.ok().build());
when(baseResourceImpl.query(null, null, null, null, null, null, null)).thenCallRealMethod();
// when
Response response = baseResourceImpl.query(null, null, null, null, null, null, null);
// then
verify(baseResourceImpl, times(1)).find(searchRequest);
assertTrue(response != null);
assertTrue(response.getStatus() == Status.OK.getStatusCode());
}
@Test
public void testCreate_ErrorIfBothAttributesAndExcludedAttributesExist() {
// given
@SuppressWarnings("unchecked")
BaseResourceTypeResourceImpl<ScimUser> baseResourceImpl = Mockito.mock(BaseResourceTypeResourceImpl.class);
ScimUser scimUser = null;
try {
scimUser = getScimUser();
} catch (PhoneNumberParseException e) {
fail("Parsing phone number in getScimUser failed");
}
when(baseResourceImpl.create(scimUser, includedAttributeList, excludedAttributeList)).thenCallRealMethod();
// when
Response response = baseResourceImpl.create(scimUser, includedAttributeList, excludedAttributeList);
// then
assertTrue(response != null);
assertTrue(response.getStatus() == Status.BAD_REQUEST.getStatusCode());
assertTrue(response.getEntity() instanceof ErrorResponse);
assertTrue(((ErrorResponse)response.getEntity()).getDetail().equals("Cannot include both attributes and excluded attributes in a single request"));
}
@Test
public void testFind_ErrorIfBothAttributesAndExcludedAttributesExist() {
// given
@SuppressWarnings("rawtypes")
BaseResourceTypeResourceImpl baseResourceImpl = Mockito.mock(BaseResourceTypeResourceImpl.class);
SearchRequest searchRequest = new SearchRequest();
searchRequest.setAttributes(includedAttributeList.getAttributeReferences());
searchRequest.setExcludedAttributes(excludedAttributeList.getAttributeReferences());
when(baseResourceImpl.find(searchRequest)).thenCallRealMethod();
// when
Response response = baseResourceImpl.find(searchRequest);
// then
assertTrue(response != null);
assertTrue(response.getStatus() == Status.BAD_REQUEST.getStatusCode());
assertTrue(response.getEntity() instanceof ErrorResponse);
assertTrue(((ErrorResponse)response.getEntity()).getDetail().equals("Cannot include both attributes and excluded attributes in a single request"));
}
@Test
public void testUpdate_ErrorIfBothAttributesAndExcludedAttributesExist() {
// given
@SuppressWarnings("unchecked")
BaseResourceTypeResourceImpl<ScimUser> baseResourceImpl = Mockito.mock(BaseResourceTypeResourceImpl.class);
ScimUser scimUser = null;
try {
scimUser = getScimUser();
} catch (PhoneNumberParseException e) {
fail("Parsing phone number in getScimUser failed");
}
when(baseResourceImpl.update(scimUser, "1", includedAttributeList, excludedAttributeList)).thenCallRealMethod();
// when
Response response = baseResourceImpl.update(scimUser, "1", includedAttributeList, excludedAttributeList);
// then
assertTrue(response != null);
assertTrue(response.getStatus() == Status.BAD_REQUEST.getStatusCode());
assertTrue(response.getEntity() instanceof ErrorResponse);
assertTrue(((ErrorResponse)response.getEntity()).getDetail().equals("Cannot include both attributes and excluded attributes in a single request"));
}
@Test
public void testPatch_ErrorIfBothAttributesAndExcludedAttributesExist() throws Exception {
// given
@SuppressWarnings("unchecked")
BaseResourceTypeResourceImpl<ScimUser> baseResourceImpl = Mockito.mock(BaseResourceTypeResourceImpl.class);
PatchRequest patchRequest = new PatchRequest();
when(baseResourceImpl.patch(patchRequest, "1", includedAttributeList, excludedAttributeList)).thenCallRealMethod();
// when
Response response = baseResourceImpl.patch(patchRequest, "1", includedAttributeList, excludedAttributeList);
// then
assertTrue(response != null);
assertTrue(response.getStatus() == Status.BAD_REQUEST.getStatusCode());
assertTrue(response.getEntity() instanceof ErrorResponse);
assertTrue(((ErrorResponse)response.getEntity()).getDetail().equals("Cannot include both attributes and excluded attributes in a single request"));
}
@Test
public void handleException_jaxrsExceptionTest() {
BaseResourceTypeResourceImpl<ScimUser> baseResourceImpl = mock(BaseResourceTypeResourceImpl.class);
when(baseResourceImpl.handleException(any())).thenCallRealMethod();
Exception e = new WebApplicationException();
catchException(() -> baseResourceImpl.handleException(e));
assertThat(caughtException(), sameInstance(e));
}
@Test
public void handleException_runtimeExceptionTest() {
BaseResourceTypeResourceImpl<ScimUser> baseResourceImpl = mock(BaseResourceTypeResourceImpl.class);
when(baseResourceImpl.handleException(any())).thenCallRealMethod();
Exception e = new RuntimeException("fake test exception");
Response response = baseResourceImpl.handleException(e);
assertThat(response.getStatus(), is(500));
assertThat(((ErrorResponse)response.getEntity()).getDetail(), is("fake test exception"));
}
@Test
public void handleException_nullExceptionTest() {
BaseResourceTypeResourceImpl<ScimUser> baseResourceImpl = mock(BaseResourceTypeResourceImpl.class);
when(baseResourceImpl.handleException(any())).thenCallRealMethod();
Response response = baseResourceImpl.handleException(null);
assertThat(response.getStatus(), is(500));
assertThat(((ErrorResponse)response.getEntity()).getDetail(), is("Unknown Server Error"));
}
private ScimUser getScimUser() throws PhoneNumberParseException {
ScimUser user = new ScimUser();
user.setActive(true);
user.setId("1");
user.setExternalId("e1");
user.setUserName("jed1");
user.setActive(true);
user.setNickName("Jonny");
user.setPassword("secret");
user.setPreferredLanguage("English");
user.setProfileUrl("http://example.com/Users/JohnDoe");
user.setUserName("jed1");
user.setDisplayName("John Doe");
Name name = new Name();
name.setHonorificPrefix("Mr.");
name.setGivenName("John");
name.setMiddleName("E");
name.setFamilyName("Doe");
name.setHonorificSuffix("Jr.");
name.setFormatted("Mr. John E. Doe Jr.");
user.setName(name);
List<Address> addresses = new ArrayList<>();
Address address = new Address();
address.setStreetAddress("123 Main St.");
address.setLocality("State College");
address.setRegion("PA");
address.setPostalCode("16801");
address.setCountry("USA");
address.setType("home");
address.setPrimary(true);
address.setDisplay("123 Main St. State College, PA 16801");
address.setFormatted("123 Main St. State College, PA 16801");
addresses.add(address);
address = new Address();
address.setStreetAddress("456 Main St.");
address.setLocality("State College");
address.setRegion("PA");
address.setPostalCode("16801");
address.setCountry("USA");
address.setType("work");
address.setPrimary(false);
address.setDisplay("456 Main St. State College, PA 16801");
address.setFormatted("456 Main St. State College, PA 16801");
addresses.add(address);
user.setAddresses(addresses);
List<PhoneNumber> phoneNumbers = new ArrayList<>();
PhoneNumber phoneNumber = new LocalPhoneNumberBuilder().subscriberNumber("123-456-7890").countryCode("+1").build();
phoneNumber.setDisplay("123-456-7890");
phoneNumber.setPrimary(true);
phoneNumber.setType("home");
phoneNumbers.add(phoneNumber);
phoneNumber = new GlobalPhoneNumberBuilder().globalNumber("1-800-555-1234").build();
phoneNumber.setDisplay("1-800-555-1234");
phoneNumber.setPrimary(false);
phoneNumber.setType("work");
phoneNumbers.add(phoneNumber);
user.setPhoneNumbers(phoneNumbers);
EnterpriseExtension enterpriseEntension = new EnterpriseExtension();
enterpriseEntension.setCostCenter("CC-123");
enterpriseEntension.setDepartment("DEPT-xyz");
enterpriseEntension.setDivision("DIV-1");
enterpriseEntension.setEmployeeNumber("1234567890");
Manager manager = new Manager();
manager.setDisplayName("Bob Smith");
manager.setValue("0987654321");
enterpriseEntension.setManager(manager);
enterpriseEntension.setOrganization("ORG-X");
user.addExtension(enterpriseEntension);
ExampleObjectExtension exampleObjectExtension = new ExampleObjectExtension();
exampleObjectExtension.setValueAlways("always");
exampleObjectExtension.setValueDefault("default");
exampleObjectExtension.setValueNever("never");
exampleObjectExtension.setValueRequest("request");
ComplexObject valueComplex = new ComplexObject();
valueComplex.setDisplayName("ValueComplex");
valueComplex.setValue("Value");
exampleObjectExtension.setValueComplex(valueComplex);
user.addExtension(exampleObjectExtension);
return user;
}
}