Fix up service scoping in the EF Core xml repository and update package version to 2.2
This commit is contained in:
parent
8f7d995508
commit
7520ffa0ef
|
|
@ -79,10 +79,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.DataPr
|
||||||
EndProject
|
EndProject
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.DataProtection.EntityFrameworkCore.Test", "test\Microsoft.AspNetCore.DataProtection.EntityFrameworkCore.Test\Microsoft.AspNetCore.DataProtection.EntityFrameworkCore.Test.csproj", "{06728BF2-C5EB-44C7-9F30-14FAA5649E14}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.DataProtection.EntityFrameworkCore.Test", "test\Microsoft.AspNetCore.DataProtection.EntityFrameworkCore.Test\Microsoft.AspNetCore.DataProtection.EntityFrameworkCore.Test.csproj", "{06728BF2-C5EB-44C7-9F30-14FAA5649E14}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EntityFrameworkCore", "samples\EntityFrameworkCore\EntityFrameworkCore.csproj", "{E837A2E3-FC93-494C-8689-5AF9C6802AD7}"
|
|
||||||
EndProject
|
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.DataProtection.EntityFrameworkCore", "src\Microsoft.AspNetCore.DataProtection.EntityFrameworkCore\Microsoft.AspNetCore.DataProtection.EntityFrameworkCore.csproj", "{3E4CA7FE-741B-4C78-A775-220E0E3C1B03}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.DataProtection.EntityFrameworkCore", "src\Microsoft.AspNetCore.DataProtection.EntityFrameworkCore\Microsoft.AspNetCore.DataProtection.EntityFrameworkCore.csproj", "{3E4CA7FE-741B-4C78-A775-220E0E3C1B03}"
|
||||||
EndProject
|
EndProject
|
||||||
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EntityFrameworkCoreSample", "samples\EntityFrameworkCoreSample\EntityFrameworkCoreSample.csproj", "{22BA4EAB-641E-42B2-BB37-9C3BCFD99F76}"
|
||||||
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
Debug|Any CPU = Debug|Any CPU
|
Debug|Any CPU = Debug|Any CPU
|
||||||
|
|
@ -279,14 +279,6 @@ Global
|
||||||
{06728BF2-C5EB-44C7-9F30-14FAA5649E14}.Release|Any CPU.Build.0 = Release|Any CPU
|
{06728BF2-C5EB-44C7-9F30-14FAA5649E14}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
{06728BF2-C5EB-44C7-9F30-14FAA5649E14}.Release|x86.ActiveCfg = Release|Any CPU
|
{06728BF2-C5EB-44C7-9F30-14FAA5649E14}.Release|x86.ActiveCfg = Release|Any CPU
|
||||||
{06728BF2-C5EB-44C7-9F30-14FAA5649E14}.Release|x86.Build.0 = Release|Any CPU
|
{06728BF2-C5EB-44C7-9F30-14FAA5649E14}.Release|x86.Build.0 = Release|Any CPU
|
||||||
{E837A2E3-FC93-494C-8689-5AF9C6802AD7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
|
||||||
{E837A2E3-FC93-494C-8689-5AF9C6802AD7}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
|
||||||
{E837A2E3-FC93-494C-8689-5AF9C6802AD7}.Debug|x86.ActiveCfg = Debug|Any CPU
|
|
||||||
{E837A2E3-FC93-494C-8689-5AF9C6802AD7}.Debug|x86.Build.0 = Debug|Any CPU
|
|
||||||
{E837A2E3-FC93-494C-8689-5AF9C6802AD7}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
|
||||||
{E837A2E3-FC93-494C-8689-5AF9C6802AD7}.Release|Any CPU.Build.0 = Release|Any CPU
|
|
||||||
{E837A2E3-FC93-494C-8689-5AF9C6802AD7}.Release|x86.ActiveCfg = Release|Any CPU
|
|
||||||
{E837A2E3-FC93-494C-8689-5AF9C6802AD7}.Release|x86.Build.0 = Release|Any CPU
|
|
||||||
{3E4CA7FE-741B-4C78-A775-220E0E3C1B03}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
{3E4CA7FE-741B-4C78-A775-220E0E3C1B03}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
{3E4CA7FE-741B-4C78-A775-220E0E3C1B03}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{3E4CA7FE-741B-4C78-A775-220E0E3C1B03}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{3E4CA7FE-741B-4C78-A775-220E0E3C1B03}.Debug|x86.ActiveCfg = Debug|Any CPU
|
{3E4CA7FE-741B-4C78-A775-220E0E3C1B03}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||||
|
|
@ -295,6 +287,14 @@ Global
|
||||||
{3E4CA7FE-741B-4C78-A775-220E0E3C1B03}.Release|Any CPU.Build.0 = Release|Any CPU
|
{3E4CA7FE-741B-4C78-A775-220E0E3C1B03}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
{3E4CA7FE-741B-4C78-A775-220E0E3C1B03}.Release|x86.ActiveCfg = Release|Any CPU
|
{3E4CA7FE-741B-4C78-A775-220E0E3C1B03}.Release|x86.ActiveCfg = Release|Any CPU
|
||||||
{3E4CA7FE-741B-4C78-A775-220E0E3C1B03}.Release|x86.Build.0 = Release|Any CPU
|
{3E4CA7FE-741B-4C78-A775-220E0E3C1B03}.Release|x86.Build.0 = Release|Any CPU
|
||||||
|
{22BA4EAB-641E-42B2-BB37-9C3BCFD99F76}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{22BA4EAB-641E-42B2-BB37-9C3BCFD99F76}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{22BA4EAB-641E-42B2-BB37-9C3BCFD99F76}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||||
|
{22BA4EAB-641E-42B2-BB37-9C3BCFD99F76}.Debug|x86.Build.0 = Debug|Any CPU
|
||||||
|
{22BA4EAB-641E-42B2-BB37-9C3BCFD99F76}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{22BA4EAB-641E-42B2-BB37-9C3BCFD99F76}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{22BA4EAB-641E-42B2-BB37-9C3BCFD99F76}.Release|x86.ActiveCfg = Release|Any CPU
|
||||||
|
{22BA4EAB-641E-42B2-BB37-9C3BCFD99F76}.Release|x86.Build.0 = Release|Any CPU
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
|
|
@ -324,8 +324,8 @@ Global
|
||||||
{295E8539-5450-4764-B3F5-51F968628022} = {5A3A5DE3-49AD-431C-971D-B01B62D94AE2}
|
{295E8539-5450-4764-B3F5-51F968628022} = {5A3A5DE3-49AD-431C-971D-B01B62D94AE2}
|
||||||
{C85ED942-8121-453F-8308-9DB730843B63} = {60336AB3-948D-4D15-A5FB-F32A2B91E814}
|
{C85ED942-8121-453F-8308-9DB730843B63} = {60336AB3-948D-4D15-A5FB-F32A2B91E814}
|
||||||
{06728BF2-C5EB-44C7-9F30-14FAA5649E14} = {60336AB3-948D-4D15-A5FB-F32A2B91E814}
|
{06728BF2-C5EB-44C7-9F30-14FAA5649E14} = {60336AB3-948D-4D15-A5FB-F32A2B91E814}
|
||||||
{E837A2E3-FC93-494C-8689-5AF9C6802AD7} = {5A3A5DE3-49AD-431C-971D-B01B62D94AE2}
|
|
||||||
{3E4CA7FE-741B-4C78-A775-220E0E3C1B03} = {5FCB2DA3-5395-47F5-BCEE-E0EA319448EA}
|
{3E4CA7FE-741B-4C78-A775-220E0E3C1B03} = {5FCB2DA3-5395-47F5-BCEE-E0EA319448EA}
|
||||||
|
{22BA4EAB-641E-42B2-BB37-9C3BCFD99F76} = {5A3A5DE3-49AD-431C-971D-B01B62D94AE2}
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||||
SolutionGuid = {DD305D75-BD1B-43AE-BF04-869DA6A0858F}
|
SolutionGuid = {DD305D75-BD1B-43AE-BF04-869DA6A0858F}
|
||||||
|
|
|
||||||
|
|
@ -1,21 +0,0 @@
|
||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
|
||||||
|
|
||||||
using Microsoft.AspNetCore.DataProtection.EntityFrameworkCore;
|
|
||||||
using Microsoft.EntityFrameworkCore;
|
|
||||||
|
|
||||||
namespace EntityFrameworkCore
|
|
||||||
{
|
|
||||||
class DataProtectionKeyContext : DbContext, IDataProtectionKeyContext
|
|
||||||
{
|
|
||||||
public DataProtectionKeyContext(DbContextOptions<DataProtectionKeyContext> options) : base(options) { }
|
|
||||||
public DbSet<DataProtectionKey> DataProtectionKeys { get; set; }
|
|
||||||
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
|
|
||||||
{
|
|
||||||
base.OnConfiguring(optionsBuilder);
|
|
||||||
optionsBuilder.UseInMemoryDatabase("DataProtection_EntityFrameworkCore");
|
|
||||||
optionsBuilder.UseQueryTrackingBehavior(QueryTrackingBehavior.NoTracking);
|
|
||||||
optionsBuilder.EnableSensitiveDataLogging();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,27 +1,35 @@
|
||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
// Copyright (c) .NET Foundation. All rights reserved.
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
using System;
|
||||||
using Microsoft.AspNetCore.DataProtection;
|
using Microsoft.AspNetCore.DataProtection;
|
||||||
using Microsoft.AspNetCore.DataProtection.EntityFrameworkCore;
|
using Microsoft.AspNetCore.DataProtection.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using System;
|
|
||||||
|
|
||||||
namespace EntityFrameworkCore
|
namespace EntityFrameworkCoreSample
|
||||||
{
|
{
|
||||||
class Program
|
class Program
|
||||||
{
|
{
|
||||||
static void Main(string[] args)
|
static void Main(string[] args)
|
||||||
{
|
{
|
||||||
// Configure
|
// Configure
|
||||||
using (var services = new ServiceCollection()
|
var services = new ServiceCollection()
|
||||||
.AddLogging(o => o.AddConsole().SetMinimumLevel(LogLevel.Debug))
|
.AddLogging(o => o.AddConsole().SetMinimumLevel(LogLevel.Debug))
|
||||||
.AddDbContext<DataProtectionKeyContext>()
|
.AddDbContext<DataProtectionKeyContext>(o =>
|
||||||
|
{
|
||||||
|
o.UseInMemoryDatabase("DataProtection_EntityFrameworkCore");
|
||||||
|
o.UseQueryTrackingBehavior(QueryTrackingBehavior.NoTracking);
|
||||||
|
o.EnableSensitiveDataLogging();
|
||||||
|
})
|
||||||
.AddDataProtection()
|
.AddDataProtection()
|
||||||
.PersistKeysToDbContext<DataProtectionKeyContext>()
|
.PersistKeysToDbContext<DataProtectionKeyContext>()
|
||||||
.SetDefaultKeyLifetime(TimeSpan.FromDays(7))
|
.SetDefaultKeyLifetime(TimeSpan.FromDays(7))
|
||||||
.Services
|
.Services
|
||||||
.BuildServiceProvider(validateScopes: true))
|
.BuildServiceProvider(validateScopes: true);
|
||||||
|
|
||||||
|
using(services)
|
||||||
{
|
{
|
||||||
// Run a sample payload
|
// Run a sample payload
|
||||||
var protector = services.GetDataProtector("sample-purpose");
|
var protector = services.GetDataProtector("sample-purpose");
|
||||||
|
|
@ -30,4 +38,11 @@ namespace EntityFrameworkCore
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class DataProtectionKeyContext : DbContext, IDataProtectionKeyContext
|
||||||
|
{
|
||||||
|
public DataProtectionKeyContext(DbContextOptions<DataProtectionKeyContext> options) : base(options) { }
|
||||||
|
|
||||||
|
public DbSet<DataProtectionKey> DataProtectionKeys { get; set; }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -7,7 +7,7 @@ using Microsoft.Extensions.DependencyInjection;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using StackExchange.Redis;
|
using StackExchange.Redis;
|
||||||
|
|
||||||
namespace Redis
|
namespace RedisSample
|
||||||
{
|
{
|
||||||
public class Program
|
public class Program
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -1,22 +0,0 @@
|
||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
|
||||||
|
|
||||||
using Microsoft.AspNetCore.DataProtection.KeyManagement;
|
|
||||||
using Microsoft.AspNetCore.DataProtection.Repositories;
|
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
|
||||||
using Microsoft.Extensions.Options;
|
|
||||||
using System;
|
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.DataProtection.EntityFrameworkCore
|
|
||||||
{
|
|
||||||
internal class ConfigureKeyManagementOptions : IConfigureOptions<KeyManagementOptions>
|
|
||||||
{
|
|
||||||
private readonly IServiceProvider _serviceProvider;
|
|
||||||
|
|
||||||
public ConfigureKeyManagementOptions(IServiceProvider serviceProvider)
|
|
||||||
=> _serviceProvider = serviceProvider;
|
|
||||||
|
|
||||||
public void Configure(KeyManagementOptions options)
|
|
||||||
=> options.XmlRepository = _serviceProvider.CreateScope().ServiceProvider.GetRequiredService<IXmlRepository>();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,9 +1,6 @@
|
||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
// Copyright (c) .NET Foundation. All rights reserved.
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
using System.ComponentModel.DataAnnotations;
|
|
||||||
using System.ComponentModel.DataAnnotations.Schema;
|
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.DataProtection.EntityFrameworkCore
|
namespace Microsoft.AspNetCore.DataProtection.EntityFrameworkCore
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
@ -14,8 +11,6 @@ namespace Microsoft.AspNetCore.DataProtection.EntityFrameworkCore
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The entity identifier of the <see cref="DataProtectionKey"/>.
|
/// The entity identifier of the <see cref="DataProtectionKey"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Key]
|
|
||||||
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
|
|
||||||
public int Id { get; set; }
|
public int Id { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
|
||||||
|
|
@ -1,15 +1,15 @@
|
||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
// Copyright (c) .NET Foundation. All rights reserved.
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
using Microsoft.AspNetCore.DataProtection.EntityFrameworkCore;
|
||||||
using Microsoft.AspNetCore.DataProtection.KeyManagement;
|
using Microsoft.AspNetCore.DataProtection.KeyManagement;
|
||||||
using Microsoft.AspNetCore.DataProtection.Repositories;
|
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
|
using Microsoft.Extensions.Logging.Abstractions;
|
||||||
using Microsoft.Extensions.Options;
|
using Microsoft.Extensions.Options;
|
||||||
using System;
|
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.DataProtection.EntityFrameworkCore
|
namespace Microsoft.AspNetCore.DataProtection
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Extension method class for configuring instances of <see cref="EntityFrameworkCoreXmlRepository{TContext}"/>
|
/// Extension method class for configuring instances of <see cref="EntityFrameworkCoreXmlRepository{TContext}"/>
|
||||||
|
|
@ -24,22 +24,15 @@ namespace Microsoft.AspNetCore.DataProtection.EntityFrameworkCore
|
||||||
public static IDataProtectionBuilder PersistKeysToDbContext<TContext>(this IDataProtectionBuilder builder)
|
public static IDataProtectionBuilder PersistKeysToDbContext<TContext>(this IDataProtectionBuilder builder)
|
||||||
where TContext : DbContext, IDataProtectionKeyContext
|
where TContext : DbContext, IDataProtectionKeyContext
|
||||||
{
|
{
|
||||||
var services = builder.Services;
|
builder.Services.AddSingleton<IConfigureOptions<KeyManagementOptions>>(services =>
|
||||||
|
|
||||||
services.AddScoped<Func<TContext>>(
|
|
||||||
provider => new Func<TContext>(
|
|
||||||
() => provider.CreateScope().ServiceProvider.GetService<TContext>()));
|
|
||||||
|
|
||||||
services.AddScoped<IXmlRepository>(provider =>
|
|
||||||
{
|
{
|
||||||
var scope = provider.CreateScope();
|
var loggerFactory = services.GetService<ILoggerFactory>() ?? NullLoggerFactory.Instance;
|
||||||
return new EntityFrameworkCoreXmlRepository<TContext>(
|
return new ConfigureOptions<KeyManagementOptions>(options =>
|
||||||
contextFactory: scope.ServiceProvider.GetRequiredService<Func<TContext>>(),
|
{
|
||||||
loggerFactory: scope.ServiceProvider.GetService<ILoggerFactory>());
|
options.XmlRepository = new EntityFrameworkCoreXmlRepository<TContext>(services, loggerFactory);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
services.AddTransient<IConfigureOptions<KeyManagementOptions>, ConfigureKeyManagementOptions>();
|
|
||||||
|
|
||||||
return builder;
|
return builder;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,14 @@
|
||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
// Copyright (c) .NET Foundation. All rights reserved.
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
using Microsoft.AspNetCore.DataProtection.Repositories;
|
|
||||||
using Microsoft.EntityFrameworkCore;
|
|
||||||
using Microsoft.Extensions.Logging;
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Xml.Linq;
|
using System.Xml.Linq;
|
||||||
|
using Microsoft.AspNetCore.DataProtection.Repositories;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.DataProtection.EntityFrameworkCore
|
namespace Microsoft.AspNetCore.DataProtection.EntityFrameworkCore
|
||||||
{
|
{
|
||||||
|
|
@ -17,40 +18,51 @@ namespace Microsoft.AspNetCore.DataProtection.EntityFrameworkCore
|
||||||
public class EntityFrameworkCoreXmlRepository<TContext> : IXmlRepository
|
public class EntityFrameworkCoreXmlRepository<TContext> : IXmlRepository
|
||||||
where TContext : DbContext, IDataProtectionKeyContext
|
where TContext : DbContext, IDataProtectionKeyContext
|
||||||
{
|
{
|
||||||
private readonly ILoggerFactory _loggerFactory;
|
private readonly IServiceProvider _services;
|
||||||
private readonly Func<TContext> _contextFactory;
|
private readonly ILogger _logger;
|
||||||
|
|
||||||
private ILogger<EntityFrameworkCoreXmlRepository<TContext>> _logger => _loggerFactory?.CreateLogger<EntityFrameworkCoreXmlRepository<TContext>>();
|
|
||||||
|
|
||||||
private TContext _context => _contextFactory?.Invoke();
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Creates a new instance of the <see cref="EntityFrameworkCoreXmlRepository{TContext}"/>.
|
/// Creates a new instance of the <see cref="EntityFrameworkCoreXmlRepository{TContext}"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="contextFactory">The factory method that creates a context to store instances of <see cref="DataProtectionKey"/></param>
|
/// <param name="services"></param>
|
||||||
/// <param name="loggerFactory">The <see cref="ILoggerFactory"/>.</param>
|
/// <param name="loggerFactory">The <see cref="ILoggerFactory"/>.</param>
|
||||||
public EntityFrameworkCoreXmlRepository(Func<TContext> contextFactory, ILoggerFactory loggerFactory = null)
|
public EntityFrameworkCoreXmlRepository(IServiceProvider services, ILoggerFactory loggerFactory)
|
||||||
{
|
{
|
||||||
_contextFactory = contextFactory ?? throw new ArgumentNullException(nameof(contextFactory));
|
if (loggerFactory == null)
|
||||||
_loggerFactory = loggerFactory;
|
{
|
||||||
|
throw new ArgumentNullException(nameof(loggerFactory));
|
||||||
|
}
|
||||||
|
|
||||||
|
_logger = loggerFactory.CreateLogger<EntityFrameworkCoreXmlRepository<TContext>>();
|
||||||
|
_services = services ?? throw new ArgumentNullException(nameof(services));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public virtual IReadOnlyCollection<XElement> GetAllElements()
|
public virtual IReadOnlyCollection<XElement> GetAllElements()
|
||||||
=> _context?.Set<DataProtectionKey>()?.AsNoTracking().Select(key => TryParseKeyXml(key.Xml)).ToList().AsReadOnly();
|
{
|
||||||
|
using (var scope = _services.CreateScope())
|
||||||
|
{
|
||||||
|
var context = scope.ServiceProvider.GetRequiredService<TContext>();
|
||||||
|
return context.DataProtectionKeys.AsNoTracking().Select(key => TryParseKeyXml(key.Xml)).ToList().AsReadOnly();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public void StoreElement(XElement element, string friendlyName)
|
public void StoreElement(XElement element, string friendlyName)
|
||||||
{
|
{
|
||||||
var newKey = new DataProtectionKey()
|
using (var scope = _services.CreateScope())
|
||||||
{
|
{
|
||||||
FriendlyName = friendlyName,
|
var context = scope.ServiceProvider.GetRequiredService<TContext>();
|
||||||
Xml = element.ToString(SaveOptions.DisableFormatting)
|
var newKey = new DataProtectionKey()
|
||||||
};
|
{
|
||||||
var context = _context;
|
FriendlyName = friendlyName,
|
||||||
context?.Set<DataProtectionKey>()?.Add(newKey);
|
Xml = element.ToString(SaveOptions.DisableFormatting)
|
||||||
_logger?.LogSavingKeyToDbContext(friendlyName, typeof(TContext).Name);
|
};
|
||||||
context?.SaveChanges();
|
|
||||||
|
context.DataProtectionKeys.Add(newKey);
|
||||||
|
_logger.LogSavingKeyToDbContext(friendlyName, typeof(TContext).Name);
|
||||||
|
context.SaveChanges();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private XElement TryParseKeyXml(string xml)
|
private XElement TryParseKeyXml(string xml)
|
||||||
|
|
|
||||||
|
|
@ -1,16 +1,11 @@
|
||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<Description>EntityFramworkCore storage support as key store.</Description>
|
<Description>Support for storing keys using Entity Framework Core.</Description>
|
||||||
<VersionPrefix Condition="'$(ExperimentalVersionPrefix)' != ''">$(ExperimentalVersionPrefix)</VersionPrefix>
|
|
||||||
<VersionSuffix Condition="'$(ExperimentalVersionSuffix)' != ''">$(ExperimentalVersionSuffix)</VersionSuffix>
|
|
||||||
<VerifyVersion Condition="'$(ExperimentalVersionPrefix)' != ''">false</VerifyVersion>
|
|
||||||
<PackageVersion>$(ExperimentalPackageVersion)</PackageVersion>
|
|
||||||
<TargetFramework>netstandard2.0</TargetFramework>
|
<TargetFramework>netstandard2.0</TargetFramework>
|
||||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||||
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
||||||
<PackageTags>aspnetcore;dataprotection;entityframeworkcore</PackageTags>
|
<PackageTags>aspnetcore;dataprotection;entityframeworkcore</PackageTags>
|
||||||
<EnableApiCheck>false</EnableApiCheck>
|
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|
@ -21,4 +16,8 @@
|
||||||
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="$(MicrosoftEntityFrameworkCorePackageVersion)" />
|
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="$(MicrosoftEntityFrameworkCorePackageVersion)" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Folder Include="Properties\" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,203 @@
|
||||||
|
{
|
||||||
|
"AssemblyIdentity": "Microsoft.AspNetCore.DataProtection.EntityFrameworkCore, Version=2.2.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60",
|
||||||
|
"Types": [
|
||||||
|
{
|
||||||
|
"Name": "Microsoft.AspNetCore.DataProtection.EntityFrameworkCoreDataProtectionExtensions",
|
||||||
|
"Visibility": "Public",
|
||||||
|
"Kind": "Class",
|
||||||
|
"Abstract": true,
|
||||||
|
"Static": true,
|
||||||
|
"Sealed": true,
|
||||||
|
"ImplementedInterfaces": [],
|
||||||
|
"Members": [
|
||||||
|
{
|
||||||
|
"Kind": "Method",
|
||||||
|
"Name": "PersistKeysToDbContext<T0>",
|
||||||
|
"Parameters": [
|
||||||
|
{
|
||||||
|
"Name": "builder",
|
||||||
|
"Type": "Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"ReturnType": "Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder",
|
||||||
|
"Static": true,
|
||||||
|
"Extension": true,
|
||||||
|
"Visibility": "Public",
|
||||||
|
"GenericParameter": [
|
||||||
|
{
|
||||||
|
"ParameterName": "TContext",
|
||||||
|
"ParameterPosition": 0,
|
||||||
|
"BaseTypeOrInterfaces": [
|
||||||
|
"Microsoft.EntityFrameworkCore.DbContext",
|
||||||
|
"Microsoft.AspNetCore.DataProtection.EntityFrameworkCore.IDataProtectionKeyContext"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"GenericParameters": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Name": "Microsoft.AspNetCore.DataProtection.EntityFrameworkCore.DataProtectionKey",
|
||||||
|
"Visibility": "Public",
|
||||||
|
"Kind": "Class",
|
||||||
|
"ImplementedInterfaces": [],
|
||||||
|
"Members": [
|
||||||
|
{
|
||||||
|
"Kind": "Method",
|
||||||
|
"Name": "get_Id",
|
||||||
|
"Parameters": [],
|
||||||
|
"ReturnType": "System.Int32",
|
||||||
|
"Visibility": "Public",
|
||||||
|
"GenericParameter": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Kind": "Method",
|
||||||
|
"Name": "set_Id",
|
||||||
|
"Parameters": [
|
||||||
|
{
|
||||||
|
"Name": "value",
|
||||||
|
"Type": "System.Int32"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"ReturnType": "System.Void",
|
||||||
|
"Visibility": "Public",
|
||||||
|
"GenericParameter": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Kind": "Method",
|
||||||
|
"Name": "get_FriendlyName",
|
||||||
|
"Parameters": [],
|
||||||
|
"ReturnType": "System.String",
|
||||||
|
"Visibility": "Public",
|
||||||
|
"GenericParameter": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Kind": "Method",
|
||||||
|
"Name": "set_FriendlyName",
|
||||||
|
"Parameters": [
|
||||||
|
{
|
||||||
|
"Name": "value",
|
||||||
|
"Type": "System.String"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"ReturnType": "System.Void",
|
||||||
|
"Visibility": "Public",
|
||||||
|
"GenericParameter": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Kind": "Method",
|
||||||
|
"Name": "get_Xml",
|
||||||
|
"Parameters": [],
|
||||||
|
"ReturnType": "System.String",
|
||||||
|
"Visibility": "Public",
|
||||||
|
"GenericParameter": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Kind": "Method",
|
||||||
|
"Name": "set_Xml",
|
||||||
|
"Parameters": [
|
||||||
|
{
|
||||||
|
"Name": "value",
|
||||||
|
"Type": "System.String"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"ReturnType": "System.Void",
|
||||||
|
"Visibility": "Public",
|
||||||
|
"GenericParameter": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Kind": "Constructor",
|
||||||
|
"Name": ".ctor",
|
||||||
|
"Parameters": [],
|
||||||
|
"Visibility": "Public",
|
||||||
|
"GenericParameter": []
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"GenericParameters": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Name": "Microsoft.AspNetCore.DataProtection.EntityFrameworkCore.EntityFrameworkCoreXmlRepository<T0>",
|
||||||
|
"Visibility": "Public",
|
||||||
|
"Kind": "Class",
|
||||||
|
"ImplementedInterfaces": [
|
||||||
|
"Microsoft.AspNetCore.DataProtection.Repositories.IXmlRepository"
|
||||||
|
],
|
||||||
|
"Members": [
|
||||||
|
{
|
||||||
|
"Kind": "Method",
|
||||||
|
"Name": "GetAllElements",
|
||||||
|
"Parameters": [],
|
||||||
|
"ReturnType": "System.Collections.Generic.IReadOnlyCollection<System.Xml.Linq.XElement>",
|
||||||
|
"Virtual": true,
|
||||||
|
"ImplementedInterface": "Microsoft.AspNetCore.DataProtection.Repositories.IXmlRepository",
|
||||||
|
"Visibility": "Public",
|
||||||
|
"GenericParameter": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Kind": "Method",
|
||||||
|
"Name": "StoreElement",
|
||||||
|
"Parameters": [
|
||||||
|
{
|
||||||
|
"Name": "element",
|
||||||
|
"Type": "System.Xml.Linq.XElement"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Name": "friendlyName",
|
||||||
|
"Type": "System.String"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"ReturnType": "System.Void",
|
||||||
|
"Sealed": true,
|
||||||
|
"Virtual": true,
|
||||||
|
"ImplementedInterface": "Microsoft.AspNetCore.DataProtection.Repositories.IXmlRepository",
|
||||||
|
"Visibility": "Public",
|
||||||
|
"GenericParameter": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Kind": "Constructor",
|
||||||
|
"Name": ".ctor",
|
||||||
|
"Parameters": [
|
||||||
|
{
|
||||||
|
"Name": "services",
|
||||||
|
"Type": "System.IServiceProvider"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Name": "loggerFactory",
|
||||||
|
"Type": "Microsoft.Extensions.Logging.ILoggerFactory"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"Visibility": "Public",
|
||||||
|
"GenericParameter": []
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"GenericParameters": [
|
||||||
|
{
|
||||||
|
"ParameterName": "TContext",
|
||||||
|
"ParameterPosition": 0,
|
||||||
|
"BaseTypeOrInterfaces": [
|
||||||
|
"Microsoft.EntityFrameworkCore.DbContext",
|
||||||
|
"Microsoft.AspNetCore.DataProtection.EntityFrameworkCore.IDataProtectionKeyContext"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Name": "Microsoft.AspNetCore.DataProtection.EntityFrameworkCore.IDataProtectionKeyContext",
|
||||||
|
"Visibility": "Public",
|
||||||
|
"Kind": "Interface",
|
||||||
|
"Abstract": true,
|
||||||
|
"ImplementedInterfaces": [],
|
||||||
|
"Members": [
|
||||||
|
{
|
||||||
|
"Kind": "Method",
|
||||||
|
"Name": "get_DataProtectionKeys",
|
||||||
|
"Parameters": [],
|
||||||
|
"ReturnType": "Microsoft.EntityFrameworkCore.DbSet<Microsoft.AspNetCore.DataProtection.EntityFrameworkCore.DataProtectionKey>",
|
||||||
|
"GenericParameter": []
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"GenericParameters": []
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
@ -1,12 +1,14 @@
|
||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
// Copyright (c) .NET Foundation. All rights reserved.
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
using Microsoft.AspNetCore.DataProtection.EntityFrameworkCore;
|
|
||||||
using Microsoft.AspNetCore.DataProtection.EntityFrameworkCore.Test;
|
|
||||||
using Microsoft.EntityFrameworkCore;
|
|
||||||
using System;
|
using System;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Xml.Linq;
|
using System.Xml.Linq;
|
||||||
|
using Microsoft.AspNetCore.DataProtection.EntityFrameworkCore;
|
||||||
|
using Microsoft.AspNetCore.DataProtection.EntityFrameworkCore.Test;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using Microsoft.Extensions.Logging.Abstractions;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.DataProtection
|
namespace Microsoft.AspNetCore.DataProtection
|
||||||
|
|
@ -16,7 +18,7 @@ namespace Microsoft.AspNetCore.DataProtection
|
||||||
[Fact]
|
[Fact]
|
||||||
public void CreateRepository_ThrowsIf_ContextIsNull()
|
public void CreateRepository_ThrowsIf_ContextIsNull()
|
||||||
{
|
{
|
||||||
Assert.Throws<ArgumentNullException>(() => new EntityFrameworkCoreXmlRepository<DataProtectionKeyContext>(null));
|
Assert.Throws<ArgumentNullException>(() => new EntityFrameworkCoreXmlRepository<DataProtectionKeyContext>(null, null));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
|
|
@ -25,13 +27,13 @@ namespace Microsoft.AspNetCore.DataProtection
|
||||||
var element = XElement.Parse("<Element1/>");
|
var element = XElement.Parse("<Element1/>");
|
||||||
var friendlyName = "Element1";
|
var friendlyName = "Element1";
|
||||||
var key = new DataProtectionKey() { FriendlyName = friendlyName, Xml = element.ToString() };
|
var key = new DataProtectionKey() { FriendlyName = friendlyName, Xml = element.ToString() };
|
||||||
using (var context = BuildDataProtectionKeyContext(nameof(StoreElement_PersistsData)))
|
|
||||||
{
|
var services = GetServices(nameof(StoreElement_PersistsData));
|
||||||
var service = new EntityFrameworkCoreXmlRepository<DataProtectionKeyContext>(() => context);
|
var service = new EntityFrameworkCoreXmlRepository<DataProtectionKeyContext>(services, NullLoggerFactory.Instance);
|
||||||
service.StoreElement(element, friendlyName);
|
service.StoreElement(element, friendlyName);
|
||||||
}
|
|
||||||
// Use a separate instance of the context to verify correct data was saved to database
|
// Use a separate instance of the context to verify correct data was saved to database
|
||||||
using (var context = BuildDataProtectionKeyContext(nameof(StoreElement_PersistsData)))
|
using (var context = services.CreateScope().ServiceProvider.GetRequiredService< DataProtectionKeyContext>())
|
||||||
{
|
{
|
||||||
Assert.Equal(1, context.DataProtectionKeys.Count());
|
Assert.Equal(1, context.DataProtectionKeys.Count());
|
||||||
Assert.Equal(key.FriendlyName, context.DataProtectionKeys.Single()?.FriendlyName);
|
Assert.Equal(key.FriendlyName, context.DataProtectionKeys.Single()?.FriendlyName);
|
||||||
|
|
@ -44,25 +46,24 @@ namespace Microsoft.AspNetCore.DataProtection
|
||||||
{
|
{
|
||||||
var element1 = XElement.Parse("<Element1/>");
|
var element1 = XElement.Parse("<Element1/>");
|
||||||
var element2 = XElement.Parse("<Element2/>");
|
var element2 = XElement.Parse("<Element2/>");
|
||||||
using (var context = BuildDataProtectionKeyContext(nameof(GetAllElements_ReturnsAllElements)))
|
|
||||||
{
|
var services = GetServices(nameof(GetAllElements_ReturnsAllElements));
|
||||||
var service = new EntityFrameworkCoreXmlRepository<DataProtectionKeyContext>(() => context);
|
var service1 = CreateRepo(services);
|
||||||
service.StoreElement(element1, "element1");
|
service1.StoreElement(element1, "element1");
|
||||||
service.StoreElement(element2, "element2");
|
service1.StoreElement(element2, "element2");
|
||||||
}
|
|
||||||
// Use a separate instance of the context to verify correct data was saved to database
|
// Use a separate instance of the context to verify correct data was saved to database
|
||||||
using (var context = BuildDataProtectionKeyContext(nameof(GetAllElements_ReturnsAllElements)))
|
var service2 = CreateRepo(services);
|
||||||
{
|
var elements = service2.GetAllElements();
|
||||||
var service = new EntityFrameworkCoreXmlRepository<DataProtectionKeyContext>(() => context);
|
Assert.Equal(2, elements.Count);
|
||||||
var elements = service.GetAllElements();
|
|
||||||
Assert.Equal(2, elements.Count);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private DbContextOptions<DataProtectionKeyContext> BuildDbContextOptions(string databaseName)
|
private EntityFrameworkCoreXmlRepository<DataProtectionKeyContext> CreateRepo(IServiceProvider services)
|
||||||
=> new DbContextOptionsBuilder<DataProtectionKeyContext>().UseInMemoryDatabase(databaseName: databaseName).Options;
|
=> new EntityFrameworkCoreXmlRepository<DataProtectionKeyContext>(services, NullLoggerFactory.Instance);
|
||||||
|
|
||||||
private DataProtectionKeyContext BuildDataProtectionKeyContext(string databaseName)
|
private IServiceProvider GetServices(string dbName)
|
||||||
=> new DataProtectionKeyContext(BuildDbContextOptions(databaseName));
|
=> new ServiceCollection()
|
||||||
|
.AddDbContext<DataProtectionKeyContext>(o => o.UseInMemoryDatabase(dbName))
|
||||||
|
.BuildServiceProvider(validateScopes: true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,7 @@ namespace Microsoft.AspNetCore.DataProtection.EntityFrameworkCore.Test
|
||||||
.AddDbContext<DataProtectionKeyContext>()
|
.AddDbContext<DataProtectionKeyContext>()
|
||||||
.AddDataProtection()
|
.AddDataProtection()
|
||||||
.PersistKeysToDbContext<DataProtectionKeyContext>();
|
.PersistKeysToDbContext<DataProtectionKeyContext>();
|
||||||
var serviceProvider = serviceCollection.BuildServiceProvider();
|
var serviceProvider = serviceCollection.BuildServiceProvider(validateScopes: true);
|
||||||
var keyManagementOptions = serviceProvider.GetRequiredService<IOptions<KeyManagementOptions>>();
|
var keyManagementOptions = serviceProvider.GetRequiredService<IOptions<KeyManagementOptions>>();
|
||||||
Assert.IsType<EntityFrameworkCoreXmlRepository<DataProtectionKeyContext>>(keyManagementOptions.Value.XmlRepository);
|
Assert.IsType<EntityFrameworkCoreXmlRepository<DataProtectionKeyContext>>(keyManagementOptions.Value.XmlRepository);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue