add ability to import users

This commit is contained in:
sbwalker
2023-09-20 10:43:49 -04:00
parent 886df69058
commit 8e5e79a799
11 changed files with 421 additions and 6 deletions

View File

@ -28,9 +28,10 @@ namespace Oqtane.Controllers
private readonly IUserPermissions _userPermissions;
private readonly ISettingRepository _settings;
private readonly IJwtManager _jwtManager;
private readonly IFileRepository _files;
private readonly ILogManager _logger;
public UserController(IUserRepository users, ITenantManager tenantManager, IUserManager userManager, ISiteRepository sites, IUserPermissions userPermissions, ISettingRepository settings, IJwtManager jwtManager, ILogManager logger)
public UserController(IUserRepository users, ITenantManager tenantManager, IUserManager userManager, ISiteRepository sites, IUserPermissions userPermissions, ISettingRepository settings, IJwtManager jwtManager, IFileRepository files, ILogManager logger)
{
_users = users;
_tenantManager = tenantManager;
@ -39,6 +40,7 @@ namespace Oqtane.Controllers
_userPermissions = userPermissions;
_settings = settings;
_jwtManager = jwtManager;
_files = files;
_logger = logger;
}
@ -369,5 +371,22 @@ namespace Oqtane.Controllers
return requirements;
}
// POST api/<controller>/import?siteid=x&fileid=y
[HttpPost("import")]
[Authorize(Roles = RoleNames.Admin)]
public async Task<bool> Import(string siteid, string fileid)
{
if (int.TryParse(siteid, out int SiteId) && SiteId == _tenantManager.GetAlias().SiteId && int.TryParse(fileid, out int FileId))
{
return await _userManager.ImportUsers(SiteId, FileId);
}
else
{
_logger.Log(LogLevel.Error, this, LogFunction.Security, "Unauthorized User Import Attempt {SiteId} {FileId}", siteid, fileid);
HttpContext.Response.StatusCode = (int)HttpStatusCode.Forbidden;
return false;
}
}
}
}

View File

@ -18,5 +18,6 @@ namespace Oqtane.Managers
User VerifyTwoFactor(User user, string token);
Task<User> LinkExternalAccount(User user, string token, string type, string key, string name);
Task<bool> ValidatePassword(string password);
Task<bool> ImportUsers(int siteId, int fileId);
}
}

View File

@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Net;
@ -16,24 +17,32 @@ namespace Oqtane.Managers
public class UserManager : IUserManager
{
private readonly IUserRepository _users;
private readonly IRoleRepository _roles;
private readonly IUserRoleRepository _userRoles;
private readonly UserManager<IdentityUser> _identityUserManager;
private readonly SignInManager<IdentityUser> _identitySignInManager;
private readonly ITenantManager _tenantManager;
private readonly INotificationRepository _notifications;
private readonly IFolderRepository _folders;
private readonly IFileRepository _files;
private readonly IProfileRepository _profiles;
private readonly ISettingRepository _settings;
private readonly ISyncManager _syncManager;
private readonly ILogManager _logger;
public UserManager(IUserRepository users, IUserRoleRepository userRoles, UserManager<IdentityUser> identityUserManager, SignInManager<IdentityUser> identitySignInManager, ITenantManager tenantManager, INotificationRepository notifications, IFolderRepository folders, ISyncManager syncManager, ILogManager logger)
public UserManager(IUserRepository users, IRoleRepository roles, IUserRoleRepository userRoles, UserManager<IdentityUser> identityUserManager, SignInManager<IdentityUser> identitySignInManager, ITenantManager tenantManager, INotificationRepository notifications, IFolderRepository folders, IFileRepository files, IProfileRepository profiles, ISettingRepository settings, ISyncManager syncManager, ILogManager logger)
{
_users = users;
_roles = roles;
_userRoles = userRoles;
_identityUserManager = identityUserManager;
_identitySignInManager = identitySignInManager;
_tenantManager = tenantManager;
_notifications = notifications;
_folders = folders;
_files = files;
_profiles = profiles;
_settings = settings;
_syncManager = syncManager;
_logger = logger;
}
@ -95,6 +104,12 @@ namespace Oqtane.Managers
IdentityUser identityuser = await _identityUserManager.FindByNameAsync(user.Username);
if (identityuser == null)
{
if (string.IsNullOrEmpty(user.Password))
{
// create random password ie. Jan-01-2023+12:00:00!
Random rnd = new Random();
user.Password = DateTime.UtcNow.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;
@ -443,5 +458,144 @@ namespace Oqtane.Managers
var result = await validator.ValidateAsync(_identityUserManager, null, password);
return result.Succeeded;
}
public async Task<bool> ImportUsers(int siteId, int fileId)
{
var success = true;
int users = 0;
var file = _files.GetFile(fileId);
if (file != null)
{
var path = _files.GetFilePath(file);
if (System.IO.File.Exists(path))
{
var roles = _roles.GetRoles(siteId).ToList();
var profiles = _profiles.GetProfiles(siteId).ToList();
try
{
string row;
using (var reader = new StreamReader(path))
{
// get header row
row = reader.ReadLine();
var header = row.Replace("\"", "").Split(',');
row = reader.ReadLine();
while (row != null)
{
var values = row.Replace("\"", "").Split(',');
if (values.Length > 3)
{
// user
var user = _users.GetUser(values[1], values[0]);
if (user == null)
{
user = new User();
user.SiteId = siteId;
user.Email = values[0];
user.Username = (!string.IsNullOrEmpty(values[1])) ? values[1] : user.Email;
user.DisplayName = (!string.IsNullOrEmpty(values[2])) ? values[2] : user.Username;
user = await AddUser(user);
if (user == null)
{
_logger.Log(LogLevel.Error, this, LogFunction.Create, "Error Creating User {Email}", values[0]);
success = false;
}
}
if (user != null && !string.IsNullOrEmpty(values[3]))
{
// roles (comma delimited)
foreach (var rolename in values[3].Split(','))
{
var role = roles.FirstOrDefault(item => item.Name == rolename);
if (role == null)
{
role = new Role();
role.SiteId = siteId;
role.Name = rolename;
role.Description = rolename;
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)
{
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]))
{
var profile = profiles.FirstOrDefault(item => item.Name == header[index]);
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];
_settings.AddSetting(setting);
}
else
{
if (setting.SettingValue != values[index])
{
setting.SettingValue = values[index];
_settings.UpdateSetting(setting);
}
}
}
}
}
}
users++;
}
row = reader.ReadLine();
}
}
_logger.Log(LogLevel.Information, this, LogFunction.Create, "{Users} Users Imported", users);
}
catch (Exception ex)
{
_logger.Log(LogLevel.Error, this, LogFunction.Create, ex, "Error Importing User Import File {SiteId} {FileId}", siteId, fileId);
success = false;
}
}
else
{
_logger.Log(LogLevel.Error, this, LogFunction.Create,"User Import File Does Not Exist {Path}", path);
success = false;
}
}
else
{
_logger.Log(LogLevel.Error, this, LogFunction.Create, "User Import File Does Not Exist {SiteId} {FileId}", siteId, fileId);
success = false;
}
return success;
}
}
}

View File

@ -11,6 +11,8 @@ namespace Oqtane.Repository
UserRole UpdateUserRole(UserRole userRole);
UserRole GetUserRole(int userRoleId);
UserRole GetUserRole(int userRoleId, bool tracking);
UserRole GetUserRole(int userId, int roleId);
UserRole GetUserRole(int userId, int roleId, bool tracking);
void DeleteUserRole(int userRoleId);
void DeleteUserRoles(int userId);
}

View File

@ -78,6 +78,29 @@ namespace Oqtane.Repository
}
}
public UserRole GetUserRole(int userId, int roleId)
{
return GetUserRole(userId, roleId, true);
}
public UserRole GetUserRole(int userId, int roleId, bool tracking)
{
if (tracking)
{
return _db.UserRole
.Include(item => item.Role) // eager load roles
.Include(item => item.User) // eager load users
.FirstOrDefault(item => item.UserId == userId && item.RoleId == roleId);
}
else
{
return _db.UserRole.AsNoTracking()
.Include(item => item.Role) // eager load roles
.Include(item => item.User) // eager load users
.FirstOrDefault(item => item.UserId == userId && item.RoleId == roleId);
}
}
public void DeleteUserRole(int userRoleId)
{
UserRole userRole = _db.UserRole.Find(userRoleId);

View File

@ -0,0 +1 @@
Email,Username,DisplayName,Roles,FirstName,LastName,Street,City,Region,Country,PostalCode,Phone
1 Email Username DisplayName Roles FirstName LastName Street City Region Country PostalCode Phone