using System; using System.Collections.Generic; using System.Globalization; using System.IO; using System.Linq; using System.Net; using System.Threading.Tasks; using Microsoft.AspNetCore.Identity; using Microsoft.Extensions.Caching.Memory; using Microsoft.Extensions.Localization; using Oqtane.Enums; using Oqtane.Infrastructure; using Oqtane.Models; using Oqtane.Repository; using Oqtane.Security; using Oqtane.Shared; namespace Oqtane.Managers { public class UserManager : IUserManager { private readonly IUserRepository _users; private readonly IRoleRepository _roles; private readonly IUserRoleRepository _userRoles; private readonly UserManager _identityUserManager; private readonly SignInManager _identitySignInManager; private readonly ITenantManager _tenantManager; private readonly INotificationRepository _notifications; private readonly IFolderRepository _folders; private readonly IProfileRepository _profiles; private readonly ISettingRepository _settings; private readonly ISiteRepository _sites; private readonly ISyncManager _syncManager; private readonly ILogManager _logger; private readonly IMemoryCache _cache; private readonly IStringLocalizer _localizer; public UserManager(IUserRepository users, IRoleRepository roles, IUserRoleRepository userRoles, UserManager identityUserManager, SignInManager identitySignInManager, ITenantManager tenantManager, INotificationRepository notifications, IFolderRepository folders, IProfileRepository profiles, ISettingRepository settings, ISiteRepository sites, ISyncManager syncManager, ILogManager logger, IMemoryCache cache, IStringLocalizer localizer) { _users = users; _roles = roles; _userRoles = userRoles; _identityUserManager = identityUserManager; _identitySignInManager = identitySignInManager; _tenantManager = tenantManager; _notifications = notifications; _folders = folders; _profiles = profiles; _settings = settings; _sites = sites; _syncManager = syncManager; _logger = logger; _cache = cache; _localizer = localizer; } public User GetUser(int userid, int siteid) { var alias = _tenantManager.GetAlias(); return _cache.GetOrCreate($"user:{userid}:{alias.SiteKey}", entry => { entry.SlidingExpiration = TimeSpan.FromMinutes(30); User user = _users.GetUser(userid); if (user != null) { user.SiteId = siteid; user.Roles = GetUserRoles(user.UserId, user.SiteId); user.SecurityStamp = _identityUserManager.FindByNameAsync(user.Username).GetAwaiter().GetResult()?.SecurityStamp; user.Settings = _settings.GetSettings(EntityNames.User, user.UserId) .ToDictionary(setting => setting.SettingName, setting => setting.SettingValue); } return user; }); } public User GetUser(string username, int siteid) { User user = _users.GetUser(username); if (user != null) { user = GetUser(user.UserId, siteid); } return user; } public User GetUser(string username, string email, int siteid) { User user = _users.GetUser(username, email); if (user != null) { user = GetUser(user.UserId, siteid); } return user; } private string GetUserRoles(int userId, int siteId) { string roles = ""; List userroles = _userRoles.GetUserRoles(userId, siteId).ToList(); foreach (UserRole userrole in userroles) { if (Utilities.IsEffectiveAndNotExpired(userrole.EffectiveDate, userrole.ExpiryDate)) { roles += userrole.Role.Name + ";"; if (userrole.Role.Name == RoleNames.Host && !userroles.Any(item => item.Role.Name == RoleNames.Admin)) { roles += RoleNames.Admin + ";"; } if (userrole.Role.Name == RoleNames.Host && !userroles.Any(item => item.Role.Name == RoleNames.Registered)) { roles += RoleNames.Registered + ";"; } } } if (roles != "") roles = ";" + roles; return roles; } public async Task AddUser(User user) { User User = null; var alias = _tenantManager.GetAlias(); bool succeeded = false; string errors = ""; IdentityUser identityuser = await _identityUserManager.FindByNameAsync(user.Username); if (identityuser == null) { if (string.IsNullOrEmpty(user.Password)) { // generate password based on random date and punctuation ie. Jan-23-1981+14:43:12! Random rnd = new Random(); var date = DateTime.UtcNow.AddDays(-rnd.Next(50 * 365)).AddHours(rnd.Next(0, 24)).AddMinutes(rnd.Next(0, 60)).AddSeconds(rnd.Next(0, 60)); user.Password = date.ToString("MMM-dd-yyyy+HH:mm:ss", CultureInfo.InvariantCulture) + (char)rnd.Next(33, 47); } identityuser = new IdentityUser(); identityuser.UserName = user.Username; identityuser.Email = user.Email; identityuser.EmailConfirmed = user.EmailConfirmed; var result = await _identityUserManager.CreateAsync(identityuser, user.Password); succeeded = result.Succeeded; if (!succeeded) { errors = string.Join(", ", result.Errors.Select(e => e.Description)); } } else { succeeded = true; if (!user.IsAuthenticated) { var result = await _identitySignInManager.CheckPasswordSignInAsync(identityuser, user.Password, false); succeeded = result.Succeeded; if (!succeeded) { errors = "Password Not Valid For User"; } user.EmailConfirmed = succeeded; } } if (succeeded) { user.DisplayName = (user.DisplayName == null) ? user.Username : user.DisplayName; user.LastLoginOn = null; user.LastIPAddress = ""; User = _users.AddUser(user); _syncManager.AddSyncEvent(alias, EntityNames.User, User.UserId, SyncEventActions.Create); } else { _logger.Log(user.SiteId, LogLevel.Error, this, LogFunction.Create, "Unable To Add User {Username} - {Errors}", user.Username, errors); } if (User != null) { string siteName = _sites.GetSite(user.SiteId).Name; if (!user.EmailConfirmed) { string token = await _identityUserManager.GenerateEmailConfirmationTokenAsync(identityuser); string url = alias.Protocol + alias.Name + "/login?name=" + user.Username + "&token=" + WebUtility.UrlEncode(token); string subject = _localizer["VerificationEmailSubject"]; subject = subject.Replace("[SiteName]", siteName); string body = _localizer["VerificationEmailBody"].Value; body = body.Replace("[UserDisplayName]", user.DisplayName); body = body.Replace("[URL]", url); body = body.Replace("[SiteName]", siteName); var notification = new Notification(alias.SiteId, User, subject, body); _notifications.AddNotification(notification); } else { if (!user.SuppressNotification) { string url = alias.Protocol + alias.Name + "/login"; string subject = _localizer["NoVerificationEmailSubject"]; subject = subject.Replace("[SiteName]", siteName); string body = _localizer["NoVerificationEmailBody"].Value; body = body.Replace("[UserDisplayName]", user.DisplayName); body = body.Replace("[URL]", url); body = body.Replace("[SiteName]", siteName); body = body.Replace("[Username]", user.Username); var notification = new Notification(alias.SiteId, User, subject, body); _notifications.AddNotification(notification); } } User.Password = ""; // remove sensitive information _logger.Log(user.SiteId, LogLevel.Information, this, LogFunction.Create, "User Added {User}", User); } else { user.Password = ""; // remove sensitive information _logger.Log(user.SiteId, LogLevel.Error, this, LogFunction.Create, "Unable To Add User {User}", user); } return User; } public async Task UpdateUser(User user) { IdentityUser identityuser = await _identityUserManager.FindByNameAsync(user.Username); if (identityuser != null) { var alias = _tenantManager.GetAlias(); if (!string.IsNullOrEmpty(user.Password)) { var validator = new PasswordValidator(); var result = await validator.ValidateAsync(_identityUserManager, null, user.Password); if (result.Succeeded) { identityuser.PasswordHash = _identityUserManager.PasswordHasher.HashPassword(identityuser, user.Password); await _identityUserManager.UpdateAsync(identityuser); await _identityUserManager.UpdateSecurityStampAsync(identityuser); // will force user to sign in again } else { _logger.Log(user.SiteId, LogLevel.Error, this, LogFunction.Update, "Unable To Update User {Username}. Password Does Not Meet Complexity Requirements.", user.Username); return null; } } if (user.Email != identityuser.Email) { identityuser.Email = user.Email; await _identityUserManager.UpdateAsync(identityuser); // security stamp not updated // if email address changed and it is not confirmed, verification is required for new email address if (!user.EmailConfirmed) { string token = await _identityUserManager.GenerateEmailConfirmationTokenAsync(identityuser); string url = alias.Protocol + alias.Name + "/login?name=" + user.Username + "&token=" + WebUtility.UrlEncode(token); string body = "Dear " + user.DisplayName + ",\n\nIn Order To Verify The Email Address Associated To Your User Account Please Click The Link Displayed Below:\n\n" + url + "\n\nThank You!"; var notification = new Notification(user.SiteId, user, "User Account Verification", body); _notifications.AddNotification(notification); } } if (user.EmailConfirmed) { var emailConfirmationToken = await _identityUserManager.GenerateEmailConfirmationTokenAsync(identityuser); await _identityUserManager.ConfirmEmailAsync(identityuser, emailConfirmationToken); } user = _users.UpdateUser(user); _syncManager.AddSyncEvent(_tenantManager.GetAlias(), EntityNames.User, user.UserId, SyncEventActions.Update); _syncManager.AddSyncEvent(_tenantManager.GetAlias(), EntityNames.User, user.UserId, SyncEventActions.Reload); user.Password = ""; // remove sensitive information _logger.Log(LogLevel.Information, this, LogFunction.Update, "User Updated {User}", user); } else { _logger.Log(user.SiteId, LogLevel.Error, this, LogFunction.Update, "Unable To Update User {Username}. User Does Not Exist.", user.Username); user = null; } return user; } public async Task DeleteUser(int userid, int siteid) { // remove user roles for site foreach (UserRole userrole in _userRoles.GetUserRoles(userid, siteid).ToList()) { _userRoles.DeleteUserRole(userrole.UserRoleId); _logger.Log(LogLevel.Information, this, LogFunction.Delete, "User Role Deleted {UserRole}", userrole); } // remove user folder for site var folder = _folders.GetFolder(siteid, $"Users/{userid}/"); if (folder != null) { if (Directory.Exists(_folders.GetFolderPath(folder))) { Directory.Delete(_folders.GetFolderPath(folder), true); } _folders.DeleteFolder(folder.FolderId); _logger.Log(LogLevel.Information, this, LogFunction.Delete, "User Folder Deleted {Folder}", folder); } // delete user if they are not a member of any other sites if (!_userRoles.GetUserRoles(userid, -1).Any()) { // get identity user var user = _users.GetUser(userid, false); IdentityUser identityuser = await _identityUserManager.FindByNameAsync(user.Username); if (identityuser != null) { // delete identity user var result = await _identityUserManager.DeleteAsync(identityuser); if (result != null) { // delete user _users.DeleteUser(userid); _syncManager.AddSyncEvent(_tenantManager.GetAlias(), EntityNames.User, userid, SyncEventActions.Delete); _syncManager.AddSyncEvent(_tenantManager.GetAlias(), EntityNames.User, userid, SyncEventActions.Reload); _logger.Log(LogLevel.Information, this, LogFunction.Delete, "User Deleted {UserId}", userid, result.ToString()); } else { _logger.Log(LogLevel.Error, this, LogFunction.Delete, "Error Deleting User {UserId}", userid); } } } } public async Task LoginUser(User user, bool setCookie, bool isPersistent) { user.IsAuthenticated = false; IdentityUser identityuser = await _identityUserManager.FindByNameAsync(user.Username); if (identityuser != null) { var result = await _identitySignInManager.CheckPasswordSignInAsync(identityuser, user.Password, true); if (result.Succeeded) { var LastIPAddress = user.LastIPAddress ?? ""; user = _users.GetUser(user.Username); if (!user.IsDeleted) { var alias = _tenantManager.GetAlias(); var twoFactorSetting = _settings.GetSetting(EntityNames.Site, alias.SiteId, "LoginOptions:TwoFactor")?.SettingValue ?? "false"; var twoFactorRequired = twoFactorSetting == "required" || user.TwoFactorRequired; if (twoFactorRequired) { var token = await _identityUserManager.GenerateTwoFactorTokenAsync(identityuser, "Email"); user.TwoFactorCode = token; user.TwoFactorExpiry = DateTime.UtcNow.AddMinutes(10); _users.UpdateUser(user); string siteName = _sites.GetSite(alias.SiteId).Name; string subject = _localizer["TwoFactorEmailSubject"]; subject = subject.Replace("[SiteName]", siteName); string body = _localizer["TwoFactorEmailBody"].Value; body = body.Replace("[UserDisplayName]", user.DisplayName); body = body.Replace("[SiteName]", siteName); body = body.Replace("[Token]", token); var notification = new Notification(alias.SiteId, user, subject, body); _notifications.AddNotification(notification); _logger.Log(LogLevel.Information, this, LogFunction.Security, "User Verification Notification Sent For {Username}", user.Username); user.TwoFactorRequired = true; } else { if (await _identityUserManager.IsEmailConfirmedAsync(identityuser)) { user = GetUser(identityuser.UserName, alias.SiteId); if (user != null) { // ensure user is registered for site if (UserSecurity.ContainsRole(user.Roles, RoleNames.Registered)) { user.IsAuthenticated = true; user.LastLoginOn = DateTime.UtcNow; user.LastIPAddress = LastIPAddress; _users.UpdateUser(user); _logger.Log(LogLevel.Information, this, LogFunction.Security, "User Login Successful For {Username} From IP Address {IPAddress}", user.Username, LastIPAddress); _syncManager.AddSyncEvent(alias, EntityNames.User, user.UserId, "Login"); if (setCookie) { await _identitySignInManager.SignInAsync(identityuser, isPersistent); } } else { _logger.Log(LogLevel.Information, this, LogFunction.Security, "User {Username} Is Not An Active Member Of Site {SiteId}", user.Username, alias.SiteId); } } } else { _logger.Log(LogLevel.Information, this, LogFunction.Security, "User Email Address Not Verified {Username}", user.Username); } } } else { _logger.Log(LogLevel.Information, this, LogFunction.Security, "User Login Failed - Account Deleted {Username}", user.Username); } } else { if (result.IsLockedOut) { var alias = _tenantManager.GetAlias(); user = _users.GetUser(user.Username); string token = await _identityUserManager.GeneratePasswordResetTokenAsync(identityuser); string url = alias.Protocol + alias.Name + "/reset?name=" + user.Username + "&token=" + WebUtility.UrlEncode(token); string siteName = _sites.GetSite(alias.SiteId).Name; string subject = _localizer["UserLockoutEmailSubject"]; subject = subject.Replace("[SiteName]", siteName); string body = _localizer["UserLockoutEmailBody"].Value; body = body.Replace("[UserDisplayName]", user.DisplayName); body = body.Replace("[URL]", url); body = body.Replace("[SiteName]", siteName); var notification = new Notification(alias.SiteId, user, subject, body); _notifications.AddNotification(notification); _logger.Log(LogLevel.Information, this, LogFunction.Security, "User Lockout Notification Sent For {Username}", user.Username); } else { _logger.Log(LogLevel.Information, this, LogFunction.Security, "User Login Failed {Username}", user.Username); } } } return user; } public async Task LogoutUserEverywhere(User user) { var identityuser = await _identityUserManager.FindByNameAsync(user.Username); if (identityuser != null) { await _identityUserManager.UpdateSecurityStampAsync(identityuser); _syncManager.AddSyncEvent(_tenantManager.GetAlias(), EntityNames.User, user.UserId, SyncEventActions.Update); _syncManager.AddSyncEvent(_tenantManager.GetAlias(), EntityNames.User, user.UserId, SyncEventActions.Reload); } } public async Task VerifyEmail(User user, string token) { IdentityUser identityuser = await _identityUserManager.FindByNameAsync(user.Username); if (identityuser != null && !string.IsNullOrEmpty(token)) { var result = await _identityUserManager.ConfirmEmailAsync(identityuser, token); if (result.Succeeded) { _logger.Log(LogLevel.Information, this, LogFunction.Security, "Email Verified For {Username}", user.Username); } else { _logger.Log(LogLevel.Error, this, LogFunction.Security, "Email Verification Failed For {Username} - Error {Error}", user.Username, string.Join(" ", result.Errors.ToList().Select(e => e.Description))); user = null; } } else { _logger.Log(LogLevel.Error, this, LogFunction.Security, "Email Verification Failed For {Username}And Token {Token}", user.Username, token); user = null; } return user; } public async Task ForgotPassword(User user) { IdentityUser identityuser = await _identityUserManager.FindByNameAsync(user.Username); if (identityuser != null) { var alias = _tenantManager.GetAlias(); user = _users.GetUser(user.Username); string token = await _identityUserManager.GeneratePasswordResetTokenAsync(identityuser); string url = alias.Protocol + alias.Name + "/reset?name=" + user.Username + "&token=" + WebUtility.UrlEncode(token); string siteName = _sites.GetSite(alias.SiteId).Name; string subject = _localizer["ForgotPasswordEmailSubject"]; subject = subject.Replace("[SiteName]", siteName); string body = _localizer["ForgotPasswordEmailBody"].Value; body = body.Replace("[UserDisplayName]", user.DisplayName); body = body.Replace("[URL]", url); body = body.Replace("[SiteName]", siteName); var notification = new Notification(_tenantManager.GetAlias().SiteId, user, subject, body); _notifications.AddNotification(notification); _logger.Log(LogLevel.Information, this, LogFunction.Security, "Password Reset Notification Sent For {Username}", user.Username); } else { _logger.Log(LogLevel.Error, this, LogFunction.Security, "Password Reset Notification Failed For {Username}", user.Username); } } public async Task ResetPassword(User user, string token) { IdentityUser identityuser = await _identityUserManager.FindByNameAsync(user.Username); if (identityuser != null && !string.IsNullOrEmpty(token)) { // note that ResetPasswordAsync checks password complexity rules var result = await _identityUserManager.ResetPasswordAsync(identityuser, token, user.Password); if (result.Succeeded) { user = _users.GetUser(user.Username); _syncManager.AddSyncEvent(_tenantManager.GetAlias(), EntityNames.User, user.UserId, SyncEventActions.Update); _syncManager.AddSyncEvent(_tenantManager.GetAlias(), EntityNames.User, user.UserId, SyncEventActions.Reload); _logger.Log(LogLevel.Information, this, LogFunction.Security, "Password Reset For {Username}", user.Username); user.Password = ""; } else { _logger.Log(LogLevel.Information, this, LogFunction.Security, "Password Reset Failed For {Username} - Error {Error}", user.Username, string.Join(" ", result.Errors.ToList().Select(e => e.Description))); user = null; } } else { _logger.Log(LogLevel.Error, this, LogFunction.Security, "Password Reset Failed For {Username} And Token {Token}", user.Username, token); user = null; } return user; } public User VerifyTwoFactor(User user, string token) { user = _users.GetUser(user.Username); if (user != null) { var alias = _tenantManager.GetAlias(); var twoFactorSetting = _settings.GetSetting(EntityNames.Site, alias.SiteId, "LoginOptions:TwoFactor")?.SettingValue ?? "false"; var twoFactorRequired = twoFactorSetting == "required" || user.TwoFactorRequired; if (twoFactorRequired && user.TwoFactorCode == token && DateTime.UtcNow < user.TwoFactorExpiry) { user.IsAuthenticated = true; } } return user; } public async Task LinkExternalAccount(User user, string token, string type, string key, string name) { IdentityUser identityuser = await _identityUserManager.FindByNameAsync(user.Username); if (identityuser != null && !string.IsNullOrEmpty(token)) { var result = await _identityUserManager.ConfirmEmailAsync(identityuser, token); if (result.Succeeded) { // make LoginProvider multi-tenant aware type += ":" + user.SiteId.ToString(); await _identityUserManager.AddLoginAsync(identityuser, new UserLoginInfo(type, key, name)); _logger.Log(LogLevel.Information, this, LogFunction.Security, "External Login Linkage Successful For {Username} And Provider {Provider}", user.Username, type); } else { _logger.Log(LogLevel.Error, this, LogFunction.Security, "External Login Linkage Failed For {Username} - Error {Error}", user.Username, string.Join(" ", result.Errors.ToList().Select(e => e.Description))); user = null; } } return user; } public async Task ValidateUser(string username, string email, string password) { var validateResult = new UserValidateResult { Succeeded = true }; //validate username var allowedChars = _identityUserManager.Options.User.AllowedUserNameCharacters; if (string.IsNullOrWhiteSpace(username) || (!string.IsNullOrEmpty(allowedChars) && username.Any(c => !allowedChars.Contains(c)))) { validateResult.Succeeded = false; validateResult.Errors.Add("Message.Username.Invalid", string.Empty); } //validate password var passwordValidator = new PasswordValidator(); var passwordResult = await passwordValidator.ValidateAsync(_identityUserManager, null, password); if (!passwordResult.Succeeded) { validateResult.Succeeded = false; validateResult.Errors.Add("Message.Password.Invalid", string.Empty); } return validateResult; } public async Task ValidatePassword(string password) { var validator = new PasswordValidator(); var result = await validator.ValidateAsync(_identityUserManager, null, password); return result.Succeeded; } public async Task> ImportUsers(int siteId, string filePath, bool notify) { var success = true; int rows = 0; int users = 0; if (System.IO.File.Exists(filePath)) { var roles = _roles.GetRoles(siteId).ToList(); var profiles = _profiles.GetProfiles(siteId).ToList(); try { string row = ""; using (var reader = new StreamReader(filePath)) { // header row if (reader.Peek() > -1) { row = reader.ReadLine(); } if (!string.IsNullOrEmpty(row.Trim())) { var header = row.Replace("\"", "").Split('\t'); if (header[0].Trim() == "Email") { for (int index = 4; index < header.Length - 1; index++) { if (!string.IsNullOrEmpty(header[index].Trim()) && !profiles.Any(item => item.Name == header[index].Trim())) { _logger.Log(LogLevel.Error, this, LogFunction.Create, "User Import Contains Profile Name {Profile} Which Does Not Exist", header[index]); success = false; } } } else { _logger.Log(LogLevel.Error, this, LogFunction.Create, "User Import File Is Not In Correct Format. Please Use Template Provided."); success = false; } if (success) { // detail rows while (reader.Peek() > -1) { row = reader.ReadLine(); rows++; if (!string.IsNullOrEmpty(row.Trim())) { var values = row.Replace("\"", "").Split('\t'); // user var email = (values.Length > 0) ? values[0].Trim() : ""; var username = (values.Length > 1) ? values[1].Trim() : ""; var displayname = (values.Length > 2) ? values[2].Trim() : ""; var user = _users.GetUser(username, email); if (user == null) { user = new User(); user.SiteId = siteId; user.Email = values[0]; user.Username = (!string.IsNullOrEmpty(username)) ? username : user.Email; user.DisplayName = (!string.IsNullOrEmpty(displayname)) ? displayname : user.Username; user.EmailConfirmed = true; user.SuppressNotification = !notify; user = await AddUser(user); if (user == null) { _logger.Log(LogLevel.Error, this, LogFunction.Create, "User Import Error Importing User {Email} {Username} {DisplayName}", email, username, displayname); success = false; } } else { if (!string.IsNullOrEmpty(displayname)) { user.DisplayName = displayname; user.Password = ""; user = await UpdateUser(user); } } var rolenames = (values.Length > 3) ? values[3].Trim() : ""; if (user != null && !string.IsNullOrEmpty(rolenames)) { // roles (comma delimited) foreach (var rolename in rolenames.Split(',')) { var role = roles.FirstOrDefault(item => item.Name == rolename.Trim()); if (role == null) { role = new Role(); role.SiteId = siteId; role.Name = rolename.Trim(); role.Description = rolename.Trim(); role = _roles.AddRole(role); roles.Add(role); } if (role != null) { var userrole = _userRoles.GetUserRole(user.UserId, role.RoleId, false); if (userrole == null) { userrole = new UserRole(); userrole.UserId = user.UserId; userrole.RoleId = role.RoleId; _userRoles.AddUserRole(userrole); } } } } if (user != null && values.Length > 4) { // profiles var settings = _settings.GetSettings(EntityNames.User, user.UserId); for (int index = 4; index < values.Length - 1; index++) { if (header.Length > index && !string.IsNullOrEmpty(values[index].Trim())) { var profile = profiles.FirstOrDefault(item => item.Name == header[index].Trim()); if (profile != null) { var setting = settings.FirstOrDefault(item => item.SettingName == profile.Name); if (setting == null) { setting = new Setting(); setting.EntityName = EntityNames.User; setting.EntityId = user.UserId; setting.SettingName = profile.Name; setting.SettingValue = values[index].Trim(); _settings.AddSetting(setting); } else { if (setting.SettingValue != values[index].Trim()) { setting.SettingValue = values[index].Trim(); _settings.UpdateSetting(setting); } } } } } } users++; } } } } else { success = false; _logger.Log(LogLevel.Error, this, LogFunction.Create, "User Import File Contains No Header Row"); } } _logger.Log(LogLevel.Information, this, LogFunction.Create, "User Import: {Rows} Rows Processed, {Users} Users Imported", rows, users); } catch (Exception ex) { success = false; _logger.Log(LogLevel.Error, this, LogFunction.Create, ex, "Error Importing User Import File {SiteId} {FilePath} {Notify}", siteId, filePath, notify); } } else { success = false; _logger.Log(LogLevel.Error, this, LogFunction.Create, "User Import File Does Not Exist {FilePath}", filePath); } // return results var result = new Dictionary(); result.Add("Success", success.ToString()); result.Add("Users", users.ToString()); return result; } } }