/* * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"). * You may not use this file except in compliance with the License. * A copy of the License is located at * * http://aws.amazon.com/apache2.0 * * or in the "license" file accompanying this file. This file is distributed * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either * express or implied. See the License for the specific language governing * permissions and limitations under the License. */ using System; using System.Collections.Generic; using System.Globalization; using System.IO; using System.Linq; using System.Reflection; using System.Threading; using Amazon.CognitoIdentity; using Amazon.CognitoSync.Model; using Amazon.CognitoSync.Model.Internal.MarshallTransformations; using Amazon.Runtime; using Amazon.Runtime.Internal; using Amazon.Runtime.Internal.Auth; using Amazon.Runtime.Internal.Transform; using Amazon.Runtime.Internal.Util; using Amazon.Util.Internal; namespace Amazon.CognitoSync.Internal { /// /// This handler overrides the base CredentialsRetriever which is removed from the pipeline. When /// the service client is using the CognitoAWSCredentials credentials object it makes sure that all /// CognitoSync calls have the latest identity id and identity pool id. /// public class CognitoCredentialsRetriever : CredentialsRetriever { /// /// Construct an instance of CognitoCredentialsRetriever /// /// public CognitoCredentialsRetriever(AWSCredentials credentials) : base(credentials) { } #if BCL /// /// Custom pipeline handler /// /// protected override void PreInvoke(IExecutionContext executionContext) { base.PreInvoke(executionContext); // Only configure IdentityPoolId and IdentityId when using CognitoAWSCredentials var cognitoCredentials = Credentials as CognitoAWSCredentials; if (cognitoCredentials != null) { SetIdentity(executionContext, cognitoCredentials.GetIdentityId(), cognitoCredentials.IdentityPoolId); } } #elif AWS_ASYNC_API public override async System.Threading.Tasks.Task InvokeAsync(IExecutionContext executionContext) { T result = await base.InvokeAsync(executionContext).ConfigureAwait(false); // Only configure IdentityPoolId and IdentityId when using CognitoAWSCredentials var cognitoCredentials = Credentials as CognitoAWSCredentials; if (cognitoCredentials != null) { string identityId = await cognitoCredentials.GetIdentityIdAsync().ConfigureAwait(false); SetIdentity(executionContext, identityId, cognitoCredentials.IdentityPoolId); } return result; } #endif private static void SetIdentity(IExecutionContext executionContext, string identityId, string identityPoolId) { var request = executionContext.RequestContext.OriginalRequest; var syncRequest = request as AmazonCognitoSyncRequest; if (syncRequest != null) { // Set the IdentityId and IdentityPoolId fields on the request. CSRequestCache.SetFields(syncRequest, identityPoolId, identityId); } } /// /// A cache of objects that store the reflection objects. This is done so that reflection is only used once in order to /// set the fields on the request. /// private static class CSRequestCache { /// /// This class holds on to the reflection objects to invoke the setters for IdentityId and IdentityPoolId for the given type. /// private class CSRequest { private ITypeInfo requestType; private PropertyInfo identityPoolIdProperty; private PropertyInfo identityIdProperty; public static ITypeInfo SyncRequestType = TypeFactory.GetTypeInfo(typeof(AmazonCognitoSyncRequest)); public CSRequest(Type requestType) { this.requestType = TypeFactory.GetTypeInfo(requestType); if (!SyncRequestType.IsAssignableFrom(this.requestType)) throw new InvalidOperationException(string.Format(CultureInfo.InvariantCulture, "Unable to assign {0} from {1}", SyncRequestType.FullName, requestType.FullName)); this.identityIdProperty = this.requestType.GetProperty("IdentityId"); this.identityPoolIdProperty = this.requestType.GetProperty("IdentityPoolId"); } public void SetFields(AmazonCognitoSyncRequest request, string identityPoolId, string identityId) { if (identityIdProperty != null) identityIdProperty.SetValue(request, identityId, null); if (identityPoolIdProperty != null) identityPoolIdProperty.SetValue(request, identityPoolId, null); } } private static Dictionary requestCache = new Dictionary(); static CSRequestCache() { PopulateCache(); } private static void PopulateCache() { var sourceAssembly = CSRequest.SyncRequestType.Assembly; var allTypes = sourceAssembly.GetTypes(); // Look up all CognitoSync request objects for caching. foreach (var type in allTypes) { var typeInfo = TypeFactory.GetTypeInfo(type); if (CSRequest.SyncRequestType.IsAssignableFrom(typeInfo) && !typeInfo.Equals(CSRequest.SyncRequestType)) { var csRequest = new CSRequest(type); requestCache[type] = csRequest; } } } /// /// Set the IdentityId and IdentityPoolId properties on the request object /// /// /// /// public static void SetFields(AmazonCognitoSyncRequest request, string identityPoolId, string identityId) { Type requestType = request.GetType(); CSRequest csRequest; if (requestCache.TryGetValue(requestType, out csRequest)) { csRequest.SetFields(request, identityPoolId, identityId); } } } } }