Make roles optional in Extensions.Identity
This commit is contained in:
parent
f91e3ff342
commit
f555a26b4a
|
|
@ -0,0 +1,224 @@
|
|||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio 15
|
||||
VisualStudioVersion = 15.0.26507.0
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{0F647068-6602-4E24-B1DC-8ED91481A50A}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{52D59F18-62D2-4D17-8CF2-BE192445AF8E}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Identity", "src\Microsoft.AspNetCore.Identity\Microsoft.AspNetCore.Identity.csproj", "{1729302E-A58E-4652-B639-5B6B68DA2748}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Identity.Test", "test\Microsoft.AspNetCore.Identity.Test\Microsoft.AspNetCore.Identity.Test.csproj", "{2CF3927B-19E4-4866-9BAA-2C131580E7C3}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Identity.InMemory.Test", "test\Microsoft.AspNetCore.Identity.InMemory.Test\Microsoft.AspNetCore.Identity.InMemory.Test.csproj", "{65161409-C4C4-4D63-A73B-231FCFF4D503}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "samples", "samples", "{58D94A0E-C2B7-43A7-8826-99ECBB1E0A50}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "IdentitySample.Mvc", "samples\IdentitySample.Mvc\IdentitySample.Mvc.csproj", "{E1BFA023-CFFD-49CE-8466-1C28DD2EC1F6}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Identity.EntityFrameworkCore.Test", "test\Microsoft.AspNetCore.Identity.EntityFrameworkCore.Test\Microsoft.AspNetCore.Identity.EntityFrameworkCore.Test.csproj", "{37236EA3-915D-46D5-997C-DF513C500E4B}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Identity.EntityFrameworkCore.InMemory.Test", "test\Microsoft.AspNetCore.Identity.EntityFrameworkCore.InMemory.Test\Microsoft.AspNetCore.Identity.EntityFrameworkCore.InMemory.Test.csproj", "{EA7EB28F-53B8-4009-9C6B-74DB090CA8DD}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Identity.EntityFrameworkCore", "src\Microsoft.AspNetCore.Identity.EntityFrameworkCore\Microsoft.AspNetCore.Identity.EntityFrameworkCore.csproj", "{4490894C-3572-4E63-86F1-EE5105CE8A06}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNet.Identity.AspNetCoreCompat", "src\Microsoft.AspNet.Identity.AspNetCoreCompat\Microsoft.AspNet.Identity.AspNetCoreCompat.csproj", "{6A74C6EA-B241-4D6B-BCE4-BF89EC1D2475}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Identity.Specification.Tests", "src\Microsoft.AspNetCore.Identity.Specification.Tests\Microsoft.AspNetCore.Identity.Specification.Tests.csproj", "{5608E828-DD54-4E2A-B73C-FC22268BE797}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Extensions.Identity.Core", "src\Microsoft.Extensions.Identity.Core\Microsoft.Extensions.Identity.Core.csproj", "{D5905D78-A32E-44B8-8F21-EDAEDC95D9B8}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Extensions.Identity.Stores", "src\Microsoft.Extensions.Identity.Stores\Microsoft.Extensions.Identity.Stores.csproj", "{FADA11FC-DC06-4832-A569-7B2374A6CD42}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Debug|Mixed Platforms = Debug|Mixed Platforms
|
||||
Debug|x64 = Debug|x64
|
||||
Debug|x86 = Debug|x86
|
||||
Release|Any CPU = Release|Any CPU
|
||||
Release|Mixed Platforms = Release|Mixed Platforms
|
||||
Release|x64 = Release|x64
|
||||
Release|x86 = Release|x86
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{1729302E-A58E-4652-B639-5B6B68DA2748}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{1729302E-A58E-4652-B639-5B6B68DA2748}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{1729302E-A58E-4652-B639-5B6B68DA2748}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
|
||||
{1729302E-A58E-4652-B639-5B6B68DA2748}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
|
||||
{1729302E-A58E-4652-B639-5B6B68DA2748}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{1729302E-A58E-4652-B639-5B6B68DA2748}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{1729302E-A58E-4652-B639-5B6B68DA2748}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{1729302E-A58E-4652-B639-5B6B68DA2748}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{1729302E-A58E-4652-B639-5B6B68DA2748}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{1729302E-A58E-4652-B639-5B6B68DA2748}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
|
||||
{1729302E-A58E-4652-B639-5B6B68DA2748}.Release|Mixed Platforms.Build.0 = Release|Any CPU
|
||||
{1729302E-A58E-4652-B639-5B6B68DA2748}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{1729302E-A58E-4652-B639-5B6B68DA2748}.Release|x64.Build.0 = Release|Any CPU
|
||||
{1729302E-A58E-4652-B639-5B6B68DA2748}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{2CF3927B-19E4-4866-9BAA-2C131580E7C3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{2CF3927B-19E4-4866-9BAA-2C131580E7C3}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{2CF3927B-19E4-4866-9BAA-2C131580E7C3}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
|
||||
{2CF3927B-19E4-4866-9BAA-2C131580E7C3}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
|
||||
{2CF3927B-19E4-4866-9BAA-2C131580E7C3}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{2CF3927B-19E4-4866-9BAA-2C131580E7C3}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{2CF3927B-19E4-4866-9BAA-2C131580E7C3}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{2CF3927B-19E4-4866-9BAA-2C131580E7C3}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{2CF3927B-19E4-4866-9BAA-2C131580E7C3}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{2CF3927B-19E4-4866-9BAA-2C131580E7C3}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
|
||||
{2CF3927B-19E4-4866-9BAA-2C131580E7C3}.Release|Mixed Platforms.Build.0 = Release|Any CPU
|
||||
{2CF3927B-19E4-4866-9BAA-2C131580E7C3}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{2CF3927B-19E4-4866-9BAA-2C131580E7C3}.Release|x64.Build.0 = Release|Any CPU
|
||||
{2CF3927B-19E4-4866-9BAA-2C131580E7C3}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{65161409-C4C4-4D63-A73B-231FCFF4D503}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{65161409-C4C4-4D63-A73B-231FCFF4D503}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{65161409-C4C4-4D63-A73B-231FCFF4D503}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
|
||||
{65161409-C4C4-4D63-A73B-231FCFF4D503}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
|
||||
{65161409-C4C4-4D63-A73B-231FCFF4D503}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{65161409-C4C4-4D63-A73B-231FCFF4D503}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{65161409-C4C4-4D63-A73B-231FCFF4D503}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{65161409-C4C4-4D63-A73B-231FCFF4D503}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{65161409-C4C4-4D63-A73B-231FCFF4D503}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{65161409-C4C4-4D63-A73B-231FCFF4D503}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
|
||||
{65161409-C4C4-4D63-A73B-231FCFF4D503}.Release|Mixed Platforms.Build.0 = Release|Any CPU
|
||||
{65161409-C4C4-4D63-A73B-231FCFF4D503}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{65161409-C4C4-4D63-A73B-231FCFF4D503}.Release|x64.Build.0 = Release|Any CPU
|
||||
{65161409-C4C4-4D63-A73B-231FCFF4D503}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{E1BFA023-CFFD-49CE-8466-1C28DD2EC1F6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{E1BFA023-CFFD-49CE-8466-1C28DD2EC1F6}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{E1BFA023-CFFD-49CE-8466-1C28DD2EC1F6}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
|
||||
{E1BFA023-CFFD-49CE-8466-1C28DD2EC1F6}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
|
||||
{E1BFA023-CFFD-49CE-8466-1C28DD2EC1F6}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{E1BFA023-CFFD-49CE-8466-1C28DD2EC1F6}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{E1BFA023-CFFD-49CE-8466-1C28DD2EC1F6}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{E1BFA023-CFFD-49CE-8466-1C28DD2EC1F6}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{E1BFA023-CFFD-49CE-8466-1C28DD2EC1F6}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{E1BFA023-CFFD-49CE-8466-1C28DD2EC1F6}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
|
||||
{E1BFA023-CFFD-49CE-8466-1C28DD2EC1F6}.Release|Mixed Platforms.Build.0 = Release|Any CPU
|
||||
{E1BFA023-CFFD-49CE-8466-1C28DD2EC1F6}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{E1BFA023-CFFD-49CE-8466-1C28DD2EC1F6}.Release|x64.Build.0 = Release|Any CPU
|
||||
{E1BFA023-CFFD-49CE-8466-1C28DD2EC1F6}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{37236EA3-915D-46D5-997C-DF513C500E4B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{37236EA3-915D-46D5-997C-DF513C500E4B}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{37236EA3-915D-46D5-997C-DF513C500E4B}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
|
||||
{37236EA3-915D-46D5-997C-DF513C500E4B}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
|
||||
{37236EA3-915D-46D5-997C-DF513C500E4B}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{37236EA3-915D-46D5-997C-DF513C500E4B}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{37236EA3-915D-46D5-997C-DF513C500E4B}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{37236EA3-915D-46D5-997C-DF513C500E4B}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{37236EA3-915D-46D5-997C-DF513C500E4B}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{37236EA3-915D-46D5-997C-DF513C500E4B}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
|
||||
{37236EA3-915D-46D5-997C-DF513C500E4B}.Release|Mixed Platforms.Build.0 = Release|Any CPU
|
||||
{37236EA3-915D-46D5-997C-DF513C500E4B}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{37236EA3-915D-46D5-997C-DF513C500E4B}.Release|x64.Build.0 = Release|Any CPU
|
||||
{37236EA3-915D-46D5-997C-DF513C500E4B}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{EA7EB28F-53B8-4009-9C6B-74DB090CA8DD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{EA7EB28F-53B8-4009-9C6B-74DB090CA8DD}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{EA7EB28F-53B8-4009-9C6B-74DB090CA8DD}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
|
||||
{EA7EB28F-53B8-4009-9C6B-74DB090CA8DD}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
|
||||
{EA7EB28F-53B8-4009-9C6B-74DB090CA8DD}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{EA7EB28F-53B8-4009-9C6B-74DB090CA8DD}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{EA7EB28F-53B8-4009-9C6B-74DB090CA8DD}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{EA7EB28F-53B8-4009-9C6B-74DB090CA8DD}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{EA7EB28F-53B8-4009-9C6B-74DB090CA8DD}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{EA7EB28F-53B8-4009-9C6B-74DB090CA8DD}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
|
||||
{EA7EB28F-53B8-4009-9C6B-74DB090CA8DD}.Release|Mixed Platforms.Build.0 = Release|Any CPU
|
||||
{EA7EB28F-53B8-4009-9C6B-74DB090CA8DD}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{EA7EB28F-53B8-4009-9C6B-74DB090CA8DD}.Release|x64.Build.0 = Release|Any CPU
|
||||
{EA7EB28F-53B8-4009-9C6B-74DB090CA8DD}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{4490894C-3572-4E63-86F1-EE5105CE8A06}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{4490894C-3572-4E63-86F1-EE5105CE8A06}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{4490894C-3572-4E63-86F1-EE5105CE8A06}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
|
||||
{4490894C-3572-4E63-86F1-EE5105CE8A06}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
|
||||
{4490894C-3572-4E63-86F1-EE5105CE8A06}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{4490894C-3572-4E63-86F1-EE5105CE8A06}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{4490894C-3572-4E63-86F1-EE5105CE8A06}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{4490894C-3572-4E63-86F1-EE5105CE8A06}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{4490894C-3572-4E63-86F1-EE5105CE8A06}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{4490894C-3572-4E63-86F1-EE5105CE8A06}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
|
||||
{4490894C-3572-4E63-86F1-EE5105CE8A06}.Release|Mixed Platforms.Build.0 = Release|Any CPU
|
||||
{4490894C-3572-4E63-86F1-EE5105CE8A06}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{4490894C-3572-4E63-86F1-EE5105CE8A06}.Release|x64.Build.0 = Release|Any CPU
|
||||
{4490894C-3572-4E63-86F1-EE5105CE8A06}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{6A74C6EA-B241-4D6B-BCE4-BF89EC1D2475}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{6A74C6EA-B241-4D6B-BCE4-BF89EC1D2475}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{6A74C6EA-B241-4D6B-BCE4-BF89EC1D2475}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
|
||||
{6A74C6EA-B241-4D6B-BCE4-BF89EC1D2475}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
|
||||
{6A74C6EA-B241-4D6B-BCE4-BF89EC1D2475}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{6A74C6EA-B241-4D6B-BCE4-BF89EC1D2475}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{6A74C6EA-B241-4D6B-BCE4-BF89EC1D2475}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{6A74C6EA-B241-4D6B-BCE4-BF89EC1D2475}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{6A74C6EA-B241-4D6B-BCE4-BF89EC1D2475}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{6A74C6EA-B241-4D6B-BCE4-BF89EC1D2475}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{6A74C6EA-B241-4D6B-BCE4-BF89EC1D2475}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
|
||||
{6A74C6EA-B241-4D6B-BCE4-BF89EC1D2475}.Release|Mixed Platforms.Build.0 = Release|Any CPU
|
||||
{6A74C6EA-B241-4D6B-BCE4-BF89EC1D2475}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{6A74C6EA-B241-4D6B-BCE4-BF89EC1D2475}.Release|x64.Build.0 = Release|Any CPU
|
||||
{6A74C6EA-B241-4D6B-BCE4-BF89EC1D2475}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{6A74C6EA-B241-4D6B-BCE4-BF89EC1D2475}.Release|x86.Build.0 = Release|Any CPU
|
||||
{5608E828-DD54-4E2A-B73C-FC22268BE797}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{5608E828-DD54-4E2A-B73C-FC22268BE797}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{5608E828-DD54-4E2A-B73C-FC22268BE797}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
|
||||
{5608E828-DD54-4E2A-B73C-FC22268BE797}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
|
||||
{5608E828-DD54-4E2A-B73C-FC22268BE797}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{5608E828-DD54-4E2A-B73C-FC22268BE797}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{5608E828-DD54-4E2A-B73C-FC22268BE797}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{5608E828-DD54-4E2A-B73C-FC22268BE797}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{5608E828-DD54-4E2A-B73C-FC22268BE797}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{5608E828-DD54-4E2A-B73C-FC22268BE797}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{5608E828-DD54-4E2A-B73C-FC22268BE797}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
|
||||
{5608E828-DD54-4E2A-B73C-FC22268BE797}.Release|Mixed Platforms.Build.0 = Release|Any CPU
|
||||
{5608E828-DD54-4E2A-B73C-FC22268BE797}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{5608E828-DD54-4E2A-B73C-FC22268BE797}.Release|x64.Build.0 = Release|Any CPU
|
||||
{5608E828-DD54-4E2A-B73C-FC22268BE797}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{5608E828-DD54-4E2A-B73C-FC22268BE797}.Release|x86.Build.0 = Release|Any CPU
|
||||
{D5905D78-A32E-44B8-8F21-EDAEDC95D9B8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{D5905D78-A32E-44B8-8F21-EDAEDC95D9B8}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{D5905D78-A32E-44B8-8F21-EDAEDC95D9B8}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
|
||||
{D5905D78-A32E-44B8-8F21-EDAEDC95D9B8}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
|
||||
{D5905D78-A32E-44B8-8F21-EDAEDC95D9B8}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{D5905D78-A32E-44B8-8F21-EDAEDC95D9B8}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{D5905D78-A32E-44B8-8F21-EDAEDC95D9B8}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{D5905D78-A32E-44B8-8F21-EDAEDC95D9B8}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{D5905D78-A32E-44B8-8F21-EDAEDC95D9B8}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{D5905D78-A32E-44B8-8F21-EDAEDC95D9B8}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{D5905D78-A32E-44B8-8F21-EDAEDC95D9B8}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
|
||||
{D5905D78-A32E-44B8-8F21-EDAEDC95D9B8}.Release|Mixed Platforms.Build.0 = Release|Any CPU
|
||||
{D5905D78-A32E-44B8-8F21-EDAEDC95D9B8}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{D5905D78-A32E-44B8-8F21-EDAEDC95D9B8}.Release|x64.Build.0 = Release|Any CPU
|
||||
{D5905D78-A32E-44B8-8F21-EDAEDC95D9B8}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{D5905D78-A32E-44B8-8F21-EDAEDC95D9B8}.Release|x86.Build.0 = Release|Any CPU
|
||||
{FADA11FC-DC06-4832-A569-7B2374A6CD42}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{FADA11FC-DC06-4832-A569-7B2374A6CD42}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{FADA11FC-DC06-4832-A569-7B2374A6CD42}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
|
||||
{FADA11FC-DC06-4832-A569-7B2374A6CD42}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
|
||||
{FADA11FC-DC06-4832-A569-7B2374A6CD42}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{FADA11FC-DC06-4832-A569-7B2374A6CD42}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{FADA11FC-DC06-4832-A569-7B2374A6CD42}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{FADA11FC-DC06-4832-A569-7B2374A6CD42}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{FADA11FC-DC06-4832-A569-7B2374A6CD42}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{FADA11FC-DC06-4832-A569-7B2374A6CD42}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{FADA11FC-DC06-4832-A569-7B2374A6CD42}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
|
||||
{FADA11FC-DC06-4832-A569-7B2374A6CD42}.Release|Mixed Platforms.Build.0 = Release|Any CPU
|
||||
{FADA11FC-DC06-4832-A569-7B2374A6CD42}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{FADA11FC-DC06-4832-A569-7B2374A6CD42}.Release|x64.Build.0 = Release|Any CPU
|
||||
{FADA11FC-DC06-4832-A569-7B2374A6CD42}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{FADA11FC-DC06-4832-A569-7B2374A6CD42}.Release|x86.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(NestedProjects) = preSolution
|
||||
{1729302E-A58E-4652-B639-5B6B68DA2748} = {0F647068-6602-4E24-B1DC-8ED91481A50A}
|
||||
{2CF3927B-19E4-4866-9BAA-2C131580E7C3} = {52D59F18-62D2-4D17-8CF2-BE192445AF8E}
|
||||
{65161409-C4C4-4D63-A73B-231FCFF4D503} = {52D59F18-62D2-4D17-8CF2-BE192445AF8E}
|
||||
{E1BFA023-CFFD-49CE-8466-1C28DD2EC1F6} = {58D94A0E-C2B7-43A7-8826-99ECBB1E0A50}
|
||||
{37236EA3-915D-46D5-997C-DF513C500E4B} = {52D59F18-62D2-4D17-8CF2-BE192445AF8E}
|
||||
{EA7EB28F-53B8-4009-9C6B-74DB090CA8DD} = {52D59F18-62D2-4D17-8CF2-BE192445AF8E}
|
||||
{4490894C-3572-4E63-86F1-EE5105CE8A06} = {0F647068-6602-4E24-B1DC-8ED91481A50A}
|
||||
{6A74C6EA-B241-4D6B-BCE4-BF89EC1D2475} = {0F647068-6602-4E24-B1DC-8ED91481A50A}
|
||||
{5608E828-DD54-4E2A-B73C-FC22268BE797} = {0F647068-6602-4E24-B1DC-8ED91481A50A}
|
||||
{D5905D78-A32E-44B8-8F21-EDAEDC95D9B8} = {0F647068-6602-4E24-B1DC-8ED91481A50A}
|
||||
{FADA11FC-DC06-4832-A569-7B2374A6CD42} = {0F647068-6602-4E24-B1DC-8ED91481A50A}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
<Project>
|
||||
<ItemGroup>
|
||||
<ExcludeSolutions Include="$(RepositoryRoot)IdentityCore.sln" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
|
@ -27,7 +27,7 @@ namespace Microsoft.AspNetCore.Identity.EntityFrameworkCore
|
|||
/// Base class for the Entity Framework database context used for identity.
|
||||
/// </summary>
|
||||
/// <typeparam name="TUser">The type of the user objects.</typeparam>
|
||||
public class IdentityDbContext<TUser> : IdentityDbContext<TUser, IdentityRole, string> where TUser : IdentityUser
|
||||
public class IdentityDbContext<TUser> : IdentityDbContext<TUser, string> where TUser : IdentityUser
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of <see cref="IdentityDbContext"/>.
|
||||
|
|
@ -41,6 +41,27 @@ namespace Microsoft.AspNetCore.Identity.EntityFrameworkCore
|
|||
protected IdentityDbContext() { }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Base class for the Entity Framework database context used for identity.
|
||||
/// </summary>
|
||||
/// <typeparam name="TUser">The type of user objects.</typeparam>
|
||||
/// <typeparam name="TKey">The type of the primary key for users and roles.</typeparam>
|
||||
public class IdentityDbContext<TUser, TKey> : IdentityDbContext<TUser, TKey, IdentityUserClaim<TKey>, IdentityUserLogin<TKey>, IdentityUserToken<TKey>>
|
||||
where TUser : IdentityUser<TKey>
|
||||
where TKey : IEquatable<TKey>
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the db context.
|
||||
/// </summary>
|
||||
/// <param name="options">The options to be used by a <see cref="DbContext"/>.</param>
|
||||
public IdentityDbContext(DbContextOptions options) : base(options) { }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the class.
|
||||
/// </summary>
|
||||
protected IdentityDbContext() { }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Base class for the Entity Framework database context used for identity.
|
||||
/// </summary>
|
||||
|
|
@ -68,21 +89,15 @@ namespace Microsoft.AspNetCore.Identity.EntityFrameworkCore
|
|||
/// Base class for the Entity Framework database context used for identity.
|
||||
/// </summary>
|
||||
/// <typeparam name="TUser">The type of user objects.</typeparam>
|
||||
/// <typeparam name="TRole">The type of role objects.</typeparam>
|
||||
/// <typeparam name="TKey">The type of the primary key for users and roles.</typeparam>
|
||||
/// <typeparam name="TUserClaim">The type of the user claim object.</typeparam>
|
||||
/// <typeparam name="TUserRole">The type of the user role object.</typeparam>
|
||||
/// <typeparam name="TUserLogin">The type of the user login object.</typeparam>
|
||||
/// <typeparam name="TRoleClaim">The type of the role claim object.</typeparam>
|
||||
/// <typeparam name="TUserToken">The type of the user token object.</typeparam>
|
||||
public abstract class IdentityDbContext<TUser, TRole, TKey, TUserClaim, TUserRole, TUserLogin, TRoleClaim, TUserToken> : DbContext
|
||||
where TUser : IdentityUser<TKey, TUserClaim, TUserRole, TUserLogin, TUserToken>
|
||||
where TRole : IdentityRole<TKey, TUserRole, TRoleClaim>
|
||||
public abstract class IdentityDbContext<TUser, TKey, TUserClaim, TUserLogin, TUserToken> : DbContext
|
||||
where TUser : IdentityUser<TKey>
|
||||
where TKey : IEquatable<TKey>
|
||||
where TUserClaim : IdentityUserClaim<TKey>
|
||||
where TUserRole : IdentityUserRole<TKey>
|
||||
where TUserLogin : IdentityUserLogin<TKey>
|
||||
where TRoleClaim : IdentityRoleClaim<TKey>
|
||||
where TUserToken : IdentityUserToken<TKey>
|
||||
{
|
||||
/// <summary>
|
||||
|
|
@ -111,26 +126,11 @@ namespace Microsoft.AspNetCore.Identity.EntityFrameworkCore
|
|||
/// </summary>
|
||||
public DbSet<TUserLogin> UserLogins { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the <see cref="DbSet{TEntity}"/> of User roles.
|
||||
/// </summary>
|
||||
public DbSet<TUserRole> UserRoles { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the <see cref="DbSet{TEntity}"/> of User tokens.
|
||||
/// </summary>
|
||||
public DbSet<TUserToken> UserTokens { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the <see cref="DbSet{TEntity}"/> of roles.
|
||||
/// </summary>
|
||||
public DbSet<TRole> Roles { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the <see cref="DbSet{TEntity}"/> of role claims.
|
||||
/// </summary>
|
||||
public DbSet<TRoleClaim> RoleClaims { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Configures the schema needed for the identity framework.
|
||||
/// </summary>
|
||||
|
|
@ -155,10 +155,90 @@ namespace Microsoft.AspNetCore.Identity.EntityFrameworkCore
|
|||
// Replace with b.HasMany<IdentityUserClaim>().
|
||||
b.HasMany<TUserClaim>().WithOne().HasForeignKey(uc => uc.UserId).IsRequired();
|
||||
b.HasMany<TUserLogin>().WithOne().HasForeignKey(ul => ul.UserId).IsRequired();
|
||||
b.HasMany<TUserRole>().WithOne().HasForeignKey(ur => ur.UserId).IsRequired();
|
||||
b.HasMany<TUserToken>().WithOne().HasForeignKey(ut => ut.UserId).IsRequired();
|
||||
});
|
||||
|
||||
builder.Entity<TUserClaim>(b =>
|
||||
{
|
||||
b.HasKey(uc => uc.Id);
|
||||
b.ToTable("AspNetUserClaims");
|
||||
});
|
||||
|
||||
builder.Entity<TUserLogin>(b =>
|
||||
{
|
||||
b.HasKey(l => new { l.LoginProvider, l.ProviderKey });
|
||||
b.ToTable("AspNetUserLogins");
|
||||
});
|
||||
|
||||
builder.Entity<TUserToken>(b =>
|
||||
{
|
||||
b.HasKey(l => new { l.UserId, l.LoginProvider, l.Name });
|
||||
b.ToTable("AspNetUserTokens");
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Base class for the Entity Framework database context used for identity.
|
||||
/// </summary>
|
||||
/// <typeparam name="TUser">The type of user objects.</typeparam>
|
||||
/// <typeparam name="TRole">The type of role objects.</typeparam>
|
||||
/// <typeparam name="TKey">The type of the primary key for users and roles.</typeparam>
|
||||
/// <typeparam name="TUserClaim">The type of the user claim object.</typeparam>
|
||||
/// <typeparam name="TUserRole">The type of the user role object.</typeparam>
|
||||
/// <typeparam name="TUserLogin">The type of the user login object.</typeparam>
|
||||
/// <typeparam name="TRoleClaim">The type of the role claim object.</typeparam>
|
||||
/// <typeparam name="TUserToken">The type of the user token object.</typeparam>
|
||||
public abstract class IdentityDbContext<TUser, TRole, TKey, TUserClaim, TUserRole, TUserLogin, TRoleClaim, TUserToken> : IdentityDbContext<TUser, TKey, TUserClaim, TUserLogin, TUserToken>
|
||||
where TUser : IdentityUser<TKey>
|
||||
where TRole : IdentityRole<TKey>
|
||||
where TKey : IEquatable<TKey>
|
||||
where TUserClaim : IdentityUserClaim<TKey>
|
||||
where TUserRole : IdentityUserRole<TKey>
|
||||
where TUserLogin : IdentityUserLogin<TKey>
|
||||
where TRoleClaim : IdentityRoleClaim<TKey>
|
||||
where TUserToken : IdentityUserToken<TKey>
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the class.
|
||||
/// </summary>
|
||||
/// <param name="options">The options to be used by a <see cref="DbContext"/>.</param>
|
||||
public IdentityDbContext(DbContextOptions options) : base(options) { }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the class.
|
||||
/// </summary>
|
||||
protected IdentityDbContext() { }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the <see cref="DbSet{TEntity}"/> of User roles.
|
||||
/// </summary>
|
||||
public DbSet<TUserRole> UserRoles { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the <see cref="DbSet{TEntity}"/> of roles.
|
||||
/// </summary>
|
||||
public DbSet<TRole> Roles { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the <see cref="DbSet{TEntity}"/> of role claims.
|
||||
/// </summary>
|
||||
public DbSet<TRoleClaim> RoleClaims { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Configures the schema needed for the identity framework.
|
||||
/// </summary>
|
||||
/// <param name="builder">
|
||||
/// The builder being used to construct the model for this context.
|
||||
/// </param>
|
||||
protected override void OnModelCreating(ModelBuilder builder)
|
||||
{
|
||||
base.OnModelCreating(builder);
|
||||
builder.Entity<TUser>(b =>
|
||||
{
|
||||
b.HasMany<TUserRole>().WithOne().HasForeignKey(ur => ur.UserId).IsRequired();
|
||||
});
|
||||
|
||||
builder.Entity<TRole>(b =>
|
||||
{
|
||||
b.HasKey(r => r.Id);
|
||||
|
|
@ -173,35 +253,17 @@ namespace Microsoft.AspNetCore.Identity.EntityFrameworkCore
|
|||
b.HasMany<TRoleClaim>().WithOne().HasForeignKey(rc => rc.RoleId).IsRequired();
|
||||
});
|
||||
|
||||
builder.Entity<TUserClaim>(b =>
|
||||
{
|
||||
b.HasKey(uc => uc.Id);
|
||||
b.ToTable("AspNetUserClaims");
|
||||
});
|
||||
|
||||
builder.Entity<TRoleClaim>(b =>
|
||||
builder.Entity<TRoleClaim>(b =>
|
||||
{
|
||||
b.HasKey(rc => rc.Id);
|
||||
b.ToTable("AspNetRoleClaims");
|
||||
});
|
||||
|
||||
builder.Entity<TUserRole>(b =>
|
||||
builder.Entity<TUserRole>(b =>
|
||||
{
|
||||
b.HasKey(r => new { r.UserId, r.RoleId });
|
||||
b.ToTable("AspNetUserRoles");
|
||||
});
|
||||
|
||||
builder.Entity<TUserLogin>(b =>
|
||||
{
|
||||
b.HasKey(l => new { l.LoginProvider, l.ProviderKey });
|
||||
b.ToTable("AspNetUserLogins");
|
||||
});
|
||||
|
||||
builder.Entity<TUserToken>(b =>
|
||||
{
|
||||
b.HasKey(l => new { l.UserId, l.LoginProvider, l.Name });
|
||||
b.ToTable("AspNetUserTokens");
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -30,32 +30,68 @@ namespace Microsoft.Extensions.DependencyInjection
|
|||
|
||||
private static void AddStores(IServiceCollection services, Type userType, Type roleType, Type contextType)
|
||||
{
|
||||
var identityUserType = FindGenericBaseType(userType, typeof(IdentityUser<,,,,>));
|
||||
var identityUserType = FindGenericBaseType(userType, typeof(IdentityUser<>));
|
||||
if (identityUserType == null)
|
||||
{
|
||||
throw new InvalidOperationException(Resources.NotIdentityUser);
|
||||
}
|
||||
var identityRoleType = FindGenericBaseType(roleType, typeof(IdentityRole<,,>));
|
||||
if (identityRoleType == null)
|
||||
|
||||
var keyType = identityUserType.GenericTypeArguments[0];
|
||||
|
||||
if (roleType != null)
|
||||
{
|
||||
throw new InvalidOperationException(Resources.NotIdentityRole);
|
||||
var identityRoleType = FindGenericBaseType(roleType, typeof(IdentityRole<>));
|
||||
if (identityRoleType == null)
|
||||
{
|
||||
throw new InvalidOperationException(Resources.NotIdentityRole);
|
||||
}
|
||||
|
||||
Type userStoreType = null;
|
||||
Type roleStoreType = null;
|
||||
var identityContext = FindGenericBaseType(contextType, typeof(IdentityDbContext<,,,,,,,>));
|
||||
if (identityContext == null)
|
||||
{
|
||||
// If its a custom DbContext, we can only add the default POCOs
|
||||
userStoreType = typeof(UserStore<,,,>).MakeGenericType(userType, roleType, contextType, keyType);
|
||||
roleStoreType = typeof(RoleStore<,,>).MakeGenericType(roleType, contextType, keyType);
|
||||
}
|
||||
else
|
||||
{
|
||||
userStoreType = typeof(UserStore<,,,,,,,,>).MakeGenericType(userType, roleType, contextType,
|
||||
identityContext.GenericTypeArguments[2],
|
||||
identityContext.GenericTypeArguments[3],
|
||||
identityContext.GenericTypeArguments[4],
|
||||
identityContext.GenericTypeArguments[5],
|
||||
identityContext.GenericTypeArguments[7],
|
||||
identityContext.GenericTypeArguments[6]);
|
||||
roleStoreType = typeof(RoleStore<,,,,>).MakeGenericType(roleType, contextType,
|
||||
identityContext.GenericTypeArguments[2],
|
||||
identityContext.GenericTypeArguments[4],
|
||||
identityContext.GenericTypeArguments[6]);
|
||||
}
|
||||
services.TryAddScoped(typeof(IUserStore<>).MakeGenericType(userType), userStoreType);
|
||||
services.TryAddScoped(typeof(IRoleStore<>).MakeGenericType(roleType), roleStoreType);
|
||||
}
|
||||
else
|
||||
{ // No Roles
|
||||
Type userStoreType = null;
|
||||
var identityContext = FindGenericBaseType(contextType, typeof(IdentityDbContext<,,,,>));
|
||||
if (identityContext == null)
|
||||
{
|
||||
// If its a custom DbContext, we can only add the default POCOs
|
||||
userStoreType = typeof(UserStore<,,,>).MakeGenericType(userType, roleType, contextType, keyType);
|
||||
}
|
||||
else
|
||||
{
|
||||
userStoreType = typeof(UserOnlyStore<,,,,,>).MakeGenericType(userType, roleType, contextType,
|
||||
identityContext.GenericTypeArguments[1],
|
||||
identityContext.GenericTypeArguments[2],
|
||||
identityContext.GenericTypeArguments[3],
|
||||
identityContext.GenericTypeArguments[4]);
|
||||
}
|
||||
services.TryAddScoped(typeof(IUserStore<>).MakeGenericType(userType), userStoreType);
|
||||
}
|
||||
|
||||
services.TryAddScoped(
|
||||
typeof(IUserStore<>).MakeGenericType(userType),
|
||||
typeof(UserStore<,,,,,,,,>).MakeGenericType(userType, roleType, contextType,
|
||||
identityUserType.GenericTypeArguments[0],
|
||||
identityUserType.GenericTypeArguments[1],
|
||||
identityUserType.GenericTypeArguments[2],
|
||||
identityUserType.GenericTypeArguments[3],
|
||||
identityUserType.GenericTypeArguments[4],
|
||||
identityRoleType.GenericTypeArguments[2]));
|
||||
services.TryAddScoped(
|
||||
typeof(IRoleStore<>).MakeGenericType(roleType),
|
||||
typeof(RoleStore<,,,,>).MakeGenericType(roleType, contextType,
|
||||
identityRoleType.GenericTypeArguments[0],
|
||||
identityRoleType.GenericTypeArguments[1],
|
||||
identityRoleType.GenericTypeArguments[2]));
|
||||
}
|
||||
|
||||
private static TypeInfo FindGenericBaseType(Type currentType, Type genericBaseType)
|
||||
|
|
|
|||
|
|
@ -15,64 +15,56 @@ namespace Microsoft.AspNetCore.Identity.EntityFrameworkCore
|
|||
/// </summary>
|
||||
internal static string NotIdentityRole
|
||||
{
|
||||
get { return GetString("NotIdentityRole"); }
|
||||
get => GetString("NotIdentityRole");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// AddEntityFrameworkStores can only be called with a role that derives from IdentityRole<TKey, TUserRole, TRoleClaim>.
|
||||
/// </summary>
|
||||
internal static string FormatNotIdentityRole()
|
||||
{
|
||||
return GetString("NotIdentityRole");
|
||||
}
|
||||
=> GetString("NotIdentityRole");
|
||||
|
||||
/// <summary>
|
||||
/// AddEntityFrameworkStores can only be called with a user that derives from IdentityUser<TKey, TUserClaim, TUserRole, TUserLogin, TUserToken>.
|
||||
/// </summary>
|
||||
internal static string NotIdentityUser
|
||||
{
|
||||
get { return GetString("NotIdentityUser"); }
|
||||
get => GetString("NotIdentityUser");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// AddEntityFrameworkStores can only be called with a user that derives from IdentityUser<TKey, TUserClaim, TUserRole, TUserLogin, TUserToken>.
|
||||
/// </summary>
|
||||
internal static string FormatNotIdentityUser()
|
||||
{
|
||||
return GetString("NotIdentityUser");
|
||||
}
|
||||
=> GetString("NotIdentityUser");
|
||||
|
||||
/// <summary>
|
||||
/// Role {0} does not exist.
|
||||
/// </summary>
|
||||
internal static string RoleNotFound
|
||||
{
|
||||
get { return GetString("RoleNotFound"); }
|
||||
get => GetString("RoleNotFound");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Role {0} does not exist.
|
||||
/// </summary>
|
||||
internal static string FormatRoleNotFound(object p0)
|
||||
{
|
||||
return string.Format(CultureInfo.CurrentCulture, GetString("RoleNotFound"), p0);
|
||||
}
|
||||
=> string.Format(CultureInfo.CurrentCulture, GetString("RoleNotFound"), p0);
|
||||
|
||||
/// <summary>
|
||||
/// Value cannot be null or empty.
|
||||
/// </summary>
|
||||
internal static string ValueCannotBeNullOrEmpty
|
||||
{
|
||||
get { return GetString("ValueCannotBeNullOrEmpty"); }
|
||||
get => GetString("ValueCannotBeNullOrEmpty");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Value cannot be null or empty.
|
||||
/// </summary>
|
||||
internal static string FormatValueCannotBeNullOrEmpty()
|
||||
{
|
||||
return GetString("ValueCannotBeNullOrEmpty");
|
||||
}
|
||||
=> GetString("ValueCannotBeNullOrEmpty");
|
||||
|
||||
private static string GetString(string name, params string[] formatterNames)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -9,7 +9,6 @@ using System.Security.Claims;
|
|||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.Internal;
|
||||
|
||||
namespace Microsoft.AspNetCore.Identity.EntityFrameworkCore
|
||||
{
|
||||
|
|
@ -77,7 +76,7 @@ namespace Microsoft.AspNetCore.Identity.EntityFrameworkCore
|
|||
public class RoleStore<TRole, TContext, TKey, TUserRole, TRoleClaim> :
|
||||
IQueryableRoleStore<TRole>,
|
||||
IRoleClaimStore<TRole>
|
||||
where TRole : IdentityRole<TKey, TUserRole, TRoleClaim>
|
||||
where TRole : IdentityRole<TKey>
|
||||
where TKey : IEquatable<TKey>
|
||||
where TContext : DbContext
|
||||
where TUserRole : IdentityUserRole<TKey>, new()
|
||||
|
|
@ -361,10 +360,7 @@ namespace Microsoft.AspNetCore.Identity.EntityFrameworkCore
|
|||
/// <summary>
|
||||
/// Dispose the stores
|
||||
/// </summary>
|
||||
public void Dispose()
|
||||
{
|
||||
_disposed = true;
|
||||
}
|
||||
public void Dispose() => _disposed = true;
|
||||
|
||||
/// <summary>
|
||||
/// Get the claims associated with the specified <paramref name="role"/> as an asynchronous operation.
|
||||
|
|
@ -434,10 +430,7 @@ namespace Microsoft.AspNetCore.Identity.EntityFrameworkCore
|
|||
/// <summary>
|
||||
/// A navigation property for the roles the store contains.
|
||||
/// </summary>
|
||||
public virtual IQueryable<TRole> Roles
|
||||
{
|
||||
get { return Context.Set<TRole>(); }
|
||||
}
|
||||
public virtual IQueryable<TRole> Roles => Context.Set<TRole>();
|
||||
|
||||
private DbSet<TRoleClaim> RoleClaims { get { return Context.Set<TRoleClaim>(); } }
|
||||
|
||||
|
|
@ -448,8 +441,6 @@ namespace Microsoft.AspNetCore.Identity.EntityFrameworkCore
|
|||
/// <param name="claim">The associated claim.</param>
|
||||
/// <returns>The role claim entity.</returns>
|
||||
protected virtual TRoleClaim CreateRoleClaim(TRole role, Claim claim)
|
||||
{
|
||||
return new TRoleClaim { RoleId = role.Id, ClaimType = claim.Type, ClaimValue = claim.Value };
|
||||
}
|
||||
=> new TRoleClaim { RoleId = role.Id, ClaimType = claim.Type, ClaimValue = claim.Value };
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,567 @@
|
|||
// 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 System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Security.Claims;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace Microsoft.AspNetCore.Identity.EntityFrameworkCore
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates a new instance of a persistence store for the specified user type.
|
||||
/// </summary>
|
||||
/// <typeparam name="TUser">The type representing a user.</typeparam>
|
||||
public class UserOnlyStore<TUser> : UserOnlyStore<TUser, DbContext, string> where TUser : IdentityUser<string>, new()
|
||||
{
|
||||
/// <summary>
|
||||
/// Constructs a new instance of <see cref="UserOnlyStore{TUser}"/>.
|
||||
/// </summary>
|
||||
/// <param name="context">The <see cref="DbContext"/>.</param>
|
||||
/// <param name="describer">The <see cref="IdentityErrorDescriber"/>.</param>
|
||||
public UserOnlyStore(DbContext context, IdentityErrorDescriber describer = null) : base(context, describer) { }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents a new instance of a persistence store for the specified user and role types.
|
||||
/// </summary>
|
||||
/// <typeparam name="TUser">The type representing a user.</typeparam>
|
||||
/// <typeparam name="TContext">The type of the data context class used to access the store.</typeparam>
|
||||
public class UserOnlyStore<TUser, TContext> : UserOnlyStore<TUser, TContext, string>
|
||||
where TUser : IdentityUser<string>
|
||||
where TContext : DbContext
|
||||
{
|
||||
/// <summary>
|
||||
/// Constructs a new instance of <see cref="UserStore{TUser, TRole, TContext}"/>.
|
||||
/// </summary>
|
||||
/// <param name="context">The <see cref="DbContext"/>.</param>
|
||||
/// <param name="describer">The <see cref="IdentityErrorDescriber"/>.</param>
|
||||
public UserOnlyStore(TContext context, IdentityErrorDescriber describer = null) : base(context, describer) { }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents a new instance of a persistence store for the specified user and role types.
|
||||
/// </summary>
|
||||
/// <typeparam name="TUser">The type representing a user.</typeparam>
|
||||
/// <typeparam name="TContext">The type of the data context class used to access the store.</typeparam>
|
||||
/// <typeparam name="TKey">The type of the primary key for a role.</typeparam>
|
||||
public class UserOnlyStore<TUser, TContext, TKey> : UserOnlyStore<TUser, TContext, TKey, IdentityUserClaim<TKey>, IdentityUserLogin<TKey>, IdentityUserToken<TKey>>
|
||||
where TUser : IdentityUser<TKey>
|
||||
where TContext : DbContext
|
||||
where TKey : IEquatable<TKey>
|
||||
{
|
||||
/// <summary>
|
||||
/// Constructs a new instance of <see cref="UserStore{TUser, TRole, TContext, TKey}"/>.
|
||||
/// </summary>
|
||||
/// <param name="context">The <see cref="DbContext"/>.</param>
|
||||
/// <param name="describer">The <see cref="IdentityErrorDescriber"/>.</param>
|
||||
public UserOnlyStore(TContext context, IdentityErrorDescriber describer = null) : base(context, describer) { }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents a new instance of a persistence store for the specified user and role types.
|
||||
/// </summary>
|
||||
/// <typeparam name="TUser">The type representing a user.</typeparam>
|
||||
/// <typeparam name="TContext">The type of the data context class used to access the store.</typeparam>
|
||||
/// <typeparam name="TKey">The type of the primary key for a role.</typeparam>
|
||||
/// <typeparam name="TUserClaim">The type representing a claim.</typeparam>
|
||||
/// <typeparam name="TUserLogin">The type representing a user external login.</typeparam>
|
||||
/// <typeparam name="TUserToken">The type representing a user token.</typeparam>
|
||||
public class UserOnlyStore<TUser, TContext, TKey, TUserClaim, TUserLogin, TUserToken> :
|
||||
UserStoreBase<TUser, TKey, TUserClaim, TUserLogin, TUserToken>,
|
||||
IUserLoginStore<TUser>,
|
||||
IUserClaimStore<TUser>,
|
||||
IUserPasswordStore<TUser>,
|
||||
IUserSecurityStampStore<TUser>,
|
||||
IUserEmailStore<TUser>,
|
||||
IUserLockoutStore<TUser>,
|
||||
IUserPhoneNumberStore<TUser>,
|
||||
IQueryableUserStore<TUser>,
|
||||
IUserTwoFactorStore<TUser>,
|
||||
IUserAuthenticationTokenStore<TUser>,
|
||||
IUserAuthenticatorKeyStore<TUser>,
|
||||
IUserTwoFactorRecoveryCodeStore<TUser>
|
||||
where TUser : IdentityUser<TKey>
|
||||
where TContext : DbContext
|
||||
where TKey : IEquatable<TKey>
|
||||
where TUserClaim : IdentityUserClaim<TKey>, new()
|
||||
where TUserLogin : IdentityUserLogin<TKey>, new()
|
||||
where TUserToken : IdentityUserToken<TKey>, new()
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates a new instance of the store.
|
||||
/// </summary>
|
||||
/// <param name="context">The context used to access the store.</param>
|
||||
/// <param name="describer">The <see cref="IdentityErrorDescriber"/> used to describe store errors.</param>
|
||||
public UserOnlyStore(TContext context, IdentityErrorDescriber describer = null) : base(describer ?? new IdentityErrorDescriber())
|
||||
{
|
||||
if (context == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(context));
|
||||
}
|
||||
Context = context;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the database context for this store.
|
||||
/// </summary>
|
||||
public TContext Context { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// DbSet of users.
|
||||
/// </summary>
|
||||
protected DbSet<TUser> UsersSet { get { return Context.Set<TUser>(); } }
|
||||
|
||||
/// <summary>
|
||||
/// DbSet of user claims.
|
||||
/// </summary>
|
||||
protected DbSet<TUserClaim> UserClaims { get { return Context.Set<TUserClaim>(); } }
|
||||
|
||||
/// <summary>
|
||||
/// DbSet of user logins.
|
||||
/// </summary>
|
||||
protected DbSet<TUserLogin> UserLogins { get { return Context.Set<TUserLogin>(); } }
|
||||
|
||||
/// <summary>
|
||||
/// DbSet of user tokens.
|
||||
/// </summary>
|
||||
protected DbSet<TUserToken> UserTokens { get { return Context.Set<TUserToken>(); } }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a flag indicating if changes should be persisted after CreateAsync, UpdateAsync and DeleteAsync are called.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// True if changes should be automatically persisted, otherwise false.
|
||||
/// </value>
|
||||
public bool AutoSaveChanges { get; set; } = true;
|
||||
|
||||
/// <summary>Saves the current store.</summary>
|
||||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> used to propagate notifications that the operation should be canceled.</param>
|
||||
/// <returns>The <see cref="Task"/> that represents the asynchronous operation.</returns>
|
||||
protected Task SaveChanges(CancellationToken cancellationToken)
|
||||
{
|
||||
return AutoSaveChanges ? Context.SaveChangesAsync(cancellationToken) : Task.CompletedTask;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates the specified <paramref name="user"/> in the user store.
|
||||
/// </summary>
|
||||
/// <param name="user">The user to create.</param>
|
||||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> used to propagate notifications that the operation should be canceled.</param>
|
||||
/// <returns>The <see cref="Task"/> that represents the asynchronous operation, containing the <see cref="IdentityResult"/> of the creation operation.</returns>
|
||||
public async override Task<IdentityResult> CreateAsync(TUser user, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
ThrowIfDisposed();
|
||||
if (user == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(user));
|
||||
}
|
||||
Context.Add(user);
|
||||
await SaveChanges(cancellationToken);
|
||||
return IdentityResult.Success;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates the specified <paramref name="user"/> in the user store.
|
||||
/// </summary>
|
||||
/// <param name="user">The user to update.</param>
|
||||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> used to propagate notifications that the operation should be canceled.</param>
|
||||
/// <returns>The <see cref="Task"/> that represents the asynchronous operation, containing the <see cref="IdentityResult"/> of the update operation.</returns>
|
||||
public async override Task<IdentityResult> UpdateAsync(TUser user, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
ThrowIfDisposed();
|
||||
if (user == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(user));
|
||||
}
|
||||
|
||||
Context.Attach(user);
|
||||
user.ConcurrencyStamp = Guid.NewGuid().ToString();
|
||||
Context.Update(user);
|
||||
try
|
||||
{
|
||||
await SaveChanges(cancellationToken);
|
||||
}
|
||||
catch (DbUpdateConcurrencyException)
|
||||
{
|
||||
return IdentityResult.Failed(ErrorDescriber.ConcurrencyFailure());
|
||||
}
|
||||
return IdentityResult.Success;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Deletes the specified <paramref name="user"/> from the user store.
|
||||
/// </summary>
|
||||
/// <param name="user">The user to delete.</param>
|
||||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> used to propagate notifications that the operation should be canceled.</param>
|
||||
/// <returns>The <see cref="Task"/> that represents the asynchronous operation, containing the <see cref="IdentityResult"/> of the update operation.</returns>
|
||||
public async override Task<IdentityResult> DeleteAsync(TUser user, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
ThrowIfDisposed();
|
||||
if (user == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(user));
|
||||
}
|
||||
|
||||
Context.Remove(user);
|
||||
try
|
||||
{
|
||||
await SaveChanges(cancellationToken);
|
||||
}
|
||||
catch (DbUpdateConcurrencyException)
|
||||
{
|
||||
return IdentityResult.Failed(ErrorDescriber.ConcurrencyFailure());
|
||||
}
|
||||
return IdentityResult.Success;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Finds and returns a user, if any, who has the specified <paramref name="userId"/>.
|
||||
/// </summary>
|
||||
/// <param name="userId">The user ID to search for.</param>
|
||||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> used to propagate notifications that the operation should be canceled.</param>
|
||||
/// <returns>
|
||||
/// The <see cref="Task"/> that represents the asynchronous operation, containing the user matching the specified <paramref name="userId"/> if it exists.
|
||||
/// </returns>
|
||||
public override Task<TUser> FindByIdAsync(string userId, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
ThrowIfDisposed();
|
||||
var id = ConvertIdFromString(userId);
|
||||
return UsersSet.FindAsync(new object[] { id }, cancellationToken);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Finds and returns a user, if any, who has the specified normalized user name.
|
||||
/// </summary>
|
||||
/// <param name="normalizedUserName">The normalized user name to search for.</param>
|
||||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> used to propagate notifications that the operation should be canceled.</param>
|
||||
/// <returns>
|
||||
/// The <see cref="Task"/> that represents the asynchronous operation, containing the user matching the specified <paramref name="normalizedUserName"/> if it exists.
|
||||
/// </returns>
|
||||
public override Task<TUser> FindByNameAsync(string normalizedUserName, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
ThrowIfDisposed();
|
||||
return Users.FirstOrDefaultAsync(u => u.NormalizedUserName == normalizedUserName, cancellationToken);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A navigation property for the users the store contains.
|
||||
/// </summary>
|
||||
public override IQueryable<TUser> Users
|
||||
{
|
||||
get { return UsersSet; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return a user with the matching userId if it exists.
|
||||
/// </summary>
|
||||
/// <param name="userId">The user's id.</param>
|
||||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> used to propagate notifications that the operation should be canceled.</param>
|
||||
/// <returns>The user if it exists.</returns>
|
||||
protected override Task<TUser> FindUserAsync(TKey userId, CancellationToken cancellationToken)
|
||||
{
|
||||
return Users.SingleOrDefaultAsync(u => u.Id.Equals(userId), cancellationToken);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return a user login with the matching userId, provider, providerKey if it exists.
|
||||
/// </summary>
|
||||
/// <param name="userId">The user's id.</param>
|
||||
/// <param name="loginProvider">The login provider name.</param>
|
||||
/// <param name="providerKey">The key provided by the <paramref name="loginProvider"/> to identify a user.</param>
|
||||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> used to propagate notifications that the operation should be canceled.</param>
|
||||
/// <returns>The user login if it exists.</returns>
|
||||
protected override Task<TUserLogin> FindUserLoginAsync(TKey userId, string loginProvider, string providerKey, CancellationToken cancellationToken)
|
||||
{
|
||||
return UserLogins.SingleOrDefaultAsync(userLogin => userLogin.UserId.Equals(userId) && userLogin.LoginProvider == loginProvider && userLogin.ProviderKey == providerKey, cancellationToken);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return a user login with provider, providerKey if it exists.
|
||||
/// </summary>
|
||||
/// <param name="loginProvider">The login provider name.</param>
|
||||
/// <param name="providerKey">The key provided by the <paramref name="loginProvider"/> to identify a user.</param>
|
||||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> used to propagate notifications that the operation should be canceled.</param>
|
||||
/// <returns>The user login if it exists.</returns>
|
||||
protected override Task<TUserLogin> FindUserLoginAsync(string loginProvider, string providerKey, CancellationToken cancellationToken)
|
||||
{
|
||||
return UserLogins.SingleOrDefaultAsync(userLogin => userLogin.LoginProvider == loginProvider && userLogin.ProviderKey == providerKey, cancellationToken);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the claims associated with the specified <paramref name="user"/> as an asynchronous operation.
|
||||
/// </summary>
|
||||
/// <param name="user">The user whose claims should be retrieved.</param>
|
||||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> used to propagate notifications that the operation should be canceled.</param>
|
||||
/// <returns>A <see cref="Task{TResult}"/> that contains the claims granted to a user.</returns>
|
||||
public async override Task<IList<Claim>> GetClaimsAsync(TUser user, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
ThrowIfDisposed();
|
||||
if (user == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(user));
|
||||
}
|
||||
|
||||
return await UserClaims.Where(uc => uc.UserId.Equals(user.Id)).Select(c => c.ToClaim()).ToListAsync(cancellationToken);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds the <paramref name="claims"/> given to the specified <paramref name="user"/>.
|
||||
/// </summary>
|
||||
/// <param name="user">The user to add the claim to.</param>
|
||||
/// <param name="claims">The claim to add to the user.</param>
|
||||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> used to propagate notifications that the operation should be canceled.</param>
|
||||
/// <returns>The <see cref="Task"/> that represents the asynchronous operation.</returns>
|
||||
public override Task AddClaimsAsync(TUser user, IEnumerable<Claim> claims, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
ThrowIfDisposed();
|
||||
if (user == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(user));
|
||||
}
|
||||
if (claims == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(claims));
|
||||
}
|
||||
foreach (var claim in claims)
|
||||
{
|
||||
UserClaims.Add(CreateUserClaim(user, claim));
|
||||
}
|
||||
return Task.FromResult(false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Replaces the <paramref name="claim"/> on the specified <paramref name="user"/>, with the <paramref name="newClaim"/>.
|
||||
/// </summary>
|
||||
/// <param name="user">The user to replace the claim on.</param>
|
||||
/// <param name="claim">The claim replace.</param>
|
||||
/// <param name="newClaim">The new claim replacing the <paramref name="claim"/>.</param>
|
||||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> used to propagate notifications that the operation should be canceled.</param>
|
||||
/// <returns>The <see cref="Task"/> that represents the asynchronous operation.</returns>
|
||||
public async override Task ReplaceClaimAsync(TUser user, Claim claim, Claim newClaim, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
ThrowIfDisposed();
|
||||
if (user == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(user));
|
||||
}
|
||||
if (claim == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(claim));
|
||||
}
|
||||
if (newClaim == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(newClaim));
|
||||
}
|
||||
|
||||
var matchedClaims = await UserClaims.Where(uc => uc.UserId.Equals(user.Id) && uc.ClaimValue == claim.Value && uc.ClaimType == claim.Type).ToListAsync(cancellationToken);
|
||||
foreach (var matchedClaim in matchedClaims)
|
||||
{
|
||||
matchedClaim.ClaimValue = newClaim.Value;
|
||||
matchedClaim.ClaimType = newClaim.Type;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes the <paramref name="claims"/> given from the specified <paramref name="user"/>.
|
||||
/// </summary>
|
||||
/// <param name="user">The user to remove the claims from.</param>
|
||||
/// <param name="claims">The claim to remove.</param>
|
||||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> used to propagate notifications that the operation should be canceled.</param>
|
||||
/// <returns>The <see cref="Task"/> that represents the asynchronous operation.</returns>
|
||||
public async override Task RemoveClaimsAsync(TUser user, IEnumerable<Claim> claims, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
ThrowIfDisposed();
|
||||
if (user == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(user));
|
||||
}
|
||||
if (claims == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(claims));
|
||||
}
|
||||
foreach (var claim in claims)
|
||||
{
|
||||
var matchedClaims = await UserClaims.Where(uc => uc.UserId.Equals(user.Id) && uc.ClaimValue == claim.Value && uc.ClaimType == claim.Type).ToListAsync(cancellationToken);
|
||||
foreach (var c in matchedClaims)
|
||||
{
|
||||
UserClaims.Remove(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds the <paramref name="login"/> given to the specified <paramref name="user"/>.
|
||||
/// </summary>
|
||||
/// <param name="user">The user to add the login to.</param>
|
||||
/// <param name="login">The login to add to the user.</param>
|
||||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> used to propagate notifications that the operation should be canceled.</param>
|
||||
/// <returns>The <see cref="Task"/> that represents the asynchronous operation.</returns>
|
||||
public override Task AddLoginAsync(TUser user, UserLoginInfo login,
|
||||
CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
ThrowIfDisposed();
|
||||
if (user == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(user));
|
||||
}
|
||||
if (login == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(login));
|
||||
}
|
||||
UserLogins.Add(CreateUserLogin(user, login));
|
||||
return Task.FromResult(false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes the <paramref name="loginProvider"/> given from the specified <paramref name="user"/>.
|
||||
/// </summary>
|
||||
/// <param name="user">The user to remove the login from.</param>
|
||||
/// <param name="loginProvider">The login to remove from the user.</param>
|
||||
/// <param name="providerKey">The key provided by the <paramref name="loginProvider"/> to identify a user.</param>
|
||||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> used to propagate notifications that the operation should be canceled.</param>
|
||||
/// <returns>The <see cref="Task"/> that represents the asynchronous operation.</returns>
|
||||
public override async Task RemoveLoginAsync(TUser user, string loginProvider, string providerKey,
|
||||
CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
ThrowIfDisposed();
|
||||
if (user == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(user));
|
||||
}
|
||||
var entry = await FindUserLoginAsync(user.Id, loginProvider, providerKey, cancellationToken);
|
||||
if (entry != null)
|
||||
{
|
||||
UserLogins.Remove(entry);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves the associated logins for the specified <param ref="user"/>.
|
||||
/// </summary>
|
||||
/// <param name="user">The user whose associated logins to retrieve.</param>
|
||||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> used to propagate notifications that the operation should be canceled.</param>
|
||||
/// <returns>
|
||||
/// The <see cref="Task"/> for the asynchronous operation, containing a list of <see cref="UserLoginInfo"/> for the specified <paramref name="user"/>, if any.
|
||||
/// </returns>
|
||||
public async override Task<IList<UserLoginInfo>> GetLoginsAsync(TUser user, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
ThrowIfDisposed();
|
||||
if (user == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(user));
|
||||
}
|
||||
var userId = user.Id;
|
||||
return await UserLogins.Where(l => l.UserId.Equals(userId))
|
||||
.Select(l => new UserLoginInfo(l.LoginProvider, l.ProviderKey, l.ProviderDisplayName)).ToListAsync(cancellationToken);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves the user associated with the specified login provider and login provider key.
|
||||
/// </summary>
|
||||
/// <param name="loginProvider">The login provider who provided the <paramref name="providerKey"/>.</param>
|
||||
/// <param name="providerKey">The key provided by the <paramref name="loginProvider"/> to identify a user.</param>
|
||||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> used to propagate notifications that the operation should be canceled.</param>
|
||||
/// <returns>
|
||||
/// The <see cref="Task"/> for the asynchronous operation, containing the user, if any which matched the specified login provider and key.
|
||||
/// </returns>
|
||||
public async override Task<TUser> FindByLoginAsync(string loginProvider, string providerKey,
|
||||
CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
ThrowIfDisposed();
|
||||
var userLogin = await FindUserLoginAsync(loginProvider, providerKey, cancellationToken);
|
||||
if (userLogin != null)
|
||||
{
|
||||
return await FindUserAsync(userLogin.UserId, cancellationToken);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the user, if any, associated with the specified, normalized email address.
|
||||
/// </summary>
|
||||
/// <param name="normalizedEmail">The normalized email address to return the user for.</param>
|
||||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> used to propagate notifications that the operation should be canceled.</param>
|
||||
/// <returns>
|
||||
/// The task object containing the results of the asynchronous lookup operation, the user if any associated with the specified normalized email address.
|
||||
/// </returns>
|
||||
public override Task<TUser> FindByEmailAsync(string normalizedEmail, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
ThrowIfDisposed();
|
||||
return Users.FirstOrDefaultAsync(u => u.NormalizedEmail == normalizedEmail, cancellationToken);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves all users with the specified claim.
|
||||
/// </summary>
|
||||
/// <param name="claim">The claim whose users should be retrieved.</param>
|
||||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> used to propagate notifications that the operation should be canceled.</param>
|
||||
/// <returns>
|
||||
/// The <see cref="Task"/> contains a list of users, if any, that contain the specified claim.
|
||||
/// </returns>
|
||||
public async override Task<IList<TUser>> GetUsersForClaimAsync(Claim claim, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
ThrowIfDisposed();
|
||||
if (claim == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(claim));
|
||||
}
|
||||
|
||||
var query = from userclaims in UserClaims
|
||||
join user in Users on userclaims.UserId equals user.Id
|
||||
where userclaims.ClaimValue == claim.Value
|
||||
&& userclaims.ClaimType == claim.Type
|
||||
select user;
|
||||
|
||||
return await query.ToListAsync(cancellationToken);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Find a user token if it exists.
|
||||
/// </summary>
|
||||
/// <param name="user">The token owner.</param>
|
||||
/// <param name="loginProvider">The login provider for the token.</param>
|
||||
/// <param name="name">The name of the token.</param>
|
||||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> used to propagate notifications that the operation should be canceled.</param>
|
||||
/// <returns>The user token if it exists.</returns>
|
||||
protected override Task<TUserToken> FindTokenAsync(TUser user, string loginProvider, string name, CancellationToken cancellationToken)
|
||||
=> UserTokens.FindAsync(new object[] { user.Id, loginProvider, name }, cancellationToken);
|
||||
|
||||
/// <summary>
|
||||
/// Add a new user token.
|
||||
/// </summary>
|
||||
/// <param name="token">The token to be added.</param>
|
||||
/// <returns></returns>
|
||||
protected override Task AddUserTokenAsync(TUserToken token)
|
||||
{
|
||||
UserTokens.Add(token);
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Remove a new user token.
|
||||
/// </summary>
|
||||
/// <param name="token">The token to be removed.</param>
|
||||
/// <returns></returns>
|
||||
protected override Task RemoveUserTokenAsync(TUserToken token)
|
||||
{
|
||||
UserTokens.Remove(token);
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -9,7 +9,6 @@ using System.Security.Claims;
|
|||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.Internal;
|
||||
|
||||
namespace Microsoft.AspNetCore.Identity.EntityFrameworkCore
|
||||
{
|
||||
|
|
@ -95,22 +94,9 @@ namespace Microsoft.AspNetCore.Identity.EntityFrameworkCore
|
|||
/// <typeparam name="TUserToken">The type representing a user token.</typeparam>
|
||||
/// <typeparam name="TRoleClaim">The type representing a role claim.</typeparam>
|
||||
public class UserStore<TUser, TRole, TContext, TKey, TUserClaim, TUserRole, TUserLogin, TUserToken, TRoleClaim> :
|
||||
UserStoreBase<TUser, TRole, TKey, TUserClaim, TUserRole, TUserLogin, TUserToken, TRoleClaim>,
|
||||
IUserLoginStore<TUser>,
|
||||
IUserRoleStore<TUser>,
|
||||
IUserClaimStore<TUser>,
|
||||
IUserPasswordStore<TUser>,
|
||||
IUserSecurityStampStore<TUser>,
|
||||
IUserEmailStore<TUser>,
|
||||
IUserLockoutStore<TUser>,
|
||||
IUserPhoneNumberStore<TUser>,
|
||||
IQueryableUserStore<TUser>,
|
||||
IUserTwoFactorStore<TUser>,
|
||||
IUserAuthenticationTokenStore<TUser>,
|
||||
IUserAuthenticatorKeyStore<TUser>,
|
||||
IUserTwoFactorRecoveryCodeStore<TUser>
|
||||
where TUser : IdentityUser<TKey, TUserClaim, TUserRole, TUserLogin, TUserToken>
|
||||
where TRole : IdentityRole<TKey, TUserRole, TRoleClaim>
|
||||
UserStoreBase<TUser, TRole, TKey, TUserClaim, TUserRole, TUserLogin, TUserToken, TRoleClaim>
|
||||
where TUser : IdentityUser<TKey>
|
||||
where TRole : IdentityRole<TKey>
|
||||
where TContext : DbContext
|
||||
where TKey : IEquatable<TKey>
|
||||
where TUserClaim : IdentityUserClaim<TKey>, new()
|
||||
|
|
|
|||
|
|
@ -54,8 +54,8 @@ namespace Microsoft.AspNetCore.Identity.Service.EntityFrameworkCore
|
|||
TRedirectUri,
|
||||
TApplicationKey> :
|
||||
IdentityDbContext<TUser, TRole, TUserKey, TUserClaim, TUserRole, TUserLogin, TRoleClaim, TUserToken>
|
||||
where TUser : IdentityUser<TUserKey, TUserClaim, TUserRole, TUserLogin, TUserToken>
|
||||
where TRole : IdentityRole<TUserKey, TUserRole, TRoleClaim>
|
||||
where TUser : IdentityUser<TUserKey>
|
||||
where TRole : IdentityRole<TUserKey>
|
||||
where TUserKey : IEquatable<TUserKey>
|
||||
where TUserClaim : IdentityUserClaim<TUserKey>
|
||||
where TUserRole : IdentityUserRole<TUserKey>
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
|
@ -1,119 +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 System;
|
||||
using System.Text;
|
||||
|
||||
namespace Microsoft.AspNetCore.Identity
|
||||
{
|
||||
// See http://tools.ietf.org/html/rfc3548#section-5
|
||||
internal static class Base32
|
||||
{
|
||||
private static readonly string _base32Chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567";
|
||||
|
||||
public static string ToBase32(byte[] input)
|
||||
{
|
||||
if (input == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(input));
|
||||
}
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (int offset = 0; offset < input.Length;)
|
||||
{
|
||||
byte a, b, c, d, e, f, g, h;
|
||||
int numCharsToOutput = GetNextGroup(input, ref offset, out a, out b, out c, out d, out e, out f, out g, out h);
|
||||
|
||||
sb.Append((numCharsToOutput >= 1) ? _base32Chars[a] : '=');
|
||||
sb.Append((numCharsToOutput >= 2) ? _base32Chars[b] : '=');
|
||||
sb.Append((numCharsToOutput >= 3) ? _base32Chars[c] : '=');
|
||||
sb.Append((numCharsToOutput >= 4) ? _base32Chars[d] : '=');
|
||||
sb.Append((numCharsToOutput >= 5) ? _base32Chars[e] : '=');
|
||||
sb.Append((numCharsToOutput >= 6) ? _base32Chars[f] : '=');
|
||||
sb.Append((numCharsToOutput >= 7) ? _base32Chars[g] : '=');
|
||||
sb.Append((numCharsToOutput >= 8) ? _base32Chars[h] : '=');
|
||||
}
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
public static byte[] FromBase32(string input)
|
||||
{
|
||||
if (input == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(input));
|
||||
}
|
||||
input = input.TrimEnd('=').ToUpperInvariant();
|
||||
if (input.Length == 0)
|
||||
{
|
||||
return new byte[0];
|
||||
}
|
||||
|
||||
var output = new byte[input.Length * 5 / 8];
|
||||
var bitIndex = 0;
|
||||
var inputIndex = 0;
|
||||
var outputBits = 0;
|
||||
var outputIndex = 0;
|
||||
while (outputIndex < output.Length)
|
||||
{
|
||||
var byteIndex = _base32Chars.IndexOf(input[inputIndex]);
|
||||
if (byteIndex < 0)
|
||||
{
|
||||
throw new FormatException();
|
||||
}
|
||||
|
||||
var bits = Math.Min(5 - bitIndex, 8 - outputBits);
|
||||
output[outputIndex] <<= bits;
|
||||
output[outputIndex] |= (byte)(byteIndex >> (5 - (bitIndex + bits)));
|
||||
|
||||
bitIndex += bits;
|
||||
if (bitIndex >= 5)
|
||||
{
|
||||
inputIndex++;
|
||||
bitIndex = 0;
|
||||
}
|
||||
|
||||
outputBits += bits;
|
||||
if (outputBits >= 8)
|
||||
{
|
||||
outputIndex++;
|
||||
outputBits = 0;
|
||||
}
|
||||
}
|
||||
return output;
|
||||
}
|
||||
|
||||
// returns the number of bytes that were output
|
||||
private static int GetNextGroup(byte[] input, ref int offset, out byte a, out byte b, out byte c, out byte d, out byte e, out byte f, out byte g, out byte h)
|
||||
{
|
||||
uint b1, b2, b3, b4, b5;
|
||||
|
||||
int retVal;
|
||||
switch (offset - input.Length)
|
||||
{
|
||||
case 1: retVal = 2; break;
|
||||
case 2: retVal = 4; break;
|
||||
case 3: retVal = 5; break;
|
||||
case 4: retVal = 7; break;
|
||||
default: retVal = 8; break;
|
||||
}
|
||||
|
||||
b1 = (offset < input.Length) ? input[offset++] : 0U;
|
||||
b2 = (offset < input.Length) ? input[offset++] : 0U;
|
||||
b3 = (offset < input.Length) ? input[offset++] : 0U;
|
||||
b4 = (offset < input.Length) ? input[offset++] : 0U;
|
||||
b5 = (offset < input.Length) ? input[offset++] : 0U;
|
||||
|
||||
a = (byte)(b1 >> 3);
|
||||
b = (byte)(((b1 & 0x07) << 2) | (b2 >> 6));
|
||||
c = (byte)((b2 >> 1) & 0x1f);
|
||||
d = (byte)(((b2 & 0x01) << 4) | (b3 >> 4));
|
||||
e = (byte)(((b3 & 0x0f) << 1) | (b4 >> 7));
|
||||
f = (byte)((b4 >> 2) & 0x1f);
|
||||
g = (byte)(((b4 & 0x3) << 3) | (b5 >> 5));
|
||||
h = (byte)(b5 & 0x1f);
|
||||
|
||||
return retVal;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
// 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 System;
|
||||
using System.Reflection;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
namespace Microsoft.AspNetCore.Identity
|
||||
{
|
||||
/// <summary>
|
||||
/// Helper functions for configuring identity services.
|
||||
/// </summary>
|
||||
public static class IdentityBuilderExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Adds the default token providers used to generate tokens for reset passwords, change email
|
||||
/// and change telephone number operations, and for two factor authentication token generation.
|
||||
/// </summary>
|
||||
/// <param name="builder">The current <see cref="IdentityBuilder"/> instance.</param>
|
||||
/// <returns>The current <see cref="IdentityBuilder"/> instance.</returns>
|
||||
public static IdentityBuilder AddDefaultTokenProviders(this IdentityBuilder builder)
|
||||
{
|
||||
var userType = builder.UserType;
|
||||
var dataProtectionProviderType = typeof(DataProtectorTokenProvider<>).MakeGenericType(userType);
|
||||
var phoneNumberProviderType = typeof(PhoneNumberTokenProvider<>).MakeGenericType(userType);
|
||||
var emailTokenProviderType = typeof(EmailTokenProvider<>).MakeGenericType(userType);
|
||||
var authenticatorProviderType = typeof(AuthenticatorTokenProvider<>).MakeGenericType(userType);
|
||||
return builder.AddTokenProvider(TokenOptions.DefaultProvider, dataProtectionProviderType)
|
||||
.AddTokenProvider(TokenOptions.DefaultEmailProvider, emailTokenProviderType)
|
||||
.AddTokenProvider(TokenOptions.DefaultPhoneProvider, phoneNumberProviderType)
|
||||
.AddTokenProvider(TokenOptions.DefaultAuthenticatorProvider, authenticatorProviderType);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a <see cref="SignInManager{TUser}"/> for the <seealso cref="IdentityBuilder.UserType"/>.
|
||||
/// </summary>
|
||||
/// <typeparam name="TSignInManager">The type of the sign in manager to add.</typeparam>
|
||||
/// <param name="builder">The current <see cref="IdentityBuilder"/> instance.</param>
|
||||
/// <returns>The current <see cref="IdentityBuilder"/> instance.</returns>
|
||||
public static IdentityBuilder AddSignInManager<TSignInManager>(this IdentityBuilder builder) where TSignInManager : class
|
||||
{
|
||||
var managerType = typeof(SignInManager<>).MakeGenericType(builder.UserType);
|
||||
|
||||
var customType = typeof(TSignInManager);
|
||||
if (!managerType.GetTypeInfo().IsAssignableFrom(customType.GetTypeInfo()))
|
||||
{
|
||||
throw new InvalidOperationException(Resources.FormatInvalidManagerType(customType.Name, "SignInManager", builder.UserType.Name));
|
||||
}
|
||||
if (managerType != customType)
|
||||
{
|
||||
builder.Services.AddScoped(typeof(TSignInManager), services => services.GetRequiredService(managerType));
|
||||
}
|
||||
builder.Services.AddScoped(managerType, typeof(TSignInManager));
|
||||
return builder;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -5,58 +5,52 @@ namespace Microsoft.AspNetCore.Identity
|
|||
using System.Reflection;
|
||||
using System.Resources;
|
||||
|
||||
internal static class AspNetIdentityResources
|
||||
internal static class Resources
|
||||
{
|
||||
private static readonly ResourceManager _resourceManager
|
||||
= new ResourceManager("Microsoft.AspNetCore.Identity.Resources", typeof(AspNetIdentityResources).GetTypeInfo().Assembly);
|
||||
= new ResourceManager("Microsoft.AspNetCore.Identity.Resources", typeof(Resources).GetTypeInfo().Assembly);
|
||||
|
||||
/// <summary>
|
||||
/// Type {0} must derive from {1}<{2}>.
|
||||
/// </summary>
|
||||
internal static string InvalidManagerType
|
||||
{
|
||||
get { return GetString("InvalidManagerType"); }
|
||||
get => GetString("InvalidManagerType");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Type {0} must derive from {1}<{2}>.
|
||||
/// </summary>
|
||||
internal static string FormatInvalidManagerType(object p0, object p1, object p2)
|
||||
{
|
||||
return string.Format(CultureInfo.CurrentCulture, GetString("InvalidManagerType"), p0, p1, p2);
|
||||
}
|
||||
=> string.Format(CultureInfo.CurrentCulture, GetString("InvalidManagerType"), p0, p1, p2);
|
||||
|
||||
/// <summary>
|
||||
/// The provided PasswordHasherCompatibilityMode is invalid.
|
||||
/// </summary>
|
||||
internal static string InvalidPasswordHasherCompatibilityMode
|
||||
{
|
||||
get { return GetString("InvalidPasswordHasherCompatibilityMode"); }
|
||||
get => GetString("InvalidPasswordHasherCompatibilityMode");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The provided PasswordHasherCompatibilityMode is invalid.
|
||||
/// </summary>
|
||||
internal static string FormatInvalidPasswordHasherCompatibilityMode()
|
||||
{
|
||||
return GetString("InvalidPasswordHasherCompatibilityMode");
|
||||
}
|
||||
=> GetString("InvalidPasswordHasherCompatibilityMode");
|
||||
|
||||
/// <summary>
|
||||
/// The iteration count must be a positive integer.
|
||||
/// </summary>
|
||||
internal static string InvalidPasswordHasherIterationCount
|
||||
{
|
||||
get { return GetString("InvalidPasswordHasherIterationCount"); }
|
||||
get => GetString("InvalidPasswordHasherIterationCount");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The iteration count must be a positive integer.
|
||||
/// </summary>
|
||||
internal static string FormatInvalidPasswordHasherIterationCount()
|
||||
{
|
||||
return GetString("InvalidPasswordHasherIterationCount");
|
||||
}
|
||||
=> GetString("InvalidPasswordHasherIterationCount");
|
||||
|
||||
private static string GetString(string name, params string[] formatterNames)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -5,6 +5,8 @@ using System;
|
|||
using System.Reflection;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.DependencyInjection.Extensions;
|
||||
using Microsoft.Extensions.Identity.Core;
|
||||
|
||||
namespace Microsoft.AspNetCore.Identity
|
||||
{
|
||||
|
|
@ -17,15 +19,22 @@ namespace Microsoft.AspNetCore.Identity
|
|||
/// Creates a new instance of <see cref="IdentityBuilder"/>.
|
||||
/// </summary>
|
||||
/// <param name="user">The <see cref="Type"/> to use for the users.</param>
|
||||
/// <param name="role">The <see cref="Type"/> to use for the roles.</param>
|
||||
/// <param name="services">The <see cref="IServiceCollection"/> to attach to.</param>
|
||||
public IdentityBuilder(Type user, Type role, IServiceCollection services)
|
||||
public IdentityBuilder(Type user, IServiceCollection services)
|
||||
{
|
||||
UserType = user;
|
||||
RoleType = role;
|
||||
Services = services;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of <see cref="IdentityBuilder"/>.
|
||||
/// </summary>
|
||||
/// <param name="user">The <see cref="Type"/> to use for the users.</param>
|
||||
/// <param name="role">The <see cref="Type"/> to use for the roles.</param>
|
||||
/// <param name="services">The <see cref="IServiceCollection"/> to attach to.</param>
|
||||
public IdentityBuilder(Type user, Type role, IServiceCollection services) : this(user, services)
|
||||
=> RoleType = role;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the <see cref="Type"/> used for users.
|
||||
/// </summary>
|
||||
|
|
@ -60,32 +69,18 @@ namespace Microsoft.AspNetCore.Identity
|
|||
/// <summary>
|
||||
/// Adds an <see cref="IUserValidator{TUser}"/> for the <seealso cref="UserType"/>.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The user validator type.</typeparam>
|
||||
/// <typeparam name="TUser">The user validator type.</typeparam>
|
||||
/// <returns>The current <see cref="IdentityBuilder"/> instance.</returns>
|
||||
public virtual IdentityBuilder AddUserValidator<T>() where T : class
|
||||
{
|
||||
return AddScoped(typeof(IUserValidator<>).MakeGenericType(UserType), typeof(T));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds an <see cref="IRoleValidator{TRole}"/> for the <seealso cref="RoleType"/>.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The role validator type.</typeparam>
|
||||
/// <returns>The current <see cref="IdentityBuilder"/> instance.</returns>
|
||||
public virtual IdentityBuilder AddRoleValidator<T>() where T : class
|
||||
{
|
||||
return AddScoped(typeof(IRoleValidator<>).MakeGenericType(RoleType), typeof(T));
|
||||
}
|
||||
public virtual IdentityBuilder AddUserValidator<TUser>() where TUser : class
|
||||
=> AddScoped(typeof(IUserValidator<>).MakeGenericType(UserType), typeof(TUser));
|
||||
|
||||
/// <summary>
|
||||
/// Adds an <see cref="IUserClaimsPrincipalFactory{TUser}"/> for the <seealso cref="UserType"/>.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of the claims principal factory.</typeparam>
|
||||
/// <typeparam name="TUser">The type of the claims principal factory.</typeparam>
|
||||
/// <returns>The current <see cref="IdentityBuilder"/> instance.</returns>
|
||||
public virtual IdentityBuilder AddClaimsPrincipalFactory<T>() where T : class
|
||||
{
|
||||
return AddScoped(typeof(IUserClaimsPrincipalFactory<>).MakeGenericType(UserType), typeof(T));
|
||||
}
|
||||
public virtual IdentityBuilder AddClaimsPrincipalFactory<TUser>() where TUser : class
|
||||
=> AddScoped(typeof(IUserClaimsPrincipalFactory<>).MakeGenericType(UserType), typeof(TUser));
|
||||
|
||||
/// <summary>
|
||||
/// Adds an <see cref="IdentityErrorDescriber"/>.
|
||||
|
|
@ -101,32 +96,18 @@ namespace Microsoft.AspNetCore.Identity
|
|||
/// <summary>
|
||||
/// Adds an <see cref="IPasswordValidator{TUser}"/> for the <seealso cref="UserType"/>.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The user type whose password will be validated.</typeparam>
|
||||
/// <typeparam name="TUser">The user type whose password will be validated.</typeparam>
|
||||
/// <returns>The current <see cref="IdentityBuilder"/> instance.</returns>
|
||||
public virtual IdentityBuilder AddPasswordValidator<T>() where T : class
|
||||
{
|
||||
return AddScoped(typeof(IPasswordValidator<>).MakeGenericType(UserType), typeof(T));
|
||||
}
|
||||
public virtual IdentityBuilder AddPasswordValidator<TUser>() where TUser : class
|
||||
=> AddScoped(typeof(IPasswordValidator<>).MakeGenericType(UserType), typeof(TUser));
|
||||
|
||||
/// <summary>
|
||||
/// Adds an <see cref="IUserStore{TUser}"/> for the <seealso cref="UserType"/>.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The user type held in the store.</typeparam>
|
||||
/// <typeparam name="TUser">The user type held in the store.</typeparam>
|
||||
/// <returns>The current <see cref="IdentityBuilder"/> instance.</returns>
|
||||
public virtual IdentityBuilder AddUserStore<T>() where T : class
|
||||
{
|
||||
return AddScoped(typeof(IUserStore<>).MakeGenericType(UserType), typeof(T));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a <see cref="IRoleStore{TRole}"/> for the <seealso cref="RoleType"/>.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The role type held in the store.</typeparam>
|
||||
/// <returns>The current <see cref="IdentityBuilder"/> instance.</returns>
|
||||
public virtual IdentityBuilder AddRoleStore<T>() where T : class
|
||||
{
|
||||
return AddScoped(typeof(IRoleStore<>).MakeGenericType(RoleType), typeof(T));
|
||||
}
|
||||
public virtual IdentityBuilder AddUserStore<TUser>() where TUser : class
|
||||
=> AddScoped(typeof(IUserStore<>).MakeGenericType(UserType), typeof(TUser));
|
||||
|
||||
/// <summary>
|
||||
/// Adds a token provider.
|
||||
|
|
@ -135,9 +116,7 @@ namespace Microsoft.AspNetCore.Identity
|
|||
/// <param name="providerName">The name of the provider to add.</param>
|
||||
/// <returns>The current <see cref="IdentityBuilder"/> instance.</returns>
|
||||
public virtual IdentityBuilder AddTokenProvider<TProvider>(string providerName) where TProvider : class
|
||||
{
|
||||
return AddTokenProvider(providerName, typeof(TProvider));
|
||||
}
|
||||
=> AddTokenProvider(providerName, typeof(TProvider));
|
||||
|
||||
/// <summary>
|
||||
/// Adds a token provider for the <seealso cref="UserType"/>.
|
||||
|
|
@ -149,7 +128,7 @@ namespace Microsoft.AspNetCore.Identity
|
|||
{
|
||||
if (!typeof(IUserTwoFactorTokenProvider<>).MakeGenericType(UserType).GetTypeInfo().IsAssignableFrom(provider.GetTypeInfo()))
|
||||
{
|
||||
throw new InvalidOperationException(AspNetIdentityResources.FormatInvalidManagerType(provider.Name, "IUserTokenProvider", UserType.Name));
|
||||
throw new InvalidOperationException(Resources.FormatInvalidManagerType(provider.Name, "IUserTokenProvider", UserType.Name));
|
||||
}
|
||||
Services.Configure<IdentityOptions>(options =>
|
||||
{
|
||||
|
|
@ -159,23 +138,6 @@ namespace Microsoft.AspNetCore.Identity
|
|||
return this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds the default token providers used to generate tokens for reset passwords, change email
|
||||
/// and change telephone number operations, and for two factor authentication token generation.
|
||||
/// </summary>
|
||||
/// <returns>The current <see cref="IdentityBuilder"/> instance.</returns>
|
||||
public virtual IdentityBuilder AddDefaultTokenProviders()
|
||||
{
|
||||
var dataProtectionProviderType = typeof(DataProtectorTokenProvider<>).MakeGenericType(UserType);
|
||||
var phoneNumberProviderType = typeof(PhoneNumberTokenProvider<>).MakeGenericType(UserType);
|
||||
var emailTokenProviderType = typeof(EmailTokenProvider<>).MakeGenericType(UserType);
|
||||
var authenticatorProviderType = typeof(AuthenticatorTokenProvider<>).MakeGenericType(UserType);
|
||||
return AddTokenProvider(TokenOptions.DefaultProvider, dataProtectionProviderType)
|
||||
.AddTokenProvider(TokenOptions.DefaultEmailProvider, emailTokenProviderType)
|
||||
.AddTokenProvider(TokenOptions.DefaultPhoneProvider, phoneNumberProviderType)
|
||||
.AddTokenProvider(TokenOptions.DefaultAuthenticatorProvider, authenticatorProviderType);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a <see cref="UserManager{TUser}"/> for the <seealso cref="UserType"/>.
|
||||
/// </summary>
|
||||
|
|
@ -185,15 +147,60 @@ namespace Microsoft.AspNetCore.Identity
|
|||
{
|
||||
var userManagerType = typeof(UserManager<>).MakeGenericType(UserType);
|
||||
var customType = typeof(TUserManager);
|
||||
if (userManagerType == customType ||
|
||||
!userManagerType.GetTypeInfo().IsAssignableFrom(customType.GetTypeInfo()))
|
||||
if (!userManagerType.GetTypeInfo().IsAssignableFrom(customType.GetTypeInfo()))
|
||||
{
|
||||
throw new InvalidOperationException(AspNetIdentityResources.FormatInvalidManagerType(customType.Name, "UserManager", UserType.Name));
|
||||
throw new InvalidOperationException(Resources.FormatInvalidManagerType(customType.Name, "UserManager", UserType.Name));
|
||||
}
|
||||
if (userManagerType != customType)
|
||||
{
|
||||
Services.AddScoped(customType, services => services.GetRequiredService(userManagerType));
|
||||
}
|
||||
Services.AddScoped(customType, services => services.GetRequiredService(userManagerType));
|
||||
return AddScoped(userManagerType, customType);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds Role related services for TRole, including IRoleStore, IRoleValidator, and RoleManager.
|
||||
/// </summary>
|
||||
/// <typeparam name="TRole">The role type.</typeparam>
|
||||
/// <returns>The current <see cref="IdentityBuilder"/> instance.</returns>
|
||||
public virtual IdentityBuilder AddRoles<TRole>() where TRole : class
|
||||
{
|
||||
RoleType = typeof(TRole);
|
||||
AddRoleStore<TRole>();
|
||||
AddRoleValidator<RoleValidator<TRole>>();
|
||||
Services.TryAddScoped<RoleManager<TRole>, RoleManager<TRole>>();
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds an <see cref="IRoleValidator{TRole}"/> for the <seealso cref="RoleType"/>.
|
||||
/// </summary>
|
||||
/// <typeparam name="TRole">The role validator type.</typeparam>
|
||||
/// <returns>The current <see cref="IdentityBuilder"/> instance.</returns>
|
||||
public virtual IdentityBuilder AddRoleValidator<TRole>() where TRole : class
|
||||
{
|
||||
if (RoleType == null)
|
||||
{
|
||||
throw new InvalidOperationException(Resources.NoRoleType);
|
||||
}
|
||||
return AddScoped(typeof(IRoleValidator<>).MakeGenericType(RoleType), typeof(TRole));
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Adds a <see cref="IRoleStore{TRole}"/> for the <seealso cref="RoleType"/>.
|
||||
/// </summary>
|
||||
/// <typeparam name="TRole">The role type held in the store.</typeparam>
|
||||
/// <returns>The current <see cref="IdentityBuilder"/> instance.</returns>
|
||||
public virtual IdentityBuilder AddRoleStore<TRole>() where TRole : class
|
||||
{
|
||||
if (RoleType == null)
|
||||
{
|
||||
throw new InvalidOperationException(Resources.NoRoleType);
|
||||
}
|
||||
return AddScoped(typeof(IRoleStore<>).MakeGenericType(RoleType), typeof(TRole));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a <see cref="RoleManager{TRole}"/> for the <seealso cref="RoleType"/>.
|
||||
/// </summary>
|
||||
|
|
@ -201,33 +208,21 @@ namespace Microsoft.AspNetCore.Identity
|
|||
/// <returns>The current <see cref="IdentityBuilder"/> instance.</returns>
|
||||
public virtual IdentityBuilder AddRoleManager<TRoleManager>() where TRoleManager : class
|
||||
{
|
||||
if (RoleType == null)
|
||||
{
|
||||
throw new InvalidOperationException(Resources.NoRoleType);
|
||||
}
|
||||
var managerType = typeof(RoleManager<>).MakeGenericType(RoleType);
|
||||
var customType = typeof(TRoleManager);
|
||||
if (managerType == customType ||
|
||||
!managerType.GetTypeInfo().IsAssignableFrom(customType.GetTypeInfo()))
|
||||
if (!managerType.GetTypeInfo().IsAssignableFrom(customType.GetTypeInfo()))
|
||||
{
|
||||
throw new InvalidOperationException(AspNetIdentityResources.FormatInvalidManagerType(customType.Name, "RoleManager", RoleType.Name));
|
||||
throw new InvalidOperationException(Resources.FormatInvalidManagerType(customType.Name, "RoleManager", RoleType.Name));
|
||||
}
|
||||
if (managerType != customType)
|
||||
{
|
||||
Services.AddScoped(typeof(TRoleManager), services => services.GetRequiredService(managerType));
|
||||
}
|
||||
Services.AddScoped(typeof(TRoleManager), services => services.GetRequiredService(managerType));
|
||||
return AddScoped(managerType, typeof(TRoleManager));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a <see cref="SignInManager{TUser}"/> for the <seealso cref="UserType"/>.
|
||||
/// </summary>
|
||||
/// <typeparam name="TSignInManager">The type of the sign in manager to add.</typeparam>
|
||||
/// <returns>The current <see cref="IdentityBuilder"/> instance.</returns>
|
||||
public virtual IdentityBuilder AddSignInManager<TSignInManager>() where TSignInManager : class
|
||||
{
|
||||
var managerType = typeof(SignInManager<>).MakeGenericType(UserType);
|
||||
var customType = typeof(TSignInManager);
|
||||
if (managerType == customType ||
|
||||
!managerType.GetTypeInfo().IsAssignableFrom(customType.GetTypeInfo()))
|
||||
{
|
||||
throw new InvalidOperationException(AspNetIdentityResources.FormatInvalidManagerType(customType.Name, "SignInManager", UserType.Name));
|
||||
}
|
||||
Services.AddScoped(typeof(TSignInManager), services => services.GetRequiredService(managerType));
|
||||
return AddScoped(managerType, typeof(TSignInManager));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,6 +1,8 @@
|
|||
// 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.Extensions.Identity.Core;
|
||||
|
||||
namespace Microsoft.AspNetCore.Identity
|
||||
{
|
||||
/// <summary>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,47 @@
|
|||
// 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 System;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Identity;
|
||||
using Microsoft.Extensions.DependencyInjection.Extensions;
|
||||
|
||||
namespace Microsoft.Extensions.DependencyInjection
|
||||
{
|
||||
/// <summary>
|
||||
/// Contains extension methods to <see cref="IServiceCollection"/> for configuring identity services.
|
||||
/// </summary>
|
||||
public static class IdentityServiceCollectionExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Adds and configures the identity system for the specified User and Role types.
|
||||
/// </summary>
|
||||
/// <typeparam name="TUser">The type representing a User in the system.</typeparam>
|
||||
/// <param name="services">The services available in the application.</param>
|
||||
/// <param name="setupAction">An action to configure the <see cref="IdentityOptions"/>.</param>
|
||||
/// <returns>An <see cref="IdentityBuilder"/> for creating and configuring the identity system.</returns>
|
||||
public static IdentityBuilder AddIdentityCore<TUser>(this IServiceCollection services, Action<IdentityOptions> setupAction)
|
||||
where TUser : class
|
||||
{
|
||||
// Services identity depends on
|
||||
services.AddOptions().AddLogging();
|
||||
|
||||
// Services used by identity
|
||||
services.TryAddScoped<IUserValidator<TUser>, UserValidator<TUser>>();
|
||||
services.TryAddScoped<IPasswordValidator<TUser>, PasswordValidator<TUser>>();
|
||||
services.TryAddScoped<IPasswordHasher<TUser>, PasswordHasher<TUser>>();
|
||||
services.TryAddScoped<ILookupNormalizer, UpperInvariantLookupNormalizer>();
|
||||
// No interface for the error describer so we can add errors without rev'ing the interface
|
||||
services.TryAddScoped<IdentityErrorDescriber>();
|
||||
services.TryAddScoped<IUserClaimsPrincipalFactory<TUser>, UserClaimsPrincipalFactory<TUser>>();
|
||||
services.TryAddScoped<UserManager<TUser>, UserManager<TUser>>();
|
||||
|
||||
if (setupAction != null)
|
||||
{
|
||||
services.Configure(setupAction);
|
||||
}
|
||||
|
||||
return new IdentityBuilder(typeof(TUser), services);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -11,6 +11,7 @@
|
|||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.AspNetCore.Cryptography.KeyDerivation" Version="$(AspNetCoreVersion)" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging" Version="$(AspNetCoreVersion)" />
|
||||
<PackageReference Include="Microsoft.Extensions.Options" Version="$(AspNetCoreVersion)" />
|
||||
<PackageReference Include="System.ComponentModel.Annotations" Version="$(CoreFxVersion)" />
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ using System;
|
|||
using System.Runtime.CompilerServices;
|
||||
using System.Security.Cryptography;
|
||||
using Microsoft.AspNetCore.Cryptography.KeyDerivation;
|
||||
using Microsoft.Extensions.Identity.Core;
|
||||
using Microsoft.Extensions.Options;
|
||||
|
||||
namespace Microsoft.AspNetCore.Identity
|
||||
|
|
@ -53,12 +54,12 @@ namespace Microsoft.AspNetCore.Identity
|
|||
_iterCount = options.IterationCount;
|
||||
if (_iterCount < 1)
|
||||
{
|
||||
throw new InvalidOperationException(AspNetIdentityResources.InvalidPasswordHasherIterationCount);
|
||||
throw new InvalidOperationException(Resources.InvalidPasswordHasherIterationCount);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new InvalidOperationException(AspNetIdentityResources.InvalidPasswordHasherCompatibilityMode);
|
||||
throw new InvalidOperationException(Resources.InvalidPasswordHasherCompatibilityMode);
|
||||
}
|
||||
|
||||
_rng = options.Rng;
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
// <auto-generated />
|
||||
namespace Microsoft.AspNetCore.Identity
|
||||
namespace Microsoft.Extensions.Identity.Core
|
||||
{
|
||||
using System.Globalization;
|
||||
using System.Reflection;
|
||||
|
|
@ -15,753 +15,673 @@ namespace Microsoft.AspNetCore.Identity
|
|||
/// </summary>
|
||||
internal static string ConcurrencyFailure
|
||||
{
|
||||
get { return GetString("ConcurrencyFailure"); }
|
||||
get => GetString("ConcurrencyFailure");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Optimistic concurrency failure, object has been modified.
|
||||
/// </summary>
|
||||
internal static string FormatConcurrencyFailure()
|
||||
{
|
||||
return GetString("ConcurrencyFailure");
|
||||
}
|
||||
=> GetString("ConcurrencyFailure");
|
||||
|
||||
/// <summary>
|
||||
/// An unknown failure has occurred.
|
||||
/// </summary>
|
||||
internal static string DefaultError
|
||||
{
|
||||
get { return GetString("DefaultError"); }
|
||||
get => GetString("DefaultError");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// An unknown failure has occurred.
|
||||
/// </summary>
|
||||
internal static string FormatDefaultError()
|
||||
{
|
||||
return GetString("DefaultError");
|
||||
}
|
||||
=> GetString("DefaultError");
|
||||
|
||||
/// <summary>
|
||||
/// Email '{0}' is already taken.
|
||||
/// </summary>
|
||||
internal static string DuplicateEmail
|
||||
{
|
||||
get { return GetString("DuplicateEmail"); }
|
||||
get => GetString("DuplicateEmail");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Email '{0}' is already taken.
|
||||
/// </summary>
|
||||
internal static string FormatDuplicateEmail(object p0)
|
||||
{
|
||||
return string.Format(CultureInfo.CurrentCulture, GetString("DuplicateEmail"), p0);
|
||||
}
|
||||
=> string.Format(CultureInfo.CurrentCulture, GetString("DuplicateEmail"), p0);
|
||||
|
||||
/// <summary>
|
||||
/// Role name '{0}' is already taken.
|
||||
/// </summary>
|
||||
internal static string DuplicateRoleName
|
||||
{
|
||||
get { return GetString("DuplicateRoleName"); }
|
||||
get => GetString("DuplicateRoleName");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Role name '{0}' is already taken.
|
||||
/// </summary>
|
||||
internal static string FormatDuplicateRoleName(object p0)
|
||||
{
|
||||
return string.Format(CultureInfo.CurrentCulture, GetString("DuplicateRoleName"), p0);
|
||||
}
|
||||
=> string.Format(CultureInfo.CurrentCulture, GetString("DuplicateRoleName"), p0);
|
||||
|
||||
/// <summary>
|
||||
/// User name '{0}' is already taken.
|
||||
/// </summary>
|
||||
internal static string DuplicateUserName
|
||||
{
|
||||
get { return GetString("DuplicateUserName"); }
|
||||
get => GetString("DuplicateUserName");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// User name '{0}' is already taken.
|
||||
/// </summary>
|
||||
internal static string FormatDuplicateUserName(object p0)
|
||||
{
|
||||
return string.Format(CultureInfo.CurrentCulture, GetString("DuplicateUserName"), p0);
|
||||
}
|
||||
=> string.Format(CultureInfo.CurrentCulture, GetString("DuplicateUserName"), p0);
|
||||
|
||||
/// <summary>
|
||||
/// Email '{0}' is invalid.
|
||||
/// </summary>
|
||||
internal static string InvalidEmail
|
||||
{
|
||||
get { return GetString("InvalidEmail"); }
|
||||
get => GetString("InvalidEmail");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Email '{0}' is invalid.
|
||||
/// </summary>
|
||||
internal static string FormatInvalidEmail(object p0)
|
||||
{
|
||||
return string.Format(CultureInfo.CurrentCulture, GetString("InvalidEmail"), p0);
|
||||
}
|
||||
=> string.Format(CultureInfo.CurrentCulture, GetString("InvalidEmail"), p0);
|
||||
|
||||
/// <summary>
|
||||
/// Type {0} must derive from {1}<{2}>.
|
||||
/// </summary>
|
||||
internal static string InvalidManagerType
|
||||
{
|
||||
get { return GetString("InvalidManagerType"); }
|
||||
get => GetString("InvalidManagerType");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Type {0} must derive from {1}<{2}>.
|
||||
/// </summary>
|
||||
internal static string FormatInvalidManagerType(object p0, object p1, object p2)
|
||||
{
|
||||
return string.Format(CultureInfo.CurrentCulture, GetString("InvalidManagerType"), p0, p1, p2);
|
||||
}
|
||||
=> string.Format(CultureInfo.CurrentCulture, GetString("InvalidManagerType"), p0, p1, p2);
|
||||
|
||||
/// <summary>
|
||||
/// The provided PasswordHasherCompatibilityMode is invalid.
|
||||
/// </summary>
|
||||
internal static string InvalidPasswordHasherCompatibilityMode
|
||||
{
|
||||
get { return GetString("InvalidPasswordHasherCompatibilityMode"); }
|
||||
get => GetString("InvalidPasswordHasherCompatibilityMode");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The provided PasswordHasherCompatibilityMode is invalid.
|
||||
/// </summary>
|
||||
internal static string FormatInvalidPasswordHasherCompatibilityMode()
|
||||
{
|
||||
return GetString("InvalidPasswordHasherCompatibilityMode");
|
||||
}
|
||||
=> GetString("InvalidPasswordHasherCompatibilityMode");
|
||||
|
||||
/// <summary>
|
||||
/// The iteration count must be a positive integer.
|
||||
/// </summary>
|
||||
internal static string InvalidPasswordHasherIterationCount
|
||||
{
|
||||
get { return GetString("InvalidPasswordHasherIterationCount"); }
|
||||
get => GetString("InvalidPasswordHasherIterationCount");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The iteration count must be a positive integer.
|
||||
/// </summary>
|
||||
internal static string FormatInvalidPasswordHasherIterationCount()
|
||||
{
|
||||
return GetString("InvalidPasswordHasherIterationCount");
|
||||
}
|
||||
=> GetString("InvalidPasswordHasherIterationCount");
|
||||
|
||||
/// <summary>
|
||||
/// Role name '{0}' is invalid.
|
||||
/// </summary>
|
||||
internal static string InvalidRoleName
|
||||
{
|
||||
get { return GetString("InvalidRoleName"); }
|
||||
get => GetString("InvalidRoleName");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Role name '{0}' is invalid.
|
||||
/// </summary>
|
||||
internal static string FormatInvalidRoleName(object p0)
|
||||
{
|
||||
return string.Format(CultureInfo.CurrentCulture, GetString("InvalidRoleName"), p0);
|
||||
}
|
||||
=> string.Format(CultureInfo.CurrentCulture, GetString("InvalidRoleName"), p0);
|
||||
|
||||
/// <summary>
|
||||
/// Invalid token.
|
||||
/// </summary>
|
||||
internal static string InvalidToken
|
||||
{
|
||||
get { return GetString("InvalidToken"); }
|
||||
get => GetString("InvalidToken");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Invalid token.
|
||||
/// </summary>
|
||||
internal static string FormatInvalidToken()
|
||||
{
|
||||
return GetString("InvalidToken");
|
||||
}
|
||||
=> GetString("InvalidToken");
|
||||
|
||||
/// <summary>
|
||||
/// User name '{0}' is invalid, can only contain letters or digits.
|
||||
/// </summary>
|
||||
internal static string InvalidUserName
|
||||
{
|
||||
get { return GetString("InvalidUserName"); }
|
||||
get => GetString("InvalidUserName");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// User name '{0}' is invalid, can only contain letters or digits.
|
||||
/// </summary>
|
||||
internal static string FormatInvalidUserName(object p0)
|
||||
{
|
||||
return string.Format(CultureInfo.CurrentCulture, GetString("InvalidUserName"), p0);
|
||||
}
|
||||
=> string.Format(CultureInfo.CurrentCulture, GetString("InvalidUserName"), p0);
|
||||
|
||||
/// <summary>
|
||||
/// A user with this login already exists.
|
||||
/// </summary>
|
||||
internal static string LoginAlreadyAssociated
|
||||
{
|
||||
get { return GetString("LoginAlreadyAssociated"); }
|
||||
get => GetString("LoginAlreadyAssociated");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A user with this login already exists.
|
||||
/// </summary>
|
||||
internal static string FormatLoginAlreadyAssociated()
|
||||
{
|
||||
return GetString("LoginAlreadyAssociated");
|
||||
}
|
||||
=> GetString("LoginAlreadyAssociated");
|
||||
|
||||
/// <summary>
|
||||
/// AddIdentity must be called on the service collection.
|
||||
/// </summary>
|
||||
internal static string MustCallAddIdentity
|
||||
{
|
||||
get { return GetString("MustCallAddIdentity"); }
|
||||
get => GetString("MustCallAddIdentity");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// AddIdentity must be called on the service collection.
|
||||
/// </summary>
|
||||
internal static string FormatMustCallAddIdentity()
|
||||
{
|
||||
return GetString("MustCallAddIdentity");
|
||||
}
|
||||
=> GetString("MustCallAddIdentity");
|
||||
|
||||
/// <summary>
|
||||
/// No IUserTokenProvider named '{0}' is registered.
|
||||
/// </summary>
|
||||
internal static string NoTokenProvider
|
||||
{
|
||||
get { return GetString("NoTokenProvider"); }
|
||||
get => GetString("NoTokenProvider");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// No IUserTokenProvider named '{0}' is registered.
|
||||
/// </summary>
|
||||
internal static string FormatNoTokenProvider(object p0)
|
||||
{
|
||||
return string.Format(CultureInfo.CurrentCulture, GetString("NoTokenProvider"), p0);
|
||||
}
|
||||
=> string.Format(CultureInfo.CurrentCulture, GetString("NoTokenProvider"), p0);
|
||||
|
||||
/// <summary>
|
||||
/// User security stamp cannot be null.
|
||||
/// </summary>
|
||||
internal static string NullSecurityStamp
|
||||
{
|
||||
get { return GetString("NullSecurityStamp"); }
|
||||
get => GetString("NullSecurityStamp");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// User security stamp cannot be null.
|
||||
/// </summary>
|
||||
internal static string FormatNullSecurityStamp()
|
||||
{
|
||||
return GetString("NullSecurityStamp");
|
||||
}
|
||||
=> GetString("NullSecurityStamp");
|
||||
|
||||
/// <summary>
|
||||
/// Incorrect password.
|
||||
/// </summary>
|
||||
internal static string PasswordMismatch
|
||||
{
|
||||
get { return GetString("PasswordMismatch"); }
|
||||
get => GetString("PasswordMismatch");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Incorrect password.
|
||||
/// </summary>
|
||||
internal static string FormatPasswordMismatch()
|
||||
{
|
||||
return GetString("PasswordMismatch");
|
||||
}
|
||||
=> GetString("PasswordMismatch");
|
||||
|
||||
/// <summary>
|
||||
/// Passwords must have at least one digit ('0'-'9').
|
||||
/// </summary>
|
||||
internal static string PasswordRequiresDigit
|
||||
{
|
||||
get { return GetString("PasswordRequiresDigit"); }
|
||||
get => GetString("PasswordRequiresDigit");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Passwords must have at least one digit ('0'-'9').
|
||||
/// </summary>
|
||||
internal static string FormatPasswordRequiresDigit()
|
||||
{
|
||||
return GetString("PasswordRequiresDigit");
|
||||
}
|
||||
=> GetString("PasswordRequiresDigit");
|
||||
|
||||
/// <summary>
|
||||
/// Passwords must have at least one lowercase ('a'-'z').
|
||||
/// </summary>
|
||||
internal static string PasswordRequiresLower
|
||||
{
|
||||
get { return GetString("PasswordRequiresLower"); }
|
||||
get => GetString("PasswordRequiresLower");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Passwords must have at least one lowercase ('a'-'z').
|
||||
/// </summary>
|
||||
internal static string FormatPasswordRequiresLower()
|
||||
{
|
||||
return GetString("PasswordRequiresLower");
|
||||
}
|
||||
=> GetString("PasswordRequiresLower");
|
||||
|
||||
/// <summary>
|
||||
/// Passwords must have at least one non alphanumeric character.
|
||||
/// </summary>
|
||||
internal static string PasswordRequiresNonAlphanumeric
|
||||
{
|
||||
get { return GetString("PasswordRequiresNonAlphanumeric"); }
|
||||
get => GetString("PasswordRequiresNonAlphanumeric");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Passwords must have at least one non alphanumeric character.
|
||||
/// </summary>
|
||||
internal static string FormatPasswordRequiresNonAlphanumeric()
|
||||
{
|
||||
return GetString("PasswordRequiresNonAlphanumeric");
|
||||
}
|
||||
=> GetString("PasswordRequiresNonAlphanumeric");
|
||||
|
||||
/// <summary>
|
||||
/// Passwords must have at least one uppercase ('A'-'Z').
|
||||
/// </summary>
|
||||
internal static string PasswordRequiresUpper
|
||||
{
|
||||
get { return GetString("PasswordRequiresUpper"); }
|
||||
get => GetString("PasswordRequiresUpper");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Passwords must have at least one uppercase ('A'-'Z').
|
||||
/// </summary>
|
||||
internal static string FormatPasswordRequiresUpper()
|
||||
{
|
||||
return GetString("PasswordRequiresUpper");
|
||||
}
|
||||
=> GetString("PasswordRequiresUpper");
|
||||
|
||||
/// <summary>
|
||||
/// Passwords must be at least {0} characters.
|
||||
/// </summary>
|
||||
internal static string PasswordTooShort
|
||||
{
|
||||
get { return GetString("PasswordTooShort"); }
|
||||
get => GetString("PasswordTooShort");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Passwords must be at least {0} characters.
|
||||
/// </summary>
|
||||
internal static string FormatPasswordTooShort(object p0)
|
||||
{
|
||||
return string.Format(CultureInfo.CurrentCulture, GetString("PasswordTooShort"), p0);
|
||||
}
|
||||
=> string.Format(CultureInfo.CurrentCulture, GetString("PasswordTooShort"), p0);
|
||||
|
||||
/// <summary>
|
||||
/// Role {0} does not exist.
|
||||
/// </summary>
|
||||
internal static string RoleNotFound
|
||||
{
|
||||
get { return GetString("RoleNotFound"); }
|
||||
get => GetString("RoleNotFound");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Role {0} does not exist.
|
||||
/// </summary>
|
||||
internal static string FormatRoleNotFound(object p0)
|
||||
{
|
||||
return string.Format(CultureInfo.CurrentCulture, GetString("RoleNotFound"), p0);
|
||||
}
|
||||
=> string.Format(CultureInfo.CurrentCulture, GetString("RoleNotFound"), p0);
|
||||
|
||||
/// <summary>
|
||||
/// Store does not implement IQueryableRoleStore<TRole>.
|
||||
/// </summary>
|
||||
internal static string StoreNotIQueryableRoleStore
|
||||
{
|
||||
get { return GetString("StoreNotIQueryableRoleStore"); }
|
||||
get => GetString("StoreNotIQueryableRoleStore");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Store does not implement IQueryableRoleStore<TRole>.
|
||||
/// </summary>
|
||||
internal static string FormatStoreNotIQueryableRoleStore()
|
||||
{
|
||||
return GetString("StoreNotIQueryableRoleStore");
|
||||
}
|
||||
=> GetString("StoreNotIQueryableRoleStore");
|
||||
|
||||
/// <summary>
|
||||
/// Store does not implement IQueryableUserStore<TUser>.
|
||||
/// </summary>
|
||||
internal static string StoreNotIQueryableUserStore
|
||||
{
|
||||
get { return GetString("StoreNotIQueryableUserStore"); }
|
||||
get => GetString("StoreNotIQueryableUserStore");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Store does not implement IQueryableUserStore<TUser>.
|
||||
/// </summary>
|
||||
internal static string FormatStoreNotIQueryableUserStore()
|
||||
{
|
||||
return GetString("StoreNotIQueryableUserStore");
|
||||
}
|
||||
=> GetString("StoreNotIQueryableUserStore");
|
||||
|
||||
/// <summary>
|
||||
/// Store does not implement IRoleClaimStore<TRole>.
|
||||
/// </summary>
|
||||
internal static string StoreNotIRoleClaimStore
|
||||
{
|
||||
get { return GetString("StoreNotIRoleClaimStore"); }
|
||||
get => GetString("StoreNotIRoleClaimStore");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Store does not implement IRoleClaimStore<TRole>.
|
||||
/// </summary>
|
||||
internal static string FormatStoreNotIRoleClaimStore()
|
||||
{
|
||||
return GetString("StoreNotIRoleClaimStore");
|
||||
}
|
||||
=> GetString("StoreNotIRoleClaimStore");
|
||||
|
||||
/// <summary>
|
||||
/// Store does not implement IUserAuthenticationTokenStore<User>.
|
||||
/// </summary>
|
||||
internal static string StoreNotIUserAuthenticationTokenStore
|
||||
{
|
||||
get { return GetString("StoreNotIUserAuthenticationTokenStore"); }
|
||||
get => GetString("StoreNotIUserAuthenticationTokenStore");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Store does not implement IUserAuthenticationTokenStore<User>.
|
||||
/// </summary>
|
||||
internal static string FormatStoreNotIUserAuthenticationTokenStore()
|
||||
{
|
||||
return GetString("StoreNotIUserAuthenticationTokenStore");
|
||||
}
|
||||
=> GetString("StoreNotIUserAuthenticationTokenStore");
|
||||
|
||||
/// <summary>
|
||||
/// Store does not implement IUserClaimStore<TUser>.
|
||||
/// </summary>
|
||||
internal static string StoreNotIUserClaimStore
|
||||
{
|
||||
get { return GetString("StoreNotIUserClaimStore"); }
|
||||
get => GetString("StoreNotIUserClaimStore");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Store does not implement IUserClaimStore<TUser>.
|
||||
/// </summary>
|
||||
internal static string FormatStoreNotIUserClaimStore()
|
||||
{
|
||||
return GetString("StoreNotIUserClaimStore");
|
||||
}
|
||||
=> GetString("StoreNotIUserClaimStore");
|
||||
|
||||
/// <summary>
|
||||
/// Store does not implement IUserConfirmationStore<TUser>.
|
||||
/// </summary>
|
||||
internal static string StoreNotIUserConfirmationStore
|
||||
{
|
||||
get { return GetString("StoreNotIUserConfirmationStore"); }
|
||||
get => GetString("StoreNotIUserConfirmationStore");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Store does not implement IUserConfirmationStore<TUser>.
|
||||
/// </summary>
|
||||
internal static string FormatStoreNotIUserConfirmationStore()
|
||||
{
|
||||
return GetString("StoreNotIUserConfirmationStore");
|
||||
}
|
||||
=> GetString("StoreNotIUserConfirmationStore");
|
||||
|
||||
/// <summary>
|
||||
/// Store does not implement IUserEmailStore<TUser>.
|
||||
/// </summary>
|
||||
internal static string StoreNotIUserEmailStore
|
||||
{
|
||||
get { return GetString("StoreNotIUserEmailStore"); }
|
||||
get => GetString("StoreNotIUserEmailStore");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Store does not implement IUserEmailStore<TUser>.
|
||||
/// </summary>
|
||||
internal static string FormatStoreNotIUserEmailStore()
|
||||
{
|
||||
return GetString("StoreNotIUserEmailStore");
|
||||
}
|
||||
=> GetString("StoreNotIUserEmailStore");
|
||||
|
||||
/// <summary>
|
||||
/// Store does not implement IUserLockoutStore<TUser>.
|
||||
/// </summary>
|
||||
internal static string StoreNotIUserLockoutStore
|
||||
{
|
||||
get { return GetString("StoreNotIUserLockoutStore"); }
|
||||
get => GetString("StoreNotIUserLockoutStore");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Store does not implement IUserLockoutStore<TUser>.
|
||||
/// </summary>
|
||||
internal static string FormatStoreNotIUserLockoutStore()
|
||||
{
|
||||
return GetString("StoreNotIUserLockoutStore");
|
||||
}
|
||||
=> GetString("StoreNotIUserLockoutStore");
|
||||
|
||||
/// <summary>
|
||||
/// Store does not implement IUserLoginStore<TUser>.
|
||||
/// </summary>
|
||||
internal static string StoreNotIUserLoginStore
|
||||
{
|
||||
get { return GetString("StoreNotIUserLoginStore"); }
|
||||
get => GetString("StoreNotIUserLoginStore");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Store does not implement IUserLoginStore<TUser>.
|
||||
/// </summary>
|
||||
internal static string FormatStoreNotIUserLoginStore()
|
||||
{
|
||||
return GetString("StoreNotIUserLoginStore");
|
||||
}
|
||||
=> GetString("StoreNotIUserLoginStore");
|
||||
|
||||
/// <summary>
|
||||
/// Store does not implement IUserPasswordStore<TUser>.
|
||||
/// </summary>
|
||||
internal static string StoreNotIUserPasswordStore
|
||||
{
|
||||
get { return GetString("StoreNotIUserPasswordStore"); }
|
||||
get => GetString("StoreNotIUserPasswordStore");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Store does not implement IUserPasswordStore<TUser>.
|
||||
/// </summary>
|
||||
internal static string FormatStoreNotIUserPasswordStore()
|
||||
{
|
||||
return GetString("StoreNotIUserPasswordStore");
|
||||
}
|
||||
=> GetString("StoreNotIUserPasswordStore");
|
||||
|
||||
/// <summary>
|
||||
/// Store does not implement IUserPhoneNumberStore<TUser>.
|
||||
/// </summary>
|
||||
internal static string StoreNotIUserPhoneNumberStore
|
||||
{
|
||||
get { return GetString("StoreNotIUserPhoneNumberStore"); }
|
||||
get => GetString("StoreNotIUserPhoneNumberStore");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Store does not implement IUserPhoneNumberStore<TUser>.
|
||||
/// </summary>
|
||||
internal static string FormatStoreNotIUserPhoneNumberStore()
|
||||
{
|
||||
return GetString("StoreNotIUserPhoneNumberStore");
|
||||
}
|
||||
=> GetString("StoreNotIUserPhoneNumberStore");
|
||||
|
||||
/// <summary>
|
||||
/// Store does not implement IUserRoleStore<TUser>.
|
||||
/// </summary>
|
||||
internal static string StoreNotIUserRoleStore
|
||||
{
|
||||
get { return GetString("StoreNotIUserRoleStore"); }
|
||||
get => GetString("StoreNotIUserRoleStore");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Store does not implement IUserRoleStore<TUser>.
|
||||
/// </summary>
|
||||
internal static string FormatStoreNotIUserRoleStore()
|
||||
{
|
||||
return GetString("StoreNotIUserRoleStore");
|
||||
}
|
||||
=> GetString("StoreNotIUserRoleStore");
|
||||
|
||||
/// <summary>
|
||||
/// Store does not implement IUserSecurityStampStore<TUser>.
|
||||
/// </summary>
|
||||
internal static string StoreNotIUserSecurityStampStore
|
||||
{
|
||||
get { return GetString("StoreNotIUserSecurityStampStore"); }
|
||||
get => GetString("StoreNotIUserSecurityStampStore");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Store does not implement IUserSecurityStampStore<TUser>.
|
||||
/// </summary>
|
||||
internal static string FormatStoreNotIUserSecurityStampStore()
|
||||
{
|
||||
return GetString("StoreNotIUserSecurityStampStore");
|
||||
}
|
||||
=> GetString("StoreNotIUserSecurityStampStore");
|
||||
|
||||
/// <summary>
|
||||
/// Store does not implement IUserAuthenticatorKeyStore<User>.
|
||||
/// </summary>
|
||||
internal static string StoreNotIUserAuthenticatorKeyStore
|
||||
{
|
||||
get { return GetString("StoreNotIUserAuthenticatorKeyStore"); }
|
||||
get => GetString("StoreNotIUserAuthenticatorKeyStore");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Store does not implement IUserAuthenticatorKeyStore<User>.
|
||||
/// </summary>
|
||||
internal static string FormatStoreNotIUserAuthenticatorKeyStore()
|
||||
{
|
||||
return GetString("StoreNotIUserAuthenticatorKeyStore");
|
||||
}
|
||||
=> GetString("StoreNotIUserAuthenticatorKeyStore");
|
||||
|
||||
/// <summary>
|
||||
/// Store does not implement IUserTwoFactorStore<TUser>.
|
||||
/// </summary>
|
||||
internal static string StoreNotIUserTwoFactorStore
|
||||
{
|
||||
get { return GetString("StoreNotIUserTwoFactorStore"); }
|
||||
get => GetString("StoreNotIUserTwoFactorStore");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Store does not implement IUserTwoFactorStore<TUser>.
|
||||
/// </summary>
|
||||
internal static string FormatStoreNotIUserTwoFactorStore()
|
||||
{
|
||||
return GetString("StoreNotIUserTwoFactorStore");
|
||||
}
|
||||
=> GetString("StoreNotIUserTwoFactorStore");
|
||||
|
||||
/// <summary>
|
||||
/// Recovery code redemption failed.
|
||||
/// </summary>
|
||||
internal static string RecoveryCodeRedemptionFailed
|
||||
{
|
||||
get { return GetString("RecoveryCodeRedemptionFailed"); }
|
||||
get => GetString("RecoveryCodeRedemptionFailed");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Recovery code redemption failed.
|
||||
/// </summary>
|
||||
internal static string FormatRecoveryCodeRedemptionFailed()
|
||||
{
|
||||
return GetString("RecoveryCodeRedemptionFailed");
|
||||
}
|
||||
=> GetString("RecoveryCodeRedemptionFailed");
|
||||
|
||||
/// <summary>
|
||||
/// User already has a password set.
|
||||
/// </summary>
|
||||
internal static string UserAlreadyHasPassword
|
||||
{
|
||||
get { return GetString("UserAlreadyHasPassword"); }
|
||||
get => GetString("UserAlreadyHasPassword");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// User already has a password set.
|
||||
/// </summary>
|
||||
internal static string FormatUserAlreadyHasPassword()
|
||||
{
|
||||
return GetString("UserAlreadyHasPassword");
|
||||
}
|
||||
=> GetString("UserAlreadyHasPassword");
|
||||
|
||||
/// <summary>
|
||||
/// User already in role '{0}'.
|
||||
/// </summary>
|
||||
internal static string UserAlreadyInRole
|
||||
{
|
||||
get { return GetString("UserAlreadyInRole"); }
|
||||
get => GetString("UserAlreadyInRole");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// User already in role '{0}'.
|
||||
/// </summary>
|
||||
internal static string FormatUserAlreadyInRole(object p0)
|
||||
{
|
||||
return string.Format(CultureInfo.CurrentCulture, GetString("UserAlreadyInRole"), p0);
|
||||
}
|
||||
=> string.Format(CultureInfo.CurrentCulture, GetString("UserAlreadyInRole"), p0);
|
||||
|
||||
/// <summary>
|
||||
/// User is locked out.
|
||||
/// </summary>
|
||||
internal static string UserLockedOut
|
||||
{
|
||||
get { return GetString("UserLockedOut"); }
|
||||
get => GetString("UserLockedOut");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// User is locked out.
|
||||
/// </summary>
|
||||
internal static string FormatUserLockedOut()
|
||||
{
|
||||
return GetString("UserLockedOut");
|
||||
}
|
||||
=> GetString("UserLockedOut");
|
||||
|
||||
/// <summary>
|
||||
/// Lockout is not enabled for this user.
|
||||
/// </summary>
|
||||
internal static string UserLockoutNotEnabled
|
||||
{
|
||||
get { return GetString("UserLockoutNotEnabled"); }
|
||||
get => GetString("UserLockoutNotEnabled");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Lockout is not enabled for this user.
|
||||
/// </summary>
|
||||
internal static string FormatUserLockoutNotEnabled()
|
||||
{
|
||||
return GetString("UserLockoutNotEnabled");
|
||||
}
|
||||
=> GetString("UserLockoutNotEnabled");
|
||||
|
||||
/// <summary>
|
||||
/// User {0} does not exist.
|
||||
/// </summary>
|
||||
internal static string UserNameNotFound
|
||||
{
|
||||
get { return GetString("UserNameNotFound"); }
|
||||
get => GetString("UserNameNotFound");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// User {0} does not exist.
|
||||
/// </summary>
|
||||
internal static string FormatUserNameNotFound(object p0)
|
||||
{
|
||||
return string.Format(CultureInfo.CurrentCulture, GetString("UserNameNotFound"), p0);
|
||||
}
|
||||
=> string.Format(CultureInfo.CurrentCulture, GetString("UserNameNotFound"), p0);
|
||||
|
||||
/// <summary>
|
||||
/// User is not in role '{0}'.
|
||||
/// </summary>
|
||||
internal static string UserNotInRole
|
||||
{
|
||||
get { return GetString("UserNotInRole"); }
|
||||
get => GetString("UserNotInRole");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// User is not in role '{0}'.
|
||||
/// </summary>
|
||||
internal static string FormatUserNotInRole(object p0)
|
||||
{
|
||||
return string.Format(CultureInfo.CurrentCulture, GetString("UserNotInRole"), p0);
|
||||
}
|
||||
=> string.Format(CultureInfo.CurrentCulture, GetString("UserNotInRole"), p0);
|
||||
|
||||
/// <summary>
|
||||
/// Store does not implement IUserTwoFactorRecoveryCodeStore<User>.
|
||||
/// </summary>
|
||||
internal static string StoreNotIUserTwoFactorRecoveryCodeStore
|
||||
{
|
||||
get { return GetString("StoreNotIUserTwoFactorRecoveryCodeStore"); }
|
||||
get => GetString("StoreNotIUserTwoFactorRecoveryCodeStore");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Store does not implement IUserTwoFactorRecoveryCodeStore<User>.
|
||||
/// </summary>
|
||||
internal static string FormatStoreNotIUserTwoFactorRecoveryCodeStore()
|
||||
{
|
||||
return GetString("StoreNotIUserTwoFactorRecoveryCodeStore");
|
||||
}
|
||||
=> GetString("StoreNotIUserTwoFactorRecoveryCodeStore");
|
||||
|
||||
/// <summary>
|
||||
/// Passwords must use at least {0} different characters.
|
||||
/// </summary>
|
||||
internal static string PasswordRequiresUniqueChars
|
||||
{
|
||||
get { return GetString("PasswordRequiresUniqueChars"); }
|
||||
get => GetString("PasswordRequiresUniqueChars");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Passwords must use at least {0} different characters.
|
||||
/// </summary>
|
||||
internal static string FormatPasswordRequiresUniqueChars(object p0)
|
||||
=> string.Format(CultureInfo.CurrentCulture, GetString("PasswordRequiresUniqueChars"), p0);
|
||||
|
||||
/// <summary>
|
||||
/// No RoleType was specified, try AddRoles<TRole>().
|
||||
/// </summary>
|
||||
internal static string NoRoleType
|
||||
{
|
||||
return string.Format(CultureInfo.CurrentCulture, GetString("PasswordRequiresUniqueChars"), p0);
|
||||
get => GetString("NoRoleType");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// No RoleType was specified, try AddRoles<TRole>().
|
||||
/// </summary>
|
||||
internal static string FormatNoRoleType()
|
||||
=> GetString("NoRoleType");
|
||||
|
||||
private static string GetString(string name, params string[] formatterNames)
|
||||
{
|
||||
var value = _resourceManager.GetString(name);
|
||||
|
|
|
|||
|
|
@ -305,4 +305,8 @@
|
|||
<value>Passwords must use at least {0} different characters.</value>
|
||||
<comment>Error message for passwords that are based on similar characters</comment>
|
||||
</data>
|
||||
<data name="NoRoleType" xml:space="preserve">
|
||||
<value>No RoleType was specified, try AddRoles<TRole>().</value>
|
||||
<comment>Error when the IdentityBuilder.RoleType was not specified</comment>
|
||||
</data>
|
||||
</root>
|
||||
|
|
@ -7,6 +7,7 @@ using System.Linq;
|
|||
using System.Security.Claims;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Extensions.Identity.Core;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace Microsoft.AspNetCore.Identity
|
||||
|
|
|
|||
|
|
@ -13,36 +13,27 @@ namespace Microsoft.AspNetCore.Identity
|
|||
/// Provides methods to create a claims principal for a given user.
|
||||
/// </summary>
|
||||
/// <typeparam name="TUser">The type used to represent a user.</typeparam>
|
||||
/// <typeparam name="TRole">The type used to represent a role.</typeparam>
|
||||
public class UserClaimsPrincipalFactory<TUser, TRole> : IUserClaimsPrincipalFactory<TUser>
|
||||
public class UserClaimsPrincipalFactory<TUser> : IUserClaimsPrincipalFactory<TUser>
|
||||
where TUser : class
|
||||
where TRole : class
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="UserClaimsPrincipalFactory{TUser, TRole}"/> class.
|
||||
/// Initializes a new instance of the <see cref="UserClaimsPrincipalFactory{TUser}"/> class.
|
||||
/// </summary>
|
||||
/// <param name="userManager">The <see cref="UserManager{TUser}"/> to retrieve user information from.</param>
|
||||
/// <param name="roleManager">The <see cref="RoleManager{TRole}"/> to retrieve a user's roles from.</param>
|
||||
/// <param name="optionsAccessor">The configured <see cref="IdentityOptions"/>.</param>
|
||||
public UserClaimsPrincipalFactory(
|
||||
UserManager<TUser> userManager,
|
||||
RoleManager<TRole> roleManager,
|
||||
UserManager<TUser> userManager,
|
||||
IOptions<IdentityOptions> optionsAccessor)
|
||||
{
|
||||
if (userManager == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(userManager));
|
||||
}
|
||||
if (roleManager == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(roleManager));
|
||||
}
|
||||
if (optionsAccessor == null || optionsAccessor.Value == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(optionsAccessor));
|
||||
}
|
||||
UserManager = userManager;
|
||||
RoleManager = roleManager;
|
||||
Options = optionsAccessor.Value;
|
||||
}
|
||||
|
||||
|
|
@ -54,14 +45,6 @@ namespace Microsoft.AspNetCore.Identity
|
|||
/// </value>
|
||||
public UserManager<TUser> UserManager { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the <see cref="RoleManager{TRole}"/> for this factory.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The current <see cref="RoleManager{TRole}"/> for this factory instance.
|
||||
/// </value>
|
||||
public RoleManager<TRole> RoleManager { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the <see cref="IdentityOptions"/> for this factory.
|
||||
/// </summary>
|
||||
|
|
@ -81,18 +64,78 @@ namespace Microsoft.AspNetCore.Identity
|
|||
{
|
||||
throw new ArgumentNullException(nameof(user));
|
||||
}
|
||||
var id = await GenerateClaimsAsync(user);
|
||||
return new ClaimsPrincipal(id);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Generate the claims for a user.
|
||||
/// </summary>
|
||||
/// <param name="user">The user to create a <see cref="ClaimsIdentity"/> from.</param>
|
||||
/// <returns>The <see cref="Task"/> that represents the asynchronous creation operation, containing the created <see cref="ClaimsIdentity"/>.</returns>
|
||||
protected virtual async Task<ClaimsIdentity> GenerateClaimsAsync(TUser user)
|
||||
{
|
||||
var userId = await UserManager.GetUserIdAsync(user);
|
||||
var userName = await UserManager.GetUserNameAsync(user);
|
||||
var id = new ClaimsIdentity(IdentityConstants.ApplicationScheme,
|
||||
var id = new ClaimsIdentity("Identity.Application", // REVIEW: Used to match Application scheme
|
||||
Options.ClaimsIdentity.UserNameClaimType,
|
||||
Options.ClaimsIdentity.RoleClaimType);
|
||||
id.AddClaim(new Claim(Options.ClaimsIdentity.UserIdClaimType, userId));
|
||||
id.AddClaim(new Claim(Options.ClaimsIdentity.UserNameClaimType, userName));
|
||||
if (UserManager.SupportsUserSecurityStamp)
|
||||
{
|
||||
id.AddClaim(new Claim(Options.ClaimsIdentity.SecurityStampClaimType,
|
||||
id.AddClaim(new Claim(Options.ClaimsIdentity.SecurityStampClaimType,
|
||||
await UserManager.GetSecurityStampAsync(user)));
|
||||
}
|
||||
if (UserManager.SupportsUserClaim)
|
||||
{
|
||||
id.AddClaims(await UserManager.GetClaimsAsync(user));
|
||||
}
|
||||
return id;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Provides methods to create a claims principal for a given user.
|
||||
/// </summary>
|
||||
/// <typeparam name="TUser">The type used to represent a user.</typeparam>
|
||||
/// <typeparam name="TRole">The type used to represent a role.</typeparam>
|
||||
public class UserClaimsPrincipalFactory<TUser, TRole> : UserClaimsPrincipalFactory<TUser>
|
||||
where TUser : class
|
||||
where TRole : class
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="UserClaimsPrincipalFactory{TUser, TRole}"/> class.
|
||||
/// </summary>
|
||||
/// <param name="userManager">The <see cref="UserManager{TUser}"/> to retrieve user information from.</param>
|
||||
/// <param name="roleManager">The <see cref="RoleManager{TRole}"/> to retrieve a user's roles from.</param>
|
||||
/// <param name="options">The configured <see cref="IdentityOptions"/>.</param>
|
||||
public UserClaimsPrincipalFactory(UserManager<TUser> userManager, RoleManager<TRole> roleManager, IOptions<IdentityOptions> options)
|
||||
: base(userManager, options)
|
||||
{
|
||||
if (roleManager == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(roleManager));
|
||||
}
|
||||
RoleManager = roleManager;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the <see cref="RoleManager{TRole}"/> for this factory.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The current <see cref="RoleManager{TRole}"/> for this factory instance.
|
||||
/// </value>
|
||||
public RoleManager<TRole> RoleManager { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Generate the claims for a user.
|
||||
/// </summary>
|
||||
/// <param name="user">The user to create a <see cref="ClaimsIdentity"/> from.</param>
|
||||
/// <returns>The <see cref="Task"/> that represents the asynchronous creation operation, containing the created <see cref="ClaimsIdentity"/>.</returns>
|
||||
protected override async Task<ClaimsIdentity> GenerateClaimsAsync(TUser user)
|
||||
{
|
||||
var id = await base.GenerateClaimsAsync(user);
|
||||
if (UserManager.SupportsUserRole)
|
||||
{
|
||||
var roles = await UserManager.GetRolesAsync(user);
|
||||
|
|
@ -109,21 +152,7 @@ namespace Microsoft.AspNetCore.Identity
|
|||
}
|
||||
}
|
||||
}
|
||||
if (UserManager.SupportsUserClaim)
|
||||
{
|
||||
id.AddClaims(await UserManager.GetClaimsAsync(user));
|
||||
}
|
||||
return await CreatePrincipalAsync(id);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a <see cref="ClaimsPrincipal"/> from a <see cref="ClaimsIdentity"/>.
|
||||
/// </summary>
|
||||
/// <param name="id">The <see cref="ClaimsIdentity"/> with claims.</param>
|
||||
/// <returns>The <see cref="Task"/> that represents the asynchronous creation operation, containing the <see cref="ClaimsPrincipal"/> with the <see cref="ClaimsIdentity"/>.</returns>
|
||||
protected virtual Task<ClaimsPrincipal> CreatePrincipalAsync(ClaimsIdentity id)
|
||||
{
|
||||
return Task.FromResult(new ClaimsPrincipal(id));
|
||||
return id;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -12,6 +12,7 @@ using System.Threading;
|
|||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Identity.Core;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Options;
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@
|
|||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Microsoft.AspNetCore.Identity
|
||||
{
|
||||
|
|
@ -39,34 +38,7 @@ namespace Microsoft.AspNetCore.Identity
|
|||
/// Represents a role in the identity system
|
||||
/// </summary>
|
||||
/// <typeparam name="TKey">The type used for the primary key for the role.</typeparam>
|
||||
public class IdentityRole<TKey> : IdentityRole<TKey, IdentityUserRole<TKey>, IdentityRoleClaim<TKey>>
|
||||
where TKey : IEquatable<TKey>
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of <see cref="IdentityRole{TKey}"/>.
|
||||
/// </summary>
|
||||
public IdentityRole() { }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of <see cref="IdentityRole{TKey}"/>.
|
||||
/// </summary>
|
||||
/// <param name="roleName">The role name.</param>
|
||||
public IdentityRole(string roleName) : this()
|
||||
{
|
||||
Name = roleName;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents a role in the identity system
|
||||
/// </summary>
|
||||
/// <typeparam name="TKey">The type used for the primary key for the role.</typeparam>
|
||||
/// <typeparam name="TUserRole">The type used for user roles.</typeparam>
|
||||
/// <typeparam name="TRoleClaim">The type used for role claims.</typeparam>
|
||||
public class IdentityRole<TKey, TUserRole, TRoleClaim>
|
||||
where TKey : IEquatable<TKey>
|
||||
where TUserRole : IdentityUserRole<TKey>
|
||||
where TRoleClaim : IdentityRoleClaim<TKey>
|
||||
public class IdentityRole<TKey> where TKey : IEquatable<TKey>
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of <see cref="IdentityRole{TKey}"/>.
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@
|
|||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Microsoft.AspNetCore.Identity
|
||||
{
|
||||
|
|
@ -39,19 +38,7 @@ namespace Microsoft.AspNetCore.Identity
|
|||
/// Represents a user in the identity system
|
||||
/// </summary>
|
||||
/// <typeparam name="TKey">The type used for the primary key for the user.</typeparam>
|
||||
public class IdentityUser<TKey> : IdentityUser<TKey, IdentityUserClaim<TKey>, IdentityUserRole<TKey>, IdentityUserLogin<TKey>, IdentityUserToken<TKey>>
|
||||
where TKey : IEquatable<TKey>
|
||||
{ }
|
||||
|
||||
/// <summary>
|
||||
/// Represents a user in the identity system
|
||||
/// </summary>
|
||||
/// <typeparam name="TKey">The type used for the primary key for the user.</typeparam>
|
||||
/// <typeparam name="TUserClaim">The type representing a claim.</typeparam>
|
||||
/// <typeparam name="TUserRole">The type representing a user role.</typeparam>
|
||||
/// <typeparam name="TUserLogin">The type representing a user external login.</typeparam>
|
||||
/// <typeparam name="TUserToken">The type representing a user external login.</typeparam>
|
||||
public class IdentityUser<TKey, TUserClaim, TUserRole, TUserLogin, TUserToken> where TKey : IEquatable<TKey>
|
||||
public class IdentityUser<TKey> where TKey : IEquatable<TKey>
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of <see cref="IdentityUser{TKey}"/>.
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ namespace Microsoft.AspNetCore.Identity
|
|||
public abstract class RoleStoreBase<TRole, TKey, TUserRole, TRoleClaim> :
|
||||
IQueryableRoleStore<TRole>,
|
||||
IRoleClaimStore<TRole>
|
||||
where TRole : IdentityRole<TKey, TUserRole, TRoleClaim>
|
||||
where TRole : IdentityRole<TKey>
|
||||
where TKey : IEquatable<TKey>
|
||||
where TUserRole : IdentityUserRole<TKey>, new()
|
||||
where TRoleClaim : IdentityRoleClaim<TKey>, new()
|
||||
|
|
@ -219,10 +219,7 @@ namespace Microsoft.AspNetCore.Identity
|
|||
/// <summary>
|
||||
/// Dispose the stores
|
||||
/// </summary>
|
||||
public void Dispose()
|
||||
{
|
||||
_disposed = true;
|
||||
}
|
||||
public void Dispose() => _disposed = true;
|
||||
|
||||
/// <summary>
|
||||
/// Get the claims associated with the specified <paramref name="role"/> as an asynchronous operation.
|
||||
|
|
@ -265,8 +262,6 @@ namespace Microsoft.AspNetCore.Identity
|
|||
/// <param name="claim">The associated claim.</param>
|
||||
/// <returns>The role claim entity.</returns>
|
||||
protected virtual TRoleClaim CreateRoleClaim(TRole role, Claim claim)
|
||||
{
|
||||
return new TRoleClaim { RoleId = role.Id, ClaimType = claim.Type, ClaimValue = claim.Value };
|
||||
}
|
||||
=> new TRoleClaim { RoleId = role.Id, ClaimType = claim.Type, ClaimValue = claim.Value };
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,24 +8,19 @@ using System.Linq;
|
|||
using System.Security.Claims;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Extensions.Internal;
|
||||
|
||||
namespace Microsoft.AspNetCore.Identity
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a new instance of a persistence store for the specified user and role types.
|
||||
/// Represents a new instance of a persistence store for the specified user type.
|
||||
/// </summary>
|
||||
/// <typeparam name="TUser">The type representing a user.</typeparam>
|
||||
/// <typeparam name="TRole">The type representing a role.</typeparam>
|
||||
/// <typeparam name="TKey">The type of the primary key for a role.</typeparam>
|
||||
/// <typeparam name="TKey">The type of the primary key for a user.</typeparam>
|
||||
/// <typeparam name="TUserClaim">The type representing a claim.</typeparam>
|
||||
/// <typeparam name="TUserRole">The type representing a user role.</typeparam>
|
||||
/// <typeparam name="TUserLogin">The type representing a user external login.</typeparam>
|
||||
/// <typeparam name="TUserToken">The type representing a user token.</typeparam>
|
||||
/// <typeparam name="TRoleClaim">The type representing a role claim.</typeparam>
|
||||
public abstract class UserStoreBase<TUser, TRole, TKey, TUserClaim, TUserRole, TUserLogin, TUserToken, TRoleClaim> :
|
||||
public abstract class UserStoreBase<TUser, TKey, TUserClaim, TUserLogin, TUserToken> :
|
||||
IUserLoginStore<TUser>,
|
||||
IUserRoleStore<TUser>,
|
||||
IUserClaimStore<TUser>,
|
||||
IUserPasswordStore<TUser>,
|
||||
IUserSecurityStampStore<TUser>,
|
||||
|
|
@ -37,14 +32,11 @@ namespace Microsoft.AspNetCore.Identity
|
|||
IUserAuthenticationTokenStore<TUser>,
|
||||
IUserAuthenticatorKeyStore<TUser>,
|
||||
IUserTwoFactorRecoveryCodeStore<TUser>
|
||||
where TUser : IdentityUser<TKey, TUserClaim, TUserRole, TUserLogin, TUserToken>
|
||||
where TRole : IdentityRole<TKey, TUserRole, TRoleClaim>
|
||||
where TUser : IdentityUser<TKey>
|
||||
where TKey : IEquatable<TKey>
|
||||
where TUserClaim : IdentityUserClaim<TKey>, new()
|
||||
where TUserRole : IdentityUserRole<TKey>, new()
|
||||
where TUserLogin : IdentityUserLogin<TKey>, new()
|
||||
where TUserToken : IdentityUserToken<TKey>, new()
|
||||
where TRoleClaim : IdentityRoleClaim<TKey>, new()
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates a new instance.
|
||||
|
|
@ -67,21 +59,6 @@ namespace Microsoft.AspNetCore.Identity
|
|||
/// </summary>
|
||||
public IdentityErrorDescriber ErrorDescriber { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Called to create a new instance of a <see cref="IdentityUserRole{TKey}"/>.
|
||||
/// </summary>
|
||||
/// <param name="user">The associated user.</param>
|
||||
/// <param name="role">The associated role.</param>
|
||||
/// <returns></returns>
|
||||
protected virtual TUserRole CreateUserRole(TUser user, TRole role)
|
||||
{
|
||||
return new TUserRole()
|
||||
{
|
||||
UserId = user.Id,
|
||||
RoleId = role.Id
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called to create a new instance of a <see cref="IdentityUserClaim{TKey}"/>.
|
||||
/// </summary>
|
||||
|
|
@ -349,23 +326,6 @@ namespace Microsoft.AspNetCore.Identity
|
|||
return Task.FromResult(user.PasswordHash != null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return a role with the normalized name if it exists.
|
||||
/// </summary>
|
||||
/// <param name="normalizedRoleName">The normalized role name.</param>
|
||||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> used to propagate notifications that the operation should be canceled.</param>
|
||||
/// <returns>The role if it exists.</returns>
|
||||
protected abstract Task<TRole> FindRoleAsync(string normalizedRoleName, CancellationToken cancellationToken);
|
||||
|
||||
/// <summary>
|
||||
/// Return a user role for the userId and roleId if it exists.
|
||||
/// </summary>
|
||||
/// <param name="userId">The user's id.</param>
|
||||
/// <param name="roleId">The role's id.</param>
|
||||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> used to propagate notifications that the operation should be canceled.</param>
|
||||
/// <returns>The user role if it exists.</returns>
|
||||
protected abstract Task<TUserRole> FindUserRoleAsync(TKey userId, TKey roleId, CancellationToken cancellationToken);
|
||||
|
||||
/// <summary>
|
||||
/// Return a user with the matching userId if it exists.
|
||||
/// </summary>
|
||||
|
|
@ -393,42 +353,6 @@ namespace Microsoft.AspNetCore.Identity
|
|||
/// <returns>The user login if it exists.</returns>
|
||||
protected abstract Task<TUserLogin> FindUserLoginAsync(string loginProvider, string providerKey, CancellationToken cancellationToken);
|
||||
|
||||
/// <summary>
|
||||
/// Adds the given <paramref name="normalizedRoleName"/> to the specified <paramref name="user"/>.
|
||||
/// </summary>
|
||||
/// <param name="user">The user to add the role to.</param>
|
||||
/// <param name="normalizedRoleName">The role to add.</param>
|
||||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> used to propagate notifications that the operation should be canceled.</param>
|
||||
/// <returns>The <see cref="Task"/> that represents the asynchronous operation.</returns>
|
||||
public abstract Task AddToRoleAsync(TUser user, string normalizedRoleName, CancellationToken cancellationToken = default(CancellationToken));
|
||||
|
||||
/// <summary>
|
||||
/// Removes the given <paramref name="normalizedRoleName"/> from the specified <paramref name="user"/>.
|
||||
/// </summary>
|
||||
/// <param name="user">The user to remove the role from.</param>
|
||||
/// <param name="normalizedRoleName">The role to remove.</param>
|
||||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> used to propagate notifications that the operation should be canceled.</param>
|
||||
/// <returns>The <see cref="Task"/> that represents the asynchronous operation.</returns>
|
||||
public abstract Task RemoveFromRoleAsync(TUser user, string normalizedRoleName, CancellationToken cancellationToken = default(CancellationToken));
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves the roles the specified <paramref name="user"/> is a member of.
|
||||
/// </summary>
|
||||
/// <param name="user">The user whose roles should be retrieved.</param>
|
||||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> used to propagate notifications that the operation should be canceled.</param>
|
||||
/// <returns>A <see cref="Task{TResult}"/> that contains the roles the user is a member of.</returns>
|
||||
public abstract Task<IList<string>> GetRolesAsync(TUser user, CancellationToken cancellationToken = default(CancellationToken));
|
||||
|
||||
/// <summary>
|
||||
/// Returns a flag indicating if the specified user is a member of the give <paramref name="normalizedRoleName"/>.
|
||||
/// </summary>
|
||||
/// <param name="user">The user whose role membership should be checked.</param>
|
||||
/// <param name="normalizedRoleName">The role to check membership of</param>
|
||||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> used to propagate notifications that the operation should be canceled.</param>
|
||||
/// <returns>A <see cref="Task{TResult}"/> containing a flag indicating if the specified user is a member of the given group. If the
|
||||
/// user is a member of the group the returned value with be true, otherwise it will be false.</returns>
|
||||
public abstract Task<bool> IsInRoleAsync(TUser user, string normalizedRoleName, CancellationToken cancellationToken = default(CancellationToken));
|
||||
|
||||
/// <summary>
|
||||
/// Throws if this class has been disposed.
|
||||
/// </summary>
|
||||
|
|
@ -957,16 +881,6 @@ namespace Microsoft.AspNetCore.Identity
|
|||
/// </returns>
|
||||
public abstract Task<IList<TUser>> GetUsersForClaimAsync(Claim claim, CancellationToken cancellationToken = default(CancellationToken));
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves all users in the specified role.
|
||||
/// </summary>
|
||||
/// <param name="normalizedRoleName">The role whose users should be retrieved.</param>
|
||||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> used to propagate notifications that the operation should be canceled.</param>
|
||||
/// <returns>
|
||||
/// The <see cref="Task"/> contains a list of users, if any, that are in the specified role.
|
||||
/// </returns>
|
||||
public abstract Task<IList<TUser>> GetUsersInRoleAsync(string normalizedRoleName, CancellationToken cancellationToken = default(CancellationToken));
|
||||
|
||||
/// <summary>
|
||||
/// Find a user token if it exists.
|
||||
/// </summary>
|
||||
|
|
@ -1139,4 +1053,113 @@ namespace Microsoft.AspNetCore.Identity
|
|||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents a new instance of a persistence store for the specified user and role types.
|
||||
/// </summary>
|
||||
/// <typeparam name="TUser">The type representing a user.</typeparam>
|
||||
/// <typeparam name="TRole">The type representing a role.</typeparam>
|
||||
/// <typeparam name="TKey">The type of the primary key for a role.</typeparam>
|
||||
/// <typeparam name="TUserClaim">The type representing a claim.</typeparam>
|
||||
/// <typeparam name="TUserRole">The type representing a user role.</typeparam>
|
||||
/// <typeparam name="TUserLogin">The type representing a user external login.</typeparam>
|
||||
/// <typeparam name="TUserToken">The type representing a user token.</typeparam>
|
||||
/// <typeparam name="TRoleClaim">The type representing a role claim.</typeparam>
|
||||
public abstract class UserStoreBase<TUser, TRole, TKey, TUserClaim, TUserRole, TUserLogin, TUserToken, TRoleClaim> :
|
||||
UserStoreBase<TUser, TKey, TUserClaim, TUserLogin, TUserToken>,
|
||||
IUserRoleStore<TUser>
|
||||
where TUser : IdentityUser<TKey>
|
||||
where TRole : IdentityRole<TKey>
|
||||
where TKey : IEquatable<TKey>
|
||||
where TUserClaim : IdentityUserClaim<TKey>, new()
|
||||
where TUserRole : IdentityUserRole<TKey>, new()
|
||||
where TUserLogin : IdentityUserLogin<TKey>, new()
|
||||
where TUserToken : IdentityUserToken<TKey>, new()
|
||||
where TRoleClaim : IdentityRoleClaim<TKey>, new()
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates a new instance.
|
||||
/// </summary>
|
||||
/// <param name="describer">The <see cref="IdentityErrorDescriber"/> used to describe store errors.</param>
|
||||
public UserStoreBase(IdentityErrorDescriber describer) : base(describer) { }
|
||||
|
||||
/// <summary>
|
||||
/// Called to create a new instance of a <see cref="IdentityUserRole{TKey}"/>.
|
||||
/// </summary>
|
||||
/// <param name="user">The associated user.</param>
|
||||
/// <param name="role">The associated role.</param>
|
||||
/// <returns></returns>
|
||||
protected virtual TUserRole CreateUserRole(TUser user, TRole role)
|
||||
{
|
||||
return new TUserRole()
|
||||
{
|
||||
UserId = user.Id,
|
||||
RoleId = role.Id
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves all users in the specified role.
|
||||
/// </summary>
|
||||
/// <param name="normalizedRoleName">The role whose users should be retrieved.</param>
|
||||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> used to propagate notifications that the operation should be canceled.</param>
|
||||
/// <returns>
|
||||
/// The <see cref="Task"/> contains a list of users, if any, that are in the specified role.
|
||||
/// </returns>
|
||||
public abstract Task<IList<TUser>> GetUsersInRoleAsync(string normalizedRoleName, CancellationToken cancellationToken = default(CancellationToken));
|
||||
|
||||
/// <summary>
|
||||
/// Adds the given <paramref name="normalizedRoleName"/> to the specified <paramref name="user"/>.
|
||||
/// </summary>
|
||||
/// <param name="user">The user to add the role to.</param>
|
||||
/// <param name="normalizedRoleName">The role to add.</param>
|
||||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> used to propagate notifications that the operation should be canceled.</param>
|
||||
/// <returns>The <see cref="Task"/> that represents the asynchronous operation.</returns>
|
||||
public abstract Task AddToRoleAsync(TUser user, string normalizedRoleName, CancellationToken cancellationToken = default(CancellationToken));
|
||||
|
||||
/// <summary>
|
||||
/// Removes the given <paramref name="normalizedRoleName"/> from the specified <paramref name="user"/>.
|
||||
/// </summary>
|
||||
/// <param name="user">The user to remove the role from.</param>
|
||||
/// <param name="normalizedRoleName">The role to remove.</param>
|
||||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> used to propagate notifications that the operation should be canceled.</param>
|
||||
/// <returns>The <see cref="Task"/> that represents the asynchronous operation.</returns>
|
||||
public abstract Task RemoveFromRoleAsync(TUser user, string normalizedRoleName, CancellationToken cancellationToken = default(CancellationToken));
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves the roles the specified <paramref name="user"/> is a member of.
|
||||
/// </summary>
|
||||
/// <param name="user">The user whose roles should be retrieved.</param>
|
||||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> used to propagate notifications that the operation should be canceled.</param>
|
||||
/// <returns>A <see cref="Task{TResult}"/> that contains the roles the user is a member of.</returns>
|
||||
public abstract Task<IList<string>> GetRolesAsync(TUser user, CancellationToken cancellationToken = default(CancellationToken));
|
||||
|
||||
/// <summary>
|
||||
/// Returns a flag indicating if the specified user is a member of the give <paramref name="normalizedRoleName"/>.
|
||||
/// </summary>
|
||||
/// <param name="user">The user whose role membership should be checked.</param>
|
||||
/// <param name="normalizedRoleName">The role to check membership of</param>
|
||||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> used to propagate notifications that the operation should be canceled.</param>
|
||||
/// <returns>A <see cref="Task{TResult}"/> containing a flag indicating if the specified user is a member of the given group. If the
|
||||
/// user is a member of the group the returned value with be true, otherwise it will be false.</returns>
|
||||
public abstract Task<bool> IsInRoleAsync(TUser user, string normalizedRoleName, CancellationToken cancellationToken = default(CancellationToken));
|
||||
|
||||
/// <summary>
|
||||
/// Return a role with the normalized name if it exists.
|
||||
/// </summary>
|
||||
/// <param name="normalizedRoleName">The normalized role name.</param>
|
||||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> used to propagate notifications that the operation should be canceled.</param>
|
||||
/// <returns>The role if it exists.</returns>
|
||||
protected abstract Task<TRole> FindRoleAsync(string normalizedRoleName, CancellationToken cancellationToken);
|
||||
|
||||
/// <summary>
|
||||
/// Return a user role for the userId and roleId if it exists.
|
||||
/// </summary>
|
||||
/// <param name="userId">The user's id.</param>
|
||||
/// <param name="roleId">The role's id.</param>
|
||||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> used to propagate notifications that the operation should be canceled.</param>
|
||||
/// <returns>The user role if it exists.</returns>
|
||||
protected abstract Task<TUserRole> FindUserRoleAsync(TKey userId, TKey roleId, CancellationToken cancellationToken);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,11 +14,16 @@ namespace Microsoft.AspNetCore.Identity.EntityFrameworkCore.InMemory.Test
|
|||
}
|
||||
|
||||
public class InMemoryContext<TUser> :
|
||||
InMemoryContext<TUser, IdentityRole, string>
|
||||
IdentityDbContext<TUser, string>
|
||||
where TUser : IdentityUser
|
||||
{
|
||||
public InMemoryContext(DbContextOptions options) : base(options)
|
||||
{ }
|
||||
|
||||
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
|
||||
{
|
||||
optionsBuilder.UseInMemoryDatabase("ScratchUsers");
|
||||
}
|
||||
}
|
||||
|
||||
public class InMemoryContext<TUser, TRole, TKey> : IdentityDbContext<TUser, TRole, TKey>
|
||||
|
|
@ -36,8 +41,8 @@ namespace Microsoft.AspNetCore.Identity.EntityFrameworkCore.InMemory.Test
|
|||
}
|
||||
|
||||
public abstract class InMemoryContext<TUser, TRole, TKey, TUserClaim, TUserRole, TUserLogin, TRoleClaim, TUserToken> : IdentityDbContext<TUser, TRole, TKey, TUserClaim, TUserRole, TUserLogin, TRoleClaim, TUserToken>
|
||||
where TUser : IdentityUser<TKey, TUserClaim, TUserRole, TUserLogin, TUserToken>
|
||||
where TRole : IdentityRole<TKey, TUserRole, TRoleClaim>
|
||||
where TUser : IdentityUser<TKey>
|
||||
where TRole : IdentityRole<TKey>
|
||||
where TKey : IEquatable<TKey>
|
||||
where TUserClaim : IdentityUserClaim<TKey>
|
||||
where TUserRole : IdentityUserRole<TKey>
|
||||
|
|
@ -45,12 +50,9 @@ namespace Microsoft.AspNetCore.Identity.EntityFrameworkCore.InMemory.Test
|
|||
where TRoleClaim : IdentityRoleClaim<TKey>
|
||||
where TUserToken : IdentityUserToken<TKey>
|
||||
{
|
||||
public InMemoryContext(DbContextOptions options) : base(options)
|
||||
{ }
|
||||
public InMemoryContext(DbContextOptions options) : base(options) { }
|
||||
|
||||
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
|
||||
{
|
||||
optionsBuilder.UseInMemoryDatabase("Scratch");
|
||||
}
|
||||
=> optionsBuilder.UseInMemoryDatabase("Scratch");
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
// 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 System;
|
||||
using System.Linq.Expressions;
|
||||
using Microsoft.AspNetCore.Identity.Test;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
namespace Microsoft.AspNetCore.Identity.EntityFrameworkCore.InMemory.Test
|
||||
{
|
||||
public class InMemoryEFOnlyUsersTest : UserManagerSpecificationTestBase<IdentityUser, string>
|
||||
{
|
||||
protected override object CreateTestContext()
|
||||
=> new InMemoryContext<IdentityUser>(new DbContextOptionsBuilder().Options);
|
||||
|
||||
protected override void AddUserStore(IServiceCollection services, object context = null)
|
||||
=> services.AddSingleton<IUserStore<IdentityUser>>(new UserStore<IdentityUser, IdentityRole, DbContext, string, IdentityUserClaim<string>, IdentityUserRole<string>, IdentityUserLogin<string>, IdentityUserToken<string>, IdentityRoleClaim<string>>((InMemoryContext<IdentityUser>)context, new IdentityErrorDescriber()));
|
||||
|
||||
protected override IdentityUser CreateTestUser(string namePrefix = "", string email = "", string phoneNumber = "",
|
||||
bool lockoutEnabled = false, DateTimeOffset? lockoutEnd = default(DateTimeOffset?), bool useNamePrefixAsUserName = false)
|
||||
{
|
||||
return new IdentityUser
|
||||
{
|
||||
UserName = useNamePrefixAsUserName ? namePrefix : string.Format("{0}{1}", namePrefix, Guid.NewGuid()),
|
||||
Email = email,
|
||||
PhoneNumber = phoneNumber,
|
||||
LockoutEnabled = lockoutEnabled,
|
||||
LockoutEnd = lockoutEnd
|
||||
};
|
||||
}
|
||||
|
||||
protected override void SetUserPasswordHash(IdentityUser user, string hashedPassword)
|
||||
{
|
||||
user.PasswordHash = hashedPassword;
|
||||
}
|
||||
|
||||
protected override Expression<Func<IdentityUser, bool>> UserNameEqualsPredicate(string userName) => u => u.UserName == userName;
|
||||
|
||||
protected override Expression<Func<IdentityUser, bool>> UserNameStartsWithPredicate(string userName) => u => u.UserName.StartsWith(userName);
|
||||
}
|
||||
}
|
||||
|
|
@ -188,7 +188,7 @@ namespace Microsoft.AspNetCore.Identity.EntityFrameworkCore.InMemory.Test
|
|||
|
||||
#region Generic Type defintions
|
||||
|
||||
public class IdentityUserWithGenerics : IdentityUser<string, IdentityUserClaimWithIssuer, IdentityUserRoleWithDate, IdentityUserLoginWithContext, IdentityUserTokenWithStuff>
|
||||
public class IdentityUserWithGenerics : IdentityUser<string>
|
||||
{
|
||||
public IdentityUserWithGenerics()
|
||||
{
|
||||
|
|
@ -294,7 +294,7 @@ namespace Microsoft.AspNetCore.Identity.EntityFrameworkCore.InMemory.Test
|
|||
public DateTime Created { get; set; }
|
||||
}
|
||||
|
||||
public class MyIdentityRole : IdentityRole<string, IdentityUserRoleWithDate, IdentityRoleClaimWithIssuer>
|
||||
public class MyIdentityRole : IdentityRole<string>
|
||||
{
|
||||
public MyIdentityRole() : base()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -0,0 +1,290 @@
|
|||
// 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 System;
|
||||
using System.Data.SqlClient;
|
||||
using System.Linq;
|
||||
using System.Linq.Expressions;
|
||||
using System.Security.Claims;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Identity.Test;
|
||||
using Microsoft.AspNetCore.Testing;
|
||||
using Microsoft.AspNetCore.Testing.xunit;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNetCore.Identity.EntityFrameworkCore.Test
|
||||
{
|
||||
public abstract class SqlStoreOnlyUsersTestBase<TUser, TKey> : UserManagerSpecificationTestBase<TUser, TKey>, IClassFixture<ScratchDatabaseFixture>
|
||||
where TUser : IdentityUser<TKey>, new()
|
||||
where TKey : IEquatable<TKey>
|
||||
{
|
||||
private readonly ScratchDatabaseFixture _fixture;
|
||||
|
||||
protected SqlStoreOnlyUsersTestBase(ScratchDatabaseFixture fixture)
|
||||
{
|
||||
_fixture = fixture;
|
||||
}
|
||||
|
||||
protected override bool ShouldSkipDbTests()
|
||||
{
|
||||
return TestPlatformHelper.IsMono || !TestPlatformHelper.IsWindows;
|
||||
}
|
||||
|
||||
public class TestUserDbContext : IdentityDbContext<TUser, TKey>
|
||||
{
|
||||
public TestUserDbContext(DbContextOptions options) : base(options) { }
|
||||
}
|
||||
|
||||
protected override TUser CreateTestUser(string namePrefix = "", string email = "", string phoneNumber = "",
|
||||
bool lockoutEnabled = false, DateTimeOffset? lockoutEnd = default(DateTimeOffset?), bool useNamePrefixAsUserName = false)
|
||||
{
|
||||
return new TUser
|
||||
{
|
||||
UserName = useNamePrefixAsUserName ? namePrefix : string.Format("{0}{1}", namePrefix, Guid.NewGuid()),
|
||||
Email = email,
|
||||
PhoneNumber = phoneNumber,
|
||||
LockoutEnabled = lockoutEnabled,
|
||||
LockoutEnd = lockoutEnd
|
||||
};
|
||||
}
|
||||
|
||||
protected override Expression<Func<TUser, bool>> UserNameEqualsPredicate(string userName) => u => u.UserName == userName;
|
||||
|
||||
protected override Expression<Func<TUser, bool>> UserNameStartsWithPredicate(string userName) => u => u.UserName.StartsWith(userName);
|
||||
|
||||
public TestUserDbContext CreateContext()
|
||||
{
|
||||
var db = DbUtil.Create<TestUserDbContext>(_fixture.ConnectionString);
|
||||
db.Database.EnsureCreated();
|
||||
return db;
|
||||
}
|
||||
|
||||
protected override object CreateTestContext()
|
||||
{
|
||||
return CreateContext();
|
||||
}
|
||||
|
||||
protected override void AddUserStore(IServiceCollection services, object context = null)
|
||||
{
|
||||
services.AddSingleton<IUserStore<TUser>>(new UserOnlyStore<TUser, TestUserDbContext, TKey>((TestUserDbContext)context));
|
||||
}
|
||||
|
||||
protected override void SetUserPasswordHash(TUser user, string hashedPassword)
|
||||
{
|
||||
user.PasswordHash = hashedPassword;
|
||||
}
|
||||
|
||||
[ConditionalFact]
|
||||
[FrameworkSkipCondition(RuntimeFrameworks.Mono)]
|
||||
[OSSkipCondition(OperatingSystems.Linux)]
|
||||
[OSSkipCondition(OperatingSystems.MacOSX)]
|
||||
public void EnsureDefaultSchema()
|
||||
{
|
||||
VerifyDefaultSchema(CreateContext());
|
||||
}
|
||||
|
||||
internal static void VerifyDefaultSchema(TestUserDbContext dbContext)
|
||||
{
|
||||
var sqlConn = dbContext.Database.GetDbConnection();
|
||||
|
||||
using (var db = new SqlConnection(sqlConn.ConnectionString))
|
||||
{
|
||||
db.Open();
|
||||
Assert.True(VerifyColumns(db, "AspNetUsers", "Id", "UserName", "Email", "PasswordHash", "SecurityStamp",
|
||||
"EmailConfirmed", "PhoneNumber", "PhoneNumberConfirmed", "TwoFactorEnabled", "LockoutEnabled",
|
||||
"LockoutEnd", "AccessFailedCount", "ConcurrencyStamp", "NormalizedUserName", "NormalizedEmail"));
|
||||
Assert.False(VerifyColumns(db, "AspNetRoles", "Id", "Name", "NormalizedName", "ConcurrencyStamp"));
|
||||
Assert.False(VerifyColumns(db, "AspNetUserRoles", "UserId", "RoleId"));
|
||||
Assert.True(VerifyColumns(db, "AspNetUserClaims", "Id", "UserId", "ClaimType", "ClaimValue"));
|
||||
Assert.True(VerifyColumns(db, "AspNetUserLogins", "UserId", "ProviderKey", "LoginProvider", "ProviderDisplayName"));
|
||||
Assert.True(VerifyColumns(db, "AspNetUserTokens", "UserId", "LoginProvider", "Name", "Value"));
|
||||
|
||||
VerifyIndex(db, "AspNetUsers", "UserNameIndex", isUnique: true);
|
||||
VerifyIndex(db, "AspNetUsers", "EmailIndex");
|
||||
db.Close();
|
||||
}
|
||||
}
|
||||
|
||||
internal static bool VerifyColumns(SqlConnection conn, string table, params string[] columns)
|
||||
{
|
||||
var count = 0;
|
||||
using (
|
||||
var command =
|
||||
new SqlCommand("SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS where TABLE_NAME=@Table", conn))
|
||||
{
|
||||
command.Parameters.Add(new SqlParameter("Table", table));
|
||||
using (var reader = command.ExecuteReader())
|
||||
{
|
||||
while (reader.Read())
|
||||
{
|
||||
count++;
|
||||
if (!columns.Contains(reader.GetString(0)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return count == columns.Length;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal static void VerifyIndex(SqlConnection conn, string table, string index, bool isUnique = false)
|
||||
{
|
||||
using (
|
||||
var command =
|
||||
new SqlCommand(
|
||||
"SELECT COUNT(*) FROM sys.indexes where NAME=@Index AND object_id = OBJECT_ID(@Table) AND is_unique = @Unique", conn))
|
||||
{
|
||||
command.Parameters.Add(new SqlParameter("Index", index));
|
||||
command.Parameters.Add(new SqlParameter("Table", table));
|
||||
command.Parameters.Add(new SqlParameter("Unique", isUnique));
|
||||
using (var reader = command.ExecuteReader())
|
||||
{
|
||||
Assert.True(reader.Read());
|
||||
Assert.True(reader.GetInt32(0) > 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[ConditionalFact]
|
||||
[FrameworkSkipCondition(RuntimeFrameworks.Mono)]
|
||||
[OSSkipCondition(OperatingSystems.Linux)]
|
||||
[OSSkipCondition(OperatingSystems.MacOSX)]
|
||||
public async Task DeleteUserRemovesTokensTest()
|
||||
{
|
||||
// Need fail if not empty?
|
||||
var userMgr = CreateManager();
|
||||
var user = CreateTestUser();
|
||||
IdentityResultAssert.IsSuccess(await userMgr.CreateAsync(user));
|
||||
IdentityResultAssert.IsSuccess(await userMgr.SetAuthenticationTokenAsync(user, "provider", "test", "value"));
|
||||
|
||||
Assert.Equal("value", await userMgr.GetAuthenticationTokenAsync(user, "provider", "test"));
|
||||
|
||||
IdentityResultAssert.IsSuccess(await userMgr.DeleteAsync(user));
|
||||
|
||||
Assert.Null(await userMgr.GetAuthenticationTokenAsync(user, "provider", "test"));
|
||||
}
|
||||
|
||||
|
||||
[ConditionalFact]
|
||||
[FrameworkSkipCondition(RuntimeFrameworks.Mono)]
|
||||
[OSSkipCondition(OperatingSystems.Linux)]
|
||||
[OSSkipCondition(OperatingSystems.MacOSX)]
|
||||
public void CanCreateUserUsingEF()
|
||||
{
|
||||
using (var db = CreateContext())
|
||||
{
|
||||
var user = CreateTestUser();
|
||||
db.Users.Add(user);
|
||||
db.SaveChanges();
|
||||
Assert.True(db.Users.Any(u => u.UserName == user.UserName));
|
||||
Assert.NotNull(db.Users.FirstOrDefault(u => u.UserName == user.UserName));
|
||||
}
|
||||
}
|
||||
|
||||
[ConditionalFact]
|
||||
[FrameworkSkipCondition(RuntimeFrameworks.Mono)]
|
||||
[OSSkipCondition(OperatingSystems.Linux)]
|
||||
[OSSkipCondition(OperatingSystems.MacOSX)]
|
||||
public async Task CanCreateUsingManager()
|
||||
{
|
||||
var manager = CreateManager();
|
||||
var user = CreateTestUser();
|
||||
IdentityResultAssert.IsSuccess(await manager.CreateAsync(user));
|
||||
IdentityResultAssert.IsSuccess(await manager.DeleteAsync(user));
|
||||
}
|
||||
|
||||
private async Task LazyLoadTestSetup(TestUserDbContext db, TUser user)
|
||||
{
|
||||
var context = CreateContext();
|
||||
var manager = CreateManager(context);
|
||||
IdentityResultAssert.IsSuccess(await manager.CreateAsync(user));
|
||||
IdentityResultAssert.IsSuccess(await manager.AddLoginAsync(user, new UserLoginInfo("provider", user.Id.ToString(), "display")));
|
||||
Claim[] userClaims =
|
||||
{
|
||||
new Claim("Whatever", "Value"),
|
||||
new Claim("Whatever2", "Value2")
|
||||
};
|
||||
foreach (var c in userClaims)
|
||||
{
|
||||
IdentityResultAssert.IsSuccess(await manager.AddClaimAsync(user, c));
|
||||
}
|
||||
}
|
||||
|
||||
[ConditionalFact]
|
||||
[FrameworkSkipCondition(RuntimeFrameworks.Mono)]
|
||||
[OSSkipCondition(OperatingSystems.Linux)]
|
||||
[OSSkipCondition(OperatingSystems.MacOSX)]
|
||||
public async Task LoadFromDbFindByIdTest()
|
||||
{
|
||||
var db = CreateContext();
|
||||
var user = CreateTestUser();
|
||||
await LazyLoadTestSetup(db, user);
|
||||
|
||||
db = CreateContext();
|
||||
var manager = CreateManager(db);
|
||||
|
||||
var userById = await manager.FindByIdAsync(user.Id.ToString());
|
||||
Assert.Equal(2, (await manager.GetClaimsAsync(userById)).Count);
|
||||
Assert.Equal(1, (await manager.GetLoginsAsync(userById)).Count);
|
||||
Assert.Equal(2, (await manager.GetRolesAsync(userById)).Count);
|
||||
}
|
||||
|
||||
[ConditionalFact]
|
||||
[FrameworkSkipCondition(RuntimeFrameworks.Mono)]
|
||||
[OSSkipCondition(OperatingSystems.Linux)]
|
||||
[OSSkipCondition(OperatingSystems.MacOSX)]
|
||||
public async Task LoadFromDbFindByNameTest()
|
||||
{
|
||||
var db = CreateContext();
|
||||
var user = CreateTestUser();
|
||||
await LazyLoadTestSetup(db, user);
|
||||
|
||||
db = CreateContext();
|
||||
var manager = CreateManager(db);
|
||||
var userByName = await manager.FindByNameAsync(user.UserName);
|
||||
Assert.Equal(2, (await manager.GetClaimsAsync(userByName)).Count);
|
||||
Assert.Equal(1, (await manager.GetLoginsAsync(userByName)).Count);
|
||||
Assert.Equal(2, (await manager.GetRolesAsync(userByName)).Count);
|
||||
}
|
||||
|
||||
[ConditionalFact]
|
||||
[FrameworkSkipCondition(RuntimeFrameworks.Mono)]
|
||||
[OSSkipCondition(OperatingSystems.Linux)]
|
||||
[OSSkipCondition(OperatingSystems.MacOSX)]
|
||||
public async Task LoadFromDbFindByLoginTest()
|
||||
{
|
||||
var db = CreateContext();
|
||||
var user = CreateTestUser();
|
||||
await LazyLoadTestSetup(db, user);
|
||||
|
||||
db = CreateContext();
|
||||
var manager = CreateManager(db);
|
||||
var userByLogin = await manager.FindByLoginAsync("provider", user.Id.ToString());
|
||||
Assert.Equal(2, (await manager.GetClaimsAsync(userByLogin)).Count);
|
||||
Assert.Equal(1, (await manager.GetLoginsAsync(userByLogin)).Count);
|
||||
Assert.Equal(2, (await manager.GetRolesAsync(userByLogin)).Count);
|
||||
}
|
||||
|
||||
[ConditionalFact]
|
||||
[FrameworkSkipCondition(RuntimeFrameworks.Mono)]
|
||||
[OSSkipCondition(OperatingSystems.Linux)]
|
||||
[OSSkipCondition(OperatingSystems.MacOSX)]
|
||||
public async Task LoadFromDbFindByEmailTest()
|
||||
{
|
||||
var db = CreateContext();
|
||||
var user = CreateTestUser();
|
||||
user.Email = "fooz@fizzy.pop";
|
||||
await LazyLoadTestSetup(db, user);
|
||||
|
||||
db = CreateContext();
|
||||
var manager = CreateManager(db);
|
||||
var userByEmail = await manager.FindByEmailAsync(user.Email);
|
||||
Assert.Equal(2, (await manager.GetClaimsAsync(userByEmail)).Count);
|
||||
Assert.Equal(1, (await manager.GetLoginsAsync(userByEmail)).Count);
|
||||
Assert.Equal(2, (await manager.GetRolesAsync(userByEmail)).Count);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -7,15 +7,19 @@ using System.Linq;
|
|||
using System.Linq.Expressions;
|
||||
using System.Security.Claims;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Identity.Test;
|
||||
using Microsoft.AspNetCore.Testing;
|
||||
using Microsoft.AspNetCore.Testing.xunit;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNetCore.Identity.EntityFrameworkCore.Test
|
||||
{
|
||||
// TODO: Add test variation with non IdentityDbContext
|
||||
|
||||
public abstract class SqlStoreTestBase<TUser, TRole, TKey> : IdentitySpecificationTestBase<TUser, TRole, TKey>, IClassFixture<ScratchDatabaseFixture>
|
||||
where TUser : IdentityUser<TKey>, new()
|
||||
where TRole : IdentityRole<TKey>, new()
|
||||
|
|
@ -28,6 +32,25 @@ namespace Microsoft.AspNetCore.Identity.EntityFrameworkCore.Test
|
|||
_fixture = fixture;
|
||||
}
|
||||
|
||||
protected override void SetupIdentityServices(IServiceCollection services, object context)
|
||||
{
|
||||
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
|
||||
services.AddSingleton<TestDbContext>((TestDbContext)context);
|
||||
services.AddLogging();
|
||||
services.AddSingleton<ILogger<UserManager<TUser>>>(new TestLogger<UserManager<TUser>>());
|
||||
services.AddSingleton<ILogger<RoleManager<TRole>>>(new TestLogger<RoleManager<TRole>>());
|
||||
services.AddIdentity<TUser, TRole>(options =>
|
||||
{
|
||||
options.Password.RequireDigit = false;
|
||||
options.Password.RequireLowercase = false;
|
||||
options.Password.RequireNonAlphanumeric = false;
|
||||
options.Password.RequireUppercase = false;
|
||||
options.User.AllowedUserNameCharacters = null;
|
||||
})
|
||||
.AddDefaultTokenProviders()
|
||||
.AddEntityFrameworkStores<TestDbContext>();
|
||||
}
|
||||
|
||||
protected override bool ShouldSkipDbTests()
|
||||
{
|
||||
return TestPlatformHelper.IsMono || !TestPlatformHelper.IsWindows;
|
||||
|
|
@ -363,6 +386,5 @@ namespace Microsoft.AspNetCore.Identity.EntityFrameworkCore.Test
|
|||
Assert.Equal(1, (await manager.GetLoginsAsync(userByEmail)).Count);
|
||||
Assert.Equal(2, (await manager.GetRolesAsync(userByEmail)).Count);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -101,15 +101,6 @@ namespace Microsoft.AspNetCore.Identity.EntityFrameworkCore.Test
|
|||
Assert.Contains("AddEntityFrameworkStores", e.Message);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void AddEntityFrameworkStoresWithMismatchedUserRoleThrows()
|
||||
{
|
||||
var services = new ServiceCollection();
|
||||
var builder = services.AddIdentity<IdentityUserWithGenerics, IdentityRole>();
|
||||
var e = Assert.Throws<ArgumentException>(() => builder.AddEntityFrameworkStores<ContextWithGenerics>());
|
||||
Assert.Contains("violates the constraint of type 'TRole'", e.Message);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task CanAddRemoveUserClaimWithIssuer()
|
||||
{
|
||||
|
|
@ -218,7 +209,7 @@ namespace Microsoft.AspNetCore.Identity.EntityFrameworkCore.Test
|
|||
|
||||
#region Generic Type defintions
|
||||
|
||||
public class IdentityUserWithGenerics : IdentityUser<string, IdentityUserClaimWithIssuer, IdentityUserRoleWithDate, IdentityUserLoginWithContext, IdentityUserTokenWithStuff>
|
||||
public class IdentityUserWithGenerics : IdentityUser<string>
|
||||
{
|
||||
public IdentityUserWithGenerics()
|
||||
{
|
||||
|
|
@ -328,7 +319,7 @@ namespace Microsoft.AspNetCore.Identity.EntityFrameworkCore.Test
|
|||
public DateTime Created { get; set; }
|
||||
}
|
||||
|
||||
public class MyIdentityRole : IdentityRole<string, IdentityUserRoleWithDate, IdentityRoleClaimWithIssuer>
|
||||
public class MyIdentityRole : IdentityRole<string>
|
||||
{
|
||||
public MyIdentityRole() : base()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -12,302 +12,13 @@ using Microsoft.AspNetCore.Identity.Test;
|
|||
namespace Microsoft.AspNetCore.Identity.InMemory
|
||||
{
|
||||
public class InMemoryStore<TUser, TRole> :
|
||||
IUserLoginStore<TUser>,
|
||||
InMemoryUserStore<TUser>,
|
||||
IUserRoleStore<TUser>,
|
||||
IUserClaimStore<TUser>,
|
||||
IUserPasswordStore<TUser>,
|
||||
IUserSecurityStampStore<TUser>,
|
||||
IUserEmailStore<TUser>,
|
||||
IUserLockoutStore<TUser>,
|
||||
IUserPhoneNumberStore<TUser>,
|
||||
IQueryableUserStore<TUser>,
|
||||
IUserTwoFactorStore<TUser>,
|
||||
IQueryableRoleStore<TRole>,
|
||||
IRoleClaimStore<TRole>,
|
||||
IUserAuthenticationTokenStore<TUser>,
|
||||
IUserAuthenticatorKeyStore<TUser>,
|
||||
IUserTwoFactorRecoveryCodeStore<TUser>
|
||||
IRoleClaimStore<TRole>
|
||||
where TRole : TestRole
|
||||
where TUser : TestUser
|
||||
{
|
||||
private readonly Dictionary<string, TUser> _logins = new Dictionary<string, TUser>();
|
||||
|
||||
private readonly Dictionary<string, TUser> _users = new Dictionary<string, TUser>();
|
||||
|
||||
public IQueryable<TUser> Users
|
||||
{
|
||||
get { return _users.Values.AsQueryable(); }
|
||||
}
|
||||
|
||||
public Task<IList<Claim>> GetClaimsAsync(TUser user, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
var claims = user.Claims.Select(c => new Claim(c.ClaimType, c.ClaimValue)).ToList();
|
||||
return Task.FromResult<IList<Claim>>(claims);
|
||||
}
|
||||
|
||||
public Task AddClaimsAsync(TUser user, IEnumerable<Claim> claims, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
foreach (var claim in claims)
|
||||
{
|
||||
user.Claims.Add(new TestUserClaim { ClaimType = claim.Type, ClaimValue = claim.Value, UserId = user.Id });
|
||||
}
|
||||
return Task.FromResult(0);
|
||||
}
|
||||
|
||||
public Task ReplaceClaimAsync(TUser user, Claim claim, Claim newClaim, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
var matchedClaims = user.Claims.Where(uc => uc.ClaimValue == claim.Value && uc.ClaimType == claim.Type).ToList();
|
||||
foreach (var matchedClaim in matchedClaims)
|
||||
{
|
||||
matchedClaim.ClaimValue = newClaim.Value;
|
||||
matchedClaim.ClaimType = newClaim.Type;
|
||||
}
|
||||
return Task.FromResult(0);
|
||||
}
|
||||
|
||||
public Task RemoveClaimsAsync(TUser user, IEnumerable<Claim> claims, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
foreach (var claim in claims)
|
||||
{
|
||||
var entity =
|
||||
user.Claims.FirstOrDefault(
|
||||
uc => uc.UserId == user.Id && uc.ClaimType == claim.Type && uc.ClaimValue == claim.Value);
|
||||
if (entity != null)
|
||||
{
|
||||
user.Claims.Remove(entity);
|
||||
}
|
||||
}
|
||||
return Task.FromResult(0);
|
||||
}
|
||||
|
||||
public Task SetEmailAsync(TUser user, string email, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
user.Email = email;
|
||||
return Task.FromResult(0);
|
||||
}
|
||||
|
||||
public Task<string> GetEmailAsync(TUser user, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
return Task.FromResult(user.Email);
|
||||
}
|
||||
|
||||
public Task<string> GetNormalizedEmailAsync(TUser user, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
return Task.FromResult(user.NormalizedEmail);
|
||||
}
|
||||
|
||||
public Task SetNormalizedEmailAsync(TUser user, string normalizedEmail, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
user.NormalizedEmail = normalizedEmail;
|
||||
return Task.FromResult(0);
|
||||
}
|
||||
|
||||
|
||||
public Task<bool> GetEmailConfirmedAsync(TUser user, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
return Task.FromResult(user.EmailConfirmed);
|
||||
}
|
||||
|
||||
public Task SetEmailConfirmedAsync(TUser user, bool confirmed, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
user.EmailConfirmed = confirmed;
|
||||
return Task.FromResult(0);
|
||||
}
|
||||
|
||||
public Task<TUser> FindByEmailAsync(string email, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
return
|
||||
Task.FromResult(
|
||||
Users.FirstOrDefault(u => u.NormalizedEmail == email));
|
||||
}
|
||||
|
||||
public Task<DateTimeOffset?> GetLockoutEndDateAsync(TUser user, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
return Task.FromResult(user.LockoutEnd);
|
||||
}
|
||||
|
||||
public Task SetLockoutEndDateAsync(TUser user, DateTimeOffset? lockoutEnd, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
user.LockoutEnd = lockoutEnd;
|
||||
return Task.FromResult(0);
|
||||
}
|
||||
|
||||
public Task<int> IncrementAccessFailedCountAsync(TUser user, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
user.AccessFailedCount++;
|
||||
return Task.FromResult(user.AccessFailedCount);
|
||||
}
|
||||
|
||||
public Task ResetAccessFailedCountAsync(TUser user, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
user.AccessFailedCount = 0;
|
||||
return Task.FromResult(0);
|
||||
}
|
||||
|
||||
public Task<int> GetAccessFailedCountAsync(TUser user, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
return Task.FromResult(user.AccessFailedCount);
|
||||
}
|
||||
|
||||
public Task<bool> GetLockoutEnabledAsync(TUser user, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
return Task.FromResult(user.LockoutEnabled);
|
||||
}
|
||||
|
||||
public Task SetLockoutEnabledAsync(TUser user, bool enabled, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
user.LockoutEnabled = enabled;
|
||||
return Task.FromResult(0);
|
||||
}
|
||||
|
||||
private string GetLoginKey(string loginProvider, string providerKey)
|
||||
{
|
||||
return loginProvider + "|" + providerKey;
|
||||
}
|
||||
|
||||
public virtual Task AddLoginAsync(TUser user, UserLoginInfo login,
|
||||
CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
user.Logins.Add(new TestUserLogin
|
||||
{
|
||||
UserId = user.Id,
|
||||
ProviderKey = login.ProviderKey,
|
||||
LoginProvider = login.LoginProvider,
|
||||
ProviderDisplayName = login.ProviderDisplayName
|
||||
});
|
||||
_logins[GetLoginKey(login.LoginProvider, login.ProviderKey)] = user;
|
||||
return Task.FromResult(0);
|
||||
}
|
||||
|
||||
public Task RemoveLoginAsync(TUser user, string loginProvider, string providerKey,
|
||||
CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
var loginEntity =
|
||||
user.Logins.SingleOrDefault(
|
||||
l =>
|
||||
l.ProviderKey == providerKey && l.LoginProvider == loginProvider &&
|
||||
l.UserId == user.Id);
|
||||
if (loginEntity != null)
|
||||
{
|
||||
user.Logins.Remove(loginEntity);
|
||||
}
|
||||
_logins[GetLoginKey(loginProvider, providerKey)] = null;
|
||||
return Task.FromResult(0);
|
||||
}
|
||||
|
||||
public Task<IList<UserLoginInfo>> GetLoginsAsync(TUser user, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
IList<UserLoginInfo> result = user.Logins
|
||||
.Select(l => new UserLoginInfo(l.LoginProvider, l.ProviderKey, l.ProviderDisplayName)).ToList();
|
||||
return Task.FromResult(result);
|
||||
}
|
||||
|
||||
public Task<TUser> FindByLoginAsync(string loginProvider, string providerKey, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
string key = GetLoginKey(loginProvider, providerKey);
|
||||
if (_logins.ContainsKey(key))
|
||||
{
|
||||
return Task.FromResult(_logins[key]);
|
||||
}
|
||||
return Task.FromResult<TUser>(null);
|
||||
}
|
||||
|
||||
public Task<string> GetUserIdAsync(TUser user, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
return Task.FromResult(user.Id);
|
||||
}
|
||||
|
||||
public Task<string> GetUserNameAsync(TUser user, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
return Task.FromResult(user.UserName);
|
||||
}
|
||||
|
||||
public Task SetUserNameAsync(TUser user, string userName, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
user.UserName = userName;
|
||||
return Task.FromResult(0);
|
||||
}
|
||||
|
||||
public Task<IdentityResult> CreateAsync(TUser user, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
_users[user.Id] = user;
|
||||
return Task.FromResult(IdentityResult.Success);
|
||||
}
|
||||
|
||||
public Task<IdentityResult> UpdateAsync(TUser user, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
_users[user.Id] = user;
|
||||
return Task.FromResult(IdentityResult.Success);
|
||||
}
|
||||
|
||||
public Task<TUser> FindByIdAsync(string userId, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
if (_users.ContainsKey(userId))
|
||||
{
|
||||
return Task.FromResult(_users[userId]);
|
||||
}
|
||||
return Task.FromResult<TUser>(null);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
}
|
||||
|
||||
public Task<TUser> FindByNameAsync(string userName, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
return
|
||||
Task.FromResult(
|
||||
Users.FirstOrDefault(u => u.NormalizedUserName == userName));
|
||||
}
|
||||
|
||||
public Task<IdentityResult> DeleteAsync(TUser user, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
if (user == null || !_users.ContainsKey(user.Id))
|
||||
{
|
||||
throw new InvalidOperationException("Unknown user");
|
||||
}
|
||||
_users.Remove(user.Id);
|
||||
return Task.FromResult(IdentityResult.Success);
|
||||
}
|
||||
|
||||
public Task SetPasswordHashAsync(TUser user, string passwordHash, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
user.PasswordHash = passwordHash;
|
||||
return Task.FromResult(0);
|
||||
}
|
||||
|
||||
public Task<string> GetPasswordHashAsync(TUser user, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
return Task.FromResult(user.PasswordHash);
|
||||
}
|
||||
|
||||
public Task<bool> HasPasswordAsync(TUser user, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
return Task.FromResult(user.PasswordHash != null);
|
||||
}
|
||||
|
||||
public Task SetPhoneNumberAsync(TUser user, string phoneNumber, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
user.PhoneNumber = phoneNumber;
|
||||
return Task.FromResult(0);
|
||||
}
|
||||
|
||||
public Task<string> GetPhoneNumberAsync(TUser user, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
return Task.FromResult(user.PhoneNumber);
|
||||
}
|
||||
|
||||
public Task<bool> GetPhoneNumberConfirmedAsync(TUser user, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
return Task.FromResult(user.PhoneNumberConfirmed);
|
||||
}
|
||||
|
||||
public Task SetPhoneNumberConfirmedAsync(TUser user, bool confirmed, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
user.PhoneNumberConfirmed = confirmed;
|
||||
return Task.FromResult(0);
|
||||
}
|
||||
|
||||
// RoleId == roleName for InMemory
|
||||
public Task AddToRoleAsync(TUser user, string role, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
|
|
@ -348,39 +59,6 @@ namespace Microsoft.AspNetCore.Identity.InMemory
|
|||
return Task.FromResult(result);
|
||||
}
|
||||
|
||||
public Task SetSecurityStampAsync(TUser user, string stamp, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
user.SecurityStamp = stamp;
|
||||
return Task.FromResult(0);
|
||||
}
|
||||
|
||||
public Task<string> GetSecurityStampAsync(TUser user, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
return Task.FromResult(user.SecurityStamp);
|
||||
}
|
||||
|
||||
public Task SetTwoFactorEnabledAsync(TUser user, bool enabled, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
user.TwoFactorEnabled = enabled;
|
||||
return Task.FromResult(0);
|
||||
}
|
||||
|
||||
public Task<bool> GetTwoFactorEnabledAsync(TUser user, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
return Task.FromResult(user.TwoFactorEnabled);
|
||||
}
|
||||
|
||||
public Task<string> GetNormalizedUserNameAsync(TUser user, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
return Task.FromResult(user.NormalizedUserName);
|
||||
}
|
||||
|
||||
public Task SetNormalizedUserNameAsync(TUser user, string userName, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
user.NormalizedUserName = userName;
|
||||
return Task.FromResult(0);
|
||||
}
|
||||
|
||||
// RoleId == rolename for inmemory store tests
|
||||
public Task<IList<TUser>> GetUsersInRoleAsync(string roleName, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
|
|
@ -397,20 +75,6 @@ namespace Microsoft.AspNetCore.Identity.InMemory
|
|||
return Task.FromResult<IList<TUser>>(Users.Where(u => (u.Roles.Where(x => x.RoleId == role.Id).Count() > 0)).Select(x => x).ToList());
|
||||
}
|
||||
|
||||
public Task<IList<TUser>> GetUsersForClaimAsync(Claim claim, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
if (claim == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(claim));
|
||||
}
|
||||
|
||||
var query = from user in Users
|
||||
where user.Claims.Where(x => x.ClaimType == claim.Type && x.ClaimValue == claim.Value).FirstOrDefault() != null
|
||||
select user;
|
||||
|
||||
return Task.FromResult<IList<TUser>>(query.ToList());
|
||||
}
|
||||
|
||||
private readonly Dictionary<string, TRole> _roles = new Dictionary<string, TRole>();
|
||||
|
||||
public Task<IdentityResult> CreateAsync(TRole role, CancellationToken cancellationToken = default(CancellationToken))
|
||||
|
|
@ -502,87 +166,6 @@ namespace Microsoft.AspNetCore.Identity.InMemory
|
|||
return Task.FromResult(0);
|
||||
}
|
||||
|
||||
public Task SetTokenAsync(TUser user, string loginProvider, string name, string value, CancellationToken cancellationToken)
|
||||
{
|
||||
var tokenEntity =
|
||||
user.Tokens.SingleOrDefault(
|
||||
l =>
|
||||
l.TokenName == name && l.LoginProvider == loginProvider &&
|
||||
l.UserId == user.Id);
|
||||
if (tokenEntity != null)
|
||||
{
|
||||
tokenEntity.TokenValue = value;
|
||||
}
|
||||
else
|
||||
{
|
||||
user.Tokens.Add(new TestUserToken
|
||||
{
|
||||
UserId = user.Id,
|
||||
LoginProvider = loginProvider,
|
||||
TokenName = name,
|
||||
TokenValue = value
|
||||
});
|
||||
}
|
||||
return Task.FromResult(0);
|
||||
}
|
||||
|
||||
public Task RemoveTokenAsync(TUser user, string loginProvider, string name, CancellationToken cancellationToken)
|
||||
{
|
||||
var tokenEntity =
|
||||
user.Tokens.SingleOrDefault(
|
||||
l =>
|
||||
l.TokenName == name && l.LoginProvider == loginProvider &&
|
||||
l.UserId == user.Id);
|
||||
if (tokenEntity != null)
|
||||
{
|
||||
user.Tokens.Remove(tokenEntity);
|
||||
}
|
||||
return Task.FromResult(0);
|
||||
}
|
||||
|
||||
public Task<string> GetTokenAsync(TUser user, string loginProvider, string name, CancellationToken cancellationToken)
|
||||
{
|
||||
var tokenEntity =
|
||||
user.Tokens.SingleOrDefault(
|
||||
l =>
|
||||
l.TokenName == name && l.LoginProvider == loginProvider &&
|
||||
l.UserId == user.Id);
|
||||
return Task.FromResult(tokenEntity?.TokenValue);
|
||||
}
|
||||
|
||||
private const string AuthenticatorStoreLoginProvider = "[AspNetAuthenticatorStore]";
|
||||
private const string AuthenticatorKeyTokenName = "AuthenticatorKey";
|
||||
private const string RecoveryCodeTokenName = "RecoveryCodes";
|
||||
|
||||
public Task SetAuthenticatorKeyAsync(TUser user, string key, CancellationToken cancellationToken)
|
||||
{
|
||||
return SetTokenAsync(user, AuthenticatorStoreLoginProvider, AuthenticatorKeyTokenName, key, cancellationToken);
|
||||
}
|
||||
|
||||
public Task<string> GetAuthenticatorKeyAsync(TUser user, CancellationToken cancellationToken)
|
||||
{
|
||||
return GetTokenAsync(user, AuthenticatorStoreLoginProvider, AuthenticatorKeyTokenName, cancellationToken);
|
||||
}
|
||||
|
||||
public Task ReplaceCodesAsync(TUser user, IEnumerable<string> recoveryCodes, CancellationToken cancellationToken)
|
||||
{
|
||||
var mergedCodes = string.Join(";", recoveryCodes);
|
||||
return SetTokenAsync(user, AuthenticatorStoreLoginProvider, RecoveryCodeTokenName, mergedCodes, cancellationToken);
|
||||
}
|
||||
|
||||
public async Task<bool> RedeemCodeAsync(TUser user, string code, CancellationToken cancellationToken)
|
||||
{
|
||||
var mergedCodes = await GetTokenAsync(user, AuthenticatorStoreLoginProvider, RecoveryCodeTokenName, cancellationToken) ?? "";
|
||||
var splitCodes = mergedCodes.Split(';');
|
||||
if (splitCodes.Contains(code))
|
||||
{
|
||||
var updatedCodes = new List<string>(splitCodes.Where(s => s != code));
|
||||
await ReplaceCodesAsync(user, updatedCodes, cancellationToken);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public IQueryable<TRole> Roles
|
||||
{
|
||||
get { return _roles.Values.AsQueryable(); }
|
||||
|
|
|
|||
|
|
@ -0,0 +1,435 @@
|
|||
// 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 System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Security.Claims;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Identity.Test;
|
||||
|
||||
namespace Microsoft.AspNetCore.Identity.InMemory
|
||||
{
|
||||
public class InMemoryUserStore<TUser> :
|
||||
IUserLoginStore<TUser>,
|
||||
IUserClaimStore<TUser>,
|
||||
IUserPasswordStore<TUser>,
|
||||
IUserSecurityStampStore<TUser>,
|
||||
IUserEmailStore<TUser>,
|
||||
IUserLockoutStore<TUser>,
|
||||
IUserPhoneNumberStore<TUser>,
|
||||
IQueryableUserStore<TUser>,
|
||||
IUserTwoFactorStore<TUser>,
|
||||
IUserAuthenticationTokenStore<TUser>,
|
||||
IUserAuthenticatorKeyStore<TUser>,
|
||||
IUserTwoFactorRecoveryCodeStore<TUser>
|
||||
where TUser : TestUser
|
||||
{
|
||||
private readonly Dictionary<string, TUser> _logins = new Dictionary<string, TUser>();
|
||||
|
||||
private readonly Dictionary<string, TUser> _users = new Dictionary<string, TUser>();
|
||||
|
||||
public IQueryable<TUser> Users
|
||||
{
|
||||
get { return _users.Values.AsQueryable(); }
|
||||
}
|
||||
|
||||
public Task<IList<Claim>> GetClaimsAsync(TUser user, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
var claims = user.Claims.Select(c => new Claim(c.ClaimType, c.ClaimValue)).ToList();
|
||||
return Task.FromResult<IList<Claim>>(claims);
|
||||
}
|
||||
|
||||
public Task AddClaimsAsync(TUser user, IEnumerable<Claim> claims, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
foreach (var claim in claims)
|
||||
{
|
||||
user.Claims.Add(new TestUserClaim { ClaimType = claim.Type, ClaimValue = claim.Value, UserId = user.Id });
|
||||
}
|
||||
return Task.FromResult(0);
|
||||
}
|
||||
|
||||
public Task ReplaceClaimAsync(TUser user, Claim claim, Claim newClaim, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
var matchedClaims = user.Claims.Where(uc => uc.ClaimValue == claim.Value && uc.ClaimType == claim.Type).ToList();
|
||||
foreach (var matchedClaim in matchedClaims)
|
||||
{
|
||||
matchedClaim.ClaimValue = newClaim.Value;
|
||||
matchedClaim.ClaimType = newClaim.Type;
|
||||
}
|
||||
return Task.FromResult(0);
|
||||
}
|
||||
|
||||
public Task RemoveClaimsAsync(TUser user, IEnumerable<Claim> claims, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
foreach (var claim in claims)
|
||||
{
|
||||
var entity =
|
||||
user.Claims.FirstOrDefault(
|
||||
uc => uc.UserId == user.Id && uc.ClaimType == claim.Type && uc.ClaimValue == claim.Value);
|
||||
if (entity != null)
|
||||
{
|
||||
user.Claims.Remove(entity);
|
||||
}
|
||||
}
|
||||
return Task.FromResult(0);
|
||||
}
|
||||
|
||||
public Task SetEmailAsync(TUser user, string email, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
user.Email = email;
|
||||
return Task.FromResult(0);
|
||||
}
|
||||
|
||||
public Task<string> GetEmailAsync(TUser user, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
return Task.FromResult(user.Email);
|
||||
}
|
||||
|
||||
public Task<string> GetNormalizedEmailAsync(TUser user, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
return Task.FromResult(user.NormalizedEmail);
|
||||
}
|
||||
|
||||
public Task SetNormalizedEmailAsync(TUser user, string normalizedEmail, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
user.NormalizedEmail = normalizedEmail;
|
||||
return Task.FromResult(0);
|
||||
}
|
||||
|
||||
|
||||
public Task<bool> GetEmailConfirmedAsync(TUser user, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
return Task.FromResult(user.EmailConfirmed);
|
||||
}
|
||||
|
||||
public Task SetEmailConfirmedAsync(TUser user, bool confirmed, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
user.EmailConfirmed = confirmed;
|
||||
return Task.FromResult(0);
|
||||
}
|
||||
|
||||
public Task<TUser> FindByEmailAsync(string email, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
return
|
||||
Task.FromResult(
|
||||
Users.FirstOrDefault(u => u.NormalizedEmail == email));
|
||||
}
|
||||
|
||||
public Task<DateTimeOffset?> GetLockoutEndDateAsync(TUser user, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
return Task.FromResult(user.LockoutEnd);
|
||||
}
|
||||
|
||||
public Task SetLockoutEndDateAsync(TUser user, DateTimeOffset? lockoutEnd, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
user.LockoutEnd = lockoutEnd;
|
||||
return Task.FromResult(0);
|
||||
}
|
||||
|
||||
public Task<int> IncrementAccessFailedCountAsync(TUser user, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
user.AccessFailedCount++;
|
||||
return Task.FromResult(user.AccessFailedCount);
|
||||
}
|
||||
|
||||
public Task ResetAccessFailedCountAsync(TUser user, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
user.AccessFailedCount = 0;
|
||||
return Task.FromResult(0);
|
||||
}
|
||||
|
||||
public Task<int> GetAccessFailedCountAsync(TUser user, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
return Task.FromResult(user.AccessFailedCount);
|
||||
}
|
||||
|
||||
public Task<bool> GetLockoutEnabledAsync(TUser user, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
return Task.FromResult(user.LockoutEnabled);
|
||||
}
|
||||
|
||||
public Task SetLockoutEnabledAsync(TUser user, bool enabled, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
user.LockoutEnabled = enabled;
|
||||
return Task.FromResult(0);
|
||||
}
|
||||
|
||||
private string GetLoginKey(string loginProvider, string providerKey)
|
||||
{
|
||||
return loginProvider + "|" + providerKey;
|
||||
}
|
||||
|
||||
public virtual Task AddLoginAsync(TUser user, UserLoginInfo login,
|
||||
CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
user.Logins.Add(new TestUserLogin
|
||||
{
|
||||
UserId = user.Id,
|
||||
ProviderKey = login.ProviderKey,
|
||||
LoginProvider = login.LoginProvider,
|
||||
ProviderDisplayName = login.ProviderDisplayName
|
||||
});
|
||||
_logins[GetLoginKey(login.LoginProvider, login.ProviderKey)] = user;
|
||||
return Task.FromResult(0);
|
||||
}
|
||||
|
||||
public Task RemoveLoginAsync(TUser user, string loginProvider, string providerKey,
|
||||
CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
var loginEntity =
|
||||
user.Logins.SingleOrDefault(
|
||||
l =>
|
||||
l.ProviderKey == providerKey && l.LoginProvider == loginProvider &&
|
||||
l.UserId == user.Id);
|
||||
if (loginEntity != null)
|
||||
{
|
||||
user.Logins.Remove(loginEntity);
|
||||
}
|
||||
_logins[GetLoginKey(loginProvider, providerKey)] = null;
|
||||
return Task.FromResult(0);
|
||||
}
|
||||
|
||||
public Task<IList<UserLoginInfo>> GetLoginsAsync(TUser user, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
IList<UserLoginInfo> result = user.Logins
|
||||
.Select(l => new UserLoginInfo(l.LoginProvider, l.ProviderKey, l.ProviderDisplayName)).ToList();
|
||||
return Task.FromResult(result);
|
||||
}
|
||||
|
||||
public Task<TUser> FindByLoginAsync(string loginProvider, string providerKey, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
string key = GetLoginKey(loginProvider, providerKey);
|
||||
if (_logins.ContainsKey(key))
|
||||
{
|
||||
return Task.FromResult(_logins[key]);
|
||||
}
|
||||
return Task.FromResult<TUser>(null);
|
||||
}
|
||||
|
||||
public Task<string> GetUserIdAsync(TUser user, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
return Task.FromResult(user.Id);
|
||||
}
|
||||
|
||||
public Task<string> GetUserNameAsync(TUser user, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
return Task.FromResult(user.UserName);
|
||||
}
|
||||
|
||||
public Task SetUserNameAsync(TUser user, string userName, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
user.UserName = userName;
|
||||
return Task.FromResult(0);
|
||||
}
|
||||
|
||||
public Task<IdentityResult> CreateAsync(TUser user, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
_users[user.Id] = user;
|
||||
return Task.FromResult(IdentityResult.Success);
|
||||
}
|
||||
|
||||
public Task<IdentityResult> UpdateAsync(TUser user, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
_users[user.Id] = user;
|
||||
return Task.FromResult(IdentityResult.Success);
|
||||
}
|
||||
|
||||
public Task<TUser> FindByIdAsync(string userId, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
if (_users.ContainsKey(userId))
|
||||
{
|
||||
return Task.FromResult(_users[userId]);
|
||||
}
|
||||
return Task.FromResult<TUser>(null);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
}
|
||||
|
||||
public Task<TUser> FindByNameAsync(string userName, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
return
|
||||
Task.FromResult(
|
||||
Users.FirstOrDefault(u => u.NormalizedUserName == userName));
|
||||
}
|
||||
|
||||
public Task<IdentityResult> DeleteAsync(TUser user, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
if (user == null || !_users.ContainsKey(user.Id))
|
||||
{
|
||||
throw new InvalidOperationException("Unknown user");
|
||||
}
|
||||
_users.Remove(user.Id);
|
||||
return Task.FromResult(IdentityResult.Success);
|
||||
}
|
||||
|
||||
public Task SetPasswordHashAsync(TUser user, string passwordHash, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
user.PasswordHash = passwordHash;
|
||||
return Task.FromResult(0);
|
||||
}
|
||||
|
||||
public Task<string> GetPasswordHashAsync(TUser user, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
return Task.FromResult(user.PasswordHash);
|
||||
}
|
||||
|
||||
public Task<bool> HasPasswordAsync(TUser user, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
return Task.FromResult(user.PasswordHash != null);
|
||||
}
|
||||
|
||||
public Task SetPhoneNumberAsync(TUser user, string phoneNumber, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
user.PhoneNumber = phoneNumber;
|
||||
return Task.FromResult(0);
|
||||
}
|
||||
|
||||
public Task<string> GetPhoneNumberAsync(TUser user, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
return Task.FromResult(user.PhoneNumber);
|
||||
}
|
||||
|
||||
public Task<bool> GetPhoneNumberConfirmedAsync(TUser user, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
return Task.FromResult(user.PhoneNumberConfirmed);
|
||||
}
|
||||
|
||||
public Task SetPhoneNumberConfirmedAsync(TUser user, bool confirmed, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
user.PhoneNumberConfirmed = confirmed;
|
||||
return Task.FromResult(0);
|
||||
}
|
||||
|
||||
public Task SetSecurityStampAsync(TUser user, string stamp, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
user.SecurityStamp = stamp;
|
||||
return Task.FromResult(0);
|
||||
}
|
||||
|
||||
public Task<string> GetSecurityStampAsync(TUser user, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
return Task.FromResult(user.SecurityStamp);
|
||||
}
|
||||
|
||||
public Task SetTwoFactorEnabledAsync(TUser user, bool enabled, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
user.TwoFactorEnabled = enabled;
|
||||
return Task.FromResult(0);
|
||||
}
|
||||
|
||||
public Task<bool> GetTwoFactorEnabledAsync(TUser user, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
return Task.FromResult(user.TwoFactorEnabled);
|
||||
}
|
||||
|
||||
public Task<string> GetNormalizedUserNameAsync(TUser user, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
return Task.FromResult(user.NormalizedUserName);
|
||||
}
|
||||
|
||||
public Task SetNormalizedUserNameAsync(TUser user, string userName, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
user.NormalizedUserName = userName;
|
||||
return Task.FromResult(0);
|
||||
}
|
||||
|
||||
public Task<IList<TUser>> GetUsersForClaimAsync(Claim claim, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
if (claim == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(claim));
|
||||
}
|
||||
|
||||
var query = from user in Users
|
||||
where user.Claims.Where(x => x.ClaimType == claim.Type && x.ClaimValue == claim.Value).FirstOrDefault() != null
|
||||
select user;
|
||||
|
||||
return Task.FromResult<IList<TUser>>(query.ToList());
|
||||
}
|
||||
|
||||
public Task SetTokenAsync(TUser user, string loginProvider, string name, string value, CancellationToken cancellationToken)
|
||||
{
|
||||
var tokenEntity =
|
||||
user.Tokens.SingleOrDefault(
|
||||
l =>
|
||||
l.TokenName == name && l.LoginProvider == loginProvider &&
|
||||
l.UserId == user.Id);
|
||||
if (tokenEntity != null)
|
||||
{
|
||||
tokenEntity.TokenValue = value;
|
||||
}
|
||||
else
|
||||
{
|
||||
user.Tokens.Add(new TestUserToken
|
||||
{
|
||||
UserId = user.Id,
|
||||
LoginProvider = loginProvider,
|
||||
TokenName = name,
|
||||
TokenValue = value
|
||||
});
|
||||
}
|
||||
return Task.FromResult(0);
|
||||
}
|
||||
|
||||
public Task RemoveTokenAsync(TUser user, string loginProvider, string name, CancellationToken cancellationToken)
|
||||
{
|
||||
var tokenEntity =
|
||||
user.Tokens.SingleOrDefault(
|
||||
l =>
|
||||
l.TokenName == name && l.LoginProvider == loginProvider &&
|
||||
l.UserId == user.Id);
|
||||
if (tokenEntity != null)
|
||||
{
|
||||
user.Tokens.Remove(tokenEntity);
|
||||
}
|
||||
return Task.FromResult(0);
|
||||
}
|
||||
|
||||
public Task<string> GetTokenAsync(TUser user, string loginProvider, string name, CancellationToken cancellationToken)
|
||||
{
|
||||
var tokenEntity =
|
||||
user.Tokens.SingleOrDefault(
|
||||
l =>
|
||||
l.TokenName == name && l.LoginProvider == loginProvider &&
|
||||
l.UserId == user.Id);
|
||||
return Task.FromResult(tokenEntity?.TokenValue);
|
||||
}
|
||||
|
||||
private const string AuthenticatorStoreLoginProvider = "[AspNetAuthenticatorStore]";
|
||||
private const string AuthenticatorKeyTokenName = "AuthenticatorKey";
|
||||
private const string RecoveryCodeTokenName = "RecoveryCodes";
|
||||
|
||||
public Task SetAuthenticatorKeyAsync(TUser user, string key, CancellationToken cancellationToken)
|
||||
{
|
||||
return SetTokenAsync(user, AuthenticatorStoreLoginProvider, AuthenticatorKeyTokenName, key, cancellationToken);
|
||||
}
|
||||
|
||||
public Task<string> GetAuthenticatorKeyAsync(TUser user, CancellationToken cancellationToken)
|
||||
{
|
||||
return GetTokenAsync(user, AuthenticatorStoreLoginProvider, AuthenticatorKeyTokenName, cancellationToken);
|
||||
}
|
||||
|
||||
public Task ReplaceCodesAsync(TUser user, IEnumerable<string> recoveryCodes, CancellationToken cancellationToken)
|
||||
{
|
||||
var mergedCodes = string.Join(";", recoveryCodes);
|
||||
return SetTokenAsync(user, AuthenticatorStoreLoginProvider, RecoveryCodeTokenName, mergedCodes, cancellationToken);
|
||||
}
|
||||
|
||||
public async Task<bool> RedeemCodeAsync(TUser user, string code, CancellationToken cancellationToken)
|
||||
{
|
||||
var mergedCodes = await GetTokenAsync(user, AuthenticatorStoreLoginProvider, RecoveryCodeTokenName, cancellationToken) ?? "";
|
||||
var splitCodes = mergedCodes.Split(';');
|
||||
if (splitCodes.Contains(code))
|
||||
{
|
||||
var updatedCodes = new List<string>(splitCodes.Where(s => s != code));
|
||||
await ReplaceCodesAsync(user, updatedCodes, cancellationToken);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
// 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 System;
|
||||
using System.Linq.Expressions;
|
||||
using Microsoft.AspNetCore.Identity.Test;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
namespace Microsoft.AspNetCore.Identity.InMemory.Test
|
||||
{
|
||||
public class InMemoryUserStoreTest : UserManagerSpecificationTestBase<TestUser, string>
|
||||
{
|
||||
protected override object CreateTestContext()
|
||||
{
|
||||
return new InMemoryUserStore<TestUser>();
|
||||
}
|
||||
|
||||
protected override void AddUserStore(IServiceCollection services, object context = null)
|
||||
{
|
||||
services.AddSingleton<IUserStore<TestUser>>((InMemoryUserStore<TestUser>)context);
|
||||
}
|
||||
|
||||
protected override void SetUserPasswordHash(TestUser user, string hashedPassword)
|
||||
{
|
||||
user.PasswordHash = hashedPassword;
|
||||
}
|
||||
|
||||
protected override TestUser CreateTestUser(string namePrefix = "", string email = "", string phoneNumber = "",
|
||||
bool lockoutEnabled = false, DateTimeOffset? lockoutEnd = default(DateTimeOffset?), bool useNamePrefixAsUserName = false)
|
||||
{
|
||||
return new TestUser
|
||||
{
|
||||
UserName = useNamePrefixAsUserName ? namePrefix : string.Format("{0}{1}", namePrefix, Guid.NewGuid()),
|
||||
Email = email,
|
||||
PhoneNumber = phoneNumber,
|
||||
LockoutEnabled = lockoutEnabled,
|
||||
LockoutEnd = lockoutEnd
|
||||
};
|
||||
}
|
||||
|
||||
protected override Expression<Func<TestUser, bool>> UserNameEqualsPredicate(string userName) => u => u.UserName == userName;
|
||||
|
||||
protected override Expression<Func<TestUser, bool>> UserNameStartsWithPredicate(string userName) => u => u.UserName.StartsWith(userName);
|
||||
}
|
||||
}
|
||||
|
|
@ -53,8 +53,8 @@ namespace Microsoft.AspNetCore.Identity.Service.EntityFrameworkCore.InMemory.Tes
|
|||
TRedirectUri,
|
||||
TApplicationKey> :
|
||||
IdentityServiceDbContext<TUser, TRole, TUserKey, TUserClaim, TUserRole, TUserLogin, TRoleClaim, TUserToken, TApplication, TScope, TApplicationClaim, TRedirectUri, TApplicationKey>
|
||||
where TUser : IdentityUser<TUserKey, TUserClaim, TUserRole, TUserLogin, TUserToken>
|
||||
where TRole : IdentityRole<TUserKey, TUserRole, TRoleClaim>
|
||||
where TUser : IdentityUser<TUserKey>
|
||||
where TRole : IdentityRole<TUserKey>
|
||||
where TUserKey : IEquatable<TUserKey>
|
||||
where TUserClaim : IdentityUserClaim<TUserKey>
|
||||
where TUserRole : IdentityUserRole<TUserKey>
|
||||
|
|
|
|||
|
|
@ -160,9 +160,6 @@ namespace Microsoft.AspNetCore.Identity.Test
|
|||
var services = new ServiceCollection()
|
||||
.AddSingleton<IConfiguration>(new ConfigurationBuilder().Build());
|
||||
var builder = services.AddIdentity<TestUser, TestRole>();
|
||||
Assert.Throws<InvalidOperationException>(() => builder.AddUserManager<UserManager<TestUser>>());
|
||||
Assert.Throws<InvalidOperationException>(() => builder.AddRoleManager<RoleManager<TestRole>>());
|
||||
Assert.Throws<InvalidOperationException>(() => builder.AddSignInManager<SignInManager<TestRole>>());
|
||||
Assert.Throws<InvalidOperationException>(() => builder.AddUserManager<object>());
|
||||
Assert.Throws<InvalidOperationException>(() => builder.AddRoleManager<object>());
|
||||
Assert.Throws<InvalidOperationException>(() => builder.AddSignInManager<object>());
|
||||
|
|
|
|||
|
|
@ -499,7 +499,7 @@ namespace Microsoft.AspNetCore.Identity.Test
|
|||
// Act
|
||||
// Assert
|
||||
var ex = await Assert.ThrowsAsync<InvalidOperationException>(() => manager.CreateAsync(user));
|
||||
Assert.Contains(Resources.NullSecurityStamp, ex.Message);
|
||||
Assert.Contains(Extensions.Identity.Core.Resources.NullSecurityStamp, ex.Message);
|
||||
|
||||
store.VerifyAll();
|
||||
}
|
||||
|
|
@ -516,7 +516,7 @@ namespace Microsoft.AspNetCore.Identity.Test
|
|||
// Act
|
||||
// Assert
|
||||
var ex = await Assert.ThrowsAsync<InvalidOperationException>(() => manager.UpdateAsync(user));
|
||||
Assert.Contains(Resources.NullSecurityStamp, ex.Message);
|
||||
Assert.Contains(Extensions.Identity.Core.Resources.NullSecurityStamp, ex.Message);
|
||||
|
||||
store.VerifyAll();
|
||||
}
|
||||
|
|
@ -698,146 +698,6 @@ namespace Microsoft.AspNetCore.Identity.Test
|
|||
Assert.ThrowsAsync<NotImplementedException>(() => manager.GenerateUserTokenAsync(new TestUser(), "A", "purpose"));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TOTPTest()
|
||||
{
|
||||
//var verify = new TotpAuthenticatorVerification();
|
||||
//var secret = "abcdefghij";
|
||||
//var secret = Base32.FromBase32(authKey);
|
||||
|
||||
// Assert.Equal(bytes, secret);
|
||||
|
||||
//var code = verify.VerifyCode(secret, -1);
|
||||
//Assert.Equal(code, 287004);
|
||||
|
||||
|
||||
//var bytes = new byte[] { (byte)'H', (byte)'e', (byte)'l', (byte)'l', (byte)'o', (byte)'!', (byte)0xDE, (byte)0xAD, (byte)0xBE, (byte)0xEF };
|
||||
//var base32 = Base32.ToBase32(bytes);
|
||||
// var code = Rfc6238AuthenticationService.GenerateCode(bytes);
|
||||
// Assert.Equal(Rfc6238AuthenticationService.GenerateCode(bytes), Rfc6238AuthenticationService.CalculateOneTimePassword(new HMACSHA1(bytes)));
|
||||
//Assert.True(Rfc6238AuthenticationService.ValidateCode(bytes, code));
|
||||
}
|
||||
|
||||
public static byte[] ToBytes(string input)
|
||||
{
|
||||
if (string.IsNullOrEmpty(input))
|
||||
{
|
||||
throw new ArgumentNullException("input");
|
||||
}
|
||||
|
||||
input = input.TrimEnd('='); //remove padding characters
|
||||
int byteCount = input.Length * 5 / 8; //this must be TRUNCATED
|
||||
byte[] returnArray = new byte[byteCount];
|
||||
|
||||
byte curByte = 0, bitsRemaining = 8;
|
||||
int mask = 0, arrayIndex = 0;
|
||||
|
||||
foreach (char c in input)
|
||||
{
|
||||
int cValue = CharToValue(c);
|
||||
|
||||
if (bitsRemaining > 5)
|
||||
{
|
||||
mask = cValue << (bitsRemaining - 5);
|
||||
curByte = (byte)(curByte | mask);
|
||||
bitsRemaining -= 5;
|
||||
}
|
||||
else
|
||||
{
|
||||
mask = cValue >> (5 - bitsRemaining);
|
||||
curByte = (byte)(curByte | mask);
|
||||
returnArray[arrayIndex++] = curByte;
|
||||
curByte = (byte)(cValue << (3 + bitsRemaining));
|
||||
bitsRemaining += 3;
|
||||
}
|
||||
}
|
||||
|
||||
//if we didn't end with a full byte
|
||||
if (arrayIndex != byteCount)
|
||||
{
|
||||
returnArray[arrayIndex] = curByte;
|
||||
}
|
||||
|
||||
return returnArray;
|
||||
}
|
||||
|
||||
public static string ToString(byte[] input)
|
||||
{
|
||||
if (input == null || input.Length == 0)
|
||||
{
|
||||
throw new ArgumentNullException("input");
|
||||
}
|
||||
|
||||
int charCount = (int)Math.Ceiling(input.Length / 5d) * 8;
|
||||
char[] returnArray = new char[charCount];
|
||||
|
||||
byte nextChar = 0, bitsRemaining = 5;
|
||||
int arrayIndex = 0;
|
||||
|
||||
foreach (byte b in input)
|
||||
{
|
||||
nextChar = (byte)(nextChar | (b >> (8 - bitsRemaining)));
|
||||
returnArray[arrayIndex++] = ValueToChar(nextChar);
|
||||
|
||||
if (bitsRemaining < 4)
|
||||
{
|
||||
nextChar = (byte)((b >> (3 - bitsRemaining)) & 31);
|
||||
returnArray[arrayIndex++] = ValueToChar(nextChar);
|
||||
bitsRemaining += 5;
|
||||
}
|
||||
|
||||
bitsRemaining -= 3;
|
||||
nextChar = (byte)((b << bitsRemaining) & 31);
|
||||
}
|
||||
|
||||
//if we didn't end with a full char
|
||||
if (arrayIndex != charCount)
|
||||
{
|
||||
returnArray[arrayIndex++] = ValueToChar(nextChar);
|
||||
while (arrayIndex != charCount) returnArray[arrayIndex++] = '='; //padding
|
||||
}
|
||||
|
||||
return new string(returnArray);
|
||||
}
|
||||
|
||||
private static int CharToValue(char c)
|
||||
{
|
||||
var value = (int)c;
|
||||
|
||||
//65-90 == uppercase letters
|
||||
if (value < 91 && value > 64)
|
||||
{
|
||||
return value - 65;
|
||||
}
|
||||
//50-55 == numbers 2-7
|
||||
if (value < 56 && value > 49)
|
||||
{
|
||||
return value - 24;
|
||||
}
|
||||
//97-122 == lowercase letters
|
||||
if (value < 123 && value > 96)
|
||||
{
|
||||
return value - 97;
|
||||
}
|
||||
|
||||
throw new ArgumentException("Character is not a Base32 character.", "c");
|
||||
}
|
||||
|
||||
private static char ValueToChar(byte b)
|
||||
{
|
||||
if (b < 26)
|
||||
{
|
||||
return (char)(b + 65);
|
||||
}
|
||||
|
||||
if (b < 32)
|
||||
{
|
||||
return (char)(b + 24);
|
||||
}
|
||||
|
||||
throw new ArgumentException("Byte is not a value Base32 value.", "b");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void UserManagerWillUseTokenProviderInstanceOverDefaults()
|
||||
{
|
||||
|
|
@ -894,7 +754,7 @@ namespace Microsoft.AspNetCore.Identity.Test
|
|||
[Fact]
|
||||
public async Task AuthTokenMethodsFailWhenStoreNotImplemented()
|
||||
{
|
||||
var error = Resources.StoreNotIUserAuthenticationTokenStore;
|
||||
var error = Extensions.Identity.Core.Resources.StoreNotIUserAuthenticationTokenStore;
|
||||
var manager = MockHelpers.TestUserManager(new NoopUserStore());
|
||||
Assert.False(manager.SupportsUserAuthenticationTokens);
|
||||
await VerifyException<NotSupportedException>(async () => await manager.GetAuthenticationTokenAsync(null, null, null), error);
|
||||
|
|
@ -905,7 +765,7 @@ namespace Microsoft.AspNetCore.Identity.Test
|
|||
[Fact]
|
||||
public async Task AuthenticatorMethodsFailWhenStoreNotImplemented()
|
||||
{
|
||||
var error = Resources.StoreNotIUserAuthenticatorKeyStore;
|
||||
var error = Extensions.Identity.Core.Resources.StoreNotIUserAuthenticatorKeyStore;
|
||||
var manager = MockHelpers.TestUserManager(new NoopUserStore());
|
||||
Assert.False(manager.SupportsUserAuthenticatorKey);
|
||||
await VerifyException<NotSupportedException>(async () => await manager.GetAuthenticatorKeyAsync(null), error);
|
||||
|
|
@ -915,7 +775,7 @@ namespace Microsoft.AspNetCore.Identity.Test
|
|||
[Fact]
|
||||
public async Task RecoveryMethodsFailWhenStoreNotImplemented()
|
||||
{
|
||||
var error = Resources.StoreNotIUserTwoFactorRecoveryCodeStore;
|
||||
var error = Extensions.Identity.Core.Resources.StoreNotIUserTwoFactorRecoveryCodeStore;
|
||||
var manager = MockHelpers.TestUserManager(new NoopUserStore());
|
||||
Assert.False(manager.SupportsUserTwoFactorRecoveryCodes);
|
||||
await VerifyException<NotSupportedException>(async () => await manager.RedeemTwoFactorRecoveryCodeAsync(null, null), error);
|
||||
|
|
|
|||
Loading…
Reference in New Issue