Make expunge globally disabled by default

This commit is contained in:
jamesagnew 2018-04-29 07:47:26 -04:00
parent 770246583d
commit 0af8fbc5d3
16 changed files with 244 additions and 99 deletions

View File

@ -225,6 +225,11 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> implements IDao {
}
protected ExpungeOutcome doExpunge(String theResourceName, Long theResourceId, Long theVersion, ExpungeOptions theExpungeOptions) {
if (!getConfig().isExpungeEnabled()) {
throw new MethodNotAllowedException("$expunge is not enabled on this server");
}
AtomicInteger remainingCount = new AtomicInteger(theExpungeOptions.getLimit());
if (theResourceName == null && theResourceId == null && theVersion == null) {
@ -295,75 +300,68 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> implements IDao {
return toExpungeOutcome(theExpungeOptions, remainingCount);
}
private void doExpungeEverythingQuery(String theQuery) {
StopWatch sw = new StopWatch();
int outcome = myEntityManager.createQuery(theQuery).executeUpdate();
ourLog.info("Query affected {} rows in {}: {}", outcome, sw.toString(), theQuery);
}
private void doExpungeEverything() {
ourLog.info("** BEGINNING GLOBAL OPERATION_NAME_EXPUNGE **");
ourLog.info("** BEGINNING GLOBAL $expunge **");
TransactionTemplate txTemplate = new TransactionTemplate(myPlatformTransactionManager);
txTemplate.setPropagationBehavior(TransactionTemplate.PROPAGATION_REQUIRED);
txTemplate.execute(new TransactionCallback<Void>() {
@Override
public Void doInTransaction(TransactionStatus theStatus) {
myEntityManager.createQuery("UPDATE " + ResourceHistoryTable.class.getSimpleName() + " d SET d.myForcedId = null").executeUpdate();
myEntityManager.createQuery("UPDATE " + ResourceTable.class.getSimpleName() + " d SET d.myForcedId = null").executeUpdate();
myEntityManager.createQuery("UPDATE " + TermCodeSystem.class.getSimpleName() + " d SET d.myCurrentVersion = null").executeUpdate();
return null;
}
txTemplate.execute(t -> {
doExpungeEverythingQuery("UPDATE " + ResourceHistoryTable.class.getSimpleName() + " d SET d.myForcedId = null");
doExpungeEverythingQuery("UPDATE " + ResourceTable.class.getSimpleName() + " d SET d.myForcedId = null");
doExpungeEverythingQuery("UPDATE " + TermCodeSystem.class.getSimpleName() + " d SET d.myCurrentVersion = null");
return null;
});
txTemplate.execute(new TransactionCallback<Void>() {
@Override
public Void doInTransaction(TransactionStatus theStatus) {
myEntityManager.createQuery("DELETE from " + SearchParamPresent.class.getSimpleName() + " d").executeUpdate();
myEntityManager.createQuery("DELETE from " + SearchParam.class.getSimpleName() + " d").executeUpdate();
myEntityManager.createQuery("DELETE from " + ForcedId.class.getSimpleName() + " d").executeUpdate();
myEntityManager.createQuery("DELETE from " + ResourceIndexedSearchParamDate.class.getSimpleName() + " d").executeUpdate();
myEntityManager.createQuery("DELETE from " + ResourceIndexedSearchParamNumber.class.getSimpleName() + " d").executeUpdate();
myEntityManager.createQuery("DELETE from " + ResourceIndexedSearchParamQuantity.class.getSimpleName() + " d").executeUpdate();
myEntityManager.createQuery("DELETE from " + ResourceIndexedSearchParamString.class.getSimpleName() + " d").executeUpdate();
myEntityManager.createQuery("DELETE from " + ResourceIndexedSearchParamToken.class.getSimpleName() + " d").executeUpdate();
myEntityManager.createQuery("DELETE from " + ResourceIndexedSearchParamUri.class.getSimpleName() + " d").executeUpdate();
myEntityManager.createQuery("DELETE from " + ResourceIndexedSearchParamCoords.class.getSimpleName() + " d").executeUpdate();
myEntityManager.createQuery("DELETE from " + ResourceIndexedCompositeStringUnique.class.getSimpleName() + " d").executeUpdate();
myEntityManager.createQuery("DELETE from " + ResourceLink.class.getSimpleName() + " d").executeUpdate();
myEntityManager.createQuery("DELETE from " + SearchResult.class.getSimpleName() + " d").executeUpdate();
myEntityManager.createQuery("DELETE from " + SearchInclude.class.getSimpleName() + " d").executeUpdate();
myEntityManager.createQuery("DELETE from " + TermConceptParentChildLink.class.getSimpleName() + " d").executeUpdate();
return null;
}
txTemplate.execute(t -> {
doExpungeEverythingQuery("DELETE from " + SearchParamPresent.class.getSimpleName() + " d");
doExpungeEverythingQuery("DELETE from " + SearchParam.class.getSimpleName() + " d");
doExpungeEverythingQuery("DELETE from " + ForcedId.class.getSimpleName() + " d");
doExpungeEverythingQuery("DELETE from " + ResourceIndexedSearchParamDate.class.getSimpleName() + " d");
doExpungeEverythingQuery("DELETE from " + ResourceIndexedSearchParamNumber.class.getSimpleName() + " d");
doExpungeEverythingQuery("DELETE from " + ResourceIndexedSearchParamQuantity.class.getSimpleName() + " d");
doExpungeEverythingQuery("DELETE from " + ResourceIndexedSearchParamString.class.getSimpleName() + " d");
doExpungeEverythingQuery("DELETE from " + ResourceIndexedSearchParamToken.class.getSimpleName() + " d");
doExpungeEverythingQuery("DELETE from " + ResourceIndexedSearchParamUri.class.getSimpleName() + " d");
doExpungeEverythingQuery("DELETE from " + ResourceIndexedSearchParamCoords.class.getSimpleName() + " d");
doExpungeEverythingQuery("DELETE from " + ResourceIndexedCompositeStringUnique.class.getSimpleName() + " d");
doExpungeEverythingQuery("DELETE from " + ResourceLink.class.getSimpleName() + " d");
doExpungeEverythingQuery("DELETE from " + SearchResult.class.getSimpleName() + " d");
doExpungeEverythingQuery("DELETE from " + SearchInclude.class.getSimpleName() + " d");
doExpungeEverythingQuery("DELETE from " + TermConceptParentChildLink.class.getSimpleName() + " d");
return null;
});
txTemplate.execute(new TransactionCallback<Void>() {
@Override
public Void doInTransaction(TransactionStatus theStatus) {
myEntityManager.createQuery("DELETE from " + TermConceptProperty.class.getSimpleName() + " d").executeUpdate();
myEntityManager.createQuery("DELETE from " + TermConceptDesignation.class.getSimpleName() + " d").executeUpdate();
myEntityManager.createQuery("DELETE from " + TermConcept.class.getSimpleName() + " d").executeUpdate();
for (TermCodeSystem next : myEntityManager.createQuery("SELECT c FROM " + TermCodeSystem.class.getName() + " c", TermCodeSystem.class).getResultList()) {
next.setCurrentVersion(null);
myEntityManager.merge(next);
}
return null;
txTemplate.execute(t -> {
doExpungeEverythingQuery("DELETE from " + TermConceptProperty.class.getSimpleName() + " d");
doExpungeEverythingQuery("DELETE from " + TermConceptDesignation.class.getSimpleName() + " d");
doExpungeEverythingQuery("DELETE from " + TermConcept.class.getSimpleName() + " d");
for (TermCodeSystem next : myEntityManager.createQuery("SELECT c FROM " + TermCodeSystem.class.getName() + " c", TermCodeSystem.class).getResultList()) {
next.setCurrentVersion(null);
myEntityManager.merge(next);
}
return null;
});
txTemplate.execute(new TransactionCallback<Void>() {
@Override
public Void doInTransaction(TransactionStatus theStatus) {
myEntityManager.createQuery("DELETE from " + TermCodeSystemVersion.class.getSimpleName() + " d").executeUpdate();
myEntityManager.createQuery("DELETE from " + TermCodeSystem.class.getSimpleName() + " d").executeUpdate();
return null;
}
txTemplate.execute(t -> {
doExpungeEverythingQuery("DELETE from " + TermCodeSystemVersion.class.getSimpleName() + " d");
doExpungeEverythingQuery("DELETE from " + TermCodeSystem.class.getSimpleName() + " d");
return null;
});
txTemplate.execute(new TransactionCallback<Void>() {
@Override
public Void doInTransaction(TransactionStatus theStatus) {
myEntityManager.createQuery("DELETE from " + SubscriptionTable.class.getSimpleName() + " d").executeUpdate();
myEntityManager.createQuery("DELETE from " + ResourceHistoryTag.class.getSimpleName() + " d").executeUpdate();
myEntityManager.createQuery("DELETE from " + ResourceTag.class.getSimpleName() + " d").executeUpdate();
myEntityManager.createQuery("DELETE from " + TagDefinition.class.getSimpleName() + " d").executeUpdate();
myEntityManager.createQuery("DELETE from " + ResourceHistoryTable.class.getSimpleName() + " d").executeUpdate();
myEntityManager.createQuery("DELETE from " + ResourceTable.class.getSimpleName() + " d").executeUpdate();
myEntityManager.createQuery("DELETE from " + org.hibernate.search.jpa.Search.class.getSimpleName() + " d").executeUpdate();
return null;
}
txTemplate.execute(t -> {
doExpungeEverythingQuery("DELETE from " + SubscriptionTable.class.getSimpleName() + " d");
doExpungeEverythingQuery("DELETE from " + ResourceHistoryTag.class.getSimpleName() + " d");
doExpungeEverythingQuery("DELETE from " + ResourceTag.class.getSimpleName() + " d");
doExpungeEverythingQuery("DELETE from " + TagDefinition.class.getSimpleName() + " d");
doExpungeEverythingQuery("DELETE from " + ResourceHistoryTable.class.getSimpleName() + " d");
doExpungeEverythingQuery("DELETE from " + ResourceTable.class.getSimpleName() + " d");
doExpungeEverythingQuery("DELETE from " + org.hibernate.search.jpa.Search.class.getSimpleName() + " d");
return null;
});
ourLog.info("** COMPLETED GLOBAL $expunge **");
}
private void expungeCurrentVersionOfResource(Long theResourceId) {

View File

@ -1,6 +1,7 @@
package ca.uhn.fhir.jpa.dao;
import ca.uhn.fhir.jpa.entity.ResourceEncodingEnum;
import ca.uhn.fhir.jpa.util.JpaConstants;
import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.Validate;
@ -115,6 +116,7 @@ public class DaoConfig {
private Integer myCountSearchResultsUpTo = null;
private IdStrategyEnum myResourceServerIdStrategy = IdStrategyEnum.SEQUENTIAL_NUMERIC;
private boolean myMarkResourcesForReindexingUponSearchParameterChange;
private boolean myExpungeEnabled;
/**
* Constructor
@ -405,8 +407,11 @@ public class DaoConfig {
/**
* This may be used to optionally register server interceptors directly against the DAOs.
*/
public void setInterceptors(List<IServerInterceptor> theInterceptors) {
myInterceptors = theInterceptors;
public void setInterceptors(IServerInterceptor... theInterceptor) {
setInterceptors(new ArrayList<IServerInterceptor>());
if (theInterceptor != null && theInterceptor.length != 0) {
getInterceptors().addAll(Arrays.asList(theInterceptor));
}
}
/**
@ -657,7 +662,7 @@ public class DaoConfig {
/**
* If enabled, the server will support the use of :contains searches,
* which are helpful but can have adverse effects on performance.
*
* <p>
* Default is <code>true</code>
*/
public boolean isAllowContainsSearches() {
@ -667,7 +672,7 @@ public class DaoConfig {
/**
* If enabled, the server will support the use of :contains searches,
* which are helpful but can have adverse effects on performance.
*
* <p>
* Default is <code>true</code>
*/
public void setAllowContainsSearches(boolean theAllowContainsSearches) {
@ -924,6 +929,36 @@ public class DaoConfig {
myDeleteStaleSearches = theDeleteStaleSearches;
}
/**
* If set to <code>true</code> (default is <code>false</code>), the $expunge operation
* will be enabled on this server. This operation is potentially dangerous since it allows
* a client to physically delete data in a way that can not be recovered (without resorting
* to backups).
* <p>
* It is recommended to not enable this setting without appropriate security
* in place on your server to prevent non-administrators from using this
* operation.
* </p>
*/
public boolean isExpungeEnabled() {
return myExpungeEnabled;
}
/**
* If set to <code>true</code> (default is <code>false</code>), the $expunge operation
* will be enabled on this server. This operation is potentially dangerous since it allows
* a client to physically delete data in a way that can not be recovered (without resorting
* to backups).
* <p>
* It is recommended to not enable this setting without appropriate security
* in place on your server to prevent non-administrators from using this
* operation.
* </p>
*/
public void setExpungeEnabled(boolean theExpungeEnabled) {
myExpungeEnabled = theExpungeEnabled;
}
/**
* Should contained IDs be indexed the same way that non-contained IDs are (default is
* <code>true</code>)
@ -1025,7 +1060,7 @@ public class DaoConfig {
/**
* If set to <code>true</code> (default is <code>true</code>), indexes will be
* created for search parameters marked as {@link ca.uhn.fhir.jpa.util.JpaConstants#EXT_SP_UNIQUE}.
* created for search parameters marked as {@link JpaConstants#EXT_SP_UNIQUE}.
* This is a HAPI FHIR specific extension which can be used to specify that no more than one
* resource can exist which matches a given criteria, using a database constraint to
* enforce this.
@ -1036,7 +1071,7 @@ public class DaoConfig {
/**
* If set to <code>true</code> (default is <code>true</code>), indexes will be
* created for search parameters marked as {@link ca.uhn.fhir.jpa.util.JpaConstants#EXT_SP_UNIQUE}.
* created for search parameters marked as {@link JpaConstants#EXT_SP_UNIQUE}.
* This is a HAPI FHIR specific extension which can be used to specify that no more than one
* resource can exist which matches a given criteria, using a database constraint to
* enforce this.
@ -1073,11 +1108,8 @@ public class DaoConfig {
/**
* This may be used to optionally register server interceptors directly against the DAOs.
*/
public void setInterceptors(IServerInterceptor... theInterceptor) {
setInterceptors(new ArrayList<IServerInterceptor>());
if (theInterceptor != null && theInterceptor.length != 0) {
getInterceptors().addAll(Arrays.asList(theInterceptor));
}
public void setInterceptors(List<IServerInterceptor> theInterceptors) {
myInterceptors = theInterceptors;
}
/**

View File

@ -245,11 +245,13 @@ public abstract class BaseJpaTest {
return bundleStr;
}
public static void purgeDatabase(IFhirSystemDao<?,?> theSystemDao, ISearchParamPresenceSvc theSearchParamPresenceSvc, ISearchCoordinatorSvc theSearchCoordinatorSvc, ISearchParamRegistry theSearchParamRegistry) {
public static void purgeDatabase(DaoConfig theDaoConfig, IFhirSystemDao<?,?> theSystemDao, ISearchParamPresenceSvc theSearchParamPresenceSvc, ISearchCoordinatorSvc theSearchCoordinatorSvc, ISearchParamRegistry theSearchParamRegistry) {
theSearchCoordinatorSvc.cancelAllActiveSearches();
boolean expungeEnabled = theDaoConfig.isExpungeEnabled();
theDaoConfig.setExpungeEnabled(true);
theSystemDao.expunge(new ExpungeOptions().setExpungeEverything(true));
theDaoConfig.setExpungeEnabled(expungeEnabled);
theSearchParamPresenceSvc.flushCachesForUnitTest();
theSearchParamRegistry.forceRefresh();

View File

@ -13,6 +13,7 @@ import ca.uhn.fhir.jpa.provider.JpaSystemProviderDstu2;
import ca.uhn.fhir.jpa.search.DatabaseBackedPagingProvider;
import ca.uhn.fhir.jpa.search.ISearchCoordinatorSvc;
import ca.uhn.fhir.jpa.sp.ISearchParamPresenceSvc;
import ca.uhn.fhir.jpa.util.SingleItemLoadingCache;
import ca.uhn.fhir.model.dstu2.composite.CodeableConceptDt;
import ca.uhn.fhir.model.dstu2.composite.CodingDt;
import ca.uhn.fhir.model.dstu2.composite.MetaDt;
@ -40,6 +41,7 @@ import org.springframework.transaction.support.TransactionTemplate;
import javax.persistence.EntityManager;
import java.io.IOException;
import java.io.InputStream;
import java.util.Map;
import static org.junit.Assert.*;
import static org.mockito.Mockito.mock;
@ -47,6 +49,9 @@ import static org.mockito.Mockito.mock;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = {TestDstu2Config.class})
public abstract class BaseJpaDstu2Test extends BaseJpaTest {
@Autowired
@Qualifier("myResourceCountsCache")
protected SingleItemLoadingCache<Map<String, Long>> myResourceCountsCache;
@Autowired
protected ISearchParamRegistry mySearchParamRegsitry;
@Autowired
@ -189,7 +194,7 @@ public abstract class BaseJpaDstu2Test extends BaseJpaTest {
@Before
@Transactional()
public void beforePurgeDatabase() {
purgeDatabase(mySystemDao, mySearchParamPresenceSvc, mySearchCoordinatorSvc, mySearchParamRegistry);
purgeDatabase(myDaoConfig, mySystemDao, mySearchParamPresenceSvc, mySearchCoordinatorSvc, mySearchParamRegistry);
}
@Before

View File

@ -265,7 +265,7 @@ public abstract class BaseJpaDstu3Test extends BaseJpaTest {
@Before
@Transactional()
public void beforePurgeDatabase() {
purgeDatabase(mySystemDao, mySearchParamPresenceSvc, mySearchCoordinatorSvc, mySearchParamRegsitry);
purgeDatabase(myDaoConfig, mySystemDao, mySearchParamPresenceSvc, mySearchCoordinatorSvc, mySearchParamRegsitry);
}
@Before

View File

@ -152,7 +152,7 @@ public class FhirResourceDaoDstu3SearchWithLuceneDisabledTest extends BaseJpaTes
@Before
@Transactional()
public void beforePurgeDatabase() {
purgeDatabase(mySystemDao, mySearchParamPresenceSvc, mySearchCoordinatorSvc, mySearchParamRegistry);
purgeDatabase(myDaoConfig, mySystemDao, mySearchParamPresenceSvc, mySearchCoordinatorSvc, mySearchParamRegistry);
}
@Before

View File

@ -13,6 +13,7 @@ import ca.uhn.fhir.jpa.search.ISearchCoordinatorSvc;
import ca.uhn.fhir.jpa.search.IStaleSearchDeletingSvc;
import ca.uhn.fhir.jpa.sp.ISearchParamPresenceSvc;
import ca.uhn.fhir.jpa.term.IHapiTerminologySvc;
import ca.uhn.fhir.jpa.util.SingleItemLoadingCache;
import ca.uhn.fhir.jpa.validation.JpaValidationSupportChainR4;
import ca.uhn.fhir.parser.IParser;
import ca.uhn.fhir.parser.StrictErrorHandler;
@ -56,6 +57,9 @@ public abstract class BaseJpaR4Test extends BaseJpaTest {
private static JpaValidationSupportChainR4 ourJpaValidationSupportChainR4;
private static IFhirResourceDaoValueSet<ValueSet, Coding, CodeableConcept> ourValueSetDao;
@Autowired
@Qualifier("myResourceCountsCache")
protected SingleItemLoadingCache<Map<String, Long>> myResourceCountsCache;
@Autowired
protected IResourceLinkDao myResourceLinkDao;
@Autowired
@ -273,7 +277,7 @@ public abstract class BaseJpaR4Test extends BaseJpaTest {
@Transactional()
public void beforePurgeDatabase() {
final EntityManager entityManager = this.myEntityManager;
purgeDatabase(mySystemDao, mySearchParamPresenceSvc, mySearchCoordinatorSvc, mySearchParamRegsitry);
purgeDatabase(myDaoConfig, mySystemDao, mySearchParamPresenceSvc, mySearchCoordinatorSvc, mySearchParamRegsitry);
}
@Before

View File

@ -93,7 +93,7 @@ public class FhirResourceDaoR4SearchWithLuceneDisabledTest extends BaseJpaTest {
@Before
@Transactional()
public void beforePurgeDatabase() {
purgeDatabase(mySystemDao, mySearchParamPresenceSvc, mySearchCoordinatorSvc, mySearchParamRegistry);
purgeDatabase(myDaoConfig, mySystemDao, mySearchParamPresenceSvc, mySearchCoordinatorSvc, mySearchParamRegistry);
}
@Before

View File

@ -1318,6 +1318,9 @@ public class ResourceProviderDstu2Test extends BaseResourceProviderDstu2Test {
pt.addName().addFamily(methodName);
ourClient.create().resource(pt).execute().getId().toUnqualifiedVersionless();
myResourceCountsCache.clear();
myResourceCountsCache.update();
HttpGet get = new HttpGet(ourServerBase + "/$get-resource-counts");
CloseableHttpResponse response = ourHttpClient.execute(get);
try {

View File

@ -1,5 +1,6 @@
package ca.uhn.fhir.jpa.provider;
import ca.uhn.fhir.jpa.dao.DaoConfig;
import ca.uhn.fhir.jpa.dao.IFhirResourceDao;
import ca.uhn.fhir.jpa.util.ExpungeOptions;
import ca.uhn.fhir.model.dstu2.resource.Observation;
@ -10,14 +11,14 @@ import ca.uhn.fhir.rest.server.exceptions.ResourceGoneException;
import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException;
import ca.uhn.fhir.util.TestUtil;
import org.hl7.fhir.instance.model.api.IIdType;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.Test;
import static org.junit.Assert.*;
public class ExpungeProviderDstu2Test extends BaseResourceProviderDstu2Test {
public class ResourceProviderExpungeDstu2Test extends BaseResourceProviderDstu2Test {
private IIdType myOneVersionPatientId;
private IIdType myTwoVersionPatientId;
private IIdType myDeletedPatientId;
@ -25,6 +26,11 @@ public class ExpungeProviderDstu2Test extends BaseResourceProviderDstu2Test {
private IIdType myTwoVersionObservationId;
private IIdType myDeletedObservationId;
@After
public void afterDisableExpunge() {
myDaoConfig.setExpungeEnabled(new DaoConfig().isExpungeEnabled());
}
private void assertExpunged(IIdType theId) {
try {
getDao(theId).read(theId);
@ -97,6 +103,11 @@ public class ExpungeProviderDstu2Test extends BaseResourceProviderDstu2Test {
}
@Before
public void beforeEnableExpunge() {
myDaoConfig.setExpungeEnabled(true);
}
private IFhirResourceDao<?> getDao(IIdType theId) {
IFhirResourceDao<?> dao;
switch (theId.getResourceType()) {

View File

@ -1632,6 +1632,7 @@ public class ResourceProviderDstu3Test extends BaseResourceProviderDstu3Test {
pt.addName().setFamily(methodName);
ourClient.create().resource(pt).execute().getId().toUnqualifiedVersionless();
myResourceCountsCache.clear();
myResourceCountsCache.update();
HttpGet get = new HttpGet(ourServerBase + "/$get-resource-counts");

View File

@ -1,22 +1,27 @@
package ca.uhn.fhir.jpa.provider.dstu3;
import ca.uhn.fhir.jpa.dao.DaoConfig;
import ca.uhn.fhir.jpa.dao.IFhirResourceDao;
import ca.uhn.fhir.jpa.util.ExpungeOptions;
import ca.uhn.fhir.jpa.util.JpaConstants;
import ca.uhn.fhir.rest.server.exceptions.PreconditionFailedException;
import ca.uhn.fhir.rest.server.exceptions.ResourceGoneException;
import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException;
import ca.uhn.fhir.util.TestUtil;
import org.hl7.fhir.dstu3.model.Observation;
import org.hl7.fhir.dstu3.model.Patient;
import org.hl7.fhir.dstu3.model.*;
import org.hl7.fhir.instance.model.api.IIdType;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import static org.junit.Assert.*;
public class ExpungeProviderDstu3Test extends BaseResourceProviderDstu3Test {
public class ResourceProviderExpungeDstu3Test extends BaseResourceProviderDstu3Test {
private static final Logger ourLog = LoggerFactory.getLogger(ResourceProviderExpungeDstu3Test.class);
private IIdType myOneVersionPatientId;
private IIdType myTwoVersionPatientId;
private IIdType myDeletedPatientId;
@ -24,6 +29,11 @@ public class ExpungeProviderDstu3Test extends BaseResourceProviderDstu3Test {
private IIdType myTwoVersionObservationId;
private IIdType myDeletedObservationId;
@After
public void afterDisableExpunge() {
myDaoConfig.setExpungeEnabled(new DaoConfig().isExpungeEnabled());
}
private void assertExpunged(IIdType theId) {
try {
getDao(theId).read(theId);
@ -96,6 +106,11 @@ public class ExpungeProviderDstu3Test extends BaseResourceProviderDstu3Test {
}
@Before
public void beforeEnableExpunge() {
myDaoConfig.setExpungeEnabled(true);
}
private IFhirResourceDao<?> getDao(IIdType theId) {
IFhirResourceDao<?> dao;
switch (theId.getResourceType()) {
@ -275,6 +290,21 @@ public class ExpungeProviderDstu3Test extends BaseResourceProviderDstu3Test {
assertGone(myDeletedObservationId);
}
@Test
public void testParameters() {
Parameters p = new Parameters();
p.addParameter()
.setName(JpaConstants.OPERATION_EXPUNGE_OUT_PARAM_EXPUNGE_COUNT)
.setValue(new IntegerType(1000));
p.addParameter()
.setName(JpaConstants.OPERATION_EXPUNGE_PARAM_EXPUNGE_PREVIOUS_VERSIONS)
.setValue(new BooleanType(true));
p.addParameter()
.setName(JpaConstants.OPERATION_EXPUNGE_PARAM_EXPUNGE_DELETED_RESOURCES)
.setValue(new BooleanType(true));
ourLog.info(myFhirCtx.newJsonParser().encodeResourceToString(p));
}
@AfterClass
public static void afterClassClearContext() {
TestUtil.clearAllStaticFieldsForUnitTest();

View File

@ -1,5 +1,6 @@
package ca.uhn.fhir.jpa.provider.r4;
import ca.uhn.fhir.jpa.dao.DaoConfig;
import ca.uhn.fhir.jpa.dao.IFhirResourceDao;
import ca.uhn.fhir.jpa.util.ExpungeOptions;
import ca.uhn.fhir.rest.server.exceptions.PreconditionFailedException;
@ -9,6 +10,7 @@ import ca.uhn.fhir.util.TestUtil;
import org.hl7.fhir.instance.model.api.IIdType;
import org.hl7.fhir.r4.model.Observation;
import org.hl7.fhir.r4.model.Patient;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.Test;
@ -24,6 +26,16 @@ public class ExpungeR4Test extends BaseResourceProviderR4Test {
private IIdType myTwoVersionObservationId;
private IIdType myDeletedObservationId;
@After
public void afterDisableExpunge() {
myDaoConfig.setExpungeEnabled(new DaoConfig().isExpungeEnabled());
}
@Before
public void beforeEnableExpunge() {
myDaoConfig.setExpungeEnabled(true);
}
private void assertExpunged(IIdType theId) {
try {
getDao(theId).read(theId);

View File

@ -1,12 +1,15 @@
package ca.uhn.fhir.jpa.provider.r4;
import ca.uhn.fhir.jpa.dao.DaoConfig;
import ca.uhn.fhir.jpa.dao.IFhirResourceDao;
import ca.uhn.fhir.jpa.util.JpaConstants;
import ca.uhn.fhir.rest.server.exceptions.MethodNotAllowedException;
import ca.uhn.fhir.rest.server.exceptions.ResourceGoneException;
import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException;
import ca.uhn.fhir.util.TestUtil;
import org.hl7.fhir.instance.model.api.IIdType;
import org.hl7.fhir.r4.model.*;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.Test;
@ -23,6 +26,11 @@ public class ResourceProviderExpungeR4Test extends BaseResourceProviderR4Test {
private IIdType myTwoVersionObservationId;
private IIdType myDeletedObservationId;
@After
public void afterDisableExpunge() {
myDaoConfig.setExpungeEnabled(new DaoConfig().isExpungeEnabled());
}
private void assertExpunged(IIdType theId) {
try {
getDao(theId).read(theId);
@ -95,6 +103,11 @@ public class ResourceProviderExpungeR4Test extends BaseResourceProviderR4Test {
}
@Before
public void beforeEnableExpunge() {
myDaoConfig.setExpungeEnabled(true);
}
private IFhirResourceDao<?> getDao(IIdType theId) {
IFhirResourceDao<?> dao;
switch (theId.getResourceType()) {
@ -150,6 +163,46 @@ public class ResourceProviderExpungeR4Test extends BaseResourceProviderR4Test {
}
@Test
public void testExpungeDisabled() {
myDaoConfig.setExpungeEnabled(new DaoConfig().isExpungeEnabled());
Parameters input = new Parameters();
input.addParameter()
.setName(JpaConstants.OPERATION_EXPUNGE_PARAM_LIMIT)
.setValue(new IntegerType(1000));
input.addParameter()
.setName(JpaConstants.OPERATION_EXPUNGE_PARAM_EXPUNGE_DELETED_RESOURCES)
.setValue(new BooleanType(true));
input.addParameter()
.setName(JpaConstants.OPERATION_EXPUNGE_PARAM_EXPUNGE_PREVIOUS_VERSIONS)
.setValue(new BooleanType(true));
try {
myClient
.operation()
.onInstance(myTwoVersionPatientId)
.named("expunge")
.withParameters(input)
.execute();
fail();
} catch (MethodNotAllowedException e){
assertEquals("HTTP 405 Method Not Allowed: $expunge is not enabled on this server", e.getMessage());
}
// Only deleted and prior patients
assertStillThere(myOneVersionPatientId);
assertStillThere(myTwoVersionPatientId.withVersion("1"));
assertStillThere(myTwoVersionPatientId.withVersion("2"));
assertGone(myDeletedPatientId);
// No observations deleted
assertStillThere(myOneVersionObservationId);
assertStillThere(myTwoVersionObservationId.withVersion("1"));
assertStillThere(myTwoVersionObservationId.withVersion("2"));
assertGone(myDeletedObservationId);
}
@Test
public void testExpungeSystemEverything() {
Parameters input = new Parameters();

View File

@ -1690,6 +1690,9 @@ public class ResourceProviderR4Test extends BaseResourceProviderR4Test {
pt.addName().setFamily(methodName);
myClient.create().resource(pt).execute().getId().toUnqualifiedVersionless();
myResourceCountsCache.clear();
myResourceCountsCache.update();
HttpGet get = new HttpGet(ourServerBase + "/$get-resource-counts");
CloseableHttpResponse response = ourHttpClient.execute(get);
try {

View File

@ -1,23 +1,6 @@
package ca.uhn.fhir.jpa.subscription;
import static org.junit.Assert.assertEquals;
import java.util.List;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHolder;
import org.hl7.fhir.instance.model.api.IBaseResource;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Assert;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import com.google.common.collect.Lists;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.jpa.dao.DaoConfig;
import ca.uhn.fhir.jpa.provider.BaseResourceProviderDstu2Test;
@ -37,6 +20,14 @@ import ca.uhn.fhir.rest.api.MethodOutcome;
import ca.uhn.fhir.rest.server.IResourceProvider;
import ca.uhn.fhir.rest.server.RestfulServer;
import ca.uhn.fhir.util.PortUtil;
import com.google.common.collect.Lists;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHolder;
import org.hl7.fhir.instance.model.api.IBaseResource;
import org.junit.*;
import java.util.List;
/**
* Test the rest-hook subscriptions