From d7e34f301eac2fcec8bffe0f53df0e794676fa8b Mon Sep 17 00:00:00 2001
From: Henrique <999396+hjgraca@users.noreply.github.com>
Date: Tue, 15 Apr 2025 17:12:46 +0100
Subject: [PATCH 01/16] initial commit, added new project and tests
---
libraries/AWS.Lambda.Powertools.sln | 30 ++
.../AWS.Lambda.Powertools.EventHandler.csproj | 19 +
.../AppSyncEvents/AppSyncAuthorizerEvent.cs | 26 +
.../AppSyncEvents/AppSyncAuthorizerResult.cs | 34 ++
.../AppSyncEvents/AppSyncCognitoIdentity.cs | 42 ++
.../AppSyncEvents/AppSyncEventsResolver.cs | 305 ++++++++++++
.../AppSyncEvents/AppSyncIamIdentity.cs | 47 ++
.../AppSyncEvents/AppSyncLambdaIdentity.cs | 13 +
.../AppSyncEvents/AppSyncOidcIdentity.cs | 22 +
.../AppSyncEvents/AppSyncRequestContext.cs | 40 ++
.../AppSyncEvents/AppSyncResolverEvent.cs | 60 +++
.../AppSyncResolverEventsResponse.cs | 11 +
.../AppSyncResolverEventsResult.cs | 19 +
.../AppSyncEvents/Channel.cs | 17 +
.../AppSyncEvents/ChannelNamespace.cs | 9 +
.../AppSyncEvents/Information.cs | 61 +++
.../AppSyncEvents/RequestContext.cs | 17 +
.../Internal/LRUCache.cs | 101 ++++
.../Internal/RouteHandlerOptions.cs | 24 +
.../Internal/RouteHandlerRegistry.cs | 164 +++++++
.../InternalsVisibleTo.cs | 18 +
.../README.md | 1 +
...ambda.Powertools.EventHandler.Tests.csproj | 41 ++
.../AppSyncEventsTests.cs | 449 ++++++++++++++++++
.../RouteHandlerRegistryTests.cs | 228 +++++++++
.../appSyncEventsEvent.json | 76 +++
26 files changed, 1874 insertions(+)
create mode 100644 libraries/src/AWS.Lambda.Powertools.EventHandler/AWS.Lambda.Powertools.EventHandler.csproj
create mode 100644 libraries/src/AWS.Lambda.Powertools.EventHandler/AppSyncEvents/AppSyncAuthorizerEvent.cs
create mode 100644 libraries/src/AWS.Lambda.Powertools.EventHandler/AppSyncEvents/AppSyncAuthorizerResult.cs
create mode 100644 libraries/src/AWS.Lambda.Powertools.EventHandler/AppSyncEvents/AppSyncCognitoIdentity.cs
create mode 100644 libraries/src/AWS.Lambda.Powertools.EventHandler/AppSyncEvents/AppSyncEventsResolver.cs
create mode 100644 libraries/src/AWS.Lambda.Powertools.EventHandler/AppSyncEvents/AppSyncIamIdentity.cs
create mode 100644 libraries/src/AWS.Lambda.Powertools.EventHandler/AppSyncEvents/AppSyncLambdaIdentity.cs
create mode 100644 libraries/src/AWS.Lambda.Powertools.EventHandler/AppSyncEvents/AppSyncOidcIdentity.cs
create mode 100644 libraries/src/AWS.Lambda.Powertools.EventHandler/AppSyncEvents/AppSyncRequestContext.cs
create mode 100644 libraries/src/AWS.Lambda.Powertools.EventHandler/AppSyncEvents/AppSyncResolverEvent.cs
create mode 100644 libraries/src/AWS.Lambda.Powertools.EventHandler/AppSyncEvents/AppSyncResolverEventsResponse.cs
create mode 100644 libraries/src/AWS.Lambda.Powertools.EventHandler/AppSyncEvents/AppSyncResolverEventsResult.cs
create mode 100644 libraries/src/AWS.Lambda.Powertools.EventHandler/AppSyncEvents/Channel.cs
create mode 100644 libraries/src/AWS.Lambda.Powertools.EventHandler/AppSyncEvents/ChannelNamespace.cs
create mode 100644 libraries/src/AWS.Lambda.Powertools.EventHandler/AppSyncEvents/Information.cs
create mode 100644 libraries/src/AWS.Lambda.Powertools.EventHandler/AppSyncEvents/RequestContext.cs
create mode 100644 libraries/src/AWS.Lambda.Powertools.EventHandler/Internal/LRUCache.cs
create mode 100644 libraries/src/AWS.Lambda.Powertools.EventHandler/Internal/RouteHandlerOptions.cs
create mode 100644 libraries/src/AWS.Lambda.Powertools.EventHandler/Internal/RouteHandlerRegistry.cs
create mode 100644 libraries/src/AWS.Lambda.Powertools.EventHandler/InternalsVisibleTo.cs
create mode 100644 libraries/src/AWS.Lambda.Powertools.EventHandler/README.md
create mode 100644 libraries/tests/AWS.Lambda.Powertools.EventHandler.Tests/AWS.Lambda.Powertools.EventHandler.Tests.csproj
create mode 100644 libraries/tests/AWS.Lambda.Powertools.EventHandler.Tests/AppSyncEventsTests.cs
create mode 100644 libraries/tests/AWS.Lambda.Powertools.EventHandler.Tests/RouteHandlerRegistryTests.cs
create mode 100644 libraries/tests/AWS.Lambda.Powertools.EventHandler.Tests/appSyncEventsEvent.json
diff --git a/libraries/AWS.Lambda.Powertools.sln b/libraries/AWS.Lambda.Powertools.sln
index 07122c3a..5d7cd4f9 100644
--- a/libraries/AWS.Lambda.Powertools.sln
+++ b/libraries/AWS.Lambda.Powertools.sln
@@ -105,6 +105,10 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Metrics", "Metrics", "{A566
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AOT-Function-ILogger", "tests\e2e\functions\core\logging\AOT-Function-ILogger\src\AOT-Function-ILogger\AOT-Function-ILogger.csproj", "{7FC6DD65-0352-4139-8D08-B25C0A0403E3}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AWS.Lambda.Powertools.EventHandler.Tests", "tests\AWS.Lambda.Powertools.EventHandler.Tests\AWS.Lambda.Powertools.EventHandler.Tests.csproj", "{61374D8E-F77C-4A31-AE07-35DAF1847369}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AWS.Lambda.Powertools.EventHandler", "src\AWS.Lambda.Powertools.EventHandler\AWS.Lambda.Powertools.EventHandler.csproj", "{F4B8D5AF-D3CA-4910-A14D-E5BAEF0FD1DE}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -562,6 +566,30 @@ Global
{7FC6DD65-0352-4139-8D08-B25C0A0403E3}.Release|x64.Build.0 = Release|Any CPU
{7FC6DD65-0352-4139-8D08-B25C0A0403E3}.Release|x86.ActiveCfg = Release|Any CPU
{7FC6DD65-0352-4139-8D08-B25C0A0403E3}.Release|x86.Build.0 = Release|Any CPU
+ {61374D8E-F77C-4A31-AE07-35DAF1847369}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {61374D8E-F77C-4A31-AE07-35DAF1847369}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {61374D8E-F77C-4A31-AE07-35DAF1847369}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {61374D8E-F77C-4A31-AE07-35DAF1847369}.Debug|x64.Build.0 = Debug|Any CPU
+ {61374D8E-F77C-4A31-AE07-35DAF1847369}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {61374D8E-F77C-4A31-AE07-35DAF1847369}.Debug|x86.Build.0 = Debug|Any CPU
+ {61374D8E-F77C-4A31-AE07-35DAF1847369}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {61374D8E-F77C-4A31-AE07-35DAF1847369}.Release|Any CPU.Build.0 = Release|Any CPU
+ {61374D8E-F77C-4A31-AE07-35DAF1847369}.Release|x64.ActiveCfg = Release|Any CPU
+ {61374D8E-F77C-4A31-AE07-35DAF1847369}.Release|x64.Build.0 = Release|Any CPU
+ {61374D8E-F77C-4A31-AE07-35DAF1847369}.Release|x86.ActiveCfg = Release|Any CPU
+ {61374D8E-F77C-4A31-AE07-35DAF1847369}.Release|x86.Build.0 = Release|Any CPU
+ {F4B8D5AF-D3CA-4910-A14D-E5BAEF0FD1DE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {F4B8D5AF-D3CA-4910-A14D-E5BAEF0FD1DE}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {F4B8D5AF-D3CA-4910-A14D-E5BAEF0FD1DE}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {F4B8D5AF-D3CA-4910-A14D-E5BAEF0FD1DE}.Debug|x64.Build.0 = Debug|Any CPU
+ {F4B8D5AF-D3CA-4910-A14D-E5BAEF0FD1DE}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {F4B8D5AF-D3CA-4910-A14D-E5BAEF0FD1DE}.Debug|x86.Build.0 = Debug|Any CPU
+ {F4B8D5AF-D3CA-4910-A14D-E5BAEF0FD1DE}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {F4B8D5AF-D3CA-4910-A14D-E5BAEF0FD1DE}.Release|Any CPU.Build.0 = Release|Any CPU
+ {F4B8D5AF-D3CA-4910-A14D-E5BAEF0FD1DE}.Release|x64.ActiveCfg = Release|Any CPU
+ {F4B8D5AF-D3CA-4910-A14D-E5BAEF0FD1DE}.Release|x64.Build.0 = Release|Any CPU
+ {F4B8D5AF-D3CA-4910-A14D-E5BAEF0FD1DE}.Release|x86.ActiveCfg = Release|Any CPU
+ {F4B8D5AF-D3CA-4910-A14D-E5BAEF0FD1DE}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
@@ -611,5 +639,7 @@ Global
{F8F80477-1EAD-4C5C-A329-CBC0A60C7CAB} = {A566F2D7-F8FE-466A-8306-85F266B7E656}
{A422C742-2CF9-409D-BDAE-15825AB62113} = {A566F2D7-F8FE-466A-8306-85F266B7E656}
{7FC6DD65-0352-4139-8D08-B25C0A0403E3} = {4EAB66F9-C9CB-4E8A-BEE6-A14CD7FDE02F}
+ {61374D8E-F77C-4A31-AE07-35DAF1847369} = {1CFF5568-8486-475F-81F6-06105C437528}
+ {F4B8D5AF-D3CA-4910-A14D-E5BAEF0FD1DE} = {73C9B1E5-3893-47E8-B373-17E5F5D7E6F5}
EndGlobalSection
EndGlobal
diff --git a/libraries/src/AWS.Lambda.Powertools.EventHandler/AWS.Lambda.Powertools.EventHandler.csproj b/libraries/src/AWS.Lambda.Powertools.EventHandler/AWS.Lambda.Powertools.EventHandler.csproj
new file mode 100644
index 00000000..7c281eff
--- /dev/null
+++ b/libraries/src/AWS.Lambda.Powertools.EventHandler/AWS.Lambda.Powertools.EventHandler.csproj
@@ -0,0 +1,19 @@
+
+
+
+
+ AWS.Lambda.Powertools.EventHandler
+ Powertools for AWS Lambda (.NET) - Event Handler package.
+ AWS.Lambda.Powertools.EventHandler
+ AWS.Lambda.Powertools.EventHandler
+ net8.0
+ false
+ enable
+ enable
+
+
+
+
+
+
+
diff --git a/libraries/src/AWS.Lambda.Powertools.EventHandler/AppSyncEvents/AppSyncAuthorizerEvent.cs b/libraries/src/AWS.Lambda.Powertools.EventHandler/AppSyncEvents/AppSyncAuthorizerEvent.cs
new file mode 100644
index 00000000..7bc29f7b
--- /dev/null
+++ b/libraries/src/AWS.Lambda.Powertools.EventHandler/AppSyncEvents/AppSyncAuthorizerEvent.cs
@@ -0,0 +1,26 @@
+namespace AWS.Lambda.Powertools.EventHandler.AppSyncEvents;
+
+///
+/// Represents an AWS AppSync authorization event that is sent to a Lambda authorizer
+/// for evaluating access permissions to the GraphQL API.
+///
+public class AppSyncAuthorizerEvent
+{
+ ///
+ /// Gets or sets the authorization token received from the client request.
+ /// This token is used to make authorization decisions.
+ ///
+ public string AuthorizationToken { get; set; }
+
+ ///
+ /// Gets or sets the headers from the client request.
+ /// Contains key-value pairs of HTTP header names and their values.
+ ///
+ public Dictionary RequestHeaders { get; set; }
+
+ ///
+ /// Gets or sets the context information about the AppSync request.
+ /// Contains metadata about the API and the GraphQL operation being executed.
+ ///
+ public AppSyncRequestContext RequestContext { get; set; }
+}
\ No newline at end of file
diff --git a/libraries/src/AWS.Lambda.Powertools.EventHandler/AppSyncEvents/AppSyncAuthorizerResult.cs b/libraries/src/AWS.Lambda.Powertools.EventHandler/AppSyncEvents/AppSyncAuthorizerResult.cs
new file mode 100644
index 00000000..642c64b3
--- /dev/null
+++ b/libraries/src/AWS.Lambda.Powertools.EventHandler/AppSyncEvents/AppSyncAuthorizerResult.cs
@@ -0,0 +1,34 @@
+using System.Text.Json.Serialization;
+
+namespace AWS.Lambda.Powertools.EventHandler.AppSyncEvents;
+
+///
+/// Represents the authorization result returned by a Lambda authorizer to AWS AppSync
+/// containing authorization decisions and optional context for the GraphQL API.
+///
+public class AppSyncAuthorizerResult
+{
+ ///
+ /// Indicates if the request is authorized
+ ///
+ [JsonPropertyName("isAuthorized")]
+ public bool IsAuthorized { get; set; }
+
+ ///
+ /// Custom context to pass to resolvers, only supports key-value pairs.
+ ///
+ [JsonPropertyName("resolverContext")]
+ public Dictionary ResolverContext { get; set; }
+
+ ///
+ /// List of fields that are denied access
+ ///
+ [JsonPropertyName("deniedFields")]
+ public IEnumerable DeniedFields { get; set; }
+
+ ///
+ /// The number of seconds that the response should be cached for
+ ///
+ [JsonPropertyName("ttlOverride")]
+ public int? TtlOverride { get; set; }
+}
\ No newline at end of file
diff --git a/libraries/src/AWS.Lambda.Powertools.EventHandler/AppSyncEvents/AppSyncCognitoIdentity.cs b/libraries/src/AWS.Lambda.Powertools.EventHandler/AppSyncEvents/AppSyncCognitoIdentity.cs
new file mode 100644
index 00000000..51ef1ed6
--- /dev/null
+++ b/libraries/src/AWS.Lambda.Powertools.EventHandler/AppSyncEvents/AppSyncCognitoIdentity.cs
@@ -0,0 +1,42 @@
+namespace AWS.Lambda.Powertools.EventHandler.AppSyncEvents;
+
+///
+/// Represents Amazon Cognito User Pools authorization identity for AppSync
+///
+public class AppSyncCognitoIdentity
+{
+ ///
+ /// The source IP address of the caller received by AWS AppSync
+ ///
+ public List SourceIp { get; set; }
+
+ ///
+ /// The username of the authenticated user
+ ///
+ public string Username { get; set; }
+
+ ///
+ /// The UUID of the authenticated user
+ ///
+ public string Sub { get; set; }
+
+ ///
+ /// The claims that the user has
+ ///
+ public Dictionary Claims { get; set; }
+
+ ///
+ /// The default authorization strategy for this caller (ALLOW or DENY)
+ ///
+ public string DefaultAuthStrategy { get; set; }
+
+ ///
+ /// List of OIDC groups
+ ///
+ public List Groups { get; set; }
+
+ ///
+ /// The token issuer
+ ///
+ public string Issuer { get; set; }
+}
\ No newline at end of file
diff --git a/libraries/src/AWS.Lambda.Powertools.EventHandler/AppSyncEvents/AppSyncEventsResolver.cs b/libraries/src/AWS.Lambda.Powertools.EventHandler/AppSyncEvents/AppSyncEventsResolver.cs
new file mode 100644
index 00000000..180f9b59
--- /dev/null
+++ b/libraries/src/AWS.Lambda.Powertools.EventHandler/AppSyncEvents/AppSyncEventsResolver.cs
@@ -0,0 +1,305 @@
+using System.Text.RegularExpressions;
+using Amazon.Lambda.Core;
+using AWS.Lambda.Powertools.EventHandler.Internal;
+
+namespace AWS.Lambda.Powertools.EventHandler.AppSyncEvents;
+
+///
+/// Resolver for AWS AppSync Events APIs.
+/// Handles onPublish and onSubscribe events from AppSync Events APIs,
+/// routing them to appropriate handlers based on path.
+///
+public class AppSyncEventsResolver
+{
+ private readonly RouteHandlerRegistry _publishRoutes;
+ private readonly RouteHandlerRegistry _subscribeRoutes;
+
+ public AppSyncEventsResolver()
+ {
+ _publishRoutes = new RouteHandlerRegistry();
+ _subscribeRoutes = new RouteHandlerRegistry();
+ }
+
+
+ ///
+ /// Registers a handler for publish events on a specific channel path
+ /// Processes each event in the payload individually
+ ///
+ public AppSyncEventsResolver OnPublish(string path, Func, Task