using System;
using System.Collections.Generic;
using System.IdentityModel.Tokens.Jwt;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using Microsoft.IdentityModel.Tokens;
using xCommons.Extensions;
using xCommons.Helpers;
using xExceptions.Constants;
using xIdentityModels;
using xIdentityModels.Constants;
using xIdentityModels.Extensions;
using xIdentityModels.Models;
using xIdentityModels.Navigations;
namespace xIds.Providers
{
public partial class XIdentityManager
{
//
#region Token Actions ...
///
/// Check a Token Entity Exists or not
///
/// an instance of XDevice
/// specifies Action Step by a member of XAction
/// a boolean value
private async Task IsTokenExistsByDeviceAndType(
XDevice device,
XAction type
)
{
//
ValidationProvider.NotNull(device);
//
var isExists = false;
var enumerator = DbContext.Tokens.AsAsyncEnumerable();
await
foreach (var token in enumerator)
{
//
if (token.Type == type &&
token.Device.IsSameAs(device))
{
isExists = true;
break;
}
}
//
return isExists;
}
///
/// Check a Token Entity Exists or not
///
/// specified user's identifier
/// specifies Action Step by a member of XAction
/// a boolean value
private async Task IsTokenExistsByUserAndType(
string userSelectByParam,
XAction type
)
{
//
ValidationProvider.NotEmpty(userSelectByParam);
//
var isExists = false;
var tokensEnumerator = DbContext.Tokens.AsAsyncEnumerable();
await
foreach (var token in tokensEnumerator)
{
//
if (token.Type == type &&
token.UserSelectByParam
.ToNormalString() == userSelectByParam
.ToNormalString())
{
//
isExists = true;
break;
}
}
//
return isExists;
}
///
/// Check a Token Entity Exists or not
///
/// represent specified action token
/// a boolean value
private async Task IsTokenExistsByToken(
string token
)
{
//
var result = await DbContext.Tokens
.AnyAsync(xt => xt.Token == token);
//
return result;
}
///
/// Check a Token Entity Exists or not
///
/// represent specified action token hash
/// a boolean value
private async Task IsTokenExistsByHash(
string hash
)
{
//
var result = await DbContext.Tokens
.AnyAsync(xt => xt.Hash == hash);
//
return result;
}
///
/// Check a Token Entity Exists or not
///
/// an instance of XToken
/// a boolean value
private async Task IsTokenExistsByToken(
XToken item
)
{
//
var result = false;
var tokenEnumerator = DbContext.Tokens
.AsAsyncEnumerable();
await
foreach (var token in tokenEnumerator)
{
//
if (token.Hash == item.Hash &&
token.Token == item.Token &&
token.Type == item.Type &&
token.UserSelectByParam
.ToNormalString() == item.UserSelectByParam
.ToNormalString() &&
token.Device.IsSameAs(item.Device))
{
//
result = true;
break;
}
}
//
return result;
}
///
/// Check a Token Entity Exists or not
///
/// specifies token id
/// a boolean value
private async Task IsTokenExistsById(
int id
)
{
return await DbContext.Tokens.AnyAsync(t => t.Id == id);
}
///
/// Retrieve Token Entity
///
/// an instance of XDevice
/// specifies Action Step by a member of XAction
/// an instance of XToken
private async Task GetTokenByDeviceAndType(
XDevice device,
XAction type
)
{
//
var isExists = await IsTokenExistsByDeviceAndType(device, type);
if (!isExists)
{
return null;
}
//
XToken item = null;
var enumerator = DbContext.Tokens.AsAsyncEnumerable();
await
foreach (var token in enumerator)
{
//
if (token.Type == type &&
token.Device.IsSameAs(device))
{
//
item = token;
break;
}
}
//
return item;
}
///
/// Retrieve Token Entity
///
/// specified user's identifier
/// specifies Action Step by a member of XAction
/// an instance of XToken
private async Task GetTokenByUserAndType(
string userSelectByParam,
XAction type
)
{
//
var isExists = await IsTokenExistsByUserAndType(userSelectByParam, type);
if (!isExists)
{
return null;
}
//
XToken item = null;
var enumerator = DbContext.Tokens.AsAsyncEnumerable();
await
foreach (var token in enumerator)
{
//
if (token.Type == type &&
token.UserSelectByParam
.ToNormalString() == userSelectByParam
.ToNormalString())
{
//
item = token;
break;
}
}
//
return item;
}
///
/// Retrieve a Token Entity
///
/// represent specified action token
/// an instance of XToken
private async Task GetTokenByToken(
string token
)
{
//
var isExists = await IsTokenExistsByToken(token);
if (!isExists)
{
return null;
}
//
var result = await DbContext.Tokens
.FirstOrDefaultAsync(xt => xt.Token == token);
//
return result;
}
///
/// Retrieve Related Hash to a Token
///
/// represent specified action token
/// hash string
private async Task GetRelatedHashByToken(
string token
)
{
//
var item = await GetTokenByToken(token);
if (item == null)
{
return null;
}
//
return item.Hash;
}
///
/// Retrieve a Token Entity
///
/// represent specified action token hash
/// an instance of XToken
private async Task GetTokenByHash(
string hash
)
{
//
// Validate Args ...
ValidationProvider.NotEmpty(hash);
//
var isExists = await IsTokenExistsByHash(hash);
if (!isExists)
{
return null;
}
//
var item = await DbContext.Tokens
.FirstOrDefaultAsync(t => t.Hash == hash);
//
return item;
}
///
/// Retrieve Related Token to a Hash string
///
/// represent specified action token hash
/// token string
private async Task GetRelatedTokenByHash(
string hash
)
{
//
var item = await GetTokenByHash(hash);
if (item == null)
{
return null;
}
//
return item.Token;
}
///
/// Retrieve a Token Expiration Date
///
/// represent specified action token
/// an instance of DateTime
private DateTime GetTokenExpirationDate(
string token
)
{
//
ValidationProvider.NotEmpty(token);
//
var result = IdentityHelper.GetTokenExpirationDate(token);
//
return result;
}
///
/// Remove a Token Entity
///
/// represent specified action token
///
private async Task RemoveTokenByToken(
string token
)
{
//
// Validate Args ...
ValidationProvider.NotEmpty(token);
//
var isExists = await IsTokenExistsByToken(token);
if (!isExists)
{
return;
}
//
var item = await GetTokenByToken(token);
if (item == null)
{
return;
}
//
DbContext.Tokens.Remove(item);
await DbContext.SaveChangesAsync();
}
///
/// Remove a Token Entity
///
/// represent specified action token hash
///
private async Task RemoveTokenByHash(
string hash
)
{
//
// Validate Args ...
ValidationProvider.NotEmpty(hash);
//
var isExists = await IsTokenExistsByHash(hash);
if (!isExists)
{
return;
}
//
var item = await GetTokenByHash(hash);
if (item == null)
{
return;
}
//
DbContext.Tokens.Remove(item);
await DbContext.SaveChangesAsync();
}
///
/// Remove a Token Entity
///
/// an instance of XDevice
///
private async Task RemoveTokenByDevice(
XDevice device
)
{
//
// Validate Args ...
ValidationProvider.NotNull(device);
//
XToken items = null;
var enumerator = DbContext.Tokens.AsAsyncEnumerable();
await
foreach (var token in enumerator)
{
//
if (token.Device.IsSameAs(device))
{
//
items = token;
break;
}
}
//
if (!items.IsNull())
{
DbContext.Tokens.RemoveRange(items);
await DbContext.SaveChangesAsync();
}
}
///
/// add a token Entity
///
/// an instance of XToken
/// an instance of XToken
private async Task AddTokenAsync(
XToken item
)
{
//
var isExist = await IsTokenExistsByToken(item);
if (isExist)
{
return await GetTokenByHash(item.Hash);
}
//
var entry = await DbContext.Tokens.AddAsync(item);
await DbContext.SaveChangesAsync();
//
return entry.Entity;
}
///
/// Hash a Request Token
///
/// an instance of XActionRequestToken
///
///
/// an instance of XToken
private async Task HashRequest(
XActionRequestToken request,
bool forceNotNullUserSelectByParam = true,
bool forceDeviceNotNull = true
)
{
//
// Validate Args ...
var secretKey = Configuration.IdentitySecretKey;
ValidationProvider.NotNull(request);
ValidationProvider.NotEmpty(secretKey);
//
ValidateActionRequest(request);
//
var type = request.Action;
var device = request.Context.Device;
var tokenObject = ToSecurityToken(request);
var tokenString = ToTokenString(tokenObject);
var tokenHash = ToHash(tokenString);
var userSelectByParam = GetUserSelectByParam(request, forceNotNullUserSelectByParam);
//
if (forceNotNullUserSelectByParam)
{
ValidationProvider.NotEmpty(userSelectByParam);
}
//
ValidationProvider.NotEmpty(tokenString, tokenHash);
//
if (forceDeviceNotNull)
{
ValidationProvider.NotNull(device);
}
//
ValidationProvider.NotNull(tokenObject);
//
var xToken = new XToken
{
Type = type,
Device = device,
Hash = tokenHash,
Token = tokenString,
UserSelectByParam = userSelectByParam
};
//
var addedToken = await AddTokenAsync(xToken);
//
return addedToken;
}
///
/// Generate Token Hash string
///
/// represent specified action token
/// check token validation parameters, default is true
/// hash string
private string ToHash(
string token,
bool checkValidation = true
)
{
//
ValidationProvider.NotEmpty(token);
//
if (checkValidation)
{
ValidateToken(token);
}
//
var result = token.ToMd5String().ToNormalString();
//
return result;
}
///
/// Generate Token string
///
/// represent specified action token
/// token string
private string ToTokenString(
SecurityToken token
)
{
//
ValidationProvider.NotNull(token, IdentityHelper);
//
var result = IdentityHelper.ToTokenString(token);
//
return result;
}
///
/// Generate Token string
///
/// represent specified action token
/// token string
private string ToTokenString(
JwtSecurityToken token
)
{
//
ValidationProvider.NotNull(token, IdentityHelper);
//
var result = IdentityHelper.ToTokenString(token);
//
return result;
}
///
/// Generate Security Token
///
/// represent specified action token
/// an instance of SecurityToken
private SecurityToken ToSecurityToken(
string token
)
{
//
ValidationProvider.NotEmpty(token);
//
var result = IdentityHelper.ToSecurityToken(token);
//
return result;
}
///
/// Generate Security Token
///
/// an instance of XActionRequestToken
/// an instance of SecurityToken
private SecurityToken ToSecurityToken(
XActionRequestToken request
)
{
//
ValidationProvider.NotNull(request);
//
ValidateActionRequest(request);
//
var result = IdentityHelper.ToSecurityToken(request);
if (result == null)
{
XException.InvalidToken.Throw();
}
//
return result;
}
///
/// Cleanup all exists tokens related to specified User
///
/// specified user's identifier
///
private async Task HandleRemoveExistsTokens(
string userSelectByParam
)
{
//
// Validate Args ...
ValidationProvider.NotEmpty(userSelectByParam);
//
var xTokens = new List();
var xTokenEnumerator = DbContext.Tokens.AsAsyncEnumerable();
await
foreach (var xToken in xTokenEnumerator)
{
//
if (xToken.UserSelectByParam == userSelectByParam &&
ObjectHelper.ToEnumerableValues().Contains(xToken.Type))
{
xTokens.Add(xToken);
}
}
//
if (xTokens.HasChild())
{
DbContext.Tokens.RemoveRange(xTokens);
await DbContext.SaveChangesAsync();
}
}
///
/// Cleanup all tokens related to specified User
///
/// a collection of user identifiers
///
private async Task HandleCleanUserTokens(
ICollection userSelectByParams
)
{
//
// Validate Args ...
if (!userSelectByParams.HasChild())
{
return;
}
//
foreach (var userSelectByParam in userSelectByParams)
{
await HandleRemoveExistsTokens(userSelectByParam);
}
}
///
/// Cleanup all tokens related to specified User
///
/// an instance of XUser
///
private async Task HandleCleanUserTokens(
XUser user
)
{
//
if (user == null)
{
return;
}
//
var userSelectByParams = GenerateUserSelectByParams(user);
//
await HandleCleanUserTokens(userSelectByParams);
}
#endregion
}
}