Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .github/workflows/publish-nuget.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,9 @@ jobs:

- name: Run tests
run: |
dotnet test test/WalletFramework.Core.Tests --configuration $BUILD_CONFIG --no-restore --no-build
dotnet test test/WalletFramework.MdocLib.Tests --configuration $BUILD_CONFIG --no-restore --no-build
dotnet test test/WalletFramework.MdocVc.Tests --configuration $BUILD_CONFIG --no-restore --no-build
dotnet test test/WalletFramework.Oid4Vc.Tests --configuration $BUILD_CONFIG --no-restore --no-build
dotnet test test/WalletFramework.SdJwtVc.Tests --configuration $BUILD_CONFIG --no-restore --no-build

Expand Down
42 changes: 0 additions & 42 deletions src/WalletFramework.Core.Tests/Path/ClaimPathTests.cs

This file was deleted.

48 changes: 48 additions & 0 deletions src/WalletFramework.Core/ClaimPaths/ClaimPath.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
using WalletFramework.Core.ClaimPaths.Errors;
using WalletFramework.Core.Functional;
using WalletFramework.Core.Path;
using Newtonsoft.Json.Linq;

namespace WalletFramework.Core.ClaimPaths;

public readonly struct ClaimPath
{
private readonly IReadOnlyList<ClaimPathComponent> _components;

private ClaimPath(IReadOnlyList<ClaimPathComponent> components)
{
_components = components;
}

public IReadOnlyList<ClaimPathComponent> GetPathComponents() => _components;

public static Validation<ClaimPath> FromComponents(IEnumerable<ClaimPathComponent> components)
{
var list = components.ToList();
if (list.Count == 0)
return new ClaimPathIsEmptyError();
return new ClaimPath(list);
}

public static Validation<ClaimPath> FromJArray(JArray array)
{
return
from components in array.TraverseAll(ClaimPathComponent.Create)
from path in FromComponents(components)
select path;
}
}

public static class ClaimPathFun
{
public static JsonPath ToJsonPath(this ClaimPath claimPath)
{
var jsonPath = "$." + string.Join('.', claimPath.GetPathComponents().Select(x =>
{
if (x.IsKey) return x.AsKey();
if (x.IsIndex) return x.AsIndex()?.ToString();
return null;
}).Where(x => x is not null));
return JsonPath.ValidJsonPath(jsonPath).UnwrapOrThrow();
}
}
38 changes: 38 additions & 0 deletions src/WalletFramework.Core/ClaimPaths/ClaimPathComponent.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
using WalletFramework.Core.ClaimPaths.Errors;
using WalletFramework.Core.Functional;
using OneOf;
using Newtonsoft.Json.Linq;

namespace WalletFramework.Core.ClaimPaths;

public sealed record ClaimPathComponent
{
private readonly OneOf<string, int, SelectAllElementsInArrayComponent> _value;

private ClaimPathComponent(OneOf<string, int, SelectAllElementsInArrayComponent> value) => _value = value;

public static Validation<ClaimPathComponent> Create(JToken token) =>
token.Type switch
{
JTokenType.String => !string.IsNullOrEmpty(token.Value<string>())
? new ClaimPathComponent(token.Value<string>()!)
: new UnknownComponentError(),
JTokenType.Integer => new ClaimPathComponent(token.Value<int>()),
JTokenType.Null => new ClaimPathComponent(new SelectAllElementsInArrayComponent()),
_ => new UnknownComponentError()
};

public T Match<T>(
Func<string, T> onKey,
Func<int, T> onIndex,
Func<SelectAllElementsInArrayComponent, T> onSelectAll) =>
_value.Match(onKey, onIndex, onSelectAll);

public bool IsKey => _value.IsT0;

public bool IsIndex => _value.IsT1;

public string? AsKey() => _value.TryPickT0(out var key, out _) ? key : null;

public int? AsIndex() => _value.TryPickT1(out var idx, out _) ? idx : null;
}
31 changes: 31 additions & 0 deletions src/WalletFramework.Core/ClaimPaths/ClaimPathJsonConverter.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using WalletFramework.Core.Functional;

namespace WalletFramework.Core.ClaimPaths;

public class ClaimPathJsonConverter : JsonConverter<ClaimPath>
{
public override bool CanWrite => true;

public override void WriteJson(JsonWriter writer, ClaimPath value, JsonSerializer serializer)
{
writer.WriteStartArray();
foreach (var component in value.GetPathComponents())
{
component.Match(
onKey: k => { writer.WriteValue(k); return 0; },
onIndex: i => { writer.WriteValue(i); return 0; },
onSelectAll: _ => { writer.WriteNull(); return 0; }
);
}
writer.WriteEndArray();
}

public override ClaimPath ReadJson(JsonReader reader, Type objectType, ClaimPath existingValue, bool hasExistingValue, JsonSerializer serializer)
{
var array = JArray.Load(reader);
var validation = ClaimPath.FromJArray(array);
return validation.UnwrapOrThrow();
}
}
64 changes: 64 additions & 0 deletions src/WalletFramework.Core/ClaimPaths/ClaimPathSelection.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
using Newtonsoft.Json.Linq;
using WalletFramework.Core.Functional;
using WalletFramework.Core.ClaimPaths.Errors;

namespace WalletFramework.Core.ClaimPaths;

public record ClaimPathSelection
{
private ClaimPathSelection(IEnumerable<JToken> values) => Values = values;

private IEnumerable<JToken> Values { get; }

public IEnumerable<JToken> GetValues() => Values;

public static Validation<ClaimPathSelection> Create(IEnumerable<JToken> values)
{
var arr = values as JToken[] ?? [.. values];
return arr.Any() ? new ClaimPathSelection(arr) : new SelectionIsEmptyError();
}
}

public static class ClaimPathSelectionFun
{
public static Validation<ClaimPathSelection> SelectObjectKey(ClaimPathSelection selection, string key)
{
if (selection.GetValues().Any(token => token is not JObject))
return new SelectedElementIsNotAnObjectError();

var newSelection = selection
.GetValues()
.Cast<JObject>()
.SelectMany(obj => obj.TryGetValue(key, out var value)
? [value]
: Array.Empty<JToken>());

return ClaimPathSelection.Create(newSelection);
}

public static Validation<ClaimPathSelection> SelectArrayIndex(ClaimPathSelection selection, int index)
{
if (selection.GetValues().Any(token => token is not JArray))
return new SelectedElementIsNotAnArrayError();

var arrays = selection.GetValues().Cast<JArray>().ToArray();
if (arrays.Any(array => index < 0 || index >= array.Count))
return new SelectedElementDoesNotExistInArrayError();

var newSelection = arrays.Select(array => array[index]);
return ClaimPathSelection.Create(newSelection);
}

public static Validation<ClaimPathSelection> SelectAllArrayElements(ClaimPathSelection selection)
{
if (selection.GetValues().Any(token => token is not JArray))
return new SelectedElementIsNotAnArrayError();

var newSelection = selection
.GetValues()
.Cast<JArray>()
.SelectMany(array => array.Children());

return ClaimPathSelection.Create(newSelection);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
using WalletFramework.Core.Functional;

namespace WalletFramework.Core.ClaimPaths.Errors.Abstractions;

public abstract record ClaimPathError : Error
{
protected ClaimPathError(string message) : base(message)
{
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
using WalletFramework.Core.Functional;

namespace WalletFramework.Core.ClaimPaths.Errors;

public record ClaimPathIsEmptyError() : Error("ClaimPath is not allowed to be empty");
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
using WalletFramework.Core.ClaimPaths.Errors.Abstractions;

namespace WalletFramework.Core.ClaimPaths.Errors;

public record ElementNotFoundError(string Namespace, string ElementId)
: ClaimPathError($"The element '{ElementId}' was not found in the namespace '{Namespace}'.");
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
using WalletFramework.Core.ClaimPaths.Errors.Abstractions;

namespace WalletFramework.Core.ClaimPaths.Errors;

public record NamespaceNotFoundError(string Namespace)
: ClaimPathError($"The namespace '{Namespace}' was not found in the document.");
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
using WalletFramework.Core.ClaimPaths.Errors.Abstractions;

namespace WalletFramework.Core.ClaimPaths.Errors;

public record SelectedElementDoesNotExistInArrayError()
: ClaimPathError("The selected element does not exist in the array.");
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
using WalletFramework.Core.ClaimPaths.Errors.Abstractions;

namespace WalletFramework.Core.ClaimPaths.Errors;

public record SelectedElementIsNotAnArrayError()
: ClaimPathError("The selected element is not an array.");
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
using WalletFramework.Core.ClaimPaths.Errors.Abstractions;

namespace WalletFramework.Core.ClaimPaths.Errors;

public record SelectedElementIsNotAnObjectError()
: ClaimPathError("The selected element is not an object.");
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
using WalletFramework.Core.ClaimPaths.Errors.Abstractions;

namespace WalletFramework.Core.ClaimPaths.Errors;

public record SelectionIsEmptyError()
: ClaimPathError("The selection is empty after processing the claims path pointer.");
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
using WalletFramework.Core.ClaimPaths.Errors.Abstractions;

namespace WalletFramework.Core.ClaimPaths.Errors;

public record UnknownComponentError()
: ClaimPathError("The claim path component is unknown or unsupported.");
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
namespace WalletFramework.Core.ClaimPaths;

public record SelectAllElementsInArrayComponent;
26 changes: 0 additions & 26 deletions src/WalletFramework.Core/Path/ClaimPath.cs

This file was deleted.

This file was deleted.

10 changes: 10 additions & 0 deletions src/WalletFramework.MdocLib/Elements/Element.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using PeterO.Cbor;
using WalletFramework.Core.Functional;
using OneOf;
using Newtonsoft.Json.Linq;
using static WalletFramework.MdocLib.Elements.ElementArray;
using static WalletFramework.MdocLib.Elements.ElementMap;

Expand Down Expand Up @@ -30,4 +31,13 @@ public override string ToString()
array => array.Value.First().ToString(),
map => map.Value.First().ToString());
}

public JToken ToJToken()
{
return Value.Match<JToken>(
singleValue => singleValue.ToJValue(),
array => array.ToJArray(),
map => map.ToJObject()
);
}
}
Loading
Loading