using System; using System.Linq; using System.Threading.Tasks; using Microsoft.AspNetCore.Identity; using xCommons.Extensions; using xExceptions.Constants; using xIdentityModels; using xIdentityModels.Constants; using xIdentityModels.Extensions; using xIdentityModels.Models; using xIdentityModels.Navigations; namespace xIds.Providers { public partial class XIdentityManager { // #region User Validators ... /// /// Validate User Name for Registration based on Policies /// /// provided user name /// a boolean value private bool ValidateUserName( string userName ) { // // Check min/max Length ... if (userName.IsNullOrEmpty() || userName.Length < Configuration.Policy.User.MinLength || userName.Length > Configuration.Policy.User.MaxLength) { return false; } // // Check Allowed UserName Characters ... if (!UserManager.Options.User.AllowedUserNameCharacters.IsNullOrEmpty() && userName.Any(c => !UserManager.Options.User.AllowedUserNameCharacters.Contains(c))) { return false; } // // Check invalid UserNames ... if (Configuration.Policy.User.InvalidUserNames .HasChild() && Configuration.Policy.User.InvalidUserNames .Any(u => userName .ToNormalString() .Contains(u.ToNormalString()))) { return false; } // return true; } /// /// Validate a User Exists /// /// specifies user identifier /// specify Excetion to thrown on failure /// private async Task ValidateUserExistsAsync( string userSelectByParam, Exception exception = null ) { // ValidationProvider .NotEmpty(userSelectByParam); // if (exception == null) { exception = XException.NotFound.ToException(); } // // Check User Exists ... var isExists = await IsUserExistsAsync(userSelectByParam); if (!isExists) { throw exception; } } /// /// Validate a User Not Exists /// /// specifies user identifier /// specify Excetion to thrown on failure /// private async Task ValidateUserNotExists( string userSelectByParam, Exception exception = null ) { // ValidationProvider .NotEmpty(userSelectByParam); // if (exception == null) { exception = XException.UserRegisteredBefore.ToException(); } // // Check User Exists ... var isExists = await IsUserExistsAsync(userSelectByParam); if (isExists) { throw exception; } } /// /// Validate User Exists and Some Usefull Checks /// /// specifies user identifier /// specifies returned object contains all Navigation Properties or not, default is false /// check a user can log in in system or not, default is false /// check user is banned or not, default is true /// specify do not thrown Exception if user is Disabled, default is false /// specify requested person is Admin role, default is false /// specify Excetion to thrown on failure /// an instance of XUser public async Task ValidateUserExistsAndRetrieve( string userSelectByParam, bool containDetails = false, bool checkCanLoginPolicies = false, bool checkIsBanned = true, bool ignoreDisabledUser = false, bool forceAdmin = false, Exception exception = null ) { // ValidationProvider .NotEmpty(userSelectByParam); ValidationProvider.NotNull( Configuration, Configuration.Policy, Configuration.Policy.SignIn); // // Prepare Default Exception ... if (exception == null) { exception = XException.InvalidData.ToException(); } // // Check User Exists ... await ValidateUserExistsAsync(userSelectByParam); // // Retrieve User ... var result = await GetUserAsync(userSelectByParam, containDetails); if (result == null) { throw exception; } // // Check Force Admin ... if (forceAdmin) { // var isAdmin = await IsAdmin(result); if (!isAdmin) { XException.NotAuthorized.Throw(); } } // // Check User not Bann ... if (checkIsBanned && result.IsBanned) { XException.UserBanned.Throw(); } // var requireConfirmedEmail = Configuration.Policy.SignIn.RequireConfirmedEmail; var requireConfirmedPhoneNumber = Configuration.Policy.SignIn.RequireConfirmedPhoneNumber; var requireEnabled = Configuration.Policy.SignIn.RequiredEnabled; // var isEnabled = result.IsEnable; var isMobileConfirmed = result.PhoneNumberConfirmed; var isEmailConfirmed = result.EmailConfirmed; // if (checkCanLoginPolicies) { // // Check IsEnabled ... if (!ignoreDisabledUser && requireEnabled && !isEnabled) { XException.UserDisabled.Throw(); } // // Check Email Confirmed ... if (requireConfirmedEmail && !isEmailConfirmed) { XException.EmailNotConfirmed.Throw(); } // // Check Mobile Confirmed ... if (requireConfirmedPhoneNumber && !isMobileConfirmed) { XException.MobileNotConfirmed.Throw(); } } // // Return Result ... return result; } /// /// Validate a Device for User Actions /// /// an instance of XDevice /// private async Task ValidateDeviceForActions( XDevice device ) { // ValidationProvider .NotNull(device); // // Check is Device Banned or not ... var isDeviceBanned = await IsDeviceBanned(device); if (isDeviceBanned) { // // Retrieve Banned Device ... var xBannedDevice = await GetBannedDevice(device); if (xBannedDevice == null) { XException.InvalidArgs.Throw(); } // // Check Banned Device Time out Passed or not ... var isDelayTimePassed = IsDelayTimePassed(xBannedDevice); if (!isDelayTimePassed) { // var passedTime = GetPassedTime(xBannedDevice); // XException.DeviceBanned .AddContentToException(passedTime.ToString()); } // // if Delay Passed of Banned Device // the device must Removed ... await BannedDeviceRemove(xBannedDevice); } } /// /// Validate a DateOfBirth for Registration /// /// users dob date, an instance of DateTime /// specify Excetion to thrown on failure /// private void ValidateDateOfBirth( DateTime dateOfBirth, Exception exception = null ) { // // Validate Args ... ValidationProvider.NotNull(dateOfBirth); // if (exception.IsNull()) { exception = XException.InvalidDate.ToException(); } // var currentDate = DateTime.UtcNow; if (dateOfBirth >= currentDate) { throw exception; } // var zeroDate = (new DateTime(1, 1, 1)).ToUniversalTime(); var minAge = Configuration.Policy.User.MinAgeForRegistration; var maxAge = Configuration.Policy.User.MaxAgeForRegistration; // var timeSpan = currentDate - dateOfBirth; var age = (zeroDate + timeSpan).Year - 1; // if (age > maxAge || age < minAge) { throw exception; } } /// /// Validate a Given User Can Registere /// /// specifies user identifier /// private async Task ValidateCanRegister( string userSelectByParam ) { // // Validate Args ... ValidationProvider.NotEmpty(userSelectByParam); // var canRegister = await CanRegister(userSelectByParam); if (!canRegister) { XException.Unavailable.Throw(); } } /// /// Validate Password by Gicen Policies /// /// an instance of XUser /// user's password /// specify Excetion to thrown on failure /// private async Task ValidatePasswordPolicies( XUser user, string password, Exception exception = null ) { // // Validate Args ... ValidationProvider.NotNull(user); ValidationProvider.NotEmpty(password); // // Prepare Default Exception ... if (exception == null) { exception = XException.InvalidPassword.ToException(); } // // Check new Password Validation ... var passwordValidator = new PasswordValidator(); var checkPasswordResult = await passwordValidator.ValidateAsync(UserManager, user, password); if (!checkPasswordResult.Succeeded) { throw exception; } } /// /// Validate a User for Dangerous Actions /// /// an instance of XUser /// specified which user request Action by an instance of XUser /// private async Task ValidateUserForDangerousAction( XUser user, XUser requester ) { // // Validate ARgs ... ValidationProvider.NotNull(user, requester); // var requesterRoleNames = await GetRoleNamesAsync(requester.Id); // var isSame = user.Id == requester.Id; var isRequesterAdmin = requesterRoleNames.Any(r => r.ToNormalString() == "admin"); if (!isSame && !isRequesterAdmin) { XException.NotAllowed.Throw(); } } #endregion // #region Device Validators ... /// /// Validate a Device for Specified User /// /// specifies user identifier /// an instance of XDevice /// specify Excetion to thrown on failure /// private async Task ValidateUserAndDeviceRelation( string userSelectByParam, XDevice device, Exception exception = null ) { // ValidationProvider.NotEmpty(userSelectByParam); ValidationProvider.NotNull(device); // if (exception == null) { exception = XException.InvalidDevice.ToException(); } // var user = await ValidateUserExistsAndRetrieve( userSelectByParam, containDetails: true); // var result = await IsDeviceRelateDToUser( userSelectByParam, device ); if (!result) { throw exception; } } #endregion // #region Token Validators ... /// /// Validate a Token /// /// token string /// specify Excetion to thrown on failure private void ValidateToken( string token, Exception exception = null ) { // ValidationProvider.NotEmpty(token); // if (exception == null) { exception = XException.InvalidToken.ToException(); } // var result = IdentityHelper.ValidateToken(token); if (!result) { throw exception; } } /// /// Validate a Token is Specified to a Device and User /// /// an instance of XDevice /// specifies Action type by a member of XAction /// specify Excetion to thrown on failure /// an instance of XToken private async Task ValidateAndRetieveTokenByDeviceAndType( XDevice device, XAction type, Exception exception = null ) { // ValidationProvider.NotNull(device); // // Prepare Default Exception ... if (exception == null) { exception = XException.NotFound.ToException(); } // var isExists = await IsTokenExistsByDeviceAndType(device, type); if (!isExists) { throw exception; } // var item = await GetTokenByDeviceAndType(device, type); if (item == null) { throw exception; } // return item; } /// /// Validate a Token By User and Specified Type /// /// specifies user identifier /// specifies Action type by a member of XAction /// specify Excetion to thrown on failure /// an instance of XToken private async Task ValidateAndRetieveTokenByUserAndType( string userSelectByParam, XAction type, Exception exception = null ) { // ValidationProvider.NotEmpty(userSelectByParam); // // Prepare Default Exception ... if (exception == null) { exception = XException.InvalidData.ToException(); } // var isExists = await IsTokenExistsByUserAndType(userSelectByParam, type); if (!isExists) { throw exception; } // var item = await GetTokenByUserAndType(userSelectByParam, type); if (item == null) { throw exception; } // return item; } /// /// Check Token Validation /// /// token string /// a boolean value private bool IsValidToken( string token ) { // ValidationProvider.NotEmpty(token); // var result = IdentityHelper.ValidateToken(token); // return result; } /// /// Retrieve Action Request Based on Action Token /// /// token string /// specify Excetion to thrown on failure /// an instance of XActionRequestToken private XActionRequestToken ValidateAndParseActionToken( string token, Exception exception = null ) { // ValidationProvider.NotEmpty(token); // // Prepare Default Exception ... if (exception == null) { exception = XException.InvalidToken.ToException(); } // ValidateToken(token); // var result = IdentityHelper.ParseActionRequestToken(token); if (result == null) { throw exception; } // ValidateActionRequest(result); // return result; } /// /// Parse Action Request from Token /// /// token string /// an instance of XActionRequestToken private XActionRequestToken ParseActionRequest( string token ) { // // Validate Args ... ValidationProvider.NotEmpty(token); // var result = IdentityHelper .ParseActionRequestToken(token); // return result; } /// /// Parse Action Hash by Corresponding Token /// /// token hash string /// an instance of XActionRequestToken private async Task ParseActionHash( string hash ) { // ValidationProvider.NotEmpty(hash); // var isHashExists = await IsTokenExistsByHash(hash); if (!isHashExists) { return null; } // var xToken = await GetTokenByHash(hash); if (xToken == null) { return null; } // var isValidToken = IsValidToken(xToken.Token); if (!isValidToken) { return null; } // var result = ParseActionRequest(xToken.Token); // return result; } /// /// Validate and Parse Action Hash /// /// token hash string /// specifies chack token Validation Parameter, default is true /// specifies check action Validations, default is true /// specify Excetion to thrown on failure /// an instance of XActionRequestToken private async Task ValidateAndParseActionHash( string hash, bool forceTokenValidation = true, bool forceActionValidation = true, Exception exception = null ) { // ValidationProvider.NotEmpty(hash); // // Prepare Default Exception ... if (exception == null) { exception = XException.InvalidToken.ToException(); } // var token = await ValidateAndRetrieveRelatedToken(hash, forceTokenValidation); // var result = await ParseActionHash(hash); if (result == null) { throw exception; } // if (forceActionValidation) { ValidateActionRequest(result); } // return result; } /// /// Validate Action Request /// /// an instance of XActionRequestToken /// specify Excetion to thrown on failure private void ValidateActionRequest( XActionRequestToken request, Exception exception = null ) { // ValidationProvider .NotNull(request); // // Prepare Default Exception ... if (exception == null) { exception = XException.InvalidData.ToException(); } // var isValid = IsValidActionRequest(request); if (!isValid) { throw exception; } } /// /// Check Action Request Validation /// /// an instance of XActionRequestToken /// a boolean value private bool IsValidActionRequest( XActionRequestToken request ) { // // Validate Args ... if (request == null || Configuration.IdentitySecretKey.IsNullOrEmpty()) { XException.InvalidArgs.Throw(); } // var result = request.Validate(Configuration.IdentitySecretKey); // return result; } /// /// Check Token and Act Based on it /// /// token string /// specify Excetion to thrown on Issue failure /// specify Excetion to thrown on failure /// private async Task ValidateAndHandleToken( string token, bool issueExcepion = false, Exception exception = null ) { // // Validate Args ... ValidationProvider.NotEmpty(token); // // Prepare Default Exception ... if (exception == null) { exception = XException.InvalidToken.ToException(); } // var isValidToken = IsValidToken(token); // if (!isValidToken) { // await RemoveTokenByToken(token); // if (issueExcepion) { throw exception; } } } /// /// Validate a Hash Exists or not /// /// token hash string /// specify Excetion to thrown on failure /// private async Task ValidateHashExists( string hash, Exception exception = null ) { // // Validate Args ... ValidationProvider.NotEmpty(hash); // // Prepare Default Exception ... if (exception == null) { exception = XException.InvalidToken.ToException(); } // var isExists = await IsTokenExistsByHash(hash); if (!isExists) { throw exception; } } /// /// Validate a Token Exists /// /// token string /// specify Excetion to thrown on failure /// private async Task ValidateTokenExists( string token, Exception exception = null ) { // // Validate Args ... ValidationProvider.NotEmpty(token); // // Prepare Default Exception ... if (exception == null) { exception = XException.InvalidToken.ToException(); } // var isExists = await IsTokenExistsByToken(token); if (!isExists) { throw exception; } } /// /// Validate a Hash and Retrieve it's Corresponding Token /// /// token hash string /// specifies chack token Validation Parameter, default is true /// specify Excetion to thrown on Issue failure /// specify Excetion to thrown on failure /// token string private async Task ValidateAndRetrieveRelatedToken( string hash, bool forceTokenValidation = true, bool issueExcepion = false, Exception exception = null ) { // // Validate Args ... ValidationProvider.NotEmpty(hash); // // Prepare Default Exception ... if (exception == null) { exception = XException.InvalidToken.ToException(); } // await ValidateHashExists(hash); // var token = await GetRelatedTokenByHash(hash); if (token.IsNullOrEmpty()) { throw exception; } // if (forceTokenValidation) { await ValidateAndHandleToken(token, issueExcepion); } // return token; } /// /// Validate a Token and Retrieve it's Corresponding Hash /// /// token string /// specifies chack token Validation Parameter, default is true /// specify Excetion to thrown on failure /// hash string private async Task ValidateAndRetrieveRelatedHash( string token, bool forceTokenValidation = true, Exception exception = null ) { // // Validate Args ... ValidationProvider.NotEmpty(token); // // Prepare Default Exception ... if (exception == null) { exception = XException.InvalidToken.ToException(); } // if (forceTokenValidation) { await ValidateAndHandleToken(token); } // await ValidateTokenExists(token); // var hash = await GetRelatedHashByToken(token); if (hash.IsNullOrEmpty()) { throw exception; } // return hash; } /// /// Validate Invitation Hash /// /// registration invitation hash string /// thrown Exception if user Exists, default is true /// private async Task ValidateInvitationHash( string invitationHash, bool forceUserExists = true ) { // // Validate Args ... ValidationProvider.NotNull(Configuration); // if (Configuration.RegistrationJustWithInvite && invitationHash.IsNullOrEmpty()) { XException.NotAllowed.Throw(); } // // Validate Invitation Token if it isn't null ... if (!invitationHash.IsNullOrEmpty()) { // await ValidateHashExists(invitationHash); // // Token Validation also done in this task ... var relatedToken = await ValidateAndRetrieveRelatedToken(invitationHash); // var inviteAction = ValidateAndParseActionToken(relatedToken); ValidationProvider.NotNull(inviteAction); // var inviteUerSelectByParam = GetUserSelectByParam(inviteAction); var inviteUserSelectBy = GetUserSelectByType(inviteUerSelectByParam); if (inviteUserSelectBy != XUserSelectBy.Email) { XException.InvalidToken.Throw(); } // if (forceUserExists) { // await ValidateUserNotExists( inviteUerSelectByParam, XException.EmailInUsed.ToException()); } } } #endregion // #region Profile Validators ... /// /// Validate a Request is Corresponding to Specific Device /// /// an instance of XDevice /// specify requested device by an instance of XDevice /// specify Excetion to thrown on failure private void ValidateRequestAndGiveDevices( XDevice device, XDevice requestDevice, Exception exception = null ) { // // Validate Args ... ValidationProvider.NotNull(device, requestDevice); // // Prepare Default Exception ... if (exception == null) { exception = XException.InvalidDevice.ToException(); } // var isDevicesSame = device.IsSameAs(requestDevice); // if (!isDevicesSame) { throw exception; } } /// /// Check Validation of a User SelectBy Param and Password /// /// specifies user identifier /// user's password /// check a user can log in in system or not, default is true /// specify Excetion to thrown on failure /// private async Task ValidateUserAndPassword( string userSelectByParam, string password, bool checkCanLoginPolicies = true, Exception exception = null ) { // // Validate Args ... ValidationProvider.NotEmpty( userSelectByParam, password ); // // Prepare Default Exception ... if (exception == null) { exception = XException.LoginFailed.ToException(); } // // Retrieve User and Validate User Exists ... var user = await ValidateUserExistsAndRetrieve( userSelectByParam, containDetails: false, checkCanLoginPolicies: checkCanLoginPolicies, ignoreDisabledUser: false, checkIsBanned: true, exception: exception); // // Check Given Password Follows Policies ... await ValidatePasswordPolicies(user, password, exception); // // Check Password for User ... var checkPasswordResult = await UserManager.CheckPasswordAsync(user, password); if (!checkPasswordResult) { throw exception; } } #endregion // #region Friendship Validators ... /// /// Validate Friendship Requested Before or not /// /// specifies a user to check as source by an instance of XUser /// specifies a user to check as dest by an instance of XUser private void ValidateRequestBefore( XUser source, XUser dest ) { // // Validate Args ... ValidationProvider.NotNull(source, dest); // var isRequested = IsFollowRequested(source, dest); if (!isRequested) { XException.NotFound.Throw(); } } /// /// Validate a Friendship Not Requested Before /// /// specifies a user to check as source by an instance of XUser /// specifies a user to check as dest by an instance of XUser private void ValidateNotRequestBefore( XUser source, XUser dest ) { // // Validate Args ... ValidationProvider.NotNull(source, dest); // var isRequested = IsFollowRequested(source, dest); if (isRequested) { XException.Duplicate.Throw(); } } /// /// Validate User Can Send Following Request to Dest User /// /// specifies a user to check as dest by an instance of XUser /// specifies a user to check as source by an instance of XUser private void ValidateFollowingRequest( XUser accepterUser, XUser requesterUser ) { // // Validate Args ... ValidationProvider.NotNull(accepterUser, requesterUser); // var isRequest = IsFollowRequested(requesterUser, accepterUser, XFriendshipState.Pending); if (!isRequest) { XException.NotFound.Throw(); } } /// /// Validate a User can Accept a Following Request or Not /// /// specifies a user to check as dest by an instance of XUser /// specifies a user to check as source by an instance of XUser private void ValidateFollowingRequestForAccept( XUser accepterUser, XUser requesterUser ) { // // Validate Args ... ValidationProvider.NotNull(accepterUser, requesterUser); // var isRequestPending = IsFollowRequested(requesterUser, accepterUser, XFriendshipState.Pending); var isRequestRejected = IsFollowRequested(requesterUser, accepterUser, XFriendshipState.Rejected); if (!isRequestPending && !isRequestRejected) { XException.NotFound.Throw(); } } /// /// Validate a Request is not Passed for Same Users /// /// specifies a user to check as source by an instance of XUser /// specifies a user to check as dest by an instance of XUser private void ValidateNotSameUsers( XUser source, XUser dest ) { // // Validate ARgs ... ValidationProvider.NotNull(source, dest); // var isSame = source.Id == dest.Id; if (isSame) { XException.ActionFailed.Throw(); } } /// /// Check a user is in Followers of another /// /// specifies a user to check as source by an instance of XUser /// specifies a user to check as dest by an instance of XUser private void ValidateIsFollowers( XUser source, XUser dest ) { // // Validate Args ... ValidationProvider.NotNull(source, dest); // ValidateNotSameUsers(source, dest); ValidateRequestBefore(dest, source); // var isFollower = IsFollowRequested(dest, source, XFriendshipState.Accepted) || IsFollowRequested(dest, source, XFriendshipState.Blocked); if (!isFollower) { XException.NotFound.Throw(); } } /// /// Check a user is in Followings of another /// /// specifies a user to check as source by an instance of XUser /// specifies a user to check as dest by an instance of XUser private void ValidateIsFollowings( XUser source, XUser dest ) { // // Validate Args ... ValidationProvider.NotNull(source, dest); // ValidateNotSameUsers(source, dest); ValidateRequestBefore(source, dest); // var isFollowing = IsFollowRequested(source, dest, XFriendshipState.Accepted); if (!isFollowing) { XException.NotFound.Throw(); } } /// /// Validate a User Blocked another /// /// specifies a user to check as source by an instance of XUser /// specifies a user to check as dest by an instance of XUser private void ValidateIsBlock( XUser source, XUser dest ) { // // Validate Args ... ValidationProvider.NotNull(source, dest); // ValidateNotSameUsers(source, dest); ValidateRequestBefore(dest, source); // var isFollower = IsFollowRequested(dest, source, XFriendshipState.Blocked); if (!isFollower) { XException.NotFound.Throw(); } } #endregion // #region XActionRequest Validators ... /// /// Validate a Device for Request /// /// an instance of XDevice /// specify requested device by an instance of XDevice /// specify Excetion to thrown on failure private void ValidateRequestAndGivenDevices( XDevice device, XDevice requestDevice, Exception exception = null ) { // // Validate Args ... ValidationProvider.NotNull(device, requestDevice); // // Prepare Default Exception ... if (exception == null) { exception = XException.InvalidDevice.ToException(); } // var isDevicesSame = device.IsSameAs(requestDevice); // if (!isDevicesSame) { throw exception; } } #endregion // #region XVerification Request ... /// /// Validate Verification Request Exists by Device /// /// an instance of XDevice /// specify Excetion to thrown on failure /// private async Task ValidateVerificationRequestExists( XDevice device, Exception exception = null ) { // ValidationProvider.NotNull(device); // if (exception == null) { exception = XException.InvalidDevice.ToException(); } // var isExists = await IsDeviceRequestedForVerificationCodeBefor(device); if (!isExists) { throw exception; } } /// /// Validate Verification Request Exists by VerificationCode /// /// Confirm Verification Code /// specify Excetion to thrown on failure /// private async Task ValidateVerificationRequestExists( string verificationCode, Exception exception = null ) { // ValidationProvider.NotEmpty(verificationCode); // if (exception == null) { exception = XException.InvalidVerificationCode.ToException(); } // var isExists = await IsVerificationCodeRequested(verificationCode); if (!isExists) { throw exception; } } /// /// Validate and Retrive Verification Request for Given Device /// /// an instance of XDevice /// specify Excetion to thrown on failure /// an instance of XVerificationRequest private async Task ValidateAndRetrieveVerificationRequest( XDevice device, Exception exception = null ) { // ValidationProvider.NotNull(device); // if (exception == null) { exception = XException.InvalidDevice.ToException(); } // await ValidateVerificationRequestExists(device); // var result = await GetVerificationRequest(device); if (result == null) { throw exception; } // return result; } /// /// Validate and Retrieve Verification Request for Given VerificationCode /// /// Confirm Verification Code /// specify Excetion to thrown on failure /// an instance of XVerificationRequest private async Task ValidateAndRetrieveVerificationRequest( string verificationCode, Exception exception = null ) { // ValidationProvider.NotEmpty(verificationCode); // if (exception == null) { exception = XException.InvalidVerificationCode.ToException(); } // await ValidateVerificationRequestExists(verificationCode); // var result = await GetVerificationRequest(verificationCode); if (result == null) { throw exception; } // return result; } /// /// Handle Prepare Verification Request /// /// Confirm Verification Code /// an instance of XActionRequestToken /// an instance of XVerificationRequest private async Task HandleVerificationRequestPreparation( string verificationCode, XActionRequestToken request ) { // ValidationProvider .NotEmpty(verificationCode); // // Check Action Request Validation ... ValidateActionRequest(request); // var device = request.Context.Device; // // Check is Device Requested Before or not ... XVerificationRequest xVerificationRequest = null; var isDeviceRequested = await IsDeviceRequestedForVerificationCodeBefor(device); if (!isDeviceRequested) { // xVerificationRequest = new XVerificationRequest { VerificationCode = verificationCode, NumberOfTries = 1, LastTryOn = DateTime.UtcNow, Device = device, Request = request }; // await AddVerificationRequest(xVerificationRequest); } else { // // Get Verification Request ... xVerificationRequest = await ValidateAndRetrieveVerificationRequest(device); } // return xVerificationRequest; } #endregion } }