fix #5349 - send verification email if unverified user attempts to login, add ability to enable/disable email verification per site
This commit is contained in:
@ -21,9 +21,7 @@ else
|
|||||||
@if (_allowexternallogin)
|
@if (_allowexternallogin)
|
||||||
{
|
{
|
||||||
<button type="button" class="btn btn-primary" @onclick="ExternalLogin">@Localizer["Use"] @PageState.Site.Settings["ExternalLogin:ProviderName"]</button>
|
<button type="button" class="btn btn-primary" @onclick="ExternalLogin">@Localizer["Use"] @PageState.Site.Settings["ExternalLogin:ProviderName"]</button>
|
||||||
<br />
|
<br /><br />
|
||||||
|
|
||||||
<br />
|
|
||||||
}
|
}
|
||||||
@if (_allowsitelogin)
|
@if (_allowsitelogin)
|
||||||
{
|
{
|
||||||
@ -49,15 +47,11 @@ else
|
|||||||
</div>
|
</div>
|
||||||
<button type="button" class="btn btn-primary" @onclick="Login">@SharedLocalizer["Login"]</button>
|
<button type="button" class="btn btn-primary" @onclick="Login">@SharedLocalizer["Login"]</button>
|
||||||
<button type="button" class="btn btn-secondary" @onclick="Cancel">@SharedLocalizer["Cancel"]</button>
|
<button type="button" class="btn btn-secondary" @onclick="Cancel">@SharedLocalizer["Cancel"]</button>
|
||||||
<br />
|
<br /><br />
|
||||||
|
|
||||||
<br />
|
|
||||||
<button type="button" class="btn btn-secondary" @onclick="Forgot">@Localizer["ForgotPassword"]</button>
|
<button type="button" class="btn btn-secondary" @onclick="Forgot">@Localizer["ForgotPassword"]</button>
|
||||||
@if (PageState.Site.AllowRegistration)
|
@if (PageState.Site.AllowRegistration)
|
||||||
{
|
{
|
||||||
<br />
|
<br /><br />
|
||||||
|
|
||||||
<br />
|
|
||||||
<NavLink href="@NavigateUrl("register")">@Localizer["Register"]</NavLink>
|
<NavLink href="@NavigateUrl("register")">@Localizer["Register"]</NavLink>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -28,6 +28,15 @@
|
|||||||
<input id="email" class="form-control" @bind="@_email" />
|
<input id="email" class="form-control" @bind="@_email" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="row mb-1 align-items-center">
|
||||||
|
<Label Class="col-sm-3" For="confirmed" HelpText="Indicates if the user's email is verified" ResourceKey="Confirmed">Verified?</Label>
|
||||||
|
<div class="col-sm-9">
|
||||||
|
<select id="confirmed" class="form-select" @bind="@_confirmed">
|
||||||
|
<option value="True">@SharedLocalizer["Yes"]</option>
|
||||||
|
<option value="False">@SharedLocalizer["No"]</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div class="row mb-1 align-items-center">
|
<div class="row mb-1 align-items-center">
|
||||||
<Label Class="col-sm-3" For="displayname" HelpText="The full name of the user" ResourceKey="DisplayName"></Label>
|
<Label Class="col-sm-3" For="displayname" HelpText="The full name of the user" ResourceKey="DisplayName"></Label>
|
||||||
<div class="col-sm-9">
|
<div class="col-sm-9">
|
||||||
@ -120,6 +129,7 @@
|
|||||||
private bool _initialized = false;
|
private bool _initialized = false;
|
||||||
private string _username = string.Empty;
|
private string _username = string.Empty;
|
||||||
private string _email = string.Empty;
|
private string _email = string.Empty;
|
||||||
|
private string _confirmed = "True";
|
||||||
private string _displayname = string.Empty;
|
private string _displayname = string.Empty;
|
||||||
private string _timezoneid = string.Empty;
|
private string _timezoneid = string.Empty;
|
||||||
private string _notify = "True";
|
private string _notify = "True";
|
||||||
@ -169,6 +179,7 @@
|
|||||||
user.Username = _username;
|
user.Username = _username;
|
||||||
user.Password = ""; // will be auto generated
|
user.Password = ""; // will be auto generated
|
||||||
user.Email = _email;
|
user.Email = _email;
|
||||||
|
user.EmailConfirmed = bool.Parse(_confirmed);
|
||||||
user.DisplayName = string.IsNullOrWhiteSpace(_displayname) ? _username : _displayname;
|
user.DisplayName = string.IsNullOrWhiteSpace(_displayname) ? _username : _displayname;
|
||||||
user.TimeZoneId = _timezoneid;
|
user.TimeZoneId = _timezoneid;
|
||||||
user.PhotoFileId = null;
|
user.PhotoFileId = null;
|
||||||
|
@ -48,7 +48,7 @@
|
|||||||
</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="confirmed" HelpText="Indicates if the user's email is verified" ResourceKey="Confirmed">Confirmed?</Label>
|
<Label Class="col-sm-3" For="confirmed" HelpText="Indicates if the user's email is verified" ResourceKey="Confirmed">Verified?</Label>
|
||||||
<div class="col-sm-9">
|
<div class="col-sm-9">
|
||||||
<select id="confirmed" class="form-select" @bind="@_confirmed">
|
<select id="confirmed" class="form-select" @bind="@_confirmed">
|
||||||
<option value="True">@SharedLocalizer["Yes"]</option>
|
<option value="True">@SharedLocalizer["Yes"]</option>
|
||||||
|
@ -74,10 +74,19 @@ else
|
|||||||
<input id="profileurl" class="form-control" @bind="@_profileurl" />
|
<input id="profileurl" class="form-control" @bind="@_profileurl" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="row mb-1 align-items-center">
|
||||||
|
<Label Class="col-sm-3" For="requirevalidemail" HelpText="Do you want to require registered users to validate their email address before they are allowed to log in?" ResourceKey="RequireValidEmail">Require Valid Email?</Label>
|
||||||
|
<div class="col-sm-9">
|
||||||
|
<select id="requirevalidemail" class="form-select" @bind="@_requirevalidemail">
|
||||||
|
<option value="true">@SharedLocalizer["Yes"]</option>
|
||||||
|
<option value="false">@SharedLocalizer["No"]</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
@if (UserSecurity.IsAuthorized(PageState.User, RoleNames.Host))
|
@if (UserSecurity.IsAuthorized(PageState.User, RoleNames.Host))
|
||||||
{
|
{
|
||||||
<div class="row mb-1 align-items-center">
|
<div class="row mb-1 align-items-center">
|
||||||
<Label Class="col-sm-3" For="twofactor" HelpText="Do you want users to use two factor authentication? Note that you should use the Disabled option until you have successfully verified that the Notification Job in Scheduled Jobs is enabled and your SMTP options in Site Settings are configured or else you will lock yourself out." ResourceKey="TwoFactor">Two Factor?</Label>
|
<Label Class="col-sm-3" For="twofactor" HelpText="Do you want users to use two factor authentication? Note that you should use the Disabled option until you have successfully verified that the Notification Job in Scheduled Jobs is enabled and your SMTP options in Site Settings are configured or else you will lock yourself out." ResourceKey="TwoFactor">Two Factor Authentication?</Label>
|
||||||
<div class="col-sm-9">
|
<div class="col-sm-9">
|
||||||
<select id="twofactor" class="form-select" @bind="@_twofactor">
|
<select id="twofactor" class="form-select" @bind="@_twofactor">
|
||||||
<option value="false">@Localizer["Disabled"]</option>
|
<option value="false">@Localizer["Disabled"]</option>
|
||||||
@ -490,6 +499,7 @@ else
|
|||||||
private string _allowregistration;
|
private string _allowregistration;
|
||||||
private string _registerurl;
|
private string _registerurl;
|
||||||
private string _profileurl;
|
private string _profileurl;
|
||||||
|
private string _requirevalidemail;
|
||||||
private string _twofactor;
|
private string _twofactor;
|
||||||
private string _cookiename;
|
private string _cookiename;
|
||||||
private string _cookieexpiration;
|
private string _cookieexpiration;
|
||||||
@ -560,6 +570,7 @@ else
|
|||||||
_allowregistration = PageState.Site.AllowRegistration.ToString().ToLower();
|
_allowregistration = PageState.Site.AllowRegistration.ToString().ToLower();
|
||||||
_registerurl = SettingService.GetSetting(settings, "LoginOptions:RegisterUrl", "");
|
_registerurl = SettingService.GetSetting(settings, "LoginOptions:RegisterUrl", "");
|
||||||
_profileurl = SettingService.GetSetting(settings, "LoginOptions:ProfileUrl", "");
|
_profileurl = SettingService.GetSetting(settings, "LoginOptions:ProfileUrl", "");
|
||||||
|
_requirevalidemail = SettingService.GetSetting(settings, "LoginOptions:RequireValidEmail", "true");
|
||||||
|
|
||||||
if (UserSecurity.IsAuthorized(PageState.User, RoleNames.Host))
|
if (UserSecurity.IsAuthorized(PageState.User, RoleNames.Host))
|
||||||
{
|
{
|
||||||
@ -685,6 +696,7 @@ else
|
|||||||
{
|
{
|
||||||
settings = SettingService.SetSetting(settings, "LoginOptions:RegisterUrl", _registerurl, false);
|
settings = SettingService.SetSetting(settings, "LoginOptions:RegisterUrl", _registerurl, false);
|
||||||
settings = SettingService.SetSetting(settings, "LoginOptions:ProfileUrl", _profileurl, false);
|
settings = SettingService.SetSetting(settings, "LoginOptions:ProfileUrl", _profileurl, false);
|
||||||
|
settings = SettingService.SetSetting(settings, "LoginOptions:RequireValidEmail", _requirevalidemail, false);
|
||||||
settings = SettingService.SetSetting(settings, "LoginOptions:TwoFactor", _twofactor, false);
|
settings = SettingService.SetSetting(settings, "LoginOptions:TwoFactor", _twofactor, false);
|
||||||
settings = SettingService.SetSetting(settings, "LoginOptions:CookieName", _cookiename, true);
|
settings = SettingService.SetSetting(settings, "LoginOptions:CookieName", _cookiename, true);
|
||||||
settings = SettingService.SetSetting(settings, "LoginOptions:CookieExpiration", _cookieexpiration, true);
|
settings = SettingService.SetSetting(settings, "LoginOptions:CookieExpiration", _cookieexpiration, true);
|
||||||
|
@ -133,7 +133,7 @@
|
|||||||
<value>External Login Could Not Be Linked. Please Contact Your Administrator For Further Instructions.</value>
|
<value>External Login Could Not Be Linked. Please Contact Your Administrator For Further Instructions.</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="Error.Login.Fail" xml:space="preserve">
|
<data name="Error.Login.Fail" xml:space="preserve">
|
||||||
<value>Login Failed. Please Remember That Passwords Are Case Sensitive. If You Have Attempted To Sign In Multiple Times Unsuccessfully, Your Account Will Be Locked Out For A Period Of Time. Note That User Accounts Often Require Email Address Verification So You May Wish To Check Your Email For A Notification.</value>
|
<value>Login Failed. Please Remember That Passwords Are Case Sensitive. If You Have Attempted To Sign In Multiple Times Unsuccessfully, Your Account Will Be Locked Out For A Period Of Time. Note That New User Accounts Often Require Email Address Verification So You May Wish To Check Your Email For A Notification Containing Further Instructions.</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="Message.Required.UserInfo" xml:space="preserve">
|
<data name="Message.Required.UserInfo" xml:space="preserve">
|
||||||
<value>Please Provide All Required Fields</value>
|
<value>Please Provide All Required Fields</value>
|
||||||
|
@ -162,4 +162,10 @@
|
|||||||
<data name="TimeZone.HelpText" xml:space="preserve">
|
<data name="TimeZone.HelpText" xml:space="preserve">
|
||||||
<value>The user's time zone</value>
|
<value>The user's time zone</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="Confirmed.Text" xml:space="preserve">
|
||||||
|
<value>Verified?</value>
|
||||||
|
</data>
|
||||||
|
<data name="Confirmed.HelpText" xml:space="preserve">
|
||||||
|
<value>Indicates if the user's email is verified</value>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
@ -217,7 +217,7 @@
|
|||||||
<value>The user's time zone</value>
|
<value>The user's time zone</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="Confirmed.Text" xml:space="preserve">
|
<data name="Confirmed.Text" xml:space="preserve">
|
||||||
<value>Confirmed?</value>
|
<value>Verified?</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="Confirmed.HelpText" xml:space="preserve">
|
<data name="Confirmed.HelpText" xml:space="preserve">
|
||||||
<value>Indicates if the user's email is verified</value>
|
<value>Indicates if the user's email is verified</value>
|
||||||
|
@ -370,7 +370,13 @@
|
|||||||
<value>Do you want users to use two factor authentication? Note that you should use the Disabled option until you have successfully verified that the Notification Job in Scheduled Jobs is enabled and your SMTP options in Site Settings are configured or else you will lock yourself out.</value>
|
<value>Do you want users to use two factor authentication? Note that you should use the Disabled option until you have successfully verified that the Notification Job in Scheduled Jobs is enabled and your SMTP options in Site Settings are configured or else you will lock yourself out.</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TwoFactor.Text" xml:space="preserve">
|
<data name="TwoFactor.Text" xml:space="preserve">
|
||||||
<value>Two Factor?</value>
|
<value>Two Factor Authentication?</value>
|
||||||
|
</data>
|
||||||
|
<data name="RequireValidEmail.HelpText" xml:space="preserve">
|
||||||
|
<value>Do you want to require registered users to validate their email address before they are allowed to log in?</value>
|
||||||
|
</data>
|
||||||
|
<data name="RequireValidEmail.Text" xml:space="preserve">
|
||||||
|
<value>Require Valid Email?</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="Disabled" xml:space="preserve">
|
<data name="Disabled" xml:space="preserve">
|
||||||
<value>Disabled</value>
|
<value>Disabled</value>
|
||||||
|
@ -165,14 +165,13 @@ namespace Oqtane.Controllers
|
|||||||
bool allowregistration;
|
bool allowregistration;
|
||||||
if (_userPermissions.IsAuthorized(User, user.SiteId, EntityNames.User, -1, PermissionNames.Write, RoleNames.Admin))
|
if (_userPermissions.IsAuthorized(User, user.SiteId, EntityNames.User, -1, PermissionNames.Write, RoleNames.Admin))
|
||||||
{
|
{
|
||||||
user.EmailConfirmed = true;
|
user.IsAuthenticated = true; // admins can add any existing user to a site
|
||||||
user.IsAuthenticated = true;
|
|
||||||
allowregistration = true;
|
allowregistration = true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
user.EmailConfirmed = false;
|
user.EmailConfirmed = false; // standard users cannot specify that their email is verified
|
||||||
user.IsAuthenticated = false;
|
user.IsAuthenticated = false; // existing users can only be added to a site if they provide a valid username and password
|
||||||
allowregistration = _sites.GetSite(user.SiteId).AllowRegistration;
|
allowregistration = _sites.GetSite(user.SiteId).AllowRegistration;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -228,11 +228,12 @@ namespace Microsoft.Extensions.DependencyInjection
|
|||||||
options.Lockout.AllowedForNewUsers = false;
|
options.Lockout.AllowedForNewUsers = false;
|
||||||
|
|
||||||
// SignIn settings
|
// SignIn settings
|
||||||
options.SignIn.RequireConfirmedEmail = true;
|
options.SignIn.RequireConfirmedEmail = false;
|
||||||
|
options.SignIn.RequireConfirmedAccount = false;
|
||||||
options.SignIn.RequireConfirmedPhoneNumber = false;
|
options.SignIn.RequireConfirmedPhoneNumber = false;
|
||||||
|
|
||||||
// User settings
|
// User settings
|
||||||
options.User.RequireUniqueEmail = false; // changing to true will cause issues for legacy data
|
options.User.RequireUniqueEmail = false;
|
||||||
options.User.AllowedUserNameCharacters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._@+";
|
options.User.AllowedUserNameCharacters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._@+";
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -180,7 +180,7 @@ namespace Oqtane.Managers
|
|||||||
if (User != null)
|
if (User != null)
|
||||||
{
|
{
|
||||||
string siteName = _sites.GetSite(user.SiteId).Name;
|
string siteName = _sites.GetSite(user.SiteId).Name;
|
||||||
if (!user.EmailConfirmed)
|
if (!user.EmailConfirmed && bool.Parse(_settings.GetSettingValue(EntityNames.Site, alias.SiteId, "LoginOptions:RequireValidEmail", "true")))
|
||||||
{
|
{
|
||||||
string token = await _identityUserManager.GenerateEmailConfirmationTokenAsync(identityuser);
|
string token = await _identityUserManager.GenerateEmailConfirmationTokenAsync(identityuser);
|
||||||
string url = alias.Protocol + alias.Name + "/login?name=" + user.Username + "&token=" + WebUtility.UrlEncode(token);
|
string url = alias.Protocol + alias.Name + "/login?name=" + user.Username + "&token=" + WebUtility.UrlEncode(token);
|
||||||
@ -252,29 +252,32 @@ namespace Oqtane.Managers
|
|||||||
await _identityUserManager.UpdateAsync(identityuser); // security stamp not updated
|
await _identityUserManager.UpdateAsync(identityuser); // security stamp not updated
|
||||||
}
|
}
|
||||||
|
|
||||||
if (user.EmailConfirmed)
|
if (bool.Parse(_settings.GetSettingValue(EntityNames.Site, alias.SiteId, "LoginOptions:RequireValidEmail", "true")))
|
||||||
{
|
{
|
||||||
if (!identityuser.EmailConfirmed)
|
if (user.EmailConfirmed)
|
||||||
{
|
{
|
||||||
var emailConfirmationToken = await _identityUserManager.GenerateEmailConfirmationTokenAsync(identityuser);
|
if (!identityuser.EmailConfirmed)
|
||||||
await _identityUserManager.ConfirmEmailAsync(identityuser, emailConfirmationToken);
|
{
|
||||||
|
var emailConfirmationToken = await _identityUserManager.GenerateEmailConfirmationTokenAsync(identityuser);
|
||||||
|
await _identityUserManager.ConfirmEmailAsync(identityuser, emailConfirmationToken);
|
||||||
|
|
||||||
string body = "Dear " + user.DisplayName + ",\n\nThe Email Address For Your User Account Has Been Verified. You Can Now Login With Your Username And Password.";
|
string body = "Dear " + user.DisplayName + ",\n\nThe Email Address For Your User Account Has Been Verified. You Can Now Login With Your Username And Password.";
|
||||||
|
var notification = new Notification(user.SiteId, user, "User Account Verification", body);
|
||||||
|
_notifications.AddNotification(notification);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
identityuser.EmailConfirmed = false;
|
||||||
|
await _identityUserManager.UpdateAsync(identityuser); // security stamp not updated
|
||||||
|
|
||||||
|
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);
|
var notification = new Notification(user.SiteId, user, "User Account Verification", body);
|
||||||
_notifications.AddNotification(notification);
|
_notifications.AddNotification(notification);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
identityuser.EmailConfirmed = false;
|
|
||||||
await _identityUserManager.UpdateAsync(identityuser); // security stamp not updated
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
user = _users.UpdateUser(user);
|
user = _users.UpdateUser(user);
|
||||||
_syncManager.AddSyncEvent(_tenantManager.GetAlias(), EntityNames.User, user.UserId, SyncEventActions.Update);
|
_syncManager.AddSyncEvent(_tenantManager.GetAlias(), EntityNames.User, user.UserId, SyncEventActions.Update);
|
||||||
@ -354,15 +357,14 @@ namespace Oqtane.Managers
|
|||||||
if (!user.IsDeleted)
|
if (!user.IsDeleted)
|
||||||
{
|
{
|
||||||
var alias = _tenantManager.GetAlias();
|
var alias = _tenantManager.GetAlias();
|
||||||
var twoFactorSetting = _settings.GetSetting(EntityNames.Site, alias.SiteId, "LoginOptions:TwoFactor")?.SettingValue ?? "false";
|
string siteName = _sites.GetSite(alias.SiteId).Name;
|
||||||
var twoFactorRequired = twoFactorSetting == "required" || user.TwoFactorRequired;
|
var twoFactorRequired = _settings.GetSettingValue(EntityNames.Site, alias.SiteId, "LoginOptions:TwoFactor", "false") == "required" || user.TwoFactorRequired;
|
||||||
if (twoFactorRequired)
|
if (twoFactorRequired)
|
||||||
{
|
{
|
||||||
var token = await _identityUserManager.GenerateTwoFactorTokenAsync(identityuser, "Email");
|
var token = await _identityUserManager.GenerateTwoFactorTokenAsync(identityuser, "Email");
|
||||||
user.TwoFactorCode = token;
|
user.TwoFactorCode = token;
|
||||||
user.TwoFactorExpiry = DateTime.UtcNow.AddMinutes(10);
|
user.TwoFactorExpiry = DateTime.UtcNow.AddMinutes(10);
|
||||||
_users.UpdateUser(user);
|
_users.UpdateUser(user);
|
||||||
string siteName = _sites.GetSite(alias.SiteId).Name;
|
|
||||||
string subject = _localizer["TwoFactorEmailSubject"];
|
string subject = _localizer["TwoFactorEmailSubject"];
|
||||||
subject = subject.Replace("[SiteName]", siteName);
|
subject = subject.Replace("[SiteName]", siteName);
|
||||||
string body = _localizer["TwoFactorEmailBody"].Value;
|
string body = _localizer["TwoFactorEmailBody"].Value;
|
||||||
@ -377,7 +379,7 @@ namespace Oqtane.Managers
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (await _identityUserManager.IsEmailConfirmedAsync(identityuser))
|
if (!bool.Parse(_settings.GetSettingValue(EntityNames.Site, alias.SiteId, "LoginOptions:RequireValidEmail", "true")) || await _identityUserManager.IsEmailConfirmedAsync(identityuser))
|
||||||
{
|
{
|
||||||
user = GetUser(identityuser.UserName, alias.SiteId);
|
user = GetUser(identityuser.UserName, alias.SiteId);
|
||||||
if (user != null)
|
if (user != null)
|
||||||
@ -400,13 +402,25 @@ namespace Oqtane.Managers
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_logger.Log(LogLevel.Information, this, LogFunction.Security, "User {Username} Is Not An Active Member Of Site {SiteId}", user.Username, alias.SiteId);
|
_logger.Log(LogLevel.Information, this, LogFunction.Security, "User Login Denied - 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 Login Denied - User Email Address Not Verified For {Username}", user.Username);
|
||||||
|
|
||||||
|
// send verification email again
|
||||||
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -538,8 +552,7 @@ namespace Oqtane.Managers
|
|||||||
if (user != null)
|
if (user != null)
|
||||||
{
|
{
|
||||||
var alias = _tenantManager.GetAlias();
|
var alias = _tenantManager.GetAlias();
|
||||||
var twoFactorSetting = _settings.GetSetting(EntityNames.Site, alias.SiteId, "LoginOptions:TwoFactor")?.SettingValue ?? "false";
|
var twoFactorRequired = _settings.GetSettingValue(EntityNames.Site, alias.SiteId, "LoginOptions:TwoFactor", "false") == "required" || user.TwoFactorRequired;
|
||||||
var twoFactorRequired = twoFactorSetting == "required" || user.TwoFactorRequired;
|
|
||||||
if (twoFactorRequired && user.TwoFactorCode == token && DateTime.UtcNow < user.TwoFactorExpiry)
|
if (twoFactorRequired && user.TwoFactorCode == token && DateTime.UtcNow < user.TwoFactorExpiry)
|
||||||
{
|
{
|
||||||
user.IsAuthenticated = true;
|
user.IsAuthenticated = true;
|
||||||
|
@ -16,5 +16,6 @@ namespace Oqtane.Repository
|
|||||||
void DeleteSetting(string entityName, int settingId);
|
void DeleteSetting(string entityName, int settingId);
|
||||||
void DeleteSettings(string entityName, int entityId);
|
void DeleteSettings(string entityName, int entityId);
|
||||||
string GetSettingValue(IEnumerable<Setting> settings, string settingName, string defaultValue);
|
string GetSettingValue(IEnumerable<Setting> settings, string settingName, string defaultValue);
|
||||||
|
string GetSettingValue(string entityName, int entityId, string settingName, string defaultValue);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -180,6 +180,19 @@ namespace Oqtane.Repository
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public string GetSettingValue(string entityName, int entityId, string settingName, string defaultValue)
|
||||||
|
{
|
||||||
|
var setting = GetSetting(entityName, entityId, settingName);
|
||||||
|
if (setting != null)
|
||||||
|
{
|
||||||
|
return setting.SettingValue;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return defaultValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private bool IsMaster(string EntityName)
|
private bool IsMaster(string EntityName)
|
||||||
{
|
{
|
||||||
return (EntityName == EntityNames.ModuleDefinition || EntityName == EntityNames.Host);
|
return (EntityName == EntityNames.ModuleDefinition || EntityName == EntityNames.Host);
|
||||||
|
Reference in New Issue
Block a user