Initial ...
This commit is contained in:
@@ -0,0 +1,742 @@
|
||||
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 ...
|
||||
/// <summary>
|
||||
/// Check a Token Entity Exists or not
|
||||
/// </summary>
|
||||
/// <param name="device">an instance of <see>XDevice</see></param>
|
||||
/// <param name="type">specifies Action Step by a member of <see>XAction</see></param>
|
||||
/// <returns>a boolean value</returns>
|
||||
private async Task<bool> 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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Check a Token Entity Exists or not
|
||||
/// </summary>
|
||||
/// <param name="userSelectByParam">specified user's identifier</param>
|
||||
/// <param name="type">specifies Action Step by a member of <see>XAction</see></param>
|
||||
/// <returns>a boolean value</returns>
|
||||
private async Task<bool> 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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Check a Token Entity Exists or not
|
||||
/// </summary>
|
||||
/// <param name="token">represent specified action token</param>
|
||||
/// <returns>a boolean value</returns>
|
||||
private async Task<bool> IsTokenExistsByToken(
|
||||
string token
|
||||
)
|
||||
{
|
||||
//
|
||||
var result = await DbContext.Tokens
|
||||
.AnyAsync(xt => xt.Token == token);
|
||||
|
||||
//
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Check a Token Entity Exists or not
|
||||
/// </summary>
|
||||
/// <param name="hash">represent specified action token hash</param>
|
||||
/// <returns>a boolean value</returns>
|
||||
private async Task<bool> IsTokenExistsByHash(
|
||||
string hash
|
||||
)
|
||||
{
|
||||
//
|
||||
var result = await DbContext.Tokens
|
||||
.AnyAsync(xt => xt.Hash == hash);
|
||||
|
||||
//
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Check a Token Entity Exists or not
|
||||
/// </summary>
|
||||
/// <param name="item">an instance of <see>XToken</see></param>
|
||||
/// <returns>a boolean value</returns>
|
||||
private async Task<bool> 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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Check a Token Entity Exists or not
|
||||
/// </summary>
|
||||
/// <param name="id">specifies token id</param>
|
||||
/// <returns>a boolean value</returns>
|
||||
private async Task<bool> IsTokenExistsById(
|
||||
int id
|
||||
)
|
||||
{
|
||||
return await DbContext.Tokens.AnyAsync(t => t.Id == id);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieve Token Entity
|
||||
/// </summary>
|
||||
/// <param name="device">an instance of <see>XDevice</see></param>
|
||||
/// <param name="type">specifies Action Step by a member of <see>XAction</see></param>
|
||||
/// <returns>an instance of <see>XToken</see></returns>
|
||||
private async Task<XToken> 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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieve Token Entity
|
||||
/// </summary>
|
||||
/// <param name="userSelectByParam">specified user's identifier</param>
|
||||
/// <param name="type">specifies Action Step by a member of <see>XAction</see></param>
|
||||
/// <returns>an instance of <see>XToken</see></returns>
|
||||
private async Task<XToken> 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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieve a Token Entity
|
||||
/// </summary>
|
||||
/// <param name="token">represent specified action token</param>
|
||||
/// <returns>an instance of <see>XToken</see></returns>
|
||||
private async Task<XToken> GetTokenByToken(
|
||||
string token
|
||||
)
|
||||
{
|
||||
//
|
||||
var isExists = await IsTokenExistsByToken(token);
|
||||
if (!isExists)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
//
|
||||
var result = await DbContext.Tokens
|
||||
.FirstOrDefaultAsync(xt => xt.Token == token);
|
||||
|
||||
//
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieve Related Hash to a Token
|
||||
/// </summary>
|
||||
/// <param name="token">represent specified action token</param>
|
||||
/// <returns>hash string</returns>
|
||||
private async Task<string> GetRelatedHashByToken(
|
||||
string token
|
||||
)
|
||||
{
|
||||
//
|
||||
var item = await GetTokenByToken(token);
|
||||
if (item == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
//
|
||||
return item.Hash;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieve a Token Entity
|
||||
/// </summary>
|
||||
/// <param name="hash">represent specified action token hash</param>
|
||||
/// <returns>an instance of <see>XToken</see></returns>
|
||||
private async Task<XToken> 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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieve Related Token to a Hash string
|
||||
/// </summary>
|
||||
/// <param name="hash">represent specified action token hash</param>
|
||||
/// <returns>token string</returns>
|
||||
private async Task<string> GetRelatedTokenByHash(
|
||||
string hash
|
||||
)
|
||||
{
|
||||
//
|
||||
var item = await GetTokenByHash(hash);
|
||||
if (item == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
//
|
||||
return item.Token;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieve a Token Expiration Date
|
||||
/// </summary>
|
||||
/// <param name="token">represent specified action token</param>
|
||||
/// <returns>an instance of <see>DateTime</see></returns>
|
||||
private DateTime GetTokenExpirationDate(
|
||||
string token
|
||||
)
|
||||
{
|
||||
//
|
||||
ValidationProvider.NotEmpty(token);
|
||||
|
||||
//
|
||||
var result = IdentityHelper.GetTokenExpirationDate(token);
|
||||
|
||||
//
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Remove a Token Entity
|
||||
/// </summary>
|
||||
/// <param name="token">represent specified action token</param>
|
||||
/// <returns></returns>
|
||||
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();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Remove a Token Entity
|
||||
/// </summary>
|
||||
/// <param name="hash">represent specified action token hash</param>
|
||||
/// <returns></returns>
|
||||
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();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Remove a Token Entity
|
||||
/// </summary>
|
||||
/// <param name="device">an instance of <see>XDevice</see></param>
|
||||
/// <returns></returns>
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// add a token Entity
|
||||
/// </summary>
|
||||
/// <param name="item">an instance of <see>XToken</see></param>
|
||||
/// <returns>an instance of <see>XToken</see></returns>
|
||||
private async Task<XToken> 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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Hash a Request Token
|
||||
/// </summary>
|
||||
/// <param name="request">an instance of <see>XActionRequestToken</see></param>
|
||||
/// <param name="forceNotNullUserSelectByParam"></param>
|
||||
/// <param name="forceDeviceNotNull"></param>
|
||||
/// <returns>an instance of <see>XToken</see></returns>
|
||||
private async Task<XToken> 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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Generate Token Hash string
|
||||
/// </summary>
|
||||
/// <param name="token">represent specified action token</param>
|
||||
/// <param name="checkValidation">check token validation parameters, default is true</param>
|
||||
/// <returns>hash string</returns>
|
||||
private string ToHash(
|
||||
string token,
|
||||
bool checkValidation = true
|
||||
)
|
||||
{
|
||||
//
|
||||
ValidationProvider.NotEmpty(token);
|
||||
|
||||
//
|
||||
if (checkValidation)
|
||||
{
|
||||
ValidateToken(token);
|
||||
}
|
||||
|
||||
//
|
||||
var result = token.ToMd5String().ToNormalString();
|
||||
|
||||
//
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Generate Token string
|
||||
/// </summary>
|
||||
/// <param name="token">represent specified action token</param>
|
||||
/// <returns>token string</returns>
|
||||
private string ToTokenString(
|
||||
SecurityToken token
|
||||
)
|
||||
{
|
||||
//
|
||||
ValidationProvider.NotNull(token, IdentityHelper);
|
||||
|
||||
//
|
||||
var result = IdentityHelper.ToTokenString(token);
|
||||
|
||||
//
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Generate Token string
|
||||
/// </summary>
|
||||
/// <param name="token">represent specified action token</param>
|
||||
/// <returns>token string</returns>
|
||||
private string ToTokenString(
|
||||
JwtSecurityToken token
|
||||
)
|
||||
{
|
||||
//
|
||||
ValidationProvider.NotNull(token, IdentityHelper);
|
||||
|
||||
//
|
||||
var result = IdentityHelper.ToTokenString(token);
|
||||
|
||||
//
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Generate Security Token
|
||||
/// </summary>
|
||||
/// <param name="token">represent specified action token</param>
|
||||
/// <returns>an instance of <see>SecurityToken</see></returns>
|
||||
private SecurityToken ToSecurityToken(
|
||||
string token
|
||||
)
|
||||
{
|
||||
//
|
||||
ValidationProvider.NotEmpty(token);
|
||||
|
||||
//
|
||||
var result = IdentityHelper.ToSecurityToken(token);
|
||||
|
||||
//
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Generate Security Token
|
||||
/// </summary>
|
||||
/// <param name="request">an instance of <see>XActionRequestToken</see></param>
|
||||
/// <returns>an instance of <see>SecurityToken</see></returns>
|
||||
private SecurityToken ToSecurityToken(
|
||||
XActionRequestToken request
|
||||
)
|
||||
{
|
||||
//
|
||||
ValidationProvider.NotNull(request);
|
||||
|
||||
//
|
||||
ValidateActionRequest(request);
|
||||
|
||||
//
|
||||
var result = IdentityHelper.ToSecurityToken(request);
|
||||
if (result == null)
|
||||
{
|
||||
XException.InvalidToken.Throw();
|
||||
}
|
||||
|
||||
//
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Cleanup all exists tokens related to specified User
|
||||
/// </summary>
|
||||
/// <param name="userSelectByParam">specified user's identifier</param>
|
||||
/// <returns></returns>
|
||||
private async Task HandleRemoveExistsTokens(
|
||||
string userSelectByParam
|
||||
)
|
||||
{
|
||||
//
|
||||
// Validate Args ...
|
||||
ValidationProvider.NotEmpty(userSelectByParam);
|
||||
|
||||
//
|
||||
var xTokens = new List<XToken>();
|
||||
var xTokenEnumerator = DbContext.Tokens.AsAsyncEnumerable();
|
||||
await
|
||||
foreach (var xToken in xTokenEnumerator)
|
||||
{
|
||||
//
|
||||
if (xToken.UserSelectByParam == userSelectByParam &&
|
||||
ObjectHelper.ToEnumerableValues<XAction>().Contains(xToken.Type))
|
||||
{
|
||||
xTokens.Add(xToken);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
if (xTokens.HasChild())
|
||||
{
|
||||
DbContext.Tokens.RemoveRange(xTokens);
|
||||
await DbContext.SaveChangesAsync();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Cleanup all tokens related to specified User
|
||||
/// </summary>
|
||||
/// <param name="userSelectByParams">a collection of user identifiers</param>
|
||||
/// <returns></returns>
|
||||
private async Task HandleCleanUserTokens(
|
||||
ICollection<string> userSelectByParams
|
||||
)
|
||||
{
|
||||
//
|
||||
// Validate Args ...
|
||||
if (!userSelectByParams.HasChild())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
foreach (var userSelectByParam in userSelectByParams)
|
||||
{
|
||||
await HandleRemoveExistsTokens(userSelectByParam);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Cleanup all tokens related to specified User
|
||||
/// </summary>
|
||||
/// <param name="user">an instance of <see>XUser</see></param>
|
||||
/// <returns></returns>
|
||||
private async Task HandleCleanUserTokens(
|
||||
XUser user
|
||||
)
|
||||
{
|
||||
//
|
||||
if (user == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
var userSelectByParams = GenerateUserSelectByParams(user);
|
||||
|
||||
//
|
||||
await HandleCleanUserTokens(userSelectByParams);
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user