Gets invite and create user working with new setting and allowing specifying a separate username.

This commit is contained in:
Shannon
2017-09-05 23:31:26 +10:00
parent 456b5fcee0
commit f3f31f2569
7 changed files with 81 additions and 26 deletions

View File

@@ -47,7 +47,7 @@
<input
type="text"
localize="placeholder"
placeholder="@placeholders_entername"
placeholder="@placeholders_enterusername"
class="input-block-level"
ng-model="vm.user.username"
umb-auto-focus name="username"

View File

@@ -26,6 +26,8 @@
vm.selectedBulkUserGroups = [];
vm.usernameIsEmail = Umbraco.Sys.ServerVariables.umbracoSettings.usernameIsEmail;
vm.allowDisableUser = true;
vm.allowEnableUser = true;
vm.allowUnlockUser = true;

View File

@@ -325,6 +325,13 @@
<span class="help-inline" val-msg-for="name" val-toggle-msg="valServerField"></span>
</umb-control-group>
<umb-control-group label="@general_username" label-for="username" required="true" ng-if="!vm.usernameIsEmail">
<input type="text" name="username" localize="placeholder" placeholder="@placeholders_enterusername" class="input-block-level"
ng-model="vm.newUser.username" val-server-field="Username" ng-required="vm.usernameIsEmail" />
<span class="help-inline" val-msg-for="username" val-toggle-msg="required"><localize key="general_required">Required</localize></span>
<span class="help-inline" val-msg-for="username" val-toggle-msg="valServerField"></span>
</umb-control-group>
<umb-control-group label="@general_email" label-for="email" required="true">
<input type="email" name="email" localize="placeholder" placeholder="@placeholders_enteremail" class="input-block-level"
ng-model="vm.newUser.email" required val-email val-server-field="Email" />

View File

@@ -81,14 +81,14 @@
<key alias="domainUpdated">Domain '%0%' has been updated</key>
<key alias="orEdit">Edit Current Domains</key>
<key alias="domainHelp">
<![CDATA[Valid domain names are: "example.com", "www.example.com", "example.com:8080" or
"https://www.example.com/". One-level paths in domains are supported, eg. "example.com/en". However, they
<![CDATA[Valid domain names are: "example.com", "www.example.com", "example.com:8080" or
"https://www.example.com/". One-level paths in domains are supported, eg. "example.com/en". However, they
should be avoided. Better use the culture setting above.]]>
</key>
<key alias="inherit">Inherit</key>
<key alias="setLanguage">Culture</key>
<key alias="setLanguageHelp">
<![CDATA[Set the culture for nodes below the current node,<br /> or inherit culture from parent nodes. Will also apply<br />
<![CDATA[Set the culture for nodes below the current node,<br /> or inherit culture from parent nodes. Will also apply<br />
to the current node, unless a domain below applies too.]]>
</key>
<key alias="setDomains">Domains</key>
@@ -339,11 +339,11 @@
<key alias="tableColumns">Number of columns</key>
<key alias="tableRows">Number of rows</key>
<key alias="templateContentAreaHelp">
<![CDATA[<strong>Set a placeholder id</strong> by setting an ID on your placeholder you can inject content into this template from child templates,
<![CDATA[<strong>Set a placeholder id</strong> by setting an ID on your placeholder you can inject content into this template from child templates,
by referring this ID using a <code>&lt;asp:content /&gt;</code> element.]]>
</key>
<key alias="templateContentPlaceHolderHelp">
<![CDATA[<strong>Select a placeholder id</strong> from the list below. You can only
<![CDATA[<strong>Select a placeholder id</strong> from the list below. You can only
choose Id's from the current template's master.]]>
</key>
<key alias="thumbnailimageclickfororiginal">Click on the image to see full size</key>
@@ -380,15 +380,15 @@
</area>
<area alias="dictionaryItem">
<key alias="description">
<![CDATA[
Edit the different language versions for the dictionary item '<em>%0%</em>' below<br/>You can add additional languages under the 'languages' in the menu on the left
<![CDATA[
Edit the different language versions for the dictionary item '<em>%0%</em>' below<br/>You can add additional languages under the 'languages' in the menu on the left
]]>
</key>
<key alias="displayName">Culture Name</key>
<key alias="changeKey">Edit the key of the dictionary item.</key>
<key alias="changeKeyError">
<![CDATA[
The key '%0%' already exists.
<![CDATA[
The key '%0%' already exists.
]]>
</key>
</area>
@@ -398,6 +398,8 @@
<key alias="confirmPassword">Confirm your password</key>
<key alias="nameentity">Name the %0%...</key>
<key alias="entername">Enter a name...</key>
<key alias="enteremail">Enter an email...</key>
<key alias="enterusername">Enter a username...</key>
<key alias="label">Label...</key>
<key alias="enterDescription">Enter a description...</key>
<key alias="search">Type to search...</key>

View File

@@ -400,6 +400,7 @@
<key alias="nameentity">Name the %0%...</key>
<key alias="entername">Enter a name...</key>
<key alias="enteremail">Enter an email...</key>
<key alias="enterusername">Enter a username...</key>
<key alias="label">Label...</key>
<key alias="enterDescription">Enter a description...</key>
<key alias="search">Type to search...</key>

View File

@@ -265,13 +265,18 @@ namespace Umbraco.Web.Editors
{
throw new HttpResponseException(Request.CreateErrorResponse(HttpStatusCode.BadRequest, ModelState));
}
var existing = Services.UserService.GetByEmail(userSave.Email);
if (existing != null)
if (UmbracoConfig.For.UmbracoSettings().Security.UsernameIsEmail)
{
ModelState.AddModelError("Email", "A user with the email already exists");
throw new HttpResponseException(Request.CreateErrorResponse(HttpStatusCode.BadRequest, ModelState));
//ensure they are the same if we're using it
userSave.Username = userSave.Email;
}
else
{
//first validate the username if were showing it
CheckUniqueUsername(userSave.Username, null);
}
CheckUniqueEmail(userSave.Email, null);
//Perform authorization here to see if the current user can actually save this user with the info being requested
var authHelper = new UserEditorAuthorizationHelper(Services.ContentService, Services.MediaService, Services.UserService, Services.EntityService);
@@ -283,7 +288,7 @@ namespace Umbraco.Web.Editors
//we want to create the user with the UserManager, this ensures the 'empty' (special) password
//format is applied without us having to duplicate that logic
var identityUser = BackOfficeIdentityUser.CreateNew(userSave.Email, userSave.Email, GlobalSettings.DefaultUILanguage);
var identityUser = BackOfficeIdentityUser.CreateNew(userSave.Username, userSave.Email, GlobalSettings.DefaultUILanguage);
identityUser.Name = userSave.Name;
var created = await UserManager.CreateAsync(identityUser);
@@ -345,7 +350,7 @@ namespace Umbraco.Web.Editors
{
throw new HttpResponseException(Request.CreateErrorResponse(HttpStatusCode.BadRequest, ModelState));
}
var hasSmtp = GlobalSettings.HasSmtpServerConfigured(RequestContext.VirtualPathRoot);
if (hasSmtp == false)
{
@@ -353,13 +358,19 @@ namespace Umbraco.Web.Editors
Request.CreateNotificationValidationErrorResponse("No Email server is configured"));
}
var user = Services.UserService.GetByEmail(userSave.Email);
if (user != null && (user.LastLoginDate != default(DateTime) || user.EmailConfirmedDate.HasValue))
IUser user;
if (UmbracoConfig.For.UmbracoSettings().Security.UsernameIsEmail)
{
ModelState.AddModelError("Email", "A user with the email already exists");
throw new HttpResponseException(Request.CreateErrorResponse(HttpStatusCode.BadRequest, ModelState));
//ensure it's the same
userSave.Username = userSave.Email;
}
else
{
//first validate the username if we're showing it
user = CheckUniqueUsername(userSave.Username, u => u.LastLoginDate != default(DateTime) || u.EmailConfirmedDate.HasValue);
}
user = CheckUniqueEmail(userSave.Email, u => u.LastLoginDate != default(DateTime) || u.EmailConfirmedDate.HasValue);
//Perform authorization here to see if the current user can actually save this user with the info being requested
var authHelper = new UserEditorAuthorizationHelper(Services.ContentService, Services.MediaService, Services.UserService, Services.EntityService);
var canSaveUser = authHelper.IsAuthorized(Security.CurrentUser, user, null, null, userSave.UserGroups);
@@ -372,7 +383,7 @@ namespace Umbraco.Web.Editors
{
//we want to create the user with the UserManager, this ensures the 'empty' (special) password
//format is applied without us having to duplicate that logic
var identityUser = BackOfficeIdentityUser.CreateNew(userSave.Email, userSave.Email, GlobalSettings.DefaultUILanguage);
var identityUser = BackOfficeIdentityUser.CreateNew(userSave.Username, userSave.Email, GlobalSettings.DefaultUILanguage);
identityUser.Name = userSave.Name;
var created = await UserManager.CreateAsync(identityUser);
@@ -402,7 +413,31 @@ namespace Umbraco.Web.Editors
return display;
}
private IUser CheckUniqueEmail(string email, Func<IUser, bool> extraCheck)
{
var user = Services.UserService.GetByEmail(email);
if (user != null && (extraCheck == null || extraCheck(user)))
{
ModelState.AddModelError("Email", "A user with the email already exists");
throw new HttpResponseException(Request.CreateErrorResponse(HttpStatusCode.BadRequest, ModelState));
}
return user;
}
private IUser CheckUniqueUsername(string username, Func<IUser, bool> extraCheck)
{
var user = Services.UserService.GetByUsername(username);
if (user != null && (extraCheck == null || extraCheck(user)))
{
ModelState.AddModelError(
UmbracoConfig.For.UmbracoSettings().Security.UsernameIsEmail ? "Email" : "Username",
"A user with the username already exists");
throw new HttpResponseException(Request.CreateErrorResponse(HttpStatusCode.BadRequest, ModelState));
}
return user;
}
private HttpContextBase EnsureHttpContext()
{
var attempt = this.TryGetHttpContext();

View File

@@ -2,6 +2,8 @@ using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Runtime.Serialization;
using Umbraco.Core;
using Umbraco.Core.Configuration;
namespace Umbraco.Web.Models.ContentEditing
{
@@ -18,7 +20,10 @@ namespace Umbraco.Web.Models.ContentEditing
[DataMember(Name = "email", IsRequired = true)]
[Required]
[EmailAddress]
public string Email { get; set; }
public string Email { get; set; }
[DataMember(Name = "username")]
public string Username { get; set; }
[DataMember(Name = "message")]
public string Message { get; set; }
@@ -26,7 +31,10 @@ namespace Umbraco.Web.Models.ContentEditing
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
if (UserGroups.Any() == false)
yield return new ValidationResult("A user must be assigned to at least one group", new[] { "UserGroups" });
yield return new ValidationResult("A user must be assigned to at least one group", new[] { "UserGroups" });
if (UmbracoConfig.For.UmbracoSettings().Security.UsernameIsEmail == false && Username.IsNullOrWhiteSpace())
yield return new ValidationResult("A username cannot be empty", new[] { "Username" });
}
}
}