Skip to content

Commit 4b0559c

Browse files
committed
mdoc oid4vci
Signed-off-by: Kevin <kevin.dinh@lissi.id>
1 parent 951ef9a commit 4b0559c

File tree

245 files changed

+8212
-4064
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

245 files changed

+8212
-4064
lines changed

src/Hyperledger.Aries/Storage/DefaultWalletRecordService.cs

Lines changed: 113 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,11 @@
66
using Hyperledger.Aries.Agents;
77
using Hyperledger.Aries.Extensions;
88
using Hyperledger.Aries.Features.PresentProof;
9+
using Hyperledger.Aries.Storage.Models;
910
using Hyperledger.Indy.NonSecretsApi;
1011
using Hyperledger.Indy.WalletApi;
1112
using Newtonsoft.Json;
13+
using Newtonsoft.Json.Linq;
1214

1315
namespace Hyperledger.Aries.Storage
1416
{
@@ -32,47 +34,80 @@ public DefaultWalletRecordService()
3234
}
3335

3436
/// <inheritdoc />
35-
public virtual Task AddAsync<T>(Wallet wallet, T record)
36-
where T : RecordBase, new()
37+
public virtual Task AddAsync<T>(Wallet wallet, T record, Func<T, JObject>? encode = null) where T : RecordBase, new()
3738
{
3839
record.CreatedAtUtc = DateTime.UtcNow;
40+
41+
var properties = record
42+
.GetType()
43+
.GetProperties()
44+
.Where(info => Attribute.IsDefined(info, typeof(RecordTagAttribute)));
45+
46+
foreach (var property in properties)
47+
{
48+
var value = property.GetValue(record);
49+
record.SetTag(property.Name, value.ToString(), false);
50+
}
51+
52+
var recordJson = encode is null
53+
? record.ToJson(_jsonSettings)
54+
: encode(record).ToString();
3955

4056
return NonSecrets.AddRecordAsync(wallet,
4157
record.TypeName,
4258
record.Id,
43-
record.ToJson(_jsonSettings),
59+
recordJson,
4460
record.Tags.ToJson());
4561
}
4662

4763
/// <inheritdoc />
48-
public virtual async Task<List<T>> SearchAsync<T>(Wallet wallet, ISearchQuery query, SearchOptions options, int count, int skip)
49-
where T : RecordBase, new()
64+
public virtual async Task<List<T>> SearchAsync<T>(
65+
Wallet wallet,
66+
ISearchQuery? query = null,
67+
SearchOptions? options = null,
68+
int count = 10,
69+
int skip = 0,
70+
Func<JObject, T>? decode = null) where T : RecordBase, new()
5071
{
5172
using var search = await NonSecrets.OpenSearchAsync(
5273
wallet,
5374
new T().TypeName,
5475
(query ?? SearchQuery.Empty).ToJson(),
5576
(options ?? new SearchOptions()).ToJson()
56-
);
77+
);
5778

5879
if(skip > 0) {
5980
await search.NextAsync(wallet, skip);
6081
}
6182

62-
var result = JsonConvert.DeserializeObject<SearchResult>(await search.NextAsync(wallet, count), _jsonSettings);
63-
64-
return result.Records?
65-
.Select(x =>
66-
{
67-
var record = JsonConvert.DeserializeObject<T>(x.Value, _jsonSettings);
68-
69-
foreach (var tag in x.Tags)
70-
record.Tags[tag.Key] = tag.Value;
71-
72-
return record;
73-
})
74-
.ToList()
75-
?? new List<T>();
83+
var searchResultStr = await search.NextAsync(wallet, count);
84+
var searchResult = JsonConvert.DeserializeObject<SearchResult>(searchResultStr, _jsonSettings);
85+
86+
if (searchResult?.Records is null)
87+
{
88+
return new List<T>();
89+
}
90+
91+
var records = searchResult.Records.Select(searchItem =>
92+
{
93+
T record;
94+
if (decode is null)
95+
{
96+
record = JsonConvert.DeserializeObject<T>(searchItem.Value, _jsonSettings)!;
97+
}
98+
else
99+
{
100+
var json = JObject.Parse(searchItem.Value);
101+
record = decode(json);
102+
}
103+
104+
foreach (var tag in searchItem.Tags)
105+
record.Tags[tag.Key] = tag.Value;
106+
107+
return record;
108+
});
109+
110+
return records.ToList();
76111
}
77112

78113
/// <inheritdoc />
@@ -91,8 +126,27 @@ await NonSecrets.UpdateRecordTagsAsync(wallet,
91126
record.Tags.ToJson(_jsonSettings));
92127
}
93128

129+
public async Task Update<T>(Wallet wallet, T record, Func<T, JObject>? encode = null) where T : RecordBase
130+
{
131+
record.UpdatedAtUtc = DateTime.UtcNow;
132+
133+
var recordJson = encode is null
134+
? record.ToJson(_jsonSettings)
135+
: encode(record).ToString();
136+
137+
await NonSecrets.UpdateRecordValueAsync(wallet,
138+
record.TypeName,
139+
record.Id,
140+
recordJson);
141+
142+
await NonSecrets.UpdateRecordTagsAsync(wallet,
143+
record.TypeName,
144+
record.Id,
145+
record.Tags.ToJson(_jsonSettings));
146+
}
147+
94148
/// <inheritdoc />
95-
public virtual async Task<T> GetAsync<T>(Wallet wallet, string id) where T : RecordBase, new()
149+
public async Task<T?> GetAsync<T>(Wallet wallet, string id, Func<JObject, T>? decode = null) where T : RecordBase, new()
96150
{
97151
try
98152
{
@@ -106,9 +160,18 @@ await NonSecrets.UpdateRecordTagsAsync(wallet,
106160
return null;
107161
}
108162

109-
var item = JsonConvert.DeserializeObject<SearchItem>(searchItemJson, _jsonSettings);
163+
var item = JsonConvert.DeserializeObject<SearchItem>(searchItemJson, _jsonSettings)!;
110164

111-
var record = JsonConvert.DeserializeObject<T>(item.Value, _jsonSettings);
165+
T record;
166+
if (decode is null)
167+
{
168+
record = JsonConvert.DeserializeObject<T>(item.Value, _jsonSettings)!;
169+
}
170+
else
171+
{
172+
var json = JObject.Parse(item.Value);
173+
record = decode(json);
174+
}
112175

113176
foreach (var tag in item.Tags)
114177
record.Tags[tag.Key] = tag.Value;
@@ -127,7 +190,7 @@ await NonSecrets.UpdateRecordTagsAsync(wallet,
127190
try
128191
{
129192
var record = await GetAsync<T>(wallet, id);
130-
var typeName = new T().TypeName;
193+
var typeName = record.TypeName;
131194

132195
await NonSecrets.DeleteRecordTagsAsync(
133196
wallet: wallet,
@@ -147,5 +210,31 @@ await NonSecrets.DeleteRecordAsync(
147210
return false;
148211
}
149212
}
213+
214+
/// <inheritdoc />
215+
public async Task<bool> Delete(Wallet wallet, RecordBase record)
216+
{
217+
try
218+
{
219+
var typeName = record.TypeName;
220+
221+
await NonSecrets.DeleteRecordTagsAsync(
222+
wallet: wallet,
223+
type: typeName,
224+
id: record.Id,
225+
tagsJson: record.Tags.Select(x => x.Key).ToArray().ToJson());
226+
await NonSecrets.DeleteRecordAsync(
227+
wallet: wallet,
228+
type: typeName,
229+
id: record.Id);
230+
231+
return true;
232+
}
233+
catch (Exception e)
234+
{
235+
Debug.WriteLine($"Couldn't delete record: {e}");
236+
return false;
237+
}
238+
}
150239
}
151240
}

src/Hyperledger.Aries/Storage/IWalletRecordService.cs

Lines changed: 34 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
1-
using System.Collections.Generic;
1+
using System;
2+
using System.Collections.Generic;
23
using System.Threading.Tasks;
34
using Hyperledger.Indy.WalletApi;
5+
using Newtonsoft.Json.Linq;
46

57
namespace Hyperledger.Aries.Storage
68
{
@@ -15,20 +17,28 @@ public interface IWalletRecordService
1517
/// <returns>The record async.</returns>
1618
/// <param name="wallet">Wallet.</param>
1719
/// <param name="record">Record.</param>
20+
/// <param name="encode">The func for encoding the record to JSON format</param>
1821
/// <typeparam name="T">The 1st type parameter.</typeparam>
19-
Task AddAsync<T>(Wallet wallet, T record) where T : RecordBase, new();
20-
22+
Task AddAsync<T>(Wallet wallet, T record, Func<T, JObject>? encode = null) where T : RecordBase, new();
23+
2124
/// <summary>
22-
/// Searchs the records async.
25+
/// Searches the records async.
2326
/// </summary>
2427
/// <returns>The records async.</returns>
2528
/// <param name="wallet">Wallet.</param>
2629
/// <param name="query">Query.</param>
2730
/// <param name="options">Options.</param>
2831
/// <param name="count">The number of items to return</param>
2932
/// <param name="skip">The number of items to skip</param>
33+
/// <param name="decode">Func for decoding the JSON to the record</param>
3034
/// <typeparam name="T">The 1st type parameter.</typeparam>
31-
Task<List<T>> SearchAsync<T>(Wallet wallet, ISearchQuery query = null, SearchOptions options = null, int count = 10, int skip = 0) where T : RecordBase, new();
35+
Task<List<T>> SearchAsync<T>(
36+
Wallet wallet,
37+
ISearchQuery? query = null,
38+
SearchOptions? options = null,
39+
int count = 10,
40+
int skip = 0,
41+
Func<JObject, T>? decode = null) where T : RecordBase, new();
3242

3343
/// <summary>
3444
/// Updates the record async.
@@ -37,15 +47,25 @@ public interface IWalletRecordService
3747
/// <param name="wallet">Wallet.</param>
3848
/// <param name="record">Credential record.</param>
3949
Task UpdateAsync(Wallet wallet, RecordBase record);
50+
51+
/// <summary>
52+
/// Updates the record async.
53+
/// </summary>
54+
/// <returns>The record async.</returns>
55+
/// <param name="wallet">Wallet.</param>
56+
/// <param name="record">Credential record.</param>
57+
/// <param name="encode">The func for encoding the record to JSON format</param>
58+
Task Update<T>(Wallet wallet, T record, Func<T, JObject>? encode = null) where T : RecordBase;
4059

4160
/// <summary>
4261
/// Gets the record async.
4362
/// </summary>
4463
/// <returns>The record async.</returns>
4564
/// <param name="wallet">Wallet.</param>
4665
/// <param name="id">Identifier.</param>
66+
/// <param name="decode">Func for decoding the JSON to the record</param>
4767
/// <typeparam name="T">The 1st type parameter.</typeparam>
48-
Task<T> GetAsync<T>(Wallet wallet, string id) where T : RecordBase, new();
68+
Task<T?> GetAsync<T>(Wallet wallet, string id, Func<JObject, T>? decode = null) where T : RecordBase, new();
4969

5070
/// <summary>
5171
/// Deletes the record async.
@@ -55,5 +75,13 @@ public interface IWalletRecordService
5575
/// <param name="id">Record Identifier.</param>
5676
/// <returns>Boolean status indicating if the removal succeed</returns>
5777
Task<bool> DeleteAsync<T>(Wallet wallet, string id) where T : RecordBase, new();
78+
79+
/// <summary>
80+
/// Deletes the record async.
81+
/// </summary>
82+
/// <param name="wallet">Wallet.</param>
83+
/// <param name="record"></param>
84+
/// <returns>Boolean status indicating if the removal succeed</returns>
85+
Task<bool> Delete(Wallet wallet, RecordBase record);
5886
}
5987
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
using System;
2+
3+
namespace Hyperledger.Aries.Storage.Models
4+
{
5+
/// <summary>
6+
/// Defines an attribute to be also saved as a tag in the record
7+
/// </summary>
8+
public class RecordTagAttribute : Attribute
9+
{
10+
}
11+
}

src/Hyperledger.Aries/Storage/Records/RecordBase.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ public DateTime? UpdatedAtUtc
3434
/// <summary>Gets or sets the tags.</summary>
3535
/// <value>The tags.</value>
3636
[JsonIgnore]
37-
protected internal Dictionary<string, string> Tags { get; set; } = new();
37+
public Dictionary<string, string> Tags { get; set; } = new();
3838

3939
/// <summary>
4040
/// Get and set the schema version of a wallet record
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
using System.Drawing;
2+
using LanguageExt;
3+
using Newtonsoft.Json;
4+
using WalletFramework.Core.Json.Converters;
5+
6+
namespace WalletFramework.Core.Colors;
7+
8+
[JsonConverter(typeof(ValueTypeJsonConverter<Color>))]
9+
public readonly struct Color
10+
{
11+
private System.Drawing.Color Value { get; }
12+
13+
private Color(System.Drawing.Color value)
14+
{
15+
Value = value;
16+
}
17+
18+
public override string ToString() => Value.ToHex();
19+
20+
public System.Drawing.Color ToSystemColor() => Value;
21+
22+
public static implicit operator System.Drawing.Color(Color color) => color.Value;
23+
24+
public static implicit operator Color(System.Drawing.Color systemColor) => new(systemColor);
25+
26+
public static implicit operator string(Color color) => color.ToString();
27+
28+
public static Option<Color> OptionColor(string hexStr)
29+
{
30+
try
31+
{
32+
var colorConverter = new ColorConverter();
33+
var systemColor = (System.Drawing.Color)colorConverter.ConvertFromString(hexStr);
34+
return systemColor.ToFrameworkColor();
35+
}
36+
catch (Exception)
37+
{
38+
return Option<Color>.None;
39+
}
40+
}
41+
}
42+
43+
public static class ColorFun
44+
{
45+
public static string ToHex(this System.Drawing.Color systemColor) =>
46+
$"#{systemColor.R:X2}{systemColor.G:X2}{systemColor.B:X2}";
47+
48+
public static Color ToFrameworkColor(this System.Drawing.Color systemColor) => systemColor;
49+
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
using WalletFramework.Core.Credentials.Errors;
2+
using WalletFramework.Core.Functional;
3+
4+
namespace WalletFramework.Core.Credentials;
5+
6+
public readonly struct CredentialId
7+
{
8+
private string Value { get; }
9+
10+
private CredentialId(string value)
11+
{
12+
Value = value;
13+
}
14+
15+
public override string ToString() => Value;
16+
17+
public static implicit operator string(CredentialId credentialId) => credentialId.Value;
18+
19+
public static CredentialId CreateCredentialId()
20+
{
21+
var id = Guid.NewGuid().ToString();
22+
return new CredentialId(id);
23+
}
24+
25+
public static Validation<CredentialId> ValidCredentialId(string id)
26+
{
27+
var isValid = Guid.TryParse(id, out _);
28+
return isValid
29+
? new CredentialId(id)
30+
: new CredentialIdError(id);
31+
}
32+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
using WalletFramework.Core.Functional;
2+
3+
namespace WalletFramework.Core.Credentials.Errors;
4+
5+
public record CredentialIdError(string Value) : Error($"The CredentialId is not a valid GUID, value is: {Value}");

0 commit comments

Comments
 (0)