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