using System; using System.Collections.Generic; using System.Globalization; using System.Linq; using System.Security.Principal; using System.Threading.Tasks; using BO.AppServer.Business.Mapper; using BO.AppServer.Business.Services.Base; using BO.AppServer.Data.Entity; using BO.AppServer.Metadata.Dto; using BO.AppServer.Metadata.Enums; using Microsoft.AspNetCore.Identity; using Microsoft.Extensions.Logging; using Quadarax.Foundation.Core.Business.Security; using Quadarax.Foundation.Core.Data; using Quadarax.Foundation.Core.Data.Interface; using Quadarax.Foundation.Core.Data.Interface.Entity.Dto; using Quadarax.Foundation.Core.Exceptions; namespace BO.AppServer.Business.Services { public class UserService : UserContextService { #region *** Private fields *** private UserManager _manUser; private RoleManager _manRole; protected WorkspaceRepo _repoWorkspace; #endregion #region *** Constructor & DI *** public UserService( WorkspaceRepo repoWorkspace, AccessService srvAccessService, RoleManager roleManager, UserRepo repoUser, UserManager userManager, IPrincipal currentPrincipal, ILoggerFactory logger) : base(repoUser, userManager, currentPrincipal, logger) { _manUser = userManager ?? throw new ArgumentNullException(nameof(userManager)); _manRole = roleManager ?? throw new ArgumentNullException(nameof(roleManager)); _repoWorkspace = repoWorkspace ?? throw new ArgumentNullException(nameof(repoWorkspace)); } #endregion #region *** Public Operations *** public async Task> GetAllUsersAsync(UserScopeEnums scope, PagingDto paging) { List users = null; switch (scope) { case UserScopeEnums.All: users = _repoUser.Query(paging).ToList(); break; case UserScopeEnums.Locked: users = _repoUser.Query(paging).Where(x=>x.IsEnabled==false).ToList(); break; case UserScopeEnums.System: users = _repoUser.Query(paging).Where(x=>x.IsSystem==true).ToList(); break; } return new ResultsValueDto(users.MapList()); } public async Task> GetUserAsync(long userId) { var user = _repoUser.Get(new []{userId}).FirstOrDefault(); return new ResultValueDto(user.Map()); } public async Task> CreateUserAsync(UserCDto newUser) { //TODO: role validation return await CreateUserAsync(newUser.Name, newUser.Password,newUser.Email,newUser.LangLcid,newUser.Roles.Select(Enum.Parse).ToArray()); } public async Task> CreateUserAsync(string userName,string userPassword, string userEmail, int prefferedLCID, RoleEnum[] roles) { try { // Validations var exists = await ExistsUserByNameAsync(userName); if (exists.Value) throw new CodeException(1100, $"Cannot create user '{userName}', user name or email already exists."); // Create Identity User var idtUser = await _manUser.FindByNameAsync(userName); if (idtUser == null) { idtUser = new IdentityUser(userName) { NormalizedUserName = userName.ToLower(CultureInfo.InvariantCulture), Email = userEmail, NormalizedEmail = userEmail.ToLower(CultureInfo.InvariantCulture), LockoutEnabled = true, PasswordHash = PasswordHelper.HashPassword(userPassword) }; await _manUser.CreateAsync(idtUser); Log.Log(LogLevel.Debug, $"User '{userName}' created in IF."); } else Log.Log(LogLevel.Debug, $"User '{userName}' already exists in IF."); // Append roles var currentRoles = await _manUser.GetRolesAsync(idtUser); await _manUser.RemoveFromRolesAsync(idtUser, currentRoles.ToArray()); foreach (var role in roles) { await _manUser.AddToRoleAsync(idtUser, role.ToString().ToUpper()); Log.Log(LogLevel.Debug, $"User '{userName}' add to role '{role}' in IF."); } // Create BO user var user = _repoUser.GetByIfReference(idtUser.Id); if (user == null) { user = _repoUser.New(); user.Ifreference = idtUser.Id; user.Name = userName; user.LangLcid = prefferedLCID; user.Created = DateTime.Now; user.IsEnabled = false; user.LangLcid = prefferedLCID; user.IsSystem = roles.Contains(RoleEnum.System); user.IsEnabled = true; _repoUser.Set(user); Log.Log(LogLevel.Debug, $"User '{userName}' [{user.Id}] created as enabled={user.IsEnabled} in BO."); user = _repoUser.Get(user.Id); } else { user.Name = idtUser.UserName; user.LangLcid = prefferedLCID; user.Modified = DateTime.Now; user.IsSystem = roles.Contains(RoleEnum.System); _repoUser.Set(user); Log.Log(LogLevel.Debug, $"User '{userName}' [{user.Id}] was recovered in BO."); } _repoUser.Commit(); return new ResultValueDto(user.Map()); } catch (Exception e) { return new ResultValueDto(e); } } public async Task ExistsUserByNameAsync(string userName) { var user = await _manUser.FindByNameAsync(userName); if (user == null) return new ResultBoolDto(false); var exists = _repoUser.Query(new Paging()).Any(x => x.Name.ToLower() == userName.ToLower(CultureInfo.InvariantCulture) && x.Ifreference == user.Id); return new ResultBoolDto(exists); } public async Task EnusreUserRolesAsync(string userName, RoleEnum[] roles) { var idtUser = await _manUser.FindByNameAsync(userName); if (idtUser == null) return new ResultBoolDto(false); var currentRoles = await _manUser.GetRolesAsync(idtUser); await _manUser.RemoveFromRolesAsync(idtUser, currentRoles.ToArray()); foreach (var role in roles) { await _manUser.AddToRoleAsync(idtUser, role.ToString().ToUpper()); Log.Log(LogLevel.Debug, $"User '{userName}' add to role '{role}' in IF."); } return new ResultBoolDto(true); } public ResultBoolDto ExistsUserByIfReference(string ifReference) { var exists = _manUser.FindByIdAsync(ifReference).Result; return new ResultBoolDto(exists!=null); } public async Task EnsureRolesAsync() { var roles = Enum.GetNames(typeof(RoleEnum)); foreach (var roleName in roles) { if (!await _manRole.RoleExistsAsync(roleName)) { var role = new IdentityRole(roleName); role.NormalizedName = roleName.ToUpper(CultureInfo.InvariantCulture); await _manRole.CreateAsync(role); Log.Log(LogLevel.Information, $"Role '{roleName}' [{role.Id}] created."); } } } /* public ResultValueDto SetUser(long userId, UserUDto user) { } public ResultValueDto SetUserLock(long userId, bool flagEnabledDisabled) { } public ResultValueDto SetUserLogAudit(long userId) { } */ #endregion } }