Skip to content

Commit 1ee62c6

Browse files
authored
Fix Document enumeration for Dictionary types to resolve WebAuthn serialization errors (#3838)
* Fix Document enumeration to handle Dictionary types, resolving WebAuthn serialization errors * Add unit tests for Document enumeration with Dictionary support
1 parent fd822f8 commit 1ee62c6

File tree

3 files changed

+151
-1
lines changed

3 files changed

+151
-1
lines changed
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
{
2+
"core": {
3+
"changeLogMessages": [
4+
"Fixed Document.cs serialization issue that caused WebAuthn operations to fail when response contained Dictionary structures"
5+
],
6+
"type": "patch",
7+
"updateMinimum": true
8+
}
9+
}

sdk/src/Core/Amazon.Runtime/Documents/Document.cs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -285,7 +285,13 @@ public override bool Equals(object obj)
285285
#region Collection Initializers
286286
IEnumerator<Document> IEnumerable<Document>.GetEnumerator()
287287
{
288-
return AsList().GetEnumerator();
288+
if (Type == DocumentType.List)
289+
return AsList().GetEnumerator();
290+
291+
if (Type == DocumentType.Dictionary)
292+
return AsDictionary().Values.GetEnumerator();
293+
294+
return new[]{this}.AsEnumerable().GetEnumerator();
289295
}
290296

291297
IEnumerator IEnumerable.GetEnumerator()

sdk/test/UnitTests/Custom/Runtime/Documents/DocumentTests.cs

Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -267,5 +267,140 @@ private void AssertIsDocumentType(Document doc, DocumentType t)
267267
else
268268
Assert.IsFalse(doc.IsString());
269269
}
270+
271+
/// <summary>
272+
/// Tests that enumerating a Dictionary type Document works correctly
273+
/// This tests the fix for WebAuthn serialization errors
274+
/// </summary>
275+
[TestMethod]
276+
[TestCategory("UnitTest")]
277+
[TestCategory("Runtime")]
278+
public void EnumerateDictionaryDocument()
279+
{
280+
// Create a dictionary document
281+
var doc = new Document
282+
{
283+
{"key1", "value1"},
284+
{"key2", 42},
285+
{"key3", true}
286+
};
287+
288+
// Ensure we can enumerate the document as IEnumerable<Document>
289+
var values = new List<Document>();
290+
foreach (var item in (IEnumerable<Document>)doc)
291+
{
292+
values.Add(item);
293+
}
294+
295+
// Should enumerate dictionary values
296+
Assert.AreEqual(3, values.Count);
297+
Assert.IsTrue(values.Any(v => v.IsString() && v.AsString() == "value1"));
298+
Assert.IsTrue(values.Any(v => v.IsInt() && v.AsInt() == 42));
299+
Assert.IsTrue(values.Any(v => v.IsBool() && v.AsBool() == true));
300+
}
301+
302+
/// <summary>
303+
/// Tests that enumerating a List type Document still works correctly
304+
/// </summary>
305+
[TestMethod]
306+
[TestCategory("UnitTest")]
307+
[TestCategory("Runtime")]
308+
public void EnumerateListDocument()
309+
{
310+
// Create a list document
311+
var doc = new Document("value1", 42, true);
312+
313+
// Ensure we can enumerate the document
314+
var values = new List<Document>();
315+
foreach (var item in (IEnumerable<Document>)doc)
316+
{
317+
values.Add(item);
318+
}
319+
320+
// Should enumerate list items in order
321+
Assert.AreEqual(3, values.Count);
322+
Assert.IsTrue(values[0].IsString() && values[0].AsString() == "value1");
323+
Assert.IsTrue(values[1].IsInt() && values[1].AsInt() == 42);
324+
Assert.IsTrue(values[2].IsBool() && values[2].AsBool() == true);
325+
}
326+
327+
/// <summary>
328+
/// Tests that enumerating non-collection type Documents returns the document itself
329+
/// </summary>
330+
[TestMethod]
331+
[TestCategory("UnitTest")]
332+
[TestCategory("Runtime")]
333+
public void EnumerateNonCollectionDocument()
334+
{
335+
// Test with various non-collection types
336+
var stringDoc = new Document("test");
337+
var intDoc = new Document(42);
338+
var boolDoc = new Document(true);
339+
var nullDoc = new Document();
340+
341+
// Each should enumerate to a single item - itself
342+
var stringValues = ((IEnumerable<Document>)stringDoc).ToList();
343+
Assert.AreEqual(1, stringValues.Count);
344+
Assert.AreEqual(stringDoc, stringValues[0]);
345+
346+
var intValues = ((IEnumerable<Document>)intDoc).ToList();
347+
Assert.AreEqual(1, intValues.Count);
348+
Assert.AreEqual(intDoc, intValues[0]);
349+
350+
var boolValues = ((IEnumerable<Document>)boolDoc).ToList();
351+
Assert.AreEqual(1, boolValues.Count);
352+
Assert.AreEqual(boolDoc, boolValues[0]);
353+
354+
var nullValues = ((IEnumerable<Document>)nullDoc).ToList();
355+
Assert.AreEqual(1, nullValues.Count);
356+
Assert.AreEqual(nullDoc, nullValues[0]);
357+
}
358+
359+
/// <summary>
360+
/// Tests that LINQ operations work correctly on Dictionary documents
361+
/// This specifically tests the WebAuthn scenario
362+
/// </summary>
363+
[TestMethod]
364+
[TestCategory("UnitTest")]
365+
[TestCategory("Runtime")]
366+
public void LinqOperationsOnDictionaryDocument()
367+
{
368+
// Create a complex dictionary document similar to WebAuthn responses
369+
var doc = new Document
370+
{
371+
{"credentialId", "abc123"},
372+
{"publicKey", "key-data"},
373+
{"signCount", 5},
374+
{"userVerified", true},
375+
{"attestationObject", new Document
376+
{
377+
{"fmt", "packed"},
378+
{"authData", "auth-data-bytes"}
379+
}
380+
}
381+
};
382+
383+
// Cast to IEnumerable<Document> to use LINQ operations
384+
var enumerable = (IEnumerable<Document>)doc;
385+
386+
// Test that we can use LINQ operations
387+
var count = enumerable.Count();
388+
Assert.AreEqual(5, count);
389+
390+
// Test FirstOrDefault
391+
var first = enumerable.FirstOrDefault();
392+
Assert.IsNotNull(first);
393+
394+
// Test Any
395+
Assert.IsTrue(enumerable.Any());
396+
397+
// Test Where (filtering)
398+
var stringValues = enumerable.Where(d => d.IsString()).ToList();
399+
Assert.IsTrue(stringValues.Count >= 2); // At least credentialId and publicKey
400+
401+
// Test Select (projection)
402+
var types = enumerable.Select(d => d.Type).ToList();
403+
Assert.AreEqual(5, types.Count);
404+
}
270405
}
271406
}

0 commit comments

Comments
 (0)