mirror of
https://github.com/bitwarden/server.git
synced 2024-11-21 12:05:42 +01:00
[BEEEP] Integration tests (#1945)
* Add api integration tests * Add some stuff * Make program mockable * Work on IntegrationTests for Identity * Formatting * Update packages.lock.json * Update more packages.lock.json * Update all packages.lock.json * Fix InMemory configuration * Actually fix test configuration * Fix tests for CI * Fix event service * Force EF EventRepository * Add client_credentials test * Remove Api.IntegrationTest * Remove Api Program changes * Cleanup * Add more Auth-Email tests * Run formatting * Address some PR feedback * Move integration stuff to it's own common project * Ran linter * Add shared project to test solution * Remove sln changes * Clean usings * Add more coverage * Address PR feedback
This commit is contained in:
parent
98546a65ea
commit
719abc7e61
@ -86,6 +86,10 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Billing.Test", "test\Billin
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Identity.Test", "test\Identity.Test\Identity.Test.csproj", "{310A1D8E-2D3F-4FA0-84D4-FFE31FCE193E}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Identity.IntegrationTest", "test\Identity.IntegrationTest\Identity.IntegrationTest.csproj", "{0D3B2BD2-53F3-421D-AD8F-C19B954C796B}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "IntegrationTestCommon", "test\IntegrationTestCommon\IntegrationTestCommon.csproj", "{0923DE59-5FB1-44F2-9302-A09D2236B470}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
@ -162,14 +166,6 @@ Global
|
||||
{C7BA2255-C1B1-4789-8BB9-C27540DA6FB8}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{C7BA2255-C1B1-4789-8BB9-C27540DA6FB8}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{C7BA2255-C1B1-4789-8BB9-C27540DA6FB8}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{BDC1D592-5947-47ED-9903-7CDBB12A50C8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{BDC1D592-5947-47ED-9903-7CDBB12A50C8}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{BDC1D592-5947-47ED-9903-7CDBB12A50C8}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{BDC1D592-5947-47ED-9903-7CDBB12A50C8}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{F72E0229-2EF7-49B3-9004-FF4C0043816E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{F72E0229-2EF7-49B3-9004-FF4C0043816E}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{F72E0229-2EF7-49B3-9004-FF4C0043816E}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{F72E0229-2EF7-49B3-9004-FF4C0043816E}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{EDC0D688-D58C-4CE1-AA07-3606AC6874B8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{EDC0D688-D58C-4CE1-AA07-3606AC6874B8}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{EDC0D688-D58C-4CE1-AA07-3606AC6874B8}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
@ -178,6 +174,14 @@ Global
|
||||
{0E99A21B-684B-4C59-9831-90F775CAB6F7}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{0E99A21B-684B-4C59-9831-90F775CAB6F7}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{0E99A21B-684B-4C59-9831-90F775CAB6F7}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{BDC1D592-5947-47ED-9903-7CDBB12A50C8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{BDC1D592-5947-47ED-9903-7CDBB12A50C8}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{BDC1D592-5947-47ED-9903-7CDBB12A50C8}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{BDC1D592-5947-47ED-9903-7CDBB12A50C8}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{F72E0229-2EF7-49B3-9004-FF4C0043816E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{F72E0229-2EF7-49B3-9004-FF4C0043816E}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{F72E0229-2EF7-49B3-9004-FF4C0043816E}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{F72E0229-2EF7-49B3-9004-FF4C0043816E}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{17DA09D7-0212-4009-879E-6B9CFDE5FA60}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{17DA09D7-0212-4009-879E-6B9CFDE5FA60}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{17DA09D7-0212-4009-879E-6B9CFDE5FA60}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
@ -202,6 +206,14 @@ Global
|
||||
{310A1D8E-2D3F-4FA0-84D4-FFE31FCE193E}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{310A1D8E-2D3F-4FA0-84D4-FFE31FCE193E}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{310A1D8E-2D3F-4FA0-84D4-FFE31FCE193E}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{0D3B2BD2-53F3-421D-AD8F-C19B954C796B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{0D3B2BD2-53F3-421D-AD8F-C19B954C796B}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{0D3B2BD2-53F3-421D-AD8F-C19B954C796B}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{0D3B2BD2-53F3-421D-AD8F-C19B954C796B}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{0923DE59-5FB1-44F2-9302-A09D2236B470}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{0923DE59-5FB1-44F2-9302-A09D2236B470}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{0923DE59-5FB1-44F2-9302-A09D2236B470}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{0923DE59-5FB1-44F2-9302-A09D2236B470}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
@ -224,16 +236,18 @@ Global
|
||||
{860DE301-0B3E-4717-9C21-A9B4C3C2B121} = {DD5BD056-4AAE-43EF-BBD2-0B569B8DA84F}
|
||||
{4866AF64-6640-4C65-A662-A31E02FF9064} = {4FDB6543-F68B-4202-9EA6-7FEA984D2D0A}
|
||||
{C7BA2255-C1B1-4789-8BB9-C27540DA6FB8} = {DD5BD056-4AAE-43EF-BBD2-0B569B8DA84F}
|
||||
{BDC1D592-5947-47ED-9903-7CDBB12A50C8} = {DD5BD056-4AAE-43EF-BBD2-0B569B8DA84E}
|
||||
{F72E0229-2EF7-49B3-9004-FF4C0043816E} = {DD5BD056-4AAE-43EF-BBD2-0B569B8DA84E}
|
||||
{EDC0D688-D58C-4CE1-AA07-3606AC6874B8} = {4FDB6543-F68B-4202-9EA6-7FEA984D2D0A}
|
||||
{0E99A21B-684B-4C59-9831-90F775CAB6F7} = {287CFF34-BBDB-4BC4-AF88-1E19A5A4679B}
|
||||
{BDC1D592-5947-47ED-9903-7CDBB12A50C8} = {DD5BD056-4AAE-43EF-BBD2-0B569B8DA84E}
|
||||
{F72E0229-2EF7-49B3-9004-FF4C0043816E} = {DD5BD056-4AAE-43EF-BBD2-0B569B8DA84E}
|
||||
{17DA09D7-0212-4009-879E-6B9CFDE5FA60} = {DD5BD056-4AAE-43EF-BBD2-0B569B8DA84F}
|
||||
{AD933445-27CE-4D30-A6ED-9065309464AD} = {DD5BD056-4AAE-43EF-BBD2-0B569B8DA84D}
|
||||
{713D44C0-1BC1-4024-96A3-A98A49F33908} = {DD5BD056-4AAE-43EF-BBD2-0B569B8DA84D}
|
||||
{ED880735-0250-43C7-9662-FDC7C7416E7F} = {DD5BD056-4AAE-43EF-BBD2-0B569B8DA84D}
|
||||
{B8639B10-2157-44BC-8CE1-D9EB4B50971F} = {DD5BD056-4AAE-43EF-BBD2-0B569B8DA84F}
|
||||
{310A1D8E-2D3F-4FA0-84D4-FFE31FCE193E} = {DD5BD056-4AAE-43EF-BBD2-0B569B8DA84F}
|
||||
{0D3B2BD2-53F3-421D-AD8F-C19B954C796B} = {DD5BD056-4AAE-43EF-BBD2-0B569B8DA84F}
|
||||
{0923DE59-5FB1-44F2-9302-A09D2236B470} = {DD5BD056-4AAE-43EF-BBD2-0B569B8DA84F}
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {E01CBF68-2E20-425F-9EDB-E0A6510CA92F}
|
||||
|
@ -3392,7 +3392,7 @@
|
||||
"infrastructure.dapper": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Core": "1.47.1",
|
||||
"Core": "1.48.1",
|
||||
"Dapper": "2.0.123",
|
||||
"System.Data.SqlClient": "4.8.3"
|
||||
}
|
||||
@ -3401,7 +3401,7 @@
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"AutoMapper.Extensions.Microsoft.DependencyInjection": "8.0.1",
|
||||
"Core": "1.47.1",
|
||||
"Core": "1.48.1",
|
||||
"Microsoft.EntityFrameworkCore.Relational": "5.0.12",
|
||||
"Npgsql.EntityFrameworkCore.PostgreSQL": "5.0.2",
|
||||
"Pomelo.EntityFrameworkCore.MySql": "5.0.3",
|
||||
@ -3411,9 +3411,9 @@
|
||||
"sharedweb": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Core": "1.47.1",
|
||||
"Infrastructure.Dapper": "1.47.1",
|
||||
"Infrastructure.EntityFramework": "1.47.1"
|
||||
"Core": "1.48.1",
|
||||
"Infrastructure.Dapper": "1.48.1",
|
||||
"Infrastructure.EntityFramework": "1.48.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3541,26 +3541,26 @@
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Azure.Messaging.EventGrid": "4.7.0",
|
||||
"CommCore": "1.47.1",
|
||||
"Core": "1.47.1",
|
||||
"CommCore": "1.48.1",
|
||||
"Core": "1.48.1",
|
||||
"Microsoft.AspNetCore.Mvc.NewtonsoftJson": "5.0.9",
|
||||
"SharedWeb": "1.47.1",
|
||||
"SharedWeb": "1.48.1",
|
||||
"Swashbuckle.AspNetCore": "6.2.3"
|
||||
}
|
||||
},
|
||||
"commcore": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Core": "1.47.1"
|
||||
"Core": "1.48.1"
|
||||
}
|
||||
},
|
||||
"common": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Api": "1.47.1",
|
||||
"Api": "1.48.1",
|
||||
"AutoFixture.AutoNSubstitute": "4.14.0",
|
||||
"AutoFixture.Xunit2": "4.14.0",
|
||||
"Core": "1.47.1",
|
||||
"Core": "1.48.1",
|
||||
"Kralizek.AutoFixture.Extensions.MockHttp": "1.2.0",
|
||||
"Microsoft.NET.Test.Sdk": "16.6.1",
|
||||
"NSubstitute": "4.2.2",
|
||||
@ -3609,11 +3609,11 @@
|
||||
"core.test": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Api": "1.47.1",
|
||||
"Api": "1.48.1",
|
||||
"AutoFixture.AutoNSubstitute": "4.14.0",
|
||||
"AutoFixture.Xunit2": "4.14.0",
|
||||
"Common": "1.47.1",
|
||||
"Core": "1.47.1",
|
||||
"Common": "1.48.1",
|
||||
"Core": "1.48.1",
|
||||
"Kralizek.AutoFixture.Extensions.MockHttp": "1.2.0",
|
||||
"Microsoft.NET.Test.Sdk": "16.6.1",
|
||||
"Moq": "4.16.1",
|
||||
@ -3624,7 +3624,7 @@
|
||||
"infrastructure.dapper": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Core": "1.47.1",
|
||||
"Core": "1.48.1",
|
||||
"Dapper": "2.0.123",
|
||||
"System.Data.SqlClient": "4.8.3"
|
||||
}
|
||||
@ -3633,7 +3633,7 @@
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"AutoMapper.Extensions.Microsoft.DependencyInjection": "8.0.1",
|
||||
"Core": "1.47.1",
|
||||
"Core": "1.48.1",
|
||||
"Microsoft.EntityFrameworkCore.Relational": "5.0.12",
|
||||
"Npgsql.EntityFrameworkCore.PostgreSQL": "5.0.2",
|
||||
"Pomelo.EntityFrameworkCore.MySql": "5.0.3",
|
||||
@ -3643,9 +3643,9 @@
|
||||
"sharedweb": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Core": "1.47.1",
|
||||
"Infrastructure.Dapper": "1.47.1",
|
||||
"Infrastructure.EntityFramework": "1.47.1"
|
||||
"Core": "1.48.1",
|
||||
"Infrastructure.Dapper": "1.48.1",
|
||||
"Infrastructure.EntityFramework": "1.48.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3416,7 +3416,7 @@
|
||||
"commcore": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Core": "1.47.1"
|
||||
"Core": "1.48.1"
|
||||
}
|
||||
},
|
||||
"core": {
|
||||
@ -3461,7 +3461,7 @@
|
||||
"infrastructure.dapper": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Core": "1.47.1",
|
||||
"Core": "1.48.1",
|
||||
"Dapper": "2.0.123",
|
||||
"System.Data.SqlClient": "4.8.3"
|
||||
}
|
||||
@ -3470,7 +3470,7 @@
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"AutoMapper.Extensions.Microsoft.DependencyInjection": "8.0.1",
|
||||
"Core": "1.47.1",
|
||||
"Core": "1.48.1",
|
||||
"Microsoft.EntityFrameworkCore.Relational": "5.0.12",
|
||||
"Npgsql.EntityFrameworkCore.PostgreSQL": "5.0.2",
|
||||
"Pomelo.EntityFrameworkCore.MySql": "5.0.3",
|
||||
@ -3480,7 +3480,7 @@
|
||||
"migrator": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Core": "1.47.1",
|
||||
"Core": "1.48.1",
|
||||
"Microsoft.Extensions.Logging": "5.0.0",
|
||||
"dbup-sqlserver": "4.4.0"
|
||||
}
|
||||
@ -3488,9 +3488,9 @@
|
||||
"sharedweb": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Core": "1.47.1",
|
||||
"Infrastructure.Dapper": "1.47.1",
|
||||
"Infrastructure.EntityFramework": "1.47.1"
|
||||
"Core": "1.48.1",
|
||||
"Infrastructure.Dapper": "1.48.1",
|
||||
"Infrastructure.EntityFramework": "1.48.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3355,7 +3355,7 @@
|
||||
"commcore": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Core": "1.47.1"
|
||||
"Core": "1.48.1"
|
||||
}
|
||||
},
|
||||
"core": {
|
||||
@ -3400,7 +3400,7 @@
|
||||
"infrastructure.dapper": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Core": "1.47.1",
|
||||
"Core": "1.48.1",
|
||||
"Dapper": "2.0.123",
|
||||
"System.Data.SqlClient": "4.8.3"
|
||||
}
|
||||
@ -3409,7 +3409,7 @@
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"AutoMapper.Extensions.Microsoft.DependencyInjection": "8.0.1",
|
||||
"Core": "1.47.1",
|
||||
"Core": "1.48.1",
|
||||
"Microsoft.EntityFrameworkCore.Relational": "5.0.12",
|
||||
"Npgsql.EntityFrameworkCore.PostgreSQL": "5.0.2",
|
||||
"Pomelo.EntityFrameworkCore.MySql": "5.0.3",
|
||||
@ -3419,9 +3419,9 @@
|
||||
"sharedweb": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Core": "1.47.1",
|
||||
"Infrastructure.Dapper": "1.47.1",
|
||||
"Infrastructure.EntityFramework": "1.47.1"
|
||||
"Core": "1.48.1",
|
||||
"Infrastructure.Dapper": "1.48.1",
|
||||
"Infrastructure.EntityFramework": "1.48.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3424,7 +3424,7 @@
|
||||
"infrastructure.dapper": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Core": "1.47.1",
|
||||
"Core": "1.48.1",
|
||||
"Dapper": "2.0.123",
|
||||
"System.Data.SqlClient": "4.8.3"
|
||||
}
|
||||
@ -3433,7 +3433,7 @@
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"AutoMapper.Extensions.Microsoft.DependencyInjection": "8.0.1",
|
||||
"Core": "1.47.1",
|
||||
"Core": "1.48.1",
|
||||
"Microsoft.EntityFrameworkCore.Relational": "5.0.12",
|
||||
"Npgsql.EntityFrameworkCore.PostgreSQL": "5.0.2",
|
||||
"Pomelo.EntityFrameworkCore.MySql": "5.0.3",
|
||||
@ -3443,9 +3443,9 @@
|
||||
"sharedweb": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Core": "1.47.1",
|
||||
"Infrastructure.Dapper": "1.47.1",
|
||||
"Infrastructure.EntityFramework": "1.47.1"
|
||||
"Core": "1.48.1",
|
||||
"Infrastructure.Dapper": "1.48.1",
|
||||
"Infrastructure.EntityFramework": "1.48.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3333,7 +3333,7 @@
|
||||
"infrastructure.dapper": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Core": "1.47.1",
|
||||
"Core": "1.48.1",
|
||||
"Dapper": "2.0.123",
|
||||
"System.Data.SqlClient": "4.8.3"
|
||||
}
|
||||
@ -3342,7 +3342,7 @@
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"AutoMapper.Extensions.Microsoft.DependencyInjection": "8.0.1",
|
||||
"Core": "1.47.1",
|
||||
"Core": "1.48.1",
|
||||
"Microsoft.EntityFrameworkCore.Relational": "5.0.12",
|
||||
"Npgsql.EntityFrameworkCore.PostgreSQL": "5.0.2",
|
||||
"Pomelo.EntityFrameworkCore.MySql": "5.0.3",
|
||||
@ -3352,9 +3352,9 @@
|
||||
"sharedweb": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Core": "1.47.1",
|
||||
"Infrastructure.Dapper": "1.47.1",
|
||||
"Infrastructure.EntityFramework": "1.47.1"
|
||||
"Core": "1.48.1",
|
||||
"Infrastructure.Dapper": "1.48.1",
|
||||
"Infrastructure.EntityFramework": "1.48.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3333,7 +3333,7 @@
|
||||
"infrastructure.dapper": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Core": "1.47.1",
|
||||
"Core": "1.48.1",
|
||||
"Dapper": "2.0.123",
|
||||
"System.Data.SqlClient": "4.8.3"
|
||||
}
|
||||
@ -3342,7 +3342,7 @@
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"AutoMapper.Extensions.Microsoft.DependencyInjection": "8.0.1",
|
||||
"Core": "1.47.1",
|
||||
"Core": "1.48.1",
|
||||
"Microsoft.EntityFrameworkCore.Relational": "5.0.12",
|
||||
"Npgsql.EntityFrameworkCore.PostgreSQL": "5.0.2",
|
||||
"Pomelo.EntityFrameworkCore.MySql": "5.0.3",
|
||||
@ -3352,9 +3352,9 @@
|
||||
"sharedweb": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Core": "1.47.1",
|
||||
"Infrastructure.Dapper": "1.47.1",
|
||||
"Infrastructure.EntityFramework": "1.47.1"
|
||||
"Core": "1.48.1",
|
||||
"Infrastructure.Dapper": "1.48.1",
|
||||
"Infrastructure.EntityFramework": "1.48.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3342,7 +3342,7 @@
|
||||
"infrastructure.dapper": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Core": "1.46.2",
|
||||
"Core": "1.48.1",
|
||||
"Dapper": "2.0.123",
|
||||
"System.Data.SqlClient": "4.8.3"
|
||||
}
|
||||
@ -3351,7 +3351,7 @@
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"AutoMapper.Extensions.Microsoft.DependencyInjection": "8.0.1",
|
||||
"Core": "1.46.2",
|
||||
"Core": "1.48.1",
|
||||
"Microsoft.EntityFrameworkCore.Relational": "5.0.12",
|
||||
"Npgsql.EntityFrameworkCore.PostgreSQL": "5.0.2",
|
||||
"Pomelo.EntityFrameworkCore.MySql": "5.0.3",
|
||||
@ -3361,9 +3361,9 @@
|
||||
"sharedweb": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Core": "1.46.2",
|
||||
"Infrastructure.Dapper": "1.46.2",
|
||||
"Infrastructure.EntityFramework": "1.46.2"
|
||||
"Core": "1.48.1",
|
||||
"Infrastructure.Dapper": "1.48.1",
|
||||
"Infrastructure.EntityFramework": "1.48.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -10,7 +10,14 @@ namespace Bit.Identity
|
||||
{
|
||||
public static void Main(string[] args)
|
||||
{
|
||||
Host
|
||||
CreateHostBuilder(args)
|
||||
.Build()
|
||||
.Run();
|
||||
}
|
||||
|
||||
public static IHostBuilder CreateHostBuilder(string[] args)
|
||||
{
|
||||
return Host
|
||||
.CreateDefaultBuilder(args)
|
||||
.ConfigureCustomAppConfiguration(args)
|
||||
.ConfigureWebHostDefaults(webBuilder =>
|
||||
@ -34,9 +41,7 @@ namespace Bit.Identity
|
||||
|
||||
return e.Level >= LogEventLevel.Error;
|
||||
}));
|
||||
})
|
||||
.Build()
|
||||
.Run();
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3333,7 +3333,7 @@
|
||||
"infrastructure.dapper": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Core": "1.47.1",
|
||||
"Core": "1.48.1",
|
||||
"Dapper": "2.0.123",
|
||||
"System.Data.SqlClient": "4.8.3"
|
||||
}
|
||||
@ -3342,7 +3342,7 @@
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"AutoMapper.Extensions.Microsoft.DependencyInjection": "8.0.1",
|
||||
"Core": "1.47.1",
|
||||
"Core": "1.48.1",
|
||||
"Microsoft.EntityFrameworkCore.Relational": "5.0.12",
|
||||
"Npgsql.EntityFrameworkCore.PostgreSQL": "5.0.2",
|
||||
"Pomelo.EntityFrameworkCore.MySql": "5.0.3",
|
||||
@ -3352,9 +3352,9 @@
|
||||
"sharedweb": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Core": "1.47.1",
|
||||
"Infrastructure.Dapper": "1.47.1",
|
||||
"Infrastructure.EntityFramework": "1.47.1"
|
||||
"Core": "1.48.1",
|
||||
"Infrastructure.Dapper": "1.48.1",
|
||||
"Infrastructure.EntityFramework": "1.48.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3427,7 +3427,7 @@
|
||||
"infrastructure.dapper": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Core": "1.47.1",
|
||||
"Core": "1.48.1",
|
||||
"Dapper": "2.0.123",
|
||||
"System.Data.SqlClient": "4.8.3"
|
||||
}
|
||||
@ -3436,7 +3436,7 @@
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"AutoMapper.Extensions.Microsoft.DependencyInjection": "8.0.1",
|
||||
"Core": "1.47.1",
|
||||
"Core": "1.48.1",
|
||||
"Microsoft.EntityFrameworkCore.Relational": "5.0.12",
|
||||
"Npgsql.EntityFrameworkCore.PostgreSQL": "5.0.2",
|
||||
"Pomelo.EntityFrameworkCore.MySql": "5.0.3",
|
||||
@ -3446,9 +3446,9 @@
|
||||
"sharedweb": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Core": "1.47.1",
|
||||
"Infrastructure.Dapper": "1.47.1",
|
||||
"Infrastructure.EntityFramework": "1.47.1"
|
||||
"Core": "1.48.1",
|
||||
"Infrastructure.Dapper": "1.48.1",
|
||||
"Infrastructure.EntityFramework": "1.48.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3333,7 +3333,7 @@
|
||||
"infrastructure.dapper": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Core": "1.46.2",
|
||||
"Core": "1.48.1",
|
||||
"Dapper": "2.0.123",
|
||||
"System.Data.SqlClient": "4.8.3"
|
||||
}
|
||||
@ -3342,7 +3342,7 @@
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"AutoMapper.Extensions.Microsoft.DependencyInjection": "8.0.1",
|
||||
"Core": "1.46.2",
|
||||
"Core": "1.48.1",
|
||||
"Microsoft.EntityFrameworkCore.Relational": "5.0.12",
|
||||
"Npgsql.EntityFrameworkCore.PostgreSQL": "5.0.2",
|
||||
"Pomelo.EntityFrameworkCore.MySql": "5.0.3",
|
||||
|
@ -3534,26 +3534,26 @@
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Azure.Messaging.EventGrid": "4.7.0",
|
||||
"CommCore": "1.47.1",
|
||||
"Core": "1.47.1",
|
||||
"CommCore": "1.48.1",
|
||||
"Core": "1.48.1",
|
||||
"Microsoft.AspNetCore.Mvc.NewtonsoftJson": "5.0.9",
|
||||
"SharedWeb": "1.47.1",
|
||||
"SharedWeb": "1.48.1",
|
||||
"Swashbuckle.AspNetCore": "6.2.3"
|
||||
}
|
||||
},
|
||||
"commcore": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Core": "1.47.1"
|
||||
"Core": "1.48.1"
|
||||
}
|
||||
},
|
||||
"common": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Api": "1.47.1",
|
||||
"Api": "1.48.1",
|
||||
"AutoFixture.AutoNSubstitute": "4.14.0",
|
||||
"AutoFixture.Xunit2": "4.14.0",
|
||||
"Core": "1.47.1",
|
||||
"Core": "1.48.1",
|
||||
"Kralizek.AutoFixture.Extensions.MockHttp": "1.2.0",
|
||||
"Microsoft.NET.Test.Sdk": "16.6.1",
|
||||
"NSubstitute": "4.2.2",
|
||||
@ -3602,7 +3602,7 @@
|
||||
"infrastructure.dapper": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Core": "1.47.1",
|
||||
"Core": "1.48.1",
|
||||
"Dapper": "2.0.123",
|
||||
"System.Data.SqlClient": "4.8.3"
|
||||
}
|
||||
@ -3611,7 +3611,7 @@
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"AutoMapper.Extensions.Microsoft.DependencyInjection": "8.0.1",
|
||||
"Core": "1.47.1",
|
||||
"Core": "1.48.1",
|
||||
"Microsoft.EntityFrameworkCore.Relational": "5.0.12",
|
||||
"Npgsql.EntityFrameworkCore.PostgreSQL": "5.0.2",
|
||||
"Pomelo.EntityFrameworkCore.MySql": "5.0.3",
|
||||
@ -3621,9 +3621,9 @@
|
||||
"sharedweb": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Core": "1.47.1",
|
||||
"Infrastructure.Dapper": "1.47.1",
|
||||
"Infrastructure.EntityFramework": "1.47.1"
|
||||
"Core": "1.48.1",
|
||||
"Infrastructure.Dapper": "1.48.1",
|
||||
"Infrastructure.EntityFramework": "1.48.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3625,34 +3625,34 @@
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Azure.Messaging.EventGrid": "4.7.0",
|
||||
"CommCore": "1.47.1",
|
||||
"Core": "1.47.1",
|
||||
"CommCore": "1.48.1",
|
||||
"Core": "1.48.1",
|
||||
"Microsoft.AspNetCore.Mvc.NewtonsoftJson": "5.0.9",
|
||||
"SharedWeb": "1.47.1",
|
||||
"SharedWeb": "1.48.1",
|
||||
"Swashbuckle.AspNetCore": "6.2.3"
|
||||
}
|
||||
},
|
||||
"billing": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Core": "1.47.1",
|
||||
"Core": "1.48.1",
|
||||
"Microsoft.VisualStudio.Web.CodeGeneration.Design": "5.0.2",
|
||||
"SharedWeb": "1.47.1"
|
||||
"SharedWeb": "1.48.1"
|
||||
}
|
||||
},
|
||||
"commcore": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Core": "1.47.1"
|
||||
"Core": "1.48.1"
|
||||
}
|
||||
},
|
||||
"common": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Api": "1.47.1",
|
||||
"Api": "1.48.1",
|
||||
"AutoFixture.AutoNSubstitute": "4.14.0",
|
||||
"AutoFixture.Xunit2": "4.14.0",
|
||||
"Core": "1.47.1",
|
||||
"Core": "1.48.1",
|
||||
"Kralizek.AutoFixture.Extensions.MockHttp": "1.2.0",
|
||||
"Microsoft.NET.Test.Sdk": "16.6.1",
|
||||
"NSubstitute": "4.2.2",
|
||||
@ -3701,7 +3701,7 @@
|
||||
"infrastructure.dapper": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Core": "1.47.1",
|
||||
"Core": "1.48.1",
|
||||
"Dapper": "2.0.123",
|
||||
"System.Data.SqlClient": "4.8.3"
|
||||
}
|
||||
@ -3710,7 +3710,7 @@
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"AutoMapper.Extensions.Microsoft.DependencyInjection": "8.0.1",
|
||||
"Core": "1.47.1",
|
||||
"Core": "1.48.1",
|
||||
"Microsoft.EntityFrameworkCore.Relational": "5.0.12",
|
||||
"Npgsql.EntityFrameworkCore.PostgreSQL": "5.0.2",
|
||||
"Pomelo.EntityFrameworkCore.MySql": "5.0.3",
|
||||
@ -3720,9 +3720,9 @@
|
||||
"sharedweb": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Core": "1.47.1",
|
||||
"Infrastructure.Dapper": "1.47.1",
|
||||
"Infrastructure.EntityFramework": "1.47.1"
|
||||
"Core": "1.48.1",
|
||||
"Infrastructure.Dapper": "1.48.1",
|
||||
"Infrastructure.EntityFramework": "1.48.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,9 +1,12 @@
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Linq.Expressions;
|
||||
using System.Reflection;
|
||||
using System.Text.Json;
|
||||
using System.Threading.Tasks;
|
||||
using Bit.Core.Utilities;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Xunit;
|
||||
using Xunit.Sdk;
|
||||
|
||||
@ -84,6 +87,116 @@ namespace Bit.Test.Common.Helpers
|
||||
return subElement;
|
||||
}
|
||||
|
||||
public static void AssertEqualJson(JsonElement a, JsonElement b)
|
||||
{
|
||||
switch (a.ValueKind)
|
||||
{
|
||||
case JsonValueKind.Array:
|
||||
Assert.Equal(JsonValueKind.Array, b.ValueKind);
|
||||
AssertEqualJsonArray(a, b);
|
||||
break;
|
||||
case JsonValueKind.Object:
|
||||
Assert.Equal(JsonValueKind.Object, b.ValueKind);
|
||||
AssertEqualJsonObject(a, b);
|
||||
break;
|
||||
case JsonValueKind.False:
|
||||
Assert.Equal(JsonValueKind.False, b.ValueKind);
|
||||
break;
|
||||
case JsonValueKind.True:
|
||||
Assert.Equal(JsonValueKind.True, b.ValueKind);
|
||||
break;
|
||||
case JsonValueKind.Number:
|
||||
Assert.Equal(JsonValueKind.Number, b.ValueKind);
|
||||
Assert.Equal(a.GetDouble(), b.GetDouble());
|
||||
break;
|
||||
case JsonValueKind.String:
|
||||
Assert.Equal(JsonValueKind.String, b.ValueKind);
|
||||
Assert.Equal(a.GetString(), b.GetString());
|
||||
break;
|
||||
case JsonValueKind.Null:
|
||||
Assert.Equal(JsonValueKind.Null, b.ValueKind);
|
||||
break;
|
||||
default:
|
||||
throw new XunitException($"Bad JsonValueKind '{a.ValueKind}'");
|
||||
}
|
||||
}
|
||||
|
||||
private static void AssertEqualJsonObject(JsonElement a, JsonElement b)
|
||||
{
|
||||
Debug.Assert(a.ValueKind == JsonValueKind.Object && b.ValueKind == JsonValueKind.Object);
|
||||
|
||||
var aObjectEnumerator = a.EnumerateObject();
|
||||
var bObjectEnumerator = b.EnumerateObject();
|
||||
|
||||
while (true)
|
||||
{
|
||||
var aCanMove = aObjectEnumerator.MoveNext();
|
||||
var bCanMove = bObjectEnumerator.MoveNext();
|
||||
|
||||
if (aCanMove)
|
||||
{
|
||||
Assert.True(bCanMove, $"a was able to enumerate over object '{a}' but b was NOT able to '{b}'");
|
||||
}
|
||||
else
|
||||
{
|
||||
Assert.False(bCanMove, $"a was NOT able to enumerate over object '{a}' but b was able to '{b}'");
|
||||
}
|
||||
|
||||
if (aCanMove == false && bCanMove == false)
|
||||
{
|
||||
// They both can't continue to enumerate at the same time, that is valid
|
||||
break;
|
||||
}
|
||||
|
||||
var aProp = aObjectEnumerator.Current;
|
||||
var bProp = bObjectEnumerator.Current;
|
||||
|
||||
Assert.Equal(aProp.Name, bProp.Name);
|
||||
// Recursion!
|
||||
AssertEqualJson(aProp.Value, bProp.Value);
|
||||
}
|
||||
}
|
||||
|
||||
private static void AssertEqualJsonArray(JsonElement a, JsonElement b)
|
||||
{
|
||||
Debug.Assert(a.ValueKind == JsonValueKind.Array && b.ValueKind == JsonValueKind.Array);
|
||||
|
||||
var aArrayEnumerator = a.EnumerateArray();
|
||||
var bArrayEnumerator = b.EnumerateArray();
|
||||
|
||||
while (true)
|
||||
{
|
||||
var aCanMove = aArrayEnumerator.MoveNext();
|
||||
var bCanMove = bArrayEnumerator.MoveNext();
|
||||
|
||||
if (aCanMove)
|
||||
{
|
||||
Assert.True(bCanMove, $"a was able to enumerate over array '{a}' but b was NOT able to '{b}'");
|
||||
}
|
||||
else
|
||||
{
|
||||
Assert.False(bCanMove, $"a was NOT able to enumerate over array '{a}' but b was able to '{b}'");
|
||||
}
|
||||
|
||||
if (aCanMove == false && bCanMove == false)
|
||||
{
|
||||
// They both can't continue to enumerate at the same time, that is valid
|
||||
break;
|
||||
}
|
||||
|
||||
var aElement = aArrayEnumerator.Current;
|
||||
var bElement = bArrayEnumerator.Current;
|
||||
|
||||
// Recursion!
|
||||
AssertEqualJson(aElement, bElement);
|
||||
}
|
||||
}
|
||||
|
||||
public async static Task<T> AssertResponseTypeIs<T>(HttpContext context)
|
||||
{
|
||||
return await JsonSerializer.DeserializeAsync<T>(context.Response.Body);
|
||||
}
|
||||
|
||||
public static TimeSpan AssertRecent(DateTime dateTime, int skewSeconds = 2)
|
||||
=> AssertRecent(dateTime, TimeSpan.FromSeconds(skewSeconds));
|
||||
|
||||
|
@ -3530,17 +3530,17 @@
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Azure.Messaging.EventGrid": "4.7.0",
|
||||
"CommCore": "1.47.1",
|
||||
"Core": "1.47.1",
|
||||
"CommCore": "1.48.1",
|
||||
"Core": "1.48.1",
|
||||
"Microsoft.AspNetCore.Mvc.NewtonsoftJson": "5.0.9",
|
||||
"SharedWeb": "1.47.1",
|
||||
"SharedWeb": "1.48.1",
|
||||
"Swashbuckle.AspNetCore": "6.2.3"
|
||||
}
|
||||
},
|
||||
"commcore": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Core": "1.47.1"
|
||||
"Core": "1.48.1"
|
||||
}
|
||||
},
|
||||
"core": {
|
||||
@ -3585,7 +3585,7 @@
|
||||
"infrastructure.dapper": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Core": "1.47.1",
|
||||
"Core": "1.48.1",
|
||||
"Dapper": "2.0.123",
|
||||
"System.Data.SqlClient": "4.8.3"
|
||||
}
|
||||
@ -3594,7 +3594,7 @@
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"AutoMapper.Extensions.Microsoft.DependencyInjection": "8.0.1",
|
||||
"Core": "1.47.1",
|
||||
"Core": "1.48.1",
|
||||
"Microsoft.EntityFrameworkCore.Relational": "5.0.12",
|
||||
"Npgsql.EntityFrameworkCore.PostgreSQL": "5.0.2",
|
||||
"Pomelo.EntityFrameworkCore.MySql": "5.0.3",
|
||||
@ -3604,9 +3604,9 @@
|
||||
"sharedweb": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Core": "1.47.1",
|
||||
"Infrastructure.Dapper": "1.47.1",
|
||||
"Infrastructure.EntityFramework": "1.47.1"
|
||||
"Core": "1.48.1",
|
||||
"Infrastructure.Dapper": "1.48.1",
|
||||
"Infrastructure.EntityFramework": "1.48.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2,6 +2,7 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using AutoFixture;
|
||||
using Bit.Core.Context;
|
||||
using Bit.Core.Entities;
|
||||
@ -13,6 +14,9 @@ using Bit.Infrastructure.Dapper;
|
||||
using Bit.Test.Common.AutoFixture;
|
||||
using Bit.Test.Common.AutoFixture.Attributes;
|
||||
using IdentityModel;
|
||||
using Microsoft.AspNetCore.DataProtection;
|
||||
using Microsoft.AspNetCore.WebUtilities;
|
||||
using NSubstitute;
|
||||
using Xunit;
|
||||
|
||||
namespace Bit.Core.Test.Utilities
|
||||
@ -390,6 +394,47 @@ namespace Bit.Core.Test.Utilities
|
||||
}
|
||||
}
|
||||
|
||||
public static IEnumerable<object[]> TokenIsValidData()
|
||||
{
|
||||
return new[]
|
||||
{
|
||||
new object[]
|
||||
{
|
||||
"first_part 476669d4-9642-4af8-9b29-9366efad4ed3 test@email.com {0}", // unprotectedTokenTemplate
|
||||
"first_part", // firstPart
|
||||
"test@email.com", // email
|
||||
Guid.Parse("476669d4-9642-4af8-9b29-9366efad4ed3"), // id
|
||||
DateTime.UtcNow.AddHours(-1), // creationTime
|
||||
12, // expirationInHours
|
||||
true, // isValid
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(TokenIsValidData))]
|
||||
public void TokenIsValid_Success(string unprotectedTokenTemplate, string firstPart, string userEmail, Guid id, DateTime creationTime, double expirationInHours, bool isValid)
|
||||
{
|
||||
var protector = new TestDataProtector(string.Format(unprotectedTokenTemplate, CoreHelpers.ToEpocMilliseconds(creationTime)));
|
||||
|
||||
Assert.Equal(isValid, CoreHelpers.TokenIsValid(firstPart, protector, "protected_token", userEmail, id, expirationInHours));
|
||||
}
|
||||
|
||||
private class TestDataProtector : IDataProtector
|
||||
{
|
||||
private readonly string _token;
|
||||
public TestDataProtector(string token)
|
||||
{
|
||||
_token = token;
|
||||
}
|
||||
public IDataProtector CreateProtector(string purpose) => throw new NotImplementedException();
|
||||
public byte[] Protect(byte[] plaintext) => throw new NotImplementedException();
|
||||
public byte[] Unprotect(byte[] protectedData)
|
||||
{
|
||||
return Encoding.UTF8.GetBytes(_token);
|
||||
}
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("hi@email.com", "hi@email.com")] // Short email with no room to obfuscate
|
||||
[InlineData("name@email.com", "na**@email.com")] // Can obfuscate
|
||||
|
@ -3546,26 +3546,26 @@
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Azure.Messaging.EventGrid": "4.7.0",
|
||||
"CommCore": "1.47.1",
|
||||
"Core": "1.47.1",
|
||||
"CommCore": "1.48.1",
|
||||
"Core": "1.48.1",
|
||||
"Microsoft.AspNetCore.Mvc.NewtonsoftJson": "5.0.9",
|
||||
"SharedWeb": "1.47.1",
|
||||
"SharedWeb": "1.48.1",
|
||||
"Swashbuckle.AspNetCore": "6.2.3"
|
||||
}
|
||||
},
|
||||
"commcore": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Core": "1.47.1"
|
||||
"Core": "1.48.1"
|
||||
}
|
||||
},
|
||||
"common": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Api": "1.47.1",
|
||||
"Api": "1.48.1",
|
||||
"AutoFixture.AutoNSubstitute": "4.14.0",
|
||||
"AutoFixture.Xunit2": "4.14.0",
|
||||
"Core": "1.47.1",
|
||||
"Core": "1.48.1",
|
||||
"Kralizek.AutoFixture.Extensions.MockHttp": "1.2.0",
|
||||
"Microsoft.NET.Test.Sdk": "16.6.1",
|
||||
"NSubstitute": "4.2.2",
|
||||
@ -3614,7 +3614,7 @@
|
||||
"infrastructure.dapper": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Core": "1.47.1",
|
||||
"Core": "1.48.1",
|
||||
"Dapper": "2.0.123",
|
||||
"System.Data.SqlClient": "4.8.3"
|
||||
}
|
||||
@ -3623,7 +3623,7 @@
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"AutoMapper.Extensions.Microsoft.DependencyInjection": "8.0.1",
|
||||
"Core": "1.47.1",
|
||||
"Core": "1.48.1",
|
||||
"Microsoft.EntityFrameworkCore.Relational": "5.0.12",
|
||||
"Npgsql.EntityFrameworkCore.PostgreSQL": "5.0.2",
|
||||
"Pomelo.EntityFrameworkCore.MySql": "5.0.3",
|
||||
@ -3633,9 +3633,9 @@
|
||||
"sharedweb": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Core": "1.47.1",
|
||||
"Infrastructure.Dapper": "1.47.1",
|
||||
"Infrastructure.EntityFramework": "1.47.1"
|
||||
"Core": "1.48.1",
|
||||
"Infrastructure.Dapper": "1.48.1",
|
||||
"Infrastructure.EntityFramework": "1.48.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3473,14 +3473,14 @@
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"AngleSharp": "0.14.0",
|
||||
"Core": "1.47.1",
|
||||
"SharedWeb": "1.47.1"
|
||||
"Core": "1.48.1",
|
||||
"SharedWeb": "1.48.1"
|
||||
}
|
||||
},
|
||||
"infrastructure.dapper": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Core": "1.47.1",
|
||||
"Core": "1.48.1",
|
||||
"Dapper": "2.0.123",
|
||||
"System.Data.SqlClient": "4.8.3"
|
||||
}
|
||||
@ -3489,7 +3489,7 @@
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"AutoMapper.Extensions.Microsoft.DependencyInjection": "8.0.1",
|
||||
"Core": "1.47.1",
|
||||
"Core": "1.48.1",
|
||||
"Microsoft.EntityFrameworkCore.Relational": "5.0.12",
|
||||
"Npgsql.EntityFrameworkCore.PostgreSQL": "5.0.2",
|
||||
"Pomelo.EntityFrameworkCore.MySql": "5.0.3",
|
||||
@ -3499,9 +3499,9 @@
|
||||
"sharedweb": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Core": "1.47.1",
|
||||
"Infrastructure.Dapper": "1.47.1",
|
||||
"Infrastructure.EntityFramework": "1.47.1"
|
||||
"Core": "1.48.1",
|
||||
"Infrastructure.Dapper": "1.48.1",
|
||||
"Infrastructure.EntityFramework": "1.48.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,37 @@
|
||||
using System.Threading.Tasks;
|
||||
using Bit.Core.Models.Api.Request.Accounts;
|
||||
using Bit.IntegrationTestCommon.Factories;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Xunit;
|
||||
|
||||
namespace Bit.Identity.IntegrationTest.Controllers
|
||||
{
|
||||
public class AccountsControllerTests : IClassFixture<IdentityApplicationFactory>
|
||||
{
|
||||
private readonly IdentityApplicationFactory _factory;
|
||||
|
||||
public AccountsControllerTests(IdentityApplicationFactory factory)
|
||||
{
|
||||
_factory = factory;
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task PostRegister_Success()
|
||||
{
|
||||
var context = await _factory.RegisterAsync(new RegisterRequestModel
|
||||
{
|
||||
Email = "test+register@email.com",
|
||||
MasterPasswordHash = "master_password_hash"
|
||||
});
|
||||
|
||||
Assert.Equal(StatusCodes.Status200OK, context.Response.StatusCode);
|
||||
|
||||
var database = _factory.GetDatabaseContext();
|
||||
var user = await database.Users
|
||||
.SingleAsync(u => u.Email == "test+register@email.com");
|
||||
|
||||
Assert.NotNull(user);
|
||||
}
|
||||
}
|
||||
}
|
454
test/Identity.IntegrationTest/Endpoints/IdentityServerTests.cs
Normal file
454
test/Identity.IntegrationTest/Endpoints/IdentityServerTests.cs
Normal file
@ -0,0 +1,454 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Net.Http;
|
||||
using System.Text.Json;
|
||||
using System.Threading.Tasks;
|
||||
using Bit.Core.Entities;
|
||||
using Bit.Core.Enums;
|
||||
using Bit.Core.Models.Api.Request.Accounts;
|
||||
using Bit.Core.Repositories;
|
||||
using Bit.Core.Utilities;
|
||||
using Bit.IntegrationTestCommon.Factories;
|
||||
using Bit.Test.Common.AutoFixture.Attributes;
|
||||
using Bit.Test.Common.Helpers;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Xunit;
|
||||
|
||||
namespace Bit.Identity.IntegrationTest.Endpoints
|
||||
{
|
||||
public class IdentityServerTests : IClassFixture<IdentityApplicationFactory>
|
||||
{
|
||||
private const int SecondsInMinute = 60;
|
||||
private const int MinutesInHour = 60;
|
||||
private const int SecondsInHour = SecondsInMinute * MinutesInHour;
|
||||
private readonly IdentityApplicationFactory _factory;
|
||||
|
||||
public IdentityServerTests(IdentityApplicationFactory factory)
|
||||
{
|
||||
_factory = factory;
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task WellKnownEndpoint_Success()
|
||||
{
|
||||
var context = await _factory.Server.GetAsync("/.well-known/openid-configuration");
|
||||
|
||||
using var body = await AssertHelper.AssertResponseTypeIs<JsonDocument>(context);
|
||||
var endpointRoot = body.RootElement;
|
||||
|
||||
// WARNING: Edits to this file should NOT just be made to "get the test to work" they should be made when intentional
|
||||
// changes were made to this endpoint and proper testing will take place to ensure clients are backwards compatible
|
||||
// or loss of functionality is properly noted.
|
||||
await using var fs = File.OpenRead("openid-configuration.json");
|
||||
using var knownConfiguration = await JsonSerializer.DeserializeAsync<JsonDocument>(fs);
|
||||
var knownConfigurationRoot = knownConfiguration.RootElement;
|
||||
|
||||
AssertHelper.AssertEqualJson(endpointRoot, knownConfigurationRoot);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task TokenEndpoint_GrantTypePassword_Success()
|
||||
{
|
||||
var deviceId = "92b9d953-b9b6-4eaf-9d3e-11d57144dfeb";
|
||||
var username = "test+tokenpassword@email.com";
|
||||
|
||||
await _factory.RegisterAsync(new RegisterRequestModel
|
||||
{
|
||||
Email = username,
|
||||
MasterPasswordHash = "master_password_hash"
|
||||
});
|
||||
|
||||
var context = await _factory.Server.PostAsync("/connect/token", new FormUrlEncodedContent(new Dictionary<string, string>
|
||||
{
|
||||
{ "scope", "api offline_access" },
|
||||
{ "client_id", "web" },
|
||||
{ "deviceType", DeviceTypeAsString(DeviceType.FirefoxBrowser) },
|
||||
{ "deviceIdentifier", deviceId },
|
||||
{ "deviceName", "firefox" },
|
||||
{ "grant_type", "password" },
|
||||
{ "username", username },
|
||||
{ "password", "master_password_hash" },
|
||||
}), context => context.Request.Headers.Add("Auth-Email", CoreHelpers.Base64UrlEncodeString(username)));
|
||||
|
||||
using var body = await AssertDefaultTokenBodyAsync(context);
|
||||
var root = body.RootElement;
|
||||
AssertRefreshTokenExists(root);
|
||||
AssertHelper.AssertJsonProperty(root, "ForcePasswordReset", JsonValueKind.False);
|
||||
AssertHelper.AssertJsonProperty(root, "ResetMasterPassword", JsonValueKind.False);
|
||||
var kdf = AssertHelper.AssertJsonProperty(root, "Kdf", JsonValueKind.Number).GetInt32();
|
||||
Assert.Equal(0, kdf);
|
||||
var kdfIterations = AssertHelper.AssertJsonProperty(root, "KdfIterations", JsonValueKind.Number).GetInt32();
|
||||
Assert.Equal(5000, kdfIterations);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task TokenEndpoint_GrantTypePassword_NoAuthEmailHeader_Fails()
|
||||
{
|
||||
var deviceId = "92b9d953-b9b6-4eaf-9d3e-11d57144dfeb";
|
||||
var username = "test+noauthemailheader@email.com";
|
||||
|
||||
await _factory.RegisterAsync(new RegisterRequestModel
|
||||
{
|
||||
Email = username,
|
||||
MasterPasswordHash = "master_password_hash",
|
||||
});
|
||||
|
||||
var context = await _factory.Server.PostAsync("/connect/token", new FormUrlEncodedContent(new Dictionary<string, string>
|
||||
{
|
||||
{ "scope", "api offline_access" },
|
||||
{ "client_id", "web" },
|
||||
{ "deviceType", DeviceTypeAsString(DeviceType.FirefoxBrowser) },
|
||||
{ "deviceIdentifier", deviceId },
|
||||
{ "deviceName", "firefox" },
|
||||
{ "grant_type", "password" },
|
||||
{ "username", username },
|
||||
{ "password", "master_password_hash" },
|
||||
}));
|
||||
|
||||
Assert.Equal(StatusCodes.Status400BadRequest, context.Response.StatusCode);
|
||||
|
||||
var body = await AssertHelper.AssertResponseTypeIs<JsonDocument>(context);
|
||||
var root = body.RootElement;
|
||||
|
||||
var error = AssertHelper.AssertJsonProperty(root, "error", JsonValueKind.String).GetString();
|
||||
Assert.Equal("invalid_grant", error);
|
||||
AssertHelper.AssertJsonProperty(root, "error_description", JsonValueKind.String);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task TokenEndpoint_GrantTypePassword_InvalidBase64AuthEmailHeader_Fails()
|
||||
{
|
||||
var deviceId = "92b9d953-b9b6-4eaf-9d3e-11d57144dfeb";
|
||||
var username = "test+badauthheader@email.com";
|
||||
|
||||
await _factory.RegisterAsync(new RegisterRequestModel
|
||||
{
|
||||
Email = username,
|
||||
MasterPasswordHash = "master_password_hash",
|
||||
});
|
||||
|
||||
var context = await _factory.Server.PostAsync("/connect/token", new FormUrlEncodedContent(new Dictionary<string, string>
|
||||
{
|
||||
{ "scope", "api offline_access" },
|
||||
{ "client_id", "web" },
|
||||
{ "deviceType", DeviceTypeAsString(DeviceType.FirefoxBrowser) },
|
||||
{ "deviceIdentifier", deviceId },
|
||||
{ "deviceName", "firefox" },
|
||||
{ "grant_type", "password" },
|
||||
{ "username", username },
|
||||
{ "password", "master_password_hash" },
|
||||
}), context => context.Request.Headers.Add("Auth-Email", "bad_value"));
|
||||
|
||||
Assert.Equal(StatusCodes.Status400BadRequest, context.Response.StatusCode);
|
||||
|
||||
var body = await AssertHelper.AssertResponseTypeIs<JsonDocument>(context);
|
||||
var root = body.RootElement;
|
||||
|
||||
var error = AssertHelper.AssertJsonProperty(root, "error", JsonValueKind.String).GetString();
|
||||
Assert.Equal("invalid_grant", error);
|
||||
AssertHelper.AssertJsonProperty(root, "error_description", JsonValueKind.String);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task TokenEndpoint_GrantTypePassword_WrongAuthEmailHeader_Fails()
|
||||
{
|
||||
var deviceId = "92b9d953-b9b6-4eaf-9d3e-11d57144dfeb";
|
||||
var username = "test+badauthheader@email.com";
|
||||
|
||||
await _factory.RegisterAsync(new RegisterRequestModel
|
||||
{
|
||||
Email = username,
|
||||
MasterPasswordHash = "master_password_hash",
|
||||
});
|
||||
|
||||
var context = await _factory.Server.PostAsync("/connect/token", new FormUrlEncodedContent(new Dictionary<string, string>
|
||||
{
|
||||
{ "scope", "api offline_access" },
|
||||
{ "client_id", "web" },
|
||||
{ "deviceType", DeviceTypeAsString(DeviceType.FirefoxBrowser) },
|
||||
{ "deviceIdentifier", deviceId },
|
||||
{ "deviceName", "firefox" },
|
||||
{ "grant_type", "password" },
|
||||
{ "username", username },
|
||||
{ "password", "master_password_hash" },
|
||||
}), context => context.Request.Headers.Add("Auth-Email", CoreHelpers.Base64UrlEncodeString("bad_value")));
|
||||
|
||||
Assert.Equal(StatusCodes.Status400BadRequest, context.Response.StatusCode);
|
||||
|
||||
var body = await AssertHelper.AssertResponseTypeIs<JsonDocument>(context);
|
||||
var root = body.RootElement;
|
||||
|
||||
var error = AssertHelper.AssertJsonProperty(root, "error", JsonValueKind.String).GetString();
|
||||
Assert.Equal("invalid_grant", error);
|
||||
AssertHelper.AssertJsonProperty(root, "error_description", JsonValueKind.String);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task TokenEndpoint_GrantTypeRefreshToken_Success()
|
||||
{
|
||||
var deviceId = "5a7b19df-0c9d-46bf-a104-8034b5a17182";
|
||||
var username = "test+tokenrefresh@email.com";
|
||||
|
||||
await _factory.RegisterAsync(new RegisterRequestModel
|
||||
{
|
||||
Email = username,
|
||||
MasterPasswordHash = "master_password_hash",
|
||||
});
|
||||
|
||||
var (_, refreshToken) = await _factory.TokenFromPasswordAsync(username, "master_password_hash", deviceId);
|
||||
|
||||
var context = await _factory.Server.PostAsync("/connect/token", new FormUrlEncodedContent(new Dictionary<string, string>
|
||||
{
|
||||
{ "grant_type", "refresh_token" },
|
||||
{ "client_id", "web" },
|
||||
{ "refresh_token", refreshToken },
|
||||
}));
|
||||
|
||||
using var body = await AssertDefaultTokenBodyAsync(context);
|
||||
AssertRefreshTokenExists(body.RootElement);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task TokenEndpoint_GrantTypeClientCredentials_Success()
|
||||
{
|
||||
var username = "test+tokenclientcredentials@email.com";
|
||||
var deviceId = "8f14a393-edfe-40ba-8c67-a856cb89c509";
|
||||
|
||||
await _factory.RegisterAsync(new RegisterRequestModel
|
||||
{
|
||||
Email = username,
|
||||
MasterPasswordHash = "master_password_hash",
|
||||
});
|
||||
|
||||
var database = _factory.GetDatabaseContext();
|
||||
var user = await database.Users
|
||||
.FirstAsync(u => u.Email == username);
|
||||
|
||||
var context = await _factory.Server.PostAsync("/connect/token", new FormUrlEncodedContent(new Dictionary<string, string>
|
||||
{
|
||||
{ "grant_type", "client_credentials" },
|
||||
{ "client_id", $"user.{user.Id}" },
|
||||
{ "client_secret", user.ApiKey },
|
||||
{ "scope", "api" },
|
||||
{ "DeviceIdentifier", deviceId },
|
||||
{ "DeviceType", DeviceTypeAsString(DeviceType.FirefoxBrowser) },
|
||||
{ "DeviceName", "firefox" },
|
||||
}));
|
||||
|
||||
await AssertDefaultTokenBodyAsync(context, "api");
|
||||
}
|
||||
|
||||
[Theory, BitAutoData]
|
||||
public async Task TokenEndpoint_GrantTypeClientCredentials_AsOrganization_Success(Organization organization, OrganizationApiKey organizationApiKey)
|
||||
{
|
||||
var orgRepo = _factory.Services.GetRequiredService<IOrganizationRepository>();
|
||||
organization = await orgRepo.CreateAsync(organization);
|
||||
organizationApiKey.OrganizationId = organization.Id;
|
||||
organizationApiKey.Type = OrganizationApiKeyType.Default;
|
||||
|
||||
var orgApiKeyRepo = _factory.Services.GetRequiredService<IOrganizationApiKeyRepository>();
|
||||
await orgApiKeyRepo.CreateAsync(organizationApiKey);
|
||||
|
||||
var context = await _factory.Server.PostAsync("/connect/token", new FormUrlEncodedContent(new Dictionary<string, string>
|
||||
{
|
||||
{ "grant_type", "client_credentials" },
|
||||
{ "client_id", $"organization.{organization.Id}" },
|
||||
{ "client_secret", organizationApiKey.ApiKey },
|
||||
{ "scope", "api.organization" },
|
||||
}));
|
||||
|
||||
Assert.Equal(StatusCodes.Status200OK, context.Response.StatusCode);
|
||||
|
||||
await AssertDefaultTokenBodyAsync(context, "api.organization");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task TokenEndpoint_GrantTypeClientCredentials_AsOrganization_BadOrgId_Fails()
|
||||
{
|
||||
var context = await _factory.Server.PostAsync("/connect/token", new FormUrlEncodedContent(new Dictionary<string, string>
|
||||
{
|
||||
{ "grant_type", "client_credentials" },
|
||||
{ "client_id", "organization.bad_guid_zz&" },
|
||||
{ "client_secret", "something" },
|
||||
{ "scope", "api.organization" },
|
||||
}));
|
||||
|
||||
Assert.Equal(StatusCodes.Status400BadRequest, context.Response.StatusCode);
|
||||
|
||||
var errorBody = await AssertHelper.AssertResponseTypeIs<JsonDocument>(context);
|
||||
var error = AssertHelper.AssertJsonProperty(errorBody.RootElement, "error", JsonValueKind.String).GetString();
|
||||
Assert.Equal("invalid_client", error);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This test currently does not test any code that is not covered by other tests but
|
||||
/// it shows that we probably have some dead code in <see cref="Core.IdentityServer.ClientStore"/>
|
||||
/// for installation, organization, and user they split on a <c>'.'</c> but have already checked that at least one
|
||||
/// <c>'.'</c> exists in the <c>client_id</c> by checking it with <see cref="string.StartsWith(string)"/>
|
||||
/// I believe that idParts.Length > 1 will ALWAYS return true
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public async Task TokenEndpoint_GrantTypeClientCredentials_AsOrganization_NoIdPart_Fails()
|
||||
{
|
||||
var context = await _factory.Server.PostAsync("/connect/token", new FormUrlEncodedContent(new Dictionary<string, string>
|
||||
{
|
||||
{ "grant_type", "client_credentials" },
|
||||
{ "client_id", "organization." },
|
||||
{ "client_secret", "something" },
|
||||
{ "scope", "api.organization" },
|
||||
}));
|
||||
|
||||
Assert.Equal(StatusCodes.Status400BadRequest, context.Response.StatusCode);
|
||||
|
||||
var errorBody = await AssertHelper.AssertResponseTypeIs<JsonDocument>(context);
|
||||
var error = AssertHelper.AssertJsonProperty(errorBody.RootElement, "error", JsonValueKind.String).GetString();
|
||||
Assert.Equal("invalid_client", error);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task TokenEndpoint_GrantTypeClientCredentials_AsOrganization_OrgDoesNotExist_Fails()
|
||||
{
|
||||
var context = await _factory.Server.PostAsync("/connect/token", new FormUrlEncodedContent(new Dictionary<string, string>
|
||||
{
|
||||
{ "grant_type", "client_credentials" },
|
||||
{ "client_id", $"organization.{Guid.NewGuid()}" },
|
||||
{ "client_secret", "something" },
|
||||
{ "scope", "api.organization" },
|
||||
}));
|
||||
|
||||
Assert.Equal(StatusCodes.Status400BadRequest, context.Response.StatusCode);
|
||||
|
||||
var errorBody = await AssertHelper.AssertResponseTypeIs<JsonDocument>(context);
|
||||
var error = AssertHelper.AssertJsonProperty(errorBody.RootElement, "error", JsonValueKind.String).GetString();
|
||||
Assert.Equal("invalid_client", error);
|
||||
}
|
||||
|
||||
[Theory, BitAutoData]
|
||||
public async Task TokenEndpoint_GrantTypeClientCredentials_AsInstallation_InstallationExists_Succeeds(Installation installation)
|
||||
{
|
||||
var installationRepo = _factory.Services.GetRequiredService<IInstallationRepository>();
|
||||
installation = await installationRepo.CreateAsync(installation);
|
||||
|
||||
var context = await _factory.Server.PostAsync("/connect/token", new FormUrlEncodedContent(new Dictionary<string, string>
|
||||
{
|
||||
{ "grant_type", "client_credentials" },
|
||||
{ "client_id", $"installation.{installation.Id}" },
|
||||
{ "client_secret", installation.Key },
|
||||
{ "scope", "api.push" },
|
||||
}));
|
||||
|
||||
Assert.Equal(StatusCodes.Status200OK, context.Response.StatusCode);
|
||||
await AssertDefaultTokenBodyAsync(context, "api.push", 24 * SecondsInHour);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task TokenEndpoint_GrantTypeClientCredentials_AsInstallation_InstallationDoesNotExist_Fails()
|
||||
{
|
||||
var context = await _factory.Server.PostAsync("/connect/token", new FormUrlEncodedContent(new Dictionary<string, string>
|
||||
{
|
||||
{ "grant_type", "client_credentials" },
|
||||
{ "client_id", $"installation.{Guid.NewGuid()}" },
|
||||
{ "client_secret", "something" },
|
||||
{ "scope", "api.push" },
|
||||
}));
|
||||
|
||||
Assert.Equal(StatusCodes.Status400BadRequest, context.Response.StatusCode);
|
||||
|
||||
var errorBody = await AssertHelper.AssertResponseTypeIs<JsonDocument>(context);
|
||||
var error = AssertHelper.AssertJsonProperty(errorBody.RootElement, "error", JsonValueKind.String).GetString();
|
||||
Assert.Equal("invalid_client", error);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task TokenEndpoint_GrantTypeClientCredentials_AsInstallation_BadInsallationId_Fails()
|
||||
{
|
||||
var context = await _factory.Server.PostAsync("/connect/token", new FormUrlEncodedContent(new Dictionary<string, string>
|
||||
{
|
||||
{ "grant_type", "client_credentials" },
|
||||
{ "client_id", "organization.bad_guid_zz&" },
|
||||
{ "client_secret", "something" },
|
||||
{ "scope", "api.organization" },
|
||||
}));
|
||||
|
||||
Assert.Equal(StatusCodes.Status400BadRequest, context.Response.StatusCode);
|
||||
|
||||
var errorBody = await AssertHelper.AssertResponseTypeIs<JsonDocument>(context);
|
||||
var error = AssertHelper.AssertJsonProperty(errorBody.RootElement, "error", JsonValueKind.String).GetString();
|
||||
Assert.Equal("invalid_client", error);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="TokenEndpoint_GrantTypeClientCredentials_AsOrganization_NoIdPart_Fails"/>
|
||||
[Fact]
|
||||
public async Task TokenEndpoint_GrantTypeClientCredentials_AsInstallation_NoIdPart_Fails()
|
||||
{
|
||||
var context = await _factory.Server.PostAsync("/connect/token", new FormUrlEncodedContent(new Dictionary<string, string>
|
||||
{
|
||||
{ "grant_type", "client_credentials" },
|
||||
{ "client_id", "installation." },
|
||||
{ "client_secret", "something" },
|
||||
{ "scope", "api.push" },
|
||||
}));
|
||||
|
||||
Assert.Equal(StatusCodes.Status400BadRequest, context.Response.StatusCode);
|
||||
|
||||
var errorBody = await AssertHelper.AssertResponseTypeIs<JsonDocument>(context);
|
||||
var error = AssertHelper.AssertJsonProperty(errorBody.RootElement, "error", JsonValueKind.String).GetString();
|
||||
Assert.Equal("invalid_client", error);
|
||||
}
|
||||
|
||||
private static string DeviceTypeAsString(DeviceType deviceType)
|
||||
{
|
||||
return ((int)deviceType).ToString();
|
||||
}
|
||||
|
||||
private static async Task<JsonDocument> AssertDefaultTokenBodyAsync(HttpContext httpContext, string expectedScope = "api offline_access", int expectedExpiresIn = SecondsInHour * 1)
|
||||
{
|
||||
var body = await AssertHelper.AssertResponseTypeIs<JsonDocument>(httpContext);
|
||||
var root = body.RootElement;
|
||||
|
||||
Assert.Equal(JsonValueKind.Object, root.ValueKind);
|
||||
AssertAccessTokenExists(root);
|
||||
AssertExpiresIn(root, expectedExpiresIn);
|
||||
AssertTokenType(root);
|
||||
AssertScope(root, expectedScope);
|
||||
return body;
|
||||
}
|
||||
|
||||
private static void AssertTokenType(JsonElement tokenResponse)
|
||||
{
|
||||
var tokenTypeProperty = AssertHelper.AssertJsonProperty(tokenResponse, "token_type", JsonValueKind.String).GetString();
|
||||
Assert.Equal("Bearer", tokenTypeProperty);
|
||||
}
|
||||
|
||||
private static int AssertExpiresIn(JsonElement tokenResponse, int expectedExpiresIn = 3600)
|
||||
{
|
||||
var expiresIn = AssertHelper.AssertJsonProperty(tokenResponse, "expires_in", JsonValueKind.Number).GetInt32();
|
||||
Assert.Equal(expectedExpiresIn, expiresIn);
|
||||
return expiresIn;
|
||||
}
|
||||
|
||||
private static string AssertAccessTokenExists(JsonElement tokenResponse)
|
||||
{
|
||||
return AssertHelper.AssertJsonProperty(tokenResponse, "access_token", JsonValueKind.String).GetString();
|
||||
}
|
||||
|
||||
private static string AssertRefreshTokenExists(JsonElement tokenResponse)
|
||||
{
|
||||
return AssertHelper.AssertJsonProperty(tokenResponse, "refresh_token", JsonValueKind.String).GetString();
|
||||
}
|
||||
|
||||
private static string AssertScopeExists(JsonElement tokenResponse)
|
||||
{
|
||||
return AssertHelper.AssertJsonProperty(tokenResponse, "scope", JsonValueKind.String).GetString();
|
||||
}
|
||||
|
||||
private static void AssertScope(JsonElement tokenResponse, string expectedScope)
|
||||
{
|
||||
var actualScope = AssertScopeExists(tokenResponse);
|
||||
Assert.Equal(expectedScope, actualScope);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,29 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
|
||||
<PropertyGroup>
|
||||
<IsPackable>false</IsPackable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="coverlet.collector" Version="3.0.3">
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="5.0.15" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.6.1" />
|
||||
<PackageReference Include="NSubstitute" Version="4.2.2" />
|
||||
<PackageReference Include="xunit" Version="2.4.1" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.2">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="AutoFixture.Xunit2" Version="4.14.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\src\Identity\Identity.csproj" />
|
||||
<ProjectReference Include="..\Common\Common.csproj" />
|
||||
<ProjectReference Include="..\IntegrationTestCommon\IntegrationTestCommon.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
12
test/Identity.IntegrationTest/Properties/launchSettings.json
Normal file
12
test/Identity.IntegrationTest/Properties/launchSettings.json
Normal file
@ -0,0 +1,12 @@
|
||||
{
|
||||
"profiles": {
|
||||
"Identity.IntegrationTest": {
|
||||
"commandName": "Project",
|
||||
"launchBrowser": false,
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
},
|
||||
"applicationUrl": "https://localhost:55088;http://localhost:55089"
|
||||
}
|
||||
}
|
||||
}
|
69
test/Identity.IntegrationTest/openid-configuration.json
Normal file
69
test/Identity.IntegrationTest/openid-configuration.json
Normal file
@ -0,0 +1,69 @@
|
||||
{
|
||||
"issuer": "http://localhost",
|
||||
"jwks_uri": "http://localhost:33656/.well-known/openid-configuration/jwks",
|
||||
"authorization_endpoint": "http://localhost:33656/connect/authorize",
|
||||
"token_endpoint": "http://localhost:33656/connect/token",
|
||||
"device_authorization_endpoint": "http://localhost:33656/connect/deviceauthorization",
|
||||
"scopes_supported": [
|
||||
"api",
|
||||
"api.push",
|
||||
"api.licensing",
|
||||
"api.organization",
|
||||
"api.installation",
|
||||
"internal",
|
||||
"offline_access"
|
||||
],
|
||||
"claims_supported": [
|
||||
"name",
|
||||
"email",
|
||||
"email_verified",
|
||||
"sstamp",
|
||||
"premium",
|
||||
"device",
|
||||
"orgowner",
|
||||
"orgadmin",
|
||||
"orgmanager",
|
||||
"orguser",
|
||||
"orgcustom",
|
||||
"providerprovideradmin",
|
||||
"providerserviceuser",
|
||||
"sub"
|
||||
],
|
||||
"grant_types_supported": [
|
||||
"authorization_code",
|
||||
"client_credentials",
|
||||
"refresh_token",
|
||||
"implicit",
|
||||
"password",
|
||||
"urn:ietf:params:oauth:grant-type:device_code"
|
||||
],
|
||||
"response_types_supported": [
|
||||
"code",
|
||||
"token",
|
||||
"id_token",
|
||||
"id_token token",
|
||||
"code id_token",
|
||||
"code token",
|
||||
"code id_token token"
|
||||
],
|
||||
"response_modes_supported": [
|
||||
"form_post",
|
||||
"query",
|
||||
"fragment"
|
||||
],
|
||||
"token_endpoint_auth_methods_supported": [
|
||||
"client_secret_basic",
|
||||
"client_secret_post"
|
||||
],
|
||||
"id_token_signing_alg_values_supported": [
|
||||
"RS256"
|
||||
],
|
||||
"subject_types_supported": [
|
||||
"public"
|
||||
],
|
||||
"code_challenge_methods_supported": [
|
||||
"plain",
|
||||
"S256"
|
||||
],
|
||||
"request_parameter_supported": true
|
||||
}
|
3768
test/Identity.IntegrationTest/packages.lock.json
Normal file
3768
test/Identity.IntegrationTest/packages.lock.json
Normal file
File diff suppressed because it is too large
Load Diff
@ -3534,26 +3534,26 @@
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Azure.Messaging.EventGrid": "4.7.0",
|
||||
"CommCore": "1.47.1",
|
||||
"Core": "1.47.1",
|
||||
"CommCore": "1.48.1",
|
||||
"Core": "1.48.1",
|
||||
"Microsoft.AspNetCore.Mvc.NewtonsoftJson": "5.0.9",
|
||||
"SharedWeb": "1.47.1",
|
||||
"SharedWeb": "1.48.1",
|
||||
"Swashbuckle.AspNetCore": "6.2.3"
|
||||
}
|
||||
},
|
||||
"commcore": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Core": "1.47.1"
|
||||
"Core": "1.48.1"
|
||||
}
|
||||
},
|
||||
"common": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Api": "1.47.1",
|
||||
"Api": "1.48.1",
|
||||
"AutoFixture.AutoNSubstitute": "4.14.0",
|
||||
"AutoFixture.Xunit2": "4.14.0",
|
||||
"Core": "1.47.1",
|
||||
"Core": "1.48.1",
|
||||
"Kralizek.AutoFixture.Extensions.MockHttp": "1.2.0",
|
||||
"Microsoft.NET.Test.Sdk": "16.6.1",
|
||||
"NSubstitute": "4.2.2",
|
||||
@ -3602,14 +3602,14 @@
|
||||
"identity": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Core": "1.47.1",
|
||||
"SharedWeb": "1.47.1"
|
||||
"Core": "1.48.1",
|
||||
"SharedWeb": "1.48.1"
|
||||
}
|
||||
},
|
||||
"infrastructure.dapper": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Core": "1.47.1",
|
||||
"Core": "1.48.1",
|
||||
"Dapper": "2.0.123",
|
||||
"System.Data.SqlClient": "4.8.3"
|
||||
}
|
||||
@ -3618,7 +3618,7 @@
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"AutoMapper.Extensions.Microsoft.DependencyInjection": "8.0.1",
|
||||
"Core": "1.47.1",
|
||||
"Core": "1.48.1",
|
||||
"Microsoft.EntityFrameworkCore.Relational": "5.0.12",
|
||||
"Npgsql.EntityFrameworkCore.PostgreSQL": "5.0.2",
|
||||
"Pomelo.EntityFrameworkCore.MySql": "5.0.3",
|
||||
@ -3628,9 +3628,9 @@
|
||||
"sharedweb": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Core": "1.47.1",
|
||||
"Infrastructure.Dapper": "1.47.1",
|
||||
"Infrastructure.EntityFramework": "1.47.1"
|
||||
"Core": "1.48.1",
|
||||
"Infrastructure.Dapper": "1.48.1",
|
||||
"Infrastructure.EntityFramework": "1.48.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,49 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Net.Http;
|
||||
using System.Net.Http.Json;
|
||||
using System.Text.Json;
|
||||
using System.Threading.Tasks;
|
||||
using Bit.Core.Enums;
|
||||
using Bit.Core.Models.Api.Request.Accounts;
|
||||
using Bit.Core.Utilities;
|
||||
using Bit.Identity;
|
||||
using Bit.Test.Common.Helpers;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
|
||||
namespace Bit.IntegrationTestCommon.Factories
|
||||
{
|
||||
public class IdentityApplicationFactory : WebApplicationFactoryBase<Startup>
|
||||
{
|
||||
public const string DefaultDeviceIdentifier = "92b9d953-b9b6-4eaf-9d3e-11d57144dfeb";
|
||||
|
||||
public async Task<HttpContext> RegisterAsync(RegisterRequestModel model)
|
||||
{
|
||||
return await Server.PostAsync("/accounts/register", JsonContent.Create(model));
|
||||
}
|
||||
|
||||
public async Task<(string Token, string RefreshToken)> TokenFromPasswordAsync(string username,
|
||||
string password,
|
||||
string deviceIdentifier = DefaultDeviceIdentifier,
|
||||
string clientId = "web",
|
||||
DeviceType deviceType = DeviceType.FirefoxBrowser,
|
||||
string deviceName = "firefox")
|
||||
{
|
||||
var context = await Server.PostAsync("/connect/token", new FormUrlEncodedContent(new Dictionary<string, string>
|
||||
{
|
||||
{ "scope", "api offline_access" },
|
||||
{ "client_id", clientId },
|
||||
{ "deviceType", ((int)deviceType).ToString() },
|
||||
{ "deviceIdentifier", deviceIdentifier },
|
||||
{ "deviceName", deviceName },
|
||||
{ "grant_type", "password" },
|
||||
{ "username", username },
|
||||
{ "password", password },
|
||||
}), context => context.Request.Headers.Add("Auth-Email", CoreHelpers.Base64UrlEncodeString(username)));
|
||||
|
||||
using var body = await AssertHelper.AssertResponseTypeIs<JsonDocument>(context);
|
||||
var root = body.RootElement;
|
||||
|
||||
return (root.GetProperty("access_token").GetString(), root.GetProperty("refresh_token").GetString());
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,102 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using AspNetCoreRateLimit;
|
||||
using Bit.Core.Repositories;
|
||||
using Bit.Core.Services;
|
||||
using Bit.Infrastructure.EntityFramework.Repositories;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.AspNetCore.Mvc.Testing;
|
||||
using Microsoft.AspNetCore.TestHost;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
namespace Bit.IntegrationTestCommon.Factories
|
||||
{
|
||||
public static class FactoryConstants
|
||||
{
|
||||
public const string DefaultDatabaseName = "test_database";
|
||||
public const string WhitelistedIp = "1.1.1.1";
|
||||
}
|
||||
|
||||
public abstract class WebApplicationFactoryBase<T> : WebApplicationFactory<T>
|
||||
where T : class
|
||||
{
|
||||
/// <summary>
|
||||
/// The database name to use for this instance of the factory. By default it will use a shared database name so all instances will connect to the same database during it's lifetime.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This will need to be set BEFORE using the <c>Server</c> property
|
||||
/// </remarks>
|
||||
public string DatabaseName { get; set; } = FactoryConstants.DefaultDatabaseName;
|
||||
|
||||
/// <summary>
|
||||
/// Configure the web host to use an EF in memory database
|
||||
/// </summary>
|
||||
protected override void ConfigureWebHost(IWebHostBuilder builder)
|
||||
{
|
||||
builder.ConfigureAppConfiguration(c =>
|
||||
{
|
||||
c.AddInMemoryCollection(new Dictionary<string, string>
|
||||
{
|
||||
// Manually insert a EF provider so that ConfigureServices will add EF repositories but we will override
|
||||
// DbContextOptions to use an in memory database
|
||||
{ "globalSettings:databaseProvider", "postgres" },
|
||||
{ "globalSettings:postgreSql:connectionString", "Host=localhost;Username=test;Password=test;Database=test" },
|
||||
});
|
||||
});
|
||||
|
||||
builder.ConfigureTestServices(services =>
|
||||
{
|
||||
var dbContextOptions = services.First(sd => sd.ServiceType == typeof(DbContextOptions<DatabaseContext>));
|
||||
services.Remove(dbContextOptions);
|
||||
services.AddScoped(_ =>
|
||||
{
|
||||
return new DbContextOptionsBuilder<DatabaseContext>()
|
||||
.UseInMemoryDatabase(DatabaseName)
|
||||
.Options;
|
||||
});
|
||||
|
||||
// QUESTION: The normal licensing service should run fine on developer machines but not in CI
|
||||
// should we have a fork here to leave the normal service for developers?
|
||||
// TODO: Eventually add the license file to CI
|
||||
var licensingService = services.First(sd => sd.ServiceType == typeof(ILicensingService));
|
||||
services.Remove(licensingService);
|
||||
services.AddSingleton<ILicensingService, NoopLicensingService>();
|
||||
|
||||
// FUTURE CONSIDERATION: Add way to run this self hosted/cloud, for now it is cloud only
|
||||
var pushRegistrationService = services.First(sd => sd.ServiceType == typeof(IPushRegistrationService));
|
||||
services.Remove(pushRegistrationService);
|
||||
services.AddSingleton<IPushRegistrationService, NoopPushRegistrationService>();
|
||||
|
||||
// Even though we are cloud we currently set this up as cloud, we can use the EF/selfhosted service
|
||||
// instead of using Noop for this service
|
||||
// TODO: Install and use azurite in CI pipeline
|
||||
var eventWriteService = services.First(sd => sd.ServiceType == typeof(IEventWriteService));
|
||||
services.Remove(eventWriteService);
|
||||
services.AddSingleton<IEventWriteService, RepositoryEventWriteService>();
|
||||
|
||||
var eventRepositoryService = services.First(sd => sd.ServiceType == typeof(IEventRepository));
|
||||
services.Remove(eventRepositoryService);
|
||||
services.AddSingleton<IEventRepository, EventRepository>();
|
||||
|
||||
// Our Rate limiter works so well that it begins to fail tests unless we carve out
|
||||
// one whitelisted ip. We should still test the rate limiter though and they should change the Ip
|
||||
// to something that is NOT whitelisted
|
||||
services.Configure<IpRateLimitOptions>(options =>
|
||||
{
|
||||
options.IpWhitelist = new List<string>
|
||||
{
|
||||
FactoryConstants.WhitelistedIp,
|
||||
};
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
public DatabaseContext GetDatabaseContext()
|
||||
{
|
||||
var scope = Services.CreateScope();
|
||||
return scope.ServiceProvider.GetRequiredService<DatabaseContext>();
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,59 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.TestHost;
|
||||
using Microsoft.Extensions.Primitives;
|
||||
|
||||
namespace Bit.IntegrationTestCommon.Factories
|
||||
{
|
||||
public static class WebApplicationFactoryExtensions
|
||||
{
|
||||
private static async Task<HttpContext> SendAsync(this TestServer server,
|
||||
HttpMethod method,
|
||||
string requestUri,
|
||||
HttpContent content = null,
|
||||
Action<HttpContext> extraConfiguration = null)
|
||||
{
|
||||
return await server.SendAsync(httpContext =>
|
||||
{
|
||||
// Automatically set the whitelisted IP so normal tests do not run into rate limit issues
|
||||
// to test rate limiter, use the extraConfiguration parameter to set Connection.RemoteIpAddress
|
||||
// it runs after this so it will take precedence.
|
||||
httpContext.Connection.RemoteIpAddress = IPAddress.Parse(FactoryConstants.WhitelistedIp);
|
||||
|
||||
httpContext.Request.Path = new PathString(requestUri);
|
||||
httpContext.Request.Method = method.Method;
|
||||
|
||||
if (content != null)
|
||||
{
|
||||
foreach (var header in content.Headers)
|
||||
{
|
||||
httpContext.Request.Headers.Add(header.Key, new StringValues(header.Value.ToArray()));
|
||||
}
|
||||
|
||||
httpContext.Request.Body = content.ReadAsStream();
|
||||
}
|
||||
|
||||
extraConfiguration?.Invoke(httpContext);
|
||||
});
|
||||
}
|
||||
public static Task<HttpContext> PostAsync(this TestServer server,
|
||||
string requestUri,
|
||||
HttpContent content,
|
||||
Action<HttpContext> extraConfiguration = null)
|
||||
=> SendAsync(server, HttpMethod.Post, requestUri, content, extraConfiguration);
|
||||
public static Task<HttpContext> GetAsync(this TestServer server,
|
||||
string requestUri,
|
||||
Action<HttpContext> extraConfiguration = null)
|
||||
=> SendAsync(server, HttpMethod.Get, requestUri, content: null, extraConfiguration);
|
||||
public static async Task<string> ReadBodyAsStringAsync(this HttpContext context)
|
||||
{
|
||||
using var sr = new StreamReader(context.Response.Body);
|
||||
return await sr.ReadToEndAsync();
|
||||
}
|
||||
}
|
||||
}
|
17
test/IntegrationTestCommon/IntegrationTestCommon.csproj
Normal file
17
test/IntegrationTestCommon/IntegrationTestCommon.csproj
Normal file
@ -0,0 +1,17 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<IsPackable>false</IsPackable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="5.0.15" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.InMemory" Version="5.0.15" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration" Version="5.0.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\src\Identity\Identity.csproj" />
|
||||
<ProjectReference Include="..\Common\Common.csproj" />
|
||||
</ItemGroup>
|
||||
</Project>
|
3744
test/IntegrationTestCommon/packages.lock.json
Normal file
3744
test/IntegrationTestCommon/packages.lock.json
Normal file
File diff suppressed because it is too large
Load Diff
@ -13,6 +13,10 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Common", "Common\Common.csp
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Billing.Test", "Billing.Test\Billing.Test.csproj", "{8CD044FE-3FED-4F29-858C-B06BCE70EAA6}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Identity.IntegrationTest", "Identity.IntegrationTest\Identity.IntegrationTest.csproj", "{E2BB0D89-4570-43AB-A2E7-C8069AD90E6A}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "IntegrationTestCommon", "IntegrationTestCommon\IntegrationTestCommon.csproj", "{41188BB8-1FAF-45F6-8DC8-F316B8A6C56B}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
@ -86,5 +90,29 @@ Global
|
||||
{8CD044FE-3FED-4F29-858C-B06BCE70EAA6}.Release|x64.Build.0 = Release|Any CPU
|
||||
{8CD044FE-3FED-4F29-858C-B06BCE70EAA6}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{8CD044FE-3FED-4F29-858C-B06BCE70EAA6}.Release|x86.Build.0 = Release|Any CPU
|
||||
{E2BB0D89-4570-43AB-A2E7-C8069AD90E6A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{E2BB0D89-4570-43AB-A2E7-C8069AD90E6A}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{E2BB0D89-4570-43AB-A2E7-C8069AD90E6A}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{E2BB0D89-4570-43AB-A2E7-C8069AD90E6A}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{E2BB0D89-4570-43AB-A2E7-C8069AD90E6A}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{E2BB0D89-4570-43AB-A2E7-C8069AD90E6A}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{E2BB0D89-4570-43AB-A2E7-C8069AD90E6A}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{E2BB0D89-4570-43AB-A2E7-C8069AD90E6A}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{E2BB0D89-4570-43AB-A2E7-C8069AD90E6A}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{E2BB0D89-4570-43AB-A2E7-C8069AD90E6A}.Release|x64.Build.0 = Release|Any CPU
|
||||
{E2BB0D89-4570-43AB-A2E7-C8069AD90E6A}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{E2BB0D89-4570-43AB-A2E7-C8069AD90E6A}.Release|x86.Build.0 = Release|Any CPU
|
||||
{41188BB8-1FAF-45F6-8DC8-F316B8A6C56B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{41188BB8-1FAF-45F6-8DC8-F316B8A6C56B}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{41188BB8-1FAF-45F6-8DC8-F316B8A6C56B}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{41188BB8-1FAF-45F6-8DC8-F316B8A6C56B}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{41188BB8-1FAF-45F6-8DC8-F316B8A6C56B}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{41188BB8-1FAF-45F6-8DC8-F316B8A6C56B}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{41188BB8-1FAF-45F6-8DC8-F316B8A6C56B}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{41188BB8-1FAF-45F6-8DC8-F316B8A6C56B}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{41188BB8-1FAF-45F6-8DC8-F316B8A6C56B}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{41188BB8-1FAF-45F6-8DC8-F316B8A6C56B}.Release|x64.Build.0 = Release|Any CPU
|
||||
{41188BB8-1FAF-45F6-8DC8-F316B8A6C56B}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{41188BB8-1FAF-45F6-8DC8-F316B8A6C56B}.Release|x86.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
|
@ -3369,17 +3369,17 @@
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Azure.Messaging.EventGrid": "4.7.0",
|
||||
"CommCore": "1.47.1",
|
||||
"Core": "1.47.1",
|
||||
"CommCore": "1.48.1",
|
||||
"Core": "1.48.1",
|
||||
"Microsoft.AspNetCore.Mvc.NewtonsoftJson": "5.0.9",
|
||||
"SharedWeb": "1.47.1",
|
||||
"SharedWeb": "1.48.1",
|
||||
"Swashbuckle.AspNetCore": "6.2.3"
|
||||
}
|
||||
},
|
||||
"commcore": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Core": "1.47.1"
|
||||
"Core": "1.48.1"
|
||||
}
|
||||
},
|
||||
"core": {
|
||||
@ -3424,7 +3424,7 @@
|
||||
"infrastructure.dapper": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Core": "1.47.1",
|
||||
"Core": "1.48.1",
|
||||
"Dapper": "2.0.123",
|
||||
"System.Data.SqlClient": "4.8.3"
|
||||
}
|
||||
@ -3433,7 +3433,7 @@
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"AutoMapper.Extensions.Microsoft.DependencyInjection": "8.0.1",
|
||||
"Core": "1.47.1",
|
||||
"Core": "1.48.1",
|
||||
"Microsoft.EntityFrameworkCore.Relational": "5.0.12",
|
||||
"Npgsql.EntityFrameworkCore.PostgreSQL": "5.0.2",
|
||||
"Pomelo.EntityFrameworkCore.MySql": "5.0.3",
|
||||
@ -3443,9 +3443,9 @@
|
||||
"sharedweb": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Core": "1.47.1",
|
||||
"Infrastructure.Dapper": "1.47.1",
|
||||
"Infrastructure.EntityFramework": "1.47.1"
|
||||
"Core": "1.48.1",
|
||||
"Infrastructure.Dapper": "1.48.1",
|
||||
"Infrastructure.EntityFramework": "1.48.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3369,17 +3369,17 @@
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Azure.Messaging.EventGrid": "4.7.0",
|
||||
"CommCore": "1.47.1",
|
||||
"Core": "1.47.1",
|
||||
"CommCore": "1.48.1",
|
||||
"Core": "1.48.1",
|
||||
"Microsoft.AspNetCore.Mvc.NewtonsoftJson": "5.0.9",
|
||||
"SharedWeb": "1.47.1",
|
||||
"SharedWeb": "1.48.1",
|
||||
"Swashbuckle.AspNetCore": "6.2.3"
|
||||
}
|
||||
},
|
||||
"commcore": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Core": "1.47.1"
|
||||
"Core": "1.48.1"
|
||||
}
|
||||
},
|
||||
"core": {
|
||||
@ -3424,7 +3424,7 @@
|
||||
"infrastructure.dapper": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Core": "1.47.1",
|
||||
"Core": "1.48.1",
|
||||
"Dapper": "2.0.123",
|
||||
"System.Data.SqlClient": "4.8.3"
|
||||
}
|
||||
@ -3433,7 +3433,7 @@
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"AutoMapper.Extensions.Microsoft.DependencyInjection": "8.0.1",
|
||||
"Core": "1.47.1",
|
||||
"Core": "1.48.1",
|
||||
"Microsoft.EntityFrameworkCore.Relational": "5.0.12",
|
||||
"Npgsql.EntityFrameworkCore.PostgreSQL": "5.0.2",
|
||||
"Pomelo.EntityFrameworkCore.MySql": "5.0.3",
|
||||
@ -3443,9 +3443,9 @@
|
||||
"sharedweb": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Core": "1.47.1",
|
||||
"Infrastructure.Dapper": "1.47.1",
|
||||
"Infrastructure.EntityFramework": "1.47.1"
|
||||
"Core": "1.48.1",
|
||||
"Infrastructure.Dapper": "1.48.1",
|
||||
"Infrastructure.EntityFramework": "1.48.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3282,7 +3282,7 @@
|
||||
"migrator": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Core": "1.46.2",
|
||||
"Core": "1.48.1",
|
||||
"Microsoft.Extensions.Logging": "5.0.0",
|
||||
"dbup-sqlserver": "4.4.0"
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user