diff --git a/src/Umbraco.Web.UI.Client/src/views/users/views/users/users.html b/src/Umbraco.Web.UI.Client/src/views/users/views/users/users.html
index a0098d411c..2f623a62f2 100644
--- a/src/Umbraco.Web.UI.Client/src/views/users/views/users/users.html
+++ b/src/Umbraco.Web.UI.Client/src/views/users/views/users/users.html
@@ -502,7 +502,7 @@
{{vm.newUser.name | umbWordLimit:1}}
- has been created
+ has been invited
@@ -517,6 +517,7 @@
size="m">
u.LastLoginDate != default(DateTime) || u.EmailConfirmedDate.HasValue);
+ user = CheckUniqueUsername(userSave.Username, u => u.LastLoginDate != default || u.EmailConfirmedDate.HasValue);
+ }
+ user = CheckUniqueEmail(userSave.Email, u => u.LastLoginDate != default || u.EmailConfirmedDate.HasValue);
+
+ var userMgr = TryGetOwinContext().Result.GetBackOfficeUserManager();
+ var inviteArgs = new UserInviteEventArgs(
+ Request.TryGetHttpContext().Result.GetCurrentRequestIpAddress(),
+ performingUser: Security.GetUserId().Result,
+ userSave);
+ userMgr.RaiseSendingUserInvite(inviteArgs);
+
+ // If the event is handled then return the data
+ if (inviteArgs.InviteHandled)
+ {
+ // if no local user was created then map the args manually for the UI
+ if (inviteArgs.User == null)
+ {
+ return new UserDisplay
+ {
+ Name = userSave.Name,
+ Email = userSave.Email,
+ Username = userSave.Username
+ };
+ }
+ else
+ {
+ //map the save info over onto the user
+ user = Mapper.Map(userSave, user);
+ //ensure the invited date is set
+ user.InvitedDate = DateTime.Now;
+ //Save the updated user
+ Services.UserService.Save(user);
+ return Mapper.Map(user);
+ }
+ }
+
+ if (EmailSender.CanSendRequiredEmail == false)
+ {
+ throw new HttpResponseException(
+ Request.CreateNotificationValidationErrorResponse("No Email server is configured"));
}
- 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);
diff --git a/src/Umbraco.Web/Security/IdentityAuditEventArgs.cs b/src/Umbraco.Web/Security/IdentityAuditEventArgs.cs
index dbd20f5c3b..23e570dd40 100644
--- a/src/Umbraco.Web/Security/IdentityAuditEventArgs.cs
+++ b/src/Umbraco.Web/Security/IdentityAuditEventArgs.cs
@@ -5,19 +5,6 @@ using Umbraco.Core.Security;
namespace Umbraco.Web.Security
{
- public class UserInviteEventArgs : IdentityAuditEventArgs
- {
- public UserInviteEventArgs(string ipAddress, int performingUser, string comment = null)
- : base(AuditEvent.SendingUserInvite, ipAddress, comment, performingUser)
- {
- }
-
- ///
- /// If event handler sets this to true it indicates that Umbraco will no try to send the invite itself
- ///
- public bool InviteHandled { get; set; }
- }
-
///
/// This class is used by events raised from the BackofficeUserManager
///
diff --git a/src/Umbraco.Web/Security/UserInviteEventArgs.cs b/src/Umbraco.Web/Security/UserInviteEventArgs.cs
new file mode 100644
index 0000000000..2cd0994c3c
--- /dev/null
+++ b/src/Umbraco.Web/Security/UserInviteEventArgs.cs
@@ -0,0 +1,30 @@
+using Umbraco.Core.Models.Membership;
+using Umbraco.Web.Models.ContentEditing;
+
+namespace Umbraco.Web.Security
+{
+ public class UserInviteEventArgs : IdentityAuditEventArgs
+ {
+ public UserInviteEventArgs(string ipAddress, int performingUser, UserInvite invitedUser, string comment = null)
+ : base(AuditEvent.SendingUserInvite, ipAddress, comment, performingUser)
+ {
+ InvitedUser = invitedUser ?? throw new System.ArgumentNullException(nameof(invitedUser));
+ }
+
+ public UserInvite InvitedUser { get; }
+
+ ///
+ /// If event handler sets this to true it indicates that Umbraco will no try to send the invite itself
+ ///
+ public bool InviteHandled { get; set; }
+
+ ///
+ /// If the event handler has created a local user then this is the result which is used to return the details to the UI
+ ///
+ ///
+ /// It is optional to create a local user in this event. In many cases the custom invite flow will be for external logins and then local users will
+ /// be created via the auto-linking process.
+ ///
+ public IUser User { get; set; }
+ }
+}
diff --git a/src/Umbraco.Web/Umbraco.Web.csproj b/src/Umbraco.Web/Umbraco.Web.csproj
index ef4f7a4a53..e3c573bf08 100755
--- a/src/Umbraco.Web/Umbraco.Web.csproj
+++ b/src/Umbraco.Web/Umbraco.Web.csproj
@@ -261,6 +261,7 @@
+