removes custom invite link, adds ability in logout event to specify an external logout get redirect for external logins.

This commit is contained in:
Shannon
2020-08-28 02:10:08 +10:00
parent d43e36596e
commit 4f1d9997d5
10 changed files with 70 additions and 62 deletions

View File

@@ -47,25 +47,9 @@ function externalLoginInfoService(externalLoginInfo, umbRequestHelper) {
}
}
/**
* If there is any external login providers with deny local login, check if any have a custom invite link and return it
* @param {any} provider optional to get the invite link directly from the provider, else will return the first one found (if any)
*/
function getUserInviteLink(provider) {
if (!provider) {
var denyLocalLoginProviders = _.filter(externalLoginInfo.providers, x => x.properties.UmbracoBackOfficeExternalLoginOptions.DenyLocalLogin);
var withInviteLink = _.filter(denyLocalLoginProviders, x => x.properties.UmbracoBackOfficeExternalLoginOptions.CustomUserInviteLink);
return withInviteLink.length > 0 ? withInviteLink[0].properties.UmbracoBackOfficeExternalLoginOptions.CustomUserInviteLink : null;
}
else {
return provider.properties.UmbracoBackOfficeExternalLoginOptions.CustomUserInviteLink;
}
}
return {
hasDenyLocalLogin: hasDenyLocalLogin,
getLoginProviders: getLoginProviders,
getUserInviteLink: getUserInviteLink,
getExternalLoginProviderView: getExternalLoginProviderView
};
}

View File

@@ -1,5 +1,5 @@
angular.module('umbraco.services')
.factory('userService', function ($rootScope, eventsService, $q, $location, requestRetryQueue, authResource, emailMarketingResource, $timeout, angularHelper) {
.factory('userService', function ($rootScope, eventsService, $q, $location, $window, requestRetryQueue, authResource, emailMarketingResource, $timeout, angularHelper) {
var currentUser = null;
var lastUserId = null;
@@ -218,8 +218,14 @@ angular.module('umbraco.services')
return authResource.performLogout()
.then(function (data) {
userAuthExpired();
//done!
return null;
if (data && data.signOutRedirectUrl) {
$window.location.replace(data.signOutRedirectUrl);
}
else {
//done!
return null;
}
});
},

View File

@@ -80,10 +80,9 @@ angular.module("umbraco")
//updateTimeout();
authResource.getCurrentUserLinkedLogins().then(function(logins) {
//reset all to be un-linked
for (var provider in $scope.externalLoginProviders) {
$scope.externalLoginProviders[provider].linkedProviderKey = undefined;
}
$scope.externalLoginProviders.forEach(provider => provider.linkedProviderKey = undefined);
//set the linked logins
for (var login in logins) {

View File

@@ -71,47 +71,38 @@
vm.denyLocalLogin = externalLoginInfoService.hasDenyLocalLogin();
// No default buttons with denyLocalLogin
// Don't show the invite button if no email is configured
if (!vm.denyLocalLogin) {
if (Umbraco.Sys.ServerVariables.umbracoSettings.showUserInvite) {
vm.defaultButton = {
labelKey: "user_inviteUser",
handler: function () {
vm.setUsersViewState('inviteUser');
}
};
vm.subButtons = [
{
labelKey: "user_createUser",
handler: function () {
vm.setUsersViewState('createUser');
}
}
];
}
else {
vm.defaultButton = {
// returns the object representing the user create button, returns null if deny local login is true
function getCreateUserButton() {
if (!vm.denyLocalLogin) {
return {
labelKey: "user_createUser",
handler: function () {
vm.setUsersViewState('createUser');
}
};
}
return null;
}
else {
// if deny local login then check if there's an invite link in the config
var customInviteLink = externalLoginInfoService.getUserInviteLink();
if (customInviteLink) {
vm.defaultButton = {
type: "link",
labelKey: "user_inviteUser",
href: customInviteLink,
hrefTarget: "_blank"
};
// No default buttons with denyLocalLogin
// Don't show the invite button if no email is configured
if (Umbraco.Sys.ServerVariables.umbracoSettings.showUserInvite) {
vm.defaultButton = {
labelKey: "user_inviteUser",
handler: function () {
vm.setUsersViewState('inviteUser');
}
};
var createUserBtn = getCreateUserButton();
if (createUserBtn) {
vm.subButtons = [createUserBtn];
}
}
else {
vm.defaultButton = getCreateUserButton();
}
vm.toggleFilter = toggleFilter;
vm.setUsersViewState = setUsersViewState;

View File

@@ -210,7 +210,12 @@ namespace Umbraco.Web.Editors
public async Task<Dictionary<string, string>> GetCurrentUserLinkedLogins()
{
var identityUser = await UserManager.FindByIdAsync(UmbracoContext.Security.GetUserId().ResultOr(0));
return identityUser.Logins.ToDictionary(x => x.LoginProvider, x => x.ProviderKey);
var result = new Dictionary<string, string>();
foreach (var l in identityUser.Logins)
{
result[l.LoginProvider] = l.ProviderKey;
}
return result;
}
/// <summary>
@@ -483,7 +488,12 @@ namespace Umbraco.Web.Editors
if (UserManager != null)
{
int.TryParse(User.Identity.GetUserId(), out var userId);
UserManager.RaiseLogoutSuccessEvent(userId);
var args = UserManager.RaiseLogoutSuccessEvent(userId);
if (!args.SignOutRedirectUrl.IsNullOrWhiteSpace())
return Request.CreateResponse(new
{
signOutRedirectUrl = args.SignOutRedirectUrl
});
}
return Request.CreateResponse(HttpStatusCode.OK);

View File

@@ -34,11 +34,6 @@ namespace Umbraco.Web.Security
/// </summary>
public bool DenyLocalLogin { get; set; }
/// <summary>
/// If specified and <see cref="DenyLocalLogin"/> is true then the user invite button in the back office will link through to this custom URL
/// </summary>
public string CustomUserInviteLink { get; set; }
/// <summary>
/// When specified this will automatically redirect to the OAuth login provider instead of prompting the user to click on the OAuth button first.
/// </summary>

View File

@@ -610,9 +610,11 @@ namespace Umbraco.Web.Security
OnLoginSuccess(new IdentityAuditEventArgs(AuditEvent.LoginSucces, GetCurrentRequestIpAddress(), affectedUser: userId));
}
internal void RaiseLogoutSuccessEvent(int userId)
internal SignOutAuditEventArgs RaiseLogoutSuccessEvent(int userId)
{
OnLogoutSuccess(new IdentityAuditEventArgs(AuditEvent.LogoutSuccess, GetCurrentRequestIpAddress(), affectedUser: userId));
var args = new SignOutAuditEventArgs(AuditEvent.LogoutSuccess, GetCurrentRequestIpAddress(), affectedUser: userId);
OnLogoutSuccess(args);
return args;
}
internal void RaisePasswordChangedEvent(int userId)

View File

@@ -4,6 +4,7 @@ using Umbraco.Core.Security;
namespace Umbraco.Web.Security
{
/// <summary>
/// This class is used by events raised from the BackofficeUserManager
/// </summary>

View File

@@ -0,0 +1,19 @@
namespace Umbraco.Web.Security
{
/// <summary>
/// Event args used when signing out
/// </summary>
public class SignOutAuditEventArgs : IdentityAuditEventArgs
{
public SignOutAuditEventArgs(AuditEvent action, string ipAddress, string comment = null, int performingUser = -1, int affectedUser = -1)
: base(action, ipAddress, comment, performingUser, affectedUser)
{
}
/// <summary>
/// Allows event handlers to set a GET absolute URL to be redirected to after successful logout out of the back office. This
/// can be used for external login providers.
/// </summary>
public string SignOutRedirectUrl { get; set; }
}
}

View File

@@ -260,6 +260,7 @@
<Compile Include="Security\BackOfficeExternalLoginProviderErrorMiddlware.cs" />
<Compile Include="Security\BackOfficeExternalLoginProviderErrors.cs" />
<Compile Include="Security\BackOfficeExternalLoginProviderOptions.cs" />
<Compile Include="Security\SignOutAuditEventArgs.cs" />
<Compile Include="Services\DashboardService.cs" />
<Compile Include="Services\IDashboardService.cs" />
<Compile Include="Models\Link.cs" />