public void GivenANodesByNameRule_WhenProcess_AllNodesShouldBeProcessed()
        {
            AnonymizationFhirPathRule[] rules = new AnonymizationFhirPathRule[]
            {
                new AnonymizationFhirPathRule("nodesByName('city')", "nodesByName('city')", "", "redact", AnonymizerRuleType.FhirPathRule, "nodesByName('city')"),
            };

            AnonymizationVisitor visitor = new AnonymizationVisitor(rules, CreateTestProcessors());

            var patient      = CreateTestPatient();
            var organization = CreateTestOrganization();
            var person       = CreateTestPerson();

            patient.Contained.Add(organization);
            organization.Contained.Add(person);

            var patientNode = ElementNode.FromElement(patient.ToTypedElement());

            patientNode.Accept(visitor);
            patientNode.RemoveEmptyNodes();

            var personCity          = patientNode.Select("Patient.contained[0].contained[0].address[0].city").FirstOrDefault();
            var personCountry       = patientNode.Select("Patient.contained[0].contained[0].address[0].country").First().Value.ToString();
            var organizationCity    = patientNode.Select("Patient.contained[0].address[0].city").FirstOrDefault();
            var organizationCountry = patientNode.Select("Patient.contained[0].address[0].country").First().Value.ToString();
            var patientCity         = patientNode.Select("Patient.address[0].city").FirstOrDefault();
            var patientCountry      = patientNode.Select("Patient.address[0].country").First().Value.ToString();

            Assert.Null(personCity);
            Assert.Null(organizationCity);
            Assert.Null(patientCity);
            Assert.Equal("persontestcountry", personCountry);
            Assert.Equal("OrgTestCountry", organizationCountry);
            Assert.Equal("patienttestcountry1", patientCountry);
        }
        public void GivenABundleWith2RuleOfDifferentMethods_WhenProcess_SecurityTagShouldBeAddedCorrectly()
        {
            AnonymizationFhirPathRule[] rules = new AnonymizationFhirPathRule[]
            {
                new AnonymizationFhirPathRule("Patient.nodesByType('date')", "nodesByType('date')", "", "dateshift", AnonymizerRuleType.FhirPathRule, "Patient.nodesByType('date')"),
                new AnonymizationFhirPathRule("Person.nodesByType('Address')", "nodesByType('Address')", "Person", "redact", AnonymizerRuleType.FhirPathRule, "Person.nodesByType('Address')"),
            };

            var person  = CreateTestPerson();
            var patient = CreateTestPatient();
            var bundle  = new Bundle();

            bundle.AddResourceEntry(person, "http://example.org/fhir/Person/1");
            bundle.AddResourceEntry(patient, "http://example.org/fhir/Patient/1");

            var bundleNode = ElementNode.FromElement(bundle.ToTypedElement());
            AnonymizationVisitor visitor = new AnonymizationVisitor(rules, CreateTestProcessors());

            bundleNode.Accept(visitor);
            bundleNode.RemoveEmptyNodes();

            bundle = bundleNode.ToPoco <Bundle>();
            Assert.Equal(2, bundle.Meta.Security.Count);
            Assert.Contains(SecurityLabels.REDACT.Code, bundle.Meta.Security.Select(s => s.Code));
            Assert.Contains(SecurityLabels.PERTURBED.Code, bundle.Meta.Security.Select(s => s.Code));

            Resource resource = bundle.Entry[0].Resource;

            Assert.Single(resource.Meta.Security);
            Assert.Contains(SecurityLabels.REDACT.Code, resource.Meta.Security.Select(s => s.Code));

            resource = bundle.Entry[1].Resource;
            Assert.Single(resource.Meta.Security);
            Assert.Contains(SecurityLabels.PERTURBED.Code, resource.Meta.Security.Select(s => s.Code));
        }
        public void GivenANodesByTypeRule_WhenProcess_AllNodesShouldBeProcessed()
        {
            AnonymizationFhirPathRule[] rules = new AnonymizationFhirPathRule[]
            {
                new AnonymizationFhirPathRule("nodesByType('Address')", "nodesByType('Address')", "", "redact", AnonymizerRuleType.FhirPathRule, "nodesByType('Address')"),
            };

            AnonymizationVisitor visitor = new AnonymizationVisitor(rules, CreateTestProcessors());

            var patient = CreateTestPatient();
            var org     = CreateTestOrganization();
            var person  = CreateTestPerson();

            patient.Contained.Add(org);
            org.Contained.Add(person);

            var patientNode = ElementNode.FromElement(patient.ToTypedElement());

            patientNode.Accept(visitor);
            patientNode.RemoveEmptyNodes();

            var personAddress  = patientNode.Select("Patient.contained[0].contained[0].address[0]").FirstOrDefault();
            var patientAddress = patientNode.Select("Patient.address[0]").FirstOrDefault();

            Assert.Null(personAddress);
            Assert.Null(patientAddress);
        }
        public void GivenAnEncryptRule_WhenProcess_NodeShouldBeEncrypted()
        {
            AnonymizationFhirPathRule[] rules = new AnonymizationFhirPathRule[]
            {
                new AnonymizationFhirPathRule("Patient.address", "address", "Patient", "encrypt", AnonymizerRuleType.FhirPathRule, "Patient.address"),
            };

            AnonymizationVisitor visitor = new AnonymizationVisitor(rules, CreateTestProcessors());

            var patient     = CreateTestPatient();
            var patientNode = ElementNode.FromElement(patient.ToTypedElement());

            patientNode.Accept(visitor);
            patientNode.RemoveEmptyNodes();

            var patientCity = patientNode.Select("Patient.address[0].city").FirstOrDefault();
            var key         = Encoding.UTF8.GetBytes("1234567890123456");
            var plainValue  = EncryptUtility.DecryptTextFromBase64WithAes(patientCity.Value.ToString(), key);

            Assert.Equal("patienttestcity1", plainValue);

            patient = patientNode.ToPoco <Patient>();
            Assert.Single(patient.Meta.Security);
            Assert.Contains(SecurityLabels.MASKED.Code, patient.Meta.Security.Select(s => s.Code));
        }
        public void GivenAFhirPathMatchContainedNode_WhenProcess_NodesInContainedShouldBeRedact()
        {
            AnonymizationFhirPathRule[] rules = new AnonymizationFhirPathRule[]
            {
                new AnonymizationFhirPathRule("Person.address.city", "address.city", "Person", "redact", AnonymizerRuleType.FhirPathRule, "Person.address"),
            };

            AnonymizationVisitor visitor = new AnonymizationVisitor(rules, CreateTestProcessors());

            var patient = CreateTestPatient();
            var org     = CreateTestOrganization();
            var person  = CreateTestPerson();

            patient.Contained.Add(org);
            org.Contained.Add(person);

            var patientNode = ElementNode.FromElement(patient.ToTypedElement());

            patientNode.Accept(visitor);
            patientNode.RemoveEmptyNodes();
            var personCity = patientNode.Select("Patient.contained[0].contained[0].address[0].city[0]").FirstOrDefault();

            Assert.Null(personCity);

            patient = patientNode.ToPoco <Patient>();
            Assert.Single(patient.Meta.Security);
            Assert.Contains(SecurityLabels.REDACT.Code, patient.Meta.Security.Select(s => s.Code));

            Assert.Null(patient.Contained[0].Meta);
        }
        public void GivenAPatientWithOnlyId_WhenProcess_NodeShouldBeRedact()
        {
            AnonymizationFhirPathRule[] rules = new AnonymizationFhirPathRule[]
            {
                new AnonymizationFhirPathRule("Patient.id", "id", "Patient", "redact", AnonymizerRuleType.FhirPathRule, "Patient.id"),
            };

            AnonymizationVisitor visitor = new AnonymizationVisitor(rules, CreateTestProcessors());

            var patient = new Patient();

            patient.Id = "Test";
            var patientNode = ElementNode.FromElement(patient.ToTypedElement());

            patientNode.Accept(visitor);
            patientNode.RemoveEmptyNodes();

            var patientId = patientNode.Select("Patient.id").FirstOrDefault();

            Assert.Null(patientId);

            patient = patientNode.ToPoco <Patient>();
            Assert.Single(patient.Meta.Security);
            Assert.Contains(SecurityLabels.REDACT.Code, patient.Meta.Security.Select(s => s.Code));
        }
        public void GivenARedactRuleAndThenAPerturbRule_WhenProcess_NodeShouldBeRedacted()
        {
            AnonymizationFhirPathRule[] rules = new AnonymizationFhirPathRule[]
            {
                new AnonymizationFhirPathRule("Observation.referenceRange.low.value", "referenceRange.low.value", "Observation", "redact", AnonymizerRuleType.FhirPathRule, "Observation.referenceRange.low.value"),
                new AnonymizationFhirPathRule("Observation.referenceRange.low", "referenceRange.low", "Observation", "perturb", AnonymizerRuleType.FhirPathRule, "Observation.referenceRange.low",
                                              new Dictionary <string, object> {
                    { "span", "2" }
                }),
            };
            AnonymizationVisitor visitor = new AnonymizationVisitor(rules, CreateTestProcessors());

            var observation     = CreateTestObservation();
            var observationNode = ElementNode.FromElement(observation.ToTypedElement());

            observationNode.Accept(visitor);

            var lowNode        = observationNode.Select("Observation.referenceRange.low");
            var perturbedValue = lowNode.Children("value").First().Value;

            Assert.Null(perturbedValue);

            observation = observationNode.ToPoco <Observation>();
            Assert.Contains(SecurityLabels.REDACT.Code, observation.Meta.Security.Select(s => s.Code));
            Assert.DoesNotContain(SecurityLabels.PERTURBED.Code, observation.Meta.Security.Select(s => s.Code));
        }
        public void GivenAPerturbRule_WhenProcess_NodeShouldBePerturbed()
        {
            AnonymizationFhirPathRule[] rules = new AnonymizationFhirPathRule[]
            {
                new AnonymizationFhirPathRule("Observation.referenceRange.low", "referenceRange.low", "Observation", "perturb", AnonymizerRuleType.FhirPathRule, "Observation.referenceRange.low",
                                              new Dictionary <string, object> {
                    { "span", 4 }
                }),
                new AnonymizationFhirPathRule("Observation.referenceRange.high.value", "referenceRange.high.value", "Observation", "perturb", AnonymizerRuleType.FhirPathRule, "Observation.referenceRange.high.value",
                                              new Dictionary <string, object> {
                    { "span", 0.2 }, { "rangeType", "proportional" }
                })
            };
            AnonymizationVisitor visitor = new AnonymizationVisitor(rules, CreateTestProcessors());

            var observation     = CreateTestObservation();
            var observationNode = ElementNode.FromElement(observation.ToTypedElement());

            observationNode.Accept(visitor);
            observationNode.RemoveEmptyNodes();

            var lowNode        = observationNode.Select("Observation.referenceRange.low");
            var perturbedValue = decimal.Parse(lowNode.Children("value").First().Value.ToString());

            Assert.InRange(perturbedValue, 8, 12);

            var highNode = observationNode.Select("Observation.referenceRange.high");

            perturbedValue = decimal.Parse(highNode.Children("value").First().Value.ToString());
            Assert.InRange(perturbedValue, 90, 110);

            observation = observationNode.ToPoco <Observation>();
            Assert.Contains(SecurityLabels.PERTURBED.Code, observation.Meta.Security.Select(s => s.Code));
        }
        public void GivenAKeepRuleAndThenANodesByTypeRule_WhenProcess_NodesShouldBeProcessedCorrectly()
        {
            AnonymizationFhirPathRule[] rules = new AnonymizationFhirPathRule[]
            {
                new AnonymizationFhirPathRule("Person.address.country", "Person.address.country", "Person", "keep", AnonymizerRuleType.FhirPathRule, "Person.address.country"),
                new AnonymizationFhirPathRule("nodesByType('Address')", "nodesByType('Address')", "", "redact", AnonymizerRuleType.FhirPathRule, "nodesByType('Address')"),
            };

            AnonymizationVisitor visitor = new AnonymizationVisitor(rules, CreateTestProcessors());

            var patient = CreateTestPatient();
            var person  = CreateTestPerson();

            patient.Contained.Add(person);

            var patientNode = ElementNode.FromElement(patient.ToTypedElement());

            patientNode.Accept(visitor);
            patientNode.RemoveEmptyNodes();

            var patientAddress = patientNode.Select("Patient.address[0]").FirstOrDefault();
            var personAddress  = patientNode.Select("Patient.contained[0].address[0]").FirstOrDefault();
            var personCity     = patientNode.Select("Patient.contained[0].address[0].city").FirstOrDefault();
            var personCountry  = patientNode.Select("Patient.contained[0].address[0].country").First().Value.ToString();

            Assert.Null(patientAddress);
            Assert.NotNull(personAddress);
            Assert.Null(personCity);
            Assert.Equal("persontestcountry", personCountry);
        }
        public void GivenANodesByTypeRuleWithResourceType_WhenProcess_OnlyNodesInSpecificResourceTypeShouldBeProcessed()
        {
            AnonymizationFhirPathRule[] rules = new AnonymizationFhirPathRule[]
            {
                new AnonymizationFhirPathRule("Person.nodesByType('Address')", "nodesByType('Address')", "Person", "redact", AnonymizerRuleType.FhirPathRule, "Person.nodesByType('Address')"),
            };

            AnonymizationVisitor visitor = new AnonymizationVisitor(rules, CreateTestProcessors());

            var patient = CreateTestPatient();
            var org     = CreateTestOrganization();
            var person  = CreateTestPerson();

            patient.Contained.Add(org);
            org.Contained.Add(person);

            var patientNode = ElementNode.FromElement(patient.ToTypedElement());

            patientNode.Accept(visitor);
            patientNode.RemoveEmptyNodes();

            var    personAddress  = patientNode.Select("Patient.contained[0].contained[0].address[0]").FirstOrDefault();
            string patientCity    = patientNode.Select("Patient.address[0].city").First().Value.ToString();
            string patientCountry = patientNode.Select("Patient.address[0].country").First().Value.ToString();

            Assert.Equal("patienttestcity1", patientCity);
            Assert.Equal("patienttestcountry1", patientCountry);
            Assert.Null(personAddress);
        }
Exemplo n.º 11
0
        public static ElementNode Anonymize(this ElementNode node, AnonymizationFhirPathRule[] rules, Dictionary <string, IAnonymizerProcessor> processors)
        {
            AnonymizationVisitor visitor = new AnonymizationVisitor(rules, processors);

            node.Accept(visitor);
            node.RemoveEmptyNodes();

            return(node);
        }
        public static ElementNode Anonymize(this ElementNode node, AnonymizationFhirPathRule[] rules,
                                            Dictionary <string, IAnonymizerProcessor> processors, AnonymizerSettings settings = null)
        {
            var visitor = new AnonymizationVisitor(rules, processors, settings);

            node.Accept(visitor);
            node.RemoveNullChildren();

            return(node);
        }
        public void GivenAFhirPathMatchBundleEntryNode_WhenProcess_NodesInBundleShouldBeRedact()
        {
            AnonymizationFhirPathRule[] rules = new AnonymizationFhirPathRule[]
            {
                new AnonymizationFhirPathRule("Person.address.city", "address.city", "Person", "redact", AnonymizerRuleType.FhirPathRule, "Person.address"),
            };

            AnonymizationVisitor visitor = new AnonymizationVisitor(rules, CreateTestProcessors());

            var person = CreateTestPerson();
            var bundle = new Bundle();

            bundle.AddResourceEntry(person, "http://example.org/fhir/Person/1");

            var bundleNode = ElementNode.FromElement(bundle.ToTypedElement());

            bundleNode.Accept(visitor);
            bundleNode.RemoveEmptyNodes();
            var personCity = bundleNode.Select("Bundle.entry[0].resource[0].address[0].city[0]").FirstOrDefault();

            Assert.Null(personCity);
        }
        public void Given2ConflictRules_WhenProcess_SecondRuleShouldBeIgnored()
        {
            AnonymizationFhirPathRule[] rules = new AnonymizationFhirPathRule[]
            {
                new AnonymizationFhirPathRule("Patient", "Patient", "Patient", "keep", AnonymizerRuleType.FhirPathRule, "Patient"),
                new AnonymizationFhirPathRule("Patient.address", "address", "Patient", "redact", AnonymizerRuleType.FhirPathRule, "Patient.address"),
            };

            AnonymizationVisitor visitor = new AnonymizationVisitor(rules, CreateTestProcessors());

            var patient     = CreateTestPatient();
            var patientNode = ElementNode.FromElement(patient.ToTypedElement());

            patientNode.Accept(visitor);
            string patientCity    = patientNode.Select("Patient.address[0].city").First().Value.ToString();
            string patientCountry = patientNode.Select("Patient.address[0].country").First().Value.ToString();

            Assert.Equal("patienttestcity1", patientCity);
            Assert.Equal("patienttestcountry1", patientCountry);

            patient = patientNode.ToPoco <Patient>();
            Assert.Null(patient.Meta);
        }
        public void GivenARuleForAll_WhenProcess_AllTypeNodesShouldBeProcessed()
        {
            AnonymizationFhirPathRule[] rules = new AnonymizationFhirPathRule[]
            {
                new AnonymizationFhirPathRule("Resource", "Resource", "Resource", "redact", AnonymizerRuleType.FhirPathRule, "Resource"),
            };

            AnonymizationVisitor visitor = new AnonymizationVisitor(rules, CreateTestProcessors());

            var patient     = CreateTestPatient();
            var patientNode = ElementNode.FromElement(patient.ToTypedElement());

            patientNode.Accept(visitor);
            patientNode.RemoveEmptyNodes();

            var patientAddress = patientNode.Select("Patient.address[0]").FirstOrDefault();

            Assert.Null(patientAddress);

            patient = patientNode.ToPoco <Patient>();
            Assert.Single(patient.Meta.Security);
            Assert.Contains(SecurityLabels.REDACT.Code, patient.Meta.Security.Select(s => s.Code));
        }
        public void GivenACryptoHashRule_WhenProcess_NodeShouldBeHashed()
        {
            AnonymizationFhirPathRule[] rules = new AnonymizationFhirPathRule[]
            {
                new AnonymizationFhirPathRule("Patient.address", "address", "Patient", "cryptoHash", AnonymizerRuleType.FhirPathRule, "Patient.address"),
            };

            AnonymizationVisitor visitor = new AnonymizationVisitor(rules, CreateTestProcessors());

            var patient     = CreateTestPatient();
            var patientNode = ElementNode.FromElement(patient.ToTypedElement());

            patientNode.Accept(visitor);
            patientNode.RemoveEmptyNodes();

            var patientAddress = patientNode.Select("Patient.address[0].city").FirstOrDefault();

            Assert.Equal("c4321653de997f3029d2efa38dd4baa6c9c2f6bd67b8a52be789f157f8b286ce", patientAddress.Value.ToString());

            patient = patientNode.ToPoco <Patient>();
            Assert.Single(patient.Meta.Security);
            Assert.Contains(SecurityLabels.CRYTOHASH.Code, patient.Meta.Security.Select(s => s.Code));
        }
        public void GivenANodesByTypeRuleWithExpressionFunction_WhenProcess_OnlyNodesMatchSpecificExpressionFunctionShouldBeProcessed()
        {
            AnonymizationFhirPathRule[] rules = new AnonymizationFhirPathRule[]
            {
                new AnonymizationFhirPathRule("nodesByType('Address').where(city='patienttestcity1').city", "nodesByType('Address').where(city='patienttestcity1').city", "", "redact", AnonymizerRuleType.FhirPathRule, "nodesByType('Address').where(city='patienttestcity1').city"),
            };

            AnonymizationVisitor visitor = new AnonymizationVisitor(rules, CreateTestProcessors());

            var patient     = CreateTestPatient();
            var patientNode = ElementNode.FromElement(patient.ToTypedElement());

            patientNode.Accept(visitor);
            patientNode.RemoveEmptyNodes();

            var patientAddress = patientNode.Select("Patient.address[0]").FirstOrDefault();
            var patientCity    = patientNode.Select("Patient.address[0].city").FirstOrDefault();
            var patientCountry = patientNode.Select("Patient.address[0].country").First().Value.ToString();

            Assert.NotNull(patientAddress);
            Assert.Null(patientCity);
            Assert.Equal("patienttestcountry1", patientCountry);
        }
        public void GivenAComplexSubstituteRule_WhenProcess_NodeShouldBeSubstituted()
        {
            AnonymizationFhirPathRule[] rules = new AnonymizationFhirPathRule[]
            {
                new AnonymizationFhirPathRule("Patient.address", "address", "Patient", "substitute", AnonymizerRuleType.FhirPathRule, "Patient.address",
                                              new Dictionary <string, object> {
                    { "replaceWith", "{ \"city\": \"ExampleCity2020\" }" }
                }),
            };

            AnonymizationVisitor visitor = new AnonymizationVisitor(rules, CreateTestProcessors());

            var patient     = CreateTestPatient();
            var patientNode = ElementNode.FromElement(patient.ToTypedElement());
            var patientCity = patientNode.Select("Patient.address[0].city").FirstOrDefault();

            Assert.Equal("patienttestcity1", patientCity.Value.ToString());
            var patientCountry = patientNode.Select("Patient.address[0].country").FirstOrDefault();

            Assert.Equal("patienttestcountry1", patientCountry.Value.ToString());

            patientNode.Accept(visitor);
            patientNode.RemoveEmptyNodes();

            patientCity = patientNode.Select("Patient.address[0].city").FirstOrDefault();
            Assert.Equal("ExampleCity2020", patientCity.Value.ToString());
            patientCountry = patientNode.Select("Patient.address[0].country").FirstOrDefault();
            Assert.Null(patientCountry);
            var patientCity2 = patientNode.Select("Patient.contact[0].address[0].city").FirstOrDefault();

            Assert.Equal("patienttestcity2", patientCity2.Value.ToString());

            patient = patientNode.ToPoco <Patient>();
            Assert.Single(patient.Meta.Security);
            Assert.Contains(SecurityLabels.SUBSTITUTED.Code, patient.Meta.Security.Select(s => s.Code));
        }