Skip to content

Commit

Permalink
reworks unique criteria of the OrgAff auth rule, closes #65
Browse files Browse the repository at this point in the history
New implementation supports multiple OrganizationAffiliation resources
for a parent/member organization combination if no resource with the
same role or roles exists.

Adds OrganizationAffiliation integration test.

Improves error handling for searches in auth rules.
  • Loading branch information
hhund committed Aug 9, 2023
1 parent d8d0dfc commit a4d6555
Show file tree
Hide file tree
Showing 5 changed files with 266 additions and 33 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -185,8 +185,8 @@ protected final boolean organizationWithIdentifierExists(Connection connection,
List<SearchQueryParameterError> uQp = query.getUnsupportedQueryParameters();
if (!uQp.isEmpty())
{
logger.warn("Unsupported query parameters {} while searching for Organization", uQp);
return false;
logger.warn("Unable to search for Organization: Unsupported query parameters: {}", uQp);
throw new IllegalStateException("Unable to search for Organization: Unsupported query parameters.");
}

try
Expand All @@ -196,8 +196,8 @@ protected final boolean organizationWithIdentifierExists(Connection connection,
}
catch (SQLException e)
{
logger.warn("Error while searching for Organization with identifier", e);
return false;
logger.warn("Unable to search for Organization", e);
throw new RuntimeException("Unable to search for Organization", e);
}
}

Expand All @@ -216,8 +216,8 @@ protected final boolean roleExists(Connection connection, Coding coding)
List<SearchQueryParameterError> uQp = query.getUnsupportedQueryParameters();
if (!uQp.isEmpty())
{
logger.warn("Unsupported query parameters {} while searching for CodeSystem", uQp);
return false;
logger.warn("Unable to search for CodeSystem: Unsupported query parameters: {}", uQp);
throw new IllegalStateException("Unable to search for CodeSystem: Unsupported query parameters");
}

try
Expand All @@ -227,8 +227,8 @@ protected final boolean roleExists(Connection connection, Coding coding)
}
catch (SQLException e)
{
logger.warn("Error while searching for Organization with identifier", e);
return false;
logger.warn("Unable to search for CodeSystem", e);
throw new RuntimeException("Unable to search for CodeSystem", e);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import dev.dsf.fhir.help.ParameterConverter;
import dev.dsf.fhir.search.PartialResult;
import dev.dsf.fhir.search.SearchQuery;
import dev.dsf.fhir.search.SearchQueryParameterError;
import dev.dsf.fhir.service.ReferenceResolver;

public class EndpointAuthorizationRule extends AbstractMetaTagAuthorizationRule<Endpoint, EndpointDao>
Expand Down Expand Up @@ -111,8 +112,12 @@ private boolean endpointWithAddressExists(Connection connection, String address)
EndpointDao dao = getDao();
SearchQuery<Endpoint> query = dao.createSearchQueryWithoutUserFilter(0, 0).configureParameters(queryParameters);

if (!query.getUnsupportedQueryParameters().isEmpty())
return false;
List<SearchQueryParameterError> uQp = query.getUnsupportedQueryParameters();
if (!uQp.isEmpty())
{
logger.warn("Unable to search for Endpoint: Unsupported query parameters: {}", uQp);
throw new IllegalStateException("Unable to search for Endpoint: Unsupported query parameters");
}

try
{
Expand All @@ -121,8 +126,8 @@ private boolean endpointWithAddressExists(Connection connection, String address)
}
catch (SQLException e)
{
logger.warn("Error while searching for Endpoint with address", e);
return false;
logger.warn("Unable to search for Endpoint", e);
throw new RuntimeException("Unable to search for Endpoint", e);
}
}

Expand All @@ -133,8 +138,12 @@ private boolean endpointWithIdentifierExists(Connection connection, String ident
EndpointDao dao = getDao();
SearchQuery<Endpoint> query = dao.createSearchQueryWithoutUserFilter(0, 0).configureParameters(queryParameters);

if (!query.getUnsupportedQueryParameters().isEmpty())
return false;
List<SearchQueryParameterError> uQp = query.getUnsupportedQueryParameters();
if (!uQp.isEmpty())
{
logger.warn("Unable to search for Endpoint: Unsupported query parameters: {}", uQp);
throw new IllegalStateException("Unable to search for Endpoint: Unsupported query parameters");
}

try
{
Expand All @@ -143,8 +152,8 @@ private boolean endpointWithIdentifierExists(Connection connection, String ident
}
catch (SQLException e)
{
logger.warn("Error while searching for Endpoint with identifier", e);
return false;
logger.warn("Unable to search for Endpoint", e);
throw new RuntimeException("Unable to search for Endpoint", e);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import java.util.Optional;
import java.util.stream.Collectors;

import org.hl7.fhir.r4.model.CodeableConcept;
import org.hl7.fhir.r4.model.OrganizationAffiliation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
Expand All @@ -21,6 +22,7 @@
import dev.dsf.fhir.help.ParameterConverter;
import dev.dsf.fhir.search.PartialResult;
import dev.dsf.fhir.search.SearchQuery;
import dev.dsf.fhir.search.SearchQueryParameterError;
import dev.dsf.fhir.service.ReferenceResolver;

public class OrganizationAffiliationAuthorizationRule
Expand Down Expand Up @@ -79,6 +81,36 @@ private Optional<String> newResourceOk(Connection connection, Identity identity,
errors.add("OrganizationAffiliation.participatingOrganization missing");
}

if (newResource.hasEndpoint())
{
for (int i = 0; i < newResource.getEndpoint().size(); i++)
{
if (!newResource.getEndpoint().get(i).hasReference())
{
errors.add("OrganizationAffiliation.endpoint[" + i + "].reference missing");
}
}
}
else
{
errors.add("OrganizationAffiliation.endpoint missing");
}

if (newResource.hasCode())
{
for (int i = 0; i < newResource.getCode().size(); i++)
{
if (!newResource.getCode().get(i).hasCoding())
{
errors.add("OrganizationAffiliation.code[" + i + "].coding missing");
}
}
}
else
{
errors.add("OrganizationAffiliation.code missing");
}

if (!hasValidReadAccessTag(connection, newResource))
{
errors.add("OrganizationAffiliation is missing valid read access tag");
Expand All @@ -93,21 +125,29 @@ private Optional<String> newResourceOk(Connection connection, Identity identity,
@Override
protected boolean resourceExists(Connection connection, OrganizationAffiliation newResource)
{
return organizationAffiliationWithParentAndMemberExists(connection, newResource);
return organizationAffiliationWithParentAndMemberAndRoleExists(connection, newResource);
}

private boolean organizationAffiliationWithParentAndMemberExists(Connection connection,
private boolean organizationAffiliationWithParentAndMemberAndRoleExists(Connection connection,
OrganizationAffiliation newResource)
{
Map<String, List<String>> queryParameters = Map.of("primary-organization",
Collections.singletonList(newResource.getOrganization().getReference()), "participating-organization",
Collections.singletonList(newResource.getParticipatingOrganization().getReference()));
Collections.singletonList(newResource.getParticipatingOrganization().getReference()), "role",
newResource.getCode().stream().map(CodeableConcept::getCoding).flatMap(List::stream)
.map(c -> c.getSystem() + "|" + c.getCode()).toList());

OrganizationAffiliationDao dao = getDao();
SearchQuery<OrganizationAffiliation> query = dao.createSearchQueryWithoutUserFilter(0, 0)
.configureParameters(queryParameters);

if (!query.getUnsupportedQueryParameters().isEmpty())
return false;
List<SearchQueryParameterError> uQp = query.getUnsupportedQueryParameters();
if (!uQp.isEmpty())
{
logger.warn("Unable to search for OrganizationAffiliation: Unsupported query parameters: {}", uQp);
throw new IllegalStateException(
"Unable to search for OrganizationAffiliation: Unsupported query parameters");
}

try
{
Expand All @@ -116,16 +156,17 @@ private boolean organizationAffiliationWithParentAndMemberExists(Connection conn
}
catch (SQLException e)
{
logger.warn("Error while searching for Endpoint with address", e);
return false;
logger.warn("Unable to search for OrganizationAffiliation", e);
throw new RuntimeException("Unable to search for OrganizationAffiliation", e);
}
}

@Override
protected boolean modificationsOk(Connection connection, OrganizationAffiliation oldResource,
OrganizationAffiliation newResource)
{
return isParentSame(oldResource, newResource) && isMemberSame(oldResource, newResource);
return isParentSame(oldResource, newResource) && isMemberSame(oldResource, newResource)
&& !resourceExists(connection, newResource);
}

private boolean isParentSame(OrganizationAffiliation oldResource, OrganizationAffiliation newResource)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,12 +88,10 @@ private Optional<String> newResourceOk(Connection connection, Identity identity,
if (optDao.isPresent())
{
SearchQuery<?> searchQuery = optDao.get().createSearchQueryWithoutUserFilter(1, 1);
List<SearchQueryParameterError> unsupportedQueryParameters = searchQuery
.getUnsupportedQueryParameters();

if (!unsupportedQueryParameters.isEmpty())
List<SearchQueryParameterError> uQp = searchQuery.getUnsupportedQueryParameters();
if (!uQp.isEmpty())
{
errors.add("Subscription.criteria invalid (parameters '" + unsupportedQueryParameters.stream()
errors.add("Subscription.criteria invalid (parameters '" + uQp.stream()
.map(SearchQueryParameterError::toString).collect(Collectors.joining(", "))
+ "' not supported)");
}
Expand Down Expand Up @@ -136,8 +134,12 @@ protected boolean resourceExists(Connection connection, Subscription newResource
SearchQuery<Subscription> query = dao.createSearchQueryWithoutUserFilter(1, 1)
.configureParameters(queryParameters);

if (!query.getUnsupportedQueryParameters().isEmpty())
return false;
List<SearchQueryParameterError> uQp = query.getUnsupportedQueryParameters();
if (!uQp.isEmpty())
{
logger.warn("Unable to search for Subscription: Unsupported query parameters: {}", uQp);
throw new IllegalStateException("Unable to search for Subscription: Unsupported query parameters");
}

try
{
Expand All @@ -146,8 +148,8 @@ protected boolean resourceExists(Connection connection, Subscription newResource
}
catch (SQLException e)
{
logger.warn("Error while searching for Subscriptions", e);
return false;
logger.warn("Unable to search for Subscription", e);
throw new RuntimeException("Unable to search for Subscription", e);
}
}

Expand Down
Loading

0 comments on commit a4d6555

Please sign in to comment.