using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using xCommons.Extensions;
using xExceptions.Constants;
using xIdentityModels.Constants;
using xIdentityModels.Dtos;
using xIdentityModels.Models;
using xIdentityModels.Navigations;
using xModels.Dtos;
using xIds.Extensions;
using xIdentityModels.Extensions;
using xIdentityHelper;
using xIdentityHelper.Extensions;
using xDataService.Extensions;
namespace xIds.Providers
{
public partial class XIdentityManager
{
//
#region Retrieve Actions ...
///
/// Retrieve User Profile
///
/// a user identifier
/// requested user's identifier
/// specify check requested user's identifier not empty
/// and throw exception if it is, default true
/// check a user can log in in system or not, default is true
/// check user is banned or not, default is true
/// an instance of XUserProfileDto
public async Task GetUserProfileAsync(
string userSelectByParam,
string requestedUserSelectByParam,
bool forceCheckRequestedUser = true,
bool checkCanLoginPolicies = true,
bool checkIsBanned = true
)
{
//
// Data Validation ...
if (forceCheckRequestedUser)
{
ValidationProvider.NotEmpty(
userSelectByParam,
requestedUserSelectByParam);
}
else
{
ValidationProvider.NotEmpty(userSelectByParam);
}
//
var xUser = await ValidateUserExistsAndRetrieve(
userSelectByParam,
containDetails: true,
checkCanLoginPolicies: false,
checkIsBanned: false,
ignoreDisabledUser: true,
forceAdmin: false
);
//
var isAdmin = false;
var isSameUser = false;
if (forceCheckRequestedUser &&
!requestedUserSelectByParam.IsNullOrEmpty())
{
//
var xRequestedUser = await ValidateUserExistsAndRetrieve(
requestedUserSelectByParam,
containDetails: true,
checkCanLoginPolicies: false,
checkIsBanned: false,
ignoreDisabledUser: true,
forceAdmin: false
);
//
isSameUser = xUser.Id == xRequestedUser.Id;
//
var xRequestUserRoleNames = await GetRoleNamesAsync(
userSelectByParam: requestedUserSelectByParam,
checkCanLoginPolicies: false,
checkIsBanned: false
);
isAdmin = xRequestUserRoleNames.Contains(XUserRole.Admin.GetStringValue());
}
//
var roleNames = await GetRoleNamesAsync(
userSelectByParam,
checkIsBanned: checkIsBanned,
checkCanLoginPolicies: checkCanLoginPolicies
);
//
var xFriendshipInfo =
requestedUserSelectByParam.IsNullOrEmpty()
? null
: await GetFriendshipInfo(
requestedUserSelectByParam,
userSelectByParam,
checkIsBanned: checkIsBanned,
checkCanLoginPolicies: checkCanLoginPolicies
);
//
var result = xUser.ToXProfileDto(
isAdmin: isAdmin,
roles: roleNames,
isSameUser: isSameUser,
friendship: xFriendshipInfo,
profileConfig: Configuration.Policy.Profile
);
//
return result;
}
///
/// Retrieve a Collection of User Profiles
///
/// a collection of user identifiers
/// requested user's identifier
/// specify check requested user's identifier not empty
/// and throw exception if it is, default true
/// check a user can log in in system or not, default is true
/// check user is banned or not, default is true
/// an collection of XUserProfileDto instances
public async Task> GetUserProfilesAsync(
ICollection ids,
string requestedUserSelectByParam,
bool forceCheckRequestedUser = true,
bool checkCanLoginPolicies = true,
bool checkIsBanned = true
)
{
//
// Data Validation ...
if (forceCheckRequestedUser)
{
ValidationProvider.NotEmpty(requestedUserSelectByParam);
}
ValidationProvider.NotZeroChilds(ids);
//
var result = new List();
foreach (var id in ids)
{
//
var xProfile = await GetUserProfileAsync(
id,
requestedUserSelectByParam,
checkIsBanned: checkIsBanned,
checkCanLoginPolicies: checkCanLoginPolicies,
forceCheckRequestedUser: forceCheckRequestedUser
);
result.Add(xProfile);
}
//
return result;
}
///
/// Query User Profiles
///
/// requested user's identifier
/// how to filter results based on XQuery structure
/// an instance of XQueryResult of XUserProfileDto
public async Task> QueryUsers(
string requestedUserSelectByParam,
XQuery query
)
{
//
// Validation ...
if (query.IsNull())
{
XException.InvalidArgs.Throw();
}
//
// Normalize ...
query = query.NormalizeQuery(DataConfiguration.ToXDataServiceConfig());
//
// Since in Resourceable Entities we have to Search on Locales
// we Must Implement Senario Custom ...
var totalEntities = GetUsersDbSet()
.ToList()
.Where(u => !u.ContainsUserSelectByParam(requestedUserSelectByParam))
.Select(u => u.Id)
.ToList();
//
var items = await GetUserProfilesAsync(
totalEntities,
requestedUserSelectByParam,
checkIsBanned: false,
checkCanLoginPolicies: false,
forceCheckRequestedUser: false
);
//
var totalItemsCount = items.Count();
//
// Apply Filter ...
if (!query.Filter.IsNullOrEmpty())
{
//
items = items
.ApplyFilter(query.Filter);
}
int filteredItemsCount = items.Count();
//
// Count Pages ...
var totalPagesCount = query.CountPages(totalItemsCount);
var filteredPagesCount = query.CountPages(filteredItemsCount);
//
// Apply Paging and Sorting ...
if (totalItemsCount > 0 &&
filteredItemsCount > 0)
{
//
// Apply Sorting ...
items = items
.ToList()
.ApplySorting(
query.SortBy,
query.IsAscending
);
//
// Apply Paging ...
items = items
.ToList()
.ApplyPaging(
query.Page,
query.PageSize
);
}
//
// Generate Result Object ...
// Query = query,
var result = new XQueryResult
{
Items = items,
Page = query.Page,
PageSize = query.PageSize,
TotalPages = totalPagesCount,
TotalItems = totalItemsCount,
TotalFilteredPages = filteredPagesCount,
TotalFilteredItems = filteredItemsCount
};
//
return result;
}
///
/// Query In Roles User Profiles
///
/// requested user's identifier
/// an string which represent user role
/// how to filter results based on XQuery structure
/// if it's true the user must has exact role, otherwise top level users also listed, default is false
/// an instance of XQueryResult of XUserProfileDto
public async Task> QueryInRoleUsers(
string requestedUserSelectByParam,
string role,
XQuery query,
bool forceRole = false
)
{
//
// Validation ...
if (query.IsNull() || role.IsNullOrEmpty())
{
XException.InvalidArgs.Throw();
}
//
// Check Role Exists ...
var isExistsRole = await IsRoleExistsAsync(role);
if (!isExistsRole)
{
XException.NotFound.Throw();
}
//
// Normalize ...
query = query.NormalizeQuery(DataConfiguration.ToXDataServiceConfig());
//
#region Select Users Based on Specific Roles ...
var selectedUsers = new List();
var usersEnumerator = GetUsersDbSet(query.ContainsDetail).AsAsyncEnumerable();
await
foreach (var user in usersEnumerator)
{
//
if (user.ContainsUserSelectByParam(requestedUserSelectByParam))
{
continue;
}
//
// Set Default Value is True ...
var isInRole = false;
//
// if Force Role ...
if (forceRole)
{
isInRole = await UserManager.IsInRoleAsync(user, role);
}
else
{
//
// Select User Top Role ...
var userRoles = await GetRoleNamesAsync(
checkIsBanned: false,
userSelectByParam: user.Id,
checkCanLoginPolicies: false
);
isInRole = userRoles.HasRolePermissions(role);
}
//
if (isInRole)
{
selectedUsers.Add(user.Id);
}
}
#endregion
//
var items = await GetUserProfilesAsync(
selectedUsers,
requestedUserSelectByParam,
checkIsBanned: false,
checkCanLoginPolicies: false,
forceCheckRequestedUser: false
);
//
var totalItemsCount = items.Count();
//
// Apply Filter ...
if (!query.Filter.IsNullOrEmpty())
{
//
items = items
.ApplyFilter(query.Filter);
}
int filteredItemsCount = items.Count();
//
// Count Pages ...
var totalPagesCount = query.CountPages(totalItemsCount);
var filteredPagesCount = query.CountPages(filteredItemsCount);
//
// Apply Paging and Sorting ...
if (totalItemsCount > 0 &&
filteredItemsCount > 0)
{
//
// Apply Sorting ...
items = items
.ToList()
.ApplySorting(
query.SortBy,
query.IsAscending
);
//
// Apply Paging ...
items = items
.ToList()
.ApplyPaging(
query.Page,
query.PageSize
);
}
//
// Generate Result Object ...
// Query = query,
var result = new XQueryResult
{
Items = items,
Page = query.Page,
PageSize = query.PageSize,
TotalPages = totalPagesCount,
TotalItems = totalItemsCount,
TotalFilteredPages = filteredPagesCount,
TotalFilteredItems = filteredItemsCount
};
//
return result;
}
///
/// Query Specified User's Profile Images
///
/// a user identifier
/// how to filter results based on XQuery structure
/// an instance of XQueryResult of XProfileImage
public async Task> QueryAvatars(
string userSelectByParam,
XQuery query
)
{
//
// Validation ...
if (query.IsNull())
{
XException.InvalidArgs.Throw();
}
//
// Normalize ...
query = query.NormalizeQuery(DataConfiguration.ToXDataServiceConfig());
//
var xUser = await ValidateUserExistsAndRetrieve(
userSelectByParam,
containDetails: true,
checkCanLoginPolicies: true,
checkIsBanned: true
);
//
var items = query.ContainsDetail ?
DbContext.Avatars
.Include(pf => pf.User)
.AsEnumerable() :
DbContext.Avatars
.AsEnumerable();
items = items
.Where(pfi => pfi.UserId == xUser.Id);
//
var totalItemsCount = items.Count();
//
// Apply Filter ...
if (!query.Filter.IsNullOrEmpty())
{
//
items = items
.ApplyFilter(query.Filter);
}
int filteredItemsCount = items.Count();
//
// Count Pages ...
var totalPagesCount = query.CountPages(totalItemsCount);
var filteredPagesCount = query.CountPages(filteredItemsCount);
//
// Apply Paging and Sorting ...
if (totalItemsCount > 0 &&
filteredItemsCount > 0)
{
//
// Apply Sorting ...
items = items
.ToList()
.ApplySorting(
query.SortBy,
query.IsAscending
);
//
// Apply Paging ...
items = items
.ToList()
.ApplyPaging(
query.Page,
query.PageSize
);
}
//
// Generate Result Object ...
// Query = query,
var result = new XQueryResult
{
Items = items,
Page = query.Page,
PageSize = query.PageSize,
TotalPages = totalPagesCount,
TotalItems = totalItemsCount,
TotalFilteredPages = filteredPagesCount,
TotalFilteredItems = filteredItemsCount
};
//
return result;
}
///
/// Check specific user Confirmed Email or not
///
/// a user identifier
/// a boolean value
public async Task IsConfirmedEmail(
string userSelectByParam
)
{
//
// Validate Args ...
ValidationProvider.NotEmpty(userSelectByParam);
//
var xUser = await ValidateUserExistsAndRetrieve(
userSelectByParam,
containDetails: false,
checkCanLoginPolicies: false,
checkIsBanned: false,
ignoreDisabledUser: true,
forceAdmin: false
);
//
return xUser.EmailConfirmed;
}
///
/// Ceck specific user Confirmed Mobile or not
///
/// a user identifier
/// a boolean value
public async Task IsConfirmedMobile(
string userSelectByParam
)
{
//
// Validate Args ...
ValidationProvider.NotEmpty(userSelectByParam);
//
var xUser = await ValidateUserExistsAndRetrieve(
userSelectByParam,
containDetails: false,
checkCanLoginPolicies: false,
checkIsBanned: false,
ignoreDisabledUser: true,
forceAdmin: false
);
//
return xUser.PhoneNumberConfirmed;
}
#endregion
//
#region Update Actions ...
///
/// Update User Profile (FirstName/LastName/DateOfBirth) ...
///
/// a user identifier
/// requested user's identifier
/// user update info, an instance of XProfileUpdateRequest
/// an instance of XUserProfileDto
public async Task ProfileUpdateAsync(
string userSelectByParam,
string requestedUserSelectByParam,
XProfileUpdateRequest model
)
{
//
// Data Validation ...
ValidationProvider.NotEmpty(
userSelectByParam,
requestedUserSelectByParam);
ValidationProvider.NotNull(model);
//
var xUser = await ValidateUserExistsAndRetrieve(
userSelectByParam,
containDetails: true,
checkCanLoginPolicies: false,
checkIsBanned: false,
ignoreDisabledUser: true,
forceAdmin: false
);
//
var xRequestedUser = await ValidateUserExistsAndRetrieve(
requestedUserSelectByParam,
containDetails: true,
checkCanLoginPolicies: false,
checkIsBanned: false,
ignoreDisabledUser: true,
forceAdmin: false
);
//
await ValidateUserForDangerousAction(xUser, xRequestedUser);
//
// FirstName ...
if (!model.FirstName.IsNullOrEmpty())
{
xUser.FirstName = model.FirstName;
}
//
// Last Name ...
if (!model.LastName.IsNullOrEmpty())
{
xUser.LastName = model.LastName;
}
//
// Date of Birth ...
if (model.DateOfBirth.HasValue)
{
xUser.DateOfBirth = model.DateOfBirth.Value;
}
//
// Bio ...
xUser.Bio = model.Bio;
//
// Cover Image ...
xUser.CoverImage = model.CoverImage;
//
// Open To Search ...
xUser.OpenToSearch = model.OpenToSearch;
//
var updateResult = await UpdateUserAsync(xUser);
if (!updateResult.Succeeded)
{
XException.ActionFailed.Throw();
}
//
var result = await GetUserProfileAsync(userSelectByParam, requestedUserSelectByParam);
return result;
}
///
/// Update User Profile
///
/// a user identifier
/// requested user's identifier
/// user update info, an instance of XProfileUpdateRequest
/// an instance of XUserProfileDto
public async Task FullProfileUpdateAsync(
string userSelectByParam,
string requestedUserSelectByParam,
XProfileUpdateRequest model
)
{
//
// Data Validation ...
ValidationProvider.NotEmpty(
userSelectByParam,
requestedUserSelectByParam);
ValidationProvider.NotNull(model);
//
var xUser = await ValidateUserExistsAndRetrieve(
userSelectByParam,
containDetails: true,
checkCanLoginPolicies: false,
checkIsBanned: false,
ignoreDisabledUser: true,
forceAdmin: false
);
//
var xRequestedUser = await ValidateUserExistsAndRetrieve(
requestedUserSelectByParam,
containDetails: true,
checkCanLoginPolicies: false,
checkIsBanned: false,
ignoreDisabledUser: true,
forceAdmin: false
);
//
await ValidateUserForDangerousAction(xUser, xRequestedUser);
//
#region Fill User with Models Value ...
//
// FirstName ...
xUser.FirstName = !model.FirstName.IsNullOrEmpty() ?
model.FirstName :
xUser.FirstName;
//
// LastName ...
xUser.LastName = !model.LastName.IsNullOrEmpty() ?
model.LastName :
xUser.LastName;
//
// Email ...
xUser.Email = !model.Email.IsNullOrEmpty() ?
model.Email :
xUser.Email;
//
// EmailConfirmed ...
if (model.EmailConfirmed.HasValue)
{
xUser.EmailConfirmed = model.EmailConfirmed.Value;
}
//
// PhoneNumber ...
xUser.PhoneNumber = !model.PhoneNumber.IsNullOrEmpty() ?
model.PhoneNumber :
xUser.PhoneNumber;
//
// PhoneNumberConfirmed ,,,
if (model.PhoneNumberConfirmed.HasValue)
{
xUser.PhoneNumberConfirmed = model.PhoneNumberConfirmed.Value;
}
//
// DateOfBirth ...
if (model.DateOfBirth.HasValue)
{
xUser.DateOfBirth = model.DateOfBirth.Value;
}
//
// CreationDate ...
if (model.CreationDate.HasValue)
{
xUser.CreationDate = model.CreationDate.Value;
}
//
// LastLogin ...
if (model.LastLogin.HasValue)
{
xUser.LastLogin = model.LastLogin.Value;
}
//
// Avatar ...
xUser.Avatar = !model.Avatar.IsNullOrEmpty() ?
model.Avatar :
xUser.Avatar;
//
// Gender ...
if (model.Gender.HasValue)
{
xUser.Gender = model.Gender.Value;
}
//
// IsEnable ...
if (model.IsEnable.HasValue)
{
xUser.IsEnable = model.IsEnable.Value;
}
//
// IsBanned ...
if (model.IsBanned.HasValue)
{
xUser.IsBanned = model.IsBanned.Value;
}
//
// Bio ...
xUser.Bio = model.Bio;
//
// Cover Image ...
xUser.CoverImage = model.CoverImage;
//
// Open To Search ...
xUser.OpenToSearch = model.OpenToSearch;
#endregion
//
var updateResult = await UpdateUserAsync(
xUser,
checkCanLoginPolicies: false,
checkIsBanned: false
);
if (!updateResult.Succeeded)
{
XException.ActionFailed.Throw();
}
//
// Handle Roles ...
//
// Remove User from All Roles ...
if (xUser.Roles.HasChild())
{
//
var roleNames = await GetRoleNamesAsync(
xUser.Id,
checkIsBanned: false,
checkCanLoginPolicies: false
);
//
foreach (var role in roleNames)
{
//
var isRoleExists = await IsRoleExistsAsync(role);
if (isRoleExists)
{
//
var isInRole = await UserManager.IsInRoleAsync(xUser, role);
if (!isInRole)
{
//
var removeRoleResult = await UserManager.RemoveFromRoleAsync(xUser, role);
if (!removeRoleResult.Succeeded)
{
XException.ActionFailed.Throw();
}
}
}
}
}
//
// Check Roles and Add to Exists ...
if (model.Roles.HasChild())
{
//
// Check Exists Roles for Add ...
foreach (var role in model.Roles)
{
//
var isRoleExists = await IsRoleExistsAsync(role);
if (isRoleExists)
{
//
var isInRole = await UserManager.IsInRoleAsync(xUser, role);
if (!isInRole)
{
//
var addToRoleResult = await UserManager.AddToRoleAsync(xUser, role);
if (!addToRoleResult.Succeeded)
{
XException.ActionFailed.Throw();
}
}
}
}
}
//
var result = await GetUserProfileAsync(
userSelectByParam,
requestedUserSelectByParam,
checkCanLoginPolicies: false,
checkIsBanned: false
);
return result;
}
#endregion
//
#region Request For Actions ...
///
/// Request Mobile Confirm
///
/// specify destination language
/// an instance of XDevice
/// a user identifier
/// user's password
/// mobile number which need to confirm
/// an instance of XActionResponse
public async Task RequestConfirmMobile(
string lang,
XDevice device,
string userSelectByParam,
string password,
string mobileNumber = null
)
{
//
// Validate Args ...
await ValidationProvider
.GroupValidationBuilder()
.AddNotEmpty(
lang,
userSelectByParam,
password)
.AddNotNull(device)
.ValidateGroupAsync();
//
await ValidateDeviceForActions(device);
//
// Prepare Request Context ...
var context = new XActionRequestContext
{
Lang = lang,
Device = device,
MobileNumber = mobileNumber
};
//
// Validate and Retrieve User ...
var user = await ValidateUserExistsAndRetrieve(
userSelectByParam,
containDetails: false,
checkCanLoginPolicies: false,
checkIsBanned: false);
//
context.UserName = user.UserName;
//
await ValidateUserAndPassword(
userSelectByParam,
password,
false,
XException.ActionFailed.ToException());
//
ValidationProvider.MobileNumber(user.PhoneNumber);
if (!mobileNumber.IsNullOrEmpty() &&
user.PhoneNumber == mobileNumber &&
user.PhoneNumberConfirmed)
{
XException.MobileInUsed.Throw();
}
//
if (mobileNumber.IsNullOrEmpty())
{
mobileNumber = user.PhoneNumber;
}
//
// Remove All Prevoius Requests ...
await HandleRemoveExistsTokens(user.Id);
//
// Prepare New Token Result ,
// by Requesting an Action ...
var request = await ActionRequest(
lang,
device,
userSelectByParam,
XAction.RequestMobileVerificationCode,
context,
forceRenewToken: true
);
//
Logger.LogInformation($"ActionRequest: {request.ToJSON()}");
//
// Call Confirm Method of Registration ...
var result = await RequestMobileVerificationCode(
lang,
device,
request.Token,
mobileNumber,
checkMobileInUse: false);
//
return result;
}
///
/// Request Email Confirma
///
/// specify destination language
/// an instance of XDevice
/// a user identifier
/// user's password
/// email address which need to confirm
/// an instance of XActionResponse
public async Task RequestConfirmEmail(
string lang,
XDevice device,
string userSelectByParam,
string password,
string emailAddress = null
)
{
//
// Validate Args ...
await ValidationProvider
.GroupValidationBuilder()
.AddNotEmpty(
lang,
userSelectByParam,
password)
.AddNotNull(device)
.ValidateGroupAsync();
//
await ValidateDeviceForActions(device);
//
// Prepare Request Context ...
var context = new XActionRequestContext
{
Lang = lang,
Device = device,
Email = emailAddress
};
//
// Validate and Retrieve User ...
var user = await ValidateUserExistsAndRetrieve(
userSelectByParam,
containDetails: false,
checkCanLoginPolicies: false,
checkIsBanned: false);
//
context.UserName = user.UserName;
//
// Remove All Prevoius Requests ...
await HandleRemoveExistsTokens(user.Id);
//
await ValidateUserAndPassword(
userSelectByParam,
password,
false,
XException.ActionFailed.ToException());
//
ValidationProvider.EmailAddress(user.Email);
if (!emailAddress.IsNullOrEmpty() &&
user.Email == emailAddress &&
user.EmailConfirmed)
{
XException.EmailInUsed.Throw();
}
//
if (emailAddress.IsNullOrEmpty())
{
emailAddress = user.Email;
context.Email = user.Email;
}
//
// Prepare New Token Result ,
// by Requesting an Action ...
var request = await ActionRequest(
lang,
device,
userSelectByParam,
XAction.RequestEmailVerificationCode,
context,
forceRenewToken: true
);
//
// Call Confirm Method of Registration ...
var result = await RequestEmailVerificationCode(
lang,
device,
request.Token,
emailAddress,
checkEmailInUse: false);
//
return result;
}
///
/// Request Reset Password
///
/// specify destination language
/// an instance of XDevice
/// a user identifier
/// redirection url
/// an instance of XActionResponse
public async Task RequestResetPassword(
string lang,
XDevice device,
string userSelectByParam,
string returnUrl
)
{
//
// Validate Args ...
await ValidationProvider
.GroupValidationBuilder()
.AddNotEmpty(
lang,
userSelectByParam,
returnUrl)
.AddNotNull(device)
.AddUrl(returnUrl)
.ValidateGroupAsync();
//
await ValidateDeviceForActions(device);
//
// Validate and Retrieve User ...
var user = await ValidateUserExistsAndRetrieve(
userSelectByParam,
containDetails: false,
checkCanLoginPolicies: true,
checkIsBanned: true);
//
// Prepare Request Context ...
var context = new XActionRequestContext
{
Lang = lang,
Device = device,
Email = user.Email,
UserName = user.UserName
};
//
// Remove All Prevoius Requests ...
await HandleCleanUserTokens(user);
//
// Prepare New Token Result ,
// by Requesting an Action ...
var result = await ActionRequest(
lang,
device,
user.Email,
XAction.RequestResetPassword,
context
);
//
// Prepare Message ...
var xMessage = GetResetPasswordMessage(
lang,
user.Email,
result.Token,
returnUrl);
//
try
{
await MessageProvider.SendMailAsync(xMessage);
}
catch { }
//
return result;
}
///
/// Request Registration Confrirm
///
/// specify destination language
/// an instance of XDevice
/// a user identifier
/// user's password
/// redirection url
///
public async Task RequestConfirmRegistration(
string lang,
XDevice device,
string userSelectByParam,
string password,
string returnUrl
)
{
//
// Validate Args ...
await ValidationProvider
.GroupValidationBuilder()
.AddNotEmpty(
lang,
userSelectByParam,
password,
returnUrl)
.AddNotNull(device)
.AddUrl(returnUrl)
.ValidateGroupAsync();
//
// Validate user and Retrieve it ...
var user = await ValidateUserExistsAndRetrieve(
userSelectByParam,
containDetails: false,
checkCanLoginPolicies: false,
checkIsBanned: true,
ignoreDisabledUser: true);
//
// Prepare Request Context ...
var context = new XActionRequestContext
{
Lang = lang,
Device = device,
Email = user.Email
};
//
await ValidateUserAndPassword(
userSelectByParam,
password,
false,
XException.ActionFailed.ToException());
//
// Remove All Prevoius Requests ...
await HandleRemoveExistsTokens(user.Id);
//
// Prepare New Token Result ,
// by Requesting an Action ...
var result = await ActionRequest(
lang,
device,
user.Email,
XAction.Finish,
context
);
//
// Prepare XMessage Instance ...
var xMessage = GetRegistrationConfirmMessage(
lang,
user.Email,
result.Token,
returnUrl);
//
// Send Message ...
try
{
await MessageProvider.SendMailAsync(xMessage);
}
catch { }
}
#endregion
//
#region Password Actions ...
///
/// Change Password
///
/// specify destination language
/// an instance of XDevice
/// a user identifier
/// user's password
/// user's new password
/// redirection url
///
public async Task ChangePassword(
string lang,
XDevice device,
string userSelectByParam,
string password,
string newPassword,
string returnUrl
)
{
//
// Validate Args ...
await ValidationProvider
.GroupValidationBuilder()
.AddNotEmpty(
lang,
userSelectByParam,
password,
newPassword,
returnUrl)
.AddNotNull(device)
.ValidateGroupAsync();
//
// Password Unique ...
if (password == newPassword)
{
XException.PasswordsSame.Throw();
}
//
// Validate and Retrieve User ...
var user = await ValidateUserExistsAndRetrieve(
userSelectByParam,
containDetails: false,
checkCanLoginPolicies: true,
checkIsBanned: true);
//
await ValidateUserAndPassword(
userSelectByParam,
password);
//
// Check Password Policies ...
await ValidatePasswordPolicies(user, newPassword);
//
// Clean All User Tokens ...
await HandleCleanUserTokens(user);
//
// Try to Change User Password ...
var passwordResetResult = await UserManager
.ChangePasswordAsync(
user,
password,
newPassword);
//
// Check Result ...
if (!passwordResetResult.Succeeded)
{
XException.ActionFailed.Throw();
}
//
// Prepare Message ...
var xMessage = GetPasswordChangedMessage(
lang,
user.Email,
returnUrl,
throwException: false
);
//
// Send Message ...
try
{
await MessageProvider.SendMailAsync(xMessage);
}
catch { }
}
///
/// Reset User Password
///
/// specify destination language
/// an instance of XDevice
/// a token which approved user action
/// user's new password
/// redirection url
///
public async Task ResetPassword(
string lang,
XDevice device,
string actionToken,
string newPassword,
string returnUrl
)
{
//
// Validate Args ...
await ValidationProvider
.GroupValidationBuilder()
.AddNotEmpty(
lang,
actionToken,
newPassword,
returnUrl)
.AddNotNull(device)
.ValidateGroupAsync();
//
// Get Related Token to Registration Hash and Validate it,
// then Parse XActionRequest Instance from Token ...
var request = await ValidateAndParseActionHash(actionToken);
//
// Get User Identifier ...
var userSelectByParam = GetUserSelectByParam(request);
//
// Validate and Retrieve User ...
var user = await ValidateUserExistsAndRetrieve(
userSelectByParam,
containDetails: false,
checkCanLoginPolicies: true,
checkIsBanned: true);
//
// Check Password Policies ...
await ValidatePasswordPolicies(user, newPassword);
//
// Clean All User Tokens ...
await HandleCleanUserTokens(user);
//
// Try to Remove User Password ...
var removePasswordResult = await UserManager.RemovePasswordAsync(user);
if (!removePasswordResult.Succeeded)
{
XException.ActionFailed.Throw();
}
//
// try to Add New Password ...
var passwordResetResult = await UserManager.AddPasswordAsync(user, newPassword);
if (!passwordResetResult.Succeeded)
{
XException.ActionFailed.Throw();
}
//
// Prepare Message ...
var xMessage = GetPasswordChangedMessage(
lang,
user.Email,
returnUrl);
//
// Send Message ...
try
{
await MessageProvider.SendMailAsync(xMessage);
}
catch { }
}
#endregion
//
#region Profile Image Actions ...
///
/// Add Profile Image to a User
///
/// a user identifier
/// an specific File to upload, IFormFile
/// an instance of XUserProfileDto
public async Task AddAvatar(
string userSelectByParam,
IFormFile file
)
{
//
var xUser = await ValidateUserExistsAndRetrieve(
userSelectByParam,
containDetails: true,
checkCanLoginPolicies: false,
checkIsBanned: false,
ignoreDisabledUser: true,
exception: XException.NotFound.ToException()
);
//
// Handle Saving File and Attach it to User ...
var saveResult = await StorageProvider.HandleProfileImageSave(file);
//
var xProfileImage = new XProfileImage
{
UserId = xUser.Id,
Name = saveResult.FileName,
Path = saveResult.FilePath,
Thumb = saveResult.Thmbnail,
ThumbPath = saveResult.ThmbnailPath,
CreationDate = DateTime.UtcNow
};
//
xUser.Avatars.Add(xProfileImage);
var updateResult = await UpdateUserAsync(
xUser,
checkCanLoginPolicies: false,
checkIsBanned: false
);
//
if (!updateResult.Succeeded)
{
XException.ActionFailed.Throw();
}
//
xUser.Avatar = xProfileImage.ThumbPath;
updateResult = await UpdateUserAsync(
xUser,
checkCanLoginPolicies: false,
checkIsBanned: false
);
//
if (!updateResult.Succeeded)
{
XException.ActionFailed.Throw();
}
//
var result = await GetUserProfileAsync(userSelectByParam, userSelectByParam);
return result;
}
///
/// Add a Collection of Profile Images to a User
///
/// a user identifier
/// a collection of Files to upload, IFormFileCollection
/// an instance of XUserProfileDto
public async Task AddAvatars(
string userSelectByParam,
IFormFileCollection files
)
{
//
var xUser = await ValidateUserExistsAndRetrieve(
userSelectByParam,
containDetails: true,
checkCanLoginPolicies: false,
checkIsBanned: false,
ignoreDisabledUser: true,
exception: XException.NotFound.ToException()
);
//
foreach (var file in files)
{
//
// Handle Saving File and Attach it to User ...
var saveResult = await StorageProvider.HandleProfileImageSave(file);
//
var xProfileImage = new XProfileImage
{
UserId = xUser.Id,
Name = saveResult.FileName,
Path = saveResult.FilePath,
Thumb = saveResult.Thmbnail,
ThumbPath = saveResult.ThmbnailPath,
CreationDate = DateTime.UtcNow
};
//
xUser.Avatars.Add(xProfileImage);
}
//
var updateResult = await UpdateUserAsync(
xUser,
checkCanLoginPolicies: false,
checkIsBanned: false
);
//
if (!updateResult.Succeeded)
{
XException.ActionFailed.Throw();
}
//
var result = await GetUserProfileAsync(userSelectByParam, userSelectByParam);
return result;
}
///
/// Set Specific Profie Image as Current Profile Image
///
/// a user identifier
/// an integer which reperesent AvatarId to set as current Avatar
/// an instance of XUserProfileDto
public async Task SetAvatar(
string userSelectByParam,
int id
)
{
//
ValidationProvider.NotEmpty(userSelectByParam);
//
var xUser = await ValidateUserExistsAndRetrieve(
userSelectByParam,
containDetails: true,
checkCanLoginPolicies: false,
checkIsBanned: false,
ignoreDisabledUser: true,
exception: XException.NotFound.ToException()
);
//
var xProfileImage = xUser.Avatars.FirstOrDefault(pf => pf.Id == id);
if (xProfileImage.IsNull())
{
XException.NotFound.Throw();
}
//
xUser.Avatar = xProfileImage.ThumbPath;
var updateResult = await UpdateUserAsync(
xUser,
checkCanLoginPolicies: false,
checkIsBanned: false
);
//
if (!updateResult.Succeeded)
{
XException.ActionFailed.Throw();
}
//
var result = await GetUserProfileAsync(userSelectByParam, userSelectByParam);
return result;
}
///
/// Remove a Collection of User's Profile Images
///
/// a user identifier
/// a comma seperated list of avatarIds to remove
/// an instance of XUserProfileDto
public async Task RemoveAvatar(
string userSelectByParam,
ICollection ids
)
{
//
ValidationProvider.NotEmpty(userSelectByParam);
//
var xUser = await ValidateUserExistsAndRetrieve(
userSelectByParam,
containDetails: true,
checkCanLoginPolicies: false,
checkIsBanned: false,
ignoreDisabledUser: true,
exception: XException.NotFound.ToException()
);
//
var xProfileImages = xUser.Avatars
.Where(pf => ids.Contains(pf.Id));
if (xProfileImages.HasChild())
{
//
xUser.Avatars = xUser.Avatars
.Except(xProfileImages)
.ToList();
//
// Creat a List of Physical Files to Remove ...
var xFilePathsForRemove = xProfileImages.Select(pf => pf.Thumb).ToList();
xFilePathsForRemove.AddRange(xProfileImages.Select(pf => pf.Name));
//
StorageProvider.DeleteFiles(
xFilePathsForRemove,
forceFileExists: false);
//
var isCurrentProfileImage = xProfileImages.Any(pfi => pfi.ThumbPath == xUser.Avatar);
if (isCurrentProfileImage)
{
xUser.Avatar = "";
}
//
await UpdateUserAsync(xUser);
}
//
var result = await GetUserProfileAsync(userSelectByParam, userSelectByParam);
return result;
}
#endregion
//
#region Confirmations ...
///
/// Confirm Registration
///
/// specify destination language
/// an instance of XDevice
/// a token which approved user action
/// redirection url
///
public async Task ConfirmRegistration(
string lang,
XDevice device,
string actionToken,
string returnUrl
)
{
//
// Validate Args ...
await ValidationProvider
.GroupValidationBuilder()
.AddNotEmpty(
lang,
actionToken,
returnUrl)
.AddNotNull(device)
.ValidateGroupAsync();
//
// Check Device Validation ...
await ValidateDeviceForActions(device);
//
// Get Related Token to Registration Hash and Validate it,
// then Parse XActionRequest Instance from Token ...
var request = await ValidateAndParseActionHash(actionToken);
if (request.Action != XAction.Finish)
{
XException.ActionFailed.Throw();
}
//
// Extract UserSelectByParam from XActionRequest ...
var userSelectByParam = GetUserSelectByParam(
request,
forceNotNull: true);
//
// Validate user and Retrieve it ...
var user = await ValidateUserExistsAndRetrieve(
userSelectByParam,
containDetails: false,
checkCanLoginPolicies: false,
ignoreDisabledUser: true,
checkIsBanned: true);
//
// Make User Enabled ...
var xMessage = GetRegistrationFinishedMessage(
lang,
user.Email,
returnUrl);
//
user.IsEnable = true;
user.EmailConfirmed = true;
//
await UpdateUserAsync(
user,
checkCanLoginPolicies: false,
checkIsBanned: false
);
//
// Remove Token ...
await RemoveTokenByHash(actionToken);
//
// Remove All Prevoius Requests ...
await HandleRemoveExistsTokens(user.Id);
//
await RemoveVerificationCodeRequestByDevice(device);
//
// Send Mail ...
try
{
await MessageProvider.SendMailAsync(xMessage);
}
catch { }
}
///
/// Confirm Mobile Number
///
/// specify destination language
/// an instance of XDevice
/// a token which approved user action
/// recieved verification code
/// an instance of XActionResponse
public async Task ConfirmMobileNumber(
string lang,
XDevice device,
string actionToken,
string verificationCode
)
{
//
// Validate Args ...
await ValidationProvider
.GroupValidationBuilder()
.AddNotEmpty(lang, actionToken, verificationCode)
.AddNotNull(device)
.ValidateGroupAsync();
//
// Check Device Validation ...
await ValidateDeviceForActions(device);
//
// Get Related Token to Registration Hash and Validate it,
// then Parse XActionRequest Instance from Token ...
var request = await ValidateAndParseActionHash(actionToken);
ValidationProvider.MobileNumber(request.Context.MobileNumber);
//
// Validate two Device Must Same ...
ValidateRequestAndGiveDevices(device, request.Context.Device);
//
// Check XActionRequest Action Must be Request Mobile Validation ...
if (request.Action != XAction.RequestMobileVerificationCode)
{
XException.InvalidData.Throw();
}
//
// Extract UserSelectByParam from XActionRequest ...
var userSelectByParam = GetUserSelectByParam(request);
//
// since device must Requested before,
// Retrieve XVerification instance by Verification Code from Db
// and Validate it ...
XVerificationRequest xVerificationRequest = await ValidateAndRetrieveVerificationRequest(verificationCode);
//
// Check User Added To Db or Not ...
// var isUserExists = await IsUserExistsAsync(userSelectByParam);
var isAddedUser = !request.Context.UserId.IsNullOrEmpty();
if (isAddedUser)
{
//
// Validate User Exists and Retireve User Object ...
var user = await ValidateUserExistsAndRetrieve(
userSelectByParam,
containDetails: false,
checkCanLoginPolicies: false,
checkIsBanned: false);
//
// Update Exists User's Mobile Confirmation ...
user.PhoneNumberConfirmed = true;
//
// Save Changes to Db ...
await UpdateUserAsync(user, checkCanLoginPolicies: false, checkIsBanned: false);
//
request.Context.UserId = user.Id;
}
//
// Update Request Context MobileNumber Verification Code
// and it's Confirmation Status ...
request.Context.MobileVerificationCode = verificationCode;
request.Context.MobileVerified = true;
//
// Prepare New Token Result ,
// by Requesting an Action ...
var result = await ActionRequest(
lang,
device,
userSelectByParam,
XAction.ConfirmMobileNumber,
request.Context,
forceCheckUserExists: isAddedUser
);
//
// Remove Previous Token ...
await RemoveTokenByHash(actionToken);
try
{
//
// Remove XVerificationRequest instance from Db ...
await RemoveVerificationRequest(verificationCode);
}
catch { }
//
// Return Result ...
return result;
}
///
/// Confirm Email Address
///
/// specify destination language
/// an instance of XDevice
/// a token which approved user action
/// recieved verification code
/// an instance of XActionResponse
public async Task ConfirmEmailAddress(
string lang,
XDevice device,
string actionToken,
string verificationCode
)
{
//
// Validate Args ...
await ValidationProvider
.GroupValidationBuilder()
.AddNotEmpty(lang, actionToken, verificationCode)
.AddNotNull(device)
.ValidateGroupAsync();
//
// Check Device Validation ...
await ValidateDeviceForActions(device);
//
// Get Related Token to Registration Hash and Validate it,
// then Parse XActionRequest Instance from Token ...
var request = await ValidateAndParseActionHash(actionToken);
ValidationProvider.EmailAddress(request.Context.Email);
//
// Validate two Device Must Same ...
ValidateRequestAndGiveDevices(device, request.Context.Device);
//
// Check XActionRequest Action Must be Request Mobile Validation ...
if (request.Action != XAction.RequestEmailVerificationCode)
{
XException.InvalidData.Throw();
}
//
// Extract UserSelectByParam from XActionRequest ...
var userSelectByParam = GetUserSelectByParam(request);
//
// since device must Requested before,
// Retrieve XVerification instance by Verification Code from Db
// and Validate it ...
XVerificationRequest xVerificationRequest = await ValidateAndRetrieveVerificationRequest(verificationCode);
//
// Check User Added To Db or Not ...
var isAddedUser = !request.Context.UserId.IsNullOrEmpty();
if (isAddedUser)
{
//
// Validate User Exists and Retireve User Object ...
var user = await ValidateUserExistsAndRetrieve(
userSelectByParam,
containDetails: false,
checkCanLoginPolicies: false,
checkIsBanned: false);
//
// Update Exists User's Email Confirmation ...
user.EmailConfirmed = true;
//
// Save Changes to Db ...
await UpdateUserAsync(user, checkCanLoginPolicies: false, checkIsBanned: false);
//
request.Context.UserId = user.Id;
}
//
// Update Request Context Email Address Verification Code
// and it's Confirmation Status ...
request.Context.EmailVerificationCode = verificationCode;
request.Context.EmailVerified = true;
//
// Prepare New Token Result ,
// by Requesting an Action ...
var result = await ActionRequest(
lang,
device,
userSelectByParam,
XAction.ConfirmEmailAddress,
request.Context,
forceCheckUserExists: isAddedUser
);
//
// Remove Previous Token ...
await RemoveTokenByHash(actionToken);
//
// Remove XVerificationRequest instance from Db ...
await RemoveVerificationRequest(verificationCode);
//
// Return Result ...
return result;
}
#endregion
}
}