Initial Commit ...

This commit is contained in:
2024-01-25 04:44:02 +03:30
commit a8e257b855
36 changed files with 6645 additions and 0 deletions
+8
View File
@@ -0,0 +1,8 @@
#
# DotNet ...
bin
obj
#
# Natural Docs ...
Documentation/*
@@ -0,0 +1,15 @@
using xIdentityService.Constants;
namespace xIdentityService.Configuration {
public partial class XIdentityServiceConfiguration {
public string Authority { get; set; }
public string ApiName { get; set; }
public string ApiSecret { get; set; }
public string ClientId { get; set; }
public string ClientSecret { get; set; }
public string XPoweredValue { get; set; }
public XTokenType TokenType { get; set; }
public string XRevisionSecretKey { get; set; }
public int DefaultClientTimeout { get; set; } = 360;
}
}
+81
View File
@@ -0,0 +1,81 @@
using System.Collections.Generic;
using xModels.Base;
namespace xIdentityService.Configuration {
/// <summary>
/// XProxy Middleware Configuration ...
/// </summary>
public class XProxyConfiguration {
/// <summary>
/// Proxy Host Address for Clients Which Use XProxy Server ...
/// </summary>
/// <value></value>
public string Host { get; set; }
/// <summary>
/// if EnableXPoweredByAthorization property setted to true, this property determines
/// the header must be this value ...
/// </summary>
/// <value></value>
public string XPoweredValue { get; set; }
/// <summary>
/// Determines Proxy Http Handler Check SSL or not ...
/// </summary>
/// <value></value>
public bool DisableSSLCheck { get; set; }
/// <summary>
/// Determines Http Client Handler Allow Auto Redirect or not ...
/// </summary>
/// <value></value>
public bool AllowAutoRedirect { get; set; }
/// <summary>
/// Determines Proxy Server Log Received Requests or not ...
/// </summary>
/// <value></value>
public bool EnableLogging { get; set; }
/// <summary>
/// DefineRoutes for Handling ...
/// </summary>
/// <value></value>
public HashSet<XProxyRouteDescriptor> Routes { get; set; }
}
/// <summary>
/// Describe a Proxy Route ...
/// </summary>
public class XProxyRouteDescriptor : XBaseDescriptor {
/// <summary>
/// Determines which route can handled for Proxyfing ...
/// </summary>
/// <value></value>
public string Route { get; set; }
/// <summary>
/// Determines Proxy Server Handle Athorization or not ...
/// </summary>
/// <value></value>
public bool EnableAuthorization { get; set; }
/// <summary>
/// Determines Which Scopes allowed to this route if authorizations enabled ...
/// </summary>
/// <value></value>
public HashSet<string> AllowedScopes { get; set; }
/// <summary>
/// Determines Which Roles allowed to this route if authorizations enabled ...
/// </summary>
/// <value></value>
public HashSet<string> AllowedRoles { get; set; }
/// <summary>
/// Determines XProxy Can Check XPowered By Authorization or not ...
/// </summary>
/// <value></value>
public bool EnableXPoweredByAthorization { get; set; }
}
}
+6
View File
@@ -0,0 +1,6 @@
namespace xIdentityService.Constants {
public partial struct ConfigurationNodeNames {
public const string XPROXY_CONFIGURATION_NODE_NAME = "ProxyConfiguration";
public const string IDENTITY_SERVICE_NODE_NAME = "IdentityServiceConfiguration";
}
}
+197
View File
@@ -0,0 +1,197 @@
using xExceptions.Attributes;
namespace xIdentityService.Constants {
public enum XApiAccountEndpoint {
//
#region Authentication ...
[StringValue ("Account/DiscoveryDocument")]
DiscoveryDocument,
[StringValue ("Account/RequestScopeAccessToken")]
RequestScopeAccessToken,
[StringValue ("Account/Authenticate")]
Authenticate,
[StringValue ("Account/Login")]
Login,
[StringValue ("Account/RefreshTokens")]
RefreshTokens,
[StringValue ("Account/ChangePassword")]
ChangePassword,
[StringValue ("Account/ResetPassword")]
ResetPassword,
#endregion
//
#region Proile ...
[StringValue ("Account/Profile/{ids}/GetNames")]
GetNames,
[StringValue ("Account/Profile/GetNameIds")]
GetNameIds,
[StringValue ("Account/Profile/{userSelectByParam}")]
GetProfile,
[StringValue ("Account/Profile/Query")]
QueryProfiles,
[StringValue ("Account/Profile/Avatars/Query/{userSelectByParam}")]
QueryAvatars,
[StringValue ("Account/Profile/Update/{userSelectByParam}")]
UpdateProfile,
[StringValue ("Account/Profile/{userSelectByParam}")]
FullUpdateProfile,
[StringValue ("Account/Profile/Avatar")]
AddAvatar,
[StringValue ("Account/Profile/Avatars")]
AddAvatars,
[StringValue ("Account/Profile/Avatars/{ids}")]
RemoveAvatars,
[StringValue ("Account/Profile/Avatars/{id}/Set")]
SetAvatar,
#endregion
//
#region Registration ...
[StringValue ("Account/CanRegisterUserName/{userName}")]
CanRegisterUserName,
[StringValue ("Account/CanRegisterMobileNumber/{mobileNumber}")]
CanRegisterMobileNumber,
[StringValue ("Account/CanRegisterEmail/{email}")]
CanRegisterEmail,
[StringValue ("Account/IsConfirmedEmail")]
IsConfirmedEmail,
[StringValue ("Account/IsConfirmedMobile")]
IsConfirmedMobile,
[StringValue ("Account/ConfirmRegistration")]
ConfirmRegistration,
[StringValue ("Account/ConfirmMobileNumber")]
ConfirmMobileNumber,
[StringValue ("Account/ConfirmEmailAddress")]
ConfirmEmailAddress,
[StringValue ("Account/RequestConfirmMobile")]
RequestConfirmMobile,
[StringValue ("Account/RequestConfirmEmail")]
RequestConfirmEmail,
[StringValue ("Account/RequestResetPassword")]
RequestResetPassword,
[StringValue ("Account/RequestConfirmRegistration")]
RequestConfirmRegistration,
[StringValue ("Account/InviteUser")]
InviteUser,
[StringValue ("Account/RequestRegistration")]
RequestRegistration,
[StringValue ("Account/AddAccountInfo")]
AddAccountInfo,
[StringValue ("Account/AttachProfileImage")]
AttachProfileImage,
[StringValue ("Account/FinishRegistration")]
FinishRegistration,
#endregion
//
#region Friendship ...
[StringValue ("Account/Friendship/{destUser}/Follow")]
Follow,
[StringValue ("Account/Friendship/{destUser}/Cancel")]
Cancel,
[StringValue ("Account/Friendship/{destUser}/UnFollowFollower")]
UnFollowFollower,
[StringValue ("Account/Friendship/{destUser}/UnFollowFollowing")]
UnFollowFollowing,
[StringValue ("Account/Friendship/{destUser}/Block")]
Block,
[StringValue ("Account/Friendship/{destUser}/UnBlock")]
UnBlock,
[StringValue ("Account/Friendship/{destUser}/AcceptRequest")]
AcceptRequest,
[StringValue ("Account/Friendship/{destUser}/RejectRequest")]
RejectRequest,
[StringValue ("Account/Friendship/{destUser}/IsFollower")]
IsFollower,
[StringValue ("Account/Friendship/{destUser}/FollowerState")]
FollowerState,
[StringValue ("Account/Friendship/{destUser}/Follower")]
Follower,
[StringValue ("Account/Friendship/Followers")]
Followers,
[StringValue ("Account/Friendship/AllFollowers")]
AllFollowers,
[StringValue ("Account/Friendship/{destUser}/IsFollowing")]
IsFollowing,
[StringValue ("Account/Friendship/{destUser}/FollowingState")]
FollowingState,
[StringValue ("Account/Friendship/{destUser}/Following")]
Following,
[StringValue ("Account/Friendship/Followings")]
Followings,
[StringValue ("Account/Friendship/AllFollowings")]
AllFollowings,
[StringValue ("Account/Friendship/FollowingsList")]
FollowingsList,
[StringValue ("Account/Friendship/FollowersList")]
FollowersList,
[StringValue ("Account/Friendship/{destUser}/FriendshipInfo")]
FriendshipInfo,
#endregion
//
#region Admin ...
[StringValue ("Account/Ban")]
Ban,
[StringValue ("Account/UnBan")]
UnBan,
[StringValue ("Account/IsBanned/{userSelectByParam}")]
IsBanned,
#endregion
}
}
+9
View File
@@ -0,0 +1,9 @@
using xExceptions.Attributes;
namespace xIdentityService.Constants {
public enum XAuthenticationScheme {
[StringValue ("token")]
XToken, [StringValue ("introspection")]
XIntrospection,
}
}
+56
View File
@@ -0,0 +1,56 @@
using xExceptions.Attributes;
namespace xIdentityService.Constants {
public enum XParam {
[StringValue ("Content-Type")]
XContentType,
[StringValue ("{boundary}")]
XBoundary,
[StringValue ("{userSelectByParam}")]
XUserSelectByParam,
[StringValue ("{destUser}")]
XDestUser,
[StringValue ("{id}")]
XId,
[StringValue ("{ids}")]
XIds,
[StringValue ("Origin")]
XOrigin,
[StringValue ("{userName}")]
XUserName,
[StringValue ("{mobileNumber}")]
XMobileNumber,
[StringValue ("{email}")]
XEmail,
[StringValue ("role")]
XRole,
[StringValue ("forceRole")]
XForceRole,
[StringValue ("IsRefreshed")]
XIsRefreshed,
[StringValue ("file")]
XFile,
[StringValue ("files")]
XFiles,
[StringValue ("actionToken")]
XActionToken,
[StringValue ("scope")]
XScope,
}
}
+7
View File
@@ -0,0 +1,7 @@
namespace xIdentityService.Constants {
public struct XProxyConstants {
public const string XPROXY_HTTP_CLIENT = "XProxyHttpClient";
public const string XPROXY_FORWARD_HEADER = "xForwardHeader";
public const string XPROXY_ACCEPTED_HEADERS = "xAcceptedHeaders";
}
}
+7
View File
@@ -0,0 +1,7 @@
namespace xIdentityService.Constants {
public struct XResponseContentTypes {
public const string HTML = "text/html";
public const string JSON = "application/json";
public const string JavaScript = "text/javascript";
}
}
+12
View File
@@ -0,0 +1,12 @@
namespace xIdentityService.Constants {
public enum XTokenType {
//
// Summary:
// Self-contained Json Web Token
Jwt,
//
// Summary:
// Reference token
Reference
}
}
+211
View File
@@ -0,0 +1,211 @@
using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using xCommons.Configurations;
using xCommons.Constants;
using xCommons.Controllers;
using xCommons.Extensions;
using xCommons.Providers;
using xExceptions.Constants;
using xIdentityModels.Constants;
using xIdentityModels.Models;
using xIdentityService.Interfaces;
namespace xIdentityService.Controllers {
public abstract class XIBaseController : XBaseController {
private readonly IXIdentityProvider identityProvider;
public XIBaseController (
ILogger logger,
XAppConfiguration appConfiguration,
IXIdentityProvider identityProvider,
XValidationProvider validationProvider
) : base (
logger,
appConfiguration,
validationProvider
) {
this.identityProvider = identityProvider;
}
//
#region User Handlers NonActions ...
/// <summary>
/// Retrieve User Identifier Base on XActionRequest
/// </summary>
/// <param name="model"></param>
/// <param name="forceNotNull"></param>
/// <param name="excludes"></param>
/// <returns></returns>
[NonAction]
public string GetUserSelectByParam (
XActionRequest model,
bool forceNotNull = true,
ICollection<XUserSelectBy> excludes = null) {
//
// Validate Args ...
ValidationProvider.NotNull (model);
//
var result = identityProvider.GetUserSelectByParam (
model,
forceNotNull,
excludes);
//
return result;
}
/// <summary>
/// Retrieve Access Token
/// </summary>
/// <returns></returns>
[NonAction]
public async Task<string> GetAccessToken () {
//
var accessToken = Request.Headers[XAuthorization.Header]
.ToString ();
if (accessToken.IsNullOrEmpty ()) {
accessToken = await HttpContext
.GetTokenAsync (XAuthorization.AccessToken);
}
//
if (accessToken
.ToNormalString ()
.Contains (XAuthorization.TokenIdentifier
.ToNormalString ())) {
accessToken = accessToken
.Remove (0, XAuthorization.TokenIdentifier.Length);
}
//
return accessToken;
}
/// <summary>
/// Retrieve Refresh Token
/// </summary>
/// <returns></returns>
[NonAction]
public async Task<string> GetRefreshToken () {
//
var refreshToken = Request.Headers[XAuthorization.RefreshToken]
.ToString ();
if (refreshToken.IsNullOrEmpty ()) {
refreshToken = await HttpContext
.GetTokenAsync (XAuthorization.RefreshToken);
}
//
return refreshToken;
}
/// <summary>
/// Retrieve Access Token Expiration Date
/// </summary>
/// <returns></returns>
[NonAction]
public async Task<long> GetTokenExpiresAt () {
//
var expiresAtStr = Request.Headers[XAuthorization.ExpiresAt]
.ToString ();
if (expiresAtStr.IsNullOrEmpty ()) {
expiresAtStr = await HttpContext
.GetTokenAsync (XAuthorization.ExpiresAt);
}
//
var expiresAt = expiresAtStr.ConvertTo<long> ();
//
return expiresAt;
}
/// <summary>
/// Retrieve All Required Tokens
/// </summary>
/// <returns></returns>
[NonAction]
public async Task<XLoginResponse> RetrieveTokensAsXLoginResponse () {
//
var accessToken = await GetAccessToken ();
var refreshToken = await GetRefreshToken ();
var expiresAt = await GetTokenExpiresAt ();
//
return new XLoginResponse {
AccessToken = accessToken,
RefreshToken = refreshToken,
ExpiresAt = expiresAt
};
}
/// <summary>
/// Retrieve All Required Tokens
/// </summary>
/// <returns></returns>
[NonAction]
public async Task<XTokenResponse> RetrieveTokensAsXTokenResponse () {
//
var accessToken = await GetAccessToken ();
var refreshToken = await GetRefreshToken ();
var expiresAt = await GetTokenExpiresAt ();
//
return new XTokenResponse {
AccessToken = accessToken,
RefreshToken = refreshToken,
ExpiresAt = expiresAt
};
}
/// <summary>
/// Retrive UserInfo
/// </summary>
/// <returns></returns>
[NonAction]
public async Task<XUserClaimsInfoDto> GetUserInfo () {
//
var claims = User.Claims ?? null;
if (!claims.HasChild ()) {
return null;
}
var xTokens = await RetrieveTokensAsXTokenResponse ();
var result = new XUserClaimsInfoDto (
xTokens.AccessToken,
xTokens.RefreshToken,
xTokens.ExpiresAt,
User.Claims
);
//
return result;
}
/// <summary>
/// Validate User Authenticated and Retrieve User Info
/// </summary>
/// <returns></returns>
[NonAction]
public async Task<XUserClaimsInfoDto> ValidateAndGetUserInfo () {
//
if (!User.Identity.IsAuthenticated) {
XException.NotAuthorized.Throw ();
}
//
var result = await GetUserInfo ();
if (result.IsNull ()) {
XException.NotAuthorized.Throw ();
}
//
return result;
}
#endregion
}
}
+486
View File
@@ -0,0 +1,486 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using xCommons.Attributes;
using xCommons.Configurations;
using xCommons.Extensions;
using xCommons.Providers;
using xDataService.Interfaces;
using xExceptions.Constants;
using xIdentityService.Interfaces;
using xModels.Base;
using xModels.Dtos;
using xModels.Interfaces;
namespace xIdentityService.Controllers {
[Authorize]
[RequireXPowered (false)]
public abstract class XIBaseEntityController<TEntity, TKey> : XIBaseController, IXEntityControllerActions<TEntity, TKey>
where TEntity : XBaseEntity<TKey> {
public readonly IXBaseRepository<TEntity, TKey> repository;
protected XIBaseEntityController (
ILogger logger,
XAppConfiguration appConfiguration,
IXIdentityProvider identityProvider,
XValidationProvider validationProvider,
IXBaseRepository<TEntity, TKey> repository
) : base (
logger,
appConfiguration,
identityProvider,
validationProvider
) {
//
this.repository = repository;
}
//
#region Interface Implementations ...
//
#region Retrieve ...
[HttpGet ("{id}")]
public virtual async Task<ActionResult<TEntity>> Get (
[FromRoute] TKey id, [FromQuery] bool ignoreSoftDeleteds = true, [FromQuery] bool containsDetail = false
) {
//
try {
//
// Validate Args ...
ValidationProvider.NotNull (id);
//
// Get Result ...
var result = await repository
.GetAsync (
id,
ignoreSoftDeleteds : ignoreSoftDeleteds,
containsDetail : containsDetail
);
//
return Ok (result
.ToDynamicObject ());
} catch (Exception ex) {
//
var result = GetExceptionActionResult (ex);
return result;
}
}
[HttpGet]
public virtual async Task<ActionResult<IEnumerable<TEntity>>> GetAll (
[FromQuery] bool ignoreSoftDeleteds = true, [FromQuery] bool containsDetail = false
) {
//
try {
//
// Get Result ...
var result = await repository
.GetAllAsync (
ignoreSoftDeleteds: ignoreSoftDeleteds,
containsDetail: containsDetail
);
//
return Ok (result
.ToDynamicObject ());
} catch (Exception ex) {
//
var result = GetExceptionActionResult (ex);
return result;
}
}
[HttpGet ("FindOne/{query}")]
public virtual async Task<ActionResult<TEntity>> FindOne (
[FromRoute] string query, [FromQuery] bool ignoreSoftDeleteds = true, [FromQuery] bool containsDetail = false
) {
//
try {
//
// Validate Args ...
ValidationProvider.NotEmpty (query);
//
// Get Result ...
var result = await repository
.FindOneAsync (t =>
t.PropValuesContains (query),
ignoreSoftDeleteds : ignoreSoftDeleteds,
containsDetail : containsDetail
);
//
return Ok (result
.ToDynamicObject ());
} catch (Exception ex) {
//
var result = GetExceptionActionResult (ex);
return result;
}
}
[HttpGet ("FindMany/{query}")]
public virtual async Task<ActionResult<IEnumerable<TEntity>>> FindMany (
[FromRoute] string query, [FromQuery] bool ignoreSoftDeleteds = true, [FromQuery] bool containsDetail = false
) {
//
try {
//
// Validate Args ...
ValidationProvider.NotEmpty (query);
//
// Get Result ...
var result = await repository
.FindManyAsync (t =>
t.PropValuesContains (query),
ignoreSoftDeleteds : ignoreSoftDeleteds,
containsDetail : containsDetail
);
//
return Ok (result
.ToDynamicObject ());
} catch (Exception ex) {
//
var result = GetExceptionActionResult (ex);
return result;
}
}
[HttpGet ("Query")]
public virtual async Task<ActionResult<XQueryResult<TEntity>>> Query (
[FromQuery] XQuery query, [FromQuery] bool ignoreSoftDeleteds = true
) {
//
try {
//
// Validate Args ...
ValidationProvider.NotNull (query);
//
// Get Result ...
var result = await repository
.QueryAsync (
query,
ignoreSoftDeleteds : ignoreSoftDeleteds
);
//
return Ok (result
.ToDynamicObject ());
} catch (Exception ex) {
//
var result = GetExceptionActionResult (ex);
return result;
}
}
//
// TODO: Fix this ...
// [HttpGet ("RequestPage")]
// public virtual async Task<ActionResult<XPageResponse<TEntity>>> RequestPage (
// [FromQuery] XPageRequest request, [FromQuery] bool ignoreSoftDeleteds = true, [FromQuery] bool containsDetail = false
// ) {
// //
// try {
// //
// // Validate Args ...
// ValidationProvider.NotNull (request);
// //
// // Get Result ...
// var result = await repository
// .RequestPageAsync (
// request,
// ignoreSoftDeleteds : ignoreSoftDeleteds,
// containsDetail : containsDetail
// );
// //
// return Ok (result
// .ToDynamicObject ());
// } catch (Exception ex) {
// //
// var result = GetExceptionActionResult (ex);
// return result;
// }
// }
#endregion
//
#region Add ...
[HttpPost]
public virtual async Task<ActionResult<TEntity>> Add (
[FromBody] TEntity item
) {
//
try {
//
// Validate Args ...
if (!ModelState.IsValid) {
XException.InvalidArgs.Throw ();
}
ValidationProvider.NotNull (item);
//
// Get Result ...
var result = await repository
.AddAsync (
item,
saveChanges : true
);
//
return Ok (result
.ToDynamicObject ());
} catch (Exception ex) {
//
var result = GetExceptionActionResult (ex);
return result;
}
}
[HttpPost ("AddOrUpdate")]
public virtual async Task<ActionResult<TEntity>> AddOrUpdate (
[FromBody] TEntity item
) {
//
try {
//
// Validate Args ...
if (!ModelState.IsValid) {
XException.InvalidArgs.Throw ();
}
ValidationProvider.NotNull (item);
//
// Get Result ...
var result = await repository
.AddOrUpdateAsync (
item,
saveChanges : true
);
//
return Ok (result
.ToDynamicObject ());
} catch (Exception ex) {
//
var result = GetExceptionActionResult (ex);
return result;
}
}
[HttpPost ("AddMany")]
public virtual async Task<ActionResult> AddMany (
[FromBody] XBaseRangeRequest<TEntity> request
) {
//
try {
//
// Validate Args ...
if (!ModelState.IsValid) {
XException.InvalidArgs.Throw ();
}
await ValidationProvider
.GroupValidationBuilder ()
.AddNotNull (request)
.AddNotZeroChilds (request.Items)
.ValidateGroupAsync ();
//
// Get Result ...
await repository
.AddRangeAsync (
request.Items,
saveChanges : true
);
//
return Ok ();
} catch (Exception ex) {
//
var result = GetExceptionActionResult (ex);
return result;
}
}
#endregion
//
#region Update ...
[HttpPut ("{id}")]
public virtual async Task<ActionResult<TEntity>> Update (
[FromRoute] TKey id, [FromBody] TEntity item
) {
//
try {
//
// Validate Args ...
if (!ModelState.IsValid) {
XException.InvalidArgs.Throw ();
}
await ValidationProvider
.GroupValidationBuilder ()
.AddNotNull (id, item)
.ValidateGroupAsync ();
//
// Get Result ...
var result = await repository
.UpdateAsync (
id,
item,
saveChanges : true
);
//
return Ok (result
.ToDynamicObject ());
} catch (Exception ex) {
//
var result = GetExceptionActionResult (ex);
return result;
}
}
[HttpPost ("UpdateMany")]
public virtual async Task<ActionResult<bool>> UpdateMany (
[FromBody] XBaseRangeRequest<TEntity> request
) {
//
try {
//
// Validate Args ...
if (!ModelState.IsValid) {
XException.InvalidArgs.Throw ();
}
await ValidationProvider
.GroupValidationBuilder ()
.AddNotNull (request)
.AddNotZeroChilds (request.Items)
.ValidateGroupAsync ();
//
// Get Result ...
var result = await repository
.UpdateRangeAsync (
request.Items,
saveChanges : true
);
//
return Ok (result
.ToDynamicObject ());
} catch (Exception ex) {
//
var result = GetExceptionActionResult (ex);
return result;
}
}
#endregion
//
#region Exists ...
[HttpGet ("{id}/IsExists")]
public virtual async Task<ActionResult<bool>> IsExists (
[FromRoute] TKey id, [FromQuery] bool ignoreSoftDeleteds = true
) {
//
try {
//
// Validate Args ...
ValidationProvider.NotNull (id);
//
// Get Result ...
var result = await repository
.IsExistsAsync (
id,
ignoreSoftDeleteds : ignoreSoftDeleteds
);
//
return Ok (result
.ToDynamicObject ());
} catch (Exception ex) {
//
var result = GetExceptionActionResult (ex);
return result;
}
}
#endregion
//
#region Remove ...
[HttpDelete ("{id}")]
public virtual async Task<ActionResult<TEntity>> Remove (
[FromRoute] TKey id,
bool softDelete = true
) {
//
try {
//
// Validate Args ...
ValidationProvider.NotNull (id);
//
// Get Result ...
var result = await repository
.RemoveAsync (
id,
saveChanges : true,
softDelete : softDelete
);
//
return Ok (result
.ToDynamicObject ());
} catch (Exception ex) {
//
var result = GetExceptionActionResult (ex);
return result;
}
}
[HttpPost ("RemoveMany")]
public virtual async Task<ActionResult> RemoveMany (
[FromBody] XBaseRangeRequest<TEntity> request,
bool softDelete = true
) {
//
try {
//
// Validate Args ...
await ValidationProvider
.GroupValidationBuilder ()
.AddNotNull (request)
.AddNotZeroChilds (request.Items)
.ValidateGroupAsync ();
//
// Get Result ...
await repository
.RemoveRangeAsync (
request.Items,
saveChanges : true,
softDelete : softDelete
);
//
return Ok ();
} catch (Exception ex) {
//
var result = GetExceptionActionResult (ex);
return result;
}
}
#endregion
#endregion
}
}
+179
View File
@@ -0,0 +1,179 @@
using System;
using IdentityModel.AspNetCore.OAuth2Introspection;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using xCommons.Authorization;
using xCommons.Extensions;
using xIdentityService.Configuration;
using xIdentityService.Constants;
using xIdentityService.Interfaces;
using xIdentityService.Providers;
using xIdentityService.Security;
namespace xIdentityService.DI {
public static partial class XDIHelperExtension {
/// <summary>
/// Extract Module Configuration Structure from IConfiguration interface
/// </summary>
/// <param name="config"></param>
/// <returns></returns>
public static XIdentityServiceConfiguration GetXIdentityServiceConfiguration (this IConfiguration config) {
//
var xIdentityServiceConfigSection = config.GetSection (ConfigurationNodeNames.IDENTITY_SERVICE_NODE_NAME);
return xIdentityServiceConfigSection.Get<XIdentityServiceConfiguration> ();
}
/// <summary>
/// Register Service and All it's Requirements
/// </summary>
/// <param name="services"></param>
/// <param name="configuration"></param>
public static void AddXIdentityService (
this IServiceCollection services,
IConfiguration configuration,
ServiceLifetime lifeTime = ServiceLifetime.Singleton
) {
//
var identityConfiguration = configuration.GetXIdentityServiceConfiguration ();
AddIdentityService (
services,
identityConfiguration,
lifeTime
);
}
/// <summary>
/// Register Service and All it's Requirements
/// </summary>
/// <param name="services"></param>
/// <param name="configuration"></param>
public static void AddXIdentityService (
this IServiceCollection services,
XIdentityServiceConfiguration configuration,
ServiceLifetime lifeTime = ServiceLifetime.Singleton
) {
AddIdentityService (services, configuration, lifeTime);
}
/// <summary>
/// Register Custome Token Provider
/// </summary>
/// <param name="services"></param>
/// <typeparam name="T"></typeparam>
public static void AddXTokenProvider<T> (
this IServiceCollection services,
ServiceLifetime lifetime = ServiceLifetime.Singleton)
where T : IXTokenProvider {
//
Console.WriteLine ("IdentityService: Add Custom Token Provider ...");
services.Add (new ServiceDescriptor (typeof (IXTokenProvider), typeof (T), lifetime));
}
/// <summary>
/// Use Authentication
/// </summary>
/// <param name="app"></param>
public static void UseXIdentityService (this IApplicationBuilder app) {
app.UseAuthentication ();
}
//
#region Private ...
private static void AddIdentityService (
this IServiceCollection services,
XIdentityServiceConfiguration config,
ServiceLifetime lifeTime = ServiceLifetime.Singleton
) {
//
services.AddSingleton<XIdentityServiceConfiguration> (config);
//
var builder = services
.AddAuthentication (XAuthenticationScheme.XToken.GetStringValue ());
//
// Add JWT Handler ...
builder.AddJwtBearer (
XAuthenticationScheme.XToken.GetStringValue (), options => {
//
options.Authority = config.Authority;
options.TokenValidationParameters.ValidateAudience = false;
options.TokenValidationParameters.ValidTypes = new [] { "at+jwt" };
//
options.ForwardDefaultSelector = context => {
//
var path = context.Request.Path.Value;
//
var fromHeader = TokenRetrieval.FromAuthorizationHeader ();
var fromQuery = TokenRetrieval.FromQueryString ();
var bearerToken = fromHeader (context.Request) ?? fromQuery (context.Request);
//
var result = XAuthenticationScheme.XToken.GetStringValue ();
if (!bearerToken.IsNull () && !bearerToken.Contains (".")) {
result = XAuthenticationScheme.XIntrospection.GetStringValue ();
}
//
return result;
};
});
//
// Add OAuthIntrospect ...
builder.AddOAuth2Introspection (
XAuthenticationScheme.XIntrospection.GetStringValue (), options => {
//
options.Authority = config.Authority;
options.ClientId = config.ApiName;
options.ClientSecret = config.ClientSecret;
//
options.TokenRetriever = new Func<HttpRequest, string> (req => {
//
var fromHeader = TokenRetrieval.FromAuthorizationHeader ();
var fromQuery = TokenRetrieval.FromQueryString ();
//
var bearerToken = fromHeader (req) ?? fromQuery (req);
//
return bearerToken;
});
});
//
// Register Authorization Handler ...
services.AddSingleton<IAuthorizationHandler, RequiredRolesHandler> ();
Console.WriteLine ("IdentityService: register Authorization Handlers ...");
//
// Register Identity Provider ...
services.Add (new ServiceDescriptor (typeof (IXIdentityProvider), typeof (XIdentityProvider), lifeTime));
Console.WriteLine ("IdentityService: Register IdentityProvider ...");
//
// Try To Register InMemoryTokenProvier if it's not Provided ...
IXTokenProvider xTokenProvider = null;
try {
xTokenProvider = services.GetRegisteredService<IXTokenProvider> ();
} catch { }
if (xTokenProvider.IsNull ()) {
//
Console.WriteLine ("IdentityService: there is no Custom Token Provider, Adding InMemoryTokenProvider instead ...");
services.Add (new ServiceDescriptor (typeof (IXTokenProvider), typeof (XInMemoryTokenProvider), lifeTime));
}
//
// Adding Security Provider ...
services.Add (new ServiceDescriptor (typeof (IXSecurityProvider), typeof (XSecurityProvider), lifeTime));
Console.WriteLine ("IdentityService: Register Security Provider ...");
}
#endregion
}
}
@@ -0,0 +1,32 @@
using IdentityModel;
using Microsoft.AspNetCore.Authorization;
namespace xIdentityService.Extensions {
public static class AuthorizationPolicyBuilderExtensions {
/// <summary>
/// Adds a policy to check for required scopes.
/// </summary>
/// <param name="builder"></param>
/// <param name="scope">List of any required scopes. The token must contain at least one of the listed scopes.</param>
/// <returns></returns>
public static AuthorizationPolicyBuilder RequireScope (this AuthorizationPolicyBuilder builder, params string[] scope) {
return builder.RequireClaim (JwtClaimTypes.Scope, scope);
}
}
/// <summary>
/// Helper for creating scope-related policies
/// </summary>
public static class ScopePolicy {
/// <summary>
/// Creates a policy to check for required scopes.
/// </summary>
/// <param name="scopes">List of any required scopes. The token must contain at least one of the listed scopes.</param>
/// <returns></returns>
public static AuthorizationPolicy Create (params string[] scopes) {
return new AuthorizationPolicyBuilder ()
.RequireScope (scopes)
.Build ();
}
}
}
+145
View File
@@ -0,0 +1,145 @@
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
using xCommons.Constants;
using xCommons.Extensions;
using xIdentityModels.Models;
using xIdentityService.Constants;
namespace xIdentityService.Extensions {
public static class HttpContextExtensions {
/// <summary>
/// Retrieve Authentication Service ...
/// </summary>
/// <param name="context"></param>
/// <returns></returns>
public static IAuthenticationService GetAuthenticationService (this HttpContext context) {
//
var result = context.RequestServices
.GetRequiredService<IAuthenticationService> ();
//
return result;
}
/// <summary>
/// Retrieve Specific Token from HttpContext ...
/// </summary>
/// <param name="context"></param>
/// <param name="tokenName"></param>
/// <param name="scheme"></param>
/// <returns></returns>
public static async Task<string> GetXTokenAsync (
this HttpContext context,
string tokenName,
XAuthenticationScheme scheme = XAuthenticationScheme.XToken
) {
//
// Validate Args ...
if (tokenName.IsNullOrEmpty ()) {
return null;
}
//
var authService = context.GetAuthenticationService ();
if (authService.IsNull ()) {
return null;
}
//
var authResult = await authService
.AuthenticateAsync (
context,
scheme
.GetStringValue ()
);
//
var result = authResult?.Properties?
.GetTokenValue (tokenName);
return result;
}
/// <summary>
/// Retrieve Access Token
/// </summary>
/// <returns></returns>
public static async Task<string> GetAccessToken (this HttpContext context) {
//
var accessToken = context.Request.Headers[XAuthorization.Header]
.ToString ();
if (accessToken.IsNullOrEmpty ()) {
accessToken = await context
.GetTokenAsync (XAuthorization.AccessToken);
}
//
if (accessToken
.ToNormalString ()
.Contains (XAuthorization.TokenIdentifier
.ToNormalString ())) {
accessToken = accessToken
.Remove (0, XAuthorization.TokenIdentifier.Length);
}
//
return accessToken;
}
/// <summary>
/// Retrieve Refresh Token
/// </summary>
/// <returns></returns>
public static async Task<string> GetRefreshToken (this HttpContext context) {
//
var refreshToken = context.Request.Headers[XAuthorization.RefreshToken]
.ToString ();
if (refreshToken.IsNullOrEmpty ()) {
refreshToken = await context
.GetTokenAsync (XAuthorization.RefreshToken);
}
//
return refreshToken;
}
/// <summary>
/// Retrieve Access Token Expiration Date
/// </summary>
/// <returns></returns>
public static async Task<long> GetTokenExpiresAt (this HttpContext context) {
//
var expiresAtStr = context.Request.Headers[XAuthorization.ExpiresAt]
.ToString ();
if (expiresAtStr.IsNullOrEmpty ()) {
expiresAtStr = await context
.GetTokenAsync (XAuthorization.ExpiresAt);
}
//
var expiresAt = expiresAtStr.ConvertTo<long> ();
//
return expiresAt;
}
/// <summary>
/// Retrieve All Required Tokens
/// </summary>
/// <returns></returns>
public static async Task<XTokenResponse> RetrieveTokensAsXTokenResponse (HttpContext context) {
//
var accessToken = await GetAccessToken (context);
var refreshToken = await GetRefreshToken (context);
var expiresAt = await GetTokenExpiresAt (context);
//
return new XTokenResponse {
AccessToken = accessToken,
RefreshToken = refreshToken,
ExpiresAt = expiresAt
};
}
}
}
+370
View File
@@ -0,0 +1,370 @@
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Threading.Tasks;
using IdentityModel.Client;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc.Filters;
using xCommons.Constants;
using xCommons.Extensions;
using xExceptions.Constants;
using xExceptions.Models;
using xIdentityModels.Models;
using xIdentityService.Interfaces;
public static partial class XTokenExtensions {
/// <summary>
/// Retrieve Tokens From Headers
/// </summary>
/// <param name="source"></param>
/// <returns></returns>
public static XLoginResponse RetrieveTokens (this HttpRequest source) {
//
var accessToken = source.Headers[XAuthorization.Header].ToString ();
var refreshToken = source.Headers[XAuthorization.RefreshToken].ToString ();
//
var expiresAtStr = source.Headers[XAuthorization.ExpiresAt].ToString ();
long expiresAt = expiresAtStr.ConvertTo<long> ();
//
if (accessToken
.ToNormalString ()
.Contains (XAuthorization.TokenIdentifier.ToNormalString ())) {
accessToken = accessToken.Remove (0, XAuthorization.TokenIdentifier.Length);
}
//
return new XLoginResponse {
AccessToken = accessToken,
RefreshToken = refreshToken,
ExpiresAt = expiresAt
};
}
/// <summary>
/// Retrieve Tokens From HttpContext
/// </summary>
/// <param name="source"></param>
/// <returns></returns>
public static async Task<XLoginResponse> RetrieveTokens (this HttpContext source) {
//
var accessToken = await source.GetTokenAsync (XAuthorization.AccessToken);
if (accessToken
.ToNormalString ()
.Contains (XAuthorization.TokenIdentifier.ToNormalString ())) {
accessToken = accessToken.Remove (0, XAuthorization.TokenIdentifier.Length);
}
var refreshToken = await source.GetTokenAsync (XAuthorization.RefreshToken);
var expiresAtStr = await source.GetTokenAsync (XAuthorization.ExpiresAt);
long expiresAt = expiresAtStr.ConvertTo<long> ();
//
var headerRequestTokens = source.Request.RetrieveTokens ();
//
var result = new XLoginResponse {
AccessToken = accessToken ?? headerRequestTokens.AccessToken,
RefreshToken = refreshToken ?? headerRequestTokens.RefreshToken,
ExpiresAt = expiresAt != 0 ? expiresAt : headerRequestTokens.ExpiresAt
};
//
return result;
}
/// <summary>
/// Retrieve Tokens From ActionExecutingContext
/// </summary>
/// <param name="source"></param>
/// <returns></returns>
public static async Task<XLoginResponse> RetrieveTokens (this ActionExecutingContext source) {
//
var result = await source.HttpContext.RetrieveTokens ();
return result;
}
/// <summary>
/// Retrieve Tokens From XUserInfo instance
/// </summary>
/// <param name="source"></param>
/// <returns></returns>
public static XTokenResponse RetrieveTokens (this XUserClaimsInfoDto source) {
//
var result = new XLoginResponse {
AccessToken = source.AccessToken,
RefreshToken = source.RefreshToken,
ExpiresAt = source.ExpiresAt
};
//
return result;
}
/// <summary>
/// Retrieve Tokens From IHeader Dictionary
/// </summary>
/// <param name="source"></param>
/// <returns></returns>
public static XLoginResponse RetrieveTokens (this IHeaderDictionary source) {
//
var accessToken = source[XAuthorization.Header].ToString () ?? "";
if (accessToken
.ToNormalString ()
.Contains (XAuthorization.TokenIdentifier.ToNormalString ())) {
accessToken = accessToken.Remove (0, XAuthorization.TokenIdentifier.Length);
}
//
var refreshToken = source[XAuthorization.RefreshToken].ToString () ?? "";
//
var expiresAtStr = source[XAuthorization.ExpiresAt].ToString () ?? "";
var expiresAt = expiresAtStr.ConvertTo<long> ();
//
var result = new XLoginResponse {
AccessToken = accessToken,
RefreshToken = refreshToken,
ExpiresAt = expiresAt
};
//
return result;
}
/// <summary>
/// Retrieve IXIdentityProvider from HttpContext
/// </summary>
/// <param name="source"></param>
/// <returns></returns>
public static IXIdentityProvider GetXApiIdentityProvider (this FilterContext source) {
//
var services = source.HttpContext.RequestServices;
return (IXIdentityProvider) services
.GetService (typeof (IXIdentityProvider));
}
/// <summary>
/// Generate XLoginResponse instance based on TokenResponse
/// </summary>
/// <param name="source"></param>
/// <returns></returns>
public static XLoginResponse CreateXLoginResponse (this TokenResponse source) {
//
if (source.IsNull () ||
source.IsError) {
XException.InvalidToken.Throw ();
}
//
var expiresAt = new DateTimeOffset (DateTime.UtcNow)
.ToUnixTimeSeconds () +
source.ExpiresIn;
//
var result = new XLoginResponse {
AccessToken = source.AccessToken,
RefreshToken = source.RefreshToken,
ExpiresAt = expiresAt
};
//
return result;
}
/// <summary>
/// Add Authorization Tokens in Headers of
/// Specific IHeaderDictionary instance
/// </summary>
/// <param name="source"></param>
/// <param name="model"></param>
public static void SetXAuthenticationTokens (this IHeaderDictionary source, XLoginResponse model, string secret = null) {
//
source.Remove (XAuthorization.Header);
source.Remove (XAuthorization.RefreshToken);
source.Remove (XAuthorization.ExpiresAt);
source.Remove (XAuthorization.RevisionChecksum);
//
source.Add (XAuthorization.Header, $"{XAuthorization.TokenIdentifier}{model.AccessToken}");
source.Add (XAuthorization.RefreshToken, $"{model.RefreshToken}");
source.Add (XAuthorization.ExpiresAt, $"{model.ExpiresAt}");
//
if (!secret.IsNullOrEmpty ()) {
var revisionChecksum = model.GetRevisionChecksum (secret);
source.Add (XAuthorization.RevisionChecksum, revisionChecksum);
}
}
/// <summary>
/// Add Authorization Tokens in Headers of
/// Specific IHeaderDictionary instance
/// </summary>
/// <param name="source"></param>
/// <param name="model"></param>
public static void SetXAuthenticationTokens (this HttpRequestHeaders source, XLoginResponse model) {
//
source.Remove (XAuthorization.Header);
source.Remove (XAuthorization.RefreshToken);
source.Remove (XAuthorization.ExpiresAt);
source.Remove (XAuthorization.RevisionChecksum);
//
source.Add (XAuthorization.Header, $"{XAuthorization.TokenIdentifier}{model.AccessToken}");
source.Add (XAuthorization.RefreshToken, $"{model.RefreshToken}");
source.Add (XAuthorization.ExpiresAt, $"{model.ExpiresAt}");
}
/// <summary>
/// Add Authorization Tokens in Headers of
/// Specific HttpRequest instance
/// </summary>
/// <param name="source"></param>
/// <param name="model"></param>
public static void SetXAuthenticationTokens (this HttpRequest source, XLoginResponse model) {
source.Headers.SetXAuthenticationTokens (model);
}
/// <summary>
/// Add Authorization Tokens in Headers of
/// Specific HttpRequest instance
/// </summary>
/// <param name="source"></param>
/// <param name="model"></param>
public static void SetXAuthenticationTokens (this HttpRequestMessage source, XLoginResponse model) {
source.Headers.SetXAuthenticationTokens (model);
}
/// <summary>
/// Add ReNewed Authorization Tokens in Headers of
/// Specific Response.
/// Later in HttpInterceptors we can Look for AccessToken-ReNewed
/// header Value and Renew User Tokens based on it
/// </summary>
/// <param name="source"></param>
/// <param name="model"></param>
public static void SetXAuthenticationTokens (this HttpResponse source, XLoginResponse model, string secret) {
source.Headers.SetXAuthenticationTokens (model, secret);
}
/// <summary>
/// Determines a Token Can Refrsh or not
/// </summary>
/// <param name="source"></param>
/// <returns></returns>
public static bool IsRefreshable (this XLoginResponse source) {
//
var containsTokenData = !source.IsNull () &&
!source.AccessToken.IsNullOrEmpty () &&
!source.RefreshToken.IsNullOrEmpty ();
if (!containsTokenData) {
return false;
}
//
var current = new DateTimeOffset (DateTime.UtcNow)
.ToUnixTimeSeconds ();
//
// var result = current > source.ExpiresAt || current > source.ExpiresAt - XAuthorization.ThresholdBeforeTokenExpiration;
var result = current > source.ExpiresAt - XAuthorization.ThresholdBeforeTokenExpiration;
//
return result;
}
/// <summary>
/// Generate a Revision Checksum for new Tokens
/// </summary>
/// <param name="source"></param>
/// <param name="secret"></param>
/// <returns></returns>
public static string GetRevisionChecksum (this XLoginResponse source, string secret) {
return (source.AccessToken +
secret +
source.RefreshToken +
secret +
source.ExpiresAt.ToString ()
)
.ToMd5String ();
}
/// <summary>
/// Generate a Revision Checksum for new Tokens
/// </summary>
/// <param name="source"></param>
/// <param name="secret"></param>
/// <returns></returns>
public static string GetRevisionChecksum (this XTokenResponse source, string secret) {
return (source.AccessToken +
secret +
source.RefreshToken +
secret +
source.ExpiresAt.ToString ()
)
.ToMd5String ();
}
/// <summary>
/// Check an XLoginResponse instance is Valid with it's revision
/// </summary>
/// <param name="source"></param>
/// <param name="checksum"></param>
/// <param name="secret"></param>
/// <returns></returns>
public static bool ValidateRevisionChecksum (this XLoginResponse source, string checksum, string secret) {
//
var xChecksum = source.GetRevisionChecksum (secret);
return checksum == xChecksum;
}
/// <summary>
/// Check an XTokenResponse instance is Valid with it's revision
/// </summary>
/// <param name="source"></param>
/// <param name="checksum"></param>
/// <param name="secret"></param>
/// <returns></returns>
public static bool ValidateRevisionChecksum (this XTokenResponse source, string checksum, string secret) {
//
var xChecksum = source.GetRevisionChecksum (secret);
return checksum == xChecksum;
}
/// <summary>
/// Retrieve Exception Details if Fails
/// </summary>
/// <param name="source"></param>
/// <returns></returns>
public static Exception GetException (this TokenResponse source) {
//
// Validate Args ...
if (source.IsNull () || !source.IsError) {
return XException.ActionFailed.ToException ();
}
//
XError error = source.ErrorDescription.FromJSON<XError> ();
return error.ToException ();
}
/// <summary>
/// Convert XTokenResponse to Header Dictionary
/// </summary>
/// <param name="source"></param>
/// <returns></returns>
public static IDictionary<string, string> ToHeaderDictionary (this XTokenResponse source) {
//
var result = new Dictionary<string, string> { { XAuthorization.RefreshToken, source.RefreshToken },
{ XAuthorization.ExpiresAt, source.ExpiresAt.ToString () }
};
//
return result;
}
}
@@ -0,0 +1,55 @@
using xCommons.Extensions;
using xIdentityModels.Constants;
using xIdentityModels.Models;
namespace xIdentityService.Extensions {
public static class XUserClaimsInfoDtoExtensions {
public static string GetUserSelectByParam (
this XUserClaimsInfoDto source,
XUserSelectBy userSelectBy = XUserSelectBy.Username
) {
//
var result = "";
//
switch (userSelectBy) {
//
case XUserSelectBy.ID:
result = source.UserId;
break;
//
case XUserSelectBy.Username:
result = source.UserName;
break;
//
case XUserSelectBy.Email:
result = source.Email;
break;
//
case XUserSelectBy.MobileNumber:
result = source.PhoneNumber;
break;
}
//
if (result.IsNullOrEmpty ()) {
//
if (!source.UserId.IsNullOrEmpty ()) {
result = source.UserId;
} else if (!source.UserName.IsNullOrEmpty ()) {
result = source.UserName;
} else if (!source.Email.IsNullOrEmpty ()) {
result = source.Email;
} else if (!source.PhoneNumber.IsNullOrEmpty ()) {
result = source.PhoneNumber;
}
}
//
return result;
}
}
}
View File
+283
View File
@@ -0,0 +1,283 @@
using System.Collections.Generic;
using System.Threading.Tasks;
using IdentityModel.Client;
using Microsoft.AspNetCore.Http;
using RestSharp;
using xHttpService.Constants;
using xIdentityModels.Constants;
using xIdentityModels.Dtos;
using xIdentityModels.Models;
using xIdentityModels.Navigations;
using xModels.Dtos;
namespace xIdentityService.Interfaces {
public partial interface IXIdentityProvider {
//
string BaseUrl { get; }
string RevisionSecretKey { get; }
//
#region Tools ...
string GetUserSelectByParam (
XActionRequest model,
bool forceNotNull = true,
ICollection<XUserSelectBy> excludes = null
);
#endregion
//
#region Tools ...
Task<T> RunRestRequest<T> (
RestClient client,
RestRequest request,
XHttpMethod method,
bool supportRefreshingTokens = false
);
#endregion
//
#region Authentication ...
Task<DiscoveryDocumentResponse> RequestDiscoveryDocument ();
Task<XTokenResponse> RequestScopeAccessToken (string scope);
Task<TokenIntrospectionResponse> Introspection (XTokenResponse model);
Task<XLoginResponse> Login (XLoginRequest model);
Task Logout (XTokenResponse model);
Task<XTokenResponse> Authenticate (XLoginRequest model);
Task<XTokenResponse> RefreshTokens (XTokenResponse model);
Task ChangePassword (
XTokenResponse tokens,
XActionRequest model
);
#endregion
//
#region Profile ...
Task<IEnumerable<string>> GetUserNames (
XTokenResponse tokens,
string userIds
);
Task<IEnumerable<XUserNameIdResponse>> GetUserNameIds (
XTokenResponse tokens,
XUserNameIdRequest model
);
Task<XUserProfileDto> GetUserProfile (
XTokenResponse tokens,
string userSelectByParam
);
Task<XQueryResult<XUserProfileDto>> QueryUsers (
XTokenResponse tokens,
XQuery query
);
Task<XQueryResult<XUserProfileDto>> QueryInRoleUsers (
XTokenResponse tokens,
string role,
XQuery query,
bool forceRole = false
);
Task<XQueryResult<XProfileImage>> QueryAvatars (
XTokenResponse tokens,
string userSelectByParam,
XQuery query
);
Task<XUserProfileDto> ProfileUpdateAsync (
XTokenResponse tokens,
string userSelectByParam,
XProfileUpdateRequest model
);
Task<XUserProfileDto> FullProfileUpdateAsync (
XTokenResponse tokens,
string userSelectByParam,
XProfileUpdateRequest request
);
Task<XUserProfileDto> AddAvatar (
XTokenResponse tokens,
IFormFile file
);
Task<XUserProfileDto> AddAvatars (
XTokenResponse tokens,
IFormFileCollection files
);
Task<XUserProfileDto> SetAvatar (
XTokenResponse tokens,
int avatarId
);
Task<XUserProfileDto> RemoveAvatars (
XTokenResponse tokens,
string avatarIds
);
#endregion
//
#region Registration ...
Task<bool> CanRegister (string userSelectByParam);
Task<XActionResponse> InviteUser (
XTokenResponse tokens,
XActionRequest model
);
Task<XActionResponse> RequestRegistration (
XActionRequest model
);
Task<XActionResponse> AddAccountInfo (
XActionRequest model
);
Task<XActionResponse> AttachProfileImage (
string actionToken,
IFormFile file
);
Task FinishRegistration (XActionRequest model);
Task<bool> IsConfirmedEmail (
XTokenResponse tokens,
string userSelectByParam
);
Task<bool> IsConfirmedMobile (
XTokenResponse tokens,
string userSelectByParam
);
Task RequestConfirmRegistration (XActionRequest model);
Task ConfirmRegistration (
XActionRequest model
);
Task<XActionResponse> RequestConfirmMobile (XActionRequest model);
Task<XActionResponse> ConfirmMobileNumber (XActionRequest model);
Task<XActionResponse> RequestConfirmEmail (XActionRequest model);
Task<XActionResponse> ConfirmEmailAddress (XActionRequest model);
Task<XActionResponse> RequestResetPassword (XActionRequest model);
Task ResetPassword (XActionRequest model);
#endregion
//
#region Friendship ...
Task<XFriendshipFollowing> Follow (
XTokenResponse tokens,
string destUser
);
Task<bool> Cancel (
XTokenResponse tokens,
string destUser
);
Task UnFollowFollower (
XTokenResponse tokens,
string destUser
);
Task UnFollowFollowing (
XTokenResponse tokens,
string destUser
);
Task<XFriendshipFollowing> Block (
XTokenResponse tokens,
string destUser
);
Task<XFriendshipFollowing> UnBlock (
XTokenResponse tokens,
string destUser
);
Task<XFriendshipFollower> AcceptRequest (
XTokenResponse tokens,
string destUser
);
Task<XFriendshipFollower> RejectRequest (
XTokenResponse tokens,
string destUser
);
Task<bool> IsFollower (
XTokenResponse tokens,
string destUser
);
Task<XFriendshipFollower> GetFollower (
XTokenResponse tokens,
string destUser
);
Task<XFriendshipState> GetFollowerState (
XTokenResponse tokens,
string destUser
);
Task<IEnumerable<XFriendshipFollower>> GetFollowers (XTokenResponse tokens);
Task<IEnumerable<XFriendshipFollower>> GetAllFollowers (XTokenResponse tokens);
Task<bool> IsFollowing (
XTokenResponse tokens,
string destUser
);
Task<XFriendshipFollowing> GetFollowing (
XTokenResponse tokens,
string destUser
);
Task<XFriendshipState> GetFollowingState (
XTokenResponse tokens,
string destUser
);
Task<IEnumerable<XFriendshipFollowing>> GetFollowings (XTokenResponse tokens);
Task<IEnumerable<XFriendshipFollowing>> GetAllFollowings (XTokenResponse tokens);
Task<IEnumerable<string>> GetFollowingList (XTokenResponse tokens);
Task<IEnumerable<string>> GetFollowersList (XTokenResponse tokens);
Task<XFriendshipInfoDto> GetFriendshipInfo (
XTokenResponse tokens,
string destUser
);
#endregion
//
#region Admin ...
Task<IEnumerable<string>> Ban (
XTokenResponse tokens,
XUserNameIdRequest model
);
Task<IEnumerable<string>> UnBan (
XTokenResponse tokens,
XUserNameIdRequest model
);
Task<bool> IsBanned (
XTokenResponse tokens,
string userSelectByParam
);
#endregion
}
}
+67
View File
@@ -0,0 +1,67 @@
using System;
using System.Collections.Generic;
using System.Linq.Expressions;
using xIdentityService.Configuration;
namespace xIdentityService.Interfaces {
public interface IXProxyHelper {
/// <summary>
/// Proxy Configuration ...
/// </summary>
/// <value></value>
XProxyConfiguration Configuration { get; }
/// <summary>
/// retrie Normalize Host ...
/// </summary>
/// <returns></returns>
string NormalizeHost ();
/// <summary>
/// Validate XProxy Configuration for Client ...
/// </summary>
/// <returns></returns>
bool ValidateConfiguration ();
/// <summary>
/// Retrieve all Prepared url of Routes ...
/// </summary>
/// <returns></returns>
IEnumerable<string> GetRouteUrls ();
/// <summary>
/// retrieve all registred Routes ...
/// </summary>
/// <returns></returns>
IEnumerable<XProxyRouteDescriptor> GetRoutes ();
/// <summary>
/// Prepare a request url for a Proxy Route ...
/// </summary>
/// <param name="url"></param>
/// <param name="descriptor"></param>
/// <returns></returns>
string PrepareActionUrlForXProxyRoute (
string url,
XProxyRouteDescriptor descriptor
);
/// <summary>
/// Prepare a request url for a Selected Proxy Route ...
/// </summary>
/// <param name="url"></param>
/// <param name="whereClause"></param>
/// <returns></returns>
string PrepareActionUrlForXProxyRoute (
string url,
Expression<Func<XProxyRouteDescriptor, bool>> whereClause
);
/// <summary>
/// Find an Specific Route ...
/// </summary>
/// <param name="whereClause"></param>
/// <returns></returns>
XProxyRouteDescriptor FindRoute (Expression<Func<XProxyRouteDescriptor, bool>> whereClause);
}
}
+10
View File
@@ -0,0 +1,10 @@
namespace xIdentityService.Interfaces
{
public partial interface IXSecurityProvider
{
string Encrypt(string plainText);
string Decrypt(string cipherText);
string EncryptFromBytes(byte[] textBytes);
string DecryptFromBytes(byte[] cipherBytes);
}
}
+15
View File
@@ -0,0 +1,15 @@
using System.Threading.Tasks;
using xIdentityModels.Models;
namespace xIdentityService.Interfaces {
public partial interface IXTokenProvider {
Task<bool> IsTokenExists (string accessToken);
Task<bool> IsTokenExists (XTokenResponse tokens);
Task<bool> RemoveToken (string accessToken);
Task<bool> RemoveToken (XTokenResponse tokens);
Task<XTokenResponse> RetrieveToken (string accessToken);
Task<bool> AddToken (XTokenResponse tokens);
Task<bool> UpdateToken (XTokenResponse tokens);
Task<bool> AddOrUpdateToken (XTokenResponse tokens);
}
}
+182
View File
@@ -0,0 +1,182 @@
using System;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using xCommons.Constants;
using xCommons.Extensions;
using xIdentityModels.Extensions;
using xIdentityService.Interfaces;
namespace xIdentityService.Middlewares {
public partial class XIdentityTokenRefresherMiddleware {
//
#region Properties ...
private readonly ILogger logger;
private readonly RequestDelegate next;
private readonly IXTokenProvider tokenProvider;
private readonly IXIdentityProvider identityProvider;
#endregion
//
#region Constructor ...
public XIdentityTokenRefresherMiddleware (
RequestDelegate next,
ILoggerFactory loggerFactory,
IXTokenProvider tokenProvider,
IXIdentityProvider identityProvider
) {
//
this.next = next;
this.tokenProvider = tokenProvider;
this.identityProvider = identityProvider;
this.logger = loggerFactory
.CreateLogger<XIdentityTokenRefresherMiddleware> ();
}
#endregion
//
#region Actions ...
public async Task Invoke (HttpContext context) {
//
// Handle Request ...
await HandleRequest (context);
//
// Do Main Task ...
try {
await next.Invoke (context);
} catch (Exception ex) {
logger.LogError ($"Error: {ex.Message}");
}
//
// Handle Response ...
await HandleResponse (context);
}
#endregion
//
#region Private ...
private async Task HandleRequest (HttpContext context) {
//
// Log ...
logger.LogInformation ($"Start Process Request ...");
//
// Check Access Token ...
var hasAccessToken = HasAccessToken (context);
if (!hasAccessToken) {
return;
}
//
// Check Access Token ...
var accessToken = GetAccessToken (context);
var isExists = await tokenProvider
.IsTokenExists (accessToken);
if (!isExists) {
return;
}
//
// Try Check is Refreshable ...
var tokens = await tokenProvider
.RetrieveToken (accessToken);
if (tokens.IsNull ()) {
return;
}
//
// Check is Expired or Refreshable ...
var isRefreshable = tokens.IsRefreshable ();
if (!isRefreshable) {
return;
}
//
// Refresh Token ...
var refreshedTokens = await identityProvider
.RefreshTokens (tokens);
if (refreshedTokens.IsNull ()) {
return;
}
//
// Set Refreshed AccessToken to Request ...
context
.Request
.Headers[XAuthorization.Header] =
$"{XAuthorization.TokenIdentifier}{refreshedTokens.AccessToken}";
}
private async Task HandleResponse (HttpContext context) {
//
// Log ...
logger.LogInformation ($"Start Process Response ...");
//
await Task.Run (() => { });
}
private bool HasAccessToken (HttpContext context) {
//
// Check Headers ...
if (context.IsNull () ||
context.Request.IsNull () ||
context.Request.Headers.IsNull ()) {
return false;
}
//
var result = context
.Request
.Headers
.ContainsKey (
XAuthorization.Header
);
//
return result;
}
private string GetAccessToken (HttpContext context) {
//
var hasAccessToken = HasAccessToken (context);
if (!hasAccessToken) {
return string.Empty;
}
//
// Get Result ...
var result = context
.Request
.Headers[
XAuthorization.Header
];
result = result
.ToString ()
.Replace (
XAuthorization.TokenIdentifier,
""
);
//
return result;
}
#endregion
}
/// <summary>
/// Provide all DI Requirements for XIdentityTokenRefresher Middleware
/// </summary>
public static class XIdentityTokenRefresherDIHelper {
/// <summary>
/// Use XTokenValidator Middleware
/// </summary>
/// <param name="app"></param>
public static void UseXIdentityTokenRefresher (this IApplicationBuilder app) {
app.UseMiddleware<XIdentityTokenRefresherMiddleware> ();
}
}
}
+827
View File
@@ -0,0 +1,827 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
using System.Web;
using IdentityModel;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.WebUtilities;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using xCommons.Extensions;
using xExceptions.Constants;
using xIdentityService.Configuration;
using xIdentityService.Constants;
using xIdentityService.Interfaces;
using xIdentityService.Providers;
using xModels.Base;
namespace xIdentityService.Middlewares {
/// <summary>
/// Proxy Server Middleware ...
/// </summary>
public class XProxyMiddleware : XBaseClass {
//
#region Pros ...
private readonly HttpClient HTTP_CLIENT;
private readonly RequestDelegate NEXT_MIDDLEWARE;
private readonly XProxyConfiguration CONFIGURATION;
#endregion
//
#region Constructor ...
public XProxyMiddleware (
ILoggerFactory loggerFactory,
RequestDelegate nextMiddleware,
XProxyConfiguration configuration,
IHttpClientFactory httpClientFactory
) : base (loggerFactory) {
//
this.CONFIGURATION = configuration;
this.NEXT_MIDDLEWARE = nextMiddleware;
//
// Create Http Client ...
this.HTTP_CLIENT = httpClientFactory
.CreateClient (XProxyConstants.XPROXY_HTTP_CLIENT);
//
// Logging Server Configuration ...
LogXProxyServerConfig ();
}
#endregion
//
#region Public ...
public async Task InvokeAsync (HttpContext context) {
//
#region Bussiness Logic ...
//
var routeDescriptor = GetRouteDescriptor (context.Request);
if (!routeDescriptor.IsNull ()) {
//
#region Handle Authorization ...
//
try {
//
// Handle XPowered ...
if (routeDescriptor.EnableXPoweredByAthorization) {
//
var isPoweredByPass = context.Request.Headers
.Any (h => h.Key
.ToNormalString () == xCommons.Constants.XAuthorization.XPoweredBy
.ToNormalString () &&
h.Value
.ToString ()
.ToNormalString () == CONFIGURATION.XPoweredValue
.ToNormalString ()
);
//
if (!isPoweredByPass) {
ThrowNotAuthorizedException ();
}
}
//
// Handle EndableAuthorization ...
if (routeDescriptor.EnableAuthorization) {
//
// Retrieve User Info for Authentication ...
var userName = context.User.Identity.Name;
var isUserAuthenticated = !userName.IsNull () &&
context.User.Identity.IsAuthenticated;
if (!isUserAuthenticated &&
!routeDescriptor.AllowedScopes.HasChild ()
) {
ThrowNotAuthorizedException ();
}
//
// Check Allowed Scopes Authorization ...
if (routeDescriptor.AllowedScopes.HasChild ()) {
//
var scopeClaims = context.User.Claims
.Where (c => c.Type == JwtClaimTypes.Scope)
.Select (c => c.Value);
var isScopePassed = scopeClaims.HasChild () &&
scopeClaims.Any (c => routeDescriptor.AllowedScopes
.Any (allowedScope => allowedScope
.ToNormalString () == c
.ToNormalString ()
)
);
if (!isScopePassed) {
ThrowNotAuthorizedException ();
}
}
//
// Check Allowed Roles Authorization ...
if (
isUserAuthenticated &&
routeDescriptor.AllowedRoles.HasChild ()
) {
//
var roleClaim = context.User.Claims
.FirstOrDefault (c => c.Type == JwtClaimTypes.Role);
var isRolePassed = !roleClaim.IsNull () &&
routeDescriptor.AllowedRoles
.Any (role => role
.ToNormalString () == roleClaim.Value
.ToNormalString ());
if (!isRolePassed) {
ThrowNotAuthorizedException ();
}
}
}
} catch {
context.Response.StatusCode = (int) HttpStatusCode.Unauthorized;
return;
}
#endregion
//
// Extract Request Uri from Received Request ...
var requestUri = GetUri (context.Request);
if (!requestUri.IsNull ()) {
//
// Retrieve Request based on current ...
var request = GetRequestMessage (
uri: requestUri,
context: context
);
//
SendLog ($"Send Request to Recieve Response ...", LogLevel.Information);
//
// Send Request and Retrieve Response ...
try {
//
var response = await HTTP_CLIENT.SendAsync (
request,
HttpCompletionOption.ResponseContentRead
);
//
// Set Current Response Status Code ...
context.Response.StatusCode = (int) response.StatusCode;
//
// Retrieve Response Headers and Set To Current Response ...
HandleResponseHeaders (context, response);
//
// Processing Response Content ...
await ProcessResponseContent (context, response);
} catch (Exception ex) {
//
LogMessage ($"Exception: {ex.Message}", LogLevel.Error);
//
context.Response.StatusCode = (int) HttpStatusCode.BadRequest;
}
//
return;
}
}
#endregion
//
await NEXT_MIDDLEWARE (context);
}
#endregion
//
#region Private ...
/// <summary>
/// Throw Required Exception ...
/// </summary>
private void ThrowNotAuthorizedException () {
throw XException.NotAuthorized.ToException ();
}
/// <summary>
/// Show propper logs if Enabled ...
/// </summary>
/// <param name="message"></param>
/// <param name="logLevel"></param>
private void SendLog (string message, LogLevel logLevel = LogLevel.Information) {
//
if (!CONFIGURATION.EnableLogging) {
return;
}
//
LogMessage (
message: message,
logLevel: logLevel
);
}
/// <summary>
/// Log Proxy Server Configuration ...
/// </summary>
private void LogXProxyServerConfig () {
//
// Retrieve XProxyConfiguration class from Configurations and Validate them ...
if (CONFIGURATION.IsNull ()) {
throw XException.InvalidConfiguration.ToException ();
}
//
// Try to Log Proxy Configuration ...
ConsoleMessage ("===============================");
ConsoleMessage ("= Proxy Server Configurations: ");
ConsoleMessage ("===============================");
//
ConsoleMessage ($"Host: {CONFIGURATION.Host}");
ConsoleMessage ($"XPoweredValue: {CONFIGURATION.XPoweredValue}");
ConsoleMessage ($"EnableLogging: {CONFIGURATION.EnableLogging}");
ConsoleMessage ($"DisableSSLCheck: {CONFIGURATION.DisableSSLCheck}");
ConsoleMessage ($"AllowAutoRedirect: {CONFIGURATION.AllowAutoRedirect}");
ConsoleMessage ($" ");
ConsoleMessage ($"Routes: ");
ConsoleMessage ($" ");
//
CONFIGURATION.Routes
.ToList ()
.ForEach (routeDescriptor => {
ConsoleMessage ("===============================");
ConsoleMessage ($"= Rote => {routeDescriptor.Route}");
ConsoleMessage ("===============================");
ConsoleMessage ($"AllowedRoles: {routeDescriptor.AllowedRoles.ToJSON()}");
ConsoleMessage ($"AllowedScopes: {routeDescriptor.AllowedScopes.ToJSON()}");
ConsoleMessage ($"EnableAuthorization: {routeDescriptor.EnableAuthorization}");
ConsoleMessage ($"EnableXPoweredByAthorization: {routeDescriptor.EnableXPoweredByAthorization}");
ConsoleMessage ($" ");
});
}
/// <summary>
/// Retrieve Destination Request Path based on Current Request ...
/// </summary>
/// <param name="request"></param>
/// <returns></returns>
private Uri GetUri (HttpRequest request) {
//
// Create temp result ...
Uri result = null;
var requestPath = "";
//
SendLog ($"Receive Request: {request.Path} ...", LogLevel.Information);
//
// Try to Findout Route Descriptor ...
var routeDescriptor = GetRouteDescriptor (request);
//
// Route Descriptor Exists && Path for Delegating ...
if (!routeDescriptor.IsNull () &&
request.Path
.StartsWithSegments (routeDescriptor.Route)
) {
//
// Prepare Request Path by Cleaning Starter Path Segment ...
requestPath = request.Path
.ToString ()
.Replace (routeDescriptor.Route, "");
if (requestPath.StartsWith ("/")) {
requestPath = requestPath.Substring (1);
}
//
// Decoding URL ...
requestPath = HttpUtility.UrlDecode (requestPath);
//
var colonIndex = requestPath.IndexOf (":");
if (colonIndex > -1) {
//
var doubleSlash = requestPath.Substring (colonIndex + 1, 2);
var isDoubleSlash = doubleSlash == "//";
//
if (!isDoubleSlash) {
//
var protocol = requestPath
.Substring (0, colonIndex);
var section = requestPath
.Substring (colonIndex + 2, requestPath.Length - colonIndex - 2);
//
requestPath = $"{protocol}://{section}";
}
}
}
//
// Validate Request Path ...
if (!requestPath.IsNullOrEmpty ()) {
//
result = new Uri (requestPath);
//
SendLog ($"Process Request: {requestPath} ...", LogLevel.Information);
}
//
return result;
}
/// <summary>
/// Retrieve Propper Request Message based on HttpContext and uri ...F
/// </summary>
/// <param name="context"></param>
/// <param name="uri"></param>
/// <returns></returns>
private HttpRequestMessage GetRequestMessage (
HttpContext context,
Uri uri
) {
//
var result = new HttpRequestMessage ();
FillRequest (context, result);
//
// Handle Queries ...
SendLog ($"Start Processing Queries: ");
foreach (var query in context.Request.Query) {
//
var key = query.Key;
var value = HttpUtility.UrlDecode (query.Value);
//
uri = new Uri (
QueryHelpers.AddQueryString (
uri.OriginalString,
new Dictionary<string, string> {
[key] = value
}
)
);
//
SendLog ($"Query : {key}:{value} was Processed ...");
}
//
result.RequestUri = uri;
result.Headers.Host = uri.Host;
//
// Retrieve Request Method ...
result.Method = GetMethod (context.Request.Method);
//
return result;
}
/// <summary>
/// Fill Request Message by provide HttpContext ...
/// </summary>
/// <param name="context"></param>
/// <param name="message"></param>
private void FillRequest (
HttpContext context,
HttpRequestMessage message
) {
//
var requestMethod = context.Request.Method;
//
if (!HttpMethods.IsGet (requestMethod) &&
!HttpMethods.IsHead (requestMethod) &&
!HttpMethods.IsTrace (requestMethod) &&
!HttpMethods.IsDelete (requestMethod)
) {
//
var streamContent = new StreamContent (context.Request.Body);
message.Content = streamContent;
}
//
// Handle Base Headers ...
var regularHeaders = context.Request.Headers
.Where (hr => hr.Key != XProxyConstants.XPROXY_ACCEPTED_HEADERS &&
!hr.Key
.Contains (
XProxyConstants.XPROXY_FORWARD_HEADER
)
);
//
// Handle Aceepted Headers ...
IEnumerable<string> acceptedHeaders = null;
var acceptedHeadersKeyValue = context.Request.Headers
.FirstOrDefault (hr =>
hr.Key == XProxyConstants.XPROXY_ACCEPTED_HEADERS
);
if (!acceptedHeadersKeyValue.IsNull ()) {
//
acceptedHeaders = acceptedHeadersKeyValue.Value
.ToString ()
.ParseListString<string> ();
//
// Filter Regular Headers ...
if (
regularHeaders.HasChild () &&
acceptedHeaders.HasChild ()
) {
//
regularHeaders = regularHeaders
.Where (rhr => acceptedHeaders
.Contains (rhr.Key)
);
}
}
foreach (var header in regularHeaders) {
//
SendLog ($"Adding Header: {header.Key}:{header.Value} ...");
//
message.Headers.Add (
header.Key,
header.Value
.ToString ()
);
}
//
// Handle ForWarded Headers ...
// Since Forward Headers is Custom kind, this means user actually need this
// Header, so there is no need to put them on AcceptedHeaders ...
var forwardHeaders = context.Request.Headers
.Where (hr => hr.Key
.Contains (
XProxyConstants.XPROXY_FORWARD_HEADER
)
);
foreach (var header in forwardHeaders) {
//
var key = header.Key
.Replace (
XProxyConstants.XPROXY_FORWARD_HEADER,
string.Empty
);
//
SendLog ($"Forwarding Header: {header.Key} to {key} ...");
//
message.Headers
.Add (
key,
header.Value
.ToString ()
);
}
}
/// <summary>
/// Retreive and Extract Method Type of HttpRequest ...
/// </summary>
/// <param name="method"></param>
/// <returns></returns>
private static HttpMethod GetMethod (string method) {
//
if (HttpMethods.IsDelete (method)) {
return HttpMethod.Delete;
} else if (HttpMethods.IsGet (method)) {
return HttpMethod.Get;
} else if (HttpMethods.IsHead (method)) {
return HttpMethod.Head;
} else if (HttpMethods.IsOptions (method)) {
return HttpMethod.Options;
} else if (HttpMethods.IsPost (method)) {
return HttpMethod.Post;
} else if (HttpMethods.IsPut (method)) {
return HttpMethod.Put;
} else if (HttpMethods.IsTrace (method)) {
return HttpMethod.Trace;
}
//
return new HttpMethod (method);
}
/// <summary>
/// add all headers exists in HttpResponse MEssage to Current Context Response Headers ...
/// </summary>
/// <param name="context"></param>
/// <param name="message"></param>
private void HandleResponseHeaders (
HttpContext context,
HttpResponseMessage message
) {
//
// Handle Message Headers ...
foreach (var header in message.Headers) {
context.Response.Headers[header.Key] = header.Value
.ToArray ();
}
//
// Handle Message Content Headers ...
foreach (var header in message.Content.Headers) {
context.Response.Headers[header.Key] = header.Value
.ToArray ();
}
//
context.Response.Headers.Remove ("transfer-encoding");
}
/// <summary>
/// Processing Response Content and Handle it on HttpContextResponse ...
/// </summary>
/// <param name="context"></param>
/// <param name="response"></param>
/// <returns></returns>
private async Task ProcessResponseContent (
HttpContext context,
HttpResponseMessage message
) {
//
// Reading Content as Byte Array ...
var contentBytes = await message.Content
.ReadAsByteArrayAsync ();
//
// Check ContentType of Response ...
if (
IsContentOfType (message, XResponseContentTypes.HTML) ||
IsContentOfType (message, XResponseContentTypes.JSON) ||
IsContentOfType (message, XResponseContentTypes.JavaScript)
) {
//
// If their String Content ...
var stringContent = Encoding.UTF8.GetString (contentBytes);
//
// TODO: here we can change String Contents ...
//
// Writing new Content to Response ...
await context.Response
.WriteAsync (
stringContent,
Encoding.UTF8
);
} else {
//
// if they have non string content ...
await context.Response.Body
.WriteAsync (
buffer: contentBytes,
offset: 0,
count: contentBytes.Length
);
}
//
SendLog ($"Response Content Processed ...", LogLevel.Information);
}
/// <summary>
/// Check Content Type of Specific Response ...
/// </summary>
/// <param name="response"></param>
/// <param name="type"></param>
/// <returns></returns>
private bool IsContentOfType (
HttpResponseMessage response,
string type
) {
//
// Create EMpty Result ...
var result = false;
//
// Retrieve and Check Content Type of Response ...
if (response.Content?.Headers?.ContentType != null) {
result = response.Content.Headers.ContentType.MediaType == type;
}
//
return result;
}
/// <summary>
/// Retrieve and Extract Route Descriptor ...
/// </summary>
/// <param name="request"></param>
/// <returns></returns>
private XProxyRouteDescriptor GetRouteDescriptor (HttpRequest request) {
//
// Validate Args ...
if (
CONFIGURATION.IsNull () ||
!CONFIGURATION.Routes.HasChild ()
) {
return null;
}
//
var result = CONFIGURATION.Routes
.FirstOrDefault (rd => !rd.Route.IsNullOrEmpty () &&
request.Path
.StartsWithSegments (rd.Route
.ToNormalString ()
)
);
//
return result;
}
#endregion
}
/// <summary>
/// Provide all requirements for Dependency Injection Handler ...
/// </summary>
public static class XDIHelperExtension {
/// <summary>
/// Retrieve XProxy Middelware Configuration from Configuration ...
/// </summary>
/// <param name="config"></param>
/// <returns></returns>
public static XProxyConfiguration GetXProxyConfiguration (this IConfiguration config) {
//
var xProxyConfiguration = config.GetSection (ConfigurationNodeNames.XPROXY_CONFIGURATION_NODE_NAME);
return xProxyConfiguration.Get<XProxyConfiguration> ();
}
/// <summary>
/// Register HTTP Handler for XProxy Server ...
/// </summary>
/// <param name="services"></param>
/// <param name="configuration"></param>
/// <param name="httpHandler"></param>
public static void AddXProxyHttpHandler (
this IServiceCollection services,
IConfiguration configuration,
HttpClientHandler httpHandler = null
) {
//
var proxyConfig = configuration.GetXProxyConfiguration ();
if (proxyConfig.IsNull ()) {
throw XException.InvalidConfiguration.ToException ();
}
//
services.AddXProxyHttpHandler (
httpHandler: httpHandler,
configuration: proxyConfig
);
}
/// <summary>
/// Register HTTP Handler for XProxy Server ...
/// </summary>
/// <param name="services"></param>
/// <param name="configuration"></param>
/// <param name="httpHandler"></param>
public static void AddXProxyHttpHandler (
this IServiceCollection services,
XProxyConfiguration configuration,
HttpClientHandler httpHandler = null
) {
//
if (configuration.IsNull ()) {
throw XException.InvalidConfiguration.ToException ();
}
//
if (httpHandler.IsNull ()) {
httpHandler = new HttpClientHandler ();
}
//
httpHandler.AllowAutoRedirect = configuration.AllowAutoRedirect;
//
if (configuration.DisableSSLCheck) {
httpHandler.ServerCertificateCustomValidationCallback = (sender, certificate, chain, sslPolicyErrors) => true;
}
//
services
.AddHttpClient (XProxyConstants.XPROXY_HTTP_CLIENT)
.ConfigurePrimaryHttpMessageHandler (() => {
return httpHandler;
});
}
/// <summary>
/// Register XProxy On Server ...
/// </summary>
/// <param name="services"></param>
/// <param name="configuration"></param>
/// <param name="httpHandler"></param>
public static void AddXProxyServer (
this IServiceCollection services,
IConfiguration configuration,
HttpClientHandler httpHandler = null
) {
//
var proxyConfig = configuration.GetXProxyConfiguration ();
//
services.AddXProxyServer (
httpHandler: httpHandler,
configuration: proxyConfig
);
}
/// <summary>
/// Register XProxy On Server ...
/// </summary>
/// <param name="services"></param>
/// <param name="configuration"></param>
/// <param name="httpHandler"></param>
public static void AddXProxyServer (
this IServiceCollection services,
XProxyConfiguration configuration,
HttpClientHandler httpHandler = null
) {
//
// Validate Args ...
if (configuration.IsNull ()) {
throw XException.InvalidConfiguration.ToException ();
}
//
// Register Proxy Configuration ...
services.AddSingleton<XProxyConfiguration> (configuration);
//
// Regiter Proxy Handler ...
services.AddXProxyHttpHandler (
httpHandler: httpHandler,
configuration: configuration
);
}
/// <summary>
/// Register XProxy On Server ...
/// </summary>
/// <param name="services"></param>
/// <param name="configuration"></param>
public static void AddXProxyClient (
this IServiceCollection services,
IConfiguration configuration
) {
//
var proxyConfig = configuration.GetXProxyConfiguration ();
//
services.AddXProxyClient (
configuration: proxyConfig
);
}
/// <summary>
/// Register XProxy On Client ...
/// </summary>
/// <param name="services"></param>
/// <param name="configuration"></param>
public static void AddXProxyClient (
this IServiceCollection services,
XProxyConfiguration configuration
) {
//
// Validate Args ...
if (configuration.IsNull ()) {
throw XException.InvalidConfiguration.ToException ();
}
//
// Register Proxy Configuration ...
services.AddSingleton<XProxyConfiguration> (configuration);
//
// Register IXProxyHelper ...
services.AddSingleton<IXProxyHelper, XProxyHelper> ();
}
/// <summary>
/// Adding XProxy Middleware to Applications ...
/// </summary>
/// <param name="app"></param>
public static void UseXProxy (this IApplicationBuilder app) {
app.UseMiddleware<XProxyMiddleware> ();
}
}
}
+129
View File
@@ -0,0 +1,129 @@
using System.Collections.Generic;
using System.Threading.Tasks;
using xCommons.Extensions;
using xHttpService.Constants;
using xIdentityModels.Dtos;
using xIdentityModels.Models;
using xIdentityService.Constants;
namespace xIdentityService.Providers {
public partial class XIdentityProvider {
//
#region Admin ...
/// <summary>
/// Ban Specific Users
/// </summary>
/// <param name="tokens">Authentication Tokens</param>
/// <param name="model">an instance of <see>XUserNameIdRequest</see> which represents user identifier list to Ban</param>
/// <returns>a list of banned users identifiers</returns>
public async Task<IEnumerable<string>> Ban (
XTokenResponse tokens,
XUserNameIdRequest model
) {
//
// Validate Args ...
await validationProvider
.GroupValidationBuilder ()
.AddNotNull (
tokens,
model
)
.AddNotEmpty (tokens.AccessToken)
.AddNotZeroChilds (model.Ids)
.ValidateGroupAsync ();
//
var client = GetRestClient (tokens);
//
var request = GetRestRequet (XApiAccountEndpoint.Ban);
request.AddJsonBody (model);
//
var response = await RunRestRequest<IEnumerable<string>> (
client,
request,
XHttpMethod.POST
);
return response;
}
/// <summary>
/// UnBann Specific Users
/// </summary>
/// <param name="tokens">Authentication Tokens</param>
/// <param name="model">an instance of <see>XUserNameIdRequest</see> which represents user identifier list to Ban</param>
/// <returns>a list of unbanned users identifiers</returns>
public async Task<IEnumerable<string>> UnBan (
XTokenResponse tokens,
XUserNameIdRequest model
) {
//
// Validate Args ...
await validationProvider
.GroupValidationBuilder ()
.AddNotNull (
tokens,
model
)
.AddNotEmpty (tokens.AccessToken)
.AddNotZeroChilds (model.Ids)
.ValidateGroupAsync ();
//
var client = GetRestClient (tokens);
//
var request = GetRestRequet (XApiAccountEndpoint.UnBan);
request.AddJsonBody (model);
//
var response = await RunRestRequest<IEnumerable<string>> (
client,
request,
XHttpMethod.POST
);
return response;
}
/// <summary>
/// Check Specific User is Banned or not
/// </summary>
/// <param name="tokens">Authentication Tokens</param>
/// <param name="userSelectByParam">specified user's identifier</param>
/// <returns>a boolean value which represent user banned or not</returns>
public async Task<bool> IsBanned (
XTokenResponse tokens,
string userSelectByParam
) {
//
// Validate Args ...
await validationProvider
.GroupValidationBuilder ()
.AddNotNull (tokens)
.AddNotEmpty (
userSelectByParam,
tokens.AccessToken
)
.ValidateGroupAsync ();
//
var client = GetRestClient (tokens);
//
var request = GetRestRequet (
XApiAccountEndpoint.IsBanned,
@params : new Dictionary<string, string> { { XParam.XUserSelectByParam.GetStringValue (), userSelectByParam } }
);
//
var response = await RunRestRequest<bool> (
client,
request,
XHttpMethod.GET
);
return response;
}
#endregion
}
}
+317
View File
@@ -0,0 +1,317 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using IdentityModel.Client;
using xCommons.Extensions;
using xExceptions.Constants;
using xHttpService.Constants;
using xIdentityModels.Extensions;
using xIdentityModels.Models;
using xIdentityService.Constants;
namespace xIdentityService.Providers {
public partial class XIdentityProvider {
//
#region Authentication Handlers ...
/// <summary>
/// Request for Discovery Document
/// </summary>
/// <returns>an instance of DiscoveryDocumentResponse</returns>
public async Task<DiscoveryDocumentResponse> RequestDiscoveryDocument () {
//
var httpClient = GetHttpClient ();
//
try {
//
var result = httpClient
.GetDiscoveryDocumentAsync (identityConfiguration.Authority)
.ContinueWith (docTask => {
//
httpClient.Dispose ();
return docTask.Result;
});
//
return await result;
} catch {
throw XException.ActionFailed.ToException ();
}
}
/// <summary>
/// Request AccessToken for Specific XApiScope
/// </summary>
/// <param name="scope">a member of <see>XApiScope</see></param>
/// <returns>an instance of <see>XTokenResponse</see></returns>
public async Task<XTokenResponse> RequestScopeAccessToken (string scope) {
//
// Validate Args ...
var scopeName = string.Empty;
try {
scopeName = scope; // scope.GetStringValue ();
} catch { }
if (scopeName.IsNullOrEmpty ()) {
XException.InvalidArgs.Throw ();
}
//
var client = GetRestClient ();
var request = GetRestRequet (
XApiAccountEndpoint.RequestScopeAccessToken,
headers : new Dictionary<string, string> { { XParam.XScope.GetStringValue (), scope.ToString () } });
//
var response = await RunRestRequest<XTokenResponse> (
client,
request,
XHttpMethod.POST
);
//
// Save Token ...
if (!response.IsNull ()) {
await tokenProvider.AddOrUpdateToken (response);
}
//
return response;
}
/// <summary>
/// Validate a token
/// </summary>
/// <param name="model">Authentication Tokens</param>
/// <returns>an instance of TokenIntrospectionResponse</returns>
public async Task<TokenIntrospectionResponse> Introspection (XTokenResponse model) {
//
// Validate Args ...
await validationProvider
.GroupValidationBuilder ()
.AddNotNull (model)
.AddNotEmpty (model.AccessToken)
.ValidateGroupAsync ();
//
var httpClient = GetHttpClient ();
//
try {
//
var discoDoc = await RequestDiscoveryDocument ();
if (discoDoc.IsError) {
XException.ActionFailed.Throw ();
}
//
var response = await httpClient.IntrospectTokenAsync (new TokenIntrospectionRequest {
//
Address = discoDoc.IntrospectionEndpoint,
ClientId = identityConfiguration.ClientId,
ClientSecret = identityConfiguration.ClientSecret,
//
Token = model.AccessToken
});
if (response.IsError) {
throw new Exception (response.Error);
}
//
return response;
} catch {
throw XException.ActionFailed.ToException ();
}
}
/// <summary>
/// Authenticate a User
/// </summary>
/// <param name="model">User Login Required Info, an instance of <see>XLoginRequest</see></param>
/// <returns>an instance of <see>XTokenResponse</see></returns>
public async Task<XTokenResponse> Authenticate (XLoginRequest model) {
//
// Validate Args ...
validationProvider
.GroupValidationBuilder ()
.AddNotNull (model)
.AddNotEmpty (
model.UserSelectBy,
model.Password
)
.ValidateGroup ();
//
var client = GetRestClient ();
var request = GetRestRequet (XApiAccountEndpoint.Authenticate);
request.AddJsonBody (model);
//
var response = await RunRestRequest<XTokenResponse> (
client,
request,
XHttpMethod.POST
);
//
// Save Token ...
if (!response.IsNull ()) {
await tokenProvider.AddOrUpdateToken (response);
}
//
return response;
}
/// <summary>
/// Do Login based on XLoginRequest
/// </summary>
/// <param name="model">User Login Required Info, an instance of <see>XLoginRequest</see></param>
/// <returns>an instance of <see>XTokenResponse</see></returns>
public async Task<XLoginResponse> Login (XLoginRequest model) {
//
// Validate Args ...
validationProvider
.GroupValidationBuilder ()
.AddNotNull (model, model.Device)
.AddNotEmpty (
model.UserSelectBy,
model.Password
)
.ValidateGroup ();
//
var client = GetRestClient ();
var request = GetRestRequet (XApiAccountEndpoint.Login);
request.AddJsonBody (model);
//
var response = await RunRestRequest<XLoginResponse> (
client,
request,
XHttpMethod.POST
);
//
if (!response.IsNull ()) {
//
var tokens = response.ToXTokenResponse ();
await tokenProvider.AddOrUpdateToken (tokens);
}
//
return response;
}
/// <summary>
/// Logout from System
/// </summary>
/// <param name="model"></param>
/// <returns></returns>
public async Task Logout (XTokenResponse model) {
//
await validationProvider
.GroupValidationBuilder ()
.AddNotNull (model)
.AddNotEmpty (model.AccessToken)
.ValidateGroupAsync ();
//
var isExists = await tokenProvider
.IsTokenExists (model.AccessToken);
if (isExists) {
await tokenProvider
.RemoveToken (model.AccessToken);
}
}
/// <summary>
/// Refresh Tokens
/// </summary>
/// <param name="model">Authentication Tokens</param>
/// <returns>an instance of <see>XTokenResponse</see></returns>
public async Task<XTokenResponse> RefreshTokens (XTokenResponse model) {
//
// Validate Args ...
validationProvider
.GroupValidationBuilder ()
.AddNotNull (model)
.AddNotEmpty (
model.AccessToken,
model.RefreshToken
)
.ValidateGroup ();
//
var client = GetRestClient (model);
//
var request = GetRestRequet (
XApiAccountEndpoint.RefreshTokens,
headers : model.ToHeaderDictionary ());
request.AddJsonBody (model);
//
var response = await RunRestRequest<XTokenResponse> (
client,
request,
XHttpMethod.POST
);
if (!response.IsNull ()) {
await tokenProvider.UpdateToken (response);
}
//
return response;
}
#endregion
//
#region Password Actions Handlers ...
/// <summary>
/// Change Password
/// </summary>
/// <param name="tokens">Authentication Tokens</param>
/// <param name="model">an instance of <see>XActionRequest</see> class which provider requirement for action</param>
/// <returns></returns>
public async Task ChangePassword (
XTokenResponse tokens,
XActionRequest model
) {
//
// Validate Args ...
await validationProvider
.GroupValidationBuilder ()
.AddNotNull (tokens, model)
.AddNotEmpty (
model.Lang,
model.Password,
model.NewPassword,
model.ReturnUrl)
.AddNotNull (model.Device)
.ValidateGroupAsync ();
//
// Validate User Select By Param ...
var userSelectByParam = GetUserSelectByParam (
model,
forceNotNull : true,
excludes : null);
//
var client = GetRestClient (tokens);
var request = GetRestRequet (
XApiAccountEndpoint.ChangePassword,
headers : tokens.ToHeaderDictionary ());
request.AddJsonBody (model);
//
var response = await RunRestRequest<Object> (
client,
request,
XHttpMethod.POST
);
}
#endregion
}
}
+803
View File
@@ -0,0 +1,803 @@
using System.Collections.Generic;
using System.Threading.Tasks;
using xCommons.Extensions;
using xHttpService.Constants;
using xIdentityModels.Constants;
using xIdentityModels.Dtos;
using xIdentityModels.Models;
using xIdentityModels.Navigations;
using xIdentityService.Constants;
namespace xIdentityService.Providers {
public partial class XIdentityProvider {
//
#region Friendship ...
/// <summary>
/// Follow a User
/// </summary>
/// <param name="tokens">Authentication Tokens</param>
/// <param name="destUser">a user identifier which represent destination user</param>
/// <returns>an instance of <see>XFriendshipFollowing</see></returns>
public async Task<XFriendshipFollowing> Follow (
XTokenResponse tokens,
string destUser
) {
//
// Validate Args ...
await validationProvider
.GroupValidationBuilder ()
.AddNotNull (tokens)
.AddNotEmpty (
destUser,
tokens.AccessToken
)
.ValidateGroupAsync ();
//
var client = GetRestClient (tokens);
//
var request = GetRestRequet (
XApiAccountEndpoint.Follow,
@params : new Dictionary<string, string> { { XParam.XDestUser.GetStringValue (), destUser }
}
);
//
var response = await RunRestRequest<XFriendshipFollowing> (
client,
request,
XHttpMethod.POST
);
return response;
}
/// <summary>
/// Cancel Following Request
/// </summary>
/// <param name="tokens">Authentication Tokens</param>
/// <param name="destUser">a user identifier which represent destination user</param>
/// <returns>a boolean value</returns>
public async Task<bool> Cancel (
XTokenResponse tokens,
string destUser
) {
//
// Validate Args ...
await validationProvider
.GroupValidationBuilder ()
.AddNotNull (tokens)
.AddNotEmpty (
destUser,
tokens.AccessToken
)
.ValidateGroupAsync ();
//
var client = GetRestClient (tokens);
//
var request = GetRestRequet (
XApiAccountEndpoint.Cancel,
@params : new Dictionary<string, string> { { XParam.XDestUser.GetStringValue (), destUser }
}
);
//
var response = await RunRestRequest<bool> (
client,
request,
XHttpMethod.POST
);
return response;
}
/// <summary>
/// Unfollow a Follower
/// </summary>
/// <param name="tokens">Authentication Tokens</param>
/// <param name="destUser">a user identifier which represent destination user</param>
/// <returns></returns>
public async Task UnFollowFollower (
XTokenResponse tokens,
string destUser
) {
//
// Validate Args ...
await validationProvider
.GroupValidationBuilder ()
.AddNotNull (tokens)
.AddNotEmpty (
destUser,
tokens.AccessToken
)
.ValidateGroupAsync ();
//
var client = GetRestClient (tokens);
//
var request = GetRestRequet (
XApiAccountEndpoint.UnFollowFollower,
@params : new Dictionary<string, string> { { XParam.XDestUser.GetStringValue (), destUser }
}
);
//
var response = await RunRestRequest<object> (
client,
request,
XHttpMethod.POST
);
}
/// <summary>
/// Unfollow Following
/// </summary>
/// <param name="tokens">Authentication Tokens</param>
/// <param name="destUser">a user identifier which represent destination user</param>
/// <returns></returns>
public async Task UnFollowFollowing (
XTokenResponse tokens,
string destUser
) {
//
// Validate Args ...
await validationProvider
.GroupValidationBuilder ()
.AddNotNull (tokens)
.AddNotEmpty (
destUser,
tokens.AccessToken
)
.ValidateGroupAsync ();
//
var client = GetRestClient (tokens);
//
var request = GetRestRequet (
XApiAccountEndpoint.UnFollowFollowing,
@params : new Dictionary<string, string> { { XParam.XDestUser.GetStringValue (), destUser }
}
);
//
var response = await RunRestRequest<object> (
client,
request,
XHttpMethod.POST
);
}
/// <summary>
/// Block a Follower
/// </summary>
/// <param name="tokens">Authentication Tokens</param>
/// <param name="destUser">a user identifier which represent destination user</param>
/// <returns>an instance of <see>XFriendshipFollowing</see></returns>
public async Task<XFriendshipFollowing> Block (
XTokenResponse tokens,
string destUser
) {
//
// Validate Args ...
await validationProvider
.GroupValidationBuilder ()
.AddNotNull (tokens)
.AddNotEmpty (
destUser,
tokens.AccessToken
)
.ValidateGroupAsync ();
//
var client = GetRestClient (tokens);
//
var request = GetRestRequet (
XApiAccountEndpoint.Block,
@params : new Dictionary<string, string> { { XParam.XDestUser.GetStringValue (), destUser }
}
);
//
var response = await RunRestRequest<XFriendshipFollowing> (
client,
request,
XHttpMethod.POST
);
return response;
}
/// <summary>
/// Unblock a Blocked User
/// </summary>
/// <param name="tokens">Authentication Tokens</param>
/// <param name="destUser">a user identifier which represent destination user</param>
/// <returns>an instance of <see>XFriendshipFollowing</see></returns>
public async Task<XFriendshipFollowing> UnBlock (
XTokenResponse tokens,
string destUser
) {
//
// Validate Args ...
await validationProvider
.GroupValidationBuilder ()
.AddNotNull (tokens)
.AddNotEmpty (
destUser,
tokens.AccessToken
)
.ValidateGroupAsync ();
//
var client = GetRestClient (tokens);
//
var request = GetRestRequet (
XApiAccountEndpoint.UnBlock,
@params : new Dictionary<string, string> { { XParam.XDestUser.GetStringValue (), destUser }
}
);
//
var response = await RunRestRequest<XFriendshipFollowing> (
client,
request,
XHttpMethod.POST
);
return response;
}
/// <summary>
/// Accept a Following Request
/// </summary>
/// <param name="tokens">Authentication Tokens</param>
/// <param name="destUser">a user identifier which represent destination user</param>
/// <returns>an instance of <see>XFriendshipFollower</see></returns>
public async Task<XFriendshipFollower> AcceptRequest (
XTokenResponse tokens,
string destUser
) {
//
// Validate Args ...
await validationProvider
.GroupValidationBuilder ()
.AddNotNull (tokens)
.AddNotEmpty (
destUser,
tokens.AccessToken
)
.ValidateGroupAsync ();
//
var client = GetRestClient (tokens);
//
var request = GetRestRequet (
XApiAccountEndpoint.AcceptRequest,
@params : new Dictionary<string, string> { { XParam.XDestUser.GetStringValue (), destUser }
}
);
//
var response = await RunRestRequest<XFriendshipFollower> (
client,
request,
XHttpMethod.POST
);
return response;
}
/// <summary>
/// Reject a Following Request
/// </summary>
/// <param name="tokens">Authentication Tokens</param>
/// <param name="destUser">a user identifier which represent destination user</param>
/// <returns>an instance of <see>XFriendshipFollower</see></returns>
public async Task<XFriendshipFollower> RejectRequest (
XTokenResponse tokens,
string destUser
) {
//
// Validate Args ...
await validationProvider
.GroupValidationBuilder ()
.AddNotNull (tokens)
.AddNotEmpty (
destUser,
tokens.AccessToken
)
.ValidateGroupAsync ();
//
var client = GetRestClient (tokens);
//
var request = GetRestRequet (
XApiAccountEndpoint.RejectRequest,
@params : new Dictionary<string, string> { { XParam.XDestUser.GetStringValue (), destUser }
}
);
//
var response = await RunRestRequest<XFriendshipFollower> (
client,
request,
XHttpMethod.POST
);
return response;
}
/// <summary>
/// Check a User IsFollower of Requested User
/// </summary>
/// <param name="tokens">Authentication Tokens</param>
/// <param name="destUser">a user identifier which represent destination user</param>
/// <returns>a boolean value</returns>
public async Task<bool> IsFollower (
XTokenResponse tokens,
string destUser
) {
//
// Validate Args ...
await validationProvider
.GroupValidationBuilder ()
.AddNotNull (tokens)
.AddNotEmpty (
destUser,
tokens.AccessToken
)
.ValidateGroupAsync ();
//
var client = GetRestClient (tokens);
//
var request = GetRestRequet (
XApiAccountEndpoint.IsFollower,
@params : new Dictionary<string, string> { { XParam.XDestUser.GetStringValue (), destUser }
}
);
//
var response = await RunRestRequest<bool> (
client,
request,
XHttpMethod.GET
);
return response;
}
/// <summary>
/// Get Specific Follower
/// </summary>
/// <param name="tokens">Authentication Tokens</param>
/// <param name="destUser">a user identifier which represent destination user</param>
/// <returns>an instance of <see>XFriendshipFollower</see></returns>
public async Task<XFriendshipFollower> GetFollower (
XTokenResponse tokens,
string destUser
) {
//
// Validate Args ...
await validationProvider
.GroupValidationBuilder ()
.AddNotNull (tokens)
.AddNotEmpty (
destUser,
tokens.AccessToken
)
.ValidateGroupAsync ();
//
var client = GetRestClient (tokens);
//
var request = GetRestRequet (
XApiAccountEndpoint.Follower,
@params : new Dictionary<string, string> { { XParam.XDestUser.GetStringValue (), destUser }
}
);
//
var response = await RunRestRequest<XFriendshipFollower> (
client,
request,
XHttpMethod.GET
);
return response;
}
/// <summary>
/// Get Follower State of a User
/// </summary>
/// <param name="tokens">Authentication Tokens</param>
/// <param name="destUser">a user identifier which represent destination user</param>
/// <returns>an instance of <see>XFriendshipState</see></returns>
public async Task<XFriendshipState> GetFollowerState (
XTokenResponse tokens,
string destUser
) {
//
// Validate Args ...
await validationProvider
.GroupValidationBuilder ()
.AddNotNull (tokens)
.AddNotEmpty (
destUser,
tokens.AccessToken
)
.ValidateGroupAsync ();
//
var client = GetRestClient (tokens);
//
var request = GetRestRequet (
XApiAccountEndpoint.FollowerState,
@params : new Dictionary<string, string> { { XParam.XDestUser.GetStringValue (), destUser }
}
);
//
var response = await RunRestRequest<XFriendshipState> (
client,
request,
XHttpMethod.GET
);
return response;
}
/// <summary>
/// Get Followers List Of Current User
/// </summary>
/// <param name="tokens">Authentication Tokens</param>
/// <returns>a collection of <see>XFriendshipFollower</see></returns>
public async Task<IEnumerable<XFriendshipFollower>> GetFollowers (
XTokenResponse tokens
) {
//
// Validate Args ...
await validationProvider
.GroupValidationBuilder ()
.AddNotNull (tokens)
.AddNotEmpty (tokens.AccessToken)
.ValidateGroupAsync ();
//
var client = GetRestClient (tokens);
//
var request = GetRestRequet (XApiAccountEndpoint.Followers);
//
var response = await RunRestRequest<IEnumerable<XFriendshipFollower>> (
client,
request,
XHttpMethod.GET
);
return response;
}
/// <summary>
/// Get All Followers List Includes Blocked, Requested and etc
/// of Current User
/// </summary>
/// <param name="tokens">Authentication Tokens</param>
/// <returns>a collection of <see>XFriendshipFollower</see></returns>
public async Task<IEnumerable<XFriendshipFollower>> GetAllFollowers (
XTokenResponse tokens
) {
//
// Validate Args ...
await validationProvider
.GroupValidationBuilder ()
.AddNotNull (tokens)
.AddNotEmpty (tokens.AccessToken)
.ValidateGroupAsync ();
//
var client = GetRestClient (tokens);
//
var request = GetRestRequet (XApiAccountEndpoint.AllFollowers);
//
var response = await RunRestRequest<IEnumerable<XFriendshipFollower>> (
client,
request,
XHttpMethod.GET
);
return response;
}
/// <summary>
/// Check a User is in Followings of Current User
/// </summary>
/// <param name="tokens">Authentication Tokens</param>
/// <param name="destUser">a user identifier which represent destination user</param>
/// <returns>a boolean value</returns>
public async Task<bool> IsFollowing (
XTokenResponse tokens,
string destUser
) {
//
// Validate Args ...
await validationProvider
.GroupValidationBuilder ()
.AddNotNull (tokens)
.AddNotEmpty (
destUser,
tokens.AccessToken
)
.ValidateGroupAsync ();
//
var client = GetRestClient (tokens);
//
var request = GetRestRequet (
XApiAccountEndpoint.IsFollowing,
@params : new Dictionary<string, string> { { XParam.XDestUser.GetStringValue (), destUser }
}
);
//
var response = await RunRestRequest<bool> (
client,
request,
XHttpMethod.GET
);
return response;
}
/// <summary>
/// Get Specific Following Model
/// </summary>
/// <param name="tokens">Authentication Tokens</param>
/// <param name="destUser">a user identifier which represent destination user</param>
/// <returns>an instance of <see>XFriendshipFollowing</see></returns>
public async Task<XFriendshipFollowing> GetFollowing (
XTokenResponse tokens,
string destUser
) {
//
// Validate Args ...
await validationProvider
.GroupValidationBuilder ()
.AddNotNull (tokens)
.AddNotEmpty (
destUser,
tokens.AccessToken
)
.ValidateGroupAsync ();
//
var client = GetRestClient (tokens);
//
var request = GetRestRequet (
XApiAccountEndpoint.Following,
@params : new Dictionary<string, string> { { XParam.XDestUser.GetStringValue (), destUser }
}
);
//
var response = await RunRestRequest<XFriendshipFollowing> (
client,
request,
XHttpMethod.GET
);
return response;
}
/// <summary>
/// Get Following State Relation between Specific User
/// and Current User
/// </summary>
/// <param name="tokens">Authentication Tokens</param>
/// <param name="destUser">a user identifier which represent destination user</param>
/// <returns>an instance of <see>XFriendshipState</see></returns>
public async Task<XFriendshipState> GetFollowingState (
XTokenResponse tokens,
string destUser
) {
//
// Validate Args ...
await validationProvider
.GroupValidationBuilder ()
.AddNotNull (tokens)
.AddNotEmpty (
destUser,
tokens.AccessToken
)
.ValidateGroupAsync ();
//
var client = GetRestClient (tokens);
//
var request = GetRestRequet (
XApiAccountEndpoint.FollowingState,
@params : new Dictionary<string, string> { { XParam.XDestUser.GetStringValue (), destUser }
}
);
//
var response = await RunRestRequest<XFriendshipState> (
client,
request,
XHttpMethod.GET
);
return response;
}
/// <summary>
/// Get Followings of Current User
/// </summary>
/// <param name="tokens">Authentication Tokens</param>
/// <returns>a collection of <see>XFriendshipFollowing</see></returns>
public async Task<IEnumerable<XFriendshipFollowing>> GetFollowings (
XTokenResponse tokens
) {
//
// Validate Args ...
await validationProvider
.GroupValidationBuilder ()
.AddNotNull (tokens)
.AddNotEmpty (tokens.AccessToken)
.ValidateGroupAsync ();
//
var client = GetRestClient (tokens);
//
var request = GetRestRequet (XApiAccountEndpoint.Followings);
//
var response = await RunRestRequest<IEnumerable<XFriendshipFollowing>> (
client,
request,
XHttpMethod.GET
);
return response;
}
/// <summary>
/// Get All Following List Includes Blocked, Requested and etc
/// of Current User
/// </summary>
/// <param name="tokens">Authentication Tokens</param>
/// <returns>a collection of <see>XFriendshipFollowing</see></returns>
public async Task<IEnumerable<XFriendshipFollowing>> GetAllFollowings (
XTokenResponse tokens
) {
//
// Validate Args ...
await validationProvider
.GroupValidationBuilder ()
.AddNotNull (tokens)
.AddNotEmpty (tokens.AccessToken)
.ValidateGroupAsync ();
//
var client = GetRestClient (tokens);
//
var request = GetRestRequet (XApiAccountEndpoint.AllFollowings);
//
var response = await RunRestRequest<IEnumerable<XFriendshipFollowing>> (
client,
request,
XHttpMethod.GET
);
return response;
}
/// <summary>
/// Return Following UserName's List of Current User
/// </summary>
/// <param name="tokens">Authentication Tokens</param>
/// <returns>a collection of UserNames</returns>
public async Task<IEnumerable<string>> GetFollowingList (
XTokenResponse tokens
) {
//
// Validate Args ...
await validationProvider
.GroupValidationBuilder ()
.AddNotNull (tokens)
.AddNotEmpty (tokens.AccessToken)
.ValidateGroupAsync ();
//
var client = GetRestClient (tokens);
//
var request = GetRestRequet (XApiAccountEndpoint.FollowingsList);
//
var response = await RunRestRequest<IEnumerable<string>> (
client,
request,
XHttpMethod.GET
);
return response;
}
/// <summary>
/// Return Followers UserName's List of Current User
/// </summary>
/// <param name="tokens">Authentication Tokens</param>
/// <returns>a collection of UserNames</returns>
public async Task<IEnumerable<string>> GetFollowersList (
XTokenResponse tokens
) {
//
// Validate Args ...
await validationProvider
.GroupValidationBuilder ()
.AddNotNull (tokens)
.AddNotEmpty (tokens.AccessToken)
.ValidateGroupAsync ();
//
var client = GetRestClient (tokens);
//
var request = GetRestRequet (XApiAccountEndpoint.FollowersList);
//
var response = await RunRestRequest<IEnumerable<string>> (
client,
request,
XHttpMethod.GET
);
return response;
}
/// <summary>
/// Get Friendship Info Model between Specific User and Current User
/// </summary>
/// <param name="tokens">Authentication Tokens</param>
/// <param name="destUser">a user identifier which represent destination user</param>
/// <returns>an instance of <see>XFriendshipInfoDto</see></returns>
public async Task<XFriendshipInfoDto> GetFriendshipInfo (
XTokenResponse tokens,
string destUser
) {
//
// Validate Args ...
await validationProvider
.GroupValidationBuilder ()
.AddNotNull (tokens)
.AddNotEmpty (
destUser,
tokens.AccessToken
)
.ValidateGroupAsync ();
//
var client = GetRestClient (tokens);
//
var request = GetRestRequet (
XApiAccountEndpoint.FriendshipInfo,
@params : new Dictionary<string, string> { { XParam.XDestUser.GetStringValue (), destUser }
}
);
//
var response = await RunRestRequest<XFriendshipInfoDto> (
client,
request,
XHttpMethod.GET
);
return response;
}
#endregion
}
}
+496
View File
@@ -0,0 +1,496 @@
using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using xCommons.Extensions;
using xHttpService.Constants;
using xHttpService.Extensions;
using xIdentityModels.Dtos;
using xIdentityModels.Models;
using xIdentityModels.Navigations;
using xIdentityService.Constants;
using xModels.Dtos;
namespace xIdentityService.Providers {
public partial class XIdentityProvider {
//
#region User Actions ...
/// <summary>
/// Retrieve User Names based on UserIds
/// </summary>
/// <param name="tokens">Authentication Tokens</param>
/// <param name="ids">a comma seperated list of UserIds</param>
/// <returns>a collection of UserNames</returns>
public async Task<IEnumerable<string>> GetUserNames (
XTokenResponse tokens,
string ids
) {
//
// Validate Args ...
await validationProvider
.GroupValidationBuilder ()
.AddNotNull (tokens)
.AddNotEmpty (ids, tokens.AccessToken)
.ValidateGroupAsync ();
//
var client = GetRestClient (tokens);
var request = GetRestRequet (
XApiAccountEndpoint.GetNames,
@params : new Dictionary<string, string> { { XParam.XIds.GetStringValue (), ids } }
);
//
var response = await RunRestRequest<IEnumerable<string>> (
client,
request,
XHttpMethod.GET
);
return response;
}
/// <summary>
/// get user ids and retrieve corresponding user names
/// </summary>
/// <param name="tokens">Authentication Tokens</param>
/// <param name="model">an instance of <see>XUserNameIdRequest</see> which represent required UserIds collection</param>
/// <returns>a collection of <see>XUserNameIdResponse</see> instance</returns>
public async Task<IEnumerable<XUserNameIdResponse>> GetUserNameIds (
XTokenResponse tokens,
XUserNameIdRequest model
) {
//
// Validate Args ...
await validationProvider
.GroupValidationBuilder ()
.AddNotNull (model, tokens)
.AddNotZeroChilds (model.Ids)
.AddNotEmpty (tokens.AccessToken)
.ValidateGroupAsync ();
//
var client = GetRestClient (tokens);
var request = GetRestRequet (XApiAccountEndpoint.GetNameIds);
request.AddJsonBody (model);
//
var response = await RunRestRequest<IEnumerable<XUserNameIdResponse>> (
client,
request,
XHttpMethod.POST
);
return response;
}
#endregion
//
#region Profile Actions ...
/// <summary>
/// Get Profile Object of Specific User
/// </summary>
/// <param name="tokens">Authentication Tokens</param>
/// <param name="userSelectByParam">determine's which user profile must be retrieved</param>
/// <returns>an instance of <see>XUserProfileDto</see></returns>
public async Task<XUserProfileDto> GetUserProfile (
XTokenResponse tokens,
string userSelectByParam
) {
//
// Validate Args ...
await validationProvider
.GroupValidationBuilder ()
.AddNotNull (tokens)
.AddNotEmpty (userSelectByParam, tokens.AccessToken)
.ValidateGroupAsync ();
//
var client = GetRestClient (tokens);
//
var request = GetRestRequet (
XApiAccountEndpoint.GetProfile,
@params : new Dictionary<string, string> { { XParam.XUserSelectByParam.GetStringValue (), userSelectByParam } }
);
//
var response = await RunRestRequest<XUserProfileDto> (
client,
request,
XHttpMethod.GET
);
return response;
}
/// <summary>
/// Retrieve Users Based On Query
/// </summary>
/// <param name="tokens">Authentication Tokens</param>
/// <param name="query">how to filter results based on <see>XQuery</see> structure</param>
/// <returns>an instance of <see>XQueryResult</see> of <see>XUserProfileDto</see></returns>
public async Task<XQueryResult<XUserProfileDto>> QueryUsers (
XTokenResponse tokens,
XQuery query
) {
//
// Validate Args ...
await validationProvider
.GroupValidationBuilder ()
.AddNotNull (tokens, query)
.AddNotEmpty (tokens.AccessToken)
.ValidateGroupAsync ();
//
var client = GetRestClient (tokens);
//
var request = GetRestRequet (XApiAccountEndpoint.QueryProfiles);
//
// Attach XQuery to Request ...
request = request.AttachXQuery (query);
//
var response = await RunRestRequest<XQueryResult<XUserProfileDto>> (
client,
request,
XHttpMethod.GET
);
return response;
}
/// <summary>
/// Retrieve Users Based On Query and Specified role
/// </summary>
/// <param name="tokens">Authentication Tokens</param>
/// <param name="role">an string which represent user role</param>
/// <param name="query">how to filter results based on <see>XQuery</see> structure</param>
/// <param name="forceRole">if it's true the user must has exact role, otherwise top level users also listed</param>
/// <returns>an instance of <see>XQueryResult</see> of <see>XUserProfileDto</see></returns>
public async Task<XQueryResult<XUserProfileDto>> QueryInRoleUsers (
XTokenResponse tokens,
string role,
XQuery query,
bool forceRole = false
) {
//
// Validate Args ...
await validationProvider
.GroupValidationBuilder ()
.AddNotNull (tokens, query)
.AddNotEmpty (tokens.AccessToken, role)
.ValidateGroupAsync ();
//
var client = GetRestClient (tokens);
//
var request = GetRestRequet (
XApiAccountEndpoint.QueryProfiles,
headers : new Dictionary<string, string> { { XParam.XRole.GetStringValue (), role },
{ XParam.XForceRole.GetStringValue (), forceRole.AsHttpParamString () }
}
);
//
// Attach XQuery to Request ...
request = request.AttachXQuery (query);
//
var response = await RunRestRequest<XQueryResult<XUserProfileDto>> (
client,
request,
XHttpMethod.GET
);
return response;
}
/// <summary>
/// Query Specified User's Profile Images
/// </summary>
/// <param name="tokens">Authentication Tokens</param>
/// <param name="userSelectByParam">determine's which user profile must be retrieved</param>
/// <param name="query">how to filter results based on <see>XQuery</see> structure</param>
/// <returns>an instance of <see>XQueryResult</see> of <see>XProfileImage</see></returns>
public async Task<XQueryResult<XProfileImage>> QueryAvatars (
XTokenResponse tokens,
string userSelectByParam,
XQuery query
) {
//
// Validate Args ...
await validationProvider
.GroupValidationBuilder ()
.AddNotNull (tokens, query)
.AddNotEmpty (tokens.AccessToken, userSelectByParam)
.ValidateGroupAsync ();
//
var client = GetRestClient (tokens);
//
var request = GetRestRequet (
XApiAccountEndpoint.QueryAvatars,
@params : new Dictionary<string, string> { { XParam.XUserSelectByParam.GetStringValue (), userSelectByParam }
}
);
//
// Attach XQuery to Request ...
request = request.AttachXQuery (query);
//
var response = await RunRestRequest<XQueryResult<XProfileImage>> (
client,
request,
XHttpMethod.GET
);
return response;
}
/// <summary>
/// Update User Profile based on <see>XProfileUpdateRequest</see> (FirstName/LastName/DateOfBirth)
/// </summary>
/// <param name="tokens">Authentication Tokens</param>
/// <param name="userSelectByParam">determine's which user profile must be retrieved</param>
/// <param name="model">user update info, an instance of <see>XProfileUpdateRequest</see></param>
/// <returns>an instance of <see>XUserProfileDto</see></returns>
public async Task<XUserProfileDto> ProfileUpdateAsync (
XTokenResponse tokens,
string userSelectByParam,
XProfileUpdateRequest model
) {
//
// Validate Args ...
await validationProvider
.GroupValidationBuilder ()
.AddNotNull (tokens, model)
.AddNotEmpty (tokens.AccessToken, userSelectByParam)
.ValidateGroupAsync ();
//
var client = GetRestClient (tokens);
//
var request = GetRestRequet (
XApiAccountEndpoint.UpdateProfile,
@params : new Dictionary<string, string> { { XParam.XUserSelectByParam.GetStringValue (), userSelectByParam }
}
);
request.AddJsonBody (model);
//
var response = await RunRestRequest<XUserProfileDto> (
client,
request,
XHttpMethod.POST
);
return response;
}
/// <summary>
/// Update a User Profile based on <see>XProfileUpdateRequest</see> Full
/// </summary>
/// <param name="tokens">Authentication Tokens</param>
/// <param name="userSelectByParam">determine's which user profile must be retrieved</param>
/// <param name="model">user update info, an instance of <see>XProfileUpdateRequest</see></param>
/// <returns>an instance of <see>XUserProfileDto</see></returns>
public async Task<XUserProfileDto> FullProfileUpdateAsync (
XTokenResponse tokens,
string userSelectByParam,
XProfileUpdateRequest model
) {
//
// Validate Args ...
await validationProvider
.GroupValidationBuilder ()
.AddNotNull (tokens, model)
.AddNotEmpty (tokens.AccessToken, userSelectByParam)
.ValidateGroupAsync ();
//
var client = GetRestClient (tokens);
//
var request = GetRestRequet (
XApiAccountEndpoint.FullUpdateProfile,
@params : new Dictionary<string, string> { { XParam.XUserSelectByParam.GetStringValue (), userSelectByParam }
}
);
request.AddJsonBody (model);
//
var response = await RunRestRequest<XUserProfileDto> (
client,
request,
XHttpMethod.POST
);
return response;
}
/// <summary>
/// Add a New Profile Image
/// </summary>
/// <param name="tokens">Authentication Tokens</param>
/// <param name="file">an specific File to upload, <see>IFormFile</see></param>
/// <returns>an instance of <see>XUserProfileDto</see></returns>
public async Task<XUserProfileDto> AddAvatar (
XTokenResponse tokens,
IFormFile file
) {
//
// Validate Args ...
await validationProvider
.GroupValidationBuilder ()
.AddNotNull (tokens, file)
.AddNotEmpty (tokens.AccessToken)
.ValidateGroupAsync ();
//
var client = GetRestClient (tokens);
//
var request = GetRestRequet (XApiAccountEndpoint.AddAvatar);
request.AlwaysMultipartFormData = true;
request.AddFileBytes (
XParam.XFile.GetStringValue (),
file.ToByteArray (),
file.FileName,
file.ContentType
);
//
var response = await RunRestRequest<XUserProfileDto> (
client,
request,
XHttpMethod.POST
);
return response;
}
/// <summary>
/// Add a New Collection of Profile Images
/// </summary>
/// <param name="tokens">Authentication Tokens</param>
/// <param name="files">a collection of Files to upload, <see>IFormFileCollection</see></param>
/// <returns>an instance of <see>XUserProfileDto</see></returns>
public async Task<XUserProfileDto> AddAvatars (
XTokenResponse tokens,
IFormFileCollection files
) {
//
// Validate Args ...
await validationProvider
.GroupValidationBuilder ()
.AddNotNull (tokens)
.AddNotZeroChilds (files)
.AddNotEmpty (tokens.AccessToken)
.ValidateGroupAsync ();
//
var client = GetRestClient (tokens);
//
var request = GetRestRequet (XApiAccountEndpoint.AddAvatars);
request.AlwaysMultipartFormData = true;
//
// Add Files ...
foreach (var file in files) {
//
// Add Single file ...
request.AddFileBytes (
XParam.XFiles.GetStringValue (),
file.ToByteArray (),
file.FileName,
file.ContentType
);
}
//
var response = await RunRestRequest<XUserProfileDto> (
client,
request,
XHttpMethod.POST
);
return response;
}
/// <summary>
/// set Specified Profile Image as Avatar
/// </summary>
/// <param name="tokens">Authentication Tokens</param>
/// <param name="id">an integer which reperesent AvatarId to set as current Avatar</param>
/// <returns>an instance of <see>XUserProfileDto</see></returns>
public async Task<XUserProfileDto> SetAvatar (
XTokenResponse tokens,
int id
) {
//
// Validate Args ...
id.ValidateIntId ();
//
// Validate Args ...
await validationProvider
.GroupValidationBuilder ()
.AddNotNull (tokens)
.AddNotEmpty (tokens.AccessToken)
.ValidateGroupAsync ();
//
var client = GetRestClient (tokens);
//
var request = GetRestRequet (
XApiAccountEndpoint.SetAvatar,
@params : new Dictionary<string, string> { { XParam.XId.GetStringValue (), id.ToString () }
}
);
//
var response = await RunRestRequest<XUserProfileDto> (
client,
request,
XHttpMethod.POST
);
return response;
}
/// <summary>
/// Remove Profile Images
/// </summary>
/// <param name="tokens">Authentication Tokens</param>
/// <param name="avatarIds">a comma seperated list of avatarIds to remove</param>
/// <returns>an instance of <see>XUserProfileDto</see></returns>
public async Task<XUserProfileDto> RemoveAvatars (
XTokenResponse tokens,
string avatarIds
) {
//
// Validate Args ...
await validationProvider
.GroupValidationBuilder ()
.AddNotNull (tokens)
.AddNotEmpty (avatarIds, tokens.AccessToken)
.ValidateGroupAsync ();
//
var client = GetRestClient (tokens);
//
var request = GetRestRequet (
XApiAccountEndpoint.RemoveAvatars,
@params : new Dictionary<string, string> { { XParam.XIds.GetStringValue (), avatarIds }
}
);
//
var response = await RunRestRequest<XUserProfileDto> (
client,
request,
XHttpMethod.DELETE
);
return response;
}
#endregion
}
}
+653
View File
@@ -0,0 +1,653 @@
using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using xCommons.Extensions;
using xExceptions.Constants;
using xHttpService.Constants;
using xIdentityModels.Constants;
using xIdentityModels.Extensions;
using xIdentityModels.Models;
using xIdentityService.Constants;
namespace xIdentityService.Providers {
public partial class XIdentityProvider {
//
#region Registration ...
/// <summary>
/// Check a User Selector is Available for Registration or Not
/// </summary>
/// <param name="userSelectByParam">an string value which reperesent a user</param>
/// <returns>a boolean value</returns>
public async Task<bool> CanRegister (string userSelectByParam) {
//
// Validate ARgs ...
validationProvider.NotEmpty (userSelectByParam);
//
var client = GetRestClient ();
//
// Check Endpoint ...
var endpoint = XApiAccountEndpoint.CanRegisterUserName;
var @params = new Dictionary<string, string> { { XParam.XUserName.GetStringValue (), userSelectByParam } };
//
// Check UserSelectByType ...
var type = userSelectByParam.GetUserSelectByType ();
switch (type) {
//
case XUserSelectBy.Username:
break;
//
case XUserSelectBy.MobileNumber:
//
endpoint = XApiAccountEndpoint.CanRegisterMobileNumber;
@params = new Dictionary<string, string> { { XParam.XMobileNumber.GetStringValue (), userSelectByParam } };
break;
//
case XUserSelectBy.Email:
//
endpoint = XApiAccountEndpoint.CanRegisterEmail;
@params = new Dictionary<string, string> { { XParam.XEmail.GetStringValue (), userSelectByParam } };
break;
//
default:
throw XException.InvalidData.ToException ();
}
//
var request = GetRestRequet (
endpoint,
@params: @params
);
//
var response = await RunRestRequest<bool> (
client,
request,
XHttpMethod.GET
);
return response;
}
/// <summary>
/// Invite a User to Register on Dashboard
/// </summary>
/// <param name="tokens">Authentication Tokens</param>
/// <param name="model">an instance of <see>XActionRequest</see> class which provider requirement for action</param>
/// <returns>an instance of <see>XActionResponse</see></returns>
public async Task<XActionResponse> InviteUser (
XTokenResponse tokens,
XActionRequest model
) {
//
// Validate Args ...
await validationProvider
.GroupValidationBuilder ()
.AddNotNull (
tokens,
model,
model.Device)
.AddNotEmpty (
tokens.AccessToken,
model.Lang,
model.Email,
model.ReturnUrl)
.AddEmailAddress (model.Email)
.ValidateGroupAsync ();
//
var client = GetRestClient (tokens);
//
var request = GetRestRequet (XApiAccountEndpoint.InviteUser);
request.AddJsonBody (model);
//
var response = await RunRestRequest<XActionResponse> (
client,
request,
XHttpMethod.POST
);
return response;
}
/// <summary>
/// Recieve some Basic Informations and Start Registration Proccess
/// if they Valid
///
/// Registration Proccess Starts with Invoking this Action
/// </summary>
/// <param name="model">an instance of <see>XActionRequest</see> class which provider requirement for action</param>
/// <returns>an instance of <see>XActionResponse</see></returns>
public async Task<XActionResponse> RequestRegistration (
XActionRequest model
) {
//
// Validate Args ...
await validationProvider
.GroupValidationBuilder ()
.AddNotNull (
model,
model.Device,
model.DateOfBirth)
.AddNotEmpty (
model.Lang,
model.FirstName,
model.LastName)
.ValidateGroupAsync ();
//
var client = GetRestClient ();
//
var request = GetRestRequet (XApiAccountEndpoint.RequestRegistration);
request.AddJsonBody (model);
//
var response = await RunRestRequest<XActionResponse> (
client,
request,
XHttpMethod.POST
);
return response;
}
/// <summary>
/// Add User Account Informations
/// </summary>
/// <param name="model">an instance of <see>XActionRequest</see> class which provider requirement for action</param>
/// <returns>an instance of <see>XActionResponse</see></returns>
public async Task<XActionResponse> AddAccountInfo (
XActionRequest model
) {
//
// Validate Args ...
await validationProvider
.GroupValidationBuilder ()
.AddNotNull (
model,
model.Device)
.AddNotEmpty (
model.Lang,
model.UserName,
model.Password,
model.ActionToken)
.ValidateGroupAsync ();
//
var client = GetRestClient ();
//
var request = GetRestRequet (XApiAccountEndpoint.AddAccountInfo);
request.AddJsonBody (model);
//
var response = await RunRestRequest<XActionResponse> (
client,
request,
XHttpMethod.POST
);
return response;
}
/// <summary>
/// Upload and Attach a Profile Image for User. this is an Optional Step
/// </summary>
/// <param name="actionToken">user's requested action token</param>
/// <param name="file">an instance of <see>IFormFile</see> for user's Avatar</param>
/// <returns>an instance of <see>XActionResponse</see></returns>
public async Task<XActionResponse> AttachProfileImage (
string actionToken,
IFormFile file
) {
//
// Validate Args ...
await validationProvider
.GroupValidationBuilder ()
.AddNotNull (file)
.AddNotEmpty (actionToken)
.ValidateGroupAsync ();
//
var client = GetRestClient ();
//
var request = GetRestRequet (XApiAccountEndpoint.AttachProfileImage);
//
// Prepare Request Data ...
request.AddParameter (XParam.XActionToken.GetStringValue (), actionToken);
request.AddFileBytes (
XParam.XFile.GetStringValue (),
file.ToByteArray (),
file.FileName,
file.ContentType
);
//
var response = await RunRestRequest<XActionResponse> (
client,
request,
XHttpMethod.POST
);
return response;
}
/// <summary>
/// Finish Registrationn Proccess
/// </summary>
/// <param name="model">an instance of <see>XActionRequest</see> class which provider requirement for action</param>
/// <returns></returns>
public async Task FinishRegistration (XActionRequest model) {
//
// Validate Args ...
await validationProvider
.GroupValidationBuilder ()
.AddNotEmpty (
model.Lang,
model.Password,
model.ReturnUrl)
.AddNotNull (model.Device)
.AddUrl (model.ReturnUrl)
.ValidateGroupAsync ();
//
// Create Http Client ...
var client = GetRestClient ();
//
// Create Request ...
var request = GetRestRequet (XApiAccountEndpoint.FinishRegistration);
//
// Prepare Request Data ...
request.AddJsonBody (model);
//
var response = await RunRestRequest<object> (
client,
request,
XHttpMethod.POST
);
}
/// <summary>
/// Check User is Confirmed Email or not
/// </summary>
/// <param name="tokens">Authentication Tokens</param>
/// <param name="userSelectByParam">an string value which reperesent a user</param>
/// <returns>a boolean value</returns>
public async Task<bool> IsConfirmedEmail (
XTokenResponse tokens,
string userSelectByParam
) {
//
// Validate Args ...
await validationProvider
.GroupValidationBuilder ()
.AddNotNull (tokens)
.AddNotEmpty (
tokens.AccessToken,
userSelectByParam)
.ValidateGroupAsync ();
//
var client = GetRestClient (tokens);
//
var request = GetRestRequet (XApiAccountEndpoint.IsConfirmedEmail);
//
var response = await RunRestRequest<bool> (
client,
request,
XHttpMethod.GET
);
return response;
}
/// <summary>
/// Check User is Confirmed Mobile or not
/// </summary>
/// <param name="tokens">Authentication Tokens</param>
/// <param name="userSelectByParam">an string value which reperesent a user</param>
/// <returns>a boolean value</returns>
public async Task<bool> IsConfirmedMobile (
XTokenResponse tokens,
string userSelectByParam
) {
//
// Validate Args ...
await validationProvider
.GroupValidationBuilder ()
.AddNotNull (tokens)
.AddNotEmpty (
tokens.AccessToken,
userSelectByParam)
.ValidateGroupAsync ();
//
var client = GetRestClient (tokens);
//
var request = GetRestRequet (XApiAccountEndpoint.IsConfirmedMobile);
//
var response = await RunRestRequest<bool> (
client,
request,
XHttpMethod.GET
);
return response;
}
/// <summary>
/// Request Registration Confirm
/// </summary>
/// <param name="model">an instance of <see>XActionRequest</see> class which provider requirement for action</param>
/// <returns></returns>
public async Task RequestConfirmRegistration (XActionRequest model) {
//
// Validate Args ...
await validationProvider
.GroupValidationBuilder ()
.AddNotEmpty (
model.Lang,
model.Password,
model.ReturnUrl)
.AddNotNull (model.Device)
.AddUrl (model.ReturnUrl)
.ValidateGroupAsync ();
//
// Get UserSelect By Param ...
var userSelectByParam = model.GetUserSelectByParam ();
validationProvider.NotEmpty (userSelectByParam);
//
var client = GetRestClient ();
//
var request = GetRestRequet (XApiAccountEndpoint.RequestConfirmRegistration);
request.AddJsonBody (model);
//
var response = await RunRestRequest<object> (
client,
request,
XHttpMethod.POST
);
}
/// <summary>
/// Confirm Registration
/// </summary>
/// <param name="model">an instance of <see>XActionRequest</see> class which provider requirement for action</param>
/// <returns></returns>
public async Task ConfirmRegistration (
XActionRequest model
) {
//
// Validate Args ...
await validationProvider
.GroupValidationBuilder ()
.AddNotEmpty (
model.Lang,
model.ActionToken,
model.ReturnUrl
)
.AddNotNull (model.Device)
.ValidateGroupAsync ();
//
var client = GetRestClient ();
//
var request = GetRestRequet (XApiAccountEndpoint.ConfirmRegistration);
request.AddJsonBody (model);
//
var response = await RunRestRequest<object> (
client,
request,
XHttpMethod.POST
);
}
/// <summary>
/// Request For Mobile Number Change/Confirm
/// </summary>
/// <param name="model">an instance of <see>XActionRequest</see> class which provider requirement for action</param>
/// <returns>an instance of <see>XActionResponse</see></returns>
public async Task<XActionResponse> RequestConfirmMobile (XActionRequest model) {
//
// Validate Args ...
await validationProvider
.GroupValidationBuilder ()
.AddNotEmpty (
model.Lang,
model.Password,
model.MobileNumber
)
.AddNotNull (model.Device)
.AddMobileNumber (model.MobileNumber)
.ValidateGroupAsync ();
//
// Get UserSelect By Param ...
var userSelectByParam = GetUserSelectByParam (
model,
excludes : new List<XUserSelectBy> {
XUserSelectBy.Email,
XUserSelectBy.MobileNumber
});
//
var client = GetRestClient ();
//
var request = GetRestRequet (XApiAccountEndpoint.RequestConfirmMobile);
request.AddJsonBody (model);
//
var response = await RunRestRequest<XActionResponse> (
client,
request,
XHttpMethod.POST
);
return response;
}
/// <summary>
/// Confirm Requested Mobile Number
/// </summary>
/// <param name="model">an instance of <see>XActionRequest</see> class which provider requirement for action</param>
/// <returns>an instance of <see>XActionResponse</see></returns>
public async Task<XActionResponse> ConfirmMobileNumber (XActionRequest model) {
//
// Validate Args ...
await validationProvider
.GroupValidationBuilder ()
.AddNotEmpty (
model.Lang,
model.ActionToken,
model.MobileVerificationCode
)
.AddNotNull (model.Device)
.ValidateGroupAsync ();
//
var client = GetRestClient ();
//
var request = GetRestRequet (XApiAccountEndpoint.ConfirmMobileNumber);
request.AddJsonBody (model);
//
var response = await RunRestRequest<XActionResponse> (
client,
request,
XHttpMethod.POST
);
return response;
}
/// <summary>
/// Request For Email Address Change/Confirm
/// </summary>
/// <param name="model">an instance of <see>XActionRequest</see> class which provider requirement for action</param>
/// <returns>an instance of <see>XActionResponse</see></returns>
public async Task<XActionResponse> RequestConfirmEmail (XActionRequest model) {
//
// Validate Args ...
await validationProvider
.GroupValidationBuilder ()
.AddNotEmpty (
model.Lang,
model.Email,
model.Password)
.AddNotNull (model.Device)
.AddEmailAddress (model.Email)
.ValidateGroupAsync ();
//
// Get UserSelect By Param ...
var userSelectByParam = GetUserSelectByParam (
model,
excludes : new List<XUserSelectBy> {
XUserSelectBy.Email,
XUserSelectBy.MobileNumber
});
//
var client = GetRestClient ();
//
var request = GetRestRequet (XApiAccountEndpoint.RequestConfirmEmail);
request.AddJsonBody (model);
//
var response = await RunRestRequest<XActionResponse> (
client,
request,
XHttpMethod.POST
);
return response;
}
/// <summary>
/// Confirm Requested Email Address
/// </summary>
/// <param name="model">an instance of <see>XActionRequest</see> class which provider requirement for action</param>
/// <returns>an instance of <see>XActionResponse</see></returns>
public async Task<XActionResponse> ConfirmEmailAddress (XActionRequest model) {
//
// Validate Args ...
await validationProvider
.GroupValidationBuilder ()
.AddNotEmpty (
model.Lang,
model.ActionToken,
model.EmailVerificationCode
)
.AddNotNull (model.Device)
.ValidateGroupAsync ();
//
var client = GetRestClient ();
//
var request = GetRestRequet (XApiAccountEndpoint.ConfirmEmailAddress);
request.AddJsonBody (model);
//
var response = await RunRestRequest<XActionResponse> (
client,
request,
XHttpMethod.POST
);
return response;
}
/// <summary>
/// Request Reset Password Action
/// </summary>
/// <param name="model">an instance of <see>XActionRequest</see> class which provider requirement for action</param>
/// <returns>an instance of <see>XActionResponse</see></returns>
public async Task<XActionResponse> RequestResetPassword (XActionRequest model) {
//
// Validate Args ...
await validationProvider
.GroupValidationBuilder ()
.AddNotEmpty (
model.Lang,
model.ReturnUrl)
.AddNotNull (model.Device)
.AddUrl (model.ReturnUrl)
.ValidateGroupAsync ();
//
// Get UserSelect By Param ...
var userSelectByParam = GetUserSelectByParam (
model,
excludes : new List<XUserSelectBy> {
XUserSelectBy.Email,
XUserSelectBy.MobileNumber
});
//
var client = GetRestClient ();
//
var request = GetRestRequet (XApiAccountEndpoint.RequestResetPassword);
request.AddJsonBody (model);
//
var response = await RunRestRequest<XActionResponse> (
client,
request,
XHttpMethod.POST
);
return response;
}
/// <summary>
/// Reset a User's Password
/// </summary>
/// <param name="model">an instance of <see>XActionRequest</see> class which provider requirement for action</param>
/// <returns></returns>
public async Task ResetPassword (XActionRequest model) {
//
// Validate Args ...
await validationProvider
.GroupValidationBuilder ()
.AddNotNull (model)
.AddNotEmpty (
model.Lang,
model.ActionToken,
model.NewPassword,
model.ReturnUrl)
.AddNotNull (model.Device)
.ValidateGroupAsync ();
//
var client = GetRestClient ();
//
var request = GetRestRequet (XApiAccountEndpoint.ResetPassword);
request.AddJsonBody (model);
//
var response = await RunRestRequest<object> (
client,
request,
XHttpMethod.POST
);
}
#endregion
}
}
+406
View File
@@ -0,0 +1,406 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
using RestSharp;
using RestSharp.Authenticators;
using xCommons.Constants;
using xCommons.Extensions;
using xCommons.Providers;
using xExceptions.Constants;
using xHttpService.Constants;
using xIdentityModels.Constants;
using xIdentityModels.Extensions;
using xIdentityModels.Models;
using xIdentityService.Configuration;
using xIdentityService.Constants;
using xIdentityService.Interfaces;
namespace xIdentityService.Providers {
public partial class XIdentityProvider : IXIdentityProvider {
private readonly IXTokenProvider tokenProvider;
private readonly IHostingEnvironment environment;
private JsonSerializerSettings jsonSerializerSettings;
private readonly XValidationProvider validationProvider;
private readonly XIdentityServiceConfiguration identityConfiguration;
public string BaseUrl { get; }
public string RevisionSecretKey { get; }
public bool ReadResponseAsString { get; set; }
public ILogger<XIdentityProvider> Logger { get; }
public XIdentityProvider (
IXTokenProvider tokenProvider,
IHostingEnvironment environment,
ILogger<XIdentityProvider> logger,
XIdentityServiceConfiguration identityConfiguration,
XValidationProvider validationProvider
) {
//
BaseUrl = identityConfiguration.Authority;
RevisionSecretKey = identityConfiguration.XRevisionSecretKey;
//
this.environment = environment;
Logger = logger;
//
this.identityConfiguration = identityConfiguration;
this.validationProvider = validationProvider;
this.jsonSerializerSettings = new JsonSerializerSettings {
ContractResolver = new CamelCasePropertyNamesContractResolver ()
};
//
this.tokenProvider = tokenProvider;
}
//
#region Tools ...
/// <summary>
/// Get an Instance of Http Client
/// </summary>
/// <returns></returns>
public HttpClient GetHttpClient () {
//
HttpClient httpClient = null;
//
// httpClient = new HttpClient ();
var httpClientHandler = new HttpClientHandler () {
ServerCertificateCustomValidationCallback = (sender, cert, chain, sslPolicyErrors) => {
//
Logger.LogInformation (
$"XSSL Handler: {Environment.NewLine}, sender: {sender}, {Environment.NewLine} cert: {cert}, {Environment.NewLine} chain: {chain}, {Environment.NewLine} sslPolicyErrors: {sslPolicyErrors}"
);
//
return true;
},
ClientCertificateOptions = ClientCertificateOption.Manual,
};
httpClient = new HttpClient (httpClientHandler);
//
// Set Timeout ...
// TODO: Fix this ...
// httpClient.Timeout = TimeSpan
// .FromSeconds (identityConfiguration.DefaultClientTimeout);
//
return httpClient;
}
/// <summary>
/// Get an Instance of RestClient
/// </summary>
/// <returns></returns>
public RestClient GetRestClient (XTokenResponse tokens = null) {
//
var client = new RestClient (BaseUrl);
//
// Set Authenticator ...
if (!tokens.IsNull () &&
!tokens.AccessToken.IsNullOrEmpty ()) {
client.Authenticator = new JwtAuthenticator (tokens.AccessToken);
}
//
// Refresh Token ...
if (!tokens.IsNull () &&
!tokens.RefreshToken.IsNullOrEmpty ()) {
client.AddDefaultHeader (XAuthorization.RefreshToken, tokens.RefreshToken);
}
//
// ExpiresAt ...
if (!tokens.IsNull () &&
tokens.ExpiresAt > 0) {
client.AddDefaultHeader (XAuthorization.ExpiresAt, tokens.ExpiresAt.AsHttpParamString ());
}
//
// Set Default Timeout ...
client.Timeout = identityConfiguration.DefaultClientTimeout;
//
// SSL Validation Handler ...
client.RemoteCertificateValidationCallback = (sender, cert, chain, sslPolicyErrors) => {
//
Logger.LogInformation (
$"XSSL Handler: {Environment.NewLine}, sender: {sender}, {Environment.NewLine} cert: {cert}, {Environment.NewLine} chain: {chain}, {Environment.NewLine} sslPolicyErrors: {sslPolicyErrors}"
);
//
return true;
};
//
return client;
}
/// <summary>
/// Get an Instance of RestRequest
/// </summary>
/// <param name="endpoint"></param>
/// <param name="params"></param>
/// <returns></returns>
public RestRequest GetRestRequet (
XApiAccountEndpoint endpoint,
IDictionary<string, string> @params = null,
bool addXPoweredValue = true,
IDictionary<string, string> headers = null
) {
//
var url = endpoint.GetStringValue ();
//
// Add Route Payloads ...
if (!@params.IsNull () && @params.Count > 0) {
//
var enumerator = @params.GetEnumerator ();
while (enumerator.MoveNext ()) {
//
var item = enumerator.Current;
//
url = url.Replace (item.Key, item.Value.ToUrlEncoded ());
}
}
//
// Create request ...
var request = new RestRequest (url, DataFormat.Json);
//
if (addXPoweredValue) {
request.AddHeader (XAuthorization.XPoweredBy, identityConfiguration.XPoweredValue);
}
//
// Add Headers to request ...
if (!headers.IsNull () && headers.Count > 0) {
//
var enumerator = headers.GetEnumerator ();
while (enumerator.MoveNext ()) {
//
var item = enumerator.Current;
request.AddHeader (item.Key, item.Value);
}
}
//
return request;
}
/// <summary>
/// Handle Call Specific Request and retrieve Response
/// </summary>
/// <param name="client"></param>
/// <param name="request"></param>
/// <param name="method"></param>
/// <typeparam name="T"></typeparam>
/// <returns></returns>
public async Task<T> RunRestRequest<T> (
RestClient client,
RestRequest request,
XHttpMethod method,
bool supportRefreshingTokens = true
) {
//
var response = await Task.Run (async () => {
//
IRestResponse resp = null;
//
// Call Endpoint Service using Specified Method ...
switch (method) {
//
// Get ...
case XHttpMethod.GET:
resp = client.Get (request);
break;
//
// Put ...
case XHttpMethod.PUT:
resp = client.Put (request);
break;
//
// Post ...
case XHttpMethod.POST:
resp = client.Post (request);
break;
//
// Delete ...
case XHttpMethod.DELETE:
resp = client.Delete (request);
break;
}
//
if (!resp.IsSuccessful) {
//
// Log Exception ...
Logger.LogError ($"Error: {resp.ErrorMessage}");
Logger.LogError ($"Exception: {resp.ErrorException.ToJSON()}");
if (!resp.ErrorMessage.IsNullOrEmpty () &&
resp.ErrorMessage.Contains ("timed out")) {
XException.Timeout.Throw ();
}
//
// TODO: Check UnAuthorized Status here for
// Refresh Tokens or Issue Correct Exception ...
if (supportRefreshingTokens &&
resp.StatusCode == System.Net.HttpStatusCode.Unauthorized) {
//
var isRefreshed = request.Parameters.Any (rp =>
rp.Name == XParam.XIsRefreshed.GetStringValue () &&
rp.Value.ToString ().ToNormalString () == true.ToJSON ());
//
Logger.LogInformation ($"isRefreshed: {isRefreshed}");
//
// Get Access Token ...
XTokenResponse tokens = null;
var accessToken = request.Parameters.FirstOrDefault (rp =>
rp.Name.ToNormalString () == XAuthorization.Header.ToNormalString ()).Value.ToString ();
if (!accessToken.IsNullOrEmpty ()) {
//
accessToken = accessToken.Replace (XAuthorization.TokenIdentifier, "");
//
if (!accessToken.IsNullOrEmpty ()) {
tokens = await tokenProvider.RetrieveToken (accessToken);
}
}
//
// Refresh Token and then re do request ...
if (!isRefreshed &&
!accessToken.IsNullOrEmpty () &&
!tokens.IsNull () &&
tokens.IsRefreshable ()) {
//
request.AddHeader (XParam.XIsRefreshed.GetStringValue (), true.ToJSON ());
//
// Refreshe Tokens ...
var refreshedTokens = await RefreshTokens (tokens);
//
// Renew Rest Client with Refreshed Tokens ...
var timeout = client.Timeout;
client = GetRestClient (refreshedTokens);
client.Timeout = Timeout.Infinite;
//
// Do Request Again using renew Client ...
return await RunRestRequest<T> (
client: client,
request: request,
method: method);
}
}
//
var ex = resp.Content.ToXError ();
if (!ex.IsNull ()) {
throw ex.ToException ();
}
//
// UnAuthorized ...
if (resp.StatusCode == System.Net.HttpStatusCode.Unauthorized) {
XException.NotAuthorized.Throw ();
}
//
// NotFound ...
if (resp.StatusCode == System.Net.HttpStatusCode.NotFound) {
XException.NotFound.Throw ();
}
//
XException.ActionFailed.Throw ();
}
//
var result = resp.Content.FromJSON<T> ();
return result;
});
//
return response;
}
/// <summary>
/// Get User SelectBy Param
/// </summary>
/// <param name="model"></param>
/// <param name="forceNotNull"></param>
/// <param name="excludes"></param>
/// <returns></returns>
public string GetUserSelectByParam (
XActionRequest model,
bool forceNotNull = true,
ICollection<XUserSelectBy> excludes = null
) {
//
// Validate Args ...
validationProvider.NotNull (model);
//
var id = model.UserId;
var userName = model.UserName;
var email = model.Email;
var phoneNumber = model.MobileNumber;
//
if (excludes != null) {
//
if (excludes.Contains (XUserSelectBy.ID)) {
id = null;
}
if (excludes.Contains (XUserSelectBy.Email)) {
email = null;
}
if (excludes.Contains (XUserSelectBy.MobileNumber)) {
phoneNumber = null;
}
if (excludes.Contains (XUserSelectBy.Username)) {
userName = null;
}
}
var selectByParam =
id.IsNullOrEmpty () ?
userName.IsNullOrEmpty () ?
email.IsNullOrEmpty () ?
phoneNumber.IsNullOrEmpty () ? null : phoneNumber : email : userName : id;
//
// Check result ...
if (forceNotNull &&
selectByParam.IsNullOrEmpty ()) {
XException.InvalidData.Throw ();
}
//
return selectByParam;
}
#endregion
}
}
+151
View File
@@ -0,0 +1,151 @@
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using xCommons.Extensions;
using xIdentityModels.Models;
using xIdentityService.Interfaces;
namespace xIdentityService.Providers {
public partial class XInMemoryTokenProvider : IXTokenProvider {
private IDictionary<string, XTokenResponse> DbContext;
public XInMemoryTokenProvider () {
//
this.DbContext = new Dictionary<string, XTokenResponse> ();
}
public async Task<bool> IsTokenExists (string accessToken) {
//
// Validate Args ...
if (accessToken.IsNullOrEmpty ()) {
return false;
}
//
// Process Result ...
var result = DbContext.Keys.Any (k => k == accessToken);
return await Task.FromResult (result);
}
public async Task<bool> IsTokenExists (XTokenResponse tokens) {
//
// Validate Args ...
if (tokens.IsNull () ||
tokens.AccessToken.IsNullOrEmpty () ||
!await IsTokenExists (tokens.AccessToken)) {
return false;
};
//
// Process Result ...
var result = await IsTokenExists (tokens.AccessToken);
return result;
}
public async Task<bool> RemoveToken (string accessToken) {
//
// Validate Args ...
if (accessToken.IsNullOrEmpty ()) {
return false;
}
//
// Process Result ...
var result = DbContext.Remove (accessToken);
return await Task.FromResult (result);
}
public async Task<bool> RemoveToken (XTokenResponse tokens) {
//
// Validate Args ...
if (tokens.IsNull () ||
tokens.AccessToken.IsNullOrEmpty () ||
!await IsTokenExists (tokens.AccessToken)) {
return false;
};
//
// Process Result ...
var result = await RemoveToken (tokens.AccessToken);
return result;
}
public async Task<XTokenResponse> RetrieveToken (string accessToken) {
//
// Validate Args ...
if (accessToken.IsNullOrEmpty () ||
!await IsTokenExists (accessToken)) {
return null;
}
//
// Process Result ...
var result = DbContext[accessToken];
return result;
}
public async Task<bool> AddToken (XTokenResponse tokens) {
//
// Validate Args ...
if (tokens.IsNull () ||
tokens.AccessToken.IsNullOrEmpty () ||
await IsTokenExists (tokens.AccessToken)) {
return false;
};
//
// Process Result ...
try {
//
DbContext.Add (tokens.AccessToken, tokens);
return true;
} catch {
return false;
}
}
public async Task<bool> UpdateToken (XTokenResponse tokens) {
//
// Validate Args ...
if (tokens.IsNull () ||
tokens.AccessToken.IsNullOrEmpty () ||
!await IsTokenExists (tokens.AccessToken)) {
return false;
};
//
// Process Result ...
try {
//
DbContext[tokens.AccessToken] = tokens;
return true;
} catch {
return false;
}
}
public async Task<bool> AddOrUpdateToken (XTokenResponse tokens) {
//
// Validate Args ...
if (tokens.IsNull () ||
tokens.AccessToken.IsNullOrEmpty ()
) {
return false;
};
//
// Process Result ...
try {
//
var isExists = await IsTokenExists (tokens);
if (isExists) {
return await UpdateToken (tokens);
} else {
return await AddToken (tokens);
}
} catch {
return false;
}
}
}
}
+215
View File
@@ -0,0 +1,215 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Web;
using xCommons.Extensions;
using xExceptions.Constants;
using xIdentityService.Configuration;
using xIdentityService.Interfaces;
namespace xIdentityService.Providers {
public class XProxyHelper : IXProxyHelper {
//
#region Props ...
public XProxyConfiguration Configuration { get; }
#endregion
//
#region Constructor ...
public XProxyHelper (XProxyConfiguration configuration) {
this.Configuration = configuration;
}
#endregion
//
#region Actions ...
/// <summary>
/// Validate XProxy Configuration for Client ...
/// </summary>
/// <returns></returns>
public bool ValidateConfiguration () {
//
var result = !Configuration.IsNull () &&
!Configuration.Host.IsNullOrEmpty () &&
Configuration.Host.IsValidUrl () &&
Configuration.Routes.HasChild ();
//
return result;
}
/// <summary>
/// retrie Normalize Host ...
/// </summary>
/// <returns></returns>
public string NormalizeHost () {
//
var result = string.Empty;
//
if (!Configuration.IsNull () &&
!Configuration.Host.IsNullOrEmpty () &&
Configuration.Host.IsValidUrl ()
) {
//
result = Configuration.Host
.ToNormalString ();
//
if (result.EndsWith ("/")) {
result = result.Substring (0, result.Length - 1);
}
}
//
return result;
}
/// <summary>
/// retrieve all registred Routes ...
/// </summary>
/// <returns></returns>
public IEnumerable<XProxyRouteDescriptor> GetRoutes () {
//
// Validate Args ...
if (Configuration.IsNull ()) {
return null;
}
//
return Configuration.Routes;
}
/// <summary>
/// Retrieve all Prepared url of Routes ...
/// </summary>
/// <returns></returns>
public IEnumerable<string> GetRouteUrls () {
//
var normalHost = NormalizeHost ();
if (normalHost.IsNullOrEmpty ()) {
return null;
}
//
var result = GetRoutes ()
.Select (r => $"{normalHost}{r.Route}");
//
return result;
}
/// <summary>
/// Find an Specific Route ...
/// </summary>
/// <param name="whereClause"></param>
/// <returns></returns>
public XProxyRouteDescriptor FindRoute (Expression<Func<XProxyRouteDescriptor, bool>> whereClause) {
//
// Validate Arg ...
if (whereClause.IsNull ()) {
return null;
}
//
var whereFunc = whereClause
.Compile ();
//
var result = GetRoutes ()
.FirstOrDefault (whereFunc);
//
return result;
}
/// <summary>
/// Prepare a request url for a Proxy Route ...
/// </summary>
/// <param name="url"></param>
/// <param name="descriptor"></param>
/// <returns></returns>
public string PrepareActionUrlForXProxyRoute (
string url,
XProxyRouteDescriptor descriptor
) {
//
if (!url.IsValidUrl () ||
url.IsNullOrEmpty () ||
!ValidateConfiguration ()
) {
throw XException.InvalidArgs.ToException ();
}
//
// find Route ...
var routeDescriptor = GetRoutes ()
.FirstOrDefault (r => r
.IsSameContent (descriptor)
);
//
// Validate Route Descriptor ...
if (
routeDescriptor.IsNull () ||
routeDescriptor.Route.IsNullOrEmpty ()
) {
throw XException.InvalidArgs.ToException ();
}
//
// Retrieve and Validate Host Address ...
var host = NormalizeHost ();
if (!host.IsValidUrl () ||
host.IsNullOrEmpty ()
) {
throw XException.InvalidArgs.ToException ();
}
//
url = $"{host}{routeDescriptor.Route}/{HttpUtility.UrlEncode(url)}";
//
return url;
}
/// <summary>
/// Prepare a request url for a Selected Proxy Route ...
/// </summary>
/// <param name="url"></param>
/// <param name="whereClause"></param>
/// <returns></returns>
public string PrepareActionUrlForXProxyRoute (
string url,
Expression<Func<XProxyRouteDescriptor, bool>> whereClause
) {
//
if (!url.IsValidUrl () ||
url.IsNullOrEmpty () ||
whereClause.IsNull () ||
!ValidateConfiguration ()
) {
throw XException.InvalidArgs.ToException ();
}
//
var descriptor = FindRoute (whereClause);
//
// find Route ...
var result = PrepareActionUrlForXProxyRoute (
url: url,
descriptor: descriptor
);
//
return result;
}
#endregion
//
#region Private ...
#endregion
}
}
+22
View File
@@ -0,0 +1,22 @@
# xIdentityService
it is a Part of xDashboard on SaherElm IT Center which provides:
- Any Requirement to Connect XIdentityServer.
- etc.
this module has following dependencies :
- xCommons
- xModels
- xHttpService
for configure and use this Module refer to DI.XDIHelperExtension.cs file.
## Maintainer
Hadi Khazaee asl
[https://www.saherelm.ir](https://www.saherelm.ir)
[hadi_khazaee_asl@yahoo.com](mailto:hadi_khazaee_asl@yahoo.com)
+147
View File
@@ -0,0 +1,147 @@
using System;
using System.IO;
using System.Security.Cryptography;
using System.Text;
using xCommons.Extensions;
using xCommons.Helpers;
using xCommons.Providers;
using xIdentityService.Configuration;
using xIdentityService.Interfaces;
namespace xIdentityService.Security {
public partial class XSecurityProvider : IXSecurityProvider {
private readonly string secretKey;
private readonly byte[] iv;
private readonly byte[] key;
private readonly XValidationProvider validationProvider;
public XSecurityProvider (
XIdentityServiceConfiguration identityConfiguration,
XValidationProvider validationProvider
) {
//
this.secretKey = identityConfiguration.XRevisionSecretKey.ToMd5String ();
this.validationProvider = validationProvider;
//
var ivBytes = new byte[16];
var keyBytes = new byte[32];
var secretBytes = Encoding.UTF8.GetBytes (this.secretKey);
//
Array.Copy (
secretBytes,
ivBytes,
secretBytes.Length < ivBytes.Length ?
secretBytes.Length :
ivBytes.Length
);
this.iv = ivBytes;
//
Array.Copy (
secretBytes,
keyBytes,
secretBytes.Length < keyBytes.Length ?
secretBytes.Length :
keyBytes.Length
);
this.key = keyBytes;
// Encoding.UTF8.GetBytes (this.secretKey);
}
public string Encrypt (string plainText) {
//
validationProvider.NotEmpty (plainText);
//
var textBytes = Encoding.UTF8.GetBytes (plainText);
var result = EncryptFromBytes (textBytes);
//
return result;
}
public string Decrypt (string cipherText) {
//
validationProvider.NotEmpty (cipherText);
//
var cipherBytes = Convert.FromBase64String (cipherText);
var result = DecryptFromBytes (cipherBytes);
//
return result;
}
public string EncryptFromBytes (byte[] textBytes) {
//
// Validate Args ...
validationProvider.NotNull (textBytes);
// Declare the string used to hold
// the decrypted text.
byte[] encryptedBytes = null;
// Create an RijndaelManaged object
// with the specified key and IV.
using (var rijAlg = new RijndaelManaged ()) {
//Settings
rijAlg.Mode = CipherMode.CBC;
rijAlg.Padding = PaddingMode.PKCS7;
// rijAlg.FeedbackSize = 128;
rijAlg.Key = key;
rijAlg.IV = iv;
//
using (var encryptor = rijAlg.CreateEncryptor (rijAlg.Key, rijAlg.IV)) {
encryptedBytes = encryptor.TransformFinalBlock (textBytes, 0, textBytes.Length);
}
}
//
return Convert.ToBase64String (encryptedBytes);
}
public string DecryptFromBytes (byte[] cipherBytes) {
//
// Validate Args ...
validationProvider.NotNull (cipherBytes);
// Declare the string used to hold
// the decrypted text.
string plaintext = null;
// Create an RijndaelManaged object
// with the specified key and IV.
using (var rijAlg = new RijndaelManaged ()) {
//Settings
rijAlg.Mode = CipherMode.CBC;
rijAlg.Padding = PaddingMode.PKCS7;
// rijAlg.FeedbackSize = 128;
rijAlg.Key = key;
rijAlg.IV = iv;
// Create a decrytor to perform the stream transform.
var decryptor = rijAlg.CreateDecryptor (rijAlg.Key, rijAlg.IV);
// Create the streams used for decryption.
using (var msDecrypt = new MemoryStream (cipherBytes)) {
using (var csDecrypt = new CryptoStream (msDecrypt, decryptor, CryptoStreamMode.Read)) {
using (var srDecrypt = new StreamReader (csDecrypt)) {
// Read the decrypted bytes from the decrypting stream
// and place them in a string.
plaintext = srDecrypt.ReadToEnd ();
}
}
}
}
//
return plaintext;
}
}
}
+7
View File
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<packageSources>
<add key="nuget" value="https://api.nuget.org/v3/index.json" protocolVersion="3" />
<add key="liget" value="https://nuget.saherelmhub.ir/v3/index.json" protocolVersion="3" />
</packageSources>
</configuration>
+39
View File
@@ -0,0 +1,39 @@
<Project Sdk="Microsoft.NET.Sdk">
<!-- Runtime Definition -->
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<PackageId>xDashboard.xIdentityService</PackageId>
<Version>1.0.0</Version>
<Authors>Hadi Khazaee Asl</Authors>
<Company>SaherElm IT Center</Company>
<Description>
provide an interface to connect xDashboard IdentityServer and do OAuth Actions to xDashboard
project.
</Description>
<!-- Icon Definition -->
<PackageIcon>icon.png</PackageIcon>
</PropertyGroup>
<!-- Icon Handling -->
<ItemGroup>
<None Include="../../Resources/Images/favicon.png" Link="icon.png" Pack="true" PackagePath="\icon.png" />
</ItemGroup>
<!-- Local Modules -->
<ItemGroup>
<PackageReference Include="xDashboard.xHttpService" Version="1.0.0" />
<PackageReference Include="xDashboard.xDataService" Version="1.0.0" />
<!-- <ProjectReference Include="../xHttpService/xHttpService.csproj" />
<ProjectReference Include="../xDataService/xDataService.csproj" /> -->
</ItemGroup>
<!-- Dependencies -->
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Authentication.Abstractions" Version="2.2.0" />
<PackageReference Include="IdentityModel.AspNetCore.OAuth2Introspection" Version="4.0.0-preview.6" />
</ItemGroup>
</Project>