Skip to content

Commit 029a261

Browse files
Improve functionality for external member logins (#11855)
* Bugfix - Take ufprt from form data if the request has form content type, otherwise fallback to use the query * External linking for members * Changed migration to reuse old table * removed unnecessary web.config files * Cleanup * Extracted class to own file * Clean up * Rollback changes to Umbraco.Web.UI.csproj * Fixed migration for SqlCE * Change notification handler to be on deleted * Update src/Umbraco.Infrastructure/Security/MemberUserStore.cs Co-authored-by: Mole <[email protected]> * Fixed issue with errors not shown on member linking * fixed issue with errors * clean up * Fix issue where external logins could not be used to upgrade Umbraco, because the externalLogin table was expected to look different. (Like after the migration) * Fixed issue in Ignore legacy column now using result column. Co-authored-by: Mole <[email protected]>
1 parent 229ca98 commit 029a261

File tree

53 files changed

+1651
-184
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

53 files changed

+1651
-184
lines changed

src/Umbraco.Core/Constants-Security.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ public static class Security
5050
/// providers need to be setup differently and each auth type for the back office will be prefixed with this value
5151
/// </remarks>
5252
public const string BackOfficeExternalAuthenticationTypePrefix = "Umbraco.";
53+
public const string MemberExternalAuthenticationTypePrefix = "UmbracoMembers.";
5354

5455
public const string StartContentNodeIdClaimType = "http://umbraco.org/2015/02/identity/claims/backoffice/startcontentnode";
5556
public const string StartMediaNodeIdClaimType = "http://umbraco.org/2015/02/identity/claims/backoffice/startmedianode";

src/Umbraco.Core/Extensions/ClaimsIdentityExtensions.cs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,19 @@ public static string GetUserName(this IIdentity identity)
6262
return username;
6363
}
6464

65+
public static string GetEmail(this IIdentity identity)
66+
{
67+
if (identity == null) throw new ArgumentNullException(nameof(identity));
68+
69+
string email = null;
70+
if (identity is ClaimsIdentity claimsIdentity)
71+
{
72+
email = claimsIdentity.FindFirstValue(ClaimTypes.Email);
73+
}
74+
75+
return email;
76+
}
77+
6578
/// <summary>
6679
/// Returns the first claim value found in the <see cref="ClaimsIdentity"/> for the given claimType
6780
/// </summary>
Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,29 @@
1+
using System;
12
using System.Collections.Generic;
23
using Umbraco.Cms.Core.Security;
34

45
namespace Umbraco.Cms.Core.Persistence.Repositories
56
{
7+
68
public interface IExternalLoginRepository : IReadWriteQueryRepository<int, IIdentityUserLogin>, IQueryRepository<IIdentityUserToken>
79
{
10+
811
/// <summary>
912
/// Replaces all external login providers for the user
1013
/// </summary>
1114
/// <param name="userId"></param>
1215
/// <param name="logins"></param>
16+
[Obsolete("Use method that takes guid as param from IExternalLoginWithKeyRepository")]
1317
void Save(int userId, IEnumerable<IExternalLogin> logins);
1418

1519
/// <summary>
1620
/// Replaces all external login provider tokens for the providers specified for the user
1721
/// </summary>
1822
/// <param name="userId"></param>
1923
/// <param name="tokens"></param>
24+
[Obsolete("Use method that takes guid as param from IExternalLoginWithKeyRepository")]
2025
void Save(int userId, IEnumerable<IExternalLoginToken> tokens);
21-
26+
[Obsolete("Use method that takes guid as param from IExternalLoginWithKeyRepository")]
2227
void DeleteUserLogins(int memberId);
2328
}
2429
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using Umbraco.Cms.Core.Security;
4+
5+
namespace Umbraco.Cms.Core.Persistence.Repositories
6+
{
7+
8+
/// <summary>
9+
/// Repository for external logins with Guid as key, so it can be shared for members and users
10+
/// </summary>
11+
public interface IExternalLoginWithKeyRepository : IReadWriteQueryRepository<int, IIdentityUserLogin>, IQueryRepository<IIdentityUserToken>
12+
{
13+
/// <summary>
14+
/// Replaces all external login providers for the user/member key
15+
/// </summary>
16+
void Save(Guid userOrMemberKey, IEnumerable<IExternalLogin> logins);
17+
18+
/// <summary>
19+
/// Replaces all external login provider tokens for the providers specified for the user/member key
20+
/// </summary>
21+
void Save(Guid userOrMemberKey, IEnumerable<IExternalLoginToken> tokens);
22+
23+
/// <summary>
24+
/// Deletes all external logins for the specified the user/member key
25+
/// </summary>
26+
void DeleteUserLogins(Guid userOrMemberKey);
27+
}
28+
}

src/Umbraco.Core/Security/IIdentityUserLogin.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ public interface IIdentityUserLogin : IEntity, IRememberBeingDirty
1919
string ProviderKey { get; set; }
2020

2121
/// <summary>
22-
/// Gets or sets user Id for the user who owns this login
22+
/// Gets or sets user or member key (Guid) for the user/member who owns this login
2323
/// </summary>
2424
string UserId { get; set; } // TODO: This should be able to be used by both users and members
2525

src/Umbraco.Core/Services/IExternalLoginService.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
using System;
12
using System.Collections.Generic;
23
using Umbraco.Cms.Core.Security;
34

@@ -6,6 +7,7 @@ namespace Umbraco.Cms.Core.Services
67
/// <summary>
78
/// Used to store the external login info
89
/// </summary>
10+
[Obsolete("Use IExternalLoginServiceWithKey. This will be removed in Umbraco 10")]
911
public interface IExternalLoginService : IService
1012
{
1113
/// <summary>
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using Umbraco.Cms.Core.Security;
4+
5+
namespace Umbraco.Cms.Core.Services
6+
{
7+
public interface IExternalLoginWithKeyService : IService
8+
{
9+
/// <summary>
10+
/// Returns all user logins assigned
11+
/// </summary>
12+
IEnumerable<IIdentityUserLogin> GetExternalLogins(Guid userOrMemberKey);
13+
14+
/// <summary>
15+
/// Returns all user login tokens assigned
16+
/// </summary>
17+
IEnumerable<IIdentityUserToken> GetExternalLoginTokens(Guid userOrMemberKey);
18+
19+
/// <summary>
20+
/// Returns all logins matching the login info - generally there should only be one but in some cases
21+
/// there might be more than one depending on if an administrator has been editing/removing members
22+
/// </summary>
23+
IEnumerable<IIdentityUserLogin> Find(string loginProvider, string providerKey);
24+
25+
/// <summary>
26+
/// Saves the external logins associated with the user
27+
/// </summary>
28+
/// <param name="userOrMemberKey">
29+
/// The user or member key associated with the logins
30+
/// </param>
31+
/// <param name="logins"></param>
32+
/// <remarks>
33+
/// This will replace all external login provider information for the user
34+
/// </remarks>
35+
void Save(Guid userOrMemberKey, IEnumerable<IExternalLogin> logins);
36+
37+
/// <summary>
38+
/// Saves the external login tokens associated with the user
39+
/// </summary>
40+
/// <param name="userId">
41+
/// The user or member key associated with the logins
42+
/// </param>
43+
/// <param name="tokens"></param>
44+
/// <remarks>
45+
/// This will replace all external login tokens for the user
46+
/// </remarks>
47+
void Save(Guid userOrMemberKey,IEnumerable<IExternalLoginToken> tokens);
48+
49+
/// <summary>
50+
/// Deletes all user logins - normally used when a member is deleted
51+
/// </summary>
52+
void DeleteUserLogins(Guid userOrMemberKey);
53+
}
54+
}

src/Umbraco.Infrastructure/DependencyInjection/UmbracoBuilder.Repositories.cs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
using Microsoft.Extensions.DependencyInjection;
12
using Umbraco.Cms.Core.DependencyInjection;
23
using Umbraco.Cms.Core.Persistence.Repositories;
34
using Umbraco.Cms.Infrastructure.Persistence.Repositories.Implement;
@@ -29,7 +30,9 @@ internal static IUmbracoBuilder AddRepositories(this IUmbracoBuilder builder)
2930
builder.Services.AddUnique<IDocumentTypeContainerRepository, DocumentTypeContainerRepository>();
3031
builder.Services.AddUnique<IDomainRepository, DomainRepository>();
3132
builder.Services.AddUnique<IEntityRepository, EntityRepository>();
32-
builder.Services.AddUnique<IExternalLoginRepository, ExternalLoginRepository>();
33+
builder.Services.AddUnique<ExternalLoginRepository>();
34+
builder.Services.AddUnique<IExternalLoginRepository>(factory => factory.GetRequiredService<ExternalLoginRepository>());
35+
builder.Services.AddUnique<IExternalLoginWithKeyRepository>(factory => factory.GetRequiredService<ExternalLoginRepository>());
3336
builder.Services.AddUnique<ILanguageRepository, LanguageRepository>();
3437
builder.Services.AddUnique<IMacroRepository, MacroRepository>();
3538
builder.Services.AddUnique<IMediaRepository, MediaRepository>();

src/Umbraco.Infrastructure/DependencyInjection/UmbracoBuilder.Services.cs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,13 @@
88
using Umbraco.Cms.Core.Cache;
99
using Umbraco.Cms.Core.Configuration.Models;
1010
using Umbraco.Cms.Core.DependencyInjection;
11+
using Umbraco.Cms.Core.Events;
1112
using Umbraco.Cms.Core.Hosting;
1213
using Umbraco.Cms.Core.IO;
1314
using Umbraco.Cms.Core.Packaging;
15+
using Umbraco.Cms.Core.Persistence.Repositories;
1416
using Umbraco.Cms.Core.Routing;
17+
using Umbraco.Cms.Core.Scoping;
1518
using Umbraco.Cms.Core.Services;
1619
using Umbraco.Cms.Core.Services.Implement;
1720
using Umbraco.Cms.Infrastructure.Packaging;
@@ -64,7 +67,14 @@ internal static IUmbracoBuilder AddServices(this IUmbracoBuilder builder)
6467
builder.Services.AddUnique<IMemberTypeService, MemberTypeService>();
6568
builder.Services.AddUnique<IMemberGroupService, MemberGroupService>();
6669
builder.Services.AddUnique<INotificationService, NotificationService>();
67-
builder.Services.AddUnique<IExternalLoginService, ExternalLoginService>();
70+
builder.Services.AddUnique<ExternalLoginService>(factory => new ExternalLoginService(
71+
factory.GetRequiredService<IScopeProvider>(),
72+
factory.GetRequiredService<ILoggerFactory>(),
73+
factory.GetRequiredService<IEventMessagesFactory>(),
74+
factory.GetRequiredService<IExternalLoginWithKeyRepository>()
75+
));
76+
builder.Services.AddUnique<IExternalLoginService>(factory => factory.GetRequiredService<ExternalLoginService>());
77+
builder.Services.AddUnique<IExternalLoginWithKeyService>(factory => factory.GetRequiredService<ExternalLoginService>());
6878
builder.Services.AddUnique<IRedirectUrlService, RedirectUrlService>();
6979
builder.Services.AddUnique<IConsentService, ConsentService>();
7080
builder.Services.AddTransient(SourcesFactory);

src/Umbraco.Infrastructure/Migrations/Upgrade/UmbracoPlan.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
using Umbraco.Cms.Infrastructure.Migrations.Upgrade.V_9_0_0;
1616
using Umbraco.Cms.Infrastructure.Migrations.Upgrade.V_9_1_0;
1717
using Umbraco.Cms.Infrastructure.Migrations.Upgrade.V_9_2_0;
18+
using Umbraco.Cms.Infrastructure.Migrations.Upgrade.V_9_3_0;
1819
using Umbraco.Extensions;
1920

2021
namespace Umbraco.Cms.Infrastructure.Migrations.Upgrade
@@ -269,6 +270,11 @@ protected void DefinePlan()
269270
To<AddUserGroup2NodeTable>("{0571C395-8F0B-44E9-8E3F-47BDD08D817B}");
270271
To<AddDefaultForNotificationsToggle>("{AD3D3B7F-8E74-45A4-85DB-7FFAD57F9243}");
271272
To<MovePackageXMLToDb>("{A2F22F17-5870-4179-8A8D-2362AA4A0A5F}");
273+
274+
275+
// TO 9.3.0
276+
To<UpdateExternalLoginToUseKeyInsteadOfId>("{CA7A1D9D-C9D4-4914-BC0A-459E7B9C3C8C}");
277+
272278
}
273279
}
274280
}

0 commit comments

Comments
 (0)