/// <summary> /// Sets the passed <paramref name="anonymizerOption" /> <paramref name="anonymizerApproach" /> /// </summary> /// <param name="anonymizerOption">the passed DataCategory to</param> /// <param name="anonymizerApproach">t</param> public void SetOption(DataCategory anonymizerOption, AnonymizerApproach anonymizerApproach) { try { Operations.Add(anonymizerOption, anonymizerApproach); } catch (ArgumentException) { Operations.Remove(anonymizerOption); Operations.Add(anonymizerOption, anonymizerApproach); } }
internal static bool IsAnonymizerRelevant(this PropertyInfo prop, AnonymizerApproach approach, DataCategory?dataCategory) { switch (approach) { case AnonymizerApproach.DELETE: return(prop.IsDeletionRelevant(dataCategory)); case AnonymizerApproach.HASH: return(prop.IsHashingRelevant(dataCategory)); case AnonymizerApproach.ENCRYPT: case AnonymizerApproach.DECRYPT: return(prop.IsEncryptionRelevant(dataCategory)); default: return(false); } }
/// <summary> /// Apply the configuration set in the constructor to the JObject set in the constructor. /// </summary> /// <see cref="Anonymizer(AnonymizerConfiguration)"/> /// <returns>A modified JObject with the configuration applied.</returns> public T ApplyOperations <T>(BusinessObject bo) { if (bo == null) { throw new ArgumentNullException(nameof(bo)); } Dictionary <DataCategory, AnonymizerApproach> mapping = configuration.operations; BusinessObject result = bo.DeepClone <BusinessObject>(); foreach (DataCategory dataCategory in mapping.Keys) { AnonymizerApproach approach = mapping[dataCategory]; PropertyInfo[] affectedProps = bo.GetType().GetProperties() .Where(p => p.GetCustomAttributes(typeof(DataCategoryAttribute), false).Length > 0) .OrderBy(ap => ap.GetCustomAttribute <JsonPropertyAttribute>()?.Order) .ToArray <PropertyInfo>(); foreach (PropertyInfo affectedProp in affectedProps) { if (!affectedProp.IsAnonymizerRelevant(approach, dataCategory)) { continue; } switch (approach) { case AnonymizerApproach.HASH: try { object affectedFieldValue = affectedProp.GetValue(result); HashObject(ref affectedFieldValue, dataCategory); affectedProp.SetValue(result, affectedFieldValue); } catch (RuntimeBinderException e) { _logger.LogWarning($"Catched RuntimeBinderException in Object {bo.GetBoTyp()}. Probably due to trying to get the type of a null object BO: {e.Message}"); } break; case AnonymizerApproach.DELETE: /* We'd like to set the value to null, but the business object might not allow * it resulting in a JsonSerializationException. That's why we first check, * whether the field is actually required. If it has to be non-null we set the * annotated default value, otherwise we can safely set null. */ bool isRequired = false; Attribute defaultValueAttribute = null; Attribute jsonPropertyAttribute = affectedProp.GetCustomAttributes().Where(a => a.GetType() == typeof(JsonPropertyAttribute)).FirstOrDefault(); if (jsonPropertyAttribute != null) { JsonPropertyAttribute jpa = (JsonPropertyAttribute)jsonPropertyAttribute; if (jpa.Required == Required.Always) { isRequired = true; defaultValueAttribute = affectedProp.GetCustomAttributes().Where(a => a.GetType() == typeof(DefaultValueAttribute)).FirstOrDefault(); } } if (isRequired && defaultValueAttribute != null) { DefaultValueAttribute dva = (DefaultValueAttribute)defaultValueAttribute; affectedProp.SetValue(result, dva.Value); } else if (bo.GetType().IsSubclassOf(typeof(BO4E.BO.BusinessObject))) { // e.g. 1*Energiemenge (mappedObject)---> n*Verbrauch (boSubObject) var boSubObject = affectedProp.GetValue(bo); if (boSubObject != null) { try { if (boSubObject.GetType().IsGenericType&& boSubObject.GetType().GetGenericTypeDefinition() == typeof(List <>)) { Type listElementType = boSubObject.GetType().GetGenericArguments()[0]; Type listType = typeof(List <>).MakeGenericType(listElementType); object newEmptyList = Activator.CreateInstance(listType); boSubObject = newEmptyList; } else { boSubObject = null; } } catch (RuntimeBinderException e) { _logger.LogError($"Couldn't null BO field!: {e.Message}"); } affectedProp.SetValue(result, boSubObject); } } else { // strings, integers, elementary affectedProp.SetValue(result, null); } break; case AnonymizerApproach.ENCRYPT: if (this.publicKeyX509 == null) { throw new ArgumentNullException("To use the encryption feature you have to provide a public X509 certificate using the SetPublicKey method."); } using (X509AsymmetricEncrypter xasyncenc = new X509AsymmetricEncrypter(this.publicKeyX509)) { if (affectedProp.GetValue(bo).GetType() == typeof(string)) { if (affectedProp.GetValue(bo) != null) { affectedProp.SetValue(result, xasyncenc.Encrypt(affectedProp.GetValue(bo).ToString())); } } else if (affectedProp.GetValue(bo).GetType().IsSubclassOf(typeof(BO4E.COM.COM))) { var comObject = affectedProp.GetValue(bo); dynamic comFields = comObject.GetType().GetProperties(); foreach (dynamic comField in comFields) { try { comField.SetValue(comObject, xasyncenc.Encrypt(comField.GetValue(comObject)).ToString()); } catch (ArgumentException e) { // das sollte passieren, wenn das Argument kein String is und deswegen das encrypten kein sinn macht _logger.LogError($"Couldn't encrypt COM field!: {e.Message}"); } catch (Exception f) { // das sollte passieren, wenn das Argument ein enum _logger.LogError($"Couldn't encrypt COM field!: {f.Message}"); } } affectedProp.SetValue(result, comObject); } else if (affectedProp.PropertyType.IsSubclassOf(typeof(BO4E.BO.BusinessObject))) { affectedProp.SetValue(result, xasyncenc.Encrypt((BusinessObject)affectedProp.GetValue(bo))); } else if (affectedProp.PropertyType.ToString().StartsWith("BO4E.ENUM")) // todo: check for namespace instead of strinyfied comparison { //affectedField.SetValue(mappedObject, Sha256HashEnum(affectedField.GetValue(mappedObject).ToString())); _logger.LogWarning($"Encrypting {affectedProp.PropertyType} is not supported, since the result would not be a valid ENUM value."); //throw new NotSupportedException($"Hashing {affectedField.FieldType} is not supported, since the result would not be a valid ENUM value."); } else { throw new NotImplementedException($"Encrypting {affectedProp.PropertyType} is not implemented yet."); } } break; case AnonymizerApproach.DECRYPT: if (this.privateKey == null) { throw new ArgumentNullException("To use the decryption feature you have to provide a private key using the SetPrivateKey method."); } using (X509AsymmetricEncrypter xasydec = new X509AsymmetricEncrypter(this.privateKey)) { affectedProp.SetValue(result, xasydec.Decrypt(affectedProp.GetValue(bo).ToString())); } continue; case AnonymizerApproach.KEEP: // do nothing continue; default: continue; } } } if (typeof(T) == typeof(JObject)) { return((T)(object)JObject.FromObject(result)); } return((T)(object)result); }