diff --git a/dsf-bpe/dsf-bpe-server/src/main/java/dev/dsf/bpe/authentication/BpeServerRole.java b/dsf-bpe/dsf-bpe-server/src/main/java/dev/dsf/bpe/authentication/BpeServerRole.java index a2a108d28..aaa63e1ab 100644 --- a/dsf-bpe/dsf-bpe-server/src/main/java/dev/dsf/bpe/authentication/BpeServerRole.java +++ b/dsf-bpe/dsf-bpe-server/src/main/java/dev/dsf/bpe/authentication/BpeServerRole.java @@ -1,15 +1,21 @@ package dev.dsf.bpe.authentication; -import java.util.stream.Stream; - import dev.dsf.common.auth.conf.DsfRole; +import dev.dsf.common.auth.conf.RoleConfig.RoleKeyAndValues; public enum BpeServerRole implements DsfRole { ADMIN; - public static boolean isValid(String role) + public static BpeServerRole from(RoleKeyAndValues role) + { + return role != null && role.key() != null && !role.key().isBlank() && ADMIN.name().equals(role.key()) + && role.values().isEmpty() ? ADMIN : null; + } + + @Override + public boolean matches(DsfRole role) { - return role != null && !role.isBlank() && Stream.of(values()).map(Enum::name).anyMatch(n -> n.equals(role)); + return ADMIN.equals(role); } } diff --git a/dsf-bpe/dsf-bpe-server/src/main/java/dev/dsf/bpe/authentication/IdentityProviderImpl.java b/dsf-bpe/dsf-bpe-server/src/main/java/dev/dsf/bpe/authentication/IdentityProviderImpl.java index a2dca5b19..db549054a 100644 --- a/dsf-bpe/dsf-bpe-server/src/main/java/dev/dsf/bpe/authentication/IdentityProviderImpl.java +++ b/dsf-bpe/dsf-bpe-server/src/main/java/dev/dsf/bpe/authentication/IdentityProviderImpl.java @@ -18,13 +18,14 @@ import dev.dsf.common.auth.conf.PractitionerIdentityImpl; import dev.dsf.common.auth.conf.RoleConfig; -public class IdentityProviderImpl extends AbstractIdentityProvider implements IdentityProvider, InitializingBean +public class IdentityProviderImpl extends AbstractIdentityProvider + implements IdentityProvider, InitializingBean { private static final Logger logger = LoggerFactory.getLogger(IdentityProviderImpl.class); private final LocalOrganizationAndEndpointProvider organizationAndEndpointProvider; - public IdentityProviderImpl(RoleConfig roleConfig, + public IdentityProviderImpl(RoleConfig roleConfig, LocalOrganizationAndEndpointProvider organizationAndEndpointProvider) { super(roleConfig); diff --git a/dsf-bpe/dsf-bpe-server/src/main/java/dev/dsf/bpe/spring/config/AuthenticationConfig.java b/dsf-bpe/dsf-bpe-server/src/main/java/dev/dsf/bpe/spring/config/AuthenticationConfig.java index f8f99fca5..4c387ea24 100644 --- a/dsf-bpe/dsf-bpe-server/src/main/java/dev/dsf/bpe/spring/config/AuthenticationConfig.java +++ b/dsf-bpe/dsf-bpe-server/src/main/java/dev/dsf/bpe/spring/config/AuthenticationConfig.java @@ -41,10 +41,10 @@ public IdentityProvider identityProvider() } @Bean - public RoleConfig roleConfig() + public RoleConfig roleConfig() { - RoleConfig config = new RoleConfigReader().read(propertiesConfig.getRoleConfig(), - role -> BpeServerRole.isValid(role) ? BpeServerRole.valueOf(role) : null, _ -> null); + RoleConfig config = new RoleConfigReader().read(propertiesConfig.getRoleConfig(), + BpeServerRole::from, _ -> null); logger.info("Role config: {}", config.toString()); return config; diff --git a/dsf-common/dsf-common-auth/src/main/java/dev/dsf/common/auth/conf/AbstractIdentity.java b/dsf-common/dsf-common-auth/src/main/java/dev/dsf/common/auth/conf/AbstractIdentity.java index f7669279a..670d102a6 100644 --- a/dsf-common/dsf-common-auth/src/main/java/dev/dsf/common/auth/conf/AbstractIdentity.java +++ b/dsf-common/dsf-common-auth/src/main/java/dev/dsf/common/auth/conf/AbstractIdentity.java @@ -87,7 +87,7 @@ public Set getDsfRoles() @Override public boolean hasDsfRole(DsfRole dsfRole) { - return dsfRoles.contains(dsfRole); + return dsfRoles.stream().anyMatch(r -> r.matches(dsfRole)); } @Override diff --git a/dsf-common/dsf-common-auth/src/main/java/dev/dsf/common/auth/conf/AbstractIdentityProvider.java b/dsf-common/dsf-common-auth/src/main/java/dev/dsf/common/auth/conf/AbstractIdentityProvider.java index 46ac636aa..293e93909 100644 --- a/dsf-common/dsf-common-auth/src/main/java/dev/dsf/common/auth/conf/AbstractIdentityProvider.java +++ b/dsf-common/dsf-common-auth/src/main/java/dev/dsf/common/auth/conf/AbstractIdentityProvider.java @@ -41,16 +41,16 @@ import dev.dsf.common.auth.DsfOpenIdCredentials; import dev.dsf.common.auth.conf.RoleConfig.Mapping; -public abstract class AbstractIdentityProvider implements IdentityProvider, InitializingBean +public abstract class AbstractIdentityProvider implements IdentityProvider, InitializingBean { private static final Logger logger = LoggerFactory.getLogger(AbstractIdentityProvider.class); private static final String PRACTITIONER_IDENTIFIER_SYSTEM = "http://dsf.dev/sid/practitioner-identifier"; - private final RoleConfig roleConfig; + private final RoleConfig roleConfig; private final Set thumbprints; - public AbstractIdentityProvider(RoleConfig roleConfig) + public AbstractIdentityProvider(RoleConfig roleConfig) { this.roleConfig = roleConfig; @@ -81,7 +81,7 @@ public final Identity getIdentity(DsfOpenIdCredentials credentials) List rolesFromTokens = getRolesFromTokens(parsedIdToken, parsedAccessToken); List groupsFromTokens = getGroupsFromTokens(parsedIdToken, parsedAccessToken); - Set dsfRoles = getDsfRolesFor(practitioner.get(), null, rolesFromTokens, groupsFromTokens); + Set dsfRoles = getDsfRolesFor(practitioner.get(), null, rolesFromTokens, groupsFromTokens); Set practitionerRoles = getPractitionerRolesFor(practitioner.get(), null, rolesFromTokens, groupsFromTokens); @@ -187,19 +187,18 @@ private List getPropertyArray(Map map, String property) } // thumbprint from certificate, token roles and groups from jwt - protected final Set getDsfRolesFor(Practitioner practitioner, String thumbprint, List tokenRoles, + protected final Set getDsfRolesFor(Practitioner practitioner, String thumbprint, List tokenRoles, List tokenGroups) { List emailAddresses = practitioner.getIdentifier().stream() .filter(i -> PRACTITIONER_IDENTIFIER_SYSTEM.equals(i.getSystem()) && i.hasValue()) .map(Identifier::getValue).toList(); - Stream r1 = emailAddresses.stream().map(roleConfig::getDsfRolesForEmail).flatMap(List::stream); - Stream r2 = thumbprint == null ? Stream.empty() - : roleConfig.getDsfRolesForThumbprint(thumbprint).stream(); - Stream r3 = tokenRoles == null ? Stream.empty() + Stream r1 = emailAddresses.stream().map(roleConfig::getDsfRolesForEmail).flatMap(List::stream); + Stream r2 = thumbprint == null ? Stream.empty() : roleConfig.getDsfRolesForThumbprint(thumbprint).stream(); + Stream r3 = tokenRoles == null ? Stream.empty() : tokenRoles.stream().map(roleConfig::getDsfRolesForTokenRole).flatMap(List::stream); - Stream r4 = tokenGroups == null ? Stream.empty() + Stream r4 = tokenGroups == null ? Stream.empty() : tokenGroups.stream().map(roleConfig::getDsfRolesForTokenGroup).flatMap(List::stream); return Stream.of(r1, r2, r3, r4).flatMap(Function.identity()).distinct().collect(Collectors.toSet()); diff --git a/dsf-common/dsf-common-auth/src/main/java/dev/dsf/common/auth/conf/DsfRole.java b/dsf-common/dsf-common-auth/src/main/java/dev/dsf/common/auth/conf/DsfRole.java index 409e3f796..aa143409a 100644 --- a/dsf-common/dsf-common-auth/src/main/java/dev/dsf/common/auth/conf/DsfRole.java +++ b/dsf-common/dsf-common-auth/src/main/java/dev/dsf/common/auth/conf/DsfRole.java @@ -3,4 +3,11 @@ public interface DsfRole { String name(); + + /** + * @param role + * may be null + * @return true if same or superset of given role + */ + boolean matches(DsfRole role); } diff --git a/dsf-common/dsf-common-auth/src/main/java/dev/dsf/common/auth/conf/RoleConfig.java b/dsf-common/dsf-common-auth/src/main/java/dev/dsf/common/auth/conf/RoleConfig.java index 34cbf419e..399a05b63 100644 --- a/dsf-common/dsf-common-auth/src/main/java/dev/dsf/common/auth/conf/RoleConfig.java +++ b/dsf-common/dsf-common-auth/src/main/java/dev/dsf/common/auth/conf/RoleConfig.java @@ -14,7 +14,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -public class RoleConfig +public class RoleConfig { private static final Logger logger = LoggerFactory.getLogger(RoleConfig.class); @@ -34,7 +34,7 @@ public class RoleConfig private static final String EMAIL_PATTERN_STRING = "^[\\w!#$%&'*+/=?`{\\|}~^-]+(?:\\.[\\w!#$%&'*+/=?`{\\|}~^-]+)*@(?:[a-zA-Z0-9-]+\\.)+[a-zA-Z]{2,6}$"; private static final Pattern EMAIL_PATTERN = Pattern.compile(EMAIL_PATTERN_STRING); - public static final class Mapping + public static final class Mapping { private final String name; @@ -43,11 +43,11 @@ public static final class Mapping private final List tokenRoles = new ArrayList<>(); private final List tokenGroups = new ArrayList<>(); - private final List dsfRoles = new ArrayList<>(); + private final List dsfRoles = new ArrayList<>(); private final List practitionerRoles = new ArrayList<>(); public Mapping(String name, List thumbprints, List emails, List tokenRoles, - List tokenGroups, List dsfRoles, List practitionerRoles) + List tokenGroups, List dsfRoles, List practitionerRoles) { this.name = name; @@ -91,7 +91,7 @@ public List getTokenGroups() return Collections.unmodifiableList(tokenGroups); } - public List getDsfRoles() + public List getDsfRoles() { return Collections.unmodifiableList(dsfRoles); } @@ -112,21 +112,40 @@ public String toString() } } - private final List entries = new ArrayList<>(); + public static record RoleKeyAndValues(String key, List values) + { + public RoleKeyAndValues(String key) + { + this(key, List.of()); + } + } + + public static interface DsfRoleFactory + { + /** + * @param roleKeyAndValues + * not null + * @return null if no role exists for the given key and values + */ + R create(RoleKeyAndValues roleKeyAndValues); + } + + private final List> entries = new ArrayList<>(); /** * @param config * parsed yaml * @param dsfRoleFactory - * factory should return null if the given string does not represent a valid role, the role - * needs to exists + * not null * @param practitionerRoleFactory - * factory should return null if the given string does not represent a valid code, the code - * or CodeSystem does not need to exist + * not null, factory should return null if the given string does not represent + * a valid code, the code or CodeSystem does not need to exist */ - public RoleConfig(Object config, Function dsfRoleFactory, - Function practitionerRoleFactory) + public RoleConfig(Object config, DsfRoleFactory dsfRoleFactory, Function practitionerRoleFactory) { + Objects.requireNonNull(dsfRoleFactory, "dsfRoleFactory"); + Objects.requireNonNull(practitionerRoleFactory, "practitionerRoleFactory"); + if (config != null && config instanceof List l) { l.forEach(mapping -> @@ -139,7 +158,7 @@ public RoleConfig(Object config, Function dsfRoleFactory, && mappingValues instanceof Map v) { List thumbprints = null, emails = null, tokenRoles = null, tokenGroups = null; - List dsfRoles = null; + List dsfRoles = null; List practitionerRoles = null; for (Entry property : v.entrySet()) @@ -153,7 +172,7 @@ public RoleConfig(Object config, Function dsfRoleFactory, { if (value == null || value.isBlank()) { - logger.warn("Ignoring empty of blank thumbprint in rule '{}'", + logger.warn("Ignoring empty or blank thumbprint in rule '{}'", mappingKey); return null; } @@ -166,7 +185,7 @@ else if (!THUMBPRINT_PATTERN.matcher(value.trim()).matches()) } else return value.trim(); - }).filter(g -> g != null).toList(); + }).filter(Objects::nonNull).toList(); break; case PROPERTY_EMAIL: @@ -174,7 +193,7 @@ else if (!THUMBPRINT_PATTERN.matcher(value.trim()).matches()) { if (value == null || value.isBlank()) { - logger.warn("Ignoring empty of blank email in rule '{}'", + logger.warn("Ignoring empty or blank email in rule '{}'", mappingKey); return null; } @@ -187,7 +206,7 @@ else if (!EMAIL_PATTERN.matcher(value.trim()).matches()) } else return value.trim(); - }).filter(g -> g != null).toList(); + }).filter(Objects::nonNull).toList(); break; case PROPERTY_TOKEN_ROLE: @@ -195,13 +214,13 @@ else if (!EMAIL_PATTERN.matcher(value.trim()).matches()) { if (value == null || value.isBlank()) { - logger.warn("Ignoring empty of blank token-role in rule '{}'", + logger.warn("Ignoring empty or blank token-role in rule '{}'", mappingKey); return null; } else return value.trim(); - }).filter(g -> g != null).toList(); + }).filter(Objects::nonNull).toList(); break; case PROPERTY_TOKEN_GROUP: @@ -209,32 +228,33 @@ else if (!EMAIL_PATTERN.matcher(value.trim()).matches()) { if (value == null || value.isBlank()) { - logger.warn("Ignoring empty of blank token-group in rule '{}'", + logger.warn("Ignoring empty or blank token-group in rule '{}'", mappingKey); return null; } else return value.trim(); - }).filter(g -> g != null).toList(); + }).filter(Objects::nonNull).toList(); break; case PROPERTY_DSF_ROLE: - dsfRoles = getValues(property.getValue()).stream().map(value -> + dsfRoles = getRoleKeyAndValues(property.getValue()).stream().map(value -> { - if (value == null || value.isBlank()) + if (value == null || value.key().isBlank()) { - logger.warn("Ignoring empty of blank dsf-role in rule '{}'", + logger.warn("Ignoring empty or blank dsf-role in rule '{}'", mappingKey); return null; } - DsfRole dsfRole = dsfRoleFactory.apply(value.trim()); + R dsfRole = dsfRoleFactory.create(value); if (dsfRole == null) - logger.warn("Unknown dsf-role '{}', ignoring value in rule '{}'", - value, mappingKey); + logger.warn( + "Unknown or malformed dsf-role '{}', ignoring value in rule '{}'", + value.key(), mappingKey); return dsfRole; - }).filter(r -> r != null).toList(); + }).filter(Objects::nonNull).toList(); break; case PROPERTY_PRACTITIONER_ROLE: @@ -255,7 +275,7 @@ else if (!EMAIL_PATTERN.matcher(value.trim()).matches()) value, mappingKey); return coding; - }).filter(r -> r != null).toList(); + }).filter(Objects::nonNull).toList(); break; default: @@ -266,14 +286,12 @@ else if (!EMAIL_PATTERN.matcher(value.trim()).matches()) } } - entries.add(new Mapping((String) mappingKey, thumbprints, emails, tokenRoles, tokenGroups, - dsfRoles, practitionerRoles)); + entries.add(new Mapping((String) mappingKey, thumbprints, emails, tokenRoles, + tokenGroups, dsfRoles, practitionerRoles)); } else if (mappingKey != null && mappingKey instanceof String && (mappingValues == null || !(mappingValues instanceof Map))) - { logger.warn("Ignoring invalid rule '{}', no value specified or value not map", mappingKey); - } else logger.warn("Ignoring invalid rule '{}'", Objects.toString(mappingKey)); }); @@ -284,46 +302,74 @@ else if (mappingKey != null && mappingKey instanceof String } } - @SuppressWarnings("unchecked") - private static List getValues(Object o) + private List getValues(Object o) { return switch (o) { case String s -> List.of(s); - case @SuppressWarnings("rawtypes") List l -> l; + case List l -> l.stream().filter(v -> v instanceof String).map(v -> (String) v).toList(); default -> List.of(); }; } - public List getEntries() + private List getRoleKeyAndValues(Object o) + { + return switch (o) + { + case String s -> List.of(new RoleKeyAndValues(s)); + case List l -> getRoleKeyAndValuesFromList(l); + default -> List.of(); + }; + } + + private List getRoleKeyAndValuesFromList(List l) + { + return l.stream().map(v -> switch (v) + { + case String s -> new RoleKeyAndValues(s); + case Map m when m.size() == 1 -> getRoleKeyAndValuesFromMap(m); + default -> null; + }).filter(Objects::nonNull).toList(); + } + + private RoleKeyAndValues getRoleKeyAndValuesFromMap(Map m) + { + return m.entrySet().stream().findFirst().filter(e -> e.getKey() instanceof String) + .filter(e -> e.getValue() instanceof List l && l.stream().allMatch(v -> v instanceof String)) + .map(e -> new RoleKeyAndValues((String) e.getKey(), ((List) e.getValue()).stream() + .filter(v -> v instanceof String).map(v -> (String) v).toList())) + .orElse(null); + } + + public List> getEntries() { return Collections.unmodifiableList(entries); } - public List getDsfRolesForThumbprint(String thumbprint) + public List getDsfRolesForThumbprint(String thumbprint) { return getDsfRoleFor(Mapping::getThumbprints, thumbprint); } - public List getDsfRolesForEmail(String email) + public List getDsfRolesForEmail(String email) { return getDsfRoleFor(Mapping::getEmails, email); } - public List getDsfRolesForTokenRole(String tokenRole) + public List getDsfRolesForTokenRole(String tokenRole) { return getDsfRoleFor(Mapping::getTokenRoles, tokenRole); } - public List getDsfRolesForTokenGroup(String tokenGroup) + public List getDsfRolesForTokenGroup(String tokenGroup) { return getDsfRoleFor(Mapping::getTokenGroups, tokenGroup); } - private List getDsfRoleFor(Function> values, String value) + private List getDsfRoleFor(Function, List> values, String value) { - return getEntries().stream().filter(m -> values.apply(m).contains(value)).flatMap(m -> m.getDsfRoles().stream()) - .toList(); + return getEntries().stream().filter(m -> values.apply(m).contains(value)).map(Mapping::getDsfRoles) + .flatMap(List::stream).toList(); } public List getPractitionerRolesForThumbprint(String thumbprint) @@ -346,10 +392,10 @@ public List getPractitionerRolesForTokenGroup(String tokenGroup) return getPractitionerRoleFor(Mapping::getTokenGroups, tokenGroup); } - private List getPractitionerRoleFor(Function> values, String value) + private List getPractitionerRoleFor(Function, List> values, String value) { - return getEntries().stream().filter(m -> values.apply(m).contains(value)) - .flatMap(m -> m.getPractitionerRoles().stream()).toList(); + return getEntries().stream().filter(m -> values.apply(m).contains(value)).map(Mapping::getPractitionerRoles) + .flatMap(List::stream).toList(); } @Override diff --git a/dsf-common/dsf-common-auth/src/main/java/dev/dsf/common/auth/conf/RoleConfigReader.java b/dsf-common/dsf-common-auth/src/main/java/dev/dsf/common/auth/conf/RoleConfigReader.java index 656063823..510eac4f1 100644 --- a/dsf-common/dsf-common-auth/src/main/java/dev/dsf/common/auth/conf/RoleConfigReader.java +++ b/dsf-common/dsf-common-auth/src/main/java/dev/dsf/common/auth/conf/RoleConfigReader.java @@ -7,9 +7,11 @@ import org.hl7.fhir.r4.model.Coding; import org.yaml.snakeyaml.Yaml; +import dev.dsf.common.auth.conf.RoleConfig.DsfRoleFactory; + public class RoleConfigReader { - public RoleConfig read(String config, Function dsfRoleFactory, + public RoleConfig read(String config, DsfRoleFactory dsfRoleFactory, Function practitionerRoleFactory) { Objects.requireNonNull(config, "config"); @@ -17,10 +19,10 @@ public RoleConfig read(String config, Function dsfRoleFactory, Objects.requireNonNull(practitionerRoleFactory, "practitionerRoleFactory"); Object o = yaml().load(config); - return new RoleConfig(o, dsfRoleFactory, practitionerRoleFactory); + return new RoleConfig(o, dsfRoleFactory, practitionerRoleFactory); } - public RoleConfig read(InputStream config, Function dsfRoleFactory, + public RoleConfig read(InputStream config, DsfRoleFactory dsfRoleFactory, Function practitionerRoleFactory) { Objects.requireNonNull(config, "config"); @@ -28,7 +30,7 @@ public RoleConfig read(InputStream config, Function dsfRoleFact Objects.requireNonNull(practitionerRoleFactory, "practitionerRoleFactory"); Object o = yaml().load(config); - return new RoleConfig(o, dsfRoleFactory, practitionerRoleFactory); + return new RoleConfig(o, dsfRoleFactory, practitionerRoleFactory); } protected Yaml yaml() diff --git a/dsf-common/dsf-common-auth/src/test/java/dev/dsf/common/auth/RoleConfigTest.java b/dsf-common/dsf-common-auth/src/test/java/dev/dsf/common/auth/RoleConfigTest.java index 3e5018b08..1eb7675e2 100644 --- a/dsf-common/dsf-common-auth/src/test/java/dev/dsf/common/auth/RoleConfigTest.java +++ b/dsf-common/dsf-common-auth/src/test/java/dev/dsf/common/auth/RoleConfigTest.java @@ -5,8 +5,8 @@ import static org.junit.Assert.assertTrue; import java.util.List; +import java.util.Set; import java.util.function.Function; -import java.util.stream.Stream; import org.hl7.fhir.r4.model.Coding; import org.junit.Test; @@ -17,18 +17,35 @@ import dev.dsf.common.auth.conf.DsfRole; import dev.dsf.common.auth.conf.RoleConfig; import dev.dsf.common.auth.conf.RoleConfig.Mapping; +import dev.dsf.common.auth.conf.RoleConfig.RoleKeyAndValues; public class RoleConfigTest { private static final Logger logger = LoggerFactory.getLogger(RoleConfigTest.class); - private static enum TestRole implements DsfRole + private static interface TestRole extends DsfRole { - foo, bar, baz; + List resourceTypes(); + } + + private static record TestRoleImpl(String name, List resourceTypes) implements TestRole + { + private static final Set VALID_ROLES = Set.of("foo", "bar", "baz"); + private static final Set VALID_RESOURCES = Set.of("Task", "QuestionnaireResponse"); - public static boolean isValid(String s) + public static TestRoleImpl create(RoleKeyAndValues keyAndValues) { - return Stream.of(values()).map(Enum::name).anyMatch(n -> n.equals(s)); + if (VALID_ROLES.contains(keyAndValues.key()) + && keyAndValues.values().stream().allMatch(VALID_RESOURCES::contains)) + return new TestRoleImpl(keyAndValues.key(), keyAndValues.values()); + else + return null; + } + + @Override + public boolean matches(DsfRole role) + { + return false; } } @@ -58,7 +75,7 @@ public void testRead() throws Exception email: someone@test.com dsf-role: - foo - - bar + - bar: [Task, QuestionnaireResponse] - invalid practitioner-role: http://test.org/fhir/CodeSystem/foo|bar - test2: @@ -88,8 +105,8 @@ public void testRead() throws Exception return null; }; - RoleConfig roles = new RoleConfig(new Yaml().load(document), - s -> TestRole.isValid(s) ? TestRole.valueOf(s) : null, practitionerRoleFactory); + RoleConfig roles = new RoleConfig(new Yaml().load(document), TestRoleImpl::create, + practitionerRoleFactory); roles.getEntries().forEach(e -> logger.debug(e.toString())); assertNotNull(roles.getEntries()); @@ -97,24 +114,28 @@ public void testRead() throws Exception assertMapping("foo", List.of( "f7f9ef095c5c246d3e8149729221e668b6ffd9a117fe23e2687658f6a203d31a0e769fb20dc2af6361306717116c700c5905a895a7311057af461c5d78a257b5"), - List.of(), List.of(), List.of(), List.of(TestRole.foo, TestRole.bar, TestRole.baz), List.of(), - roles.getEntries().get(0)); + List.of(), List.of(), List.of(), List.of(new TestRoleImpl("foo", List.of()), + new TestRoleImpl("bar", List.of()), new TestRoleImpl("baz", List.of())), + List.of(), roles.getEntries().get(0)); assertMapping("bar", List.of( "2d259cc15ee2fe57bc11e1322040ee9e045dd3efb83ed1cb0f393c3bdfecaf3f6506e5573fbc213a1025a7c3dfef101fc8d85ab069e5662d666ea970c7e0cbb6", "b52a8b63b030181b8b6bc9ca1e47279da4842ef7ab46c08de6c5713a4e8ecc2c1d7f8cd5c17fe4eb0fe43838ee4b020a88634ea47c520dcc7f5f966b66e69190"), - List.of("one@test.com", "two@test.com"), List.of(), List.of(), List.of(TestRole.foo, TestRole.baz), - List.of(), roles.getEntries().get(1)); + List.of("one@test.com", "two@test.com"), List.of(), List.of(), + List.of(new TestRoleImpl("foo", List.of()), new TestRoleImpl("baz", List.of())), List.of(), + roles.getEntries().get(1)); assertMapping("test1", List.of(), List.of("someone@test.com"), List.of(), List.of(), - List.of(TestRole.foo, TestRole.bar), + List.of(new TestRoleImpl("foo", List.of()), + new TestRoleImpl("bar", List.of("Task", "QuestionnaireResponse"))), List.of(new Coding().setSystem("http://test.org/fhir/CodeSystem/foo").setCode("bar")), roles.getEntries().get(2)); - assertMapping("test2", List.of(), List.of(), List.of("claim_a", "claim_b"), List.of(), List.of(TestRole.foo), - List.of(), roles.getEntries().get(3)); + assertMapping("test2", List.of(), List.of(), List.of("claim_a", "claim_b"), List.of(), + List.of(new TestRoleImpl("foo", List.of())), List.of(), roles.getEntries().get(3)); - assertMapping("test3", List.of(), List.of(), List.of(), List.of("group1"), List.of(TestRole.foo), + assertMapping("test3", List.of(), List.of(), List.of(), List.of("group1"), + List.of(new TestRoleImpl("foo", List.of())), List.of(new Coding().setSystem("http://test.org/fhir/CodeSystem/foo").setCode("bar"), new Coding().setSystem("http://test.org/fhir/CodeSystem/foo").setCode("baz")), roles.getEntries().get(4)); @@ -122,7 +143,7 @@ public void testRead() throws Exception private void assertMapping(String expectedName, List expectedThumbprints, List expectedEmails, List expectedTokenRoles, List expectedTokenGroups, List expectedDsfRoles, - List expectedPractionerRole, Mapping actual) + List expectedPractionerRole, Mapping actual) { assertNotNull(actual); assertEquals(expectedName, actual.getName()); diff --git a/dsf-docker-test-setup-3dic-ttp/docker-compose.yml b/dsf-docker-test-setup-3dic-ttp/docker-compose.yml index 917c85c5b..a89155913 100644 --- a/dsf-docker-test-setup-3dic-ttp/docker-compose.yml +++ b/dsf-docker-test-setup-3dic-ttp/docker-compose.yml @@ -171,13 +171,11 @@ services: thumbprint: ${WEBBROWSER_TEST_USER_THUMBPRINT} token-role: admin dsf-role: - - CREATE + - CREATE: [Task] - READ - - UPDATE - - DELETE + - UPDATE: [QuestionnaireResponse] - SEARCH - HISTORY - - PERMANENT_DELETE practitioner-role: - http://dsf.dev/fhir/CodeSystem/practitioner-role|DSF_ADMIN - bpe-oidc-auth-client: @@ -260,13 +258,13 @@ services: thumbprint: ${WEBBROWSER_TEST_USER_THUMBPRINT} token-role: admin dsf-role: - - CREATE + - CREATE: + - Task - READ - - UPDATE - - DELETE + - UPDATE: + - QuestionnaireResponse - SEARCH - HISTORY - - PERMANENT_DELETE practitioner-role: - http://dsf.dev/fhir/CodeSystem/practitioner-role|DSF_ADMIN DEV_DSF_SERVER_AUTH_TRUST_CLIENT_CERTIFICATE_CAS: /run/secrets/ca_chain.crt @@ -342,13 +340,11 @@ services: thumbprint: ${WEBBROWSER_TEST_USER_THUMBPRINT} token-role: admin dsf-role: - - CREATE + - CREATE: [Task] - READ - - UPDATE - - DELETE + - UPDATE: [QuestionnaireResponse] - SEARCH - HISTORY - - PERMANENT_DELETE practitioner-role: - http://dsf.dev/fhir/CodeSystem/practitioner-role|DSF_ADMIN DEV_DSF_SERVER_AUTH_TRUST_CLIENT_CERTIFICATE_CAS: /run/secrets/ca_chain.crt @@ -431,13 +427,11 @@ services: thumbprint: ${WEBBROWSER_TEST_USER_THUMBPRINT} token-role: admin dsf-role: - - CREATE + - CREATE: [Task] - READ - - UPDATE - - DELETE + - UPDATE: [QuestionnaireResponse] - SEARCH - HISTORY - - PERMANENT_DELETE practitioner-role: - http://dsf.dev/fhir/CodeSystem/practitioner-role|DSF_ADMIN DEV_DSF_SERVER_AUTH_TRUST_CLIENT_CERTIFICATE_CAS: /run/secrets/ca_chain.crt diff --git a/dsf-docker-test-setup/fhir/docker-compose.yml b/dsf-docker-test-setup/fhir/docker-compose.yml index df9efa838..0fc5f7176 100755 --- a/dsf-docker-test-setup/fhir/docker-compose.yml +++ b/dsf-docker-test-setup/fhir/docker-compose.yml @@ -73,13 +73,11 @@ services: - webbrowser_test_user: thumbprint: ${WEBBROWSER_TEST_USER_THUMBPRINT} dsf-role: - - CREATE + - CREATE: [Task] - READ - - UPDATE - - DELETE + - UPDATE: [QuestionnaireResponse] - SEARCH - HISTORY - - PERMANENT_DELETE practitioner-role: - http://dsf.dev/fhir/CodeSystem/practitioner-role|DSF_ADMIN DEV_DSF_SERVER_AUTH_TRUST_CLIENT_CERTIFICATE_CAS: /run/secrets/ca_chain.crt diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/authentication/FhirServerRole.java b/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/authentication/FhirServerRole.java index f811fe70c..eb5fa1aa7 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/authentication/FhirServerRole.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/authentication/FhirServerRole.java @@ -1,22 +1,12 @@ package dev.dsf.fhir.authentication; -import java.util.EnumSet; -import java.util.Set; -import java.util.stream.Stream; +import java.util.List; + +import org.hl7.fhir.r4.model.ResourceType; import dev.dsf.common.auth.conf.DsfRole; -public enum FhirServerRole implements DsfRole +public interface FhirServerRole extends DsfRole { - CREATE, READ, UPDATE, DELETE, SEARCH, HISTORY, PERMANENT_DELETE, WEBSOCKET; - - public static final Set LOCAL_ORGANIZATION = EnumSet.of(CREATE, READ, UPDATE, DELETE, SEARCH, - HISTORY, PERMANENT_DELETE, WEBSOCKET); - public static final Set REMOTE_ORGANIZATION = EnumSet.of(CREATE, READ, UPDATE, DELETE, SEARCH, - HISTORY); - - public static boolean isValid(String role) - { - return role != null && !role.isBlank() && Stream.of(values()).map(Enum::name).anyMatch(n -> n.equals(role)); - } + List resourceTypes(); } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/authentication/FhirServerRoleImpl.java b/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/authentication/FhirServerRoleImpl.java new file mode 100644 index 000000000..2b829d4b8 --- /dev/null +++ b/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/authentication/FhirServerRoleImpl.java @@ -0,0 +1,267 @@ +package dev.dsf.fhir.authentication; + +import static dev.dsf.fhir.authentication.FhirServerRoleImpl.Operation.CREATE; +import static dev.dsf.fhir.authentication.FhirServerRoleImpl.Operation.DELETE; +import static dev.dsf.fhir.authentication.FhirServerRoleImpl.Operation.HISTORY; +import static dev.dsf.fhir.authentication.FhirServerRoleImpl.Operation.PERMANENT_DELETE; +import static dev.dsf.fhir.authentication.FhirServerRoleImpl.Operation.READ; +import static dev.dsf.fhir.authentication.FhirServerRoleImpl.Operation.SEARCH; +import static dev.dsf.fhir.authentication.FhirServerRoleImpl.Operation.UPDATE; +import static dev.dsf.fhir.authentication.FhirServerRoleImpl.Operation.WEBSOCKET; + +import java.util.EnumSet; +import java.util.List; +import java.util.Objects; +import java.util.Set; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import org.hl7.fhir.r4.model.ActivityDefinition; +import org.hl7.fhir.r4.model.Binary; +import org.hl7.fhir.r4.model.Bundle; +import org.hl7.fhir.r4.model.CodeSystem; +import org.hl7.fhir.r4.model.DocumentReference; +import org.hl7.fhir.r4.model.Endpoint; +import org.hl7.fhir.r4.model.Group; +import org.hl7.fhir.r4.model.HealthcareService; +import org.hl7.fhir.r4.model.Library; +import org.hl7.fhir.r4.model.Location; +import org.hl7.fhir.r4.model.Measure; +import org.hl7.fhir.r4.model.MeasureReport; +import org.hl7.fhir.r4.model.NamingSystem; +import org.hl7.fhir.r4.model.Organization; +import org.hl7.fhir.r4.model.OrganizationAffiliation; +import org.hl7.fhir.r4.model.Patient; +import org.hl7.fhir.r4.model.Practitioner; +import org.hl7.fhir.r4.model.PractitionerRole; +import org.hl7.fhir.r4.model.Provenance; +import org.hl7.fhir.r4.model.Questionnaire; +import org.hl7.fhir.r4.model.QuestionnaireResponse; +import org.hl7.fhir.r4.model.ResearchStudy; +import org.hl7.fhir.r4.model.Resource; +import org.hl7.fhir.r4.model.ResourceType; +import org.hl7.fhir.r4.model.StructureDefinition; +import org.hl7.fhir.r4.model.Subscription; +import org.hl7.fhir.r4.model.Task; +import org.hl7.fhir.r4.model.ValueSet; + +import dev.dsf.common.auth.conf.DsfRole; +import dev.dsf.common.auth.conf.RoleConfig.RoleKeyAndValues; + +public record FhirServerRoleImpl(Operation operation, List resourceTypes) implements FhirServerRole +{ + public static enum Operation + { + CREATE, READ, UPDATE, DELETE, SEARCH, HISTORY, PERMANENT_DELETE, WEBSOCKET; + + public FhirServerRole toFhirServerRoleAllResources() + { + return new FhirServerRoleImpl(this); + } + + public static boolean isValid(String operation) + { + return operation != null && !operation.isBlank() + && Stream.of(Operation.values()).map(Enum::name).anyMatch(n -> n.equals(operation)); + } + } + + public static final Set LOCAL_ORGANIZATION = EnumSet + .of(CREATE, READ, UPDATE, DELETE, SEARCH, HISTORY, PERMANENT_DELETE, WEBSOCKET).stream() + .map(Operation::toFhirServerRoleAllResources).collect(Collectors.toSet()); + + public static final Set REMOTE_ORGANIZATION = EnumSet + .of(CREATE, READ, UPDATE, DELETE, SEARCH, HISTORY).stream().map(Operation::toFhirServerRoleAllResources) + .collect(Collectors.toSet()); + + public static final Set INITIAL_DATA_LOADER = EnumSet.of(CREATE, DELETE, UPDATE).stream() + .map(Operation::toFhirServerRoleAllResources).collect(Collectors.toSet()); + + private static ResourceType forResourceClass(Class resourceClass) + { + if (ActivityDefinition.class.equals(resourceClass)) + return ResourceType.ActivityDefinition; + else if (Binary.class.equals(resourceClass)) + return ResourceType.Binary; + else if (Bundle.class.equals(resourceClass)) + return ResourceType.Bundle; + else if (CodeSystem.class.equals(resourceClass)) + return ResourceType.CodeSystem; + else if (DocumentReference.class.equals(resourceClass)) + return ResourceType.DocumentReference; + else if (Endpoint.class.equals(resourceClass)) + return ResourceType.Endpoint; + else if (Group.class.equals(resourceClass)) + return ResourceType.Group; + else if (HealthcareService.class.equals(resourceClass)) + return ResourceType.HealthcareService; + else if (Library.class.equals(resourceClass)) + return ResourceType.Library; + else if (Location.class.equals(resourceClass)) + return ResourceType.Location; + else if (Measure.class.equals(resourceClass)) + return ResourceType.Measure; + else if (MeasureReport.class.equals(resourceClass)) + return ResourceType.MeasureReport; + else if (NamingSystem.class.equals(resourceClass)) + return ResourceType.NamingSystem; + else if (OrganizationAffiliation.class.equals(resourceClass)) + return ResourceType.OrganizationAffiliation; + else if (Organization.class.equals(resourceClass)) + return ResourceType.Organization; + else if (Patient.class.equals(resourceClass)) + return ResourceType.Patient; + else if (Practitioner.class.equals(resourceClass)) + return ResourceType.Practitioner; + else if (PractitionerRole.class.equals(resourceClass)) + return ResourceType.PractitionerRole; + else if (Provenance.class.equals(resourceClass)) + return ResourceType.Provenance; + else if (Questionnaire.class.equals(resourceClass)) + return ResourceType.Questionnaire; + else if (QuestionnaireResponse.class.equals(resourceClass)) + return ResourceType.QuestionnaireResponse; + else if (ResearchStudy.class.equals(resourceClass)) + return ResourceType.ResearchStudy; + else if (StructureDefinition.class.equals(resourceClass)) + return ResourceType.StructureDefinition; + else if (Subscription.class.equals(resourceClass)) + return ResourceType.Subscription; + else if (Task.class.equals(resourceClass)) + return ResourceType.Task; + else if (ValueSet.class.equals(resourceClass)) + return ResourceType.ValueSet; + else + throw new IllegalArgumentException("Resource class '" + resourceClass.getName() + "' not supported"); + } + + public static FhirServerRole create(Class resourceClass) + { + return new FhirServerRoleImpl(CREATE, forResourceClass(resourceClass)); + } + + public static FhirServerRole read(Class resourceClass) + { + return read(forResourceClass(resourceClass)); + } + + public static FhirServerRole read(ResourceType resourceType) + { + return new FhirServerRoleImpl(READ, resourceType); + } + + public static FhirServerRole update(Class resourceClass) + { + return new FhirServerRoleImpl(UPDATE, forResourceClass(resourceClass)); + } + + public static FhirServerRole delete(Class resourceClass) + { + return new FhirServerRoleImpl(DELETE, forResourceClass(resourceClass)); + } + + public static FhirServerRole search(Class resourceClass) + { + return search(forResourceClass(resourceClass)); + } + + public static FhirServerRole search(ResourceType resourceType) + { + return new FhirServerRoleImpl(SEARCH, resourceType); + } + + public static FhirServerRole history(Class resourceClass) + { + return history(forResourceClass(resourceClass)); + } + + public static FhirServerRole history(ResourceType resourceType) + { + return new FhirServerRoleImpl(HISTORY, resourceType); + } + + public static FhirServerRole permanentDelete(Class resourceClass) + { + return permanentDelete(forResourceClass(resourceClass)); + } + + public static FhirServerRole permanentDelete(ResourceType resourceType) + { + return new FhirServerRoleImpl(PERMANENT_DELETE, resourceType); + } + + public static FhirServerRole websocket(Class resourceClass) + { + return new FhirServerRoleImpl(WEBSOCKET, forResourceClass(resourceClass)); + } + + private static final Set SUPPORTED_RESOURCES = Set.of(ResourceType.ActivityDefinition, ResourceType.Binary, + ResourceType.Bundle, ResourceType.CodeSystem, ResourceType.DocumentReference, ResourceType.Endpoint, + ResourceType.Group, ResourceType.HealthcareService, ResourceType.Library, ResourceType.Location, + ResourceType.Measure, ResourceType.MeasureReport, ResourceType.NamingSystem, + ResourceType.OrganizationAffiliation, ResourceType.Organization, ResourceType.Patient, + ResourceType.Practitioner, ResourceType.PractitionerRole, ResourceType.Provenance, + ResourceType.Questionnaire, ResourceType.QuestionnaireResponse, ResourceType.ResearchStudy, + ResourceType.StructureDefinition, ResourceType.Task, ResourceType.ValueSet).stream().map(Enum::name) + .collect(Collectors.toSet()); + + private static boolean isSupportedResource(String resource) + { + return resource != null && !resource.isBlank() && SUPPORTED_RESOURCES.contains(resource); + } + + public static FhirServerRoleImpl from(RoleKeyAndValues keyAndValues) + { + if (Operation.isValid(keyAndValues.key()) + && keyAndValues.values().stream().allMatch(FhirServerRoleImpl::isSupportedResource)) + { + Operation operation = Operation.valueOf(keyAndValues.key()); + List resourceTypes = keyAndValues.values().stream().map(ResourceType::valueOf).toList(); + + return new FhirServerRoleImpl(operation, resourceTypes); + } + else + return null; + } + + public FhirServerRoleImpl(Operation operation, List resourceTypes) + { + Objects.requireNonNull(operation, "operation"); + Objects.requireNonNull(resourceTypes, "resourceTypes"); + + this.operation = operation; + this.resourceTypes = resourceTypes; + } + + public FhirServerRoleImpl(Operation operation, ResourceType... resourceTypes) + { + this(operation, List.of(resourceTypes)); + } + + @Override + public String name() + { + return operation.name(); + } + + @Override + public boolean matches(DsfRole role) + { + if (this == role) + return true; + + return role instanceof FhirServerRoleImpl i + ? operation == i.operation && (resourceTypes.isEmpty() || resourceTypes.containsAll(i.resourceTypes)) + : false; + } + + @Override + public String toString() + { + if (!resourceTypes.isEmpty()) + return operation.name() + " " + + resourceTypes.stream().map(ResourceType::name).collect(Collectors.joining(", ", "[", "]")); + else + return operation.name(); + } +} diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/authentication/IdentityProviderImpl.java b/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/authentication/IdentityProviderImpl.java index 93d683fdf..de64c9723 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/authentication/IdentityProviderImpl.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/authentication/IdentityProviderImpl.java @@ -19,7 +19,8 @@ import dev.dsf.common.auth.conf.PractitionerIdentityImpl; import dev.dsf.common.auth.conf.RoleConfig; -public class IdentityProviderImpl extends AbstractIdentityProvider implements IdentityProvider, InitializingBean +public class IdentityProviderImpl extends AbstractIdentityProvider + implements IdentityProvider, InitializingBean { private static final Logger logger = LoggerFactory.getLogger(IdentityProviderImpl.class); @@ -27,7 +28,7 @@ public class IdentityProviderImpl extends AbstractIdentityProvider implements Id private final EndpointProvider endpointProvider; private final String localOrganizationIdentifierValue; - public IdentityProviderImpl(RoleConfig roleConfig, OrganizationProvider organizationProvider, + public IdentityProviderImpl(RoleConfig roleConfig, OrganizationProvider organizationProvider, EndpointProvider endpointProvider, String localOrganizationIdentifierValue) { super(roleConfig); @@ -73,7 +74,8 @@ public Identity getIdentity(X509Certificate[] certificates) boolean local = isLocalOrganization(o); Optional e = local ? getLocalEndpoint() : endpointProvider.getEndpoint(o, certificates[0]); - Set r = local ? FhirServerRole.LOCAL_ORGANIZATION : FhirServerRole.REMOTE_ORGANIZATION; + Set r = local ? FhirServerRoleImpl.LOCAL_ORGANIZATION + : FhirServerRoleImpl.REMOTE_ORGANIZATION; return new OrganizationIdentityImpl(local, o, e.orElse(null), r, certificates[0]); } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/authorization/AbstractAuthorizationRule.java b/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/authorization/AbstractAuthorizationRule.java index 8a1df0ed1..23f649f86 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/authorization/AbstractAuthorizationRule.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/authorization/AbstractAuthorizationRule.java @@ -22,6 +22,7 @@ import ca.uhn.fhir.model.api.annotation.ResourceDef; import dev.dsf.common.auth.conf.Identity; import dev.dsf.fhir.authentication.FhirServerRole; +import dev.dsf.fhir.authentication.FhirServerRoleImpl; import dev.dsf.fhir.authentication.OrganizationProvider; import dev.dsf.fhir.authorization.read.ReadAccessHelper; import dev.dsf.fhir.dao.CodeSystemDao; @@ -52,6 +53,15 @@ public abstract class AbstractAuthorizationRule resourceType, DaoProvider daoProvider, String serverBase, ReferenceResolver referenceResolver, OrganizationProvider organizationProvider, ReadAccessHelper readAccessHelper, ParameterConverter parameterConverter) @@ -63,6 +73,15 @@ public AbstractAuthorizationRule(Class resourceType, DaoProvider daoProvider, this.organizationProvider = organizationProvider; this.readAccessHelper = readAccessHelper; this.parameterConverter = parameterConverter; + + createRole = FhirServerRoleImpl.create(resourceType); + readRole = FhirServerRoleImpl.read(resourceType); + updateRole = FhirServerRoleImpl.update(resourceType); + deleteRole = FhirServerRoleImpl.delete(resourceType); + historyRole = FhirServerRoleImpl.history(resourceType); + searchRole = FhirServerRoleImpl.search(resourceType); + permanentDeleteRole = FhirServerRoleImpl.permanentDelete(resourceType); + websocketRole = FhirServerRoleImpl.websocket(resourceType); } @Override @@ -230,60 +249,6 @@ private boolean hasCode(CodeSystem codeSystem, String cCode) .map(ConceptDefinitionComponent::getCode).anyMatch(c -> c.equals(cCode)); } - protected final boolean isCurrentIdentityPartOfReferencedOrganization(Connection connection, Identity identity, - String referenceLocation, Reference reference) - { - if (reference == null) - { - logger.warn("Null reference while checking if user part of referenced organization"); - - return false; - } - else - { - ResourceReference resReference = new ResourceReference(referenceLocation, reference, Organization.class); - - ReferenceType type = resReference.getType(serverBase); - if (!EnumSet.of(ReferenceType.LITERAL_INTERNAL, ReferenceType.LOGICAL).contains(type)) - { - logger.warn("Reference of type {} not supported while checking if user part of referenced organization", - type); - - return false; - } - - Optional resource = referenceResolver.resolveReference(identity, resReference, connection); - if (resource.isPresent() && resource.get() instanceof Organization) - { - // ignoring updates (version changes) to the organization id - boolean sameOrganization = identity.getOrganization().getIdElement().getIdPart() - .equals(resource.get().getIdElement().getIdPart()); - if (!sameOrganization) - logger.warn( - "Current user not part of organization {} while checking if user part of referenced organization", - resource.get().getIdElement().getValue()); - - return sameOrganization; - } - else - { - logger.warn( - "Reference to organization could not be resolved while checking if user part of referenced organization"); - - return false; - } - } - } - - protected final boolean isLocalOrganization(Organization organization) - { - if (organization == null || !organization.hasIdElement()) - return false; - - return organizationProvider.getLocalOrganization() - .map(localOrg -> localOrg.getIdElement().equals(organization.getIdElement())).orElse(false); - } - @SafeVarargs protected final Optional createIfLiteralInternalOrLogicalReference(String referenceLocation, Reference reference, Class... referenceTypes) @@ -315,16 +280,16 @@ public Optional reasonPermanentDeleteAllowed(Identity identity, R oldRes @Override public final Optional reasonSearchAllowed(Identity identity) { - if (identity.hasDsfRole(FhirServerRole.SEARCH)) + if (identity.hasDsfRole(searchRole)) { logger.info("Search of {} authorized for identity '{}'", getResourceTypeName(), identity.getName()); - return Optional.of("Identity has role " + FhirServerRole.SEARCH); + return Optional.of("Identity has role " + searchRole); } else { logger.warn("Search of {} unauthorized for identity '{}', no role {}", getResourceTypeName(), - identity.getName(), FhirServerRole.SEARCH); + identity.getName(), searchRole); return Optional.empty(); } @@ -333,16 +298,16 @@ public final Optional reasonSearchAllowed(Identity identity) @Override public final Optional reasonHistoryAllowed(Identity identity) { - if (identity.hasDsfRole(FhirServerRole.HISTORY)) + if (identity.hasDsfRole(historyRole)) { logger.info("History of {} authorized for identity '{}'", getResourceTypeName(), identity.getName()); - return Optional.of("Identity has role " + FhirServerRole.HISTORY); + return Optional.of("Identity has role " + historyRole); } else { logger.warn("History of {} unauthorized for identity '{}', no role {}", getResourceTypeName(), - identity.getName(), FhirServerRole.HISTORY); + identity.getName(), historyRole); return Optional.empty(); } @@ -354,20 +319,57 @@ public Optional reasonPermanentDeleteAllowed(Connection connection, Iden final String resourceId = oldResource.getIdElement().getIdPart(); final long resourceVersion = oldResource.getIdElement().getVersionIdPartAsLong(); - if (identity.isLocalIdentity() && identity.hasDsfRole(FhirServerRole.PERMANENT_DELETE) + if (identity.isLocalIdentity() && identity.hasDsfRole(permanentDeleteRole) && reasonDeleteAllowed(connection, identity, oldResource).isPresent()) { logger.info("Permanent delete of {}/{}/_history/{} authorized for identity '{}'", getResourceTypeName(), resourceId, resourceVersion, identity.getName()); - return Optional.of("Identity is local identity and has role " + FhirServerRole.PERMANENT_DELETE); + return Optional.of("Identity is local identity and has role " + permanentDeleteRole); } else { logger.warn( "Permanent delete of {}/{}/_history/{} unauthorized for identity '{}', not a local identity or no role {}", - getResourceTypeName(), resourceId, resourceVersion, identity.getName(), - FhirServerRole.PERMANENT_DELETE); + getResourceTypeName(), resourceId, resourceVersion, identity.getName(), permanentDeleteRole); + + return Optional.empty(); + } + } + + @Override + public Optional reasonWebsocketAllowed(Identity identity, R existingResource) + { + try (Connection connection = daoProvider.newReadOnlyAutoCommitTransaction()) + { + return reasonWebsocketAllowed(connection, identity, existingResource); + } + catch (SQLException e) + { + logger.debug("Error while accessing database", e); + logger.warn("Error while accessing database: {} - {}", e.getClass().getName(), e.getMessage()); + + throw new RuntimeException(e); + } + } + + private Optional reasonWebsocketAllowed(Connection connection, Identity identity, R existingResource) + { + final String resourceId = existingResource.getIdElement().getIdPart(); + final long resourceVersion = existingResource.getIdElement().getVersionIdPartAsLong(); + + if (identity.isLocalIdentity() && identity.hasDsfRole(websocketRole)) + { + logger.info("Websocket access to {}/{}/_history/{} authorized for local identity '{}'", + getResourceTypeName(), resourceId, resourceVersion, identity.getName()); + + return Optional.of("Identity has role " + websocketRole); + } + else + { + logger.warn( + "Websocket access to {}/{}/_history/{} unauthorized for identity '{}', not a local identity or no role {}", + getResourceTypeName(), resourceId, resourceVersion, identity.getName(), websocketRole); return Optional.empty(); } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/authorization/AbstractMetaTagAuthorizationRule.java b/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/authorization/AbstractMetaTagAuthorizationRule.java index 4983a461c..4cf305636 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/authorization/AbstractMetaTagAuthorizationRule.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/authorization/AbstractMetaTagAuthorizationRule.java @@ -10,10 +10,8 @@ import org.hl7.fhir.r4.model.Resource; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.InitializingBean; import dev.dsf.common.auth.conf.Identity; -import dev.dsf.fhir.authentication.FhirServerRole; import dev.dsf.fhir.authentication.OrganizationProvider; import dev.dsf.fhir.authorization.read.ReadAccessHelper; import dev.dsf.fhir.dao.ReadAccessDao; @@ -23,7 +21,7 @@ import dev.dsf.fhir.service.ReferenceResolver; public abstract class AbstractMetaTagAuthorizationRule> - extends AbstractAuthorizationRule implements AuthorizationRule, InitializingBean + extends AbstractAuthorizationRule { private static final Logger logger = LoggerFactory.getLogger(AbstractMetaTagAuthorizationRule.class); @@ -49,7 +47,7 @@ protected final boolean hasValidReadAccessTag(Connection connection, Resource re @Override public final Optional reasonCreateAllowed(Connection connection, Identity identity, R newResource) { - if (identity.isLocalIdentity() && identity.hasDsfRole(FhirServerRole.CREATE)) + if (identity.isLocalIdentity() && identity.hasDsfRole(createRole)) { Optional errors = newResourceOkForCreate(connection, identity, newResource); if (errors.isEmpty()) @@ -58,7 +56,7 @@ public final Optional reasonCreateAllowed(Connection connection, Identit { logger.info("Create of {} authorized for identity '{}'", getResourceTypeName(), identity.getName()); - return Optional.of("Identity is local identity and has role " + FhirServerRole.CREATE); + return Optional.of("Identity is local identity and has role " + createRole); } else { @@ -77,7 +75,7 @@ public final Optional reasonCreateAllowed(Connection connection, Identit else { logger.warn("Create of {} unauthorized for identity '{}', not a local identity or no role {}", - getResourceTypeName(), identity.getName(), FhirServerRole.CREATE); + getResourceTypeName(), identity.getName(), createRole); return Optional.empty(); } @@ -94,7 +92,7 @@ public final Optional reasonReadAllowed(Connection connection, Identity existingResource.getIdElement().getIdPart()); final long resourceVersion = existingResource.getIdElement().getVersionIdPartAsLong(); - if (identity.hasDsfRole(FhirServerRole.READ)) + if (identity.hasDsfRole(readRole)) { try { @@ -119,7 +117,7 @@ public final Optional reasonReadAllowed(Connection connection, Identity getResourceTypeName(), resourceId.toString(), resourceVersion, identity.getName(), accessTypes.size() == 1 ? "tag" : "tags", tags); - return Optional.of("Identity has role " + FhirServerRole.READ + ", matching access " + return Optional.of("Identity has role " + readRole + ", matching access " + (accessTypes.size() == 1 ? "tag" : "tags") + " " + tags); } } @@ -134,7 +132,7 @@ public final Optional reasonReadAllowed(Connection connection, Identity else { logger.warn("Read of {}/{}/_history/{} unauthorized for identity '{}', no role {}", getResourceTypeName(), - resourceId.toString(), resourceVersion, identity.getName(), FhirServerRole.READ); + resourceId.toString(), resourceVersion, identity.getName(), readRole); return Optional.empty(); } @@ -149,7 +147,7 @@ public final Optional reasonUpdateAllowed(Connection connection, Identit final String resourceId = oldResource.getIdElement().getIdPart(); final long resourceVersion = oldResource.getIdElement().getVersionIdPartAsLong(); - if (identity.isLocalIdentity() && identity.hasDsfRole(FhirServerRole.UPDATE)) + if (identity.isLocalIdentity() && identity.hasDsfRole(updateRole)) { Optional errors = newResourceOkForUpdate(connection, identity, newResource); if (errors.isEmpty()) @@ -157,22 +155,22 @@ public final Optional reasonUpdateAllowed(Connection connection, Identit if (modificationsOk(connection, oldResource, newResource)) { logger.info("Update of {}/{}/_history/{} authorized for identity '{}'", getResourceTypeName(), - resourceId.toString(), resourceVersion, identity.getName()); + resourceId, resourceVersion, identity.getName()); - return Optional.of("Identity is local identity and has role " + FhirServerRole.UPDATE); + return Optional.of("Identity is local identity and has role " + updateRole); } else { logger.warn("Update of {}/{}/_history/{} unauthorized, modification not allowed", - getResourceTypeName(), resourceId.toString(), resourceVersion); + getResourceTypeName(), resourceId, resourceVersion); return Optional.empty(); } } else { - logger.warn("Update of {}/{}/_history/{} unauthorized, {}", getResourceTypeName(), - resourceId.toString(), resourceVersion, errors.get()); + logger.warn("Update of {}/{}/_history/{} unauthorized, {}", getResourceTypeName(), resourceId, + resourceVersion, errors.get()); return Optional.empty(); } @@ -181,8 +179,7 @@ public final Optional reasonUpdateAllowed(Connection connection, Identit { logger.warn( "Update of {}/{}/_history/{} unauthorized for identity '{}', not a local identity or no role {}", - getResourceTypeName(), resourceId.toString(), resourceVersion, identity.getName(), - FhirServerRole.UPDATE); + getResourceTypeName(), resourceId, resourceVersion, identity.getName(), updateRole); return Optional.empty(); } @@ -208,18 +205,18 @@ public final Optional reasonDeleteAllowed(Connection connection, Identit final String resourceId = oldResource.getIdElement().getIdPart(); final long resourceVersion = oldResource.getIdElement().getVersionIdPartAsLong(); - if (identity.isLocalIdentity() && identity.hasDsfRole(FhirServerRole.DELETE)) + if (identity.isLocalIdentity() && identity.hasDsfRole(deleteRole)) { logger.info("Delete of {}/{}/_history/{} authorized for identity '{}'", getResourceTypeName(), resourceId, resourceVersion, identity.getName()); - return Optional.of("Identity is local identity and has role " + FhirServerRole.DELETE); + return Optional.of("Identity is local identity and has role " + deleteRole); } else { logger.warn( "Delete of {}/{}/_history/{} unauthorized for identity '{}', not a local identity or no role {}", - getResourceTypeName(), resourceId, resourceVersion, identity.getName(), FhirServerRole.DELETE); + getResourceTypeName(), resourceId, resourceVersion, identity.getName(), deleteRole); return Optional.empty(); } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/authorization/AuthorizationRule.java b/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/authorization/AuthorizationRule.java index 5e3459159..3550ff194 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/authorization/AuthorizationRule.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/authorization/AuthorizationRule.java @@ -12,8 +12,6 @@ public interface AuthorizationRule Class getResourceType(); /** - * Override this method for non default behavior. Default: Not allowed. - * * @param identity * not null * @param newResource @@ -23,8 +21,6 @@ public interface AuthorizationRule Optional reasonCreateAllowed(Identity identity, R newResource); /** - * Override this method for non default behavior. Default: Not allowed. - * * @param connection * not null * @param identity @@ -36,8 +32,6 @@ public interface AuthorizationRule Optional reasonCreateAllowed(Connection connection, Identity identity, R newResource); /** - * Override this method for non default behavior. Default: Not allowed. - * * @param identity * not null * @param existingResource @@ -47,8 +41,6 @@ public interface AuthorizationRule Optional reasonReadAllowed(Identity identity, R existingResource); /** - * Override this method for non default behavior. Default: Not allowed. - * * @param connection * not null * @param identity @@ -60,8 +52,6 @@ public interface AuthorizationRule Optional reasonReadAllowed(Connection connection, Identity identity, R existingResource); /** - * Override this method for non default behavior. Default: Not allowed. - * * @param identity * not null * @param oldResource @@ -73,8 +63,6 @@ public interface AuthorizationRule Optional reasonUpdateAllowed(Identity identity, R oldResource, R newResource); /** - * Override this method for non default behavior. Default: Not allowed. - * * @param connection * not null * @param identity @@ -88,8 +76,6 @@ public interface AuthorizationRule Optional reasonUpdateAllowed(Connection connection, Identity identity, R oldResource, R newResource); /** - * Override this method for non default behavior. Default: Not allowed. - * * @param identity * not null * @param oldResource @@ -99,8 +85,6 @@ public interface AuthorizationRule Optional reasonDeleteAllowed(Identity identity, R oldResource); /** - * Override this method for non default behavior. Default: Not allowed. - * * @param connection * not null * @param identity @@ -112,8 +96,6 @@ public interface AuthorizationRule Optional reasonDeleteAllowed(Connection connection, Identity identity, R oldResource); /** - * Override this method for non default behavior. Default: Not allowed. - * * @param identity * not null * @return Reason as String in {@link Optional#of(Object)} if delete allowed @@ -121,8 +103,6 @@ public interface AuthorizationRule Optional reasonSearchAllowed(Identity identity); /** - * Override this method for non default behavior. Default: Not allowed. - * * @param identity * not null * @return Reason as String in {@link Optional#of(Object)} if delete allowed @@ -130,8 +110,6 @@ public interface AuthorizationRule Optional reasonHistoryAllowed(Identity identity); /** - * Override this method for non default behavior. Default: Not allowed. - * * @param identity * not null * @param oldResource @@ -141,8 +119,6 @@ public interface AuthorizationRule Optional reasonPermanentDeleteAllowed(Identity identity, R oldResource); /** - * Override this method for non default behavior. Default: Not allowed. - * * @param connection * not null * @param identity @@ -152,4 +128,13 @@ public interface AuthorizationRule * @return Reason as String in {@link Optional#of(Object)} if permanent delete allowed */ Optional reasonPermanentDeleteAllowed(Connection connection, Identity identity, R oldResource); + + /** + * @param identity + * not null + * @param existingResource + * not null + * @return Reason as String in {@link Optional#of(Object)} if websocket access to resource allowed + */ + Optional reasonWebsocketAllowed(Identity identity, R existingResource); } \ No newline at end of file diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/authorization/BinaryAuthorizationRule.java b/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/authorization/BinaryAuthorizationRule.java index 9b561e72e..9b0536cca 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/authorization/BinaryAuthorizationRule.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/authorization/BinaryAuthorizationRule.java @@ -77,8 +77,7 @@ private boolean hasValidSecurityContext(Connection connection, Identity identity { Optional ref = createIfLiteralInternalOrLogicalReference("Binary.securityContext", newResource.getSecurityContext()); - Optional securityContextOpt = ref - .flatMap(r -> referenceResolver.resolveReference(identity, r, connection)); + Optional securityContextOpt = ref.flatMap(r -> referenceResolver.resolveReference(r, connection)); return securityContextOpt.isPresent() && rules.containsKey(securityContextOpt.get().getClass()); } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/authorization/QuestionnaireResponseAuthorizationRule.java b/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/authorization/QuestionnaireResponseAuthorizationRule.java index a47fb36c4..26b67d1b9 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/authorization/QuestionnaireResponseAuthorizationRule.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/authorization/QuestionnaireResponseAuthorizationRule.java @@ -17,7 +17,6 @@ import org.slf4j.LoggerFactory; import dev.dsf.common.auth.conf.Identity; -import dev.dsf.fhir.authentication.FhirServerRole; import dev.dsf.fhir.authentication.OrganizationProvider; import dev.dsf.fhir.authorization.read.ReadAccessHelper; import dev.dsf.fhir.dao.QuestionnaireResponseDao; @@ -46,7 +45,7 @@ public QuestionnaireResponseAuthorizationRule(DaoProvider daoProvider, String se public Optional reasonCreateAllowed(Connection connection, Identity identity, QuestionnaireResponse newResource) { - if (identity.isLocalIdentity() && identity.hasDsfRole(FhirServerRole.CREATE)) + if (identity.isLocalIdentity() && identity.hasDsfRole(createRole)) { Optional errors = newResourceOk(newResource, EnumSet.of(QuestionnaireResponseStatus.INPROGRESS)); if (errors.isEmpty()) @@ -63,7 +62,7 @@ public Optional reasonCreateAllowed(Connection connection, Identity iden } else { - logger.warn("Create of QuestionnaireResponse unauthorized, not a local user"); + logger.warn("Create of QuestionnaireResponse unauthorized, not a local user or no create role"); return Optional.empty(); } } @@ -147,14 +146,14 @@ private Optional getItemAndValidate(QuestionnaireResponse newResource, S public Optional reasonReadAllowed(Connection connection, Identity identity, QuestionnaireResponse existingResource) { - if (identity.isLocalIdentity() && identity.hasDsfRole(FhirServerRole.READ)) + if (identity.isLocalIdentity() && identity.hasDsfRole(readRole)) { logger.info("Read of QuestionnaireResponse authorized for local user '{}'", identity.getName()); return Optional.of("task.restriction.recipient resolved and local user part of referenced organization"); } else { - logger.warn("Read of QuestionnaireResponse unauthorized, not a local user"); + logger.warn("Read of QuestionnaireResponse unauthorized, not a local user or no read role"); return Optional.empty(); } } @@ -163,7 +162,7 @@ public Optional reasonReadAllowed(Connection connection, Identity identi public Optional reasonUpdateAllowed(Connection connection, Identity identity, QuestionnaireResponse oldResource, QuestionnaireResponse newResource) { - if (identity.isLocalIdentity() && identity.hasDsfRole(FhirServerRole.UPDATE)) + if (identity.isLocalIdentity() && identity.hasDsfRole(updateRole)) { Optional errors = newResourceOk(newResource, EnumSet.of(QuestionnaireResponseStatus.COMPLETED, QuestionnaireResponseStatus.STOPPED)); @@ -189,7 +188,7 @@ public Optional reasonUpdateAllowed(Connection connection, Identity iden } else { - logger.warn("Update of QuestionnaireResponse unauthorized, not a local user"); + logger.warn("Update of QuestionnaireResponse unauthorized, not a local user or no update role"); return Optional.empty(); } } @@ -247,14 +246,14 @@ private boolean modificationsOk(QuestionnaireResponse oldResource, Questionnaire public Optional reasonDeleteAllowed(Connection connection, Identity identity, QuestionnaireResponse oldResource) { - if (identity.isLocalIdentity() && identity.hasDsfRole(FhirServerRole.DELETE)) + if (identity.isLocalIdentity() && identity.hasDsfRole(deleteRole)) { logger.info("Delete of QuestionnaireResponse authorized for local user '{}'", identity.getName()); return Optional.of("local user"); } else { - logger.warn("Delete of QuestionnaireResponse unauthorized, not a local user"); + logger.warn("Delete of QuestionnaireResponse unauthorized, not a local user or no delete role"); return Optional.empty(); } } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/authorization/RootAuthorizationRule.java b/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/authorization/RootAuthorizationRule.java index 0db7a2ddb..3874db0be 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/authorization/RootAuthorizationRule.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/authorization/RootAuthorizationRule.java @@ -7,8 +7,9 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import dev.dsf.common.auth.conf.DsfRole; import dev.dsf.common.auth.conf.Identity; -import dev.dsf.fhir.authentication.FhirServerRole; +import dev.dsf.fhir.authentication.FhirServerRoleImpl; public class RootAuthorizationRule implements AuthorizationRule { @@ -78,15 +79,16 @@ public Optional reasonSearchAllowed(Identity identity) @Override public Optional reasonHistoryAllowed(Identity identity) { - if (identity.hasDsfRole(FhirServerRole.HISTORY)) + if (identity.getDsfRoles().stream().map(DsfRole::name) + .anyMatch(FhirServerRoleImpl.Operation.HISTORY.name()::equals)) { logger.info("History of root authorized for identity '{}'", identity.getName()); - return Optional.of("Identity has role " + FhirServerRole.HISTORY); + return Optional.of("Identity has role " + FhirServerRoleImpl.Operation.HISTORY); } else { logger.warn("History of root unauthorized for identity '{}', no role {}", identity.getName(), - FhirServerRole.HISTORY); + FhirServerRoleImpl.Operation.HISTORY); return Optional.empty(); } } @@ -102,4 +104,10 @@ public Optional reasonPermanentDeleteAllowed(Connection connection, Iden { throw new UnsupportedOperationException(); } + + @Override + public Optional reasonWebsocketAllowed(Identity identity, Resource existingResource) + { + throw new UnsupportedOperationException(); + } } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/authorization/TaskAuthorizationRule.java b/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/authorization/TaskAuthorizationRule.java index c2ab8fc6f..ce1ebb649 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/authorization/TaskAuthorizationRule.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/authorization/TaskAuthorizationRule.java @@ -3,6 +3,7 @@ import java.sql.Connection; import java.sql.SQLException; import java.util.ArrayList; +import java.util.EnumSet; import java.util.List; import java.util.Map; import java.util.Objects; @@ -19,6 +20,7 @@ import org.hl7.fhir.r4.model.Identifier; import org.hl7.fhir.r4.model.Organization; import org.hl7.fhir.r4.model.OrganizationAffiliation; +import org.hl7.fhir.r4.model.Reference; import org.hl7.fhir.r4.model.Resource; import org.hl7.fhir.r4.model.StringType; import org.hl7.fhir.r4.model.Task; @@ -31,7 +33,6 @@ import dev.dsf.common.auth.conf.Identity; import dev.dsf.common.auth.conf.OrganizationIdentity; import dev.dsf.fhir.authentication.EndpointProvider; -import dev.dsf.fhir.authentication.FhirServerRole; import dev.dsf.fhir.authentication.OrganizationProvider; import dev.dsf.fhir.authorization.process.ProcessAuthorizationHelper; import dev.dsf.fhir.authorization.read.ReadAccessHelper; @@ -44,6 +45,7 @@ import dev.dsf.fhir.search.SearchQueryParameterError; import dev.dsf.fhir.service.ReferenceResolver; import dev.dsf.fhir.service.ResourceReference; +import dev.dsf.fhir.service.ResourceReference.ReferenceType; public class TaskAuthorizationRule extends AbstractAuthorizationRule { @@ -87,10 +89,64 @@ public void afterPropertiesSet() throws Exception Objects.requireNonNull(endpointProvider, "endpointProvider"); } + private boolean isCurrentIdentityPartOfReferencedOrganization(Connection connection, Identity identity, + String referenceLocation, Reference reference) + { + if (reference == null) + { + logger.warn("Null reference while checking if user part of referenced organization"); + + return false; + } + else + { + ResourceReference resReference = new ResourceReference(referenceLocation, reference, Organization.class); + + ReferenceType type = resReference.getType(serverBase); + if (!EnumSet.of(ReferenceType.LITERAL_INTERNAL, ReferenceType.LOGICAL).contains(type)) + { + logger.warn("Reference of type {} not supported while checking if user part of referenced organization", + type); + + return false; + } + + Optional resource = referenceResolver.resolveReference(resReference, connection); + if (resource.isPresent() && resource.get() instanceof Organization) + { + // ignoring updates (version changes) to the organization id + boolean sameOrganization = identity.getOrganization().getIdElement().getIdPart() + .equals(resource.get().getIdElement().getIdPart()); + if (!sameOrganization) + logger.warn( + "Current user not part of organization {} while checking if user part of referenced organization", + resource.get().getIdElement().getValue()); + + return sameOrganization; + } + else + { + logger.warn( + "Reference to organization could not be resolved while checking if user part of referenced organization"); + + return false; + } + } + } + + private boolean isLocalOrganization(Organization organization) + { + if (organization == null || !organization.hasIdElement()) + return false; + + return organizationProvider.getLocalOrganization() + .map(localOrg -> localOrg.getIdElement().equals(organization.getIdElement())).orElse(false); + } + @Override public Optional reasonCreateAllowed(Connection connection, Identity identity, Task newResource) { - if (identity.hasDsfRole(FhirServerRole.CREATE)) + if (identity.hasDsfRole(createRole)) { if (TaskStatus.DRAFT.equals(newResource.getStatus())) { @@ -173,8 +229,7 @@ else if (TaskStatus.REQUESTED.equals(newResource.getStatus())) } else { - logger.warn("Create of Task unauthorized for identity '{}', no role {}", identity.getName(), - FhirServerRole.CREATE); + logger.warn("Create of Task unauthorized for identity '{}', no role {}", identity.getName(), createRole); return Optional.empty(); } @@ -222,7 +277,7 @@ private Optional requestedTaskOk(Connection connection, Identity identit { ResourceReference reference = new ResourceReference("Task.restriction.recipient", newResource.getRestriction().getRecipientFirstRep(), Organization.class); - Optional recipient = referenceResolver.resolveReference(identity, reference, connection); + Optional recipient = referenceResolver.resolveReference(reference, connection); if (recipient.isPresent()) { if (recipient.get() instanceof Organization o) @@ -321,7 +376,7 @@ else if (newResource.getIdentifier().stream().filter(i -> NAMING_SYSTEM_TASK_IDE { ResourceReference reference = new ResourceReference("Task.requester", newResource.getRequester(), Organization.class); - Optional requester = referenceResolver.resolveReference(identity, reference, connection); + Optional requester = referenceResolver.resolveReference(reference, connection); if (requester.isPresent()) { if (requester.get() instanceof Organization o) @@ -350,7 +405,7 @@ else if (newResource.getIdentifier().stream().filter(i -> NAMING_SYSTEM_TASK_IDE { ResourceReference reference = new ResourceReference("Task.restriction.recipient", newResource.getRestriction().getRecipientFirstRep(), Organization.class); - Optional recipient = referenceResolver.resolveReference(identity, reference, connection); + Optional recipient = referenceResolver.resolveReference(reference, connection); if (recipient.isPresent()) { if (recipient.get() instanceof Organization o) @@ -641,11 +696,10 @@ private List getAffiliations(Connection connection, Str @Override public Optional reasonReadAllowed(Connection connection, Identity identity, Task existingResource) { - final String resourceId = parameterConverter - .toUuid(getResourceTypeName(), existingResource.getIdElement().getIdPart()).toString(); + final String resourceId = existingResource.getIdElement().getIdPart(); final long resourceVersion = existingResource.getIdElement().getVersionIdPartAsLong(); - if (identity.hasDsfRole(FhirServerRole.READ)) + if (identity.hasDsfRole(readRole)) { if (identity.isLocalIdentity() && isCurrentIdentityPartOfReferencedOrganization(connection, identity, "Task.restriction.recipient", existingResource.getRestriction().getRecipientFirstRep())) @@ -678,7 +732,7 @@ else if (isCurrentIdentityPartOfReferencedOrganization(connection, identity, "Ta else { logger.warn("Read of Task/{}/_history/{} unauthorized for identity '{}', no role {}", resourceId, - resourceVersion, identity.getName(), FhirServerRole.READ); + resourceVersion, identity.getName(), readRole); return Optional.empty(); } @@ -688,11 +742,10 @@ else if (isCurrentIdentityPartOfReferencedOrganization(connection, identity, "Ta public Optional reasonUpdateAllowed(Connection connection, Identity identity, Task oldResource, Task newResource) { - final String oldResourceId = parameterConverter - .toUuid(getResourceTypeName(), oldResource.getIdElement().getIdPart()).toString(); + final String oldResourceId = oldResource.getIdElement().getIdPart(); final long oldResourceVersion = oldResource.getIdElement().getVersionIdPartAsLong(); - if (identity.hasDsfRole(FhirServerRole.UPDATE)) + if (identity.hasDsfRole(updateRole)) { if (identity.isLocalIdentity() && identity instanceof OrganizationIdentity) { @@ -920,7 +973,7 @@ else if (TaskStatus.INPROGRESS.equals(oldResource.getStatus()) else { logger.warn("Update of Task/{}/_history/{} unauthorized for identity '{}', no role {}", oldResourceId, - oldResourceVersion, identity.getName(), FhirServerRole.UPDATE); + oldResourceVersion, identity.getName(), updateRole); return Optional.empty(); } @@ -1004,11 +1057,10 @@ private Predicate isBusinessKey() @Override public Optional reasonDeleteAllowed(Connection connection, Identity identity, Task oldResource) { - final String oldResourceId = parameterConverter - .toUuid(getResourceTypeName(), oldResource.getIdElement().getIdPart()).toString(); + final String oldResourceId = oldResource.getIdElement().getIdPart(); final long oldResourceVersion = oldResource.getIdElement().getVersionIdPartAsLong(); - if (identity.hasDsfRole(FhirServerRole.DELETE)) + if (identity.hasDsfRole(deleteRole)) { if (identity.isLocalIdentity() && identity instanceof OrganizationIdentity) { @@ -1039,7 +1091,7 @@ public Optional reasonDeleteAllowed(Connection connection, Identity iden else { logger.warn("Delete of Task/{}/_history/{} unauthorized for identity '{}', no role {}", oldResourceId, - oldResourceVersion, identity.getName(), FhirServerRole.DELETE); + oldResourceVersion, identity.getName(), deleteRole); return Optional.empty(); } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/dao/command/AbstractCommandWithResource.java b/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/dao/command/AbstractCommandWithResource.java index 3a74cebb5..46f3079e2 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/dao/command/AbstractCommandWithResource.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/dao/command/AbstractCommandWithResource.java @@ -35,16 +35,8 @@ public AbstractCommandWithResource(int transactionPriority, int index, Identity this.exceptionHandler = exceptionHandler; this.parameterConverter = parameterConverter; - referencesHelper = createReferencesHelper(index, identity, serverBase, resource, responseGenerator, - referenceExtractor, referenceResolver); - } - - protected ReferencesHelper createReferencesHelper(int index, Identity identity, String serverBase, R resource, - ResponseGenerator responseGenerator, ReferenceExtractor referenceExtractor, - ReferenceResolver referenceResolver) - { - return new ReferencesHelperImpl<>(index, identity, resource, serverBase, referenceExtractor, referenceResolver, - responseGenerator); + referencesHelper = new ReferencesHelperImpl<>(index, resource, serverBase, referenceExtractor, + referenceResolver, responseGenerator); } @Override diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/dao/command/ReferencesHelperImpl.java b/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/dao/command/ReferencesHelperImpl.java index 1890fafb4..447a3aaf1 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/dao/command/ReferencesHelperImpl.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/dao/command/ReferencesHelperImpl.java @@ -16,7 +16,6 @@ import org.hl7.fhir.r4.model.Resource; import org.hl7.fhir.r4.model.Type; -import dev.dsf.common.auth.conf.Identity; import dev.dsf.fhir.help.ResponseGenerator; import dev.dsf.fhir.service.ReferenceExtractor; import dev.dsf.fhir.service.ReferenceResolver; @@ -29,19 +28,16 @@ public final class ReferencesHelperImpl implements ReferencesHelper { private final int index; - private final Identity identity; private final R resource; private final String serverBase; private final ReferenceExtractor referenceExtractor; private final ReferenceResolver referenceResolver; private final ResponseGenerator responseGenerator; - public ReferencesHelperImpl(int index, Identity identity, R resource, String serverBase, - ReferenceExtractor referenceExtractor, ReferenceResolver referenceResolver, - ResponseGenerator responseGenerator) + public ReferencesHelperImpl(int index, R resource, String serverBase, ReferenceExtractor referenceExtractor, + ReferenceResolver referenceResolver, ResponseGenerator responseGenerator) { this.index = index; - this.identity = identity; this.resource = resource; this.serverBase = serverBase; this.referenceExtractor = referenceExtractor; @@ -136,7 +132,7 @@ private Optional resolveTemporary(ResourceReference reference, private Optional resolveConditional(ResourceReference reference, Connection connection, Consumer targetConsumer) { - Optional resolvedResource = referenceResolver.resolveReference(identity, reference, connection); + Optional resolvedResource = referenceResolver.resolveReference(reference, connection); if (resolvedResource.isPresent()) { Resource target = resolvedResource.get(); @@ -181,7 +177,7 @@ public void resolveLogicalReferences(Connection connection) throws WebApplicatio private Optional resolveLogicalReference(ResourceReference reference, Connection connection) { - Optional resolvedResource = referenceResolver.resolveReference(identity, reference, connection); + Optional resolvedResource = referenceResolver.resolveReference(reference, connection); if (resolvedResource.isPresent()) { Resource target = resolvedResource.get(); @@ -222,10 +218,9 @@ private Optional checkReference(ResourceReference reference, C case LITERAL_EXTERNAL, RELATED_ARTEFACT_LITERAL_EXTERNAL_URL, ATTACHMENT_LITERAL_EXTERNAL_URL -> referenceResolver.checkLiteralExternalReference(resource, reference, index); - case LOGICAL -> referenceResolver.checkLogicalReference(identity, resource, reference, connection, index); + case LOGICAL -> referenceResolver.checkLogicalReference(resource, reference, connection, index); - case CANONICAL -> - referenceResolver.checkCanonicalReference(identity, resource, reference, connection, index); + case CANONICAL -> referenceResolver.checkCanonicalReference(resource, reference, connection, index); // unknown URLs to non FHIR servers in related artifacts must not be checked case RELATED_ARTEFACT_UNKNOWN_URL, ATTACHMENT_UNKNOWN_URL -> Optional.empty(); diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/history/filter/ActivityDefinitionHistoryIdentityFilter.java b/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/history/filter/ActivityDefinitionHistoryIdentityFilter.java index e555003cf..16f348530 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/history/filter/ActivityDefinitionHistoryIdentityFilter.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/history/filter/ActivityDefinitionHistoryIdentityFilter.java @@ -1,19 +1,21 @@ package dev.dsf.fhir.history.filter; -import org.hl7.fhir.r4.model.ActivityDefinition; +import org.hl7.fhir.r4.model.ResourceType; -import ca.uhn.fhir.model.api.annotation.ResourceDef; import dev.dsf.common.auth.conf.Identity; +import dev.dsf.fhir.authentication.FhirServerRole; +import dev.dsf.fhir.authentication.FhirServerRoleImpl; import dev.dsf.fhir.search.filter.ActivityDefinitionIdentityFilter; public class ActivityDefinitionHistoryIdentityFilter extends ActivityDefinitionIdentityFilter implements HistoryIdentityFilter { - private static final String RESOURCE_TYPE = ActivityDefinition.class.getAnnotation(ResourceDef.class).name(); + private static final FhirServerRole HISTORY_ROLE = FhirServerRoleImpl.history(ResourceType.ActivityDefinition); + private static final String RESOURCE_TYPE = ResourceType.ActivityDefinition.name(); public ActivityDefinitionHistoryIdentityFilter(Identity identity) { - super(identity, HistoryIdentityFilter.RESOURCE_TABLE, HistoryIdentityFilter.RESOURCE_ID_COLUMN); + super(identity, HistoryIdentityFilter.RESOURCE_TABLE, HistoryIdentityFilter.RESOURCE_ID_COLUMN, HISTORY_ROLE); } @Override diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/history/filter/BinaryHistoryIdentityFilter.java b/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/history/filter/BinaryHistoryIdentityFilter.java index aefedf6d6..e3537102f 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/history/filter/BinaryHistoryIdentityFilter.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/history/filter/BinaryHistoryIdentityFilter.java @@ -1,18 +1,20 @@ package dev.dsf.fhir.history.filter; -import org.hl7.fhir.r4.model.Binary; +import org.hl7.fhir.r4.model.ResourceType; -import ca.uhn.fhir.model.api.annotation.ResourceDef; import dev.dsf.common.auth.conf.Identity; +import dev.dsf.fhir.authentication.FhirServerRole; +import dev.dsf.fhir.authentication.FhirServerRoleImpl; import dev.dsf.fhir.search.filter.BinaryIdentityFilter; public class BinaryHistoryIdentityFilter extends BinaryIdentityFilter implements HistoryIdentityFilter { - private static final String RESOURCE_TYPE = Binary.class.getAnnotation(ResourceDef.class).name(); + private static final FhirServerRole HISTORY_ROLE = FhirServerRoleImpl.history(ResourceType.Binary); + private static final String RESOURCE_TYPE = ResourceType.Binary.name(); public BinaryHistoryIdentityFilter(Identity identity) { - super(identity, HistoryIdentityFilter.RESOURCE_TABLE, HistoryIdentityFilter.RESOURCE_ID_COLUMN); + super(identity, HistoryIdentityFilter.RESOURCE_TABLE, HistoryIdentityFilter.RESOURCE_ID_COLUMN, HISTORY_ROLE); } @Override diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/history/filter/BundleHistoryIdentityFilter.java b/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/history/filter/BundleHistoryIdentityFilter.java index 027f7232c..a43bff579 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/history/filter/BundleHistoryIdentityFilter.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/history/filter/BundleHistoryIdentityFilter.java @@ -1,18 +1,20 @@ package dev.dsf.fhir.history.filter; -import org.hl7.fhir.r4.model.Bundle; +import org.hl7.fhir.r4.model.ResourceType; -import ca.uhn.fhir.model.api.annotation.ResourceDef; import dev.dsf.common.auth.conf.Identity; +import dev.dsf.fhir.authentication.FhirServerRole; +import dev.dsf.fhir.authentication.FhirServerRoleImpl; import dev.dsf.fhir.search.filter.BundleIdentityFilter; public class BundleHistoryIdentityFilter extends BundleIdentityFilter implements HistoryIdentityFilter { - private static final String RESOURCE_TYPE = Bundle.class.getAnnotation(ResourceDef.class).name(); + private static final FhirServerRole HISTORY_ROLE = FhirServerRoleImpl.history(ResourceType.Bundle); + private static final String RESOURCE_TYPE = ResourceType.Bundle.name(); public BundleHistoryIdentityFilter(Identity identity) { - super(identity, HistoryIdentityFilter.RESOURCE_TABLE, HistoryIdentityFilter.RESOURCE_ID_COLUMN); + super(identity, HistoryIdentityFilter.RESOURCE_TABLE, HistoryIdentityFilter.RESOURCE_ID_COLUMN, HISTORY_ROLE); } @Override diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/history/filter/CodeSystemHistoryIdentityFilter.java b/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/history/filter/CodeSystemHistoryIdentityFilter.java index dd2e59f7a..dcf0d4ba0 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/history/filter/CodeSystemHistoryIdentityFilter.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/history/filter/CodeSystemHistoryIdentityFilter.java @@ -1,18 +1,20 @@ package dev.dsf.fhir.history.filter; -import org.hl7.fhir.r4.model.CodeSystem; +import org.hl7.fhir.r4.model.ResourceType; -import ca.uhn.fhir.model.api.annotation.ResourceDef; import dev.dsf.common.auth.conf.Identity; +import dev.dsf.fhir.authentication.FhirServerRole; +import dev.dsf.fhir.authentication.FhirServerRoleImpl; import dev.dsf.fhir.search.filter.CodeSystemIdentityFilter; public class CodeSystemHistoryIdentityFilter extends CodeSystemIdentityFilter implements HistoryIdentityFilter { - private static final String RESOURCE_TYPE = CodeSystem.class.getAnnotation(ResourceDef.class).name(); + private static final FhirServerRole HISTORY_ROLE = FhirServerRoleImpl.history(ResourceType.CodeSystem); + private static final String RESOURCE_TYPE = ResourceType.CodeSystem.name(); public CodeSystemHistoryIdentityFilter(Identity identity) { - super(identity, HistoryIdentityFilter.RESOURCE_TABLE, HistoryIdentityFilter.RESOURCE_ID_COLUMN); + super(identity, HistoryIdentityFilter.RESOURCE_TABLE, HistoryIdentityFilter.RESOURCE_ID_COLUMN, HISTORY_ROLE); } @Override diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/history/filter/DocumentReferenceHistoryIdentityFilter.java b/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/history/filter/DocumentReferenceHistoryIdentityFilter.java index 7fe070511..cbd1332fb 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/history/filter/DocumentReferenceHistoryIdentityFilter.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/history/filter/DocumentReferenceHistoryIdentityFilter.java @@ -1,19 +1,21 @@ package dev.dsf.fhir.history.filter; -import org.hl7.fhir.r4.model.DocumentReference; +import org.hl7.fhir.r4.model.ResourceType; -import ca.uhn.fhir.model.api.annotation.ResourceDef; import dev.dsf.common.auth.conf.Identity; +import dev.dsf.fhir.authentication.FhirServerRole; +import dev.dsf.fhir.authentication.FhirServerRoleImpl; import dev.dsf.fhir.search.filter.DocumentReferenceIdentityFilter; public class DocumentReferenceHistoryIdentityFilter extends DocumentReferenceIdentityFilter implements HistoryIdentityFilter { - private static final String RESOURCE_TYPE = DocumentReference.class.getAnnotation(ResourceDef.class).name(); + private static final FhirServerRole HISTORY_ROLE = FhirServerRoleImpl.history(ResourceType.DocumentReference); + private static final String RESOURCE_TYPE = ResourceType.DocumentReference.name(); public DocumentReferenceHistoryIdentityFilter(Identity identity) { - super(identity, HistoryIdentityFilter.RESOURCE_TABLE, HistoryIdentityFilter.RESOURCE_ID_COLUMN); + super(identity, HistoryIdentityFilter.RESOURCE_TABLE, HistoryIdentityFilter.RESOURCE_ID_COLUMN, HISTORY_ROLE); } @Override diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/history/filter/EndpointHistoryIdentityFilter.java b/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/history/filter/EndpointHistoryIdentityFilter.java index 1d4aa641e..4b29edf03 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/history/filter/EndpointHistoryIdentityFilter.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/history/filter/EndpointHistoryIdentityFilter.java @@ -1,18 +1,20 @@ package dev.dsf.fhir.history.filter; -import org.hl7.fhir.r4.model.Endpoint; +import org.hl7.fhir.r4.model.ResourceType; -import ca.uhn.fhir.model.api.annotation.ResourceDef; import dev.dsf.common.auth.conf.Identity; +import dev.dsf.fhir.authentication.FhirServerRole; +import dev.dsf.fhir.authentication.FhirServerRoleImpl; import dev.dsf.fhir.search.filter.EndpointIdentityFilter; public class EndpointHistoryIdentityFilter extends EndpointIdentityFilter implements HistoryIdentityFilter { - private static final String RESOURCE_TYPE = Endpoint.class.getAnnotation(ResourceDef.class).name(); + private static final FhirServerRole HISTORY_ROLE = FhirServerRoleImpl.history(ResourceType.Endpoint); + private static final String RESOURCE_TYPE = ResourceType.Endpoint.name(); public EndpointHistoryIdentityFilter(Identity identity) { - super(identity, HistoryIdentityFilter.RESOURCE_TABLE, HistoryIdentityFilter.RESOURCE_ID_COLUMN); + super(identity, HistoryIdentityFilter.RESOURCE_TABLE, HistoryIdentityFilter.RESOURCE_ID_COLUMN, HISTORY_ROLE); } @Override diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/history/filter/GroupHistoryIdentityFilter.java b/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/history/filter/GroupHistoryIdentityFilter.java index f37c7c6df..d2d4296aa 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/history/filter/GroupHistoryIdentityFilter.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/history/filter/GroupHistoryIdentityFilter.java @@ -1,18 +1,20 @@ package dev.dsf.fhir.history.filter; -import org.hl7.fhir.r4.model.Group; +import org.hl7.fhir.r4.model.ResourceType; -import ca.uhn.fhir.model.api.annotation.ResourceDef; import dev.dsf.common.auth.conf.Identity; +import dev.dsf.fhir.authentication.FhirServerRole; +import dev.dsf.fhir.authentication.FhirServerRoleImpl; import dev.dsf.fhir.search.filter.GroupIdentityFilter; public class GroupHistoryIdentityFilter extends GroupIdentityFilter implements HistoryIdentityFilter { - private static final String RESOURCE_TYPE = Group.class.getAnnotation(ResourceDef.class).name(); + private static final FhirServerRole HISTORY_ROLE = FhirServerRoleImpl.history(ResourceType.Group); + private static final String RESOURCE_TYPE = ResourceType.Group.name(); public GroupHistoryIdentityFilter(Identity identity) { - super(identity, HistoryIdentityFilter.RESOURCE_TABLE, HistoryIdentityFilter.RESOURCE_ID_COLUMN); + super(identity, HistoryIdentityFilter.RESOURCE_TABLE, HistoryIdentityFilter.RESOURCE_ID_COLUMN, HISTORY_ROLE); } @Override diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/history/filter/HealthcareServiceHistoryIdentityFilter.java b/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/history/filter/HealthcareServiceHistoryIdentityFilter.java index 9b20762ee..afcc81091 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/history/filter/HealthcareServiceHistoryIdentityFilter.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/history/filter/HealthcareServiceHistoryIdentityFilter.java @@ -1,19 +1,21 @@ package dev.dsf.fhir.history.filter; -import org.hl7.fhir.r4.model.HealthcareService; +import org.hl7.fhir.r4.model.ResourceType; -import ca.uhn.fhir.model.api.annotation.ResourceDef; import dev.dsf.common.auth.conf.Identity; +import dev.dsf.fhir.authentication.FhirServerRole; +import dev.dsf.fhir.authentication.FhirServerRoleImpl; import dev.dsf.fhir.search.filter.HealthcareServiceIdentityFilter; public class HealthcareServiceHistoryIdentityFilter extends HealthcareServiceIdentityFilter implements HistoryIdentityFilter { - private static final String RESOURCE_TYPE = HealthcareService.class.getAnnotation(ResourceDef.class).name(); + private static final FhirServerRole HISTORY_ROLE = FhirServerRoleImpl.history(ResourceType.HealthcareService); + private static final String RESOURCE_TYPE = ResourceType.HealthcareService.name(); public HealthcareServiceHistoryIdentityFilter(Identity identity) { - super(identity, HistoryIdentityFilter.RESOURCE_TABLE, HistoryIdentityFilter.RESOURCE_ID_COLUMN); + super(identity, HistoryIdentityFilter.RESOURCE_TABLE, HistoryIdentityFilter.RESOURCE_ID_COLUMN, HISTORY_ROLE); } @Override diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/history/filter/LibraryHistoryIdentityFilter.java b/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/history/filter/LibraryHistoryIdentityFilter.java index ac4735709..aefa2dd34 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/history/filter/LibraryHistoryIdentityFilter.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/history/filter/LibraryHistoryIdentityFilter.java @@ -1,18 +1,20 @@ package dev.dsf.fhir.history.filter; -import org.hl7.fhir.r4.model.Library; +import org.hl7.fhir.r4.model.ResourceType; -import ca.uhn.fhir.model.api.annotation.ResourceDef; import dev.dsf.common.auth.conf.Identity; +import dev.dsf.fhir.authentication.FhirServerRole; +import dev.dsf.fhir.authentication.FhirServerRoleImpl; import dev.dsf.fhir.search.filter.LibraryIdentityFilter; public class LibraryHistoryIdentityFilter extends LibraryIdentityFilter implements HistoryIdentityFilter { - private static final String RESOURCE_TYPE = Library.class.getAnnotation(ResourceDef.class).name(); + private static final FhirServerRole HISTORY_ROLE = FhirServerRoleImpl.history(ResourceType.Library); + private static final String RESOURCE_TYPE = ResourceType.Library.name(); public LibraryHistoryIdentityFilter(Identity identity) { - super(identity, HistoryIdentityFilter.RESOURCE_TABLE, HistoryIdentityFilter.RESOURCE_ID_COLUMN); + super(identity, HistoryIdentityFilter.RESOURCE_TABLE, HistoryIdentityFilter.RESOURCE_ID_COLUMN, HISTORY_ROLE); } @Override diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/history/filter/LocationHistoryIdentityFilter.java b/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/history/filter/LocationHistoryIdentityFilter.java index b64107970..1470955fe 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/history/filter/LocationHistoryIdentityFilter.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/history/filter/LocationHistoryIdentityFilter.java @@ -1,18 +1,20 @@ package dev.dsf.fhir.history.filter; -import org.hl7.fhir.r4.model.Location; +import org.hl7.fhir.r4.model.ResourceType; -import ca.uhn.fhir.model.api.annotation.ResourceDef; import dev.dsf.common.auth.conf.Identity; +import dev.dsf.fhir.authentication.FhirServerRole; +import dev.dsf.fhir.authentication.FhirServerRoleImpl; import dev.dsf.fhir.search.filter.LocationIdentityFilter; public class LocationHistoryIdentityFilter extends LocationIdentityFilter implements HistoryIdentityFilter { - private static final String RESOURCE_TYPE = Location.class.getAnnotation(ResourceDef.class).name(); + private static final FhirServerRole HISTORY_ROLE = FhirServerRoleImpl.history(ResourceType.Location); + private static final String RESOURCE_TYPE = ResourceType.Location.name(); public LocationHistoryIdentityFilter(Identity identity) { - super(identity, HistoryIdentityFilter.RESOURCE_TABLE, HistoryIdentityFilter.RESOURCE_ID_COLUMN); + super(identity, HistoryIdentityFilter.RESOURCE_TABLE, HistoryIdentityFilter.RESOURCE_ID_COLUMN, HISTORY_ROLE); } @Override diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/history/filter/MeasureHistoryIdentityFilter.java b/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/history/filter/MeasureHistoryIdentityFilter.java index 8a5982cdc..1865efd09 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/history/filter/MeasureHistoryIdentityFilter.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/history/filter/MeasureHistoryIdentityFilter.java @@ -1,18 +1,20 @@ package dev.dsf.fhir.history.filter; -import org.hl7.fhir.r4.model.Measure; +import org.hl7.fhir.r4.model.ResourceType; -import ca.uhn.fhir.model.api.annotation.ResourceDef; import dev.dsf.common.auth.conf.Identity; +import dev.dsf.fhir.authentication.FhirServerRole; +import dev.dsf.fhir.authentication.FhirServerRoleImpl; import dev.dsf.fhir.search.filter.MeasureIdentityFilter; public class MeasureHistoryIdentityFilter extends MeasureIdentityFilter implements HistoryIdentityFilter { - private static final String RESOURCE_TYPE = Measure.class.getAnnotation(ResourceDef.class).name(); + private static final FhirServerRole HISTORY_ROLE = FhirServerRoleImpl.history(ResourceType.Measure); + private static final String RESOURCE_TYPE = ResourceType.Measure.name(); public MeasureHistoryIdentityFilter(Identity identity) { - super(identity, HistoryIdentityFilter.RESOURCE_TABLE, HistoryIdentityFilter.RESOURCE_ID_COLUMN); + super(identity, HistoryIdentityFilter.RESOURCE_TABLE, HistoryIdentityFilter.RESOURCE_ID_COLUMN, HISTORY_ROLE); } @Override diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/history/filter/MeasureReportHistoryIdentityFilter.java b/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/history/filter/MeasureReportHistoryIdentityFilter.java index 893be8d01..8d16db7c7 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/history/filter/MeasureReportHistoryIdentityFilter.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/history/filter/MeasureReportHistoryIdentityFilter.java @@ -1,18 +1,20 @@ package dev.dsf.fhir.history.filter; -import org.hl7.fhir.r4.model.MeasureReport; +import org.hl7.fhir.r4.model.ResourceType; -import ca.uhn.fhir.model.api.annotation.ResourceDef; import dev.dsf.common.auth.conf.Identity; +import dev.dsf.fhir.authentication.FhirServerRole; +import dev.dsf.fhir.authentication.FhirServerRoleImpl; import dev.dsf.fhir.search.filter.MeasureReportIdentityFilter; public class MeasureReportHistoryIdentityFilter extends MeasureReportIdentityFilter implements HistoryIdentityFilter { - private static final String RESOURCE_TYPE = MeasureReport.class.getAnnotation(ResourceDef.class).name(); + private static final FhirServerRole HISTORY_ROLE = FhirServerRoleImpl.history(ResourceType.MeasureReport); + private static final String RESOURCE_TYPE = ResourceType.MeasureReport.name(); public MeasureReportHistoryIdentityFilter(Identity identity) { - super(identity, HistoryIdentityFilter.RESOURCE_TABLE, HistoryIdentityFilter.RESOURCE_ID_COLUMN); + super(identity, HistoryIdentityFilter.RESOURCE_TABLE, HistoryIdentityFilter.RESOURCE_ID_COLUMN, HISTORY_ROLE); } @Override diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/history/filter/NamingSystemHistoryIdentityFilter.java b/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/history/filter/NamingSystemHistoryIdentityFilter.java index a4afe2665..ec1385c37 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/history/filter/NamingSystemHistoryIdentityFilter.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/history/filter/NamingSystemHistoryIdentityFilter.java @@ -1,18 +1,20 @@ package dev.dsf.fhir.history.filter; -import org.hl7.fhir.r4.model.NamingSystem; +import org.hl7.fhir.r4.model.ResourceType; -import ca.uhn.fhir.model.api.annotation.ResourceDef; import dev.dsf.common.auth.conf.Identity; +import dev.dsf.fhir.authentication.FhirServerRole; +import dev.dsf.fhir.authentication.FhirServerRoleImpl; import dev.dsf.fhir.search.filter.NamingSystemIdentityFilter; public class NamingSystemHistoryIdentityFilter extends NamingSystemIdentityFilter implements HistoryIdentityFilter { - private static final String RESOURCE_TYPE = NamingSystem.class.getAnnotation(ResourceDef.class).name(); + private static final FhirServerRole HISTORY_ROLE = FhirServerRoleImpl.history(ResourceType.NamingSystem); + private static final String RESOURCE_TYPE = ResourceType.NamingSystem.name(); public NamingSystemHistoryIdentityFilter(Identity identity) { - super(identity, HistoryIdentityFilter.RESOURCE_TABLE, HistoryIdentityFilter.RESOURCE_ID_COLUMN); + super(identity, HistoryIdentityFilter.RESOURCE_TABLE, HistoryIdentityFilter.RESOURCE_ID_COLUMN, HISTORY_ROLE); } @Override diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/history/filter/OrganizationAffiliationHistoryIdentityFilter.java b/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/history/filter/OrganizationAffiliationHistoryIdentityFilter.java index 2cd7a07c0..79022b61b 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/history/filter/OrganizationAffiliationHistoryIdentityFilter.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/history/filter/OrganizationAffiliationHistoryIdentityFilter.java @@ -1,19 +1,21 @@ package dev.dsf.fhir.history.filter; -import org.hl7.fhir.r4.model.OrganizationAffiliation; +import org.hl7.fhir.r4.model.ResourceType; -import ca.uhn.fhir.model.api.annotation.ResourceDef; import dev.dsf.common.auth.conf.Identity; +import dev.dsf.fhir.authentication.FhirServerRole; +import dev.dsf.fhir.authentication.FhirServerRoleImpl; import dev.dsf.fhir.search.filter.OrganizationAffiliationIdentityFilter; public class OrganizationAffiliationHistoryIdentityFilter extends OrganizationAffiliationIdentityFilter implements HistoryIdentityFilter { - private static final String RESOURCE_TYPE = OrganizationAffiliation.class.getAnnotation(ResourceDef.class).name(); + private static final FhirServerRole HISTORY_ROLE = FhirServerRoleImpl.history(ResourceType.OrganizationAffiliation); + private static final String RESOURCE_TYPE = ResourceType.OrganizationAffiliation.name(); public OrganizationAffiliationHistoryIdentityFilter(Identity identity) { - super(identity, HistoryIdentityFilter.RESOURCE_TABLE, HistoryIdentityFilter.RESOURCE_ID_COLUMN); + super(identity, HistoryIdentityFilter.RESOURCE_TABLE, HistoryIdentityFilter.RESOURCE_ID_COLUMN, HISTORY_ROLE); } @Override diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/history/filter/OrganizationHistoryIdentityFilter.java b/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/history/filter/OrganizationHistoryIdentityFilter.java index f5ad93995..329f952f2 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/history/filter/OrganizationHistoryIdentityFilter.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/history/filter/OrganizationHistoryIdentityFilter.java @@ -1,18 +1,20 @@ package dev.dsf.fhir.history.filter; -import org.hl7.fhir.r4.model.Organization; +import org.hl7.fhir.r4.model.ResourceType; -import ca.uhn.fhir.model.api.annotation.ResourceDef; import dev.dsf.common.auth.conf.Identity; +import dev.dsf.fhir.authentication.FhirServerRole; +import dev.dsf.fhir.authentication.FhirServerRoleImpl; import dev.dsf.fhir.search.filter.OrganizationIdentityFilter; public class OrganizationHistoryIdentityFilter extends OrganizationIdentityFilter implements HistoryIdentityFilter { - private static final String RESOURCE_TYPE = Organization.class.getAnnotation(ResourceDef.class).name(); + private static final FhirServerRole HISTORY_ROLE = FhirServerRoleImpl.history(ResourceType.Organization); + private static final String RESOURCE_TYPE = ResourceType.Organization.name(); public OrganizationHistoryIdentityFilter(Identity identity) { - super(identity, HistoryIdentityFilter.RESOURCE_TABLE, HistoryIdentityFilter.RESOURCE_ID_COLUMN); + super(identity, HistoryIdentityFilter.RESOURCE_TABLE, HistoryIdentityFilter.RESOURCE_ID_COLUMN, HISTORY_ROLE); } @Override diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/history/filter/PatientHistoryIdentityFilter.java b/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/history/filter/PatientHistoryIdentityFilter.java index 68e89c5a0..a76b7a809 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/history/filter/PatientHistoryIdentityFilter.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/history/filter/PatientHistoryIdentityFilter.java @@ -1,18 +1,20 @@ package dev.dsf.fhir.history.filter; -import org.hl7.fhir.r4.model.Patient; +import org.hl7.fhir.r4.model.ResourceType; -import ca.uhn.fhir.model.api.annotation.ResourceDef; import dev.dsf.common.auth.conf.Identity; +import dev.dsf.fhir.authentication.FhirServerRole; +import dev.dsf.fhir.authentication.FhirServerRoleImpl; import dev.dsf.fhir.search.filter.PatientIdentityFilter; public class PatientHistoryIdentityFilter extends PatientIdentityFilter implements HistoryIdentityFilter { - private static final String RESOURCE_TYPE = Patient.class.getAnnotation(ResourceDef.class).name(); + private static final FhirServerRole HISTORY_ROLE = FhirServerRoleImpl.history(ResourceType.Patient); + private static final String RESOURCE_TYPE = ResourceType.Patient.name(); public PatientHistoryIdentityFilter(Identity identity) { - super(identity, HistoryIdentityFilter.RESOURCE_TABLE, HistoryIdentityFilter.RESOURCE_ID_COLUMN); + super(identity, HistoryIdentityFilter.RESOURCE_TABLE, HistoryIdentityFilter.RESOURCE_ID_COLUMN, HISTORY_ROLE); } @Override diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/history/filter/PractitionerHistoryIdentityFilter.java b/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/history/filter/PractitionerHistoryIdentityFilter.java index a86aee2d5..8b0a94dac 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/history/filter/PractitionerHistoryIdentityFilter.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/history/filter/PractitionerHistoryIdentityFilter.java @@ -1,18 +1,20 @@ package dev.dsf.fhir.history.filter; -import org.hl7.fhir.r4.model.Practitioner; +import org.hl7.fhir.r4.model.ResourceType; -import ca.uhn.fhir.model.api.annotation.ResourceDef; import dev.dsf.common.auth.conf.Identity; +import dev.dsf.fhir.authentication.FhirServerRole; +import dev.dsf.fhir.authentication.FhirServerRoleImpl; import dev.dsf.fhir.search.filter.PractitionerIdentityFilter; public class PractitionerHistoryIdentityFilter extends PractitionerIdentityFilter implements HistoryIdentityFilter { - private static final String RESOURCE_TYPE = Practitioner.class.getAnnotation(ResourceDef.class).name(); + private static final FhirServerRole HISTORY_ROLE = FhirServerRoleImpl.history(ResourceType.Practitioner); + private static final String RESOURCE_TYPE = ResourceType.Practitioner.name(); public PractitionerHistoryIdentityFilter(Identity identity) { - super(identity, HistoryIdentityFilter.RESOURCE_TABLE, HistoryIdentityFilter.RESOURCE_ID_COLUMN); + super(identity, HistoryIdentityFilter.RESOURCE_TABLE, HistoryIdentityFilter.RESOURCE_ID_COLUMN, HISTORY_ROLE); } @Override diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/history/filter/PractitionerRoleHistoryIdentityFilter.java b/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/history/filter/PractitionerRoleHistoryIdentityFilter.java index e10b46c8d..5f07a9c7d 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/history/filter/PractitionerRoleHistoryIdentityFilter.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/history/filter/PractitionerRoleHistoryIdentityFilter.java @@ -1,19 +1,21 @@ package dev.dsf.fhir.history.filter; -import org.hl7.fhir.r4.model.PractitionerRole; +import org.hl7.fhir.r4.model.ResourceType; -import ca.uhn.fhir.model.api.annotation.ResourceDef; import dev.dsf.common.auth.conf.Identity; +import dev.dsf.fhir.authentication.FhirServerRole; +import dev.dsf.fhir.authentication.FhirServerRoleImpl; import dev.dsf.fhir.search.filter.PractitionerRoleIdentityFilter; public class PractitionerRoleHistoryIdentityFilter extends PractitionerRoleIdentityFilter implements HistoryIdentityFilter { - private static final String RESOURCE_TYPE = PractitionerRole.class.getAnnotation(ResourceDef.class).name(); + private static final FhirServerRole HISTORY_ROLE = FhirServerRoleImpl.history(ResourceType.PractitionerRole); + private static final String RESOURCE_TYPE = ResourceType.PractitionerRole.name(); public PractitionerRoleHistoryIdentityFilter(Identity identity) { - super(identity, HistoryIdentityFilter.RESOURCE_TABLE, HistoryIdentityFilter.RESOURCE_ID_COLUMN); + super(identity, HistoryIdentityFilter.RESOURCE_TABLE, HistoryIdentityFilter.RESOURCE_ID_COLUMN, HISTORY_ROLE); } @Override diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/history/filter/ProvenanceHistoryIdentityFilter.java b/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/history/filter/ProvenanceHistoryIdentityFilter.java index f6bbf8867..d8ceb4efd 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/history/filter/ProvenanceHistoryIdentityFilter.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/history/filter/ProvenanceHistoryIdentityFilter.java @@ -1,18 +1,20 @@ package dev.dsf.fhir.history.filter; -import org.hl7.fhir.r4.model.Provenance; +import org.hl7.fhir.r4.model.ResourceType; -import ca.uhn.fhir.model.api.annotation.ResourceDef; import dev.dsf.common.auth.conf.Identity; +import dev.dsf.fhir.authentication.FhirServerRole; +import dev.dsf.fhir.authentication.FhirServerRoleImpl; import dev.dsf.fhir.search.filter.ProvenanceIdentityFilter; public class ProvenanceHistoryIdentityFilter extends ProvenanceIdentityFilter implements HistoryIdentityFilter { - private static final String RESOURCE_TYPE = Provenance.class.getAnnotation(ResourceDef.class).name(); + private static final FhirServerRole HISTORY_ROLE = FhirServerRoleImpl.history(ResourceType.Provenance); + private static final String RESOURCE_TYPE = ResourceType.Provenance.name(); public ProvenanceHistoryIdentityFilter(Identity identity) { - super(identity, HistoryIdentityFilter.RESOURCE_TABLE, HistoryIdentityFilter.RESOURCE_ID_COLUMN); + super(identity, HistoryIdentityFilter.RESOURCE_TABLE, HistoryIdentityFilter.RESOURCE_ID_COLUMN, HISTORY_ROLE); } @Override diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/history/filter/QuestionnaireHistoryIdentityFilter.java b/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/history/filter/QuestionnaireHistoryIdentityFilter.java index 6eeedd657..7cd6902be 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/history/filter/QuestionnaireHistoryIdentityFilter.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/history/filter/QuestionnaireHistoryIdentityFilter.java @@ -1,18 +1,20 @@ package dev.dsf.fhir.history.filter; -import org.hl7.fhir.r4.model.Questionnaire; +import org.hl7.fhir.r4.model.ResourceType; -import ca.uhn.fhir.model.api.annotation.ResourceDef; import dev.dsf.common.auth.conf.Identity; +import dev.dsf.fhir.authentication.FhirServerRole; +import dev.dsf.fhir.authentication.FhirServerRoleImpl; import dev.dsf.fhir.search.filter.QuestionnaireIdentityFilter; public class QuestionnaireHistoryIdentityFilter extends QuestionnaireIdentityFilter implements HistoryIdentityFilter { - private static final String RESOURCE_TYPE = Questionnaire.class.getAnnotation(ResourceDef.class).name(); + private static final FhirServerRole HISTORY_ROLE = FhirServerRoleImpl.history(ResourceType.Questionnaire); + private static final String RESOURCE_TYPE = ResourceType.Questionnaire.name(); public QuestionnaireHistoryIdentityFilter(Identity identity) { - super(identity, HistoryIdentityFilter.RESOURCE_TABLE, HistoryIdentityFilter.RESOURCE_ID_COLUMN); + super(identity, HistoryIdentityFilter.RESOURCE_TABLE, HistoryIdentityFilter.RESOURCE_ID_COLUMN, HISTORY_ROLE); } @Override diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/history/filter/QuestionnaireResponseHistoryIdentityFilter.java b/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/history/filter/QuestionnaireResponseHistoryIdentityFilter.java index 5772f857a..8c7ac2b35 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/history/filter/QuestionnaireResponseHistoryIdentityFilter.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/history/filter/QuestionnaireResponseHistoryIdentityFilter.java @@ -1,19 +1,21 @@ package dev.dsf.fhir.history.filter; -import org.hl7.fhir.r4.model.QuestionnaireResponse; +import org.hl7.fhir.r4.model.ResourceType; -import ca.uhn.fhir.model.api.annotation.ResourceDef; import dev.dsf.common.auth.conf.Identity; +import dev.dsf.fhir.authentication.FhirServerRole; +import dev.dsf.fhir.authentication.FhirServerRoleImpl; import dev.dsf.fhir.search.filter.QuestionnaireResponseIdentityFilter; public class QuestionnaireResponseHistoryIdentityFilter extends QuestionnaireResponseIdentityFilter implements HistoryIdentityFilter { - private static final String RESOURCE_TYPE = QuestionnaireResponse.class.getAnnotation(ResourceDef.class).name(); + private static final FhirServerRole HISTORY_ROLE = FhirServerRoleImpl.history(ResourceType.QuestionnaireResponse); + private static final String RESOURCE_TYPE = ResourceType.QuestionnaireResponse.name(); public QuestionnaireResponseHistoryIdentityFilter(Identity identity) { - super(identity); + super(identity, HISTORY_ROLE); } @Override diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/history/filter/ResearchStudyHistoryIdentityFilter.java b/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/history/filter/ResearchStudyHistoryIdentityFilter.java index 7152ea7fd..65e5f016b 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/history/filter/ResearchStudyHistoryIdentityFilter.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/history/filter/ResearchStudyHistoryIdentityFilter.java @@ -1,18 +1,20 @@ package dev.dsf.fhir.history.filter; -import org.hl7.fhir.r4.model.ResearchStudy; +import org.hl7.fhir.r4.model.ResourceType; -import ca.uhn.fhir.model.api.annotation.ResourceDef; import dev.dsf.common.auth.conf.Identity; +import dev.dsf.fhir.authentication.FhirServerRole; +import dev.dsf.fhir.authentication.FhirServerRoleImpl; import dev.dsf.fhir.search.filter.ResearchStudyIdentityFilter; public class ResearchStudyHistoryIdentityFilter extends ResearchStudyIdentityFilter implements HistoryIdentityFilter { - private static final String RESOURCE_TYPE = ResearchStudy.class.getAnnotation(ResourceDef.class).name(); + private static final FhirServerRole HISTORY_ROLE = FhirServerRoleImpl.history(ResourceType.ResearchStudy); + private static final String RESOURCE_TYPE = ResourceType.ResearchStudy.name(); public ResearchStudyHistoryIdentityFilter(Identity identity) { - super(identity, HistoryIdentityFilter.RESOURCE_TABLE, HistoryIdentityFilter.RESOURCE_ID_COLUMN); + super(identity, HistoryIdentityFilter.RESOURCE_TABLE, HistoryIdentityFilter.RESOURCE_ID_COLUMN, HISTORY_ROLE); } @Override diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/history/filter/StructureDefinitionHistoryIdentityFilter.java b/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/history/filter/StructureDefinitionHistoryIdentityFilter.java index 25034aee3..0bc247e3c 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/history/filter/StructureDefinitionHistoryIdentityFilter.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/history/filter/StructureDefinitionHistoryIdentityFilter.java @@ -1,19 +1,21 @@ package dev.dsf.fhir.history.filter; -import org.hl7.fhir.r4.model.StructureDefinition; +import org.hl7.fhir.r4.model.ResourceType; -import ca.uhn.fhir.model.api.annotation.ResourceDef; import dev.dsf.common.auth.conf.Identity; +import dev.dsf.fhir.authentication.FhirServerRole; +import dev.dsf.fhir.authentication.FhirServerRoleImpl; import dev.dsf.fhir.search.filter.StructureDefinitionIdentityFilter; public class StructureDefinitionHistoryIdentityFilter extends StructureDefinitionIdentityFilter implements HistoryIdentityFilter { - private static final String RESOURCE_TYPE = StructureDefinition.class.getAnnotation(ResourceDef.class).name(); + private static final FhirServerRole HISTORY_ROLE = FhirServerRoleImpl.history(ResourceType.StructureDefinition); + private static final String RESOURCE_TYPE = ResourceType.StructureDefinition.name(); public StructureDefinitionHistoryIdentityFilter(Identity identity) { - super(identity, HistoryIdentityFilter.RESOURCE_TABLE, HistoryIdentityFilter.RESOURCE_ID_COLUMN); + super(identity, HistoryIdentityFilter.RESOURCE_TABLE, HistoryIdentityFilter.RESOURCE_ID_COLUMN, HISTORY_ROLE); } @Override diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/history/filter/SubscriptionHistoryIdentityFilter.java b/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/history/filter/SubscriptionHistoryIdentityFilter.java index 740021d42..4e7ce4eaf 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/history/filter/SubscriptionHistoryIdentityFilter.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/history/filter/SubscriptionHistoryIdentityFilter.java @@ -1,18 +1,20 @@ package dev.dsf.fhir.history.filter; -import org.hl7.fhir.r4.model.Subscription; +import org.hl7.fhir.r4.model.ResourceType; -import ca.uhn.fhir.model.api.annotation.ResourceDef; import dev.dsf.common.auth.conf.Identity; +import dev.dsf.fhir.authentication.FhirServerRole; +import dev.dsf.fhir.authentication.FhirServerRoleImpl; import dev.dsf.fhir.search.filter.SubscriptionIdentityFilter; public class SubscriptionHistoryIdentityFilter extends SubscriptionIdentityFilter implements HistoryIdentityFilter { - private static final String RESOURCE_TYPE = Subscription.class.getAnnotation(ResourceDef.class).name(); + private static final FhirServerRole HISTORY_ROLE = FhirServerRoleImpl.history(ResourceType.Subscription); + private static final String RESOURCE_TYPE = ResourceType.Subscription.name(); public SubscriptionHistoryIdentityFilter(Identity identity) { - super(identity, HistoryIdentityFilter.RESOURCE_TABLE, HistoryIdentityFilter.RESOURCE_ID_COLUMN); + super(identity, HistoryIdentityFilter.RESOURCE_TABLE, HistoryIdentityFilter.RESOURCE_ID_COLUMN, HISTORY_ROLE); } @Override diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/history/filter/TaskHistoryIdentityFilter.java b/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/history/filter/TaskHistoryIdentityFilter.java index 632f68bca..eca9e9627 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/history/filter/TaskHistoryIdentityFilter.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/history/filter/TaskHistoryIdentityFilter.java @@ -1,18 +1,20 @@ package dev.dsf.fhir.history.filter; -import org.hl7.fhir.r4.model.Task; +import org.hl7.fhir.r4.model.ResourceType; -import ca.uhn.fhir.model.api.annotation.ResourceDef; import dev.dsf.common.auth.conf.Identity; +import dev.dsf.fhir.authentication.FhirServerRole; +import dev.dsf.fhir.authentication.FhirServerRoleImpl; import dev.dsf.fhir.search.filter.TaskIdentityFilter; public class TaskHistoryIdentityFilter extends TaskIdentityFilter implements HistoryIdentityFilter { - private static final String RESOURCE_TYPE = Task.class.getAnnotation(ResourceDef.class).name(); + private static final FhirServerRole HISTORY_ROLE = FhirServerRoleImpl.history(ResourceType.Task); + private static final String RESOURCE_TYPE = ResourceType.Task.name(); public TaskHistoryIdentityFilter(Identity identity) { - super(identity, HistoryIdentityFilter.RESOURCE_COLUMN); + super(identity, HistoryIdentityFilter.RESOURCE_COLUMN, HISTORY_ROLE); } @Override diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/history/filter/ValueSetHistoryIdentityFilter.java b/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/history/filter/ValueSetHistoryIdentityFilter.java index 5f33d5385..231fcca8e 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/history/filter/ValueSetHistoryIdentityFilter.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/history/filter/ValueSetHistoryIdentityFilter.java @@ -1,18 +1,20 @@ package dev.dsf.fhir.history.filter; -import org.hl7.fhir.r4.model.ValueSet; +import org.hl7.fhir.r4.model.ResourceType; -import ca.uhn.fhir.model.api.annotation.ResourceDef; import dev.dsf.common.auth.conf.Identity; +import dev.dsf.fhir.authentication.FhirServerRole; +import dev.dsf.fhir.authentication.FhirServerRoleImpl; import dev.dsf.fhir.search.filter.ValueSetIdentityFilter; public class ValueSetHistoryIdentityFilter extends ValueSetIdentityFilter implements HistoryIdentityFilter { - private static final String RESOURCE_TYPE = ValueSet.class.getAnnotation(ResourceDef.class).name(); + private static final FhirServerRole HISTORY_ROLE = FhirServerRoleImpl.history(ResourceType.ValueSet); + private static final String RESOURCE_TYPE = ResourceType.ValueSet.name(); public ValueSetHistoryIdentityFilter(Identity identity) { - super(identity, HistoryIdentityFilter.RESOURCE_TABLE, HistoryIdentityFilter.RESOURCE_ID_COLUMN); + super(identity, HistoryIdentityFilter.RESOURCE_TABLE, HistoryIdentityFilter.RESOURCE_ID_COLUMN, HISTORY_ROLE); } @Override diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/search/filter/AbstractMetaTagAuthorizationRoleIdentityFilter.java b/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/search/filter/AbstractMetaTagAuthorizationRoleIdentityFilter.java index 0bb51ade6..2ce10009a 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/search/filter/AbstractMetaTagAuthorizationRoleIdentityFilter.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/search/filter/AbstractMetaTagAuthorizationRoleIdentityFilter.java @@ -10,19 +10,26 @@ abstract class AbstractMetaTagAuthorizationRoleIdentityFilter extends AbstractIdentityFilter { - AbstractMetaTagAuthorizationRoleIdentityFilter(Identity identity, String resourceTable, String resourceIdColumn) + private final FhirServerRole operationRole; + private final FhirServerRole readRole; + + AbstractMetaTagAuthorizationRoleIdentityFilter(Identity identity, String resourceTable, String resourceIdColumn, + FhirServerRole operationRole, FhirServerRole readRole) { super(identity, resourceTable, resourceIdColumn); + + this.operationRole = operationRole; + this.readRole = readRole; } @Override public String getFilterQuery() { - if (identity.isLocalIdentity() && identity.hasDsfRole(FhirServerRole.READ)) + if (identity.isLocalIdentity() && identity.hasDsfRole(operationRole) && identity.hasDsfRole(readRole)) return "(SELECT count(*) FROM read_access WHERE read_access.resource_id = " + resourceTable + "." + resourceIdColumn + " AND read_access.resource_version = " + resourceTable + ".version" + " AND (read_access.organization_id = ? OR read_access.access_type = 'ALL' OR read_access.access_type = 'LOCAL')) > 0"; - else if (identity.hasDsfRole(FhirServerRole.READ)) + else if (identity.hasDsfRole(operationRole) && identity.hasDsfRole(readRole)) return "(SELECT count(*) FROM read_access WHERE read_access.resource_id = " + resourceTable + "." + resourceIdColumn + " AND read_access.resource_version = " + resourceTable + ".version" + " AND (read_access.organization_id = ? OR read_access.access_type = 'ALL')) > 0"; @@ -33,14 +40,14 @@ else if (identity.hasDsfRole(FhirServerRole.READ)) @Override public int getSqlParameterCount() { - return identity.hasDsfRole(FhirServerRole.READ) ? 1 : 0; + return identity.hasDsfRole(operationRole) && identity.hasDsfRole(readRole) ? 1 : 0; } @Override public void modifyStatement(int parameterIndex, int subqueryParameterIndex, PreparedStatement statement) throws SQLException { - if (identity.hasDsfRole(FhirServerRole.READ)) + if (identity.hasDsfRole(operationRole) && identity.hasDsfRole(readRole)) { String usersOrganizationId = identity.getOrganization().getIdElement().getIdPart(); statement.setObject(parameterIndex, toUuidObject(usersOrganizationId)); diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/search/filter/ActivityDefinitionIdentityFilter.java b/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/search/filter/ActivityDefinitionIdentityFilter.java index f49b89a1c..239c94af5 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/search/filter/ActivityDefinitionIdentityFilter.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/search/filter/ActivityDefinitionIdentityFilter.java @@ -1,19 +1,27 @@ package dev.dsf.fhir.search.filter; +import org.hl7.fhir.r4.model.ResourceType; + import dev.dsf.common.auth.conf.Identity; +import dev.dsf.fhir.authentication.FhirServerRole; +import dev.dsf.fhir.authentication.FhirServerRoleImpl; public class ActivityDefinitionIdentityFilter extends AbstractMetaTagAuthorizationRoleIdentityFilter { + private static final FhirServerRole SEARCH_ROLE = FhirServerRoleImpl.search(ResourceType.ActivityDefinition); + private static final FhirServerRole READ_ROLE = FhirServerRoleImpl.read(ResourceType.ActivityDefinition); + private static final String RESOURCE_TABLE = "current_activity_definitions"; private static final String RESOURCE_ID_COLUMN = "activity_definition_id"; public ActivityDefinitionIdentityFilter(Identity identity) { - super(identity, RESOURCE_TABLE, RESOURCE_ID_COLUMN); + this(identity, RESOURCE_TABLE, RESOURCE_ID_COLUMN, SEARCH_ROLE); } - public ActivityDefinitionIdentityFilter(Identity identity, String resourceTable, String resourceIdColumn) + public ActivityDefinitionIdentityFilter(Identity identity, String resourceTable, String resourceIdColumn, + FhirServerRole operationRole) { - super(identity, resourceTable, resourceIdColumn); + super(identity, resourceTable, resourceIdColumn, operationRole, READ_ROLE); } } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/search/filter/BinaryIdentityFilter.java b/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/search/filter/BinaryIdentityFilter.java index 84b1c4f79..7c237be34 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/search/filter/BinaryIdentityFilter.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/search/filter/BinaryIdentityFilter.java @@ -1,19 +1,27 @@ package dev.dsf.fhir.search.filter; +import org.hl7.fhir.r4.model.ResourceType; + import dev.dsf.common.auth.conf.Identity; +import dev.dsf.fhir.authentication.FhirServerRole; +import dev.dsf.fhir.authentication.FhirServerRoleImpl; public class BinaryIdentityFilter extends AbstractMetaTagAuthorizationRoleIdentityFilter { + private static final FhirServerRole SEARCH_ROLE = FhirServerRoleImpl.search(ResourceType.Binary); + private static final FhirServerRole READ_ROLE = FhirServerRoleImpl.read(ResourceType.Binary); + private static final String RESOURCE_TABLE = "current_binaries"; private static final String RESOURCE_ID_COLUMN = "binary_id"; public BinaryIdentityFilter(Identity identity) { - super(identity, RESOURCE_TABLE, RESOURCE_ID_COLUMN); + this(identity, RESOURCE_TABLE, RESOURCE_ID_COLUMN, SEARCH_ROLE); } - public BinaryIdentityFilter(Identity identity, String resourceTable, String resourceIdColumn) + public BinaryIdentityFilter(Identity identity, String resourceTable, String resourceIdColumn, + FhirServerRole operationRole) { - super(identity, resourceTable, resourceIdColumn); + super(identity, resourceTable, resourceIdColumn, operationRole, READ_ROLE); } } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/search/filter/BundleIdentityFilter.java b/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/search/filter/BundleIdentityFilter.java index 094be7924..54dc48771 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/search/filter/BundleIdentityFilter.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/search/filter/BundleIdentityFilter.java @@ -1,19 +1,27 @@ package dev.dsf.fhir.search.filter; +import org.hl7.fhir.r4.model.ResourceType; + import dev.dsf.common.auth.conf.Identity; +import dev.dsf.fhir.authentication.FhirServerRole; +import dev.dsf.fhir.authentication.FhirServerRoleImpl; public class BundleIdentityFilter extends AbstractMetaTagAuthorizationRoleIdentityFilter { + private static final FhirServerRole SEARCH_ROLE = FhirServerRoleImpl.search(ResourceType.Bundle); + private static final FhirServerRole READ_ROLE = FhirServerRoleImpl.read(ResourceType.Bundle); + private static final String RESOURCE_TABLE = "current_bundles"; private static final String RESOURCE_ID_COLUMN = "bundle_id"; public BundleIdentityFilter(Identity identity) { - super(identity, RESOURCE_TABLE, RESOURCE_ID_COLUMN); + this(identity, RESOURCE_TABLE, RESOURCE_ID_COLUMN, SEARCH_ROLE); } - public BundleIdentityFilter(Identity identity, String resourceTable, String resourceIdColumn) + public BundleIdentityFilter(Identity identity, String resourceTable, String resourceIdColumn, + FhirServerRole operationRole) { - super(identity, resourceTable, resourceIdColumn); + super(identity, resourceTable, resourceIdColumn, operationRole, READ_ROLE); } } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/search/filter/CodeSystemIdentityFilter.java b/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/search/filter/CodeSystemIdentityFilter.java index 041efebf5..de7cb7503 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/search/filter/CodeSystemIdentityFilter.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/search/filter/CodeSystemIdentityFilter.java @@ -1,19 +1,27 @@ package dev.dsf.fhir.search.filter; +import org.hl7.fhir.r4.model.ResourceType; + import dev.dsf.common.auth.conf.Identity; +import dev.dsf.fhir.authentication.FhirServerRole; +import dev.dsf.fhir.authentication.FhirServerRoleImpl; public class CodeSystemIdentityFilter extends AbstractMetaTagAuthorizationRoleIdentityFilter { + private static final FhirServerRole SEARCH_ROLE = FhirServerRoleImpl.search(ResourceType.CodeSystem); + private static final FhirServerRole READ_ROLE = FhirServerRoleImpl.read(ResourceType.CodeSystem); + private static final String RESOURCE_TABLE = "current_code_systems"; private static final String RESOURCE_ID_COLUMN = "code_system_id"; public CodeSystemIdentityFilter(Identity identity) { - super(identity, RESOURCE_TABLE, RESOURCE_ID_COLUMN); + this(identity, RESOURCE_TABLE, RESOURCE_ID_COLUMN, SEARCH_ROLE); } - public CodeSystemIdentityFilter(Identity identity, String resourceTable, String resourceIdColumn) + public CodeSystemIdentityFilter(Identity identity, String resourceTable, String resourceIdColumn, + FhirServerRole operationRole) { - super(identity, resourceTable, resourceIdColumn); + super(identity, resourceTable, resourceIdColumn, operationRole, READ_ROLE); } } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/search/filter/DocumentReferenceIdentityFilter.java b/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/search/filter/DocumentReferenceIdentityFilter.java index c06d20e87..5c3d84254 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/search/filter/DocumentReferenceIdentityFilter.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/search/filter/DocumentReferenceIdentityFilter.java @@ -1,19 +1,27 @@ package dev.dsf.fhir.search.filter; +import org.hl7.fhir.r4.model.ResourceType; + import dev.dsf.common.auth.conf.Identity; +import dev.dsf.fhir.authentication.FhirServerRole; +import dev.dsf.fhir.authentication.FhirServerRoleImpl; public class DocumentReferenceIdentityFilter extends AbstractMetaTagAuthorizationRoleIdentityFilter { + private static final FhirServerRole SEARCH_ROLE = FhirServerRoleImpl.search(ResourceType.DocumentReference); + private static final FhirServerRole READ_ROLE = FhirServerRoleImpl.read(ResourceType.DocumentReference); + private static final String RESOURCE_TABLE = "current_document_references"; private static String RESOURCE_ID_COLUMN = "document_reference_id"; public DocumentReferenceIdentityFilter(Identity identity) { - super(identity, RESOURCE_TABLE, RESOURCE_ID_COLUMN); + this(identity, RESOURCE_TABLE, RESOURCE_ID_COLUMN, SEARCH_ROLE); } - public DocumentReferenceIdentityFilter(Identity identity, String resourceTable, String resourceIdColumn) + public DocumentReferenceIdentityFilter(Identity identity, String resourceTable, String resourceIdColumn, + FhirServerRole operationRole) { - super(identity, resourceTable, resourceIdColumn); + super(identity, resourceTable, resourceIdColumn, operationRole, READ_ROLE); } } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/search/filter/EndpointIdentityFilter.java b/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/search/filter/EndpointIdentityFilter.java index 9a78827ff..0d4a750de 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/search/filter/EndpointIdentityFilter.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/search/filter/EndpointIdentityFilter.java @@ -1,19 +1,27 @@ package dev.dsf.fhir.search.filter; +import org.hl7.fhir.r4.model.ResourceType; + import dev.dsf.common.auth.conf.Identity; +import dev.dsf.fhir.authentication.FhirServerRole; +import dev.dsf.fhir.authentication.FhirServerRoleImpl; public class EndpointIdentityFilter extends AbstractMetaTagAuthorizationRoleIdentityFilter { + private static final FhirServerRole SEARCH_ROLE = FhirServerRoleImpl.search(ResourceType.Endpoint); + private static final FhirServerRole READ_ROLE = FhirServerRoleImpl.read(ResourceType.Endpoint); + private static final String RESOURCE_TABLE = "current_endpoints"; private static final String RESOURCE_ID_COLUMN = "endpoint_id"; public EndpointIdentityFilter(Identity identity) { - super(identity, RESOURCE_TABLE, RESOURCE_ID_COLUMN); + this(identity, RESOURCE_TABLE, RESOURCE_ID_COLUMN, SEARCH_ROLE); } - public EndpointIdentityFilter(Identity identity, String resourceTable, String resourceIdColumn) + public EndpointIdentityFilter(Identity identity, String resourceTable, String resourceIdColumn, + FhirServerRole operationRole) { - super(identity, resourceTable, resourceIdColumn); + super(identity, resourceTable, resourceIdColumn, operationRole, READ_ROLE); } } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/search/filter/GroupIdentityFilter.java b/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/search/filter/GroupIdentityFilter.java index f32e8fdfe..d3cf19e17 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/search/filter/GroupIdentityFilter.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/search/filter/GroupIdentityFilter.java @@ -1,19 +1,27 @@ package dev.dsf.fhir.search.filter; +import org.hl7.fhir.r4.model.ResourceType; + import dev.dsf.common.auth.conf.Identity; +import dev.dsf.fhir.authentication.FhirServerRole; +import dev.dsf.fhir.authentication.FhirServerRoleImpl; public class GroupIdentityFilter extends AbstractMetaTagAuthorizationRoleIdentityFilter { + private static final FhirServerRole SEARCH_ROLE = FhirServerRoleImpl.search(ResourceType.Group); + private static final FhirServerRole READ_ROLE = FhirServerRoleImpl.read(ResourceType.Group); + private static final String RESOURCE_TABLE = "current_groups"; private static final String RESOURCE_ID_COLUMN = "group_id"; public GroupIdentityFilter(Identity identity) { - super(identity, RESOURCE_TABLE, RESOURCE_ID_COLUMN); + this(identity, RESOURCE_TABLE, RESOURCE_ID_COLUMN, SEARCH_ROLE); } - public GroupIdentityFilter(Identity identity, String resourceTable, String resourceIdColumn) + public GroupIdentityFilter(Identity identity, String resourceTable, String resourceIdColumn, + FhirServerRole operationRole) { - super(identity, resourceTable, resourceIdColumn); + super(identity, resourceTable, resourceIdColumn, operationRole, READ_ROLE); } } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/search/filter/HealthcareServiceIdentityFilter.java b/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/search/filter/HealthcareServiceIdentityFilter.java index 89e7d4d23..839c55f1e 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/search/filter/HealthcareServiceIdentityFilter.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/search/filter/HealthcareServiceIdentityFilter.java @@ -1,19 +1,27 @@ package dev.dsf.fhir.search.filter; +import org.hl7.fhir.r4.model.ResourceType; + import dev.dsf.common.auth.conf.Identity; +import dev.dsf.fhir.authentication.FhirServerRole; +import dev.dsf.fhir.authentication.FhirServerRoleImpl; public class HealthcareServiceIdentityFilter extends AbstractMetaTagAuthorizationRoleIdentityFilter { + private static final FhirServerRole SEARCH_ROLE = FhirServerRoleImpl.search(ResourceType.HealthcareService); + private static final FhirServerRole READ_ROLE = FhirServerRoleImpl.read(ResourceType.HealthcareService); + private static final String RESOURCE_TABLE = "current_healthcare_services"; private static final String RESOURCE_ID_COLUMN = "healthcare_service_id"; public HealthcareServiceIdentityFilter(Identity identity) { - super(identity, RESOURCE_TABLE, RESOURCE_ID_COLUMN); + this(identity, RESOURCE_TABLE, RESOURCE_ID_COLUMN, SEARCH_ROLE); } - public HealthcareServiceIdentityFilter(Identity identity, String resourceTable, String resourceIdColumn) + public HealthcareServiceIdentityFilter(Identity identity, String resourceTable, String resourceIdColumn, + FhirServerRole operationRole) { - super(identity, resourceTable, resourceIdColumn); + super(identity, resourceTable, resourceIdColumn, operationRole, READ_ROLE); } } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/search/filter/LibraryIdentityFilter.java b/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/search/filter/LibraryIdentityFilter.java index 859fccbb2..6a70007e2 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/search/filter/LibraryIdentityFilter.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/search/filter/LibraryIdentityFilter.java @@ -1,19 +1,27 @@ package dev.dsf.fhir.search.filter; +import org.hl7.fhir.r4.model.ResourceType; + import dev.dsf.common.auth.conf.Identity; +import dev.dsf.fhir.authentication.FhirServerRole; +import dev.dsf.fhir.authentication.FhirServerRoleImpl; public class LibraryIdentityFilter extends AbstractMetaTagAuthorizationRoleIdentityFilter { + private static final FhirServerRole SEARCH_ROLE = FhirServerRoleImpl.search(ResourceType.Library); + private static final FhirServerRole READ_ROLE = FhirServerRoleImpl.read(ResourceType.Library); + private static final String RESOURCE_TABLE = "current_libraries"; private static final String RESOURCE_ID_COLUMN = "library_id"; public LibraryIdentityFilter(Identity identity) { - super(identity, RESOURCE_TABLE, RESOURCE_ID_COLUMN); + this(identity, RESOURCE_TABLE, RESOURCE_ID_COLUMN, SEARCH_ROLE); } - public LibraryIdentityFilter(Identity identity, String resourceTable, String resourceIdColumn) + public LibraryIdentityFilter(Identity identity, String resourceTable, String resourceIdColumn, + FhirServerRole operationRole) { - super(identity, resourceTable, resourceIdColumn); + super(identity, resourceTable, resourceIdColumn, operationRole, READ_ROLE); } } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/search/filter/LocationIdentityFilter.java b/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/search/filter/LocationIdentityFilter.java index 5bc15afa8..cbb6f8c29 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/search/filter/LocationIdentityFilter.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/search/filter/LocationIdentityFilter.java @@ -1,19 +1,27 @@ package dev.dsf.fhir.search.filter; +import org.hl7.fhir.r4.model.ResourceType; + import dev.dsf.common.auth.conf.Identity; +import dev.dsf.fhir.authentication.FhirServerRole; +import dev.dsf.fhir.authentication.FhirServerRoleImpl; public class LocationIdentityFilter extends AbstractMetaTagAuthorizationRoleIdentityFilter { + private static final FhirServerRole SEARCH_ROLE = FhirServerRoleImpl.search(ResourceType.Location); + private static final FhirServerRole READ_ROLE = FhirServerRoleImpl.read(ResourceType.Location); + private static final String RESOURCE_TABLE = "current_locations"; private static final String RESOURCE_ID_COLUMN = "location_id"; public LocationIdentityFilter(Identity identity) { - super(identity, RESOURCE_TABLE, RESOURCE_ID_COLUMN); + this(identity, RESOURCE_TABLE, RESOURCE_ID_COLUMN, SEARCH_ROLE); } - public LocationIdentityFilter(Identity identity, String resourceTable, String resourceIdColumn) + public LocationIdentityFilter(Identity identity, String resourceTable, String resourceIdColumn, + FhirServerRole operationRole) { - super(identity, resourceTable, resourceIdColumn); + super(identity, resourceTable, resourceIdColumn, operationRole, READ_ROLE); } } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/search/filter/MeasureIdentityFilter.java b/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/search/filter/MeasureIdentityFilter.java index bb1544253..cc147c98a 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/search/filter/MeasureIdentityFilter.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/search/filter/MeasureIdentityFilter.java @@ -1,19 +1,27 @@ package dev.dsf.fhir.search.filter; +import org.hl7.fhir.r4.model.ResourceType; + import dev.dsf.common.auth.conf.Identity; +import dev.dsf.fhir.authentication.FhirServerRole; +import dev.dsf.fhir.authentication.FhirServerRoleImpl; public class MeasureIdentityFilter extends AbstractMetaTagAuthorizationRoleIdentityFilter { + private static final FhirServerRole SEARCH_ROLE = FhirServerRoleImpl.search(ResourceType.Measure); + private static final FhirServerRole READ_ROLE = FhirServerRoleImpl.read(ResourceType.Measure); + private static final String RESOURCE_TABLE = "current_measures"; private static final String RESOURCE_ID_COLUMN = "measure_id"; public MeasureIdentityFilter(Identity identity) { - super(identity, RESOURCE_TABLE, RESOURCE_ID_COLUMN); + this(identity, RESOURCE_TABLE, RESOURCE_ID_COLUMN, SEARCH_ROLE); } - public MeasureIdentityFilter(Identity identity, String resourceTable, String resourceIdColumn) + public MeasureIdentityFilter(Identity identity, String resourceTable, String resourceIdColumn, + FhirServerRole operationRole) { - super(identity, resourceTable, resourceIdColumn); + super(identity, resourceTable, resourceIdColumn, operationRole, READ_ROLE); } } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/search/filter/MeasureReportIdentityFilter.java b/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/search/filter/MeasureReportIdentityFilter.java index 77ef6341e..330a0974b 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/search/filter/MeasureReportIdentityFilter.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/search/filter/MeasureReportIdentityFilter.java @@ -1,19 +1,27 @@ package dev.dsf.fhir.search.filter; +import org.hl7.fhir.r4.model.ResourceType; + import dev.dsf.common.auth.conf.Identity; +import dev.dsf.fhir.authentication.FhirServerRole; +import dev.dsf.fhir.authentication.FhirServerRoleImpl; public class MeasureReportIdentityFilter extends AbstractMetaTagAuthorizationRoleIdentityFilter { + private static final FhirServerRole SEARCH_ROLE = FhirServerRoleImpl.search(ResourceType.MeasureReport); + private static final FhirServerRole READ_ROLE = FhirServerRoleImpl.read(ResourceType.MeasureReport); + private static final String RESOURCE_TABLE = "current_measure_reports"; private static final String RESOURCE_ID_COLUMN = "measure_report_id"; public MeasureReportIdentityFilter(Identity identity) { - super(identity, RESOURCE_TABLE, RESOURCE_ID_COLUMN); + this(identity, RESOURCE_TABLE, RESOURCE_ID_COLUMN, SEARCH_ROLE); } - public MeasureReportIdentityFilter(Identity identity, String resourceTable, String resourceIdColumn) + public MeasureReportIdentityFilter(Identity identity, String resourceTable, String resourceIdColumn, + FhirServerRole operationRole) { - super(identity, resourceTable, resourceIdColumn); + super(identity, resourceTable, resourceIdColumn, operationRole, READ_ROLE); } } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/search/filter/NamingSystemIdentityFilter.java b/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/search/filter/NamingSystemIdentityFilter.java index 16192fa01..5b5c1b263 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/search/filter/NamingSystemIdentityFilter.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/search/filter/NamingSystemIdentityFilter.java @@ -1,19 +1,27 @@ package dev.dsf.fhir.search.filter; +import org.hl7.fhir.r4.model.ResourceType; + import dev.dsf.common.auth.conf.Identity; +import dev.dsf.fhir.authentication.FhirServerRole; +import dev.dsf.fhir.authentication.FhirServerRoleImpl; public class NamingSystemIdentityFilter extends AbstractMetaTagAuthorizationRoleIdentityFilter { + private static final FhirServerRole SEARCH_ROLE = FhirServerRoleImpl.search(ResourceType.NamingSystem); + private static final FhirServerRole READ_ROLE = FhirServerRoleImpl.read(ResourceType.NamingSystem); + private static final String RESOURCE_TABLE = "current_naming_systems"; private static final String RESOURCE_ID_COLUMN = "naming_system_id"; public NamingSystemIdentityFilter(Identity identity) { - super(identity, RESOURCE_TABLE, RESOURCE_ID_COLUMN); + this(identity, RESOURCE_TABLE, RESOURCE_ID_COLUMN, SEARCH_ROLE); } - public NamingSystemIdentityFilter(Identity identity, String resourceTable, String resourceIdColumn) + public NamingSystemIdentityFilter(Identity identity, String resourceTable, String resourceIdColumn, + FhirServerRole operationRole) { - super(identity, resourceTable, resourceIdColumn); + super(identity, resourceTable, resourceIdColumn, operationRole, READ_ROLE); } } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/search/filter/OrganizationAffiliationIdentityFilter.java b/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/search/filter/OrganizationAffiliationIdentityFilter.java index 2068160a1..7ce25fd33 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/search/filter/OrganizationAffiliationIdentityFilter.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/search/filter/OrganizationAffiliationIdentityFilter.java @@ -1,19 +1,27 @@ package dev.dsf.fhir.search.filter; +import org.hl7.fhir.r4.model.ResourceType; + import dev.dsf.common.auth.conf.Identity; +import dev.dsf.fhir.authentication.FhirServerRole; +import dev.dsf.fhir.authentication.FhirServerRoleImpl; public class OrganizationAffiliationIdentityFilter extends AbstractMetaTagAuthorizationRoleIdentityFilter { + private static final FhirServerRole SEARCH_ROLE = FhirServerRoleImpl.search(ResourceType.OrganizationAffiliation); + private static final FhirServerRole READ_ROLE = FhirServerRoleImpl.read(ResourceType.OrganizationAffiliation); + private static final String RESOURCE_TABLE = "current_organization_affiliations"; private static final String RESOURCE_ID_COLUMN = "organization_affiliation_id"; public OrganizationAffiliationIdentityFilter(Identity identity) { - super(identity, RESOURCE_TABLE, RESOURCE_ID_COLUMN); + this(identity, RESOURCE_TABLE, RESOURCE_ID_COLUMN, SEARCH_ROLE); } - public OrganizationAffiliationIdentityFilter(Identity identity, String resourceTable, String resourceIdColumn) + public OrganizationAffiliationIdentityFilter(Identity identity, String resourceTable, String resourceIdColumn, + FhirServerRole operationRole) { - super(identity, resourceTable, resourceIdColumn); + super(identity, resourceTable, resourceIdColumn, operationRole, READ_ROLE); } } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/search/filter/OrganizationIdentityFilter.java b/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/search/filter/OrganizationIdentityFilter.java index d3d2f7682..8ccb2ccde 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/search/filter/OrganizationIdentityFilter.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/search/filter/OrganizationIdentityFilter.java @@ -1,19 +1,27 @@ package dev.dsf.fhir.search.filter; +import org.hl7.fhir.r4.model.ResourceType; + import dev.dsf.common.auth.conf.Identity; +import dev.dsf.fhir.authentication.FhirServerRole; +import dev.dsf.fhir.authentication.FhirServerRoleImpl; public class OrganizationIdentityFilter extends AbstractMetaTagAuthorizationRoleIdentityFilter { + private static final FhirServerRole SEARCH_ROLE = FhirServerRoleImpl.search(ResourceType.Organization); + private static final FhirServerRole READ_ROLE = FhirServerRoleImpl.read(ResourceType.Organization); + private static final String RESOURCE_TABLE = "current_organizations"; private static final String RESOURCE_ID_COLUMN = "organization_id"; public OrganizationIdentityFilter(Identity identity) { - super(identity, RESOURCE_TABLE, RESOURCE_ID_COLUMN); + this(identity, RESOURCE_TABLE, RESOURCE_ID_COLUMN, SEARCH_ROLE); } - public OrganizationIdentityFilter(Identity identity, String resourceTable, String resourceIdColumn) + public OrganizationIdentityFilter(Identity identity, String resourceTable, String resourceIdColumn, + FhirServerRole operationRole) { - super(identity, resourceTable, resourceIdColumn); + super(identity, resourceTable, resourceIdColumn, operationRole, READ_ROLE); } } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/search/filter/PatientIdentityFilter.java b/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/search/filter/PatientIdentityFilter.java index 12d527707..2b5f5d050 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/search/filter/PatientIdentityFilter.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/search/filter/PatientIdentityFilter.java @@ -1,19 +1,27 @@ package dev.dsf.fhir.search.filter; +import org.hl7.fhir.r4.model.ResourceType; + import dev.dsf.common.auth.conf.Identity; +import dev.dsf.fhir.authentication.FhirServerRole; +import dev.dsf.fhir.authentication.FhirServerRoleImpl; public class PatientIdentityFilter extends AbstractMetaTagAuthorizationRoleIdentityFilter { + private static final FhirServerRole SEARCH_ROLE = FhirServerRoleImpl.search(ResourceType.Patient); + private static final FhirServerRole READ_ROLE = FhirServerRoleImpl.read(ResourceType.Patient); + private static final String RESOURCE_TABLE = "current_patients"; private static final String RESOURCE_ID_COLUMN = "patient_id"; public PatientIdentityFilter(Identity identity) { - super(identity, RESOURCE_TABLE, RESOURCE_ID_COLUMN); + this(identity, RESOURCE_TABLE, RESOURCE_ID_COLUMN, SEARCH_ROLE); } - public PatientIdentityFilter(Identity identity, String resourceTable, String resourceIdColumn) + public PatientIdentityFilter(Identity identity, String resourceTable, String resourceIdColumn, + FhirServerRole operationRole) { - super(identity, resourceTable, resourceIdColumn); + super(identity, resourceTable, resourceIdColumn, operationRole, READ_ROLE); } } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/search/filter/PractitionerIdentityFilter.java b/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/search/filter/PractitionerIdentityFilter.java index 3e07fe8ff..e0efff55a 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/search/filter/PractitionerIdentityFilter.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/search/filter/PractitionerIdentityFilter.java @@ -1,19 +1,27 @@ package dev.dsf.fhir.search.filter; +import org.hl7.fhir.r4.model.ResourceType; + import dev.dsf.common.auth.conf.Identity; +import dev.dsf.fhir.authentication.FhirServerRole; +import dev.dsf.fhir.authentication.FhirServerRoleImpl; public class PractitionerIdentityFilter extends AbstractMetaTagAuthorizationRoleIdentityFilter { + private static final FhirServerRole SEARCH_ROLE = FhirServerRoleImpl.search(ResourceType.Practitioner); + private static final FhirServerRole READ_ROLE = FhirServerRoleImpl.read(ResourceType.Practitioner); + private static final String RESOURCE_TABLE = "current_practitioners"; private static final String RESOURCE_ID_COLUMN = "practitioner_id"; public PractitionerIdentityFilter(Identity identity) { - super(identity, RESOURCE_TABLE, RESOURCE_ID_COLUMN); + this(identity, RESOURCE_TABLE, RESOURCE_ID_COLUMN, SEARCH_ROLE); } - public PractitionerIdentityFilter(Identity identity, String resourceTable, String resourceIdColumn) + public PractitionerIdentityFilter(Identity identity, String resourceTable, String resourceIdColumn, + FhirServerRole operationRole) { - super(identity, resourceTable, resourceIdColumn); + super(identity, resourceTable, resourceIdColumn, operationRole, READ_ROLE); } } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/search/filter/PractitionerRoleIdentityFilter.java b/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/search/filter/PractitionerRoleIdentityFilter.java index 9e477fa2d..cd9e135ac 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/search/filter/PractitionerRoleIdentityFilter.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/search/filter/PractitionerRoleIdentityFilter.java @@ -1,19 +1,27 @@ package dev.dsf.fhir.search.filter; +import org.hl7.fhir.r4.model.ResourceType; + import dev.dsf.common.auth.conf.Identity; +import dev.dsf.fhir.authentication.FhirServerRole; +import dev.dsf.fhir.authentication.FhirServerRoleImpl; public class PractitionerRoleIdentityFilter extends AbstractMetaTagAuthorizationRoleIdentityFilter { + private static final FhirServerRole SEARCH_ROLE = FhirServerRoleImpl.search(ResourceType.PractitionerRole); + private static final FhirServerRole READ_ROLE = FhirServerRoleImpl.read(ResourceType.PractitionerRole); + private static final String RESOURCE_TABLE = "current_practitioner_roles"; private static String RESOURCE_ID_COLUMN = "practitioner_role_id"; public PractitionerRoleIdentityFilter(Identity identity) { - super(identity, RESOURCE_TABLE, RESOURCE_ID_COLUMN); + this(identity, RESOURCE_TABLE, RESOURCE_ID_COLUMN, SEARCH_ROLE); } - public PractitionerRoleIdentityFilter(Identity identity, String resourceTable, String resourceIdColumn) + public PractitionerRoleIdentityFilter(Identity identity, String resourceTable, String resourceIdColumn, + FhirServerRole operationRole) { - super(identity, resourceTable, resourceIdColumn); + super(identity, resourceTable, resourceIdColumn, operationRole, READ_ROLE); } } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/search/filter/ProvenanceIdentityFilter.java b/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/search/filter/ProvenanceIdentityFilter.java index 4b59d87f1..9a838d977 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/search/filter/ProvenanceIdentityFilter.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/search/filter/ProvenanceIdentityFilter.java @@ -1,19 +1,27 @@ package dev.dsf.fhir.search.filter; +import org.hl7.fhir.r4.model.ResourceType; + import dev.dsf.common.auth.conf.Identity; +import dev.dsf.fhir.authentication.FhirServerRole; +import dev.dsf.fhir.authentication.FhirServerRoleImpl; public class ProvenanceIdentityFilter extends AbstractMetaTagAuthorizationRoleIdentityFilter { + private static final FhirServerRole SEARCH_ROLE = FhirServerRoleImpl.search(ResourceType.Provenance); + private static final FhirServerRole READ_ROLE = FhirServerRoleImpl.read(ResourceType.Provenance); + private static final String RESOURCE_TABLE = "current_provenances"; private static final String RESOURCE_ID_COLUMN = "provenance_id"; public ProvenanceIdentityFilter(Identity identity) { - super(identity, RESOURCE_TABLE, RESOURCE_ID_COLUMN); + this(identity, RESOURCE_TABLE, RESOURCE_ID_COLUMN, SEARCH_ROLE); } - public ProvenanceIdentityFilter(Identity identity, String resourceTable, String resourceIdColumn) + public ProvenanceIdentityFilter(Identity identity, String resourceTable, String resourceIdColumn, + FhirServerRole operationRole) { - super(identity, resourceTable, resourceIdColumn); + super(identity, resourceTable, resourceIdColumn, operationRole, READ_ROLE); } } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/search/filter/QuestionnaireIdentityFilter.java b/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/search/filter/QuestionnaireIdentityFilter.java index 4f727f452..01a144561 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/search/filter/QuestionnaireIdentityFilter.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/search/filter/QuestionnaireIdentityFilter.java @@ -1,19 +1,27 @@ package dev.dsf.fhir.search.filter; +import org.hl7.fhir.r4.model.ResourceType; + import dev.dsf.common.auth.conf.Identity; +import dev.dsf.fhir.authentication.FhirServerRole; +import dev.dsf.fhir.authentication.FhirServerRoleImpl; public class QuestionnaireIdentityFilter extends AbstractMetaTagAuthorizationRoleIdentityFilter { + private static final FhirServerRole SEARCH_ROLE = FhirServerRoleImpl.search(ResourceType.Questionnaire); + private static final FhirServerRole READ_ROLE = FhirServerRoleImpl.read(ResourceType.Questionnaire); + private static final String RESOURCE_TABLE = "current_questionnaires"; private static final String RESOURCE_ID_COLUMN = "questionnaire_id"; public QuestionnaireIdentityFilter(Identity identity) { - super(identity, RESOURCE_TABLE, RESOURCE_ID_COLUMN); + this(identity, RESOURCE_TABLE, RESOURCE_ID_COLUMN, SEARCH_ROLE); } - public QuestionnaireIdentityFilter(Identity identity, String resourceTable, String resourceIdColumn) + public QuestionnaireIdentityFilter(Identity identity, String resourceTable, String resourceIdColumn, + FhirServerRole operationRole) { - super(identity, resourceTable, resourceIdColumn); + super(identity, resourceTable, resourceIdColumn, operationRole, READ_ROLE); } } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/search/filter/QuestionnaireResponseIdentityFilter.java b/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/search/filter/QuestionnaireResponseIdentityFilter.java index e231facee..c20d01246 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/search/filter/QuestionnaireResponseIdentityFilter.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/search/filter/QuestionnaireResponseIdentityFilter.java @@ -3,21 +3,36 @@ import java.sql.PreparedStatement; import java.sql.SQLException; +import org.hl7.fhir.r4.model.ResourceType; + import dev.dsf.common.auth.conf.Identity; import dev.dsf.fhir.authentication.FhirServerRole; +import dev.dsf.fhir.authentication.FhirServerRoleImpl; public class QuestionnaireResponseIdentityFilter extends AbstractIdentityFilter { + private static final FhirServerRole SEARCH_ROLE = FhirServerRoleImpl.search(ResourceType.QuestionnaireResponse); + private static final FhirServerRole READ_ROLE = FhirServerRoleImpl.read(ResourceType.QuestionnaireResponse); + + private final FhirServerRole operationRole; + public QuestionnaireResponseIdentityFilter(Identity identity) + { + this(identity, SEARCH_ROLE); + } + + public QuestionnaireResponseIdentityFilter(Identity identity, FhirServerRole operationRole) { super(identity, null, null); + + this.operationRole = operationRole; } @Override public String getFilterQuery() { // read allowed for local users - if (identity.isLocalIdentity() && identity.hasDsfRole(FhirServerRole.READ)) + if (identity.isLocalIdentity() && identity.hasDsfRole(operationRole) && identity.hasDsfRole(READ_ROLE)) return ""; // read not allowed for non local users diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/search/filter/ResearchStudyIdentityFilter.java b/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/search/filter/ResearchStudyIdentityFilter.java index 5d25eeaf7..dc23134b8 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/search/filter/ResearchStudyIdentityFilter.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/search/filter/ResearchStudyIdentityFilter.java @@ -1,19 +1,27 @@ package dev.dsf.fhir.search.filter; +import org.hl7.fhir.r4.model.ResourceType; + import dev.dsf.common.auth.conf.Identity; +import dev.dsf.fhir.authentication.FhirServerRole; +import dev.dsf.fhir.authentication.FhirServerRoleImpl; public class ResearchStudyIdentityFilter extends AbstractMetaTagAuthorizationRoleIdentityFilter { + private static final FhirServerRole SEARCH_ROLE = FhirServerRoleImpl.search(ResourceType.ResearchStudy); + private static final FhirServerRole READ_ROLE = FhirServerRoleImpl.read(ResourceType.ResearchStudy); + private static final String RESOURCE_TABLE = "current_research_studies"; private static final String RESOURCE_ID_COLUMN = "research_study_id"; public ResearchStudyIdentityFilter(Identity identity) { - super(identity, RESOURCE_TABLE, RESOURCE_ID_COLUMN); + this(identity, RESOURCE_TABLE, RESOURCE_ID_COLUMN, SEARCH_ROLE); } - public ResearchStudyIdentityFilter(Identity identity, String resourceTable, String resourceIdColumn) + public ResearchStudyIdentityFilter(Identity identity, String resourceTable, String resourceIdColumn, + FhirServerRole operationRole) { - super(identity, resourceTable, resourceIdColumn); + super(identity, resourceTable, resourceIdColumn, operationRole, READ_ROLE); } } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/search/filter/StructureDefinitionIdentityFilter.java b/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/search/filter/StructureDefinitionIdentityFilter.java index 81513764f..d3cbe155c 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/search/filter/StructureDefinitionIdentityFilter.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/search/filter/StructureDefinitionIdentityFilter.java @@ -1,19 +1,27 @@ package dev.dsf.fhir.search.filter; +import org.hl7.fhir.r4.model.ResourceType; + import dev.dsf.common.auth.conf.Identity; +import dev.dsf.fhir.authentication.FhirServerRole; +import dev.dsf.fhir.authentication.FhirServerRoleImpl; public class StructureDefinitionIdentityFilter extends AbstractMetaTagAuthorizationRoleIdentityFilter { + private static final FhirServerRole SEARCH_ROLE = FhirServerRoleImpl.search(ResourceType.StructureDefinition); + private static final FhirServerRole READ_ROLE = FhirServerRoleImpl.read(ResourceType.StructureDefinition); + private static final String RESOURCE_TABLE = "current_structure_definitions"; private static final String RESOURCE_ID_COLUMN = "structure_definition_id"; public StructureDefinitionIdentityFilter(Identity identity) { - super(identity, RESOURCE_TABLE, RESOURCE_ID_COLUMN); + this(identity, RESOURCE_TABLE, RESOURCE_ID_COLUMN, SEARCH_ROLE); } - public StructureDefinitionIdentityFilter(Identity identity, String resourceTable, String resourceIdColumn) + public StructureDefinitionIdentityFilter(Identity identity, String resourceTable, String resourceIdColumn, + FhirServerRole operationRole) { - super(identity, resourceTable, resourceIdColumn); + super(identity, resourceTable, resourceIdColumn, operationRole, READ_ROLE); } } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/search/filter/StructureDefinitionSnapshotIdentityFilter.java b/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/search/filter/StructureDefinitionSnapshotIdentityFilter.java index e619c79a3..a266aea8c 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/search/filter/StructureDefinitionSnapshotIdentityFilter.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/search/filter/StructureDefinitionSnapshotIdentityFilter.java @@ -1,19 +1,27 @@ package dev.dsf.fhir.search.filter; +import org.hl7.fhir.r4.model.ResourceType; + import dev.dsf.common.auth.conf.Identity; +import dev.dsf.fhir.authentication.FhirServerRole; +import dev.dsf.fhir.authentication.FhirServerRoleImpl; public class StructureDefinitionSnapshotIdentityFilter extends AbstractMetaTagAuthorizationRoleIdentityFilter { + private static final FhirServerRole SEARCH_ROLE = FhirServerRoleImpl.search(ResourceType.StructureDefinition); + private static final FhirServerRole READ_ROLE = FhirServerRoleImpl.read(ResourceType.StructureDefinition); + private static final String RESOURCE_TABLE = "current_structure_definition_snapshots"; private static final String RESOURCE_ID_COLUMN = "structure_definition_snapshot_id"; public StructureDefinitionSnapshotIdentityFilter(Identity identity) { - super(identity, RESOURCE_TABLE, RESOURCE_ID_COLUMN); + this(identity, RESOURCE_TABLE, RESOURCE_ID_COLUMN, SEARCH_ROLE); } - public StructureDefinitionSnapshotIdentityFilter(Identity identity, String resourceTable, String resourceIdColumn) + public StructureDefinitionSnapshotIdentityFilter(Identity identity, String resourceTable, String resourceIdColumn, + FhirServerRole operationRole) { - super(identity, resourceTable, resourceIdColumn); + super(identity, resourceTable, resourceIdColumn, operationRole, READ_ROLE); } } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/search/filter/SubscriptionIdentityFilter.java b/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/search/filter/SubscriptionIdentityFilter.java index 175597a12..b700a9a08 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/search/filter/SubscriptionIdentityFilter.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/search/filter/SubscriptionIdentityFilter.java @@ -1,19 +1,27 @@ package dev.dsf.fhir.search.filter; +import org.hl7.fhir.r4.model.ResourceType; + import dev.dsf.common.auth.conf.Identity; +import dev.dsf.fhir.authentication.FhirServerRole; +import dev.dsf.fhir.authentication.FhirServerRoleImpl; public class SubscriptionIdentityFilter extends AbstractMetaTagAuthorizationRoleIdentityFilter { + private static final FhirServerRole SEARCH_ROLE = FhirServerRoleImpl.search(ResourceType.Subscription); + private static final FhirServerRole READ_ROLE = FhirServerRoleImpl.read(ResourceType.Subscription); + private static final String RESOURCE_TABLE = "current_subscriptions"; private static final String RESOURCE_ID_COLUMN = "subscription_id"; public SubscriptionIdentityFilter(Identity identity) { - super(identity, RESOURCE_TABLE, RESOURCE_ID_COLUMN); + this(identity, RESOURCE_TABLE, RESOURCE_ID_COLUMN, SEARCH_ROLE); } - public SubscriptionIdentityFilter(Identity identity, String resourceTable, String resourceIdColumn) + public SubscriptionIdentityFilter(Identity identity, String resourceTable, String resourceIdColumn, + FhirServerRole operationRole) { - super(identity, resourceTable, resourceIdColumn); + super(identity, resourceTable, resourceIdColumn, operationRole, READ_ROLE); } } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/search/filter/TaskIdentityFilter.java b/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/search/filter/TaskIdentityFilter.java index 6fb8aebbc..0eecef93f 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/search/filter/TaskIdentityFilter.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/search/filter/TaskIdentityFilter.java @@ -3,33 +3,39 @@ import java.sql.PreparedStatement; import java.sql.SQLException; +import org.hl7.fhir.r4.model.ResourceType; + import dev.dsf.common.auth.conf.Identity; import dev.dsf.fhir.authentication.FhirServerRole; +import dev.dsf.fhir.authentication.FhirServerRoleImpl; public class TaskIdentityFilter extends AbstractIdentityFilter { + private static final FhirServerRole SEARCH_ROLE = FhirServerRoleImpl.search(ResourceType.Task); + private static final FhirServerRole READ_ROLE = FhirServerRoleImpl.read(ResourceType.Task); + private static final String RESOURCE_COLUMN = "task"; private final String resourceColumn; + private final FhirServerRole operationRole; public TaskIdentityFilter(Identity identity) { - super(identity, null, null); - - this.resourceColumn = RESOURCE_COLUMN; + this(identity, RESOURCE_COLUMN, SEARCH_ROLE); } - public TaskIdentityFilter(Identity identity, String resourceColumn) + public TaskIdentityFilter(Identity identity, String resourceColumn, FhirServerRole operationRole) { super(identity, null, null); this.resourceColumn = resourceColumn; + this.operationRole = operationRole; } @Override public String getFilterQuery() { - if (identity.hasDsfRole(FhirServerRole.READ)) + if (identity.hasDsfRole(operationRole) && identity.hasDsfRole(READ_ROLE)) { // TODO modify for requester = Practitioner or PractitionerRole return "(" + resourceColumn + "->'requester'->>'reference' = ? OR " + resourceColumn @@ -44,14 +50,14 @@ public String getFilterQuery() @Override public int getSqlParameterCount() { - return identity.hasDsfRole(FhirServerRole.READ) ? 4 : 0; + return identity.hasDsfRole(operationRole) && identity.hasDsfRole(READ_ROLE) ? 4 : 0; } @Override public void modifyStatement(int parameterIndex, int subqueryParameterIndex, PreparedStatement statement) throws SQLException { - if (identity.hasDsfRole(FhirServerRole.READ)) + if (identity.hasDsfRole(operationRole) && identity.hasDsfRole(READ_ROLE)) { if (subqueryParameterIndex == 1) statement.setString(parameterIndex, identity.getOrganization().getIdElement().getValue()); diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/search/filter/ValueSetIdentityFilter.java b/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/search/filter/ValueSetIdentityFilter.java index 92ed1e555..dc4bb2852 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/search/filter/ValueSetIdentityFilter.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/search/filter/ValueSetIdentityFilter.java @@ -1,19 +1,27 @@ package dev.dsf.fhir.search.filter; +import org.hl7.fhir.r4.model.ResourceType; + import dev.dsf.common.auth.conf.Identity; +import dev.dsf.fhir.authentication.FhirServerRole; +import dev.dsf.fhir.authentication.FhirServerRoleImpl; public class ValueSetIdentityFilter extends AbstractMetaTagAuthorizationRoleIdentityFilter { + private static final FhirServerRole SEARCH_ROLE = FhirServerRoleImpl.search(ResourceType.ValueSet); + private static final FhirServerRole READ_ROLE = FhirServerRoleImpl.read(ResourceType.ValueSet); + private static final String RESOURCE_TABLE = "current_value_sets"; private static final String RESOURCE_ID_COLUMN = "value_set_id"; public ValueSetIdentityFilter(Identity identity) { - super(identity, RESOURCE_TABLE, RESOURCE_ID_COLUMN); + this(identity, RESOURCE_TABLE, RESOURCE_ID_COLUMN, SEARCH_ROLE); } - public ValueSetIdentityFilter(Identity identity, String resourceTable, String resourceIdColumn) + public ValueSetIdentityFilter(Identity identity, String resourceTable, String resourceIdColumn, + FhirServerRole operationRole) { - super(identity, resourceTable, resourceIdColumn); + super(identity, resourceTable, resourceIdColumn, operationRole, READ_ROLE); } } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/service/InitialDataLoaderImpl.java b/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/service/InitialDataLoaderImpl.java index 6616c91df..c092dc5b0 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/service/InitialDataLoaderImpl.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/service/InitialDataLoaderImpl.java @@ -1,6 +1,5 @@ package dev.dsf.fhir.service; -import java.util.EnumSet; import java.util.Objects; import org.hl7.fhir.r4.model.Bundle; @@ -13,7 +12,7 @@ import ca.uhn.fhir.context.FhirContext; import dev.dsf.common.auth.conf.Identity; import dev.dsf.common.auth.conf.OrganizationIdentityImpl; -import dev.dsf.fhir.authentication.FhirServerRole; +import dev.dsf.fhir.authentication.FhirServerRoleImpl; import dev.dsf.fhir.authorization.read.ReadAccessHelper; import dev.dsf.fhir.dao.command.CommandFactory; import dev.dsf.fhir.dao.command.CommandList; @@ -28,8 +27,8 @@ public class InitialDataLoaderImpl implements InitialDataLoader, InitializingBea Organization org = new Organization().setName("Initial Data Loader"); org.addIdentifier().setSystem(ReadAccessHelper.ORGANIZATION_IDENTIFIER_SYSTEM).setValue("initial.data.loader"); - INITIAL_DATA_LOADER = new OrganizationIdentityImpl(true, org, null, - EnumSet.of(FhirServerRole.CREATE, FhirServerRole.DELETE, FhirServerRole.UPDATE), null); + INITIAL_DATA_LOADER = new OrganizationIdentityImpl(true, org, null, FhirServerRoleImpl.INITIAL_DATA_LOADER, + null); } private static final Logger logger = LoggerFactory.getLogger(InitialDataLoaderImpl.class); diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/service/ReferenceResolver.java b/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/service/ReferenceResolver.java index 048d9e8ca..bc9103f8a 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/service/ReferenceResolver.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/service/ReferenceResolver.java @@ -6,8 +6,6 @@ import org.hl7.fhir.r4.model.OperationOutcome; import org.hl7.fhir.r4.model.Resource; -import dev.dsf.common.auth.conf.Identity; - public interface ReferenceResolver { /** @@ -20,8 +18,6 @@ public interface ReferenceResolver boolean referenceCanBeResolved(ResourceReference reference, Connection connection); /** - * @param identity - * not null * @param reference * not null * @param connection @@ -33,7 +29,7 @@ public interface ReferenceResolver * {@link ResourceReference.ReferenceType#CONDITIONAL} or * {@link ResourceReference.ReferenceType#LOGICAL} */ - Optional resolveReference(Identity identity, ResourceReference reference, Connection connection); + Optional resolveReference(ResourceReference reference, Connection connection); /** * @param resource @@ -96,8 +92,6 @@ Optional checkLiteralExternalReference(Resource resource, Reso Integer bundleIndex) throws IllegalArgumentException; /** - * @param identity - * not null * @param resource * not null * @param resourceReference @@ -111,13 +105,10 @@ Optional checkLiteralExternalReference(Resource resource, Reso * if the reference is not of type {@link ResourceReference.ReferenceType#CONDITIONAL} * @see ResourceReference#getType(String) */ - Optional checkConditionalReference(Identity identity, Resource resource, - ResourceReference resourceReference, Connection connection, Integer bundleIndex) - throws IllegalArgumentException; + Optional checkConditionalReference(Resource resource, ResourceReference resourceReference, + Connection connection, Integer bundleIndex) throws IllegalArgumentException; /** - * @param identity - * not null * @param resource * not null * @param resourceReference @@ -129,12 +120,10 @@ Optional checkConditionalReference(Identity identity, Resource * if the reference is not of type {@link ResourceReference.ReferenceType#LOGICAL} * @see ResourceReference#getType(String) */ - Optional checkLogicalReference(Identity identity, Resource resource, - ResourceReference resourceReference, Connection connection) throws IllegalArgumentException; + Optional checkLogicalReference(Resource resource, ResourceReference resourceReference, + Connection connection) throws IllegalArgumentException; /** - * @param identity - * not null * @param resource * not null * @param resourceReference @@ -148,13 +137,10 @@ Optional checkLogicalReference(Identity identity, Resource res * if the reference is not of type {@link ResourceReference.ReferenceType#LOGICAL} * @see ResourceReference#getType(String) */ - Optional checkLogicalReference(Identity identity, Resource resource, - ResourceReference resourceReference, Connection connection, Integer bundleIndex) - throws IllegalArgumentException; + Optional checkLogicalReference(Resource resource, ResourceReference resourceReference, + Connection connection, Integer bundleIndex) throws IllegalArgumentException; /** - * @param identity - * not null * @param resource * not null * @param reference @@ -166,12 +152,10 @@ Optional checkLogicalReference(Identity identity, Resource res * if the reference is not of type {@link ResourceReference.ReferenceType#CANONICAL} * @see ResourceReference#getType(String) */ - Optional checkCanonicalReference(Identity identity, Resource resource, - ResourceReference reference, Connection connection) throws IllegalArgumentException; + Optional checkCanonicalReference(Resource resource, ResourceReference reference, + Connection connection) throws IllegalArgumentException; /** - * @param identity - * not null * @param resource * not null * @param reference @@ -185,6 +169,6 @@ Optional checkCanonicalReference(Identity identity, Resource r * if the reference is not of type {@link ResourceReference.ReferenceType#CANONICAL} * @see ResourceReference#getType(String) */ - Optional checkCanonicalReference(Identity identity, Resource resource, - ResourceReference reference, Connection connection, Integer bundleIndex) throws IllegalArgumentException; + Optional checkCanonicalReference(Resource resource, ResourceReference reference, + Connection connection, Integer bundleIndex) throws IllegalArgumentException; } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/service/ReferenceResolverImpl.java b/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/service/ReferenceResolverImpl.java index 035a5c226..801f8335e 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/service/ReferenceResolverImpl.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/service/ReferenceResolverImpl.java @@ -22,7 +22,6 @@ import org.springframework.web.util.UriComponents; import org.springframework.web.util.UriComponentsBuilder; -import dev.dsf.common.auth.conf.Identity; import dev.dsf.fhir.client.ClientProvider; import dev.dsf.fhir.client.FhirWebserviceClient; import dev.dsf.fhir.dao.ResourceDao; @@ -95,9 +94,8 @@ public boolean referenceCanBeResolved(ResourceReference reference, Connection co } @Override - public Optional resolveReference(Identity identity, ResourceReference reference, Connection connection) + public Optional resolveReference(ResourceReference reference, Connection connection) { - Objects.requireNonNull(identity, "identity"); Objects.requireNonNull(reference, "reference"); Objects.requireNonNull(connection, "connection"); @@ -108,8 +106,8 @@ public Optional resolveReference(Identity identity, ResourceReference case LITERAL_EXTERNAL, RELATED_ARTEFACT_LITERAL_EXTERNAL_URL, ATTACHMENT_LITERAL_EXTERNAL_URL -> resolveLiteralExternalReference(reference); case CONDITIONAL, RELATED_ARTEFACT_CONDITIONAL_URL, ATTACHMENT_CONDITIONAL_URL -> - resolveConditionalReference(identity, reference, connection); - case LOGICAL -> resolveLogicalReference(identity, reference, connection); + resolveConditionalReference(reference, connection); + case LOGICAL -> resolveLogicalReference(reference, connection); default -> throw new IllegalArgumentException("Reference of type " + type + " not supported"); }; @@ -215,8 +213,7 @@ private Optional resolveLiteralExternalReference(ResourceReference ref } } - private Optional resolveConditionalReference(Identity identity, ResourceReference reference, - Connection connection) + private Optional resolveConditionalReference(ResourceReference reference, Connection connection) { Objects.requireNonNull(reference, "reference"); @@ -252,12 +249,11 @@ private Optional resolveConditionalReference(Identity identity, Resour return Optional.empty(); } - return search(identity, connection, d, reference, condition.getQueryParams(), referenceType); + return search(connection, d, reference, condition.getQueryParams(), referenceType); } } - private Optional resolveLogicalReference(Identity identity, ResourceReference reference, - Connection connection) + private Optional resolveLogicalReference(ResourceReference reference, Connection connection) { Objects.requireNonNull(reference, "reference"); throwIfReferenceTypeUnexpected(reference.getType(serverBase), ReferenceType.LOGICAL); @@ -283,13 +279,13 @@ private Optional resolveLogicalReference(Identity identity, ResourceRe } Identifier targetIdentifier = reference.getReference().getIdentifier(); - return search(identity, connection, d, reference, + return search(connection, d, reference, Map.of("identifier", List.of(targetIdentifier.getSystem() + "|" + targetIdentifier.getValue())), ReferenceType.LOGICAL); } } - private Optional search(Identity identity, Connection connection, ResourceDao referenceTargetDao, + private Optional search(Connection connection, ResourceDao referenceTargetDao, ResourceReference resourceReference, Map> queryParameters, ReferenceType referenceType) { if (Arrays.stream(SearchQuery.STANDARD_PARAMETERS).anyMatch(queryParameters::containsKey)) @@ -305,7 +301,7 @@ private Optional search(Identity identity, Connection connection, Reso .collect(Collectors.toMap(Entry::getKey, Entry::getValue)); } - SearchQuery query = referenceTargetDao.createSearchQuery(identity, PageAndCount.single()); + SearchQuery query = referenceTargetDao.createSearchQueryWithoutUserFilter(PageAndCount.single()); query.configureParameters(queryParameters); List unsupportedQueryParameters = query.getUnsupportedQueryParameters(); @@ -462,10 +458,9 @@ public Optional checkLiteralExternalReference(Resource resourc } @Override - public Optional checkConditionalReference(Identity identity, Resource resource, - ResourceReference reference, Connection connection, Integer bundleIndex) throws IllegalArgumentException + public Optional checkConditionalReference(Resource resource, ResourceReference reference, + Connection connection, Integer bundleIndex) throws IllegalArgumentException { - Objects.requireNonNull(identity, "identity"); Objects.requireNonNull(resource, "resource"); Objects.requireNonNull(reference, "reference"); Objects.requireNonNull(connection, "connection"); @@ -489,7 +484,7 @@ public Optional checkConditionalReference(Identity identity, R responseGenerator.referenceTargetTypeNotSupportedByResource(bundleIndex, resource, reference)); // Resource target = - return search(identity, resource, bundleIndex, connection, d, reference, condition.getQueryParams(), true); + return search(resource, bundleIndex, connection, d, reference, condition.getQueryParams(), true); // TODO add literal reference for conditional reference somewhere else // reference.getReference().setIdentifier(null).setReferenceElement( @@ -500,17 +495,16 @@ public Optional checkConditionalReference(Identity identity, R } @Override - public Optional checkLogicalReference(Identity identity, Resource resource, - ResourceReference resourceReference, Connection connection) throws IllegalArgumentException + public Optional checkLogicalReference(Resource resource, ResourceReference resourceReference, + Connection connection) throws IllegalArgumentException { - return checkLogicalReference(identity, resource, resourceReference, connection, null); + return checkLogicalReference(resource, resourceReference, connection, null); } @Override - public Optional checkLogicalReference(Identity identity, Resource resource, - ResourceReference reference, Connection connection, Integer bundleIndex) throws IllegalArgumentException + public Optional checkLogicalReference(Resource resource, ResourceReference reference, + Connection connection, Integer bundleIndex) throws IllegalArgumentException { - Objects.requireNonNull(identity, "identity"); Objects.requireNonNull(resource, "resource"); Objects.requireNonNull(reference, "reference"); Objects.requireNonNull(connection, "connection"); @@ -532,7 +526,7 @@ public Optional checkLogicalReference(Identity identity, Resou Identifier targetIdentifier = reference.getReference().getIdentifier(); // Resource target = - return search(identity, resource, bundleIndex, connection, d, reference, + return search(resource, bundleIndex, connection, d, reference, Map.of("identifier", List.of(targetIdentifier.getSystem() + "|" + targetIdentifier.getValue())), true); @@ -547,8 +541,8 @@ public Optional checkLogicalReference(Identity identity, Resou // return Optional.empty(); } - private Optional search(Identity identity, Resource resource, Integer bundleIndex, - Connection connection, ResourceDao referenceTargetDao, ResourceReference resourceReference, + private Optional search(Resource resource, Integer bundleIndex, Connection connection, + ResourceDao referenceTargetDao, ResourceReference resourceReference, Map> queryParameters, boolean logicalNotConditional) { if (Arrays.stream(SearchQuery.STANDARD_PARAMETERS).anyMatch(queryParameters::containsKey)) @@ -564,7 +558,7 @@ private Optional search(Identity identity, Resource resource, .collect(Collectors.toMap(Entry::getKey, Entry::getValue)); } - SearchQuery query = referenceTargetDao.createSearchQuery(identity, PageAndCount.exists()); + SearchQuery query = referenceTargetDao.createSearchQueryWithoutUserFilter(PageAndCount.exists()); query.configureParameters(queryParameters); List unsupportedQueryParameters = query.getUnsupportedQueryParameters(); @@ -604,17 +598,16 @@ else if (result.getTotal() == 1) } @Override - public Optional checkCanonicalReference(Identity identity, Resource resource, - ResourceReference reference, Connection connection) throws IllegalArgumentException + public Optional checkCanonicalReference(Resource resource, ResourceReference reference, + Connection connection) throws IllegalArgumentException { - return checkCanonicalReference(identity, resource, reference, connection, null); + return checkCanonicalReference(resource, reference, connection, null); } @Override - public Optional checkCanonicalReference(Identity identity, Resource resource, - ResourceReference reference, Connection connection, Integer bundleIndex) throws IllegalArgumentException + public Optional checkCanonicalReference(Resource resource, ResourceReference reference, + Connection connection, Integer bundleIndex) throws IllegalArgumentException { - Objects.requireNonNull(identity, "identity"); Objects.requireNonNull(resource, "resource"); Objects.requireNonNull(reference, "reference"); Objects.requireNonNull(connection, "connection"); @@ -636,7 +629,7 @@ public Optional checkCanonicalReference(Identity identity, Res return Optional.empty(); } - Optional referencedResource = referenceDao.flatMap(dao -> search(identity, connection, dao, reference, + Optional referencedResource = referenceDao.flatMap(dao -> search(connection, dao, reference, Map.of("url", List.of(reference.getCanonical().getValue())), ReferenceType.CANONICAL)); if (referencedResource.isPresent()) diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/spring/config/AuthenticationConfig.java b/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/spring/config/AuthenticationConfig.java index d6e09ced8..22509b946 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/spring/config/AuthenticationConfig.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/spring/config/AuthenticationConfig.java @@ -13,6 +13,7 @@ import dev.dsf.fhir.authentication.EndpointProvider; import dev.dsf.fhir.authentication.EndpointProviderImpl; import dev.dsf.fhir.authentication.FhirServerRole; +import dev.dsf.fhir.authentication.FhirServerRoleImpl; import dev.dsf.fhir.authentication.IdentityProviderImpl; import dev.dsf.fhir.authentication.OrganizationProvider; import dev.dsf.fhir.authentication.OrganizationProviderImpl; @@ -53,11 +54,10 @@ public IdentityProvider identityProvider() } @Bean - public RoleConfig roleConfig() + public RoleConfig roleConfig() { - RoleConfig config = new RoleConfigReader().read(propertiesConfig.getRoleConfig(), - role -> FhirServerRole.isValid(role) ? FhirServerRole.valueOf(role) : null, - this::practionerRoleFactory); + RoleConfig config = new RoleConfigReader().read(propertiesConfig.getRoleConfig(), + FhirServerRoleImpl::from, this::practionerRoleFactory); logger.info("Role config: {}", config.toString()); return config; diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/subscription/WebSocketSubscriptionManagerImpl.java b/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/subscription/WebSocketSubscriptionManagerImpl.java index 9d9d29410..6b83e4d92 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/subscription/WebSocketSubscriptionManagerImpl.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/subscription/WebSocketSubscriptionManagerImpl.java @@ -278,7 +278,7 @@ else if (Constants.CT_FHIR_XML_NEW.contentEquals(s.getChannel().getPayload())) // defensive copy because list could be changed by other threads while we are reading List remotes = new ArrayList<>(optRemotes.get()); - remotes.stream().filter(r -> userHasReadAccess(r, event)).forEach(r -> send(r, text)); + remotes.stream().filter(r -> userHasReadAndWebsocketAccess(r, event)).forEach(r -> send(r, text)); } private IParser newXmlParser() @@ -298,7 +298,7 @@ private IParser configureParser(IParser p) return p; } - private boolean userHasReadAccess(SessionIdAndRemoteAsync sessionAndRemote, Event event) + private boolean userHasReadAndWebsocketAccess(SessionIdAndRemoteAsync sessionAndRemote, Event event) { Optional> optRule = authorizationRuleProvider .getAuthorizationRule(event.getResourceType()); @@ -306,18 +306,23 @@ private boolean userHasReadAccess(SessionIdAndRemoteAsync sessionAndRemote, Even { @SuppressWarnings("unchecked") AuthorizationRule rule = (AuthorizationRule) optRule.get(); - Optional optReason = rule.reasonReadAllowed(sessionAndRemote.identity, event.getResource()); + Optional readAllowedReason = rule.reasonReadAllowed(sessionAndRemote.identity, event.getResource()); + Optional websocketAllowedReason = rule.reasonWebsocketAllowed(sessionAndRemote.identity, + event.getResource()); - if (optReason.isPresent()) + if (readAllowedReason.isPresent() && websocketAllowedReason.isPresent()) { - logger.info("Sending event {} to user {}, read of {} allowed {}", event.getClass().getSimpleName(), - sessionAndRemote.identity.getName(), event.getResourceType().getSimpleName(), optReason.get()); + logger.info("Sending event {} to user {}, websocket access and read of {} allowed {}, {}", + event.getClass().getSimpleName(), sessionAndRemote.identity.getName(), + event.getResourceType().getSimpleName(), websocketAllowedReason.get(), + readAllowedReason.isPresent()); return true; } else { - logger.warn("Skipping event {} for user {}, read of {} not allowed", event.getClass().getSimpleName(), - sessionAndRemote.identity.getName(), event.getResourceType().getSimpleName()); + logger.warn("Skipping event {} for user {}, websocket access or read of {} not allowed", + event.getClass().getSimpleName(), sessionAndRemote.identity.getName(), + event.getResourceType().getSimpleName()); return false; } } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/webservice/impl/AbstractResourceServiceImpl.java b/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/webservice/impl/AbstractResourceServiceImpl.java index 3fcbc0d22..201df11c0 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/webservice/impl/AbstractResourceServiceImpl.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/webservice/impl/AbstractResourceServiceImpl.java @@ -252,8 +252,7 @@ private void resolveLogicalReferences(Resource resource, Connection connection) private Optional resolveLogicalReference(Resource resource, ResourceReference reference, Connection connection) { - Optional resolvedResource = referenceResolver.resolveReference(getCurrentIdentity(), reference, - connection); + Optional resolvedResource = referenceResolver.resolveReference(reference, connection); if (resolvedResource.isPresent()) { Resource target = resolvedResource.get(); @@ -292,11 +291,9 @@ private Optional checkReference(Resource resource, Connection case LITERAL_EXTERNAL, RELATED_ARTEFACT_LITERAL_EXTERNAL_URL, ATTACHMENT_LITERAL_EXTERNAL_URL -> referenceResolver.checkLiteralExternalReference(resource, reference); - case LOGICAL -> - referenceResolver.checkLogicalReference(getCurrentIdentity(), resource, reference, connection); + case LOGICAL -> referenceResolver.checkLogicalReference(resource, reference, connection); - case CANONICAL -> - referenceResolver.checkCanonicalReference(getCurrentIdentity(), resource, reference, connection); + case CANONICAL -> referenceResolver.checkCanonicalReference(resource, reference, connection); // unknown URLs to non FHIR servers in related artifacts must not be checked case RELATED_ARTEFACT_UNKNOWN_URL, ATTACHMENT_UNKNOWN_URL -> Optional.empty(); diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/websocket/ServerEndpoint.java b/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/websocket/ServerEndpoint.java index 183077bef..4a8896917 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/websocket/ServerEndpoint.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/websocket/ServerEndpoint.java @@ -17,8 +17,9 @@ import org.springframework.beans.factory.DisposableBean; import org.springframework.beans.factory.InitializingBean; +import dev.dsf.common.auth.conf.DsfRole; import dev.dsf.common.auth.conf.Identity; -import dev.dsf.fhir.authentication.FhirServerRole; +import dev.dsf.fhir.authentication.FhirServerRoleImpl; import dev.dsf.fhir.subscription.WebSocketSubscriptionManager; import jakarta.websocket.CloseReason; import jakarta.websocket.CloseReason.CloseCodes; @@ -56,11 +57,11 @@ public void afterPropertiesSet() throws Exception public void onOpen(Session session, EndpointConfig config) { Principal principal = session.getUserPrincipal(); - if (principal == null || !(principal instanceof Identity) - || !((Identity) principal).hasDsfRole(FhirServerRole.WEBSOCKET)) + if (principal == null || !(principal instanceof Identity) || !((Identity) principal).getDsfRoles().stream() + .map(DsfRole::name).anyMatch(FhirServerRoleImpl.Operation.WEBSOCKET.name()::equals)) { logger.warn("No user in session or user is missing role {}, closing websocket, session {}", - FhirServerRole.WEBSOCKET, session.getId()); + FhirServerRoleImpl.Operation.WEBSOCKET, session.getId()); try { session.close(new CloseReason(CloseCodes.VIOLATED_POLICY, "Forbidden")); diff --git a/dsf-fhir/dsf-fhir-server/src/test/java/dev/dsf/fhir/authentication/IdentityProviderTest.java b/dsf-fhir/dsf-fhir-server/src/test/java/dev/dsf/fhir/authentication/IdentityProviderTest.java index 60d95c6a8..89e01534c 100644 --- a/dsf-fhir/dsf-fhir-server/src/test/java/dev/dsf/fhir/authentication/IdentityProviderTest.java +++ b/dsf-fhir/dsf-fhir-server/src/test/java/dev/dsf/fhir/authentication/IdentityProviderTest.java @@ -15,7 +15,6 @@ import java.security.cert.CertificateException; import java.security.cert.X509Certificate; import java.time.Period; -import java.util.EnumSet; import java.util.List; import java.util.Map; import java.util.Optional; @@ -40,6 +39,7 @@ import dev.dsf.common.auth.conf.PractitionerIdentity; import dev.dsf.common.auth.conf.RoleConfig; import dev.dsf.common.auth.conf.RoleConfig.Mapping; +import dev.dsf.fhir.authentication.FhirServerRoleImpl.Operation; public class IdentityProviderTest { @@ -117,10 +117,10 @@ public class IdentityProviderTest private OrganizationProvider organizationProvider; private EndpointProvider endpointProvider; - private RoleConfig roleConfig; + private RoleConfig roleConfig; private DsfOpenIdCredentials credentials; - private IdentityProvider createIdentityProvider(List mappings) + private IdentityProvider createIdentityProvider(List> mappings) { when(roleConfig.getEntries()).thenReturn(mappings); @@ -132,16 +132,19 @@ private IdentityProvider createIdentityProvider(List mappings) return provider; } - private Mapping createMappingWithThumbprint(String thumbprint) + private Mapping createMappingWithThumbprint(String thumbprint) { - return new Mapping("test-mapping", List.of(thumbprint), List.of(), List.of(), List.of(), List.of(), List.of()); + return new Mapping("test-mapping", List.of(thumbprint), List.of(), List.of(), List.of(), + List.of(), List.of()); } - private Mapping createMappingWithEmail(String email) + private Mapping createMappingWithEmail(String email) { - return new Mapping("test-mapping", List.of(), List.of(email), List.of(), List.of(), List.of(), List.of()); + return new Mapping("test-mapping", List.of(), List.of(email), List.of(), List.of(), List.of(), + List.of()); } + @SuppressWarnings("unchecked") @Before public void before() throws Exception { @@ -194,7 +197,7 @@ public void testGetOrganizationIdentityByX509CertificateLocalOrganization() thro assertTrue(orgI.getCertificate().isPresent()); assertEquals(LOCAL_ORGANIZATION_CERTIFICATE, orgI.getCertificate().get()); assertEquals(LOCAL_ORGANIZATION_IDENTIFIER_VALUE, orgI.getDisplayName()); - assertEquals(FhirServerRole.LOCAL_ORGANIZATION, orgI.getDsfRoles()); + assertEquals(FhirServerRoleImpl.LOCAL_ORGANIZATION, orgI.getDsfRoles()); assertEquals(LOCAL_ORGANIZATION_IDENTIFIER_VALUE, orgI.getName()); assertEquals(LOCAL_ORGANIZATION, orgI.getOrganization()); assertEquals(LOCAL_ORGANIZATION_IDENTIFIER_VALUE, orgI.getOrganizationIdentifierValue().get()); @@ -225,7 +228,7 @@ public void testGetOrganizationIdentityByX509CertificateRemoteOrganization() thr assertTrue(orgI.getCertificate().isPresent()); assertEquals(REMOTE_ORGANIZATION_CERTIFICATE, orgI.getCertificate().get()); assertEquals(REMOTE_ORGANIZATION_IDENTIFIER_VALUE, orgI.getDisplayName()); - assertEquals(FhirServerRole.REMOTE_ORGANIZATION, orgI.getDsfRoles()); + assertEquals(FhirServerRoleImpl.REMOTE_ORGANIZATION, orgI.getDsfRoles()); assertEquals(REMOTE_ORGANIZATION_IDENTIFIER_VALUE, orgI.getName()); assertEquals(REMOTE_ORGANIZATION, orgI.getOrganization()); assertEquals(REMOTE_ORGANIZATION_IDENTIFIER_VALUE, orgI.getOrganizationIdentifierValue().get()); @@ -270,9 +273,10 @@ public void testGetPractitionerIdentityByX509Certificate() throws Exception when(organizationProvider.getOrganization(LOCAL_ORGANIZATION_CERTIFICATE)).thenReturn(Optional.empty()); when(organizationProvider.getLocalOrganization()).thenReturn(Optional.of(LOCAL_ORGANIZATION)); when(endpointProvider.getLocalEndpoint()).thenReturn(Optional.of(LOCAL_ENDPOINT)); - when(roleConfig.getDsfRolesForEmail(LOCAL_PRACTITIONER_MAIL)).thenReturn(List.of(FhirServerRole.CREATE)); + when(roleConfig.getDsfRolesForEmail(LOCAL_PRACTITIONER_MAIL)) + .thenReturn(List.of(Operation.CREATE.toFhirServerRoleAllResources())); when(roleConfig.getDsfRolesForThumbprint(LOCAL_PRACTITIONER_CERTIFICATE_THUMBPRINT)) - .thenReturn(List.of(FhirServerRole.DELETE)); + .thenReturn(List.of(Operation.DELETE.toFhirServerRoleAllResources())); when(roleConfig.getPractitionerRolesForEmail(LOCAL_PRACTITIONER_MAIL)).thenReturn(List.of(PRACTIONER_ROLE1)); when(roleConfig.getPractitionerRolesForThumbprint(LOCAL_PRACTITIONER_CERTIFICATE_THUMBPRINT)) .thenReturn(List.of(PRACTIONER_ROLE2)); @@ -289,7 +293,8 @@ public void testGetPractitionerIdentityByX509Certificate() throws Exception assertTrue(practitionerI.getCredentials().isEmpty()); assertEquals(LOCAL_PRACTITIONER_NAME_GIVEN + " " + LOCAL_PRACTITIONER_NAME_FAMILY, practitionerI.getDisplayName()); - assertEquals(EnumSet.of(FhirServerRole.CREATE, FhirServerRole.DELETE), practitionerI.getDsfRoles()); + assertEquals(Set.of(Operation.CREATE.toFhirServerRoleAllResources(), + Operation.DELETE.toFhirServerRoleAllResources()), practitionerI.getDsfRoles()); assertEquals(LOCAL_ORGANIZATION_IDENTIFIER_VALUE + "/" + LOCAL_PRACTITIONER_MAIL, practitionerI.getName()); assertEquals(LOCAL_ORGANIZATION, practitionerI.getOrganization()); assertEquals(LOCAL_ORGANIZATION_IDENTIFIER_VALUE, practitionerI.getOrganizationIdentifierValue().get()); @@ -362,11 +367,14 @@ public void testGetPractitionerIdentityByOpenIdCredentials() throws Exception Map.of("resource_access", Map.of(TOKEN_ROLE2_CLIENT, Map.of("roles", new String[] { TOKEN_ROLE2 })), "groups", new String[] { TOKEN_GROUP })); - when(roleConfig.getDsfRolesForEmail(LOCAL_PRACTITIONER_MAIL)).thenReturn(List.of(FhirServerRole.CREATE)); - when(roleConfig.getDsfRolesForTokenRole(TOKEN_ROLE1)).thenReturn(List.of(FhirServerRole.DELETE)); + when(roleConfig.getDsfRolesForEmail(LOCAL_PRACTITIONER_MAIL)) + .thenReturn(List.of(Operation.CREATE.toFhirServerRoleAllResources())); + when(roleConfig.getDsfRolesForTokenRole(TOKEN_ROLE1)) + .thenReturn(List.of(Operation.DELETE.toFhirServerRoleAllResources())); when(roleConfig.getDsfRolesForTokenRole(TOKEN_ROLE2_CLIENT + "." + TOKEN_ROLE2)) - .thenReturn(List.of(FhirServerRole.HISTORY)); - when(roleConfig.getDsfRolesForTokenGroup(TOKEN_GROUP)).thenReturn(List.of(FhirServerRole.PERMANENT_DELETE)); + .thenReturn(List.of(Operation.HISTORY.toFhirServerRoleAllResources())); + when(roleConfig.getDsfRolesForTokenGroup(TOKEN_GROUP)) + .thenReturn(List.of(Operation.PERMANENT_DELETE.toFhirServerRoleAllResources())); when(roleConfig.getPractitionerRolesForEmail(LOCAL_PRACTITIONER_MAIL)).thenReturn(List.of(PRACTIONER_ROLE1)); when(roleConfig.getPractitionerRolesForTokenRole(TOKEN_ROLE1)).thenReturn(List.of(PRACTIONER_ROLE2)); @@ -386,8 +394,10 @@ public void testGetPractitionerIdentityByOpenIdCredentials() throws Exception assertEquals(credentials, practitionerI.getCredentials().get()); assertEquals(LOCAL_PRACTITIONER_NAME_GIVEN + " " + LOCAL_PRACTITIONER_NAME_FAMILY, practitionerI.getDisplayName()); - assertEquals(EnumSet.of(FhirServerRole.CREATE, FhirServerRole.DELETE, FhirServerRole.HISTORY, - FhirServerRole.PERMANENT_DELETE), practitionerI.getDsfRoles()); + assertEquals(Set.of(new FhirServerRoleImpl(Operation.CREATE, List.of()), + new FhirServerRoleImpl(Operation.DELETE, List.of()), + new FhirServerRoleImpl(Operation.HISTORY, List.of()), + new FhirServerRoleImpl(Operation.PERMANENT_DELETE, List.of())), practitionerI.getDsfRoles()); assertEquals(LOCAL_ORGANIZATION_IDENTIFIER_VALUE + "/" + LOCAL_PRACTITIONER_MAIL, practitionerI.getName()); assertEquals(LOCAL_ORGANIZATION, practitionerI.getOrganization()); assertEquals(LOCAL_ORGANIZATION_IDENTIFIER_VALUE, practitionerI.getOrganizationIdentifierValue().get()); diff --git a/dsf-fhir/dsf-fhir-server/src/test/java/dev/dsf/fhir/dao/TestOrganizationIdentity.java b/dsf-fhir/dsf-fhir-server/src/test/java/dev/dsf/fhir/dao/TestOrganizationIdentity.java index 514241f89..ed1b7462e 100644 --- a/dsf-fhir/dsf-fhir-server/src/test/java/dev/dsf/fhir/dao/TestOrganizationIdentity.java +++ b/dsf-fhir/dsf-fhir-server/src/test/java/dev/dsf/fhir/dao/TestOrganizationIdentity.java @@ -6,7 +6,7 @@ import dev.dsf.common.auth.conf.DsfRole; import dev.dsf.common.auth.conf.OrganizationIdentityImpl; -import dev.dsf.fhir.authentication.FhirServerRole; +import dev.dsf.fhir.authentication.FhirServerRoleImpl; public class TestOrganizationIdentity extends OrganizationIdentityImpl { @@ -17,11 +17,11 @@ private TestOrganizationIdentity(boolean localIdentity, Organization organizatio public static TestOrganizationIdentity local(Organization organization) { - return new TestOrganizationIdentity(true, organization, FhirServerRole.LOCAL_ORGANIZATION); + return new TestOrganizationIdentity(true, organization, FhirServerRoleImpl.LOCAL_ORGANIZATION); } public static TestOrganizationIdentity remote(Organization organization) { - return new TestOrganizationIdentity(false, organization, FhirServerRole.REMOTE_ORGANIZATION); + return new TestOrganizationIdentity(false, organization, FhirServerRoleImpl.REMOTE_ORGANIZATION); } } diff --git a/dsf-fhir/dsf-fhir-server/src/test/java/dev/dsf/fhir/integration/AbstractIntegrationTest.java b/dsf-fhir/dsf-fhir-server/src/test/java/dev/dsf/fhir/integration/AbstractIntegrationTest.java index 105227e66..41eb98bb5 100644 --- a/dsf-fhir/dsf-fhir-server/src/test/java/dev/dsf/fhir/integration/AbstractIntegrationTest.java +++ b/dsf-fhir/dsf-fhir-server/src/test/java/dev/dsf/fhir/integration/AbstractIntegrationTest.java @@ -114,6 +114,7 @@ public abstract class AbstractIntegrationTest extends AbstractDbTest private static FhirWebserviceClient webserviceClient; private static FhirWebserviceClient externalWebserviceClient; private static FhirWebserviceClient practitionerWebserviceClient; + private static FhirWebserviceClient minimalWebserviceClient; @BeforeClass public static void beforeClass() throws Exception @@ -147,6 +148,12 @@ public static void beforeClass() throws Exception certificates.getPractitionerClientCertificate().keyStore(), certificates.getPractitionerClientCertificate().keyStorePassword(), fhirContext, referenceCleaner); + logger.info("Creating minimal client ..."); + minimalWebserviceClient = createWebserviceClient(apiConnectorChannel.socket().getLocalPort(), + certificates.getMinimalClientCertificate().trustStore(), + certificates.getMinimalClientCertificate().keyStore(), + certificates.getMinimalClientCertificate().keyStorePassword(), fhirContext, referenceCleaner); + logger.info("Starting FHIR Server ..."); fhirServer = startFhirServer(statusConnectorChannel, apiConnectorChannel, baseUrl); @@ -212,7 +219,18 @@ private static JettyServer startFhirServer(ServerSocketChannel statusConnectorCh - HISTORY practitioner-role: - http://dsf.dev/fhir/CodeSystem/practitioner-role|DIC_USER - """, certificates.getPractitionerClientCertificate().certificateSha512ThumbprintHex())); + - minimal-test-user: + thumbprint: %s + dsf-role: + - CREATE: [Task] + - READ: &tqqr [Task, Questionnaire, QuestionnaireResponse] + - UPDATE: [QuestionnaireResponse] + - SEARCH: *tqqr + - HISTORY: *tqqr + practitioner-role: + - http://dsf.dev/fhir/CodeSystem/practitioner-role|DIC_USER + """, certificates.getPractitionerClientCertificate().certificateSha512ThumbprintHex(), + certificates.getMinimalClientCertificate().certificateSha512ThumbprintHex())); initParameters.put("dev.dsf.fhir.debug.log.message.dbStatement", "true"); KeyStore clientCertificateTrustStore = KeyStoreCreator @@ -382,6 +400,11 @@ protected static FhirWebserviceClient getPractitionerWebserviceClient() return practitionerWebserviceClient; } + protected static FhirWebserviceClient getMinimalWebserviceClient() + { + return minimalWebserviceClient; + } + protected static WebsocketClient getWebsocketClient() { Bundle bundle = getWebserviceClient().searchWithStrictHandling(Subscription.class, diff --git a/dsf-fhir/dsf-fhir-server/src/test/java/dev/dsf/fhir/integration/QuestionnaireVsQuestionnaireResponseIntegrationTest.java b/dsf-fhir/dsf-fhir-server/src/test/java/dev/dsf/fhir/integration/QuestionnaireVsQuestionnaireResponseIntegrationTest.java index b1dc6d7bb..bd6a1bb81 100644 --- a/dsf-fhir/dsf-fhir-server/src/test/java/dev/dsf/fhir/integration/QuestionnaireVsQuestionnaireResponseIntegrationTest.java +++ b/dsf-fhir/dsf-fhir-server/src/test/java/dev/dsf/fhir/integration/QuestionnaireVsQuestionnaireResponseIntegrationTest.java @@ -199,4 +199,32 @@ public void testPostQuestionnaireResponseInTransactionBundleQuestionnaireDoesNot expectForbidden(() -> getWebserviceClient().postBundle(bundle)); } + + @Test + public void testQuestionnaireResponseQuestionnaireDisplayItemChangedWithMinimalUser() throws Exception + { + Questionnaire questionnaire = createQuestionnaireProfileVersion100("1.0.0"); + questionnaire.addItem().setLinkId("display-id").setType(Questionnaire.QuestionnaireItemType.DISPLAY) + .setText("Default Text Value"); + + QuestionnaireDao questionnaireDao = getSpringWebApplicationContext().getBean(QuestionnaireDao.class); + questionnaireDao.create(questionnaire); + + QuestionnaireResponse questionnaireResponse = createQuestionnaireResponse("1.0.0"); + questionnaireResponse.addItem().setLinkId("display-id").setText("Default Text Value"); + + expectForbidden(() -> getMinimalWebserviceClient().create(questionnaireResponse)); + + QuestionnaireResponse created = getWebserviceClient().create(questionnaireResponse); + + created.getItem().stream().filter(i -> "display-id".equals(i.getLinkId())).findFirst() + .ifPresent(i -> i.setText("Response Test Value")); + created.setStatus(QuestionnaireResponse.QuestionnaireResponseStatus.COMPLETED); + + QuestionnaireResponse updated = getMinimalWebserviceClient().update(created); + + assertNotNull(updated); + assertNotNull(updated.getIdElement().getIdPart()); + assertNotNull(updated.getIdElement().getVersionIdPart()); + } } \ No newline at end of file diff --git a/dsf-fhir/dsf-fhir-server/src/test/java/dev/dsf/fhir/integration/TaskIntegrationTest.java b/dsf-fhir/dsf-fhir-server/src/test/java/dev/dsf/fhir/integration/TaskIntegrationTest.java index f6f65650c..688dc827a 100755 --- a/dsf-fhir/dsf-fhir-server/src/test/java/dev/dsf/fhir/integration/TaskIntegrationTest.java +++ b/dsf-fhir/dsf-fhir-server/src/test/java/dev/dsf/fhir/integration/TaskIntegrationTest.java @@ -46,7 +46,6 @@ import dev.dsf.fhir.authentication.OrganizationProvider; import dev.dsf.fhir.dao.OrganizationDao; import dev.dsf.fhir.dao.TaskDao; -import dev.dsf.fhir.dao.TestOrganizationIdentity; import dev.dsf.fhir.dao.command.ReferencesHelperImpl; import dev.dsf.fhir.help.ResponseGenerator; import dev.dsf.fhir.service.ReferenceCleaner; @@ -696,6 +695,31 @@ public void testCreateTaskAllowedLocalUser() throws Exception assertNotNull(createdTask.getIdElement().getIdPart()); } + @Test + public void testCreateTaskAllowedMinimalUser() throws Exception + { + ActivityDefinition ad5 = readActivityDefinition("dsf-test-activity-definition5-1.0.xml"); + + expectForbidden(() -> getMinimalWebserviceClient().create(ad5)); + + ActivityDefinition createdAd1 = getWebserviceClient().create(ad5); + assertNotNull(createdAd1); + assertNotNull(createdAd1.getIdElement().getIdPart()); + + StructureDefinition testTaskProfile = readTestTaskProfile(); + + expectForbidden(() -> getMinimalWebserviceClient().create(testTaskProfile)); + + StructureDefinition createdTestTaskProfile = getWebserviceClient().create(testTaskProfile); + assertNotNull(createdTestTaskProfile); + assertNotNull(createdTestTaskProfile.getIdElement().getIdPart()); + + Task task = readTestTask("Test_Organization", "Test_Organization"); + Task createdTask = getMinimalWebserviceClient().create(task); + assertNotNull(createdTask); + assertNotNull(createdTask.getIdElement().getIdPart()); + } + @Test public void testCreateTaskAllowedLocalUserWithRole() throws Exception { @@ -1459,15 +1483,12 @@ private Bundle createBundle(TaskStatus createStatus, TaskStatus updateStatus, bo Task task = readTestTaskBinary("External_Test_Organization", "Test_Organization"); task.setStatus(createStatus); - OrganizationProvider organizationProvider = getSpringWebApplicationContext() - .getBean(OrganizationProvider.class); ReferenceExtractor referenceExtractor = getSpringWebApplicationContext().getBean(ReferenceExtractor.class); ReferenceResolver referenceResolver = getSpringWebApplicationContext().getBean(ReferenceResolver.class); ResponseGenerator responseGenerator = getSpringWebApplicationContext().getBean(ResponseGenerator.class); DataSource dataSource = getSpringWebApplicationContext().getBean("dataSource", DataSource.class); - ReferencesHelperImpl referencesHelper = new ReferencesHelperImpl<>(0, - TestOrganizationIdentity.local(organizationProvider.getLocalOrganization().get()), task, getBaseUrl(), + ReferencesHelperImpl referencesHelper = new ReferencesHelperImpl<>(0, task, getBaseUrl(), referenceExtractor, referenceResolver, responseGenerator); try (Connection connection = dataSource.getConnection()) { diff --git a/dsf-fhir/dsf-fhir-server/src/test/java/dev/dsf/fhir/integration/X509Certificates.java b/dsf-fhir/dsf-fhir-server/src/test/java/dev/dsf/fhir/integration/X509Certificates.java index 8e3f8cd18..65368db2b 100755 --- a/dsf-fhir/dsf-fhir-server/src/test/java/dev/dsf/fhir/integration/X509Certificates.java +++ b/dsf-fhir/dsf-fhir-server/src/test/java/dev/dsf/fhir/integration/X509Certificates.java @@ -72,6 +72,7 @@ public String certificateSha512ThumbprintHex() private CertificateAndPrivateKey serverCertificate; private CertificateAndPrivateKey clientCertificate; private CertificateAndPrivateKey practitionerClientCertificate; + private CertificateAndPrivateKey minimalClientCertificate; private CertificateAndPrivateKey externalClientCertificate; private Path caCertificateFile; @@ -81,6 +82,8 @@ public String certificateSha512ThumbprintHex() private Path externalClientCertificatePrivateKeyFile; private Path practitionerClientCertificateFile; private Path practitionerClientCertificatePrivateKeyFile; + private Path minimalClientCertificateFile; + private Path minimalClientCertificatePrivateKeyFile; private List filesToDelete; @@ -116,6 +119,11 @@ public CertificateAndPrivateKey getPractitionerClientCertificate() return practitionerClientCertificate; } + public CertificateAndPrivateKey getMinimalClientCertificate() + { + return minimalClientCertificate; + } + public X509Certificate getCaCertificate() { return caCertificate; @@ -156,6 +164,16 @@ public Path getPractitionerClientCertificatePrivateKeyFile() return practitionerClientCertificatePrivateKeyFile; } + public Path getMinimalClientCertificateFile() + { + return minimalClientCertificateFile; + } + + public Path getMinimalClientCertificatePrivateKeyFile() + { + return minimalClientCertificatePrivateKeyFile; + } + private void createX509Certificates() throws InvalidKeyException, NoSuchAlgorithmException, KeyStoreException, CertificateException, OperatorCreationException, IllegalStateException, IOException, InvalidKeySpecException { @@ -168,6 +186,8 @@ private void createX509Certificates() throws InvalidKeyException, NoSuchAlgorith Path externalClientCertificatePrivateKeyFile = Paths.get("target", UUID.randomUUID().toString() + ".pem"); Path practitionerClientCertificateFile = Paths.get("target", UUID.randomUUID().toString() + ".pem"); Path practitionerClientCertificatePrivateKeyFile = Paths.get("target", UUID.randomUUID().toString() + ".pem"); + Path minimalClientCertificateFile = Paths.get("target", UUID.randomUUID().toString() + ".pem"); + Path minimalClientCertificatePrivateKeyFile = Paths.get("target", UUID.randomUUID().toString() + ".pem"); CertificateAuthority ca = CertificateAuthority .builderSha384EcdsaSecp384r1("DE", null, null, null, null, "Junit Test CA") @@ -210,6 +230,15 @@ private void createX509Certificates() throws InvalidKeyException, NoSuchAlgorith .toFile(practitionerClientCertificatePrivateKeyFile); // practitioner client -- + // -- minimal client + CertificationRequestAndPrivateKey minimalClientRequest = CertificationRequest + .builder(ca, "DE", null, null, null, null, "minimal-client").generateKeyPair().build(); + X509Certificate minimalClientCertificate = ca.signClientCertificate(minimalClientRequest, Period.ofDays(1)); + PemWriter.writeCertificate(minimalClientCertificate, minimalClientCertificateFile); + PemWriter.writePrivateKey(minimalClientRequest.getPrivateKey()).asPkcs8().encryptedAes128(PASSWORD) + .toFile(minimalClientCertificatePrivateKeyFile); + // minimal client -- + this.caCertificate = caCertificate; this.serverCertificate = new CertificateAndPrivateKey(caCertificate, serverCertificate, serverRequest.getPrivateKey()); @@ -219,6 +248,8 @@ private void createX509Certificates() throws InvalidKeyException, NoSuchAlgorith externalClientRequest.getPrivateKey()); this.practitionerClientCertificate = new CertificateAndPrivateKey(caCertificate, practitionerClientCertificate, practitionerClientRequest.getPrivateKey()); + this.minimalClientCertificate = new CertificateAndPrivateKey(caCertificate, minimalClientCertificate, + minimalClientRequest.getPrivateKey()); this.caCertificateFile = caCertificateFile; this.clientCertificateFile = clientCertificateFile; @@ -227,10 +258,13 @@ private void createX509Certificates() throws InvalidKeyException, NoSuchAlgorith this.externalClientCertificatePrivateKeyFile = externalClientCertificatePrivateKeyFile; this.practitionerClientCertificateFile = practitionerClientCertificateFile; this.practitionerClientCertificatePrivateKeyFile = practitionerClientCertificatePrivateKeyFile; + this.minimalClientCertificateFile = minimalClientCertificateFile; + this.minimalClientCertificatePrivateKeyFile = minimalClientCertificatePrivateKeyFile; filesToDelete = List.of(caCertificateFile, clientCertificateFile, clientCertificatePrivateKeyFile, externalClientCertificateFile, externalClientCertificatePrivateKeyFile, - practitionerClientCertificateFile, practitionerClientCertificatePrivateKeyFile); + practitionerClientCertificateFile, practitionerClientCertificatePrivateKeyFile, + minimalClientCertificateFile, minimalClientCertificatePrivateKeyFile); } private void deleteX509Certificates() diff --git a/dsf-fhir/dsf-fhir-validation/src/main/java/dev/dsf/fhir/validation/ResourceValidatorImpl.java b/dsf-fhir/dsf-fhir-validation/src/main/java/dev/dsf/fhir/validation/ResourceValidatorImpl.java index 0049142a4..efed236fc 100755 --- a/dsf-fhir/dsf-fhir-validation/src/main/java/dev/dsf/fhir/validation/ResourceValidatorImpl.java +++ b/dsf-fhir/dsf-fhir-validation/src/main/java/dev/dsf/fhir/validation/ResourceValidatorImpl.java @@ -183,6 +183,7 @@ public ValidationResult validate(Resource resource) // TODO: remove after HAPI validator is fixed: https://github.com/hapifhir/org.hl7.fhir.core/issues/193 adaptDefaultSliceValidationErrorToWarning(result); + adaptQuestionnaireTextNotSameValidationErrorToWarning(result); return new ValidationResult(context, result.getMessages().stream().filter(m -> !(ResultSeverityEnum.WARNING.equals(m.getSeverity()) @@ -196,4 +197,12 @@ private void adaptDefaultSliceValidationErrorToWarning(ValidationResult result) && AT_DEFAULT_SLICE_PATTERN.matcher(m.getMessage()).matches()) .forEach(m -> m.setSeverity(ResultSeverityEnum.WARNING)); } + + private void adaptQuestionnaireTextNotSameValidationErrorToWarning(ValidationResult result) + { + result.getMessages().stream() + .filter(m -> ResultSeverityEnum.ERROR.equals(m.getSeverity()) && m.getMessage() + .startsWith("If text exists, it must match the questionnaire definition for linkId")) + .forEach(m -> m.setSeverity(ResultSeverityEnum.WARNING)); + } }