V11/feature/update to dotnet 7 (#12712)

* Update projects to .NET 7

* Fix nullability errors

* Fix up pipelines to run 7.0

* Update langversion to preview

* Revert "Fix up pipelines to run 7.0"

This reverts commit d0fa8d01b8126a4eaa59832a3814a567705419ae.

* Fix up pipelines again, this time without indentation changes

* Include preview versions

* Versions not Version

* Fix ModelTypeTests

* Fix MemberPasswordHasherTests

Microsoft wants to use SHA512 instead of SHA256, so our old hashes will return SuccessRehashNeeded now

* Use dotnet cli instead of nuget restore

* Update src/Umbraco.Web.UI/Umbraco.Web.UI.csproj

* Update dependencies

* Fix nullability issues

* Fix unit test

* Fix nullability in ChangingPasswordModel

OldPassword can be null, if we're changing the password with password reset enabled. Additionally, we might as well use the new required keyword instead of supressing null.

* Use required keyword instead of supressing null

* Fix up pipelines again

* fix up spelling-error

* Use dotnet cli instead of nuget restore

* Fix up another NuGet command

* Use dotnet version 7 before building

* Include preview versions

* Remove condition

* Use dotnet 7 before running powershell script

* Update templates to .net 7

* Download version 7 before running linux container

* Move use dotnet 7 even earlier in E2E process

* Remove dotnet 7

* Reintroduce .NET 7 task

* Update linux docker container and remove dotnet 7 from yml

* Fix up dockerfile with ARG

* Fix up docker file with nightly builds of dotnet 7

* Reintroduce dotnet 7 so windows can use it

* Use aspnet 7 in docker

Co-authored-by: Nikolaj <nikolajlauridsen@protonmail.ch>
Co-authored-by: Zeegaan <nge@umbraco.dk>
This commit is contained in:
Nikolaj Geisle
2022-08-23 11:31:05 +02:00
committed by GitHub
parent 100ebf5c7f
commit 1b5225f4cd
90 changed files with 496 additions and 368 deletions

View File

@@ -64,6 +64,11 @@ stages:
gulpFile: src/Umbraco.Web.UI.Client/gulpfile.js
targets: coreBuild
workingDirectory: src/Umbraco.Web.UI.Client
- task: UseDotNet@2
displayName: Use .Net 7.x
inputs:
version: 7.x
includePreviewVersions: true
- task: DotNetCoreCLI@2
displayName: Run dotnet build
inputs:
@@ -228,10 +233,10 @@ stages:
artifact: build_output
path: $(Build.SourcesDirectory)
- task: UseDotNet@2
condition: and(succeeded(), eq(variables['Agent.OS'], 'Darwin')) # net6 already on the other images
displayName: Use net6
displayName: Use net7
inputs:
version: 6.x
version: 7.x
includePreviewVersions: true
- task: DotNetCoreCLI@2
displayName: Run dotnet test
inputs:
@@ -264,10 +269,10 @@ stages:
artifact: build_output
path: $(Build.SourcesDirectory)
- task: UseDotNet@2
displayName: Use net6
condition: and(succeeded(), eq(variables['Agent.OS'], 'Darwin')) # net6 already on the other images
displayName: Use net7
inputs:
version: 6.x
version: 7.x
includePreviewVersions: true
- task: DotNetCoreCLI@2
displayName: Run dotnet test
inputs:
@@ -397,6 +402,11 @@ stages:
- powershell: Invoke-Sqlcmd -Query "CREATE DATABASE $env:UmbracoDatabaseName" -ServerInstance $env:UmbracoDatabaseServer
displayName: Create database (Windows only)
condition: and(succeeded(), eq(variables['Agent.OS'], 'Windows_NT'))
- task: UseDotNet@2
displayName: Use .Net 7.x
inputs:
version: 7.x
includePreviewVersions: true
# Linux containers smooth
- task: PowerShell@2
condition: and(succeeded(), eq(variables['Agent.OS'], 'Linux'))
@@ -482,14 +492,17 @@ stages:
inputs:
artifact: nupkg
path: $(Build.ArtifactStagingDirectory)/nupkg
- task: NuGetCommand@2
displayName: Nuget push
- task: DotNetCoreCLI@2
displayName: dotnet restore
inputs:
command: 'push'
packagesToPush: $(Build.ArtifactStagingDirectory)/**/*.nupkg
nuGetFeedType: 'external'
publishFeedCredentials: 'MyGet - Pre-releases'
command: restore
projects: '**/umbraco.sln'
# TODO: Use NuGetCommand instead of DotNetCoreCLI
# - task: NuGetCommand@2
# displayName: Restore NuGet Packages
# inputs:
# restoreSolution: 'umbraco.sln'
# feedsToUse: config
- stage: Deploy_NuGet
displayName: NuGet release
dependsOn:
@@ -506,13 +519,11 @@ stages:
inputs:
artifact: nupkg
path: $(Build.ArtifactStagingDirectory)/nupkg
- task: NuGetCommand@2
displayName: Nuget push
- task: DotNetCoreCLI@2
displayName: dotnet restore
inputs:
command: 'push'
packagesToPush: $(Build.ArtifactStagingDirectory)/**/*.nupkg
nuGetFeedType: 'external'
publishFeedCredentials: 'NuGet - Umbraco.*'
command: restore
projects: '**/umbraco.sln'
- stage: Upload_API_Docs
pool:

View File

@@ -7,7 +7,7 @@
<AssemblyVersion>10.0.0</AssemblyVersion>
<InformationalVersion>10.0.0-rc1</InformationalVersion>
<FileVersion>10.0.0</FileVersion>
<LangVersion Condition="'$(LangVersion)' == ''">10.0</LangVersion>
<LangVersion Condition="'$(LangVersion)' == ''">preview</LangVersion>
<NeutralLanguage>en-US</NeutralLanguage>
<Company>Umbraco CMS</Company>
<Copyright>Copyright © Umbraco 2021</Copyright>

View File

@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net6.0</TargetFramework>
<TargetFramework>net7.0</TargetFramework>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<IsPackable>false</IsPackable>
<EnablePackageValidation>false</EnablePackageValidation>

View File

@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<TargetFramework>net7.0</TargetFramework>
<PackageId>Umbraco.Cms.Persistence.SqlServer</PackageId>
<Title>Umbraco.Cms.Persistence.SqlServer</Title>
<Description>Adds support for SQL Server to Umbraco CMS.</Description>

View File

@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<TargetFramework>net7.0</TargetFramework>
<PackageId>Umbraco.Cms.Persistence.Sqlite</PackageId>
<Title>Umbraco.Cms.Persistence.Sqlite</Title>
<Description>Adds support for SQLite to Umbraco CMS.</Description>
@@ -12,6 +12,7 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Data.Sqlite" Version="7.0.0-preview.7.22375.6" />
<PackageReference Include="Microsoft.Data.Sqlite" Version="6.0.5" />
</ItemGroup>

View File

@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk.Razor">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<TargetFramework>net7.0</TargetFramework>
<AddRazorSupportForMvc>true</AddRazorSupportForMvc>
<PackageId>Umbraco.Cms.StaticAssets</PackageId>
<Description>Contains the static assets that is required to run Umbraco CMS.</Description>

View File

@@ -1,6 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<TargetFramework>net7.0</TargetFramework>
<IncludeBuildOutput>false</IncludeBuildOutput>
<PackageId>Umbraco.Cms</PackageId>
<Title>Umbraco.Cms</Title>

View File

@@ -23,8 +23,13 @@ public class ConfigureConnectionStrings : IConfigureNamedOptions<ConnectionStrin
public void Configure(ConnectionStrings options) => Configure(Options.DefaultName, options);
/// <inheritdoc />
public void Configure(string name, ConnectionStrings options)
public void Configure(string? name, ConnectionStrings options)
{
if (name is null)
{
throw new InvalidOperationException("The name of the option instance is required.");
}
// Default to using UmbracoConnectionName
if (name == Options.DefaultName)
{

View File

@@ -11,7 +11,7 @@ namespace Umbraco.Cms.Core.Configuration.Models.Validation;
public class ContentSettingsValidator : ConfigurationValidatorBase, IValidateOptions<ContentSettings>
{
/// <inheritdoc />
public ValidateOptionsResult Validate(string name, ContentSettings options)
public ValidateOptionsResult Validate(string? name, ContentSettings options)
{
if (!ValidateError404Collection(options.Error404Collection, out var message))
{

View File

@@ -12,7 +12,7 @@ public class GlobalSettingsValidator
: ConfigurationValidatorBase, IValidateOptions<GlobalSettings>
{
/// <inheritdoc />
public ValidateOptionsResult Validate(string name, GlobalSettings options)
public ValidateOptionsResult Validate(string? name, GlobalSettings options)
{
if (!ValidateSmtpSetting(options.Smtp, out var message))
{

View File

@@ -19,7 +19,7 @@ public class HealthChecksSettingsValidator : ConfigurationValidatorBase, IValida
public HealthChecksSettingsValidator(ICronTabParser cronTabParser) => _cronTabParser = cronTabParser;
/// <inheritdoc />
public ValidateOptionsResult Validate(string name, HealthChecksSettings options)
public ValidateOptionsResult Validate(string? name, HealthChecksSettings options)
{
if (!ValidateNotificationFirstRunTime(options.Notification.FirstRunTime, out var message))
{

View File

@@ -11,7 +11,7 @@ namespace Umbraco.Cms.Core.Configuration.Models.Validation;
public class RequestHandlerSettingsValidator : ConfigurationValidatorBase, IValidateOptions<RequestHandlerSettings>
{
/// <inheritdoc />
public ValidateOptionsResult Validate(string name, RequestHandlerSettings options)
public ValidateOptionsResult Validate(string? name, RequestHandlerSettings options)
{
if (!ValidateConvertUrlsToAscii(options.ConvertUrlsToAscii, out var message))
{

View File

@@ -1,4 +1,4 @@
// Copyright (c) Umbraco.
// Copyright (c) Umbraco.
// See LICENSE for more details.
using Microsoft.Extensions.Options;
@@ -12,7 +12,7 @@ public class UnattendedSettingsValidator
: IValidateOptions<UnattendedSettings>
{
/// <inheritdoc />
public ValidateOptionsResult Validate(string name, UnattendedSettings options)
public ValidateOptionsResult Validate(string? name, UnattendedSettings options)
{
if (options.InstallUnattended)
{

View File

@@ -28,9 +28,28 @@ public static class RequestHandlerSettingsExtension
return RequestHandlerSettings.DefaultCharCollection;
}
return MergeUnique(
requestHandlerSettings.UserDefinedCharCollection,
RequestHandlerSettings.DefaultCharCollection);
return MergeUnique(requestHandlerSettings.UserDefinedCharCollection, RequestHandlerSettings.DefaultCharCollection);
}
private static IEnumerable<CharItem> GetReplacements(IConfiguration configuration, string key)
{
var replacements = new List<CharItem>();
IEnumerable<IConfigurationSection> config = configuration.GetSection(key).GetChildren();
foreach (IConfigurationSection section in config)
{
var @char = section.GetValue<string>(nameof(CharItem.Char));
var replacement = section.GetValue<string>(nameof(CharItem.Replacement));
if (@char is null || replacement is null)
{
continue;
}
replacements.Add(new CharItem { Char = @char, Replacement = replacement });
}
return replacements;
}
/// <summary>

View File

@@ -2,7 +2,7 @@ namespace Umbraco.Cms.Core.Hosting;
public interface IHostingEnvironment
{
string SiteName { get; }
string? SiteName { get; }
/// <summary>
/// The unique application ID for this Umbraco website.

View File

@@ -11,7 +11,7 @@ public class ChangingPasswordModel
/// The password value
/// </summary>
[DataMember(Name = "newPassword")]
public string? NewPassword { get; set; }
public required string NewPassword { get; set; }
/// <summary>
/// The old password - used to change a password when: EnablePasswordRetrieval = false

View File

@@ -1,4 +1,4 @@
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations;
using System.Runtime.Serialization;
namespace Umbraco.Cms.Core.Models;
@@ -11,11 +11,11 @@ public class Verify2FACodeModel
{
[Required]
[DataMember(Name = "code", IsRequired = true)]
public string? Code { get; set; }
public required string Code { get; set; }
[Required]
[DataMember(Name = "provider", IsRequired = true)]
public string? Provider { get; set; }
public required string Provider { get; set; }
/// <summary>
/// Flag indicating whether the sign-in cookie should persist after the browser is closed.

View File

@@ -1,4 +1,4 @@
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations;
using System.Runtime.Serialization;
namespace Umbraco.Cms.Core.Models;
@@ -12,9 +12,9 @@ public class SetPasswordModel
[Required]
[DataMember(Name = "password", IsRequired = true)]
public string? Password { get; set; }
public required string Password { get; set; }
[Required]
[DataMember(Name = "resetCode", IsRequired = true)]
public string? ResetCode { get; set; }
public required string ResetCode { get; set; }
}

View File

@@ -1,4 +1,4 @@
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations;
using System.Runtime.Serialization;
namespace Umbraco.Cms.Core.Models;
@@ -7,9 +7,9 @@ public class UnLinkLoginModel
{
[Required]
[DataMember(Name = "loginProvider", IsRequired = true)]
public string? LoginProvider { get; set; }
public required string LoginProvider { get; set; }
[Required]
[DataMember(Name = "providerKey", IsRequired = true)]
public string? ProviderKey { get; set; }
public required string ProviderKey { get; set; }
}

View File

@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<TargetFramework>net7.0</TargetFramework>
<RootNamespace>Umbraco.Cms.Core</RootNamespace>
<Product>Umbraco CMS</Product>
<PackageId>Umbraco.Cms.Core</PackageId>
@@ -15,6 +15,15 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="7.0.0-preview.7.22375.6" />
<PackageReference Include="Microsoft.Extensions.FileProviders.Embedded" Version="7.0.0-preview.7.22375.6" />
<PackageReference Include="Microsoft.Extensions.FileProviders.Physical" Version="7.0.0-preview.7.22375.6" />
<PackageReference Include="Microsoft.Extensions.Hosting.Abstractions" Version="7.0.0-preview.7.22375.6" />
<PackageReference Include="Microsoft.Extensions.Identity.Core" Version="7.0.0-preview.7.22375.6" />
<PackageReference Include="Microsoft.Extensions.Logging" Version="7.0.0-preview.7.22375.6" />
<PackageReference Include="Microsoft.Extensions.Options" Version="7.0.0-preview.7.22375.6" />
<PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="7.0.0-preview.7.22375.6" />
<PackageReference Include="Microsoft.Extensions.Options.DataAnnotations" Version="7.0.0-preview.7.22375.6" />
<PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="6.0.0" />
<PackageReference Include="Microsoft.Extensions.FileProviders.Embedded" Version="6.0.5" />
<PackageReference Include="Microsoft.Extensions.FileProviders.Physical" Version="6.0.0" />
@@ -30,7 +39,7 @@
</PackageReference>
<PackageReference Include="System.ComponentModel.Annotations" Version="5.0.0" />
<PackageReference Include="System.Reflection.Emit.Lightweight" Version="4.7.0" />
<PackageReference Include="System.Runtime.Caching" Version="6.0.0" />
<PackageReference Include="System.Runtime.Caching" Version="7.0.0-preview.7.22375.6" />
<PackageReference Include="Umbraco.Code" Version="2.0.0">
<PrivateAssets>all</PrivateAssets>
</PackageReference>

View File

@@ -5,12 +5,12 @@ public interface IRequestAccessor
/// <summary>
/// Returns the request/form/querystring value for the given name
/// </summary>
string GetRequestValue(string name);
string? GetRequestValue(string name);
/// <summary>
/// Returns the query string value for the given name
/// </summary>
string GetQueryStringValue(string name);
string? GetQueryStringValue(string name);
/// <summary>
/// Returns the current request uri

View File

@@ -25,7 +25,7 @@ public sealed class ConfigureIndexOptions : IConfigureNamedOptions<LuceneDirecto
_settings = settings.Value;
}
public void Configure(string name, LuceneDirectoryIndexOptions options)
public void Configure(string? name, LuceneDirectoryIndexOptions options)
{
switch (name)
{

View File

@@ -1,6 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<TargetFramework>net7.0</TargetFramework>
<RootNamespace>Umbraco.Cms.Infrastructure.Examine</RootNamespace>
<Product>Umbraco CMS</Product>
<Title>Umbraco.Examine.Lucene</Title>

View File

@@ -229,7 +229,7 @@ namespace Umbraco.Cms.Core.Configuration
{
if (provider.Source.FileProvider is PhysicalFileProvider physicalFileProvider)
{
var jsonFilePath = Path.Combine(physicalFileProvider.Root, provider.Source.Path);
var jsonFilePath = Path.Combine(physicalFileProvider.Root, provider.Source.Path!);
try
{
@@ -264,7 +264,7 @@ namespace Umbraco.Cms.Core.Configuration
return null;
}
var jsonFilePath = Path.Combine(physicalFileProvider.Root, provider.Source.Path);
var jsonFilePath = Path.Combine(physicalFileProvider.Root, provider.Source.Path!);
try
{

View File

@@ -46,12 +46,12 @@ public class BackOfficeClaimsPrincipalFactory : UserClaimsPrincipalFactory<BackO
// ensure our required claims are there
id.AddRequiredClaims(
user.Id,
user.UserName,
user.UserName!,
user.Name!,
user.CalculatedContentStartNodeIds,
user.CalculatedMediaStartNodeIds,
user.Culture,
user.SecurityStamp,
user.SecurityStamp!,
user.AllowedSections,
user.Roles.Select(x => x.RoleId).ToArray());

View File

@@ -20,7 +20,7 @@ public class BackOfficeErrorDescriber : UmbracoErrorDescriberBase
Description = _textService.Localize("validation", "duplicateUserGroupName", new[] { role }),
};
public override IdentityError InvalidRoleName(string role) => new()
public override IdentityError InvalidRoleName(string? role) => new()
{
Code = nameof(InvalidRoleName),
Description = _textService.Localize("validation", "invalidUserGroupName"),
@@ -70,7 +70,7 @@ public class MembersErrorDescriber : UmbracoErrorDescriberBase
Description = _textService.Localize("validation", "duplicateMemberGroupName", new[] { role }),
};
public override IdentityError InvalidRoleName(string role) => new()
public override IdentityError InvalidRoleName(string? role) => new()
{
Code = nameof(InvalidRoleName),
Description = _textService.Localize("validation", "invalidMemberGroupName"),

View File

@@ -117,6 +117,11 @@ public class BackOfficeUserStore : UmbracoUserStore<BackOfficeIdentityUser, Iden
throw new ArgumentNullException(nameof(user));
}
if (user.Email is null || user.UserName is null)
{
throw new InvalidOperationException("Email and UserName is required.");
}
// the password must be 'something' it could be empty if authenticating
// with an external provider so we'll just generate one and prefix it, the
// prefix will help us determine if the password hasn't actually been specified yet.
@@ -255,16 +260,14 @@ public class BackOfficeUserStore : UmbracoUserStore<BackOfficeIdentityUser, Iden
}
/// <inheritdoc />
public override Task<BackOfficeIdentityUser> FindByNameAsync(
string userName,
CancellationToken cancellationToken = default)
public override Task<BackOfficeIdentityUser?> FindByNameAsync(string userName, CancellationToken cancellationToken = default)
{
cancellationToken.ThrowIfCancellationRequested();
ThrowIfDisposed();
IUser? user = _userService.GetByUsername(userName);
if (user == null)
{
return Task.FromResult((BackOfficeIdentityUser)null!);
return Task.FromResult<BackOfficeIdentityUser?>(null);
}
BackOfficeIdentityUser? result = AssignLoginsCallback(_mapper.Map<BackOfficeIdentityUser>(user));
@@ -273,7 +276,7 @@ public class BackOfficeUserStore : UmbracoUserStore<BackOfficeIdentityUser, Iden
}
/// <inheritdoc />
protected override Task<BackOfficeIdentityUser> FindUserAsync(string userId, CancellationToken cancellationToken)
protected override Task<BackOfficeIdentityUser?> FindUserAsync(string userId, CancellationToken cancellationToken)
{
cancellationToken.ThrowIfCancellationRequested();
ThrowIfDisposed();
@@ -288,7 +291,7 @@ public class BackOfficeUserStore : UmbracoUserStore<BackOfficeIdentityUser, Iden
}
/// <inheritdoc />
public override Task<BackOfficeIdentityUser> FindByEmailAsync(
public override Task<BackOfficeIdentityUser?> FindByEmailAsync(
string email,
CancellationToken cancellationToken = default)
{
@@ -299,11 +302,11 @@ public class BackOfficeUserStore : UmbracoUserStore<BackOfficeIdentityUser, Iden
? null
: _mapper.Map<BackOfficeIdentityUser>(user);
return Task.FromResult(AssignLoginsCallback(result))!;
return Task.FromResult(AssignLoginsCallback(result));
}
/// <inheritdoc />
public override async Task SetPasswordHashAsync(BackOfficeIdentityUser user, string passwordHash, CancellationToken cancellationToken = default)
public override async Task SetPasswordHashAsync(BackOfficeIdentityUser user, string? passwordHash, CancellationToken cancellationToken = default)
{
await base.SetPasswordHashAsync(user, passwordHash, cancellationToken);
@@ -405,7 +408,7 @@ public class BackOfficeUserStore : UmbracoUserStore<BackOfficeIdentityUser, Iden
/// tracking ORMs like EFCore.
/// </remarks>
/// <inheritdoc />
public override Task SetTokenAsync(BackOfficeIdentityUser user, string loginProvider, string name, string value, CancellationToken cancellationToken)
public override Task SetTokenAsync(BackOfficeIdentityUser user, string loginProvider, string name, string? value, CancellationToken cancellationToken)
{
cancellationToken.ThrowIfCancellationRequested();
ThrowIfDisposed();
@@ -437,15 +440,15 @@ public class BackOfficeUserStore : UmbracoUserStore<BackOfficeIdentityUser, Iden
}
/// <inheritdoc />
protected override async Task<IdentityUserLogin<string>> FindUserLoginAsync(string userId, string loginProvider, string providerKey, CancellationToken cancellationToken)
protected override async Task<IdentityUserLogin<string>?> FindUserLoginAsync(string userId, string loginProvider, string providerKey, CancellationToken cancellationToken)
{
cancellationToken.ThrowIfCancellationRequested();
ThrowIfDisposed();
BackOfficeIdentityUser user = await FindUserAsync(userId, cancellationToken);
if (user is null || user.Id is null)
BackOfficeIdentityUser? user = await FindUserAsync(userId, cancellationToken);
if (user?.Id is null)
{
return null!;
return null;
}
IList<UserLoginInfo> logins = await GetLoginsAsync(user, cancellationToken);
@@ -453,7 +456,7 @@ public class BackOfficeUserStore : UmbracoUserStore<BackOfficeIdentityUser, Iden
logins.FirstOrDefault(x => x.ProviderKey == providerKey && x.LoginProvider == loginProvider);
if (found == null)
{
return null!;
return null;
}
return new IdentityUserLogin<string>
@@ -466,7 +469,7 @@ public class BackOfficeUserStore : UmbracoUserStore<BackOfficeIdentityUser, Iden
}
/// <inheritdoc />
protected override Task<IdentityUserLogin<string>> FindUserLoginAsync(string loginProvider, string providerKey, CancellationToken cancellationToken)
protected override Task<IdentityUserLogin<string>?> FindUserLoginAsync(string loginProvider, string providerKey, CancellationToken cancellationToken)
{
cancellationToken.ThrowIfCancellationRequested();
ThrowIfDisposed();
@@ -474,11 +477,11 @@ public class BackOfficeUserStore : UmbracoUserStore<BackOfficeIdentityUser, Iden
var logins = _externalLoginService.Find(loginProvider, providerKey).ToList();
if (logins.Count == 0)
{
return Task.FromResult((IdentityUserLogin<string>)null!);
return Task.FromResult<IdentityUserLogin<string>?>(null);
}
IIdentityUserLogin found = logins[0];
return Task.FromResult(new IdentityUserLogin<string>
return Task.FromResult<IdentityUserLogin<string>?>(new IdentityUserLogin<string>
{
LoginProvider = found.LoginProvider,
ProviderKey = found.ProviderKey,
@@ -488,30 +491,33 @@ public class BackOfficeUserStore : UmbracoUserStore<BackOfficeIdentityUser, Iden
}
/// <inheritdoc />
protected override Task<IdentityRole<string>> FindRoleAsync(
protected override Task<IdentityRole<string>?> FindRoleAsync(
string normalizedRoleName,
CancellationToken cancellationToken)
{
IUserGroup? group = _userService.GetUserGroupByAlias(normalizedRoleName);
if (group == null)
if (group?.Name is null)
{
return Task.FromResult((IdentityRole<string>)null!);
return Task.FromResult<IdentityRole<string>?>(null);
}
return Task.FromResult(new IdentityRole<string>(group.Name) { Id = group.Alias });
return Task.FromResult<IdentityRole<string>?>(new IdentityRole<string>(group.Name)
{
Id = group.Alias,
});
}
/// <inheritdoc />
protected override async Task<IdentityUserRole<string>> FindUserRoleAsync(string userId, string roleId, CancellationToken cancellationToken)
protected override async Task<IdentityUserRole<string>?> FindUserRoleAsync(string userId, string roleId, CancellationToken cancellationToken)
{
BackOfficeIdentityUser user = await FindUserAsync(userId, cancellationToken);
BackOfficeIdentityUser? user = await FindUserAsync(userId, cancellationToken);
if (user == null)
{
return null!;
}
IdentityUserRole<string>? found = user.Roles.FirstOrDefault(x => x.RoleId.InvariantEquals(roleId));
return found!;
return found;
}
private BackOfficeIdentityUser? AssignLoginsCallback(BackOfficeIdentityUser? user)
@@ -583,7 +589,7 @@ public class BackOfficeUserStore : UmbracoUserStore<BackOfficeIdentityUser, Iden
&& user.Email != identityUser.Email && identityUser.Email.IsNullOrWhiteSpace() == false)
{
anythingChanged = true;
user.Email = identityUser.Email;
user.Email = identityUser.Email!;
}
if (identityUser.IsPropertyDirty(nameof(BackOfficeIdentityUser.AccessFailedCount))
@@ -615,7 +621,7 @@ public class BackOfficeUserStore : UmbracoUserStore<BackOfficeIdentityUser, Iden
&& user.Username != identityUser.UserName && identityUser.UserName.IsNullOrWhiteSpace() == false)
{
anythingChanged = true;
user.Username = identityUser.UserName;
user.Username = identityUser.UserName!;
}
if (identityUser.IsPropertyDirty(nameof(BackOfficeIdentityUser.PasswordHash))
@@ -691,8 +697,7 @@ public class BackOfficeUserStore : UmbracoUserStore<BackOfficeIdentityUser, Iden
/// Overridden to support Umbraco's own data storage requirements
/// </summary>
/// <remarks>
/// The base class's implementation of this calls into FindTokenAsync, RemoveUserTokenAsync and AddUserTokenAsync, both
/// methods will only work with ORMs that are change
/// The base class's implementation of this calls into FindTokenAsync, RemoveUserTokenAsync and AddUserTokenAsync, both methods will only work with ORMs that are change
/// tracking ORMs like EFCore.
/// </remarks>
/// <inheritdoc />

View File

@@ -38,9 +38,9 @@ public static class MergeClaimsIdentityExtensions
{
foreach (IdentityUserClaim<string> claim in source.Claims
.Where(claim => !_ignoredClaims.Contains(claim.ClaimType))
.Where(claim => !destination.HasClaim(claim.ClaimType, claim.ClaimValue)))
.Where(claim => !destination.HasClaim(claim.ClaimType!, claim.ClaimValue!)))
{
destination.AddClaim(new Claim(claim.ClaimType, claim.ClaimValue));
destination.AddClaim(new Claim(claim.ClaimType!, claim.ClaimValue!));
}
}
}

View File

@@ -22,14 +22,14 @@ public interface IUmbracoUserManager<TUser> : IDisposable
/// </summary>
/// <param name="principal">The <see cref="ClaimsPrincipal" /></param>
/// <returns>A <see cref="Task{TResult}" /> representing the result of the asynchronous operation.</returns>
Task<TUser> GetUserAsync(ClaimsPrincipal principal);
Task<TUser?> GetUserAsync(ClaimsPrincipal principal);
/// <summary>
/// Get the user id from the <see cref="ClaimsPrincipal" />
/// </summary>
/// <param name="principal">the <see cref="ClaimsPrincipal" /></param>
/// <returns>Returns the user id from the <see cref="ClaimsPrincipal" /></returns>
string GetUserId(ClaimsPrincipal principal);
string? GetUserId(ClaimsPrincipal principal);
/// <summary>
/// Gets the external logins for the user
@@ -47,7 +47,7 @@ public interface IUmbracoUserManager<TUser> : IDisposable
/// Finds a user by the external login provider
/// </summary>
/// <returns>A <see cref="Task{TResult}" /> representing the result of the asynchronous operation.</returns>
Task<TUser> FindByLoginAsync(string loginProvider, string providerKey);
Task<TUser?> FindByLoginAsync(string loginProvider, string providerKey);
/// <summary>
/// Finds and returns a user, if any, who has the specified <paramref name="userId" />.
@@ -57,7 +57,7 @@ public interface IUmbracoUserManager<TUser> : IDisposable
/// The <see cref="Task" /> that represents the asynchronous operation, containing the user matching the specified
/// <paramref name="userId" /> if it exists.
/// </returns>
Task<TUser> FindByIdAsync(string? userId);
Task<TUser?> FindByIdAsync(string userId);
/// <summary>
/// Generates a password reset token for the specified <paramref name="user" />, using
@@ -80,7 +80,7 @@ public interface IUmbracoUserManager<TUser> : IDisposable
/// is to generate a token and reset it, however, when we do this we want to track a password change, not a password
/// reset
/// </remarks>
Task<IdentityResult> ChangePasswordWithResetAsync(string userId, string token, string? newPassword);
Task<IdentityResult> ChangePasswordWithResetAsync(string userId, string token, string newPassword);
/// <summary>
/// Validates that an email confirmation token matches the specified <paramref name="user" />.
@@ -91,7 +91,7 @@ public interface IUmbracoUserManager<TUser> : IDisposable
/// The <see cref="Task" /> that represents the asynchronous operation, containing the <see cref="IdentityResult" />
/// of the operation.
/// </returns>
Task<IdentityResult> ConfirmEmailAsync(TUser user, string? token);
Task<IdentityResult> ConfirmEmailAsync(TUser user, string token);
/// <summary>
/// Gets the user, if any, associated with the normalized value of the specified email address.
@@ -103,7 +103,7 @@ public interface IUmbracoUserManager<TUser> : IDisposable
/// The task object containing the results of the asynchronous lookup operation, the user, if any, associated with a
/// normalized value of the specified email address.
/// </returns>
Task<TUser> FindByEmailAsync(string email);
Task<TUser?> FindByEmailAsync(string email);
/// <summary>
/// Resets the <paramref name="user" />'s password to the specified <paramref name="newPassword" /> after
@@ -116,7 +116,7 @@ public interface IUmbracoUserManager<TUser> : IDisposable
/// The <see cref="Task" /> that represents the asynchronous operation, containing the <see cref="IdentityResult" />
/// of the operation.
/// </returns>
Task<IdentityResult> ResetPasswordAsync(TUser user, string? token, string? newPassword);
Task<IdentityResult> ResetPasswordAsync(TUser user, string token, string newPassword);
/// <summary>
/// Override to check the user approval value as well as the user lock out date, by default this only checks the user's
@@ -216,7 +216,7 @@ public interface IUmbracoUserManager<TUser> : IDisposable
/// The <see cref="Task" /> that represents the asynchronous operation, containing the <see cref="IdentityResult" />
/// of the operation.
/// </returns>
Task<IdentityResult> ChangePasswordAsync(TUser user, string? currentPassword, string? newPassword);
Task<IdentityResult> ChangePasswordAsync(TUser user, string currentPassword, string newPassword);
/// <summary>
/// Used to validate a user's session
@@ -268,7 +268,7 @@ public interface IUmbracoUserManager<TUser> : IDisposable
/// The <see cref="Task" /> that represents the asynchronous operation, containing the <see cref="IdentityResult" />
/// of the operation.
/// </returns>
Task<IdentityResult> CreateAsync(TUser user, string? password);
Task<IdentityResult> CreateAsync(TUser user, string password);
/// <summary>
/// Generate a password for a user based on the current password validator
@@ -302,7 +302,7 @@ public interface IUmbracoUserManager<TUser> : IDisposable
/// The <see cref="Task" /> that represents the asynchronous operation, containing the user matching the specified
/// <paramref name="userName" /> if it exists.
/// </returns>
Task<TUser> FindByNameAsync(string userName);
Task<TUser?> FindByNameAsync(string userName);
/// <summary>
/// Increments the access failed count for the user as an asynchronous operation.
@@ -373,7 +373,7 @@ public interface IUmbracoUserManager<TUser> : IDisposable
/// The System.Threading.Tasks.Task that represents the asynchronous operation, containing the
/// Microsoft.AspNetCore.Identity.IdentityResult of the operation.
/// </returns>
Task<IdentityResult> RemoveLoginAsync(TUser user, string? loginProvider, string? providerKey);
Task<IdentityResult> RemoveLoginAsync(TUser user, string loginProvider, string providerKey);
/// <summary>
/// Resets the access failed count for the user
@@ -395,7 +395,7 @@ public interface IUmbracoUserManager<TUser> : IDisposable
/// The task object containing the results of the asynchronous operation, the email address for the specified
/// user.
/// </returns>
Task<string> GetEmailAsync(TUser user);
Task<string?> GetEmailAsync(TUser user);
/// <summary>
/// Gets the telephone number, if any, for the specified user.
@@ -409,7 +409,7 @@ public interface IUmbracoUserManager<TUser> : IDisposable
/// A user can only support a phone number if the BackOfficeUserStore is replaced with another that implements
/// IUserPhoneNumberStore
/// </remarks>
Task<string> GetPhoneNumberAsync(TUser user);
Task<string?> GetPhoneNumberAsync(TUser user);
/// <summary>
/// Validates that a user's credentials are correct without actually logging them in.

View File

@@ -131,7 +131,7 @@ public class MemberRoleStore : IQueryableRoleStore<UmbracoIdentityRole>
}
/// <inheritdoc />
public Task<string> GetRoleNameAsync(UmbracoIdentityRole role, CancellationToken cancellationToken = default)
public Task<string?> GetRoleNameAsync(UmbracoIdentityRole role, CancellationToken cancellationToken = default)
{
cancellationToken.ThrowIfCancellationRequested();
ThrowIfDisposed();
@@ -141,11 +141,11 @@ public class MemberRoleStore : IQueryableRoleStore<UmbracoIdentityRole>
throw new ArgumentNullException(nameof(role));
}
return Task.FromResult(role.Name)!;
return Task.FromResult(role.Name);
}
/// <inheritdoc />
public Task SetRoleNameAsync(UmbracoIdentityRole role, string roleName,
public Task SetRoleNameAsync(UmbracoIdentityRole role, string? roleName,
CancellationToken cancellationToken = default)
{
cancellationToken.ThrowIfCancellationRequested();
@@ -155,23 +155,24 @@ public class MemberRoleStore : IQueryableRoleStore<UmbracoIdentityRole>
throw new ArgumentNullException(nameof(role));
}
role.Name = roleName;
return Task.CompletedTask;
}
/// <inheritdoc />
public Task<string> GetNormalizedRoleNameAsync(
public Task<string?> GetNormalizedRoleNameAsync(
UmbracoIdentityRole role,
CancellationToken cancellationToken = default)
=> GetRoleNameAsync(role, cancellationToken);
/// <inheritdoc />
public Task SetNormalizedRoleNameAsync(UmbracoIdentityRole role, string normalizedName,
public Task SetNormalizedRoleNameAsync(UmbracoIdentityRole role, string? normalizedName,
CancellationToken cancellationToken = default)
=> SetRoleNameAsync(role, normalizedName, cancellationToken);
/// <inheritdoc />
public Task<UmbracoIdentityRole> FindByIdAsync(string roleId, CancellationToken cancellationToken = default)
public Task<UmbracoIdentityRole?> FindByIdAsync(string roleId, CancellationToken cancellationToken = default)
{
cancellationToken.ThrowIfCancellationRequested();
ThrowIfDisposed();
@@ -198,11 +199,11 @@ public class MemberRoleStore : IQueryableRoleStore<UmbracoIdentityRole>
memberGroup = _memberGroupService.GetById(id);
}
return Task.FromResult(memberGroup == null ? null : MapFromMemberGroup(memberGroup))!;
return Task.FromResult(memberGroup == null ? null : MapFromMemberGroup(memberGroup));
}
/// <inheritdoc />
public Task<UmbracoIdentityRole> FindByNameAsync(string name, CancellationToken cancellationToken = default)
public Task<UmbracoIdentityRole?> FindByNameAsync(string name, CancellationToken cancellationToken = default)
{
cancellationToken.ThrowIfCancellationRequested();
ThrowIfDisposed();

View File

@@ -91,7 +91,7 @@ public class MemberUserStore : UmbracoUserStore<MemberIdentityUser, UmbracoIdent
{
cancellationToken.ThrowIfCancellationRequested();
ThrowIfDisposed();
if (user == null)
if (user is null)
{
throw new ArgumentNullException(nameof(user));
}
@@ -100,9 +100,9 @@ public class MemberUserStore : UmbracoUserStore<MemberIdentityUser, UmbracoIdent
// create member
IMember memberEntity = _memberService.CreateMember(
user.UserName,
user.Email,
user.Name.IsNullOrWhiteSpace() ? user.UserName : user.Name!,
user.UserName!,
user.Email!,
user.Name.IsNullOrWhiteSpace() ? user.UserName! : user.Name!,
user.MemberTypeAlias.IsNullOrWhiteSpace()
? Constants.Security.DefaultMemberTypeAlias
: user.MemberTypeAlias!);
@@ -255,21 +255,19 @@ public class MemberUserStore : UmbracoUserStore<MemberIdentityUser, UmbracoIdent
}
/// <inheritdoc />
public override Task<MemberIdentityUser> FindByNameAsync(
string userName,
CancellationToken cancellationToken = default)
public override Task<MemberIdentityUser?> FindByNameAsync(string userName, CancellationToken cancellationToken = default)
{
cancellationToken.ThrowIfCancellationRequested();
ThrowIfDisposed();
IMember? user = _memberService.GetByUsername(userName);
if (user == null)
{
return Task.FromResult((MemberIdentityUser)null!);
return Task.FromResult<MemberIdentityUser?>(null);
}
MemberIdentityUser result = AssignLoginsCallback(_mapper.Map<MemberIdentityUser>(user))!;
MemberIdentityUser? result = AssignLoginsCallback(_mapper.Map<MemberIdentityUser>(user))!;
return Task.FromResult(result);
return Task.FromResult<MemberIdentityUser?>(result);
}
public IPublishedContent? GetPublishedMember(MemberIdentityUser? user)
@@ -290,7 +288,7 @@ public class MemberUserStore : UmbracoUserStore<MemberIdentityUser, UmbracoIdent
}
/// <inheritdoc />
public override Task<MemberIdentityUser> FindByEmailAsync(
public override Task<MemberIdentityUser?> FindByEmailAsync(
string email,
CancellationToken cancellationToken = default)
{
@@ -301,11 +299,11 @@ public class MemberUserStore : UmbracoUserStore<MemberIdentityUser, UmbracoIdent
? null
: _mapper.Map<MemberIdentityUser>(member);
return Task.FromResult(AssignLoginsCallback(result))!;
return Task.FromResult(AssignLoginsCallback(result));
}
/// <inheritdoc />
protected override Task<MemberIdentityUser> FindUserAsync(string userId, CancellationToken cancellationToken)
protected override Task<MemberIdentityUser?> FindUserAsync(string userId, CancellationToken cancellationToken)
{
cancellationToken.ThrowIfCancellationRequested();
ThrowIfDisposed();
@@ -320,7 +318,7 @@ public class MemberUserStore : UmbracoUserStore<MemberIdentityUser, UmbracoIdent
: _memberService.GetById(UserIdToInt(userId));
if (user == null)
{
return Task.FromResult((MemberIdentityUser)null!);
return Task.FromResult((MemberIdentityUser)null!)!;
}
return Task.FromResult(AssignLoginsCallback(_mapper.Map<MemberIdentityUser>(user)))!;
@@ -440,7 +438,7 @@ public class MemberUserStore : UmbracoUserStore<MemberIdentityUser, UmbracoIdent
}
/// <inheritdoc />
protected override async Task<IdentityUserLogin<string>> FindUserLoginAsync(string userId, string loginProvider,
protected override async Task<IdentityUserLogin<string>?> FindUserLoginAsync(string userId, string loginProvider,
string providerKey, CancellationToken cancellationToken)
{
cancellationToken.ThrowIfCancellationRequested();
@@ -456,38 +454,32 @@ public class MemberUserStore : UmbracoUserStore<MemberIdentityUser, UmbracoIdent
throw new ArgumentNullException(nameof(providerKey));
}
MemberIdentityUser user = await FindUserAsync(userId, cancellationToken);
if (user == null)
MemberIdentityUser? user = await FindUserAsync(userId, cancellationToken);
if (user?.Id is null)
{
return await Task.FromResult((IdentityUserLogin<string>)null!);
return await Task.FromResult<IdentityUserLogin<string>?>(null);
}
IList<UserLoginInfo> logins = await GetLoginsAsync(user, cancellationToken);
UserLoginInfo? found =
logins.FirstOrDefault(x => x.ProviderKey == providerKey && x.LoginProvider == loginProvider);
if (found == null)
if (found is null)
{
return await Task.FromResult((IdentityUserLogin<string>)null!);
return await Task.FromResult<IdentityUserLogin<string>?>(null);
}
if (user.Id is not null)
{
return new IdentityUserLogin<string>
{
LoginProvider = found.LoginProvider,
ProviderKey = found.ProviderKey,
// TODO: We don't store this value so it will be null
ProviderDisplayName = found.ProviderDisplayName,
UserId = user.Id,
UserId = user.Id
};
}
return null!;
}
/// <inheritdoc />
protected override Task<IdentityUserLogin<string>> FindUserLoginAsync(string loginProvider, string providerKey,
protected override Task<IdentityUserLogin<string>?> FindUserLoginAsync(string loginProvider, string providerKey,
CancellationToken cancellationToken)
{
cancellationToken.ThrowIfCancellationRequested();
@@ -506,11 +498,11 @@ public class MemberUserStore : UmbracoUserStore<MemberIdentityUser, UmbracoIdent
var logins = _externalLoginService.Find(loginProvider, providerKey).ToList();
if (logins.Count == 0)
{
return Task.FromResult((IdentityUserLogin<string>)null!);
return Task.FromResult<IdentityUserLogin<string>?>(null);
}
IIdentityUserLogin found = logins[0];
return Task.FromResult(new IdentityUserLogin<string>
return Task.FromResult<IdentityUserLogin<string>?>(new IdentityUserLogin<string>
{
LoginProvider = found.LoginProvider,
ProviderKey = found.ProviderKey,
@@ -527,7 +519,7 @@ public class MemberUserStore : UmbracoUserStore<MemberIdentityUser, UmbracoIdent
{
// if there are no roles, they either haven't been loaded since we don't eagerly
// load for members, or they just have no roles.
IEnumerable<string> currentRoles = _memberService.GetAllRoles(user.UserName);
IEnumerable<string> currentRoles = _memberService.GetAllRoles(user.UserName!);
ICollection<IdentityUserRole<string>> roles = currentRoles
.Select(role => new IdentityUserRole<string> { RoleId = role, UserId = user.Id }).ToList();
@@ -538,7 +530,7 @@ public class MemberUserStore : UmbracoUserStore<MemberIdentityUser, UmbracoIdent
/// <summary>
/// Lists all users of a given role.
/// </summary>
public override Task<IList<MemberIdentityUser>?> GetUsersInRoleAsync(
public override Task<IList<MemberIdentityUser>> GetUsersInRoleAsync(
string roleName,
CancellationToken cancellationToken = default)
{
@@ -550,10 +542,10 @@ public class MemberUserStore : UmbracoUserStore<MemberIdentityUser, UmbracoIdent
throw new ArgumentNullException(nameof(roleName));
}
IEnumerable<IMember>? members = _memberService.GetMembersByMemberType(roleName);
IEnumerable<IMember> members = _memberService.GetMembersByMemberType(roleName);
IList<MemberIdentityUser>? membersIdentityUsers =
members?.Select(x => _mapper.Map<MemberIdentityUser>(x)!).ToList();
IList<MemberIdentityUser> membersIdentityUsers =
members.Select(x => _mapper.Map<MemberIdentityUser>(x)!).ToList();
return Task.FromResult(membersIdentityUsers);
}
@@ -567,8 +559,7 @@ public class MemberUserStore : UmbracoUserStore<MemberIdentityUser, UmbracoIdent
/// tracking ORMs like EFCore.
/// </remarks>
/// <inheritdoc />
public override Task SetTokenAsync(MemberIdentityUser user, string loginProvider, string name, string value,
CancellationToken cancellationToken)
public override Task SetTokenAsync(MemberIdentityUser user, string loginProvider, string name, string? value, CancellationToken cancellationToken)
{
cancellationToken.ThrowIfCancellationRequested();
ThrowIfDisposed();
@@ -626,7 +617,7 @@ public class MemberUserStore : UmbracoUserStore<MemberIdentityUser, UmbracoIdent
}
/// <inheritdoc />
protected override Task<UmbracoIdentityRole> FindRoleAsync(string roleName, CancellationToken cancellationToken)
protected override Task<UmbracoIdentityRole?> FindRoleAsync(string roleName, CancellationToken cancellationToken)
{
if (string.IsNullOrWhiteSpace(roleName))
{
@@ -634,12 +625,12 @@ public class MemberUserStore : UmbracoUserStore<MemberIdentityUser, UmbracoIdent
}
IMemberGroup? group = _memberService.GetAllRoles().SingleOrDefault(x => x.Name == roleName);
if (group == null)
if (group?.Name is null)
{
return Task.FromResult((UmbracoIdentityRole)null!);
return Task.FromResult<UmbracoIdentityRole?>(null);
}
return Task.FromResult(new UmbracoIdentityRole(group.Name)
return Task.FromResult<UmbracoIdentityRole?>(new UmbracoIdentityRole(group.Name)
{
// TODO: what should the alias be?
Id = group.Id.ToString(),
@@ -647,27 +638,25 @@ public class MemberUserStore : UmbracoUserStore<MemberIdentityUser, UmbracoIdent
}
/// <inheritdoc />
protected override async Task<IdentityUserRole<string>> FindUserRoleAsync(string userId, string roleId,
protected override async Task<IdentityUserRole<string>?> FindUserRoleAsync(string userId, string roleId,
CancellationToken cancellationToken)
{
MemberIdentityUser user = await FindUserAsync(userId, cancellationToken);
if (user == null)
MemberIdentityUser? user = await FindUserAsync(userId, cancellationToken);
if (user is null)
{
return null!;
return null;
}
IdentityUserRole<string>? found = user.Roles.FirstOrDefault(x => x.RoleId.InvariantEquals(roleId));
return found!;
return found;
}
private MemberIdentityUser? AssignLoginsCallback(MemberIdentityUser? user)
{
if (user != null)
if (user is not null)
{
user.SetLoginsCallback(
new Lazy<IEnumerable<IIdentityUserLogin>?>(() => _externalLoginService.GetExternalLogins(user.Key)));
user.SetTokensCallback(new Lazy<IEnumerable<IIdentityUserToken>?>(() =>
_externalLoginService.GetExternalLoginTokens(user.Key)));
user.SetLoginsCallback(new Lazy<IEnumerable<IIdentityUserLogin>?>(() => _externalLoginService.GetExternalLogins(user.Key)));
user.SetTokensCallback(new Lazy<IEnumerable<IIdentityUserToken>?>(() => _externalLoginService.GetExternalLoginTokens(user.Key)));
}
return user;
@@ -729,7 +718,7 @@ public class MemberUserStore : UmbracoUserStore<MemberIdentityUser, UmbracoIdent
&& member.Email != identityUser.Email && identityUser.Email.IsNullOrWhiteSpace() == false)
{
anythingChanged = true;
member.Email = identityUser.Email;
member.Email = identityUser.Email!;
}
if (identityUser.IsPropertyDirty(nameof(MemberIdentityUser.AccessFailedCount))
@@ -761,7 +750,7 @@ public class MemberUserStore : UmbracoUserStore<MemberIdentityUser, UmbracoIdent
&& member.Username != identityUser.UserName && identityUser.UserName.IsNullOrWhiteSpace() == false)
{
anythingChanged = true;
member.Username = identityUser.UserName;
member.Username = identityUser.UserName!;
}
if (identityUser.IsPropertyDirty(nameof(MemberIdentityUser.PasswordHash))

View File

@@ -7,7 +7,7 @@ namespace Umbraco.Cms.Core.Security;
/// </summary>
public class NoopLookupNormalizer : ILookupNormalizer
{
public string NormalizeName(string name) => name;
public string? NormalizeName(string? name) => name;
public string NormalizeEmail(string email) => email;
public string? NormalizeEmail(string? email) => email;
}

View File

@@ -34,7 +34,7 @@ public abstract class UmbracoErrorDescriberBase : IdentityErrorDescriber
Description = _textService.Localize("validation", "duplicateUsername", new[] { userName }),
};
public override IdentityError InvalidEmail(string email) => new()
public override IdentityError InvalidEmail(string? email) => new()
{
Code = nameof(InvalidEmail),
Description = _textService.Localize("validation", "invalidEmail"),
@@ -46,7 +46,7 @@ public abstract class UmbracoErrorDescriberBase : IdentityErrorDescriber
Description = _textService.Localize("validation", "invalidToken"),
};
public override IdentityError InvalidUserName(string userName) => new()
public override IdentityError InvalidUserName(string? userName) => new()
{
Code = nameof(InvalidUserName),
Description = _textService.Localize("validation", "invalidUsername"),

View File

@@ -6,10 +6,10 @@ namespace Umbraco.Cms.Core.Security;
public class UmbracoIdentityRole : IdentityRole, IRememberBeingDirty
{
private string? _id;
private string? _name;
private string _id = string.Empty;
private string _name = string.Empty;
public UmbracoIdentityRole(string? roleName)
public UmbracoIdentityRole(string roleName)
: base(roleName)
{
}
@@ -26,7 +26,7 @@ public class UmbracoIdentityRole : IdentityRole, IRememberBeingDirty
}
/// <inheritdoc />
public override string? Id
public override string Id
{
get => _id;
set
@@ -40,11 +40,11 @@ public class UmbracoIdentityRole : IdentityRole, IRememberBeingDirty
public override string? Name
{
get => _name;
set => BeingDirty.SetPropertyValueAndDetectChanges(value, ref _name, nameof(Name));
set => BeingDirty.SetPropertyValueAndDetectChanges(value, ref _name!, nameof(Name));
}
/// <inheritdoc />
public override string NormalizedName { get => base.Name; set => base.Name = value; }
public override string? NormalizedName { get => base.Name ?? string.Empty; set => base.Name = value; }
/// <summary>
/// Gets or sets a value indicating whether returns an Id has been set on this object this will be false if the object
@@ -58,7 +58,7 @@ public class UmbracoIdentityRole : IdentityRole, IRememberBeingDirty
// model. A good writeup of that is here:
// https://stackoverflow.com/a/37362173
// For our purposes currently we won't worry about this.
public override string ConcurrencyStamp { get => base.ConcurrencyStamp; set => base.ConcurrencyStamp = value; }
public override string? ConcurrencyStamp { get => base.ConcurrencyStamp; set => base.ConcurrencyStamp = value; }
/// <summary>
/// Gets the <see cref="BeingDirty" /> for change tracking

View File

@@ -71,7 +71,7 @@ public abstract class UmbracoIdentityUser : IdentityUser, IRememberBeingDirty
// model. A good writeup of that is here:
// https://stackoverflow.com/a/37362173
// For our purposes currently we won't worry about this.
public override string ConcurrencyStamp { get => base.ConcurrencyStamp; set => base.ConcurrencyStamp = value; }
public override string? ConcurrencyStamp { get => base.ConcurrencyStamp; set => base.ConcurrencyStamp = value; }
/// <summary>
/// Gets or sets last login date
@@ -85,7 +85,7 @@ public abstract class UmbracoIdentityUser : IdentityUser, IRememberBeingDirty
/// <summary>
/// Gets or sets email
/// </summary>
public override string Email
public override string? Email
{
get => _email;
set => BeingDirty.SetPropertyValueAndDetectChanges(value, ref _email!, nameof(Email));
@@ -247,7 +247,7 @@ public abstract class UmbracoIdentityUser : IdentityUser, IRememberBeingDirty
/// <summary>
/// Gets or sets user name
/// </summary>
public override string UserName
public override string? UserName
{
get => _userName;
set => BeingDirty.SetPropertyValueAndDetectChanges(value, ref _userName!, nameof(UserName));

View File

@@ -134,8 +134,8 @@ public abstract class UmbracoUserManager<TUser, TPasswordConfig> : UserManager<T
/// <inheritdoc />
public override async Task<bool> CheckPasswordAsync(TUser user, string? password)
{
// we cannot proceed if the user passed in does not have an identity
if (user.HasIdentity == false)
// we cannot proceed if the user passed in does not have an identity, or if no password is provided.
if (user.HasIdentity == false || password is null)
{
return false;
}
@@ -158,10 +158,10 @@ public abstract class UmbracoUserManager<TUser, TPasswordConfig> : UserManager<T
/// is to generate a token and reset it, however, when we do this we want to track a password change, not a password
/// reset
/// </remarks>
public virtual async Task<IdentityResult> ChangePasswordWithResetAsync(string userId, string token, string? newPassword)
public virtual async Task<IdentityResult> ChangePasswordWithResetAsync(string userId, string token, string newPassword)
{
TUser user = await FindByIdAsync(userId);
if (user == null)
TUser? user = await FindByIdAsync(userId);
if (user is null)
{
throw new InvalidOperationException("Could not find user");
}
@@ -251,8 +251,8 @@ public abstract class UmbracoUserManager<TUser, TPasswordConfig> : UserManager<T
public async Task<bool> ValidateCredentialsAsync(string username, string password)
{
TUser user = await FindByNameAsync(username);
if (user == null)
TUser? user = await FindByNameAsync(username);
if (user is null)
{
return false;
}

View File

@@ -84,7 +84,7 @@ public abstract class UmbracoUserStore<TUser, TRole>
}
/// <inheritdoc />
public override Task<TUser> FindByIdAsync(string userId, CancellationToken cancellationToken = default) =>
public override Task<TUser?> FindByIdAsync(string userId, CancellationToken cancellationToken = default) =>
FindUserAsync(userId, cancellationToken);
/// <summary>
@@ -96,11 +96,11 @@ public abstract class UmbracoUserStore<TUser, TRole>
throw new NotImplementedException();
/// <inheritdoc />
public override Task<string> GetNormalizedEmailAsync(TUser user, CancellationToken cancellationToken)
public override Task<string?> GetNormalizedEmailAsync(TUser user, CancellationToken cancellationToken)
=> GetEmailAsync(user, cancellationToken);
/// <inheritdoc />
public override Task<string> GetNormalizedUserNameAsync(TUser user, CancellationToken cancellationToken = default)
public override Task<string?> GetNormalizedUserNameAsync(TUser user, CancellationToken cancellationToken = default)
=> GetUserNameAsync(user, cancellationToken);
/// <summary>
@@ -221,15 +221,15 @@ public abstract class UmbracoUserStore<TUser, TRole>
public override Task ReplaceClaimAsync(TUser user, Claim claim, Claim newClaim, CancellationToken cancellationToken = default) => throw new NotImplementedException();
/// <inheritdoc />
public override Task SetNormalizedEmailAsync(TUser user, string normalizedEmail, CancellationToken cancellationToken)
public override Task SetNormalizedEmailAsync(TUser user, string? normalizedEmail, CancellationToken cancellationToken)
=> SetEmailAsync(user, normalizedEmail, cancellationToken);
/// <inheritdoc />
public override Task SetNormalizedUserNameAsync(TUser user, string normalizedName, CancellationToken cancellationToken = default)
public override Task SetNormalizedUserNameAsync(TUser user, string? normalizedName, CancellationToken cancellationToken = default)
=> SetUserNameAsync(user, normalizedName, cancellationToken);
/// <inheritdoc />
public override async Task SetPasswordHashAsync(TUser user, string passwordHash, CancellationToken cancellationToken = default)
public override async Task SetPasswordHashAsync(TUser user, string? passwordHash, CancellationToken cancellationToken = default)
{
await base.SetPasswordHashAsync(user, passwordHash, cancellationToken);
user.LastPasswordChangeDateUtc = DateTime.UtcNow;
@@ -247,7 +247,7 @@ public abstract class UmbracoUserStore<TUser, TRole>
/// </summary>
/// <inheritdoc />
[EditorBrowsable(EditorBrowsableState.Never)]
protected override Task<IdentityUserToken<string>> FindTokenAsync(TUser user, string loginProvider, string name, CancellationToken cancellationToken) => throw new NotImplementedException();
protected override Task<IdentityUserToken<string>?> FindTokenAsync(TUser user, string loginProvider, string name, CancellationToken cancellationToken) => throw new NotImplementedException();
/// <summary>
/// Not supported in Umbraco, see comments above on GetTokenAsync, RemoveTokenAsync, SetTokenAsync

View File

@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<TargetFramework>net7.0</TargetFramework>
<RootNamespace>Umbraco.Cms.Infrastructure</RootNamespace>
<PackageId>Umbraco.Cms.Infrastructure</PackageId>
<Title>Umbraco CMS Infrastructure</Title>
@@ -24,6 +24,11 @@
<PackageReference Include="Markdown" Version="2.2.1" />
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="4.0.1" />
<PackageReference Include="Microsoft.CSharp" Version="4.7.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="7.0.0-preview.7.22375.6" />
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="7.0.0-preview.7.22375.6" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="7.0.0-preview.7.22375.6" />
<PackageReference Include="Microsoft.Extensions.Http" Version="7.0.0-preview.7.22375.6" />
<PackageReference Include="Microsoft.Extensions.Identity.Stores" Version="7.0.0-preview.7.22375.6" />
<PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="6.0.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="6.0.0" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="6.0.0" />
@@ -50,6 +55,9 @@
<PackageReference Include="Serilog.Sinks.Map" Version="1.0.2" />
<PackageReference Include="SixLabors.ImageSharp" Version="2.1.3" />
<PackageReference Include="System.IO.FileSystem.AccessControl" Version="5.0.0" />
<PackageReference Include="System.Text.Encodings.Web" Version="7.0.0-preview.7.22375.6" /> <!-- Explicit updated this nested dependency due to this https://github.com/dotnet/announcements/issues/178-->
<PackageReference Include="System.Threading.Tasks.Dataflow" Version="7.0.0-preview.7.22375.6" />
<PackageReference Include="Examine.Core" Version="3.0.0-beta.9" />
<PackageReference Include="System.Security.Cryptography.Pkcs" Version="6.0.1" />
<PackageReference Include="System.Text.Encodings.Web" Version="6.0.0" /> <!-- Explicit updated this nested dependency due to this https://github.com/dotnet/announcements/issues/178-->
<PackageReference Include="System.Threading.Tasks.Dataflow" Version="6.0.0" />

View File

@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<TargetFramework>net7.0</TargetFramework>
<RootNamespace>Umbraco.Cms.Infrastructure.PublishedCache</RootNamespace>
<PackageId>Umbraco.Cms.PublishedCache.NuCache</PackageId>
<Title>Umbraco CMS Published Cache</Title>

View File

@@ -186,11 +186,13 @@ public class AuthenticationController : UmbracoApiControllerBase
[ValidateAngularAntiForgeryToken]
public async Task<IActionResult> PostUnLinkLogin(UnLinkLoginModel unlinkLoginModel)
{
BackOfficeIdentityUser? user = await _userManager.FindByIdAsync(User.Identity?.GetUserId());
if (user == null)
var userId = User.Identity?.GetUserId();
if (userId is null)
{
throw new InvalidOperationException("Could not find user");
throw new InvalidOperationException("Could not find userId");
}
var user = await _userManager.FindByIdAsync(userId);
if (user == null) throw new InvalidOperationException("Could not find user");
AuthenticationScheme? authType = (await _signInManager.GetExternalAuthenticationSchemesAsync())
.FirstOrDefault(x => x.Name == unlinkLoginModel.LoginProvider);
@@ -487,12 +489,15 @@ public class AuthenticationController : UmbracoApiControllerBase
if (provider == "Email")
{
var mailMessage = new EmailMessage(from, user.Email, subject, message, true);
await _emailSender.SendAsync(mailMessage, Constants.Web.EmailTypes.TwoFactorAuth);
}
else if (provider == "Phone")
{
await _smsSender.SendSmsAsync(await _userManager.GetPhoneNumberAsync(user), message);
var phoneNumber = await _userManager.GetPhoneNumberAsync(user);
if (phoneNumber is not null)
{
await _smsSender.SendSmsAsync(phoneNumber, message);
}
}
return Ok();
@@ -544,6 +549,10 @@ public class AuthenticationController : UmbracoApiControllerBase
{
BackOfficeIdentityUser? identityUser =
await _userManager.FindByIdAsync(model.UserId.ToString(CultureInfo.InvariantCulture));
if (identityUser is null)
{
return new ValidationErrorResult("Could not find user");
}
IdentityResult result = await _userManager.ResetPasswordAsync(identityUser, model.ResetCode, model.Password);
if (result.Succeeded)

View File

@@ -379,7 +379,7 @@ public class BackOfficeController : UmbracoController
[HttpGet]
public async Task<IActionResult> ExternalLinkLoginCallback()
{
BackOfficeIdentityUser user = await _userManager.GetUserAsync(User);
BackOfficeIdentityUser? user = await _userManager.GetUserAsync(User);
if (user == null)
{
// ... this should really not happen
@@ -497,9 +497,8 @@ public class BackOfficeController : UmbracoController
}
else if (result == SignInResult.TwoFactorRequired)
{
BackOfficeIdentityUser? attemptedUser =
await _userManager.FindByLoginAsync(loginInfo.LoginProvider, loginInfo.ProviderKey);
if (attemptedUser == null)
BackOfficeIdentityUser? attemptedUser = await _userManager.FindByLoginAsync(loginInfo.LoginProvider, loginInfo.ProviderKey);
if (attemptedUser?.UserName is null)
{
return new ValidationErrorResult(
$"No local user found for the login provider {loginInfo.LoginProvider} - {loginInfo.ProviderKey}");

View File

@@ -376,7 +376,7 @@ namespace Umbraco.Cms.Web.BackOffice.Controllers
},
{
"currentUserApiBaseUrl", _linkGenerator.GetUmbracoApiServiceBaseUrl<CurrentUserController>(
controller => controller.PostChangePassword(new ChangingPasswordModel()))
controller => controller.PostSetAvatar(new List<IFormFile>()))
},
{
"entityApiBaseUrl", _linkGenerator.GetUmbracoApiServiceBaseUrl<EntityController>(

View File

@@ -198,12 +198,13 @@ public class CurrentUserController : UmbracoAuthorizedJsonController
[AllowAnonymous]
public async Task<ActionResult<UserDetail?>> PostSetInvitedUserPassword([FromBody] string newPassword)
{
BackOfficeIdentityUser? user = await _backOfficeUserManager.FindByIdAsync(_backofficeSecurityAccessor
.BackOfficeSecurity?.GetUserId().ResultOr(0).ToString());
if (user == null)
var userId = _backofficeSecurityAccessor.BackOfficeSecurity?.GetUserId().ResultOr(0).ToString();
if (userId is null)
{
throw new InvalidOperationException("Could not find user");
throw new InvalidOperationException("Could not find user Id");
}
var user = await _backOfficeUserManager.FindByIdAsync(userId);
if (user == null) throw new InvalidOperationException("Could not find user");
IdentityResult result = await _backOfficeUserManager.AddPasswordAsync(user, newPassword);
@@ -303,8 +304,18 @@ public class CurrentUserController : UmbracoAuthorizedJsonController
[ValidateAngularAntiForgeryToken]
public async Task<Dictionary<string, string>> GetCurrentUserLinkedLogins()
{
BackOfficeIdentityUser identityUser = await _backOfficeUserManager.FindByIdAsync(_backofficeSecurityAccessor
.BackOfficeSecurity?.GetUserId().ResultOr(0).ToString(CultureInfo.InvariantCulture));
var userId = _backofficeSecurityAccessor.BackOfficeSecurity?.GetUserId().ResultOr(0).ToString(CultureInfo.InvariantCulture);
if (userId is null)
{
throw new InvalidOperationException("Could not find user Id");
}
BackOfficeIdentityUser? identityUser = await _backOfficeUserManager.FindByIdAsync(userId);
if (identityUser is null)
{
throw new InvalidOperationException("Could not find user");
}
// deduplicate in case there are duplicates (there shouldn't be now since we have a unique constraint on the external logins
// but there didn't used to be)

View File

@@ -367,7 +367,7 @@ public class MemberController : ContentControllerBase
contentItem.IsApproved,
contentItem.Name);
IdentityResult created = await _memberManager.CreateAsync(identityMember, contentItem.Password?.NewPassword);
IdentityResult created = await _memberManager.CreateAsync(identityMember, contentItem.Password?.NewPassword!);
if (created.Succeeded == false)
{
@@ -513,8 +513,12 @@ public class MemberController : ContentControllerBase
}
var needsResync = false;
MemberIdentityUser identityMember = await _memberManager.FindByIdAsync(contentItem.Id?.ToString());
var memberId = contentItem.Id?.ToString();
if (memberId is null)
{
return ValidationProblem("Member was not found");
}
MemberIdentityUser? identityMember = await _memberManager.FindByIdAsync(memberId);
if (identityMember == null)
{
return ValidationProblem("Member was not found");

View File

@@ -65,7 +65,11 @@ public class TwoFactorLoginController : UmbracoAuthorizedJsonController
[HttpGet]
public async Task<ActionResult<IEnumerable<UserTwoFactorProviderModel>>> Get2FAProvidersForUser(int userId)
{
BackOfficeIdentityUser user = await _backOfficeUserManager.FindByIdAsync(userId.ToString(CultureInfo.InvariantCulture));
BackOfficeIdentityUser? user = await _backOfficeUserManager.FindByIdAsync(userId.ToString(CultureInfo.InvariantCulture));
if (user is null)
{
throw new InvalidOperationException("Could not find user");
}
var enabledProviderNameHashSet =
new HashSet<string>(await _twoFactorLoginService.GetEnabledTwoFactorProviderNamesAsync(user.Key));

View File

@@ -565,10 +565,20 @@ public class UsersController : BackOfficeNotificationsController
return new ActionResult<IUser?>(user);
}
private async Task SendUserInviteEmailAsync(UserBasic? userDisplay, string? from, string? fromEmail, IUser? to,
string? message)
private async Task SendUserInviteEmailAsync(UserBasic? userDisplay, string? from, string? fromEmail, IUser? to, string? message)
{
BackOfficeIdentityUser user = await _userManager.FindByIdAsync(((int?)userDisplay?.Id).ToString());
var userId = userDisplay?.Id?.ToString();
if (userId is null)
{
throw new InvalidOperationException("Could not find user Id");
}
var user = await _userManager.FindByIdAsync(userId);
if (user is null)
{
throw new InvalidOperationException("Could not find user");
}
var token = await _userManager.GenerateEmailConfirmationTokenAsync(user);
// Use info from SMTP Settings if configured, otherwise set fromEmail as fallback

View File

@@ -48,7 +48,7 @@ namespace Umbraco.Extensions
IEnumerable<LocalizedTextServiceSupplementaryFileSource> userLangFileSources = contentFileProvider.GetDirectoryContents(userConfigLangFolder)
.Where(x => x.IsDirectory && x.Name.InvariantEquals("lang"))
.Select(x => new DirectoryInfo(x.PhysicalPath))
.Select(x => new DirectoryInfo(x.PhysicalPath!))
.SelectMany(x => x.GetFiles("*.user.xml", SearchOption.TopDirectoryOnly))
.Select(x => new LocalizedTextServiceSupplementaryFileSource(x, true));
@@ -87,7 +87,7 @@ namespace Umbraco.Extensions
.GetDirectoryContents(langFolder)
.Where(x => !string.IsNullOrEmpty(x.PhysicalPath))
.Where(x => x.Name.InvariantEndsWith(".xml"))
.Select(x => new FileInfo(x.PhysicalPath));
.Select(x => new FileInfo(x.PhysicalPath!));
foreach (FileInfo file in localizationFiles)
{

View File

@@ -75,7 +75,7 @@ public class CreateUnattendedUserNotificationHandler : INotificationAsyncHandler
using IServiceScope scope = _serviceScopeFactory.CreateScope();
IBackOfficeUserManager backOfficeUserManager =
scope.ServiceProvider.GetRequiredService<IBackOfficeUserManager>();
BackOfficeIdentityUser membershipUser =
BackOfficeIdentityUser? membershipUser =
await backOfficeUserManager.FindByIdAsync(Constants.Security.SuperUserIdAsString);
if (membershipUser == null)
{

View File

@@ -88,9 +88,11 @@ public class InstallApiController : ControllerBase
{
await _runtime.RestartAsync();
BackOfficeIdentityUser identityUser =
await _backOfficeUserManager.FindByIdAsync(Constants.Security.SuperUserIdAsString);
BackOfficeIdentityUser? identityUser = await _backOfficeUserManager.FindByIdAsync(Constants.Security.SuperUserIdAsString);
if (identityUser is not null)
{
_backOfficeSignInManager.SignInAsync(identityUser, false);
}
return NoContent();
}

View File

@@ -1,4 +1,4 @@
using Microsoft.Extensions.Options;
using Microsoft.Extensions.Options;
using Umbraco.Cms.Core.Configuration.Models;
namespace Umbraco.Cms.Web.BackOffice.Middleware;
@@ -18,6 +18,6 @@ public sealed class ConfigureGlobalOptionsForKeepAliveMiddlware : IPostConfigure
/// </summary>
/// <param name="name"></param>
/// <param name="options"></param>
public void PostConfigure(string name, GlobalSettings options) =>
public void PostConfigure(string? name, GlobalSettings options) =>
options.ReservedUrls += _keepAliveSettings.Value.KeepAlivePingUrl;
}

View File

@@ -62,10 +62,10 @@ public class BackOfficeAuthenticationBuilder : AuthenticationBuilder
internal class EnsureBackOfficeScheme<TOptions> : IPostConfigureOptions<TOptions>
where TOptions : RemoteAuthenticationOptions
{
public void PostConfigure(string name, TOptions options)
public void PostConfigure(string? name, TOptions options)
{
// ensure logic only applies to backoffice authentication schemes
if (name.StartsWith(Constants.Security.BackOfficeExternalAuthenticationTypePrefix))
if (name is not null && name.StartsWith(Constants.Security.BackOfficeExternalAuthenticationTypePrefix))
{
options.SignInScheme = Constants.Security.BackOfficeExternalAuthenticationType;
}

View File

@@ -126,7 +126,12 @@ public class BackOfficeSessionIdValidator
}
var userId = currentIdentity.GetUserId();
BackOfficeIdentityUser? user = await _userManager.FindByIdAsync(userId);
if (userId is null)
{
return false;
}
var user = await _userManager.FindByIdAsync(userId);
if (user == null)
{
return false;

View File

@@ -117,7 +117,7 @@ public class BackOfficeSignInManager : UmbracoSignInManager<BackOfficeIdentityUs
/// <param name="redirectUrl">The external login URL users should be redirected to during the login flow.</param>
/// <param name="userId">The current user's identifier, which will be used to provide CSRF protection.</param>
/// <returns>A configured <see cref="AuthenticationProperties" />.</returns>
public override AuthenticationProperties ConfigureExternalAuthenticationProperties(string provider, string? redirectUrl, string? userId = null)
public override AuthenticationProperties ConfigureExternalAuthenticationProperties(string? provider, string? redirectUrl, string? userId = null)
{
// borrowed from https://github.com/dotnet/aspnetcore/blob/master/src/Identity/Core/src/SignInManager.cs
// to be able to use our own XsrfKey/LoginProviderKey because the default is private :/
@@ -197,7 +197,7 @@ public class BackOfficeSignInManager : UmbracoSignInManager<BackOfficeIdentityUs
}
//Now we need to perform the auto-link, so first we need to lookup/create a user with the email address
BackOfficeIdentityUser? autoLinkUser = await UserManager.FindByEmailAsync(email);
BackOfficeIdentityUser? autoLinkUser = await UserManager.FindByEmailAsync(email!);
if (autoLinkUser != null)
{
try
@@ -228,7 +228,7 @@ public class BackOfficeSignInManager : UmbracoSignInManager<BackOfficeIdentityUs
throw new InvalidOperationException("The Name value cannot be null");
}
autoLinkUser = BackOfficeIdentityUser.CreateNew(_globalSettings, email, email, autoLinkOptions.GetUserAutoLinkCulture(_globalSettings), name);
autoLinkUser = BackOfficeIdentityUser.CreateNew(_globalSettings, email, email!, autoLinkOptions.GetUserAutoLinkCulture(_globalSettings), name);
foreach (var userGroup in autoLinkOptions.DefaultUserGroups)
{

View File

@@ -80,7 +80,7 @@ public class ConfigureBackOfficeCookieOptions : IConfigureNamedOptions<CookieAut
}
/// <inheritdoc />
public void Configure(string name, CookieAuthenticationOptions options)
public void Configure(string? name, CookieAuthenticationOptions options)
{
if (name != Constants.Security.BackOfficeAuthenticationType)
{

View File

@@ -52,7 +52,7 @@ internal class PasswordChanger<TUser> : IPasswordChanger<TUser> where TUser : Um
}
var userId = changingPasswordModel.Id.ToString();
TUser identityUser = await userMgr.FindByIdAsync(userId);
TUser? identityUser = await userMgr.FindByIdAsync(userId);
if (identityUser == null)
{
// this really shouldn't ever happen... but just in case
@@ -96,7 +96,7 @@ internal class PasswordChanger<TUser> : IPasswordChanger<TUser> where TUser : Um
}
// can we change to the new password?
IdentityResult changeResult = await userMgr.ChangePasswordAsync(identityUser, changingPasswordModel.OldPassword, changingPasswordModel.NewPassword);
IdentityResult changeResult = await userMgr.ChangePasswordAsync(identityUser, changingPasswordModel.OldPassword!, changingPasswordModel.NewPassword);
if (changeResult.Succeeded == false)
{
// no, fail with error messages for "password"

View File

@@ -141,7 +141,7 @@ public class IconService : IIconService
IEnumerable<FileInfo> coreIcons = iconFolder
.Where(x => !x.IsDirectory && x.Name.EndsWith(".svg"))
.Select(x => new FileInfo(x.PhysicalPath));
.Select(x => new FileInfo(x.PhysicalPath!));
icons.UnionWith(coreIcons);

View File

@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<TargetFramework>net7.0</TargetFramework>
<OutputType>Library</OutputType>
<RootNamespace>Umbraco.Cms.Web.BackOffice</RootNamespace>
<PackageId>Umbraco.Cms.Web.BackOffice</PackageId>

View File

@@ -82,7 +82,7 @@ public class AspNetCoreHostingEnvironment : IHostingEnvironment
public Uri ApplicationMainUrl { get; private set; } = null!;
/// <inheritdoc />
public string SiteName { get; private set; } = null!;
public string? SiteName { get; private set; }
/// <inheritdoc />
public string ApplicationId

View File

@@ -44,10 +44,10 @@ public class AspNetCoreRequestAccessor : IRequestAccessor, INotificationHandler<
});
/// <inheritdoc />
public string GetRequestValue(string name) => GetFormValue(name) ?? GetQueryStringValue(name);
public string? GetRequestValue(string name) => GetFormValue(name) ?? GetQueryStringValue(name);
/// <inheritdoc />
public string GetQueryStringValue(string name) => _httpContextAccessor.GetRequiredHttpContext().Request.Query[name];
public string? GetQueryStringValue(string name) => _httpContextAccessor.GetRequiredHttpContext().Request.Query[name];
/// <inheritdoc />
public Uri? GetRequestUrl() => _httpContextAccessor.HttpContext != null

View File

@@ -15,7 +15,7 @@ internal class OptionsMonitorAdapter<T> : IOptionsMonitor<T>
public T CurrentValue { get; }
public T Get(string name) => CurrentValue;
public T Get(string? name) => CurrentValue;
public IDisposable OnChange(Action<T, string> listener) => throw new NotImplementedException();
}

View File

@@ -49,7 +49,7 @@ public static class FormCollectionExtensions
/// <param name="items"></param>
/// <param name="key"></param>
/// <returns></returns>
public static string GetRequiredString(this FormCollection items, string key)
public static string? GetRequiredString(this FormCollection items, string key)
{
if (items.HasKey(key) == false)
{

View File

@@ -65,7 +65,7 @@ public static class HttpContextExtensions
/// <summary>
/// Get the value in the request form or query string for the key
/// </summary>
public static string GetRequestValue(this HttpContext context, string key)
public static string? GetRequestValue(this HttpContext context, string key)
{
HttpRequest request = context.Request;
if (!request.HasFormContentType)
@@ -73,7 +73,7 @@ public static class HttpContextExtensions
return request.Query[key];
}
string value = request.Form[key];
string? value = request.Form[key];
return value ?? request.Query[key];
}

View File

@@ -70,7 +70,7 @@ public sealed class RoutableDocumentFilter : IRoutableDocumentFilter
return maybeDoc;
}
private void EndpointsChanged(object value)
private void EndpointsChanged(object? value)
{
lock (_routeLocker)
{

View File

@@ -90,7 +90,7 @@ public class BackOfficeUserManager : UmbracoUserManager<BackOfficeIdentityUser,
return result;
}
public override async Task<IdentityResult> ChangePasswordWithResetAsync(string userId, string token, string? newPassword)
public override async Task<IdentityResult> ChangePasswordWithResetAsync(string userId, string token, string newPassword)
{
IdentityResult result = await base.ChangePasswordWithResetAsync(userId, token, newPassword);
if (result.Succeeded)
@@ -101,7 +101,7 @@ public class BackOfficeUserManager : UmbracoUserManager<BackOfficeIdentityUser,
return result;
}
public override async Task<IdentityResult> ChangePasswordAsync(BackOfficeIdentityUser user, string? currentPassword, string? newPassword)
public override async Task<IdentityResult> ChangePasswordAsync(BackOfficeIdentityUser user, string currentPassword, string newPassword)
{
IdentityResult result = await base.ChangePasswordAsync(user, currentPassword, newPassword);
if (result.Succeeded)

View File

@@ -18,7 +18,7 @@ public sealed class ConfigureMemberCookieOptions : IConfigureNamedOptions<Cookie
_umbracoRequestPaths = umbracoRequestPaths;
}
public void Configure(string name, CookieAuthenticationOptions options)
public void Configure(string? name, CookieAuthenticationOptions options)
{
if (name == IdentityConstants.ApplicationScheme || name == IdentityConstants.ExternalScheme)
{

View File

@@ -21,11 +21,14 @@ public class ConfigureSecurityStampOptions : IConfigureOptions<SecurityStampVali
// to flow through to this new one.
options.OnRefreshingPrincipal = refreshingPrincipal =>
{
ClaimsIdentity newIdentity = refreshingPrincipal.NewPrincipal.Identities.First();
ClaimsIdentity currentIdentity = refreshingPrincipal.CurrentPrincipal.Identities.First();
ClaimsIdentity? newIdentity = refreshingPrincipal.NewPrincipal?.Identities.First();
ClaimsIdentity? currentIdentity = refreshingPrincipal.CurrentPrincipal?.Identities.First();
if (currentIdentity is not null)
{
// Since this is refreshing an existing principal, we want to merge all claims.
newIdentity.MergeAllClaims(currentIdentity);
newIdentity?.MergeAllClaims(currentIdentity);
}
return Task.CompletedTask;
};

View File

@@ -19,7 +19,7 @@ public interface IBackOfficeSignInManager
Task<ExternalLoginInfo?> GetExternalLoginInfoAsync(string? expectedXsrf = null);
Task<BackOfficeIdentityUser> GetTwoFactorAuthenticationUserAsync();
Task<BackOfficeIdentityUser?> GetTwoFactorAuthenticationUserAsync();
Task<SignInResult> PasswordSignInAsync(string userName, string password, bool isPersistent, bool lockoutOnFailure);
@@ -29,7 +29,7 @@ public interface IBackOfficeSignInManager
Task<ClaimsPrincipal> CreateUserPrincipalAsync(BackOfficeIdentityUser user);
Task<SignInResult> TwoFactorSignInAsync(string? provider, string? code, bool isPersistent, bool rememberClient);
Task<SignInResult> TwoFactorSignInAsync(string provider, string code, bool isPersistent, bool rememberClient);
Task<IdentityResult> UpdateExternalAuthenticationTokensAsync(ExternalLoginInfo externalLogin);
}

View File

@@ -21,7 +21,7 @@ public interface IMemberSignInManager
Task<SignInResult> ExternalLoginSignInAsync(ExternalLoginInfo loginInfo, bool isPersistent, bool bypassTwoFactor = false);
Task<MemberIdentityUser> GetTwoFactorAuthenticationUserAsync();
Task<MemberIdentityUser?> GetTwoFactorAuthenticationUserAsync();
Task<SignInResult> TwoFactorSignInAsync(string? provider, string? code, bool isPersistent, bool rememberClient);
Task<SignInResult> TwoFactorSignInAsync(string provider, string code, bool isPersistent, bool rememberClient);
}

View File

@@ -188,7 +188,7 @@ public class MemberManager : UmbracoUserManager<MemberIdentityUser, MemberPasswo
return null;
}
_currentMember = await GetUserAsync(_httpContextAccessor.HttpContext?.User);
_currentMember = await GetUserAsync(_httpContextAccessor.HttpContext?.User!);
}
return _currentMember;
@@ -204,7 +204,7 @@ public class MemberManager : UmbracoUserManager<MemberIdentityUser, MemberPasswo
private async Task<bool> HasAccessAsync(string path)
{
MemberIdentityUser? currentMember = await GetCurrentMemberAsync();
if (currentMember == null || !currentMember.IsApproved || currentMember.IsLockedOut)
if (currentMember?.UserName is null || !currentMember.IsApproved || currentMember.IsLockedOut)
{
return false;
}
@@ -220,7 +220,7 @@ public class MemberManager : UmbracoUserManager<MemberIdentityUser, MemberPasswo
var result = new Dictionary<string, bool>();
MemberIdentityUser? currentMember = await GetCurrentMemberAsync();
if (currentMember == null || !currentMember.IsApproved || currentMember.IsLockedOut)
if (currentMember?.UserName is null || !currentMember.IsApproved || currentMember.IsLockedOut)
{
return result;
}

View File

@@ -159,8 +159,8 @@ public class MemberSignInManager : UmbracoSignInManager<MemberIdentityUser>, IMe
}
public override AuthenticationProperties ConfigureExternalAuthenticationProperties(
string provider,
string redirectUrl,
string? provider,
string? redirectUrl,
string? userId = null)
{
// borrowed from https://github.com/dotnet/aspnetcore/blob/master/src/Identity/Core/src/SignInManager.cs
@@ -213,7 +213,7 @@ public class MemberSignInManager : UmbracoSignInManager<MemberIdentityUser>, IMe
}
// Now we need to perform the auto-link, so first we need to lookup/create a user with the email address
MemberIdentityUser? autoLinkUser = await UserManager.FindByEmailAsync(email);
MemberIdentityUser? autoLinkUser = await UserManager.FindByEmailAsync(email!);
if (autoLinkUser != null)
{
try
@@ -244,7 +244,7 @@ public class MemberSignInManager : UmbracoSignInManager<MemberIdentityUser>, IMe
throw new InvalidOperationException("The Name value cannot be null");
}
autoLinkUser = MemberIdentityUser.CreateNew(email, email, autoLinkOptions.DefaultMemberTypeAlias, autoLinkOptions.DefaultIsApproved, name);
autoLinkUser = MemberIdentityUser.CreateNew(email!, email!, autoLinkOptions.DefaultMemberTypeAlias, autoLinkOptions.DefaultIsApproved, name);
foreach (var userGroup in autoLinkOptions.DefaultMemberGroups)
{

View File

@@ -47,7 +47,7 @@ public class PublicAccessChecker : IPublicAccessChecker
return PublicAccessStatus.LockedOut;
}
if (!_publicAccessService.HasAccess(publishedContentId, _contentService, username, userRoles))
if (!_publicAccessService.HasAccess(publishedContentId, _contentService, username!, userRoles))
{
return PublicAccessStatus.AccessDenied;
}

View File

@@ -86,7 +86,7 @@ public abstract class UmbracoSignInManager<TUser> : SignInManager<TUser>
var providerKey = auth.Principal.FindFirstValue(ClaimTypes.NameIdentifier);
var provider = items[UmbracoSignInMgrLoginProviderKey];
if (providerKey == null || provider == null)
if (providerKey is null || provider is null)
{
return null;
}
@@ -102,14 +102,14 @@ public abstract class UmbracoSignInManager<TUser> : SignInManager<TUser>
}
/// <inheritdoc />
public override async Task<TUser> GetTwoFactorAuthenticationUserAsync()
public override async Task<TUser?> GetTwoFactorAuthenticationUserAsync()
{
// borrowed from https://github.com/dotnet/aspnetcore/blob/master/src/Identity/Core/src/SignInManager.cs
// replaced in order to use a custom auth type
TwoFactorAuthenticationInfo? info = await RetrieveTwoFactorInfoAsync();
if (info == null)
if (info?.UserId is null)
{
return null!;
return null;
}
return await UserManager.FindByIdAsync(info.UserId);
@@ -142,7 +142,7 @@ public abstract class UmbracoSignInManager<TUser> : SignInManager<TUser>
}
/// <inheritdoc />
public override async Task<SignInResult> TwoFactorSignInAsync(string? provider, string? code, bool isPersistent, bool rememberClient)
public override async Task<SignInResult> TwoFactorSignInAsync(string provider, string code, bool isPersistent, bool rememberClient)
{
// borrowed from https://github.com/dotnet/aspnetcore/blob/master/src/Identity/Core/src/SignInManager.cs#L552
// replaced in order to use a custom auth type and to implement logging/events

View File

@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<TargetFramework>net7.0</TargetFramework>
<OutputType>Library</OutputType>
<RootNamespace>Umbraco.Cms.Web.Common</RootNamespace>
<PackageId>Umbraco.Cms.Web.Common</PackageId>
@@ -9,7 +9,7 @@
<Description>Contains the Web assembly needed to run Umbraco Cms. This package only contains the assembly, and can be used for package development. Use the template in the Umbraco.Templates package to setup Umbraco</Description>
</PropertyGroup>
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<TargetFramework>net7.0</TargetFramework>
<OutputType>Library</OutputType>
<RootNamespace>Umbraco.Cms.Web.Common</RootNamespace>
<PackageId>Umbraco.Cms.Web.Common</PackageId>
@@ -35,6 +35,8 @@
<ItemGroup>
<PackageReference Include="Dazinator.Extensions.FileProviders" Version="2.0.0" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="7.0.0-preview.7.22375.6" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation" Version="7.0.0-preview.7.22375.6" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="6.0.5" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation" Version="6.0.5" />
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.1.1" PrivateAssets="all" />

View File

@@ -1,22 +1,38 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<TargetFramework>net7.0</TargetFramework>
<RootNamespace>Umbraco.Cms.Web.UI</RootNamespace>
<EnablePackageValidation>false</EnablePackageValidation>
</PropertyGroup>
<Import Project="..\Umbraco.Cms\buildTransitive\Umbraco.Cms.props" />
<PropertyGroup Condition="'$(Configuration)' == 'Release'">
<DocumentationFile>bin/Release/Umbraco.Web.UI.xml</DocumentationFile>
</PropertyGroup>
<PropertyGroup>
<CopyRazorGenerateFilesToPublishDirectory>true</CopyRazorGenerateFilesToPublishDirectory>
</PropertyGroup>
<Import Project="..\Umbraco.Cms\buildTransitive\Umbraco.Cms.props" />
<ItemGroup>
<ProjectReference Include="..\Umbraco.Cms\Umbraco.Cms.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="6.0.5" />
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.1.1" PrivateAssets="all" />
<PackageReference Include="Umbraco.Code" Version="2.0.0" PrivateAssets="all" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="7.0.0-preview.7.22375.6" />
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.1.1">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Umbraco.Code" Version="2.0.0">
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<!-- Opt-in to app-local ICU to ensure consistent globalization APIs across different platforms -->
<PackageReference Include="Microsoft.ICU.ICU4C.Runtime" Version="68.2.0.9" />
<RuntimeHostConfigurationOption Include="System.Globalization.AppLocalIcu" Value="68.2.0.9" Condition="$(RuntimeIdentifier.StartsWith('linux')) or $(RuntimeIdentifier.StartsWith('win')) or ('$(RuntimeIdentifier)' == '' and !$([MSBuild]::IsOSPlatform('osx')))" />
@@ -46,6 +62,8 @@
<CallTarget Targets="AppsettingsDevBuild" Condition="!Exists('appsettings.Development.json')" />
</Target>
<Target Name="JsonSchemaBuild">
<Exec Command="dotnet run -c Release --project $(JsonSchemaProjectPath) -o &quot;$(ProjectDir)appsettings-schema.json&quot;" />
</Target>
@@ -59,4 +77,5 @@
<Message Text="Generating appsettings.Development.json because it doesnt exist" Importance="High" />
<Copy SourceFiles="$(ProjectDir)appsettings.Development.template.json" DestinationFiles="$(ProjectDir)appsettings.Development.json" />
</Target>
</Project>

View File

@@ -111,7 +111,7 @@ public class UmbExternalLoginController : SurfaceController
if (result == SignInResult.TwoFactorRequired)
{
MemberIdentityUser attemptedUser =
MemberIdentityUser? attemptedUser =
await _memberManager.FindByLoginAsync(loginInfo.LoginProvider, loginInfo.ProviderKey);
if (attemptedUser == null!)
{
@@ -218,7 +218,7 @@ public class UmbExternalLoginController : SurfaceController
[HttpGet]
public async Task<IActionResult> ExternalLinkLoginCallback(string returnUrl)
{
MemberIdentityUser user = await _memberManager.GetUserAsync(User);
MemberIdentityUser? user = await _memberManager.GetUserAsync(User);
string? loginProvider = null;
var errors = new List<string>();
if (user == null!)
@@ -272,10 +272,20 @@ public class UmbExternalLoginController : SurfaceController
returnUrl = Request.GetEncodedPathAndQuery();
}
MemberIdentityUser user = await _memberManager.FindByIdAsync(User.Identity?.GetUserId());
var userId = User.Identity?.GetUserId();
if (userId is null)
{
return CurrentUmbracoPage();
}
MemberIdentityUser? user = await _memberManager.FindByIdAsync(userId);
if (user is null)
{
return CurrentUmbracoPage();
}
IdentityResult result = await _memberManager.RemoveLoginAsync(user, provider, providerKey);
if (result.Succeeded)
{
await _memberSignInManager.SignInAsync(user, false);
@@ -283,6 +293,7 @@ public class UmbExternalLoginController : SurfaceController
}
AddModelErrors(result);
return CurrentUmbracoPage();
}
}

View File

@@ -81,7 +81,7 @@ public class UmbLoginController : SurfaceController
if (result.RequiresTwoFactor)
{
MemberIdentityUser attemptedUser = await _memberManager.FindByNameAsync(model.Username);
MemberIdentityUser? attemptedUser = await _memberManager.FindByNameAsync(model.Username);
if (attemptedUser == null!)
{
return new ValidationErrorResult(

View File

@@ -51,7 +51,7 @@ public class ProfileModelBuilder : MemberModelBuilderBase
? null
: await memberManager.GetUserAsync(_httpContextAccessor.HttpContext.User);
if (member == null)
if (member?.Email is null || member?.UserName is null)
{
return null;
}

View File

@@ -62,9 +62,9 @@ public class MemberAuthenticationBuilder : AuthenticationBuilder
private class EnsureMemberScheme<TOptions> : IPostConfigureOptions<TOptions>
where TOptions : RemoteAuthenticationOptions
{
public void PostConfigure(string name, TOptions options)
public void PostConfigure(string? name, TOptions options)
{
if (!name.StartsWith(Constants.Security.MemberExternalAuthenticationTypePrefix))
if (name is null || !name.StartsWith(Constants.Security.MemberExternalAuthenticationTypePrefix))
{
return;
}

View File

@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<TargetFramework>net7.0</TargetFramework>
<OutputType>Library</OutputType>
<RootNamespace>Umbraco.Cms.Web.Website</RootNamespace>
<PackageId>Umbraco.Cms.Web.Website</PackageId>

View File

@@ -3,7 +3,7 @@
<Import Project="$([MSBuild]::GetPathOfFileAbove('Directory.Build.props', '$(MSBuildThisFileDirectory)../src/'))" />
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<TargetFramework>net7.0</TargetFramework>
<PackageType>Template</PackageType>
<IncludeBuildOutput>false</IncludeBuildOutput>
<ContentTargetFolders>.</ContentTargetFolders>

View File

@@ -1,6 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<TargetFramework>net7.0</TargetFramework>
<ContentTargetFolders>.</ContentTargetFolders>
<Product>UmbracoPackage</Product>
<PackageId>UmbracoPackage</PackageId>

View File

@@ -1,6 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<TargetFramework>net7.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<RootNamespace Condition="'$(name)' != '$(name{-VALUE-FORMS-}safe_namespace)'">Umbraco.Cms.Web.UI</RootNamespace>

View File

@@ -3,7 +3,7 @@
<PropertyGroup>
<IsPackable>false</IsPackable>
<RootNamespace>Umbraco.TestData</RootNamespace>
<TargetFramework>net6.0</TargetFramework>
<TargetFramework>net7.0</TargetFramework>
</PropertyGroup>
<ItemGroup>

View File

@@ -2,7 +2,7 @@
## Build
############################################
FROM mcr.microsoft.com/dotnet/sdk:6.0.300 AS build
FROM mcr.microsoft.com/dotnet/nightly/sdk:7.0 AS build
WORKDIR /nupkg
COPY nupkg .
@@ -17,7 +17,7 @@ RUN dotnet publish --no-restore --configuration Release -o /dist
## Run
############################################
FROM mcr.microsoft.com/dotnet/aspnet:6.0.5 AS run
FROM mcr.microsoft.com/dotnet/nightly/aspnet:7.0 AS run
WORKDIR /cypress
COPY --from=build dist .

View File

@@ -1,6 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<TargetFramework>net7.0</TargetFramework>
<OutputType>Exe</OutputType>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
<IsPackable>false</IsPackable>
@@ -26,7 +26,7 @@
<Version>0.13.1</Version>
</PackageReference>
<PackageReference Include="Microsoft.Extensions.Logging.Debug">
<Version>6.0.0</Version>
<Version>7.0.0-preview.7.22375.6</Version>
</PackageReference>
<PackageReference Include="Moq">
<Version>4.18.1</Version>

View File

@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<TargetFramework>net7.0</TargetFramework>
<RootNamespace>Umbraco.Cms.Tests.Common</RootNamespace>
<PackageId>Umbraco.Cms.Tests</PackageId>
<Title>Umbraco CMS Test Tools</Title>

View File

@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<TargetFramework>net7.0</TargetFramework>
<RootNamespace>Umbraco.Cms.Tests.Integration</RootNamespace>
<PackageId>Umbraco.Cms.Tests.Integration</PackageId>
<Title>Umbraco CMS Integration Tests</Title>
@@ -86,8 +86,8 @@
<ItemGroup>
<PackageReference Include="Examine.Lucene" Version="3.0.0" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="7.0.0-preview.7.22375.6" />
<PackageReference Include="Microsoft.AspNet.WebApi.Client" Version="5.2.9" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="6.0.5" />
<PackageReference Include="Bogus" Version="34.0.2" />
<PackageReference Include="Microsoft.ICU.ICU4C.Runtime" Version="68.2.0.9" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.1.0" />

View File

@@ -46,7 +46,7 @@ public class ModelTypeTests
// Note the inner assembly qualified name
Assert.AreEqual(
"System.Collections.Generic.IEnumerable`1[[System.Int32[], System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]]",
"System.Collections.Generic.IEnumerable`1[[System.Int32[], System.Private.CoreLib, Version=7.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]]",
typeof(IEnumerable<>).MakeGenericType(type.MakeArrayType()).FullName);
}

View File

@@ -15,10 +15,11 @@ public class MemberPasswordHasherTests
[Test]
[TestCase(
"Password123!",
"AQAAAAEAACcQAAAAEGF/tTVoL6ef3bQPZFYfbgKFu1CDQIAMgyY1N4EDt9jqdG/hsOX93X1U6LNvlIQ3mw==",
"AQAAAAIAAYagAAAAEJBorDjt+UEvw55UJVsbgAS6T2IGao+2XpCBbO3EKZoAMzoN+CNOpPdu1c0qrFcJVw==", null, ExpectedResult = PasswordVerificationResult.Success, Description = "AspNetCoreIdentityPasswordHash: Correct password")]
[TestCase("Password123!", "AQAAAAEAACcQAAAAEGF/tTVoL6ef3bQPZFYfbgKFu1CDQIAMgyY1N4EDt9jqdG/hsOX93X1U6LNvlIQ3mw==",
null,
ExpectedResult = PasswordVerificationResult.Success,
Description = "AspNetCoreIdentityPasswordHash: Correct password")]
ExpectedResult = PasswordVerificationResult.SuccessRehashNeeded,
Description = "GivenALegacyAspNetCoreIdentityPasswordHash: Correct password")]
[TestCase(
"wrongPassword",
"AQAAAAEAACcQAAAAEGF/tTVoL6ef3bQPZFYfbgKFu1CDQIAMgyY1N4EDt9jqdG/hsOX93X1U6LNvlIQ3mw==",

View File

@@ -2,7 +2,7 @@
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net6.0</TargetFramework>
<TargetFramework>net7.0</TargetFramework>
<RootNamespace>Umbraco.Cms.Tests.UnitTests</RootNamespace>
<IsPackable>false</IsPackable>
<IsTestProject>true</IsTestProject>
@@ -26,8 +26,8 @@
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.1.0" />
<PackageReference Include="NUnit" Version="3.13.3" />
<PackageReference Include="NUnit3TestAdapter" Version="4.2.1" />
<PackageReference Include="System.Data.Odbc" Version="6.0.0" />
<PackageReference Include="System.Data.OleDb" Version="6.0.0" />
<PackageReference Include="System.Data.Odbc" Version="7.0.0-preview.7.22375.6" />
<PackageReference Include="System.Data.OleDb" Version="7.0.0-preview.7.22375.6" />
</ItemGroup>
<ItemGroup>