Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Encrypted properties #49

Merged
merged 7 commits into from
May 30, 2018
13 changes: 13 additions & 0 deletions docs/_pages/02-api-04-collections.md
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,19 @@ Adds the given property to the searchable properties collection. Property must b
collectionConfig.AddSearchableProperty(p => p.FirstName);
````

### Defining encrypted properties
{: .mt}

#### AddEncryptedProperty(Lambda encryptedPropertyExpression) *: FluidityCollectionConfig<TEntityType>*
{: .signature}

Adds the given property to the encrypted properties collection. Property must be of type `String`. When set, the property will be encrypted/decrypted on write/read respectively.

````csharp
// Example
collectionConfig.AddEncryptedProperty(p => p.Email);
````

### Applying a global filter
{: .mt}

Expand Down
4 changes: 4 additions & 0 deletions src/Fluidity/Configuration/FluidityCollectionConfig.cs
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,9 @@ public abstract class FluidityCollectionConfig : FluidityTreeItemConfig
protected List<FluidityPropertyConfig> _searchableProperties;
internal IEnumerable<FluidityPropertyConfig> SearchableProperties => _searchableProperties;

protected List<FluidityPropertyConfig> _encryptedProperties;
internal IEnumerable<FluidityPropertyConfig> EncryptedProperties => _encryptedProperties;

protected LambdaExpression _filterExpression;
internal LambdaExpression FilterExpression => _filterExpression;

Expand Down Expand Up @@ -120,6 +123,7 @@ protected FluidityCollectionConfig(Type entityType, LambdaExpression idPropertyE
_containerMenuItems = new List<MenuItem>();
_entityMenuItems = new List<MenuItem>();
_searchableProperties = new List<FluidityPropertyConfig>();
_encryptedProperties = new List<FluidityPropertyConfig>();
}
}
}
11 changes: 11 additions & 0 deletions src/Fluidity/Configuration/FluidityCollectionConfig`T.cs
Original file line number Diff line number Diff line change
Expand Up @@ -292,6 +292,17 @@ public FluidityCollectionConfig<TEntityType> AddSearchableProperty(Expression<Fu
return this;
}

/// <summary>
/// Adds a property that will be encrypted / decrypted when retrived from the repository.
/// </summary>
/// <param name="encryptedPropertyExpression">The encrypted property expression.</param>
/// <returns>The collection configuration.</returns>
public FluidityCollectionConfig<TEntityType> AddEncryptedProperty(Expression<Func<TEntityType, string>> encryptedPropertyExpression)
{
_encryptedProperties.Add(encryptedPropertyExpression);
return this;
}

/// <summary>
/// Sets which property to use as the Date Created property.
/// </summary>
Expand Down
1 change: 1 addition & 0 deletions src/Fluidity/Fluidity.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -282,6 +282,7 @@
<Compile Include="Extensions\FluidityPropertyConfigExtensions.cs" />
<Compile Include="Extensions\SqlExtensions.cs" />
<Compile Include="Events\FluidityStartingEventArgs.cs" />
<Compile Include="Helpers\SecurityHelper.cs" />
<Compile Include="Helpers\UmbracoPublishedPropertyTypeHelper.cs" />
<Compile Include="ListViewLayouts\FluidityListViewLayout.cs" />
<Compile Include="Extensions\FluidityEditorFieldConfigExtensions.cs" />
Expand Down
33 changes: 33 additions & 0 deletions src/Fluidity/Helpers/SecurityHelper.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
// <copyright file="SecurityHelper.cs" company="Matt Brailsford">
// Copyright (c) 2017 Matt Brailsford and contributors.
// Licensed under the Apache License, Version 2.0.
// </copyright>

using System;
using Umbraco.Core;

namespace Fluidity.Helpers
{
internal static class SecurityHelper
{
internal static string Encrypt(string input)
{
return input.EncryptWithMachineKey();
}

internal static string Decrypt(string input)
{
try
{
return input.DecryptWithMachineKey();
}
catch (ArgumentException ex)
{
if (!ex.Message.Contains("encryptedTicket"))
throw ex;

return input;
}
}
}
}
24 changes: 24 additions & 0 deletions src/Fluidity/Web/Models/Mappers/FluidityEntityMapper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,12 @@ public FluidityEntityDisplayModel ToDisplayModel(FluiditySectionConfig section,
{
var value = entity?.GetPropertyValue(field.Property);

var encryptedProp = collection.EncryptedProperties?.FirstOrDefault(x => x.Name == field.Property.Name);
if (encryptedProp != null)
{
value = SecurityHelper.Decrypt(value.ToString());
}

if (field.Format != null)
{
value = field.Format(value, entity);
Expand Down Expand Up @@ -157,6 +163,12 @@ public FluidityEntityEditModel ToEditModel(FluiditySectionConfig section, Fluidi
? entity?.GetPropertyValue(field.Property)
: field.DefaultValueFunc != null ? field.DefaultValueFunc() : field.Property.Type.GetDefaultValue();

var encryptedProp = collection.EncryptedProperties?.FirstOrDefault(x => x.Name == field.Property.Name);
if (encryptedProp != null)
{
value = SecurityHelper.Decrypt(value.ToString());
}

if (field.ValueMapper != null)
{
value = field.ValueMapper.ModelToEditor(value);
Expand Down Expand Up @@ -264,6 +276,13 @@ public object FromPostModel(FluiditySectionConfig section, FluidityCollectionCon

if (!dataTypeInfo.PropertyEditor.ValueEditor.IsReadOnly) {
var currentValue = entity.GetPropertyValue(propConfig.Property);

var encryptedProp = collection.EncryptedProperties?.FirstOrDefault(x => x.Name == propConfig.Property.Name);
if (encryptedProp != null)
{
currentValue = SecurityHelper.Decrypt(currentValue.ToString());
}

if (propConfig.ValueMapper != null) {
currentValue = propConfig.ValueMapper.ModelToEditor(currentValue);
}
Expand All @@ -282,6 +301,11 @@ public object FromPostModel(FluiditySectionConfig section, FluidityCollectionCon
propVal = propConfig.ValueMapper.EditorToModel(propVal);
}

if (encryptedProp != null)
{
propVal = SecurityHelper.Encrypt(propVal.ToString());
}

if (propVal != null && propVal.GetType() != propConfig.Property.Type) {
var convert = propVal.TryConvertTo(propConfig.Property.Type);
if (convert.Success) {
Expand Down