using System;
using System.Collections.Generic;
using System.Net;
using System.Threading.Tasks;
using Amazon.CognitoIdentityProvider;
using Amazon.CognitoIdentityProvider.Model;
using Amazon.Runtime;
using RMC.Core.Exceptions;
using UnityEngine;
#pragma warning disable CS1998 // async/await
namespace RMC.Backend.Baas.Aws
{
// Class Attributes ----------------------------------
///
/// Backend subsystem related to
///
public class JawsAccountsSubsystem : IAccountsSubsystem
{
// Events ----------------------------------------
public AccountsEvent OnInitialized { get; } = new AccountsEvent();
public AccountsEvent OnUserCreated { get; } = new AccountsEvent();
public AccountsEvent OnUserDeleted { get; } = new AccountsEvent();
public AccountsEvent OnUserSignedIn { get; } = new AccountsEvent();
public AccountsEvent OnUserSignedOut { get; } = new AccountsEvent();
// Properties ------------------------------------
public bool IsInitialized { get { return _isInitialized; }}
public Configuration Configuration { get { return _configuration; }}
///
/// Provide RAW access to power users
///
public AmazonCognitoIdentityProviderClient RawAmazonAmazonCognitoIdentityProviderClient
{
get
{
RequireIsInitialized();
RequireConfiguration();
return _amazonCognitoIdentityProviderClient;
}
}
// Fields ----------------------------------------
private bool _isInitialized = false;
private User _user = null;
private JawsConfiguration _configuration;
private AmazonCognitoIdentityProviderClient _amazonCognitoIdentityProviderClient;
// Initialization --------------------------------
public JawsAccountsSubsystem()
{
}
public Task InitializeAsync()
{
if (_isInitialized)
{
return Task.CompletedTask;
}
_configuration = Resources.Load("JawsConfiguration");
RequireConfiguration();
_amazonCognitoIdentityProviderClient = new AmazonCognitoIdentityProviderClient
(
new AnonymousAWSCredentials(),
_configuration.RegionEndpoint
);
_isInitialized = true;
OnInitialized.Invoke(this);
return Task.CompletedTask;
}
public void RequireIsInitialized()
{
if (!IsInitialized)
{
throw new NotInitializedException(this);
}
}
public void RequireConfiguration()
{
if (_configuration == null)
{
throw new Exception("RequireConfiguration() failed. Configuration must exist.");
}
if (!_configuration.IsValid())
{
throw new Exception("RequireConfiguration() failed. Configuration.IsValid() must be true.");
}
}
// Methods ---------------------------------------
public bool HasUser()
{
RequireIsInitialized();
return _user != null;
}
public User GetUser()
{
RequireIsInitialized();
return _user;
}
public async Task UserCreateAsync(string email, string password, string nickname)
{
RequireIsInitialized();
RequireConfiguration();
UserCreateResponse response = new UserCreateResponse();
if (HasUser())
{
response.IsSuccess = false;
response.ErrorMessage = $"SignUpAsync() failed. HasUser must not be '{HasUser()}'.";
Debug.LogError($"{response.ErrorMessage}");
return response;
}
var nicknameAttrs = new AttributeType
{
//Generally Optional. Required here. I chose to add this in the Amazon AWS console.
Name = "nickname",
Value = nickname,
};
var versionAttrs = new AttributeType
{
//Generally Optional. Required here. I chose to add this in the Amazon AWS console.
Name = "custom:app_version",
Value = "0.0.1",
};
var userAttrsList = new List();
userAttrsList.Add(nicknameAttrs);
userAttrsList.Add(versionAttrs);
var signUpRequest = new SignUpRequest
{
UserAttributes = userAttrsList,
Username = email,
ClientId = _configuration.ClientId,
Password = password
};
try
{
SignUpResponse signUpResponse = await _amazonCognitoIdentityProviderClient.SignUpAsync(signUpRequest);
response.RawResponse = signUpResponse;
bool isSuccess = signUpResponse.HttpStatusCode == HttpStatusCode.OK;
response.IsSuccess = isSuccess;
}
catch (Exception e)
{
response.ErrorMessage = $"{e.Message}";
}
OnUserCreated.Invoke(this);
return response;
}
public async Task UserSignInAsync(string email, string password)
{
RequireIsInitialized();
RequireConfiguration();
UserSignInResponse response = new UserSignInResponse();
if (string.IsNullOrEmpty(email) || string.IsNullOrEmpty(password))
{
response.IsSuccess = false;
response.ErrorMessage = $"Bad parameters. Details...";
Debug.LogError($"{response.ErrorMessage}");
return response;
}
var authParameters = new Dictionary();
authParameters.Add("USERNAME", email);
authParameters.Add("PASSWORD", password);
var authRequest = new InitiateAuthRequest
{
ClientId = _configuration.ClientId,
AuthParameters = authParameters,
AuthFlow = AuthFlowType.USER_PASSWORD_AUTH,
};
try
{
InitiateAuthResponse initiateAuthResponse = await _amazonCognitoIdentityProviderClient.InitiateAuthAsync(authRequest);
response.RawResponse = initiateAuthResponse;
response.AccessToken = initiateAuthResponse.AuthenticationResult.AccessToken;
response.IdToken = initiateAuthResponse.AuthenticationResult.IdToken;
response.IsSuccess = true;
_user = new User(email, response.IdToken, response.AccessToken );
}
catch (Exception e)
{
response.IsSuccess = false;
response.ErrorMessage = e.Message;
}
OnUserSignedIn.Invoke(this);
return response;
}
public async Task UserSignOutAsync(string accessToken)
{
RequireIsInitialized();
RequireConfiguration();
UserSignOutResponse response = new UserSignOutResponse();
if (string.IsNullOrEmpty(accessToken))
{
response.IsSuccess = false;
response.ErrorMessage = $"Bad parameters. Details...";
Debug.LogError($"{response.ErrorMessage}");
return response;
}
var signOutRequest = new GlobalSignOutRequest
{
AccessToken = accessToken
};
try
{
GlobalSignOutResponse globalSignOutResponse = await _amazonCognitoIdentityProviderClient.GlobalSignOutAsync(signOutRequest);
response.RawResponse = globalSignOutResponse;
response.IsSuccess = true;
_user = null;
}
catch (Exception e)
{
response.IsSuccess = false;
response.ErrorMessage = e.Message;
}
OnUserSignedOut.Invoke(this);
return response;
}
}
}