fix #4965 - improve user/site management

This commit is contained in:
sbwalker 2025-01-21 12:21:27 -05:00
parent 4793ab4bc9
commit 16477052e2
10 changed files with 187 additions and 105 deletions

View File

@ -58,7 +58,7 @@ else
<td>@context.EffectiveDate</td> <td>@context.EffectiveDate</td>
<td>@context.ExpiryDate</td> <td>@context.ExpiryDate</td>
<td> <td>
<ActionDialog Header="Remove User" Message="@string.Format(Localizer["Confirm.User.DeleteRole"], context.User.DisplayName)" Action="Delete" Security="SecurityAccessLevel.Edit" Class="btn btn-danger" OnClick="@(async () => await DeleteUserRole(context.UserRoleId))" Disabled="@(context.Role.IsAutoAssigned || context.User.Username == UserNames.Host || context.User.UserId == PageState.User.UserId)" ResourceKey="DeleteUserRole" /> <ActionDialog Header="Remove User" Message="@string.Format(Localizer["Confirm.User.DeleteRole"], context.User.DisplayName)" Action="Delete" Security="SecurityAccessLevel.Edit" Class="btn btn-danger" OnClick="@(async () => await DeleteUserRole(context.UserRoleId))" Disabled="@(context.User.Username == UserNames.Host || context.User.UserId == PageState.User.UserId)" ResourceKey="DeleteUserRole" />
</td> </td>
</Row> </Row>
</Pager> </Pager>
@ -180,27 +180,28 @@ else
private async Task DeleteUserRole(int UserRoleId) private async Task DeleteUserRole(int UserRoleId)
{ {
validated = true; try
var interop = new Interop(JSRuntime);
if (await interop.FormValid(form))
{ {
try var userrole = await UserRoleService.GetUserRoleAsync(UserRoleId);
if (userrole.Role.Name == RoleNames.Registered)
{
userrole.ExpiryDate = DateTime.UtcNow;
await UserRoleService.UpdateUserRoleAsync(userrole);
await logger.LogInformation("User {Username} Expired From Role {Role}", userrole.User.Username, userrole.Role.Name);
}
else
{ {
await UserRoleService.DeleteUserRoleAsync(UserRoleId); await UserRoleService.DeleteUserRoleAsync(UserRoleId);
await logger.LogInformation("User Removed From Role {UserRoleId}", UserRoleId); await logger.LogInformation("User {Username} Removed From Role {Role}", userrole.User.Username, userrole.Role.Name);
AddModuleMessage(Localizer["Confirm.User.RoleRemoved"], MessageType.Success);
await GetUserRoles();
StateHasChanged();
}
catch (Exception ex)
{
await logger.LogError(ex, "Error Removing User From Role {UserRoleId} {Error}", UserRoleId, ex.Message);
AddModuleMessage(Localizer["Error.User.RemoveRole"], MessageType.Error);
} }
AddModuleMessage(Localizer["Confirm.User.RoleRemoved"], MessageType.Success);
await GetUserRoles();
StateHasChanged();
} }
else catch (Exception ex)
{ {
AddModuleMessage(SharedLocalizer["Message.InfoRequired"], MessageType.Warning); await logger.LogError(ex, "Error Removing User From Role {UserRoleId} {Error}", UserRoleId, ex.Message);
AddModuleMessage(Localizer["Error.User.RemoveRole"], MessageType.Error);
} }
} }
} }

View File

@ -51,15 +51,18 @@
<input id="displayname" class="form-control" @bind="@displayname" /> <input id="displayname" class="form-control" @bind="@displayname" />
</div> </div>
</div> </div>
<div class="row mb-1 align-items-center"> @if (UserSecurity.IsAuthorized(PageState.User, RoleNames.Host))
<Label Class="col-sm-3" For="isdeleted" HelpText="Indicate if the user is active" ResourceKey="IsDeleted"></Label> {
<div class="col-sm-9"> <div class="row mb-1 align-items-center">
<select id="isdeleted" class="form-select" @bind="@isdeleted"> <Label Class="col-sm-3" For="isdeleted" HelpText="Indicate if the user is active" ResourceKey="IsDeleted"></Label>
<option value="True">@SharedLocalizer["Yes"]</option> <div class="col-sm-9">
<option value="False">@SharedLocalizer["No"]</option> <select id="isdeleted" class="form-select" @bind="@isdeleted">
</select> <option value="True">@SharedLocalizer["Yes"]</option>
<option value="False">@SharedLocalizer["No"]</option>
</select>
</div>
</div> </div>
</div> }
<div class="row mb-1 align-items-center"> <div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="lastlogin" HelpText="The date and time when the user last signed in" ResourceKey="LastLogin"></Label> <Label Class="col-sm-3" For="lastlogin" HelpText="The date and time when the user last signed in" ResourceKey="LastLogin"></Label>
<div class="col-sm-9"> <div class="col-sm-9">
@ -127,8 +130,11 @@
<button type="button" class="btn btn-success" @onclick="SaveUser">@SharedLocalizer["Save"]</button> <button type="button" class="btn btn-success" @onclick="SaveUser">@SharedLocalizer["Save"]</button>
<NavLink class="btn btn-secondary" href="@NavigateUrl()">@SharedLocalizer["Cancel"]</NavLink> <NavLink class="btn btn-secondary" href="@NavigateUrl()">@SharedLocalizer["Cancel"]</NavLink>
<br /> @if (UserSecurity.IsAuthorized(PageState.User, RoleNames.Host) && isdeleted == "True")
<br /> {
<ActionDialog Header="Delete User" Message="Are You Sure You Wish To Permanently Delete This User?" Action="Delete" Security="SecurityAccessLevel.Host" Class="btn btn-danger" OnClick="@(async () => await DeleteUser())" ResourceKey="DeleteUser" />
}
<br /><br />
<AuditInfo CreatedBy="@createdby" CreatedOn="@createdon" ModifiedBy="@modifiedby" ModifiedOn="@modifiedon" DeletedBy="@deletedby" DeletedOn="@deletedon"></AuditInfo> <AuditInfo CreatedBy="@createdby" CreatedOn="@createdon" ModifiedBy="@modifiedby" ModifiedOn="@modifiedon" DeletedBy="@deletedby" DeletedOn="@deletedon"></AuditInfo>
} }
@ -226,8 +232,10 @@
user.Password = _password; user.Password = _password;
user.Email = email; user.Email = email;
user.DisplayName = string.IsNullOrWhiteSpace(displayname) ? username : displayname; user.DisplayName = string.IsNullOrWhiteSpace(displayname) ? username : displayname;
if (UserSecurity.IsAuthorized(PageState.User, RoleNames.Host))
user.IsDeleted = (isdeleted == null ? true : Boolean.Parse(isdeleted)); {
user.IsDeleted = (isdeleted == null ? true : Boolean.Parse(isdeleted));
}
user = await UserService.UpdateUserAsync(user); user = await UserService.UpdateUserAsync(user);
if (user != null) if (user != null)
@ -259,6 +267,25 @@
} }
} }
private async Task DeleteUser()
{
try
{
if (UserSecurity.IsAuthorized(PageState.User, RoleNames.Host) && userid != PageState.User.UserId)
{
var user = await UserService.GetUserAsync(userid, PageState.Site.SiteId);
await UserService.DeleteUserAsync(user.UserId, PageState.Site.SiteId);
await logger.LogInformation("User Permanently Deleted {User}", user);
NavigationManager.NavigateTo(NavigateUrl());
}
}
catch (Exception ex)
{
await logger.LogError(ex, "Error Permanently Deleting User {UserId} {Error}", userid, ex.Message);
AddModuleMessage(Localizer["Error.DeleteUser"], MessageType.Error);
}
}
private bool ValidateProfiles() private bool ValidateProfiles()
{ {
foreach (Profile profile in profiles) foreach (Profile profile in profiles)

View File

@ -35,7 +35,7 @@ else
<ActionLink Action="Edit" Text="Edit" Parameters="@($"id=" + context.UserId.ToString())" Security="SecurityAccessLevel.Edit" ResourceKey="EditUser" /> <ActionLink Action="Edit" Text="Edit" Parameters="@($"id=" + context.UserId.ToString())" Security="SecurityAccessLevel.Edit" ResourceKey="EditUser" />
</td> </td>
<td> <td>
<ActionDialog Header="Delete User" Message="@string.Format(Localizer["Confirm.User.Delete"], context.User.DisplayName)" Action="Delete" Security="SecurityAccessLevel.Edit" Class="btn btn-danger" OnClick="@(async () => await DeleteUser(context))" Disabled="@(context.UserId == PageState.User.UserId)" ResourceKey="DeleteUser" /> <ActionDialog Header="Delete User" Message="@string.Format(Localizer["Confirm.User.Delete"], context.User.DisplayName)" Action="Delete" Security="SecurityAccessLevel.Edit" Class="btn btn-danger" OnClick="@(async () => await DeleteUser(context))" Disabled="@(context.UserId == PageState.User.UserId || context.User.IsDeleted)" ResourceKey="DeleteUser" />
</td> </td>
<td> <td>
<ActionLink Action="Roles" Text="Roles" Parameters="@($"id=" + context.UserId.ToString())" Security="SecurityAccessLevel.Edit" ResourceKey="Roles" /> <ActionLink Action="Roles" Text="Roles" Parameters="@($"id=" + context.UserId.ToString())" Security="SecurityAccessLevel.Edit" ResourceKey="Roles" />
@ -611,19 +611,31 @@ else
{ {
try try
{ {
var user = await UserService.GetUserAsync(UserRole.UserId, PageState.Site.SiteId); if (UserSecurity.IsAuthorized(PageState.User, RoleNames.Host))
if (user != null)
{ {
await UserService.DeleteUserAsync(user.UserId, PageState.Site.SiteId); var user = await UserService.GetUserAsync(UserRole.UserId, PageState.Site.SiteId);
await logger.LogInformation("User Deleted {User}", UserRole.User); if (user != null)
await LoadUsersAsync(true); {
StateHasChanged(); user.IsDeleted = true;
await UserService.UpdateUserAsync(user);
await logger.LogInformation("User Soft Deleted {User}", user);
}
} }
else
{
var userrole = await UserRoleService.GetUserRoleAsync(UserRole.UserRoleId);
userrole.ExpiryDate = DateTime.UtcNow;
await UserRoleService.UpdateUserRoleAsync(userrole);
await logger.LogInformation("User {Username} Expired From Role {Role}", userrole.User.Username, userrole.Role.Name);
}
AddModuleMessage(Localizer["Success.DeleteUser"], MessageType.Success);
await LoadUsersAsync(true);
StateHasChanged();
} }
catch (Exception ex) catch (Exception ex)
{ {
await logger.LogError(ex, "Error Deleting User {User} {Error}", UserRole.User, ex.Message); await logger.LogError(ex, "Error Deleting User {User} {Error}", UserRole.User, ex.Message);
AddModuleMessage(ex.Message, MessageType.Error); AddModuleMessage(Localizer["Error.DeleteUser"], MessageType.Error);
} }
} }

View File

@ -53,17 +53,17 @@ else
<p align="center"> <p align="center">
<Pager Items="@userroles"> <Pager Items="@userroles">
<Header> <Header>
<th>@Localizer["Roles"]</th> <th>@Localizer["Roles"]</th>
<th>@Localizer["Effective"]</th> <th>@Localizer["Effective"]</th>
<th>@Localizer["Expiry"]</th> <th>@Localizer["Expiry"]</th>
<th>&nbsp;</th> <th>&nbsp;</th>
</Header> </Header>
<Row> <Row>
<td>@context.Role.Name</td> <td>@context.Role.Name</td>
<td>@Utilities.UtcAsLocalDate(context.EffectiveDate)</td> <td>@Utilities.UtcAsLocalDate(context.EffectiveDate)</td>
<td>@Utilities.UtcAsLocalDate(context.ExpiryDate)</td> <td>@Utilities.UtcAsLocalDate(context.ExpiryDate)</td>
<td> <td>
<ActionDialog Header="Remove Role" Message="@string.Format(Localizer["Confirm.User.RemoveRole"], context.Role.Name)" Action="Delete" Security="SecurityAccessLevel.Edit" Class="btn btn-danger" OnClick="@(async () => await DeleteUserRole(context.UserRoleId))" Disabled="@(context.Role.IsAutoAssigned || (context.Role.Name == RoleNames.Host && userid == PageState.User.UserId))" ResourceKey="DeleteUserRole" /> <ActionDialog Header="Remove Role" Message="@string.Format(Localizer["Confirm.User.RemoveRole"], context.Role.Name)" Action="Delete" Security="SecurityAccessLevel.Edit" Class="btn btn-danger" OnClick="@(async () => await DeleteUserRole(context.UserRoleId))" Disabled="@(context.Role.Name == RoleNames.Host && userid == PageState.User.UserId)" ResourceKey="DeleteUserRole" />
</td> </td>
</Row> </Row>
</Pager> </Pager>
@ -171,8 +171,18 @@ else
{ {
try try
{ {
await UserRoleService.DeleteUserRoleAsync(UserRoleId); var userrole = await UserRoleService.GetUserRoleAsync(UserRoleId);
await logger.LogInformation("User Removed From Role {UserRoleId}", UserRoleId); if (userrole.Role.Name == RoleNames.Registered)
{
userrole.ExpiryDate = DateTime.UtcNow;
await UserRoleService.UpdateUserRoleAsync(userrole);
await logger.LogInformation("User {Username} Expired From Role {Role}", userrole.User.Username, userrole.Role.Name);
}
else
{
await UserRoleService.DeleteUserRoleAsync(UserRoleId);
await logger.LogInformation("User {Username} Removed From Role {Role}", userrole.User.Username, userrole.Role.Name);
}
AddModuleMessage(Localizer["Success.User.Remove"], MessageType.Success); AddModuleMessage(Localizer["Success.User.Remove"], MessageType.Success);
await GetUserRoles(); await GetUserRoles();
StateHasChanged(); StateHasChanged();

View File

@ -195,4 +195,13 @@
<data name="LastLogin.Text" xml:space="preserve"> <data name="LastLogin.Text" xml:space="preserve">
<value>Last Login:</value> <value>Last Login:</value>
</data> </data>
<data name="DeleteUser.Header" xml:space="preserve">
<value>Delete User</value>
</data>
<data name="DeleteUser.Text" xml:space="preserve">
<value>Delete</value>
</data>
<data name="DeleteUser.Message" xml:space="preserve">
<value>Are You Sure You Wish To Permanently Delete This User?</value>
</data>
</root> </root>

View File

@ -501,4 +501,10 @@
<data name="SaveTokens.HelpText" xml:space="preserve"> <data name="SaveTokens.HelpText" xml:space="preserve">
<value>Specify whether access and refresh tokens should be saved after a successful login. The default is false to reduce the size of the authentication cookie.</value> <value>Specify whether access and refresh tokens should be saved after a successful login. The default is false to reduce the size of the authentication cookie.</value>
</data> </data>
<data name="Success.DeleteUser" xml:space="preserve">
<value>User Deleted Successfully</value>
</data>
<data name="Error.DeleteUser" xml:space="preserve">
<value>Error Deleting User</value>
</data>
</root> </root>

View File

@ -427,7 +427,7 @@
<value>At Least One Uppercase Letter</value> <value>At Least One Uppercase Letter</value>
</data> </data>
<data name="Password.ValidationCriteria" xml:space="preserve"> <data name="Password.ValidationCriteria" xml:space="preserve">
<value>Passwords Must Have A Minimum Length Of {0} Characters, Including At Least {1} Unique Character(s), {2}{3}{4}{5} To Satisfy Password Compexity Requirements For This Site.</value> <value>Passwords Must Have A Minimum Length Of {0} Characters, Including At Least {1} Unique Character(s), {2}{3}{4}{5} To Satisfy Password Complexity Requirements For This Site.</value>
</data> </data>
<data name="ProfileInvalid" xml:space="preserve"> <data name="ProfileInvalid" xml:space="preserve">
<value>{0} Is Not Valid</value> <value>{0} Is Not Valid</value>

View File

@ -217,7 +217,7 @@ namespace Oqtane.Controllers
// DELETE api/<controller>/5?siteid=x // DELETE api/<controller>/5?siteid=x
[HttpDelete("{id}")] [HttpDelete("{id}")]
[Authorize(Policy = $"{EntityNames.User}:{PermissionNames.Write}:{RoleNames.Admin}")] [Authorize(Policy = $"{EntityNames.User}:{PermissionNames.Write}:{RoleNames.Host}")]
public async Task Delete(int id, string siteid) public async Task Delete(int id, string siteid)
{ {
User user = _users.GetUser(id, false); User user = _users.GetUser(id, false);

View File

@ -524,11 +524,6 @@ namespace Oqtane.Extensions
// manage user // manage user
if (user != null) if (user != null)
{ {
// update user
user.LastLoginOn = DateTime.UtcNow;
user.LastIPAddress = httpContext.Connection.RemoteIpAddress.ToString();
_users.UpdateUser(user);
// manage roles // manage roles
var _userRoles = httpContext.RequestServices.GetRequiredService<IUserRoleRepository>(); var _userRoles = httpContext.RequestServices.GetRequiredService<IUserRoleRepository>();
var userRoles = _userRoles.GetUserRoles(user.UserId, user.SiteId).ToList(); var userRoles = _userRoles.GetUserRoles(user.UserId, user.SiteId).ToList();
@ -588,64 +583,78 @@ namespace Oqtane.Extensions
} }
} }
// create claims identity var userrole = userRoles.FirstOrDefault(item => item.Role.Name == RoleNames.Registered);
identityuser = await _identityUserManager.FindByNameAsync(user.Username); if (!user.IsDeleted && userrole != null && Utilities.IsEffectiveAndNotExpired(userrole.EffectiveDate, userrole.ExpiryDate))
user.SecurityStamp = identityuser.SecurityStamp;
identity = UserSecurity.CreateClaimsIdentity(alias, user, userRoles);
identity.Label = ExternalLoginStatus.Success;
// user profile claims
if (!string.IsNullOrEmpty(httpContext.GetSiteSettings().GetValue("ExternalLogin:ProfileClaimTypes", "")))
{ {
var _settings = httpContext.RequestServices.GetRequiredService<ISettingRepository>(); // update user
var _profiles = httpContext.RequestServices.GetRequiredService<IProfileRepository>(); user.LastLoginOn = DateTime.UtcNow;
var profiles = _profiles.GetProfiles(alias.SiteId).ToList(); user.LastIPAddress = httpContext.Connection.RemoteIpAddress.ToString();
foreach (var mapping in httpContext.GetSiteSettings().GetValue("ExternalLogin:ProfileClaimTypes", "").Split(',', StringSplitOptions.RemoveEmptyEntries)) _users.UpdateUser(user);
// create claims identity
identityuser = await _identityUserManager.FindByNameAsync(user.Username);
user.SecurityStamp = identityuser.SecurityStamp;
identity = UserSecurity.CreateClaimsIdentity(alias, user, userRoles);
identity.Label = ExternalLoginStatus.Success;
// user profile claims
if (!string.IsNullOrEmpty(httpContext.GetSiteSettings().GetValue("ExternalLogin:ProfileClaimTypes", "")))
{ {
if (mapping.Contains(":")) var _settings = httpContext.RequestServices.GetRequiredService<ISettingRepository>();
var _profiles = httpContext.RequestServices.GetRequiredService<IProfileRepository>();
var profiles = _profiles.GetProfiles(alias.SiteId).ToList();
foreach (var mapping in httpContext.GetSiteSettings().GetValue("ExternalLogin:ProfileClaimTypes", "").Split(',', StringSplitOptions.RemoveEmptyEntries))
{ {
var claim = claimsPrincipal.Claims.FirstOrDefault(item => item.Type == mapping.Split(":")[0]); if (mapping.Contains(":"))
if (claim != null)
{ {
var profile = profiles.FirstOrDefault(item => item.Name == mapping.Split(":")[1]); var claim = claimsPrincipal.Claims.FirstOrDefault(item => item.Type == mapping.Split(":")[0]);
if (profile != null) if (claim != null)
{ {
if (!string.IsNullOrEmpty(claim.Value)) var profile = profiles.FirstOrDefault(item => item.Name == mapping.Split(":")[1]);
if (profile != null)
{ {
var setting = _settings.GetSetting(EntityNames.User, user.UserId, profile.Name); if (!string.IsNullOrEmpty(claim.Value))
if (setting != null)
{ {
setting.SettingValue = claim.Value; var setting = _settings.GetSetting(EntityNames.User, user.UserId, profile.Name);
_settings.UpdateSetting(setting); if (setting != null)
} {
else setting.SettingValue = claim.Value;
{ _settings.UpdateSetting(setting);
setting = new Setting { EntityName = EntityNames.User, EntityId = user.UserId, SettingName = profile.Name, SettingValue = claim.Value, IsPrivate = profile.IsPrivate }; }
_settings.AddSetting(setting); else
{
setting = new Setting { EntityName = EntityNames.User, EntityId = user.UserId, SettingName = profile.Name, SettingValue = claim.Value, IsPrivate = profile.IsPrivate };
_settings.AddSetting(setting);
}
} }
} }
else
{
_logger.Log(LogLevel.Error, "ExternalLogin", Enums.LogFunction.Security, "The User Profile {ProfileName} Does Not Exist For The Site. Please Verify Your User Profile Definitions.", mapping.Split(":")[1]);
}
} }
else else
{ {
_logger.Log(LogLevel.Error, "ExternalLogin", Enums.LogFunction.Security, "The User Profile {ProfileName} Does Not Exist For The Site. Please Verify Your User Profile Definitions.", mapping.Split(":")[1]); _logger.Log(LogLevel.Error, "ExternalLogin", Enums.LogFunction.Security, "The User Profile Claim {ClaimType} Does Not Exist. Please Use The Review Claims Feature To View The Claims Returned By Your Provider.", mapping.Split(":")[0]);
} }
} }
else else
{ {
_logger.Log(LogLevel.Error, "ExternalLogin", Enums.LogFunction.Security, "The User Profile Claim {ClaimType} Does Not Exist. Please Use The Review Claims Feature To View The Claims Returned By Your Provider.", mapping.Split(":")[0]); _logger.Log(LogLevel.Error, "ExternalLogin", Enums.LogFunction.Security, "The User Profile Claim Mapping {Mapping} Is Not Specified Correctly. It Should Be In The Format 'ClaimType:ProfileName'.", mapping);
} }
} }
else
{
_logger.Log(LogLevel.Error, "ExternalLogin", Enums.LogFunction.Security, "The User Profile Claim Mapping {Mapping} Is Not Specified Correctly. It Should Be In The Format 'ClaimType:ProfileName'.", mapping);
}
} }
var _syncManager = httpContext.RequestServices.GetRequiredService<ISyncManager>();
_syncManager.AddSyncEvent(alias, EntityNames.User, user.UserId, "Login");
_logger.Log(LogLevel.Information, "ExternalLogin", Enums.LogFunction.Security, "External User Login Successful For {Username} From IP Address {IPAddress} Using Provider {Provider}", user.Username, httpContext.Connection.RemoteIpAddress.ToString(), providerName);
}
else
{
identity.Label = ExternalLoginStatus.AccessDenied;
_logger.Log(LogLevel.Error, "ExternalLogin", Enums.LogFunction.Security, "External User Login Denied For {Username}. User Account Is Deleted Or Not An Active Member Of Site {SiteId}.", user.Username, user.SiteId);
} }
var _syncManager = httpContext.RequestServices.GetRequiredService<ISyncManager>();
_syncManager.AddSyncEvent(alias, EntityNames.User, user.UserId, "Login");
_logger.Log(LogLevel.Information, "ExternalLogin", Enums.LogFunction.Security, "External User Login Successful For {Username} From IP Address {IPAddress} Using Provider {Provider}", user.Username, httpContext.Connection.RemoteIpAddress.ToString(), providerName);
} }
} }
else // claims invalid else // claims invalid

View File

@ -363,28 +363,36 @@ namespace Oqtane.Managers
} }
else else
{ {
user = _users.GetUser(identityuser.UserName); if (await _identityUserManager.IsEmailConfirmedAsync(identityuser))
if (user != null)
{ {
if (await _identityUserManager.IsEmailConfirmedAsync(identityuser)) user = GetUser(identityuser.UserName, alias.SiteId);
if (user != null)
{ {
user.IsAuthenticated = true; // ensure user is registered for site
user.LastLoginOn = DateTime.UtcNow; if (user.Roles.Contains(RoleNames.Registered))
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); 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 }
{ else
_logger.Log(LogLevel.Information, this, LogFunction.Security, "User Email Address Not Verified {Username}", user.Username); {
} _logger.Log(LogLevel.Information, this, LogFunction.Security, "User Email Address Not Verified {Username}", user.Username);
} }
} }
} }