Initial Commit ...
This commit is contained in:
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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; }
|
||||
}
|
||||
}
|
||||
@@ -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";
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
using xExceptions.Attributes;
|
||||
|
||||
namespace xIdentityService.Constants {
|
||||
public enum XAuthenticationScheme {
|
||||
[StringValue ("token")]
|
||||
XToken, [StringValue ("introspection")]
|
||||
XIntrospection,
|
||||
}
|
||||
}
|
||||
@@ -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,
|
||||
}
|
||||
}
|
||||
@@ -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";
|
||||
}
|
||||
}
|
||||
@@ -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";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
namespace xIdentityService.Constants {
|
||||
public enum XTokenType {
|
||||
//
|
||||
// Summary:
|
||||
// Self-contained Json Web Token
|
||||
Jwt,
|
||||
//
|
||||
// Summary:
|
||||
// Reference token
|
||||
Reference
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -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 ();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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> ();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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> ();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -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)
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
Reference in New Issue
Block a user