Skip to content

Commit

Permalink
small balp refactorings
Browse files Browse the repository at this point in the history
  • Loading branch information
Boris Stanojevic committed Feb 1, 2024
1 parent d55c786 commit 8842e81
Show file tree
Hide file tree
Showing 9 changed files with 321 additions and 64 deletions.
Original file line number Diff line number Diff line change
@@ -1,7 +1,20 @@
/*
* Copyright 2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.openehealth.ipf.commons.audit;

import ca.uhn.fhir.context.FhirContext;

/**
* @author Boris Stanojevic
* @since 4.8
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,18 @@
/*
* Copyright 2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.openehealth.ipf.commons.audit;

import lombok.Getter;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,25 @@
/*
* Copyright 2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.openehealth.ipf.commons.audit;

import lombok.Getter;
import lombok.Setter;

public class DefaultBalpAuditContext extends DefaultAuditContext implements BalpAuditContext {

static final AuditContext NO_AUDIT = new DefaultBalpAuditContext();

@Getter
@Setter
private String auditRepositoryContextPath;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,4 @@ public class Constants {
public static final String AUDIT_LIFECYCLE_SYSTEM_NAME = "http://terminology.hl7.org/CodeSystem/dicom-audit-lifecycle";
public static final String OUSER_AGENT_TYPE_SYSTEM_NAME = " http://terminology.hl7.org/CodeSystem/v3-ParticipationType";
public static final String OUSER_AGENT_TYPE_CODE = "IRCP";
public static final String OUSER_AGENT_ISSUER_SYSTEM_NAME = " http://terminology.hl7.org/CodeSystem/v3-ParticipationType";

}
Original file line number Diff line number Diff line change
@@ -1,3 +1,18 @@
/*
* Copyright 2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.openehealth.ipf.commons.ihe.fhir.audit.events;

import org.openehealth.ipf.commons.audit.AuditContext;
Expand All @@ -15,7 +30,6 @@

import static org.apache.commons.lang3.StringUtils.isNotBlank;
import static org.openehealth.ipf.commons.ihe.fhir.audit.codes.Constants.DCM_SYSTEM_NAME;
import static org.openehealth.ipf.commons.ihe.fhir.audit.codes.Constants.OUSER_AGENT_ISSUER_SYSTEM_NAME;
import static org.openehealth.ipf.commons.ihe.fhir.audit.codes.Constants.OUSER_AGENT_TYPE_SYSTEM_NAME;

public class BalpJwtUtils {
Expand All @@ -37,9 +51,7 @@ public static <D extends BaseAuditMessageBuilder<D>> void addJwtParticipant(D de
OUSER_AGENT_TYPE_SYSTEM_NAME, "")));
ap.setUserName(dataSet.getIheIuaSubjectName());
if (isNotBlank(dataSet.getIssuer())) {
ap.getRoleIDCodes().add(
ActiveParticipantRoleId.of(CodedValueType.of(dataSet.getIssuer(),
OUSER_AGENT_ISSUER_SYSTEM_NAME, "")));
ap.setAlternativeUserID(dataSet.getIssuer());
}
delegate.addActiveParticipant(ap);
if (isNotBlank(dataSet.getClientId())) {
Expand All @@ -59,4 +71,4 @@ public static <D extends BaseAuditMessageBuilder<D>> void addJwtParticipant(D de
});
}

}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
/*
* Copyright 2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.openehealth.ipf.commons.ihe.fhir.audit.server;

import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.rest.annotation.Create;
import ca.uhn.fhir.rest.annotation.Delete;
import ca.uhn.fhir.rest.annotation.IdParam;
import ca.uhn.fhir.rest.annotation.OptionalParam;
import ca.uhn.fhir.rest.annotation.Read;
import ca.uhn.fhir.rest.annotation.ResourceParam;
import ca.uhn.fhir.rest.annotation.Search;
import ca.uhn.fhir.rest.api.MethodOutcome;
import ca.uhn.fhir.rest.param.TokenParam;
import ca.uhn.fhir.rest.server.IResourceProvider;
import ca.uhn.fhir.rest.server.RestfulServer;
import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException;
import org.hl7.fhir.dstu3.model.Organization;
import org.hl7.fhir.instance.model.api.IBaseResource;
import org.hl7.fhir.r4.model.AuditEvent;
import org.hl7.fhir.r4.model.IdType;
import org.hl7.fhir.r4.model.ResourceType;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import static org.apache.commons.lang3.StringUtils.isBlank;
import static org.apache.commons.lang3.StringUtils.isNotBlank;

public class FhirAuditServer extends RestfulServer implements IResourceProvider {

private final Map<String, AuditEvent> auditEvents = Collections.synchronizedMap(new HashMap<>());

public FhirAuditServer() {
setFhirContext(FhirContext.forR4());
setResourceProviders(this);
}

public List<AuditEvent> getAuditEvents() {
return new ArrayList<>(auditEvents.values());
}

@Read()
public AuditEvent read(@IdParam IdType theId) {
AuditEvent auditEvent = auditEvents.get(theId.getIdPart());
if (auditEvent == null) {
throw new ResourceNotFoundException(theId);
}
return auditEvent;
}

@Delete()
public MethodOutcome delete(@IdParam IdType theId) {
AuditEvent auditEvent = auditEvents.remove(theId.getIdPart());
if (auditEvent == null) {
throw new ResourceNotFoundException(theId);
}
return new MethodOutcome(theId);
}

@Create()
public MethodOutcome create(@ResourceParam AuditEvent auditEvent) {
String id = UUID.randomUUID().toString();
IdType idType = new IdType(ResourceType.AuditEvent.name(), id);
auditEvent.setId(idType);
auditEvents.put(id, auditEvent);
return new MethodOutcome(idType, true);
}

@Search
public List<AuditEvent> list(@OptionalParam(name= AuditEvent.SP_TYPE) TokenParam type,
@OptionalParam(name= AuditEvent.SP_SUBTYPE) TokenParam subtype) {
Stream<AuditEvent> allAuditEvents = getAuditEvents().stream();
if (type != null) {
if (isNotBlank(type.getSystem()) && isNotBlank(type.getValue())) {
allAuditEvents = allAuditEvents.filter(auditEvent ->
auditEvent.getType().hasSystem() && auditEvent.getType().getSystem().equals(type.getSystem()) &&
auditEvent.getType().hasCode() && auditEvent.getType().getCode().equals(type.getValue()));
} else if (isNotBlank(type.getSystem()) && isBlank(type.getValue())){
allAuditEvents = allAuditEvents.filter(auditEvent ->
auditEvent.getType().hasSystem() && auditEvent.getType().getSystem().equals(type.getSystem()));
} else if (isBlank(type.getSystem()) && isNotBlank(type.getValue())){
allAuditEvents = allAuditEvents.filter(auditEvent ->
auditEvent.getType().hasCode() && auditEvent.getType().getCode().equals(type.getValue()));
}
}
if (subtype != null) {
if (isNotBlank(subtype.getSystem()) && isNotBlank(subtype.getValue())) {
allAuditEvents = allAuditEvents.filter(auditEvent ->
auditEvent.getSubtypeFirstRep().hasSystem() && auditEvent.getSubtypeFirstRep().getSystem().equals(subtype.getSystem()) &&
auditEvent.getSubtypeFirstRep().hasCode() && auditEvent.getSubtypeFirstRep().getCode().equals(subtype.getValue()));
} else if (isNotBlank(subtype.getSystem()) && isBlank(subtype.getValue())){
allAuditEvents = allAuditEvents.filter(auditEvent ->
auditEvent.getSubtypeFirstRep().hasSystem() && auditEvent.getSubtypeFirstRep().getSystem().equals(subtype.getSystem()));
} else if (isBlank(subtype.getSystem()) && isNotBlank(subtype.getValue())){
allAuditEvents = allAuditEvents.filter(auditEvent ->
auditEvent.getSubtypeFirstRep().hasCode() && auditEvent.getSubtypeFirstRep().getCode().equals(subtype.getValue()));
}
}
return allAuditEvents.collect(Collectors.toList());
}

@Override
public Class<? extends IBaseResource> getResourceType() {
return AuditEvent.class;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
/*
* Copyright 2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.openehealth.ipf.commons.ihe.fhir.audit.server;

import io.undertow.Handlers;
import io.undertow.Undertow;
import io.undertow.UndertowOptions;
import io.undertow.server.HttpHandler;
import io.undertow.server.handlers.PathHandler;
import io.undertow.servlet.api.DeploymentInfo;
import io.undertow.servlet.api.DeploymentManager;
import io.undertow.servlet.api.InstanceFactory;
import io.undertow.servlet.api.InstanceHandle;
import org.openehealth.ipf.commons.audit.TlsParameters;
import org.openehealth.ipf.commons.ihe.fhir.extension.FhirAuditRepository;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.ServletException;

import java.io.Closeable;
import java.io.IOException;

import static io.undertow.servlet.Servlets.defaultContainer;
import static io.undertow.servlet.Servlets.deployment;
import static io.undertow.servlet.Servlets.servlet;

public class TLSBalpRepository implements Closeable {

private static final Logger LOG = LoggerFactory.getLogger(TLSBalpRepository.class);
protected final TlsParameters tlsParameters;
private Undertow server;
private final int httpsPort;

public TLSBalpRepository(TlsParameters tlsParameters, int httpsPort) {
this.tlsParameters = tlsParameters;
this.httpsPort = httpsPort;
}

public TLSBalpRepository(int httpsPort) {
this.tlsParameters = TlsParameters.getDefault();
this.httpsPort = httpsPort;
}

@Override
public void close() throws IOException {
stop();
}

public void stop() {
if (server != null) server.stop();
LOG.info("successfully stopped FHIR Audit Server");
}

public Undertow start() throws ServletException {
DeploymentInfo servletBuilder = deployment()
.setClassLoader(FhirAuditRepository.class.getClassLoader())
.setContextPath("/fhir")
.setDeploymentName("FHIR-Deployment")
.addServlets(
servlet("FhirAuditServer", FhirAuditServer.class, new FhirServletInitiator(new FhirAuditServer()))
.addMapping("/*"));

DeploymentManager manager = defaultContainer().addDeployment(servletBuilder);
manager.deploy();

HttpHandler servletHandler = manager.start();
PathHandler path = Handlers
.path(Handlers.redirect("/"))
.addPrefixPath("/", servletHandler);
server = Undertow.builder()
.setServerOption(UndertowOptions.ENABLE_HTTP2, true)
.addHttpsListener(
httpsPort,"localhost", tlsParameters.getSSLContext(true))
.setHandler(path)
.build();
server.start();
LOG.info("successfully started FHIR Audit Server on port {}", httpsPort);
return server;
}
static class FhirServletInitiator implements InstanceFactory<FhirAuditServer> {

private final FhirAuditServer fhirAuditServer;

public FhirServletInitiator(FhirAuditServer fhirAuditServer) {
this.fhirAuditServer = fhirAuditServer;
}

@Override
public InstanceHandle<FhirAuditServer> createInstance() throws InstantiationException {
return new InstanceHandle<>() {
@Override
public FhirAuditServer getInstance() {
return fhirAuditServer;
}

@Override
public void release() {

}
};
}
}

}
Loading

0 comments on commit 8842e81

Please sign in to comment.