diff --git a/cli-windows/add-firewall-rules-for-sts-auth-thru-docker.ps1 b/cli-windows/add-firewall-rules-for-sts-auth-thru-docker.ps1
index be63d8a25..865f24067 100644
--- a/cli-windows/add-firewall-rules-for-sts-auth-thru-docker.ps1
+++ b/cli-windows/add-firewall-rules-for-sts-auth-thru-docker.ps1
@@ -21,6 +21,6 @@ try {
Write-Host "Rule found"
}
catch [Exception] {
- New-NetFirewallRule -DisplayName eShopOnContainers-Inbound -Confirm -Description "eShopOnContainers Inbound Rule for port range 5100-5105" -LocalAddress Any -LocalPort 5100-5105 -Protocol tcp -RemoteAddress Any -RemotePort Any -Direction Inbound
- New-NetFirewallRule -DisplayName eShopOnContainers-Outbound -Confirm -Description "eShopOnContainers Outbound Rule for port range 5100-5105" -LocalAddress Any -LocalPort 5100-5105 -Protocol tcp -RemoteAddress Any -RemotePort Any -Direction Outbound
+ New-NetFirewallRule -DisplayName eShopOnContainers-Inbound -Confirm -Description "eShopOnContainers Inbound Rule for port range 5100-5105" -LocalAddress Any -LocalPort 5100-5110 -Protocol tcp -RemoteAddress Any -RemotePort Any -Direction Inbound
+ New-NetFirewallRule -DisplayName eShopOnContainers-Outbound -Confirm -Description "eShopOnContainers Outbound Rule for port range 5100-5105" -LocalAddress Any -LocalPort 5100-5110 -Protocol tcp -RemoteAddress Any -RemotePort Any -Direction Outbound
}
\ No newline at end of file
diff --git a/docker-compose-windows.override.yml b/docker-compose-windows.override.yml
index c3733c164..45b2db748 100644
--- a/docker-compose-windows.override.yml
+++ b/docker-compose-windows.override.yml
@@ -80,4 +80,19 @@ services:
- SA_PASSWORD=Pass@word
- ACCEPT_EULA=Y
ports:
- - "5433:1433"
\ No newline at end of file
+ - "5433:1433"
+
+ nosql.data:
+ ports:
+ - "27017:27017"
+
+ locations.api:
+ environment:
+ - ASPNETCORE_ENVIRONMENT=Development
+ - ASPNETCORE_URLS=http://0.0.0.0:80
+ - ConnectionString=mongodb://nosql.data
+ - Database=LocationsDb
+ - identityUrl=http://identity.api #Local: You need to open your local dev-machine firewall at range 5100-5105. at range 5100-5105.
+ - EventBusConnection=rabbitmq
+ ports:
+ - "5109:80"
\ No newline at end of file
diff --git a/docker-compose-windows.yml b/docker-compose-windows.yml
index 48f7ef7b4..2caf209ab 100644
--- a/docker-compose-windows.yml
+++ b/docker-compose-windows.yml
@@ -53,9 +53,20 @@ services:
- ordering.api
- identity.api
- basket.api
-
+
+ locations.api:
+ image: locations.api
+ build:
+ context: ./src/Services/Location/Locations.API
+ dockerfile: Dockerfile
+ depends_on:
+ - nosql.data
+
sql.data:
image: microsoft/mssql-server-windows
+
+ nosql.data:
+ image: mongo:windowsservercore
basket.data:
image: redis:nanoserver
diff --git a/docker-compose.override.yml b/docker-compose.override.yml
index 04d1c4d9c..94bbfef83 100644
--- a/docker-compose.override.yml
+++ b/docker-compose.override.yml
@@ -49,6 +49,15 @@ services:
ports:
- "5102:80"
+ marketing.api:
+ environment:
+ - ASPNETCORE_ENVIRONMENT=Development
+ - ASPNETCORE_URLS=http://0.0.0.0:80
+ - ConnectionString=Server=sql.data;Database=Microsoft.eShopOnContainers.Services.MarketingDb;User Id=sa;Password=Pass@word
+ - identityUrl=http://identity.api #Local: You need to open your local dev-machine firewall at range 5100-5105. at range 5100-5105.
+ ports:
+ - "5110:80"
+
webspa:
environment:
- ASPNETCORE_ENVIRONMENT=Development
@@ -83,6 +92,10 @@ services:
ports:
- "5433:1433"
+ nosql.data:
+ ports:
+ - "27017:27017"
+
webstatus:
environment:
- ASPNETCORE_ENVIRONMENT=Development
@@ -95,3 +108,14 @@ services:
- spa=http://webspa/hc
ports:
- "5107:80"
+
+ locations.api:
+ environment:
+ - ASPNETCORE_ENVIRONMENT=Development
+ - ASPNETCORE_URLS=http://0.0.0.0:80
+ - ConnectionString=mongodb://nosql.data
+ - Database=LocationsDb
+ - identityUrl=http://identity.api #Local: You need to open your local dev-machine firewall at range 5100-5105. at range 5100-5105.
+ - EventBusConnection=rabbitmq
+ ports:
+ - "5109:80"
\ No newline at end of file
diff --git a/docker-compose.prod.yml b/docker-compose.prod.yml
index c5d8839ea..b9c46b4c2 100644
--- a/docker-compose.prod.yml
+++ b/docker-compose.prod.yml
@@ -54,6 +54,15 @@ services:
ports:
- "5102:80"
+ marketing.api:
+ environment:
+ - ASPNETCORE_ENVIRONMENT=Production
+ - ASPNETCORE_URLS=http://0.0.0.0:80
+ - ConnectionString=Server=sql.data;Database=Microsoft.eShopOnContainers.Services.MarketingDb;User Id=sa;Password=Pass@word
+ - identityUrl=http://identity.api #Local: You need to open your local dev-machine firewall at range 5100-5105. at range 5100-5105.
+ ports:
+ - "5110:80"
+
webspa:
environment:
- ASPNETCORE_ENVIRONMENT=Production
diff --git a/docker-compose.vs.debug.yml b/docker-compose.vs.debug.yml
index 2e7145637..c2e5e4a06 100644
--- a/docker-compose.vs.debug.yml
+++ b/docker-compose.vs.debug.yml
@@ -61,6 +61,22 @@ services:
labels:
- "com.microsoft.visualstudio.targetoperatingsystem=linux"
+ marketing.api:
+ image: eshop/marketing.api:dev
+ build:
+ args:
+ source: ${DOCKER_BUILD_SOURCE}
+ environment:
+ - DOTNET_USE_POLLING_FILE_WATCHER=1
+ volumes:
+ - ./src/Services/Marketing/Marketing.API:/app
+ - ~/.nuget/packages:/root/.nuget/packages:ro
+ - ~/clrdbg:/clrdbg:ro
+ entrypoint: tail -f /dev/null
+ labels:
+ - "com.microsoft.visualstudio.targetoperatingsystem=linux"
+
+
webspa:
image: eshop/webspa:dev
build:
@@ -105,3 +121,18 @@ services:
entrypoint: tail -f /dev/null
labels:
- "com.microsoft.visualstudio.targetoperatingsystem=linux"
+
+ locations.api:
+ image: eshop/locations.api:dev
+ build:
+ args:
+ source: ${DOCKER_BUILD_SOURCE}
+ environment:
+ - DOTNET_USE_POLLING_FILE_WATCHER=1
+ volumes:
+ - ./src/Services/Location/Locations.API:/app
+ - ~/.nuget/packages:/root/.nuget/packages:ro
+ - ~/clrdbg:/clrdbg:ro
+ entrypoint: tail -f /dev/null
+ labels:
+ - "com.microsoft.visualstudio.targetoperatingsystem=linux"
diff --git a/docker-compose.vs.release.yml b/docker-compose.vs.release.yml
index d1ca5b2c6..87e246780 100644
--- a/docker-compose.vs.release.yml
+++ b/docker-compose.vs.release.yml
@@ -41,6 +41,16 @@ services:
labels:
- "com.microsoft.visualstudio.targetoperatingsystem=linux"
+ marketing.api:
+ build:
+ args:
+ source: ${DOCKER_BUILD_SOURCE}
+ volumes:
+ - ~/clrdbg:/clrdbg:ro
+ entrypoint: tail -f /dev/null
+ labels:
+ - "com.microsoft.visualstudio.targetoperatingsystem=linux"
+
webspa:
build:
args:
@@ -70,3 +80,13 @@ services:
entrypoint: tail -f /dev/null
labels:
- "com.microsoft.visualstudio.targetoperatingsystem=linux"
+
+ locations.api:
+ build:
+ args:
+ source: ${DOCKER_BUILD_SOURCE}
+ volumes:
+ - ~/clrdbg:/clrdbg:ro
+ entrypoint: tail -f /dev/null
+ labels:
+ - "com.microsoft.visualstudio.targetoperatingsystem=linux"
diff --git a/docker-compose.yml b/docker-compose.yml
index 21f3972f2..e9fb14179 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -36,6 +36,15 @@ services:
depends_on:
- sql.data
+ marketing.api:
+ image: eshop/marketing.api
+ build:
+ context: ./src/Services/Marketing/Marketing.API
+ dockerfile: Dockerfile
+ depends_on:
+ - sql.data
+ - identity.api
+
webspa:
image: eshop/webspa
build:
@@ -59,6 +68,9 @@ services:
sql.data:
image: microsoft/mssql-server-linux
+ nosql.data:
+ image: mongo
+
basket.data:
image: redis
ports:
@@ -74,4 +86,11 @@ services:
build:
context: ./src/Web/WebStatus
dockerfile: Dockerfile
-
\ No newline at end of file
+
+ locations.api:
+ image: locations.api
+ build:
+ context: ./src/Services/Location/Locations.API
+ dockerfile: Dockerfile
+ depends_on:
+ - nosql.data
\ No newline at end of file
diff --git a/eShopOnContainers-ServicesAndWebApps.sln b/eShopOnContainers-ServicesAndWebApps.sln
index d9c994954..22b122fe5 100644
--- a/eShopOnContainers-ServicesAndWebApps.sln
+++ b/eShopOnContainers-ServicesAndWebApps.sln
@@ -76,6 +76,18 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Extensions.Health
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EventBus.Tests", "src\BuildingBlocks\EventBus\EventBus.Tests\EventBus.Tests.csproj", "{89D80DF1-32E1-4AAF-970F-DA0AA6881F9D}"
EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Location", "Location", "{41139F64-4046-4F16-96B7-D941D96FA9C6}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Locations.API", "src\Services\Location\Locations.API\Locations.API.csproj", "{E7581357-FC34-474C-B8F5-307EE3CE05EF}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "DataProtection", "DataProtection", "{88B22DBB-AA8F-4290-A454-2C109352C345}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DataProtection", "src\BuildingBlocks\DataProtection\DataProtection\DataProtection.csproj", "{23A33F9B-7672-426D-ACF9-FF8436ADC81A}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Marketing", "Marketing", "{A5260DE0-1FDD-467E-9CC1-A028AB081CEE}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Marketing.API", "src\Services\Marketing\Marketing.API\Marketing.API.csproj", "{DF395F85-B010-465D-857A-7EBCC512C0C2}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Ad-Hoc|Any CPU = Ad-Hoc|Any CPU
@@ -1002,6 +1014,150 @@ Global
{89D80DF1-32E1-4AAF-970F-DA0AA6881F9D}.Release|x64.Build.0 = Release|Any CPU
{89D80DF1-32E1-4AAF-970F-DA0AA6881F9D}.Release|x86.ActiveCfg = Release|Any CPU
{89D80DF1-32E1-4AAF-970F-DA0AA6881F9D}.Release|x86.Build.0 = Release|Any CPU
+ {E7581357-FC34-474C-B8F5-307EE3CE05EF}.Ad-Hoc|Any CPU.ActiveCfg = Debug|Any CPU
+ {E7581357-FC34-474C-B8F5-307EE3CE05EF}.Ad-Hoc|Any CPU.Build.0 = Debug|Any CPU
+ {E7581357-FC34-474C-B8F5-307EE3CE05EF}.Ad-Hoc|ARM.ActiveCfg = Debug|Any CPU
+ {E7581357-FC34-474C-B8F5-307EE3CE05EF}.Ad-Hoc|ARM.Build.0 = Debug|Any CPU
+ {E7581357-FC34-474C-B8F5-307EE3CE05EF}.Ad-Hoc|iPhone.ActiveCfg = Debug|Any CPU
+ {E7581357-FC34-474C-B8F5-307EE3CE05EF}.Ad-Hoc|iPhone.Build.0 = Debug|Any CPU
+ {E7581357-FC34-474C-B8F5-307EE3CE05EF}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Debug|Any CPU
+ {E7581357-FC34-474C-B8F5-307EE3CE05EF}.Ad-Hoc|iPhoneSimulator.Build.0 = Debug|Any CPU
+ {E7581357-FC34-474C-B8F5-307EE3CE05EF}.Ad-Hoc|x64.ActiveCfg = Debug|Any CPU
+ {E7581357-FC34-474C-B8F5-307EE3CE05EF}.Ad-Hoc|x64.Build.0 = Debug|Any CPU
+ {E7581357-FC34-474C-B8F5-307EE3CE05EF}.Ad-Hoc|x86.ActiveCfg = Debug|Any CPU
+ {E7581357-FC34-474C-B8F5-307EE3CE05EF}.Ad-Hoc|x86.Build.0 = Debug|Any CPU
+ {E7581357-FC34-474C-B8F5-307EE3CE05EF}.AppStore|Any CPU.ActiveCfg = Debug|Any CPU
+ {E7581357-FC34-474C-B8F5-307EE3CE05EF}.AppStore|Any CPU.Build.0 = Debug|Any CPU
+ {E7581357-FC34-474C-B8F5-307EE3CE05EF}.AppStore|ARM.ActiveCfg = Debug|Any CPU
+ {E7581357-FC34-474C-B8F5-307EE3CE05EF}.AppStore|ARM.Build.0 = Debug|Any CPU
+ {E7581357-FC34-474C-B8F5-307EE3CE05EF}.AppStore|iPhone.ActiveCfg = Debug|Any CPU
+ {E7581357-FC34-474C-B8F5-307EE3CE05EF}.AppStore|iPhone.Build.0 = Debug|Any CPU
+ {E7581357-FC34-474C-B8F5-307EE3CE05EF}.AppStore|iPhoneSimulator.ActiveCfg = Debug|Any CPU
+ {E7581357-FC34-474C-B8F5-307EE3CE05EF}.AppStore|iPhoneSimulator.Build.0 = Debug|Any CPU
+ {E7581357-FC34-474C-B8F5-307EE3CE05EF}.AppStore|x64.ActiveCfg = Debug|Any CPU
+ {E7581357-FC34-474C-B8F5-307EE3CE05EF}.AppStore|x64.Build.0 = Debug|Any CPU
+ {E7581357-FC34-474C-B8F5-307EE3CE05EF}.AppStore|x86.ActiveCfg = Debug|Any CPU
+ {E7581357-FC34-474C-B8F5-307EE3CE05EF}.AppStore|x86.Build.0 = Debug|Any CPU
+ {E7581357-FC34-474C-B8F5-307EE3CE05EF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {E7581357-FC34-474C-B8F5-307EE3CE05EF}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {E7581357-FC34-474C-B8F5-307EE3CE05EF}.Debug|ARM.ActiveCfg = Debug|Any CPU
+ {E7581357-FC34-474C-B8F5-307EE3CE05EF}.Debug|ARM.Build.0 = Debug|Any CPU
+ {E7581357-FC34-474C-B8F5-307EE3CE05EF}.Debug|iPhone.ActiveCfg = Debug|Any CPU
+ {E7581357-FC34-474C-B8F5-307EE3CE05EF}.Debug|iPhone.Build.0 = Debug|Any CPU
+ {E7581357-FC34-474C-B8F5-307EE3CE05EF}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
+ {E7581357-FC34-474C-B8F5-307EE3CE05EF}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
+ {E7581357-FC34-474C-B8F5-307EE3CE05EF}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {E7581357-FC34-474C-B8F5-307EE3CE05EF}.Debug|x64.Build.0 = Debug|Any CPU
+ {E7581357-FC34-474C-B8F5-307EE3CE05EF}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {E7581357-FC34-474C-B8F5-307EE3CE05EF}.Debug|x86.Build.0 = Debug|Any CPU
+ {E7581357-FC34-474C-B8F5-307EE3CE05EF}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {E7581357-FC34-474C-B8F5-307EE3CE05EF}.Release|Any CPU.Build.0 = Release|Any CPU
+ {E7581357-FC34-474C-B8F5-307EE3CE05EF}.Release|ARM.ActiveCfg = Release|Any CPU
+ {E7581357-FC34-474C-B8F5-307EE3CE05EF}.Release|ARM.Build.0 = Release|Any CPU
+ {E7581357-FC34-474C-B8F5-307EE3CE05EF}.Release|iPhone.ActiveCfg = Release|Any CPU
+ {E7581357-FC34-474C-B8F5-307EE3CE05EF}.Release|iPhone.Build.0 = Release|Any CPU
+ {E7581357-FC34-474C-B8F5-307EE3CE05EF}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
+ {E7581357-FC34-474C-B8F5-307EE3CE05EF}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
+ {E7581357-FC34-474C-B8F5-307EE3CE05EF}.Release|x64.ActiveCfg = Release|Any CPU
+ {E7581357-FC34-474C-B8F5-307EE3CE05EF}.Release|x64.Build.0 = Release|Any CPU
+ {E7581357-FC34-474C-B8F5-307EE3CE05EF}.Release|x86.ActiveCfg = Release|Any CPU
+ {E7581357-FC34-474C-B8F5-307EE3CE05EF}.Release|x86.Build.0 = Release|Any CPU
+ {23A33F9B-7672-426D-ACF9-FF8436ADC81A}.Ad-Hoc|Any CPU.ActiveCfg = Debug|Any CPU
+ {23A33F9B-7672-426D-ACF9-FF8436ADC81A}.Ad-Hoc|Any CPU.Build.0 = Debug|Any CPU
+ {23A33F9B-7672-426D-ACF9-FF8436ADC81A}.Ad-Hoc|ARM.ActiveCfg = Debug|Any CPU
+ {23A33F9B-7672-426D-ACF9-FF8436ADC81A}.Ad-Hoc|ARM.Build.0 = Debug|Any CPU
+ {23A33F9B-7672-426D-ACF9-FF8436ADC81A}.Ad-Hoc|iPhone.ActiveCfg = Debug|Any CPU
+ {23A33F9B-7672-426D-ACF9-FF8436ADC81A}.Ad-Hoc|iPhone.Build.0 = Debug|Any CPU
+ {23A33F9B-7672-426D-ACF9-FF8436ADC81A}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Debug|Any CPU
+ {23A33F9B-7672-426D-ACF9-FF8436ADC81A}.Ad-Hoc|iPhoneSimulator.Build.0 = Debug|Any CPU
+ {23A33F9B-7672-426D-ACF9-FF8436ADC81A}.Ad-Hoc|x64.ActiveCfg = Debug|Any CPU
+ {23A33F9B-7672-426D-ACF9-FF8436ADC81A}.Ad-Hoc|x64.Build.0 = Debug|Any CPU
+ {23A33F9B-7672-426D-ACF9-FF8436ADC81A}.Ad-Hoc|x86.ActiveCfg = Debug|Any CPU
+ {23A33F9B-7672-426D-ACF9-FF8436ADC81A}.Ad-Hoc|x86.Build.0 = Debug|Any CPU
+ {23A33F9B-7672-426D-ACF9-FF8436ADC81A}.AppStore|Any CPU.ActiveCfg = Debug|Any CPU
+ {23A33F9B-7672-426D-ACF9-FF8436ADC81A}.AppStore|Any CPU.Build.0 = Debug|Any CPU
+ {23A33F9B-7672-426D-ACF9-FF8436ADC81A}.AppStore|ARM.ActiveCfg = Debug|Any CPU
+ {23A33F9B-7672-426D-ACF9-FF8436ADC81A}.AppStore|ARM.Build.0 = Debug|Any CPU
+ {23A33F9B-7672-426D-ACF9-FF8436ADC81A}.AppStore|iPhone.ActiveCfg = Debug|Any CPU
+ {23A33F9B-7672-426D-ACF9-FF8436ADC81A}.AppStore|iPhone.Build.0 = Debug|Any CPU
+ {23A33F9B-7672-426D-ACF9-FF8436ADC81A}.AppStore|iPhoneSimulator.ActiveCfg = Debug|Any CPU
+ {23A33F9B-7672-426D-ACF9-FF8436ADC81A}.AppStore|iPhoneSimulator.Build.0 = Debug|Any CPU
+ {23A33F9B-7672-426D-ACF9-FF8436ADC81A}.AppStore|x64.ActiveCfg = Debug|Any CPU
+ {23A33F9B-7672-426D-ACF9-FF8436ADC81A}.AppStore|x64.Build.0 = Debug|Any CPU
+ {23A33F9B-7672-426D-ACF9-FF8436ADC81A}.AppStore|x86.ActiveCfg = Debug|Any CPU
+ {23A33F9B-7672-426D-ACF9-FF8436ADC81A}.AppStore|x86.Build.0 = Debug|Any CPU
+ {23A33F9B-7672-426D-ACF9-FF8436ADC81A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {23A33F9B-7672-426D-ACF9-FF8436ADC81A}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {23A33F9B-7672-426D-ACF9-FF8436ADC81A}.Debug|ARM.ActiveCfg = Debug|Any CPU
+ {23A33F9B-7672-426D-ACF9-FF8436ADC81A}.Debug|ARM.Build.0 = Debug|Any CPU
+ {23A33F9B-7672-426D-ACF9-FF8436ADC81A}.Debug|iPhone.ActiveCfg = Debug|Any CPU
+ {23A33F9B-7672-426D-ACF9-FF8436ADC81A}.Debug|iPhone.Build.0 = Debug|Any CPU
+ {23A33F9B-7672-426D-ACF9-FF8436ADC81A}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
+ {23A33F9B-7672-426D-ACF9-FF8436ADC81A}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
+ {23A33F9B-7672-426D-ACF9-FF8436ADC81A}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {23A33F9B-7672-426D-ACF9-FF8436ADC81A}.Debug|x64.Build.0 = Debug|Any CPU
+ {23A33F9B-7672-426D-ACF9-FF8436ADC81A}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {23A33F9B-7672-426D-ACF9-FF8436ADC81A}.Debug|x86.Build.0 = Debug|Any CPU
+ {23A33F9B-7672-426D-ACF9-FF8436ADC81A}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {23A33F9B-7672-426D-ACF9-FF8436ADC81A}.Release|Any CPU.Build.0 = Release|Any CPU
+ {23A33F9B-7672-426D-ACF9-FF8436ADC81A}.Release|ARM.ActiveCfg = Release|Any CPU
+ {23A33F9B-7672-426D-ACF9-FF8436ADC81A}.Release|ARM.Build.0 = Release|Any CPU
+ {23A33F9B-7672-426D-ACF9-FF8436ADC81A}.Release|iPhone.ActiveCfg = Release|Any CPU
+ {23A33F9B-7672-426D-ACF9-FF8436ADC81A}.Release|iPhone.Build.0 = Release|Any CPU
+ {23A33F9B-7672-426D-ACF9-FF8436ADC81A}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
+ {23A33F9B-7672-426D-ACF9-FF8436ADC81A}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
+ {23A33F9B-7672-426D-ACF9-FF8436ADC81A}.Release|x64.ActiveCfg = Release|Any CPU
+ {23A33F9B-7672-426D-ACF9-FF8436ADC81A}.Release|x64.Build.0 = Release|Any CPU
+ {23A33F9B-7672-426D-ACF9-FF8436ADC81A}.Release|x86.ActiveCfg = Release|Any CPU
+ {23A33F9B-7672-426D-ACF9-FF8436ADC81A}.Release|x86.Build.0 = Release|Any CPU
+ {DF395F85-B010-465D-857A-7EBCC512C0C2}.Ad-Hoc|Any CPU.ActiveCfg = Debug|Any CPU
+ {DF395F85-B010-465D-857A-7EBCC512C0C2}.Ad-Hoc|Any CPU.Build.0 = Debug|Any CPU
+ {DF395F85-B010-465D-857A-7EBCC512C0C2}.Ad-Hoc|ARM.ActiveCfg = Debug|Any CPU
+ {DF395F85-B010-465D-857A-7EBCC512C0C2}.Ad-Hoc|ARM.Build.0 = Debug|Any CPU
+ {DF395F85-B010-465D-857A-7EBCC512C0C2}.Ad-Hoc|iPhone.ActiveCfg = Debug|Any CPU
+ {DF395F85-B010-465D-857A-7EBCC512C0C2}.Ad-Hoc|iPhone.Build.0 = Debug|Any CPU
+ {DF395F85-B010-465D-857A-7EBCC512C0C2}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Debug|Any CPU
+ {DF395F85-B010-465D-857A-7EBCC512C0C2}.Ad-Hoc|iPhoneSimulator.Build.0 = Debug|Any CPU
+ {DF395F85-B010-465D-857A-7EBCC512C0C2}.Ad-Hoc|x64.ActiveCfg = Debug|Any CPU
+ {DF395F85-B010-465D-857A-7EBCC512C0C2}.Ad-Hoc|x64.Build.0 = Debug|Any CPU
+ {DF395F85-B010-465D-857A-7EBCC512C0C2}.Ad-Hoc|x86.ActiveCfg = Debug|Any CPU
+ {DF395F85-B010-465D-857A-7EBCC512C0C2}.Ad-Hoc|x86.Build.0 = Debug|Any CPU
+ {DF395F85-B010-465D-857A-7EBCC512C0C2}.AppStore|Any CPU.ActiveCfg = Debug|Any CPU
+ {DF395F85-B010-465D-857A-7EBCC512C0C2}.AppStore|Any CPU.Build.0 = Debug|Any CPU
+ {DF395F85-B010-465D-857A-7EBCC512C0C2}.AppStore|ARM.ActiveCfg = Debug|Any CPU
+ {DF395F85-B010-465D-857A-7EBCC512C0C2}.AppStore|ARM.Build.0 = Debug|Any CPU
+ {DF395F85-B010-465D-857A-7EBCC512C0C2}.AppStore|iPhone.ActiveCfg = Debug|Any CPU
+ {DF395F85-B010-465D-857A-7EBCC512C0C2}.AppStore|iPhone.Build.0 = Debug|Any CPU
+ {DF395F85-B010-465D-857A-7EBCC512C0C2}.AppStore|iPhoneSimulator.ActiveCfg = Debug|Any CPU
+ {DF395F85-B010-465D-857A-7EBCC512C0C2}.AppStore|iPhoneSimulator.Build.0 = Debug|Any CPU
+ {DF395F85-B010-465D-857A-7EBCC512C0C2}.AppStore|x64.ActiveCfg = Debug|Any CPU
+ {DF395F85-B010-465D-857A-7EBCC512C0C2}.AppStore|x64.Build.0 = Debug|Any CPU
+ {DF395F85-B010-465D-857A-7EBCC512C0C2}.AppStore|x86.ActiveCfg = Debug|Any CPU
+ {DF395F85-B010-465D-857A-7EBCC512C0C2}.AppStore|x86.Build.0 = Debug|Any CPU
+ {DF395F85-B010-465D-857A-7EBCC512C0C2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {DF395F85-B010-465D-857A-7EBCC512C0C2}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {DF395F85-B010-465D-857A-7EBCC512C0C2}.Debug|ARM.ActiveCfg = Debug|Any CPU
+ {DF395F85-B010-465D-857A-7EBCC512C0C2}.Debug|ARM.Build.0 = Debug|Any CPU
+ {DF395F85-B010-465D-857A-7EBCC512C0C2}.Debug|iPhone.ActiveCfg = Debug|Any CPU
+ {DF395F85-B010-465D-857A-7EBCC512C0C2}.Debug|iPhone.Build.0 = Debug|Any CPU
+ {DF395F85-B010-465D-857A-7EBCC512C0C2}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
+ {DF395F85-B010-465D-857A-7EBCC512C0C2}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
+ {DF395F85-B010-465D-857A-7EBCC512C0C2}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {DF395F85-B010-465D-857A-7EBCC512C0C2}.Debug|x64.Build.0 = Debug|Any CPU
+ {DF395F85-B010-465D-857A-7EBCC512C0C2}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {DF395F85-B010-465D-857A-7EBCC512C0C2}.Debug|x86.Build.0 = Debug|Any CPU
+ {DF395F85-B010-465D-857A-7EBCC512C0C2}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {DF395F85-B010-465D-857A-7EBCC512C0C2}.Release|Any CPU.Build.0 = Release|Any CPU
+ {DF395F85-B010-465D-857A-7EBCC512C0C2}.Release|ARM.ActiveCfg = Release|Any CPU
+ {DF395F85-B010-465D-857A-7EBCC512C0C2}.Release|ARM.Build.0 = Release|Any CPU
+ {DF395F85-B010-465D-857A-7EBCC512C0C2}.Release|iPhone.ActiveCfg = Release|Any CPU
+ {DF395F85-B010-465D-857A-7EBCC512C0C2}.Release|iPhone.Build.0 = Release|Any CPU
+ {DF395F85-B010-465D-857A-7EBCC512C0C2}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
+ {DF395F85-B010-465D-857A-7EBCC512C0C2}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
+ {DF395F85-B010-465D-857A-7EBCC512C0C2}.Release|x64.ActiveCfg = Release|Any CPU
+ {DF395F85-B010-465D-857A-7EBCC512C0C2}.Release|x64.Build.0 = Release|Any CPU
+ {DF395F85-B010-465D-857A-7EBCC512C0C2}.Release|x86.ActiveCfg = Release|Any CPU
+ {DF395F85-B010-465D-857A-7EBCC512C0C2}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -1038,5 +1194,15 @@ Global
{22A0F9C1-2D4A-4107-95B7-8459E6688BC5} = {A81ECBC2-6B00-4DCD-8388-469174033379}
{4BD76717-3102-4969-8C2C-BAAA3F0263B6} = {A81ECBC2-6B00-4DCD-8388-469174033379}
{89D80DF1-32E1-4AAF-970F-DA0AA6881F9D} = {807BB76E-B2BB-47A2-A57B-3D1B20FF5E7F}
+ {41139F64-4046-4F16-96B7-D941D96FA9C6} = {91CF7717-08AB-4E65-B10E-0B426F01E2E8}
+ {E7581357-FC34-474C-B8F5-307EE3CE05EF} = {41139F64-4046-4F16-96B7-D941D96FA9C6}
+ {88B22DBB-AA8F-4290-A454-2C109352C345} = {DB0EFB20-B024-4E5E-A75C-52143C131D25}
+ {23A33F9B-7672-426D-ACF9-FF8436ADC81A} = {88B22DBB-AA8F-4290-A454-2C109352C345}
+ {A5260DE0-1FDD-467E-9CC1-A028AB081CEE} = {91CF7717-08AB-4E65-B10E-0B426F01E2E8}
+ {DF395F85-B010-465D-857A-7EBCC512C0C2} = {A5260DE0-1FDD-467E-9CC1-A028AB081CEE}
+ {88B22DBB-AA8F-4290-A454-2C109352C345} = {DB0EFB20-B024-4E5E-A75C-52143C131D25}
+ {23A33F9B-7672-426D-ACF9-FF8436ADC81A} = {88B22DBB-AA8F-4290-A454-2C109352C345}
+ {41139F64-4046-4F16-96B7-D941D96FA9C6} = {91CF7717-08AB-4E65-B10E-0B426F01E2E8}
+ {E7581357-FC34-474C-B8F5-307EE3CE05EF} = {41139F64-4046-4F16-96B7-D941D96FA9C6}
EndGlobalSection
EndGlobal
diff --git a/k8s/deploy.ps1 b/k8s/deploy.ps1
index 0619dd8e8..9930474ba 100644
--- a/k8s/deploy.ps1
+++ b/k8s/deploy.ps1
@@ -58,7 +58,7 @@ ExecKube -cmd 'delete configmap urls'
# start sql, rabbitmq, frontend deploymentsExecKube -cmd 'delete configmap config-files'
ExecKube -cmd 'create configmap config-files --from-file=nginx-conf=nginx.conf'
ExecKube -cmd 'label configmap config-files app=eshop'
-ExecKube -cmd 'create -f sql-data.yaml -f basket-data.yaml -f rabbitmq.yaml -f services.yaml -f frontend.yaml'
+ExecKube -cmd 'create -f sql-data.yaml -f basket-data.yaml -f keystore-data.yaml -f rabbitmq.yaml -f services.yaml -f frontend.yaml'
# building and publishing docker images not necessary when deploying through CI VSTS
if(-not $deployCI) {
diff --git a/k8s/deployments.yaml b/k8s/deployments.yaml
index 1bb406390..62352e2ef 100644
--- a/k8s/deployments.yaml
+++ b/k8s/deployments.yaml
@@ -85,6 +85,10 @@ spec:
value: http://0.0.0.0:80/identity
- name: ConnectionStrings__DefaultConnection
value: "Server=sql-data;Initial Catalog=Microsoft.eShopOnContainers.Services.IdentityDb;User Id=sa;Password=Pass@word"
+ - name: DPConnectionString
+ value: keystore-data
+ - name: IsClusterEnv
+ value: 'True'
- name: MvcClient
valueFrom:
configMapKeyRef:
@@ -152,6 +156,10 @@ spec:
env:
- name: ASPNETCORE_URLS
value: http://0.0.0.0:80/webmvc
+ - name: DPConnectionString
+ value: keystore-data
+ - name: IsClusterEnv
+ value: 'True'
- name: BasketUrl
valueFrom:
configMapKeyRef:
@@ -255,6 +263,10 @@ spec:
env:
- name: ASPNETCORE_URLS
value: http://0.0.0.0:80
+ - name: DPConnectionString
+ value: keystore-data
+ - name: IsClusterEnv
+ value: 'True'
- name: BasketUrl
valueFrom:
configMapKeyRef:
diff --git a/k8s/keystore-data.yaml b/k8s/keystore-data.yaml
new file mode 100644
index 000000000..3340cce35
--- /dev/null
+++ b/k8s/keystore-data.yaml
@@ -0,0 +1,29 @@
+apiVersion: v1
+kind: Service
+metadata:
+ labels:
+ app: eshop
+ component: keystore-data
+ name: keystore-data
+spec:
+ ports:
+ - port: 6379
+ selector:
+ app: eshop
+ component: keystore-data
+---
+apiVersion: extensions/v1beta1
+kind: Deployment
+metadata:
+ name: keystore-data
+spec:
+ template:
+ metadata:
+ labels:
+ app: eshop
+ component: keystore-data
+ spec:
+ containers:
+ - name: keystore-data
+ image: redis:3.2-alpine
+
diff --git a/src/BuildingBlocks/DataProtection/DataProtection/DataProtection.csproj b/src/BuildingBlocks/DataProtection/DataProtection/DataProtection.csproj
new file mode 100644
index 000000000..bfe61a85a
--- /dev/null
+++ b/src/BuildingBlocks/DataProtection/DataProtection/DataProtection.csproj
@@ -0,0 +1,13 @@
+
+
+
+ netcoreapp1.1
+ Microsoft.eShopOnContainers.BuildingBlocks
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/BuildingBlocks/DataProtection/DataProtection/DataProtectionBuilderExtensions.cs b/src/BuildingBlocks/DataProtection/DataProtection/DataProtectionBuilderExtensions.cs
new file mode 100644
index 000000000..3db776b9a
--- /dev/null
+++ b/src/BuildingBlocks/DataProtection/DataProtection/DataProtectionBuilderExtensions.cs
@@ -0,0 +1,95 @@
+namespace Microsoft.eShopOnContainers.BuildingBlocks
+{
+ using Microsoft.AspNetCore.DataProtection;
+ using Microsoft.AspNetCore.DataProtection.Repositories;
+ using Microsoft.Extensions.DependencyInjection;
+ using Microsoft.Extensions.Logging;
+ using System;
+ using System.Linq;
+ using System.Net;
+
+ ///
+ /// Extension methods for for configuring
+ /// data protection options.
+ ///
+ public static class DataProtectionBuilderExtensions
+ {
+ ///
+ /// Sets up data protection to persist session keys in Redis.
+ ///
+ /// The used to set up data protection options.
+ /// The connection string specifying the Redis instance and database for key storage.
+ ///
+ /// The for continued configuration.
+ ///
+ ///
+ /// Thrown if or is .
+ ///
+ ///
+ /// Thrown if is empty.
+ ///
+ public static IDataProtectionBuilder PersistKeysToRedis(this IDataProtectionBuilder builder, string redisConnectionString)
+ {
+ if (builder == null)
+ {
+ throw new ArgumentNullException(nameof(builder));
+ }
+
+ if (redisConnectionString == null)
+ {
+ throw new ArgumentNullException(nameof(redisConnectionString));
+ }
+
+ if (redisConnectionString.Length == 0)
+ {
+ throw new ArgumentException("Redis connection string may not be empty.", nameof(redisConnectionString));
+ }
+
+ var ips = Dns.GetHostAddressesAsync(redisConnectionString).Result;
+
+ return builder.Use(ServiceDescriptor.Singleton(services =>
+ new RedisXmlRepository(ips.First().ToString(), services.GetRequiredService>())));
+ }
+
+ ///
+ /// Updates an to use the service of
+ /// a specific type, removing all other services of that type.
+ ///
+ /// The that should use the specified service.
+ /// The with the service the should use.
+ ///
+ /// The for continued configuration.
+ ///
+ ///
+ /// Thrown if or is .
+ ///
+ public static IDataProtectionBuilder Use(this IDataProtectionBuilder builder, ServiceDescriptor descriptor)
+ {
+ // This algorithm of removing all other services of a specific type
+ // before adding the new/replacement service is how the base ASP.NET
+ // DataProtection bits work. Due to some of the differences in how
+ // that base set of bits handles DI, it's better to follow suit
+ // and work in the same way than to try and debug weird issues.
+ if (builder == null)
+ {
+ throw new ArgumentNullException(nameof(builder));
+ }
+
+ if (descriptor == null)
+ {
+ throw new ArgumentNullException(nameof(descriptor));
+ }
+
+ for (int i = builder.Services.Count - 1; i >= 0; i--)
+ {
+ if (builder.Services[i]?.ServiceType == descriptor.ServiceType)
+ {
+ builder.Services.RemoveAt(i);
+ }
+ }
+
+ builder.Services.Add(descriptor);
+ return builder;
+ }
+ }
+}
diff --git a/src/BuildingBlocks/DataProtection/DataProtection/RedisXmlRepository.cs b/src/BuildingBlocks/DataProtection/DataProtection/RedisXmlRepository.cs
new file mode 100644
index 000000000..f5a903b65
--- /dev/null
+++ b/src/BuildingBlocks/DataProtection/DataProtection/RedisXmlRepository.cs
@@ -0,0 +1,210 @@
+namespace Microsoft.eShopOnContainers.BuildingBlocks
+{
+ using Microsoft.AspNetCore.DataProtection.Repositories;
+ using Microsoft.Extensions.Logging;
+ using StackExchange.Redis;
+ using System;
+ using System.Collections.Generic;
+ using System.Text.RegularExpressions;
+ using System.Xml.Linq;
+
+ ///
+ /// Key repository that stores XML encrypted keys in a Redis distributed cache.
+ ///
+ ///
+ ///
+ /// The values stored in Redis are XML documents that contain encrypted session
+ /// keys used for the protection of things like session state. The document contents
+ /// are double-encrypted - first with a changing session key; then by a master key.
+ /// As such, there's no risk in storing the keys in Redis - even if someone can crack
+ /// the master key, they still need to also crack the session key. (Other solutions
+ /// for sharing keys across a farm environment include writing them to files
+ /// on a file share.)
+ ///
+ ///
+ /// While the repository uses a hash to keep the set of encrypted keys separate, you
+ /// can further separate these items from other items in Redis by specifying a unique
+ /// database in the connection string.
+ ///
+ ///
+ /// Consumers of the repository are responsible for caching the XML items as needed.
+ /// Typically repositories are consumed by things like
+ /// which generates
+ /// values that get cached. The mechanism is already optimized for caching so there's
+ /// no need to create a redundant cache.
+ ///
+ ///
+ ///
+ ///
+ public class RedisXmlRepository : IXmlRepository, IDisposable
+ {
+ ///
+ /// The root cache key for XML items stored in Redis
+ ///
+ public static readonly string RedisHashKey = "DataProtectionXmlRepository";
+
+ ///
+ /// The connection to the Redis backing store.
+ ///
+ private IConnectionMultiplexer _connection;
+
+ ///
+ /// Flag indicating whether the object has been disposed.
+ ///
+ private bool _disposed = false;
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ ///
+ /// The Redis connection string.
+ ///
+ ///
+ /// The used to log diagnostic messages.
+ ///
+ ///
+ /// Thrown if or is .
+ ///
+ public RedisXmlRepository(string connectionString, ILogger logger)
+ : this(ConnectionMultiplexer.Connect(connectionString), logger)
+ {
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ ///
+ /// The Redis database connection.
+ ///
+ ///
+ /// The used to log diagnostic messages.
+ ///
+ ///
+ /// Thrown if or is .
+ ///
+ public RedisXmlRepository(IConnectionMultiplexer connection, ILogger logger)
+ {
+ if (connection == null)
+ {
+ throw new ArgumentNullException(nameof(connection));
+ }
+
+ if (logger == null)
+ {
+ throw new ArgumentNullException(nameof(logger));
+ }
+
+ this._connection = connection;
+ this.Logger = logger;
+
+ // Mask the password so it doesn't get logged.
+ var configuration = Regex.Replace(this._connection.Configuration, @"password\s*=\s*[^,]*", "password=****", RegexOptions.IgnoreCase);
+ this.Logger.LogDebug("Storing data protection keys in Redis: {RedisConfiguration}", configuration);
+ }
+
+ ///
+ /// Gets the logger.
+ ///
+ ///
+ /// The used to log diagnostic messages.
+ ///
+ public ILogger Logger { get; private set; }
+
+ ///
+ /// Performs application-defined tasks associated with freeing, releasing,
+ /// or resetting unmanaged resources.
+ ///
+ public void Dispose()
+ {
+ this.Dispose(true);
+ }
+
+ ///
+ /// Gets all top-level XML elements in the repository.
+ ///
+ ///
+ /// An with the set of elements
+ /// stored in the repository.
+ ///
+ public IReadOnlyCollection GetAllElements()
+ {
+ var database = this._connection.GetDatabase();
+ var hash = database.HashGetAll(RedisHashKey);
+ var elements = new List();
+
+ if (hash == null || hash.Length == 0)
+ {
+ return elements.AsReadOnly();
+ }
+
+ foreach (var item in hash.ToStringDictionary())
+ {
+ elements.Add(XElement.Parse(item.Value));
+ }
+
+ this.Logger.LogDebug("Read {XmlElementCount} XML elements from Redis.", elements.Count);
+ return elements.AsReadOnly();
+ }
+
+ ///
+ /// Adds a top-level XML element to the repository.
+ ///
+ /// The element to add.
+ ///
+ /// An optional name to be associated with the XML element.
+ /// For instance, if this repository stores XML files on disk, the friendly name may
+ /// be used as part of the file name. Repository implementations are not required to
+ /// observe this parameter even if it has been provided by the caller.
+ ///
+ ///
+ /// The parameter must be unique if specified.
+ /// For instance, it could be the ID of the key being stored.
+ ///
+ ///
+ /// Thrown if is .
+ ///
+ public void StoreElement(XElement element, string friendlyName)
+ {
+ if (element == null)
+ {
+ throw new ArgumentNullException(nameof(element));
+ }
+
+ if (string.IsNullOrEmpty(friendlyName))
+ {
+ // The framework always passes in a name, but
+ // the contract indicates this may be null or empty.
+ friendlyName = Guid.NewGuid().ToString();
+ }
+
+ this.Logger.LogDebug("Storing XML element with friendly name {XmlElementFriendlyName}.", friendlyName);
+
+ this._connection.GetDatabase().HashSet(RedisHashKey, friendlyName, element.ToString());
+ }
+
+ ///
+ /// Releases unmanaged and - optionally - managed resources.
+ ///
+ ///
+ /// to release both managed and unmanaged resources;
+ /// to release only unmanaged resources.
+ ///
+ protected virtual void Dispose(bool disposing)
+ {
+ if (!this._disposed)
+ {
+ if (disposing)
+ {
+ if (this._connection != null)
+ {
+ this._connection.Close();
+ this._connection.Dispose();
+ }
+ }
+
+ this._connection = null;
+ this._disposed = true;
+ }
+ }
+ }
+}
diff --git a/src/Mobile/eShopOnContainers/eShopOnContainers.Core/GlobalSettings.cs b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/GlobalSettings.cs
index a75ee7058..b62bb7ba3 100644
--- a/src/Mobile/eShopOnContainers/eShopOnContainers.Core/GlobalSettings.cs
+++ b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/GlobalSettings.cs
@@ -43,6 +43,8 @@
public string IdentityEndpoint { get; set; }
+ public string LocationEndpoint { get; set; }
+
public string UserInfoEndpoint { get; set; }
public string LogoutEndpoint { get; set; }
@@ -62,6 +64,7 @@
LogoutEndpoint = string.Format("{0}:5105/connect/endsession", baseEndpoint);
IdentityCallback = string.Format("{0}:5105/xamarincallback", baseEndpoint);
LogoutCallback = string.Format("{0}:5105/Account/Redirecting", baseEndpoint);
+ LocationEndpoint = string.Format("{0}:5109", baseEndpoint);
}
}
}
\ No newline at end of file
diff --git a/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Helpers/Settings.cs b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Helpers/Settings.cs
index 24da4fd2b..51b1efe30 100644
--- a/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Helpers/Settings.cs
+++ b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Helpers/Settings.cs
@@ -24,9 +24,13 @@ namespace eShopOnContainers.Core.Helpers
private const string IdToken = "id_token";
private const string IdUseMocks = "use_mocks";
private const string IdUrlBase = "url_base";
+ private const string IdUseFakeLocation = "use_fake_location";
+ private const string IdFakeLatitude = "fake_latitude";
+ private const string IdFakeLongitude = "fake_longitude";
private static readonly string AccessTokenDefault = string.Empty;
private static readonly string IdTokenDefault = string.Empty;
private static readonly bool UseMocksDefault = true;
+ private static readonly bool UseFakeLocationDefault = false;
private static readonly string UrlBaseDefault = GlobalSetting.Instance.BaseEndpoint;
#endregion
@@ -78,5 +82,40 @@ namespace eShopOnContainers.Core.Helpers
AppSettings.AddOrUpdateValue(IdUrlBase, value);
}
}
+
+ public static bool UseFakeLocation
+ {
+ get
+ {
+ return AppSettings.GetValueOrDefault(IdUseFakeLocation, UseFakeLocationDefault);
+ }
+ set
+ {
+ AppSettings.AddOrUpdateValue(IdUseFakeLocation, value);
+ }
+ }
+
+ public static double FakeLatitude
+ {
+ get
+ {
+ return AppSettings.GetValueOrDefault(IdFakeLatitude);
+ }
+ set
+ {
+ AppSettings.AddOrUpdateValue(IdFakeLatitude, value);
+ }
+ }
+ public static double FakeLongitude
+ {
+ get
+ {
+ return AppSettings.GetValueOrDefault(IdFakeLongitude);
+ }
+ set
+ {
+ AppSettings.AddOrUpdateValue(IdFakeLongitude, value);
+ }
+ }
}
}
\ No newline at end of file
diff --git a/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Models/Location/LocationRequest.cs b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Models/Location/LocationRequest.cs
new file mode 100644
index 000000000..99654914c
--- /dev/null
+++ b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Models/Location/LocationRequest.cs
@@ -0,0 +1,8 @@
+namespace eShopOnContainers.Core.Models.Location
+{
+ public class LocationRequest
+ {
+ public double Longitude { get; set; }
+ public double Latitude { get; set; }
+ }
+}
diff --git a/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Services/Location/ILocationService.cs b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Services/Location/ILocationService.cs
new file mode 100644
index 000000000..bc2c59915
--- /dev/null
+++ b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Services/Location/ILocationService.cs
@@ -0,0 +1,10 @@
+namespace eShopOnContainers.Core.Services.Location
+{
+ using System.Threading.Tasks;
+ using eShopOnContainers.Core.Models.Location;
+
+ public interface ILocationService
+ {
+ Task UpdateUserLocation(LocationRequest newLocReq);
+ }
+}
\ No newline at end of file
diff --git a/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Services/Location/LocationService.cs b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Services/Location/LocationService.cs
new file mode 100644
index 000000000..2149a5118
--- /dev/null
+++ b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Services/Location/LocationService.cs
@@ -0,0 +1,28 @@
+namespace eShopOnContainers.Core.Services.Location
+{
+ using eShopOnContainers.Core.Models.Location;
+ using eShopOnContainers.Core.Services.RequestProvider;
+ using System;
+ using System.Threading.Tasks;
+
+ public class LocationService : ILocationService
+ {
+ private readonly IRequestProvider _requestProvider;
+
+ public LocationService(IRequestProvider requestProvider)
+ {
+ _requestProvider = requestProvider;
+ }
+
+ public async Task UpdateUserLocation(LocationRequest newLocReq)
+ {
+ UriBuilder builder = new UriBuilder(GlobalSetting.Instance.LocationEndpoint);
+
+ builder.Path = "api/v1/locations";
+
+ string uri = builder.ToString();
+
+ var result = await _requestProvider.PostAsync(uri, newLocReq);
+ }
+ }
+}
diff --git a/src/Mobile/eShopOnContainers/eShopOnContainers.Core/ViewModels/Base/ViewModelLocator.cs b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/ViewModels/Base/ViewModelLocator.cs
index 90abb8f09..3eda91b42 100755
--- a/src/Mobile/eShopOnContainers/eShopOnContainers.Core/ViewModels/Base/ViewModelLocator.cs
+++ b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/ViewModels/Base/ViewModelLocator.cs
@@ -11,6 +11,7 @@ using eShopOnContainers.Core.Services.Identity;
using eShopOnContainers.Core.Services.Order;
using eShopOnContainers.Core.Services.User;
using Xamarin.Forms;
+using eShopOnContainers.Core.Services.Location;
namespace eShopOnContainers.Core.ViewModels.Base
{
@@ -53,24 +54,25 @@ namespace eShopOnContainers.Core.ViewModels.Base
builder.RegisterType().As();
builder.RegisterType().As();
builder.RegisterType().As();
+ builder.RegisterType().As().SingleInstance();
- if (useMockServices)
+ if (useMockServices)
{
builder.RegisterInstance(new CatalogMockService()).As();
builder.RegisterInstance(new BasketMockService()).As();
builder.RegisterInstance(new OrderMockService()).As();
builder.RegisterInstance(new UserMockService()).As();
- UseMockService = true;
+ UseMockService = true;
}
else
{
builder.RegisterType().As().SingleInstance();
builder.RegisterType().As().SingleInstance();
builder.RegisterType().As().SingleInstance();
- builder.RegisterType().As().SingleInstance();
+ builder.RegisterType().As().SingleInstance();
- UseMockService = false;
+ UseMockService = false;
}
if (_container != null)
diff --git a/src/Mobile/eShopOnContainers/eShopOnContainers.Core/ViewModels/SettingsViewModel.cs b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/ViewModels/SettingsViewModel.cs
index 4596eb25c..8bfe9ed25 100644
--- a/src/Mobile/eShopOnContainers/eShopOnContainers.Core/ViewModels/SettingsViewModel.cs
+++ b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/ViewModels/SettingsViewModel.cs
@@ -4,38 +4,51 @@ using Xamarin.Forms;
using System.Threading.Tasks;
using eShopOnContainers.Core.Helpers;
using eShopOnContainers.Core.Models.User;
+using System;
+using eShopOnContainers.Core.Models.Location;
+using eShopOnContainers.Core.Services.Location;
namespace eShopOnContainers.Core.ViewModels
{
public class SettingsViewModel : ViewModelBase
{
- private string _title;
- private string _description;
+ private string _titleUseAzureServices;
+ private string _descriptionUseAzureServices;
private bool _useAzureServices;
+ private string _titleUseFakeLocation;
+ private string _descriptionUseFakeLocation;
+ private bool _useFakeLocation;
private string _endpoint;
+ private double _latitude;
+ private double _longitude;
+ private ILocationService _locationService;
- public SettingsViewModel()
+ public SettingsViewModel(ILocationService locationService)
{
UseAzureServices = !Settings.UseMocks;
+ _useFakeLocation = Settings.UseFakeLocation;
+ _latitude = Settings.FakeLatitude;
+ _longitude = Settings.FakeLongitude;
+ _locationService = locationService;
}
- public string Title
+ public string TitleUseAzureServices
{
- get { return _title; }
+ get { return _titleUseAzureServices; }
set
{
- _title = value;
- RaisePropertyChanged(() => Title);
+ _titleUseAzureServices = value;
+ RaisePropertyChanged(() => TitleUseAzureServices);
}
}
- public string Description
+ public string DescriptionUseAzureServices
{
- get { return _description; }
+ get { return _descriptionUseAzureServices; }
set
{
- _description = value;
- RaisePropertyChanged(() => Description);
+ _descriptionUseAzureServices = value;
+ RaisePropertyChanged(() => DescriptionUseAzureServices);
}
}
@@ -52,6 +65,39 @@ namespace eShopOnContainers.Core.ViewModels
}
}
+ public string TitleUseFakeLocation
+ {
+ get { return _titleUseFakeLocation; }
+ set
+ {
+ _titleUseFakeLocation = value;
+ RaisePropertyChanged(() => TitleUseFakeLocation);
+ }
+ }
+
+ public string DescriptionUseFakeLocation
+ {
+ get { return _descriptionUseFakeLocation; }
+ set
+ {
+ _descriptionUseFakeLocation = value;
+ RaisePropertyChanged(() => DescriptionUseFakeLocation);
+ }
+ }
+
+ public bool UseFakeLocation
+ {
+ get { return _useFakeLocation; }
+ set
+ {
+ _useFakeLocation = value;
+
+ // Save use fake location services to local storage
+ Settings.UseFakeLocation = _useFakeLocation;
+ RaisePropertyChanged(() => UseFakeLocation);
+ }
+ }
+
public string Endpoint
{
get { return _endpoint; }
@@ -68,12 +114,47 @@ namespace eShopOnContainers.Core.ViewModels
}
}
+ public double Latitude
+ {
+ get { return _latitude; }
+ set
+ {
+ _latitude = value;
+
+ UpdateLatitude(_latitude);
+
+ RaisePropertyChanged(() => Latitude);
+ }
+ }
+
+ public double Longitude
+ {
+ get { return _longitude; }
+ set
+ {
+ _longitude = value;
+
+ UpdateLongitude(_longitude);
+
+ RaisePropertyChanged(() => Longitude);
+ }
+ }
+
public ICommand ToggleMockServicesCommand => new Command(async () => await ToggleMockServicesAsync());
+ public ICommand ToggleFakeLocationCommand => new Command(() => ToggleFakeLocationAsync());
+
+ public ICommand ToggleSendLocationCommand => new Command(async () => await ToggleSendLocationAsync());
+
public override Task InitializeAsync(object navigationData)
{
UpdateInfo();
+ UpdateInfoFakeLocation();
+
Endpoint = Settings.UrlBase;
+ _latitude = Settings.FakeLatitude;
+ _longitude = Settings.FakeLongitude;
+ _useFakeLocation = Settings.UseFakeLocation;
return base.InitializeAsync(navigationData);
}
@@ -100,17 +181,48 @@ namespace eShopOnContainers.Core.ViewModels
}
}
- private void UpdateInfo()
+ private void ToggleFakeLocationAsync()
+ {
+ ViewModelLocator.RegisterDependencies(!UseAzureServices);
+ UpdateInfoFakeLocation();
+ }
+
+ private async Task ToggleSendLocationAsync()
+ {
+ LocationRequest locationRequest = new LocationRequest
+ {
+ Latitude = _latitude,
+ Longitude = _longitude
+ };
+
+ await _locationService.UpdateUserLocation(locationRequest);
+ }
+
+ private void UpdateInfo()
{
if (!UseAzureServices)
{
- Title = "Use Mock Services";
- Description = "Mock Services are simulated objects that mimic the behavior of real services using a controlled approach.";
+ TitleUseAzureServices = "Use Mock Services";
+ DescriptionUseAzureServices = "Mock Services are simulated objects that mimic the behavior of real services using a controlled approach.";
}
else
{
- Title = "Use Microservices/Containers from eShopOnContainers";
- Description = "When enabling the use of microservices/containers, the app will attempt to use real services deployed as Docker containers at the specified base endpoint, which will must be reachable through the network.";
+ TitleUseAzureServices = "Use Microservices/Containers from eShopOnContainers";
+ DescriptionUseAzureServices = "When enabling the use of microservices/containers, the app will attempt to use real services deployed as Docker containers at the specified base endpoint, which will must be reachable through the network.";
+ }
+ }
+
+ private void UpdateInfoFakeLocation()
+ {
+ if (!UseFakeLocation)
+ {
+ TitleUseFakeLocation = "Use Fake Location";
+ DescriptionUseFakeLocation = "Fake Location are added for marketing campaign testing.";
+ }
+ else
+ {
+ TitleUseFakeLocation = "Use Real Location";
+ DescriptionUseFakeLocation = "When enabling the use of real location, the app will attempt to use real location from the device.";
}
}
@@ -119,5 +231,17 @@ namespace eShopOnContainers.Core.ViewModels
// Update remote endpoint (save to local storage)
Settings.UrlBase = endpoint;
}
+
+ private void UpdateLatitude(double latitude)
+ {
+ // Update fake latitude (save to local storage)
+ Settings.FakeLatitude = latitude;
+ }
+
+ private void UpdateLongitude(double longitude)
+ {
+ // Update fake longitude (save to local storage)
+ Settings.FakeLongitude = longitude;
+ }
}
}
\ No newline at end of file
diff --git a/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Views/SettingsView.xaml b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Views/SettingsView.xaml
index 7db37dd66..a8da35daa 100644
--- a/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Views/SettingsView.xaml
+++ b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Views/SettingsView.xaml
@@ -108,11 +108,11 @@
Grid.Column="0"
Grid.Row="1">
@@ -160,8 +160,79 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Margin="12, 0, 12, 12"
+ IsVisible="{Binding UseFakeLocation}">
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Mobile/eShopOnContainers/eShopOnContainers.Core/eShopOnContainers.Core.csproj b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/eShopOnContainers.Core.csproj
index d0dd19a46..00ba88226 100644
--- a/src/Mobile/eShopOnContainers/eShopOnContainers.Core/eShopOnContainers.Core.csproj
+++ b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/eShopOnContainers.Core.csproj
@@ -1,4 +1,4 @@
-
+
@@ -70,6 +70,7 @@
+
@@ -91,6 +92,8 @@
+
+
diff --git a/src/Services/Catalog/Catalog.API/Catalog.API.csproj b/src/Services/Catalog/Catalog.API/Catalog.API.csproj
index c4cb2f679..e965440a6 100644
--- a/src/Services/Catalog/Catalog.API/Catalog.API.csproj
+++ b/src/Services/Catalog/Catalog.API/Catalog.API.csproj
@@ -30,6 +30,7 @@
+
diff --git a/src/Services/Identity/Identity.API/Configuration/Config.cs b/src/Services/Identity/Identity.API/Configuration/Config.cs
index 260989da4..b106fd5d7 100644
--- a/src/Services/Identity/Identity.API/Configuration/Config.cs
+++ b/src/Services/Identity/Identity.API/Configuration/Config.cs
@@ -12,7 +12,9 @@ namespace Identity.API.Configuration
return new List
{
new ApiResource("orders", "Orders Service"),
- new ApiResource("basket", "Basket Service")
+ new ApiResource("basket", "Basket Service"),
+ new ApiResource("marketing", "Marketing Service"),
+ new ApiResource("locations", "Locations Service")
};
}
@@ -71,7 +73,8 @@ namespace Identity.API.Configuration
IdentityServerConstants.StandardScopes.Profile,
IdentityServerConstants.StandardScopes.OfflineAccess,
"orders",
- "basket"
+ "basket",
+ "locations"
},
//Allow requesting refresh tokens for long lived API access
AllowOfflineAccess = true
@@ -86,6 +89,7 @@ namespace Identity.API.Configuration
},
ClientUri = $"{clientsUrl["Mvc"]}", // public uri of the client
AllowedGrantTypes = GrantTypes.Hybrid,
+ AllowAccessTokensViaBrowser = false,
RequireConsent = false,
AllowOfflineAccess = true,
RedirectUris = new List
@@ -102,7 +106,8 @@ namespace Identity.API.Configuration
IdentityServerConstants.StandardScopes.Profile,
IdentityServerConstants.StandardScopes.OfflineAccess,
"orders",
- "basket"
+ "basket",
+ "locations"
},
}
};
diff --git a/src/Services/Identity/Identity.API/Identity.API.csproj b/src/Services/Identity/Identity.API/Identity.API.csproj
index 4196c0625..c27a51593 100644
--- a/src/Services/Identity/Identity.API/Identity.API.csproj
+++ b/src/Services/Identity/Identity.API/Identity.API.csproj
@@ -58,6 +58,7 @@
+
@@ -69,4 +70,9 @@
+
+
+
+
+
diff --git a/src/Services/Identity/Identity.API/Migrations/20170604151240_Init-persisted-grant.Designer.cs b/src/Services/Identity/Identity.API/Migrations/20170604151240_Init-persisted-grant.Designer.cs
new file mode 100644
index 000000000..a2b93219b
--- /dev/null
+++ b/src/Services/Identity/Identity.API/Migrations/20170604151240_Init-persisted-grant.Designer.cs
@@ -0,0 +1,52 @@
+using System;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Infrastructure;
+using Microsoft.EntityFrameworkCore.Metadata;
+using Microsoft.EntityFrameworkCore.Migrations;
+using IdentityServer4.EntityFramework.DbContexts;
+
+namespace Identity.API.Migrations
+{
+ [DbContext(typeof(PersistedGrantDbContext))]
+ [Migration("20170604151240_Init-persisted-grant")]
+ partial class Initpersistedgrant
+ {
+ protected override void BuildTargetModel(ModelBuilder modelBuilder)
+ {
+ modelBuilder
+ .HasAnnotation("ProductVersion", "1.1.2")
+ .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
+
+ modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.PersistedGrant", b =>
+ {
+ b.Property("Key")
+ .HasMaxLength(200);
+
+ b.Property("ClientId")
+ .IsRequired()
+ .HasMaxLength(200);
+
+ b.Property("CreationTime");
+
+ b.Property("Data")
+ .IsRequired()
+ .HasMaxLength(50000);
+
+ b.Property("Expiration");
+
+ b.Property("SubjectId")
+ .HasMaxLength(200);
+
+ b.Property("Type")
+ .IsRequired()
+ .HasMaxLength(50);
+
+ b.HasKey("Key");
+
+ b.HasIndex("SubjectId", "ClientId", "Type");
+
+ b.ToTable("PersistedGrants");
+ });
+ }
+ }
+}
diff --git a/src/Services/Identity/Identity.API/Migrations/20170604151240_Init-persisted-grant.cs b/src/Services/Identity/Identity.API/Migrations/20170604151240_Init-persisted-grant.cs
new file mode 100644
index 000000000..51c896f5f
--- /dev/null
+++ b/src/Services/Identity/Identity.API/Migrations/20170604151240_Init-persisted-grant.cs
@@ -0,0 +1,40 @@
+using System;
+using System.Collections.Generic;
+using Microsoft.EntityFrameworkCore.Migrations;
+
+namespace Identity.API.Migrations
+{
+ public partial class Initpersistedgrant : Migration
+ {
+ protected override void Up(MigrationBuilder migrationBuilder)
+ {
+ migrationBuilder.CreateTable(
+ name: "PersistedGrants",
+ columns: table => new
+ {
+ Key = table.Column(maxLength: 200, nullable: false),
+ ClientId = table.Column(maxLength: 200, nullable: false),
+ CreationTime = table.Column(nullable: false),
+ Data = table.Column(maxLength: 50000, nullable: false),
+ Expiration = table.Column(nullable: true),
+ SubjectId = table.Column(maxLength: 200, nullable: true),
+ Type = table.Column(maxLength: 50, nullable: false)
+ },
+ constraints: table =>
+ {
+ table.PrimaryKey("PK_PersistedGrants", x => x.Key);
+ });
+
+ migrationBuilder.CreateIndex(
+ name: "IX_PersistedGrants_SubjectId_ClientId_Type",
+ table: "PersistedGrants",
+ columns: new[] { "SubjectId", "ClientId", "Type" });
+ }
+
+ protected override void Down(MigrationBuilder migrationBuilder)
+ {
+ migrationBuilder.DropTable(
+ name: "PersistedGrants");
+ }
+ }
+}
diff --git a/src/Services/Identity/Identity.API/Migrations/ConfigurationDb/20170604151338_Init-configuration.Designer.cs b/src/Services/Identity/Identity.API/Migrations/ConfigurationDb/20170604151338_Init-configuration.Designer.cs
new file mode 100644
index 000000000..9e6eb2500
--- /dev/null
+++ b/src/Services/Identity/Identity.API/Migrations/ConfigurationDb/20170604151338_Init-configuration.Designer.cs
@@ -0,0 +1,539 @@
+using System;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Infrastructure;
+using Microsoft.EntityFrameworkCore.Metadata;
+using Microsoft.EntityFrameworkCore.Migrations;
+using IdentityServer4.EntityFramework.DbContexts;
+
+namespace Identity.API.Migrations.ConfigurationDb
+{
+ [DbContext(typeof(ConfigurationDbContext))]
+ [Migration("20170604151338_Init-configuration")]
+ partial class Initconfiguration
+ {
+ protected override void BuildTargetModel(ModelBuilder modelBuilder)
+ {
+ modelBuilder
+ .HasAnnotation("ProductVersion", "1.1.2")
+ .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
+
+ modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ApiResource", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd();
+
+ b.Property("Description")
+ .HasMaxLength(1000);
+
+ b.Property("DisplayName")
+ .HasMaxLength(200);
+
+ b.Property("Enabled");
+
+ b.Property("Name")
+ .IsRequired()
+ .HasMaxLength(200);
+
+ b.HasKey("Id");
+
+ b.HasIndex("Name")
+ .IsUnique();
+
+ b.ToTable("ApiResources");
+ });
+
+ modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ApiResourceClaim", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd();
+
+ b.Property("ApiResourceId")
+ .IsRequired();
+
+ b.Property("Type")
+ .IsRequired()
+ .HasMaxLength(200);
+
+ b.HasKey("Id");
+
+ b.HasIndex("ApiResourceId");
+
+ b.ToTable("ApiClaims");
+ });
+
+ modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ApiScope", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd();
+
+ b.Property("ApiResourceId")
+ .IsRequired();
+
+ b.Property("Description")
+ .HasMaxLength(1000);
+
+ b.Property("DisplayName")
+ .HasMaxLength(200);
+
+ b.Property("Emphasize");
+
+ b.Property("Name")
+ .IsRequired()
+ .HasMaxLength(200);
+
+ b.Property("Required");
+
+ b.Property("ShowInDiscoveryDocument");
+
+ b.HasKey("Id");
+
+ b.HasIndex("ApiResourceId");
+
+ b.HasIndex("Name")
+ .IsUnique();
+
+ b.ToTable("ApiScopes");
+ });
+
+ modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ApiScopeClaim", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd();
+
+ b.Property("ApiScopeId")
+ .IsRequired();
+
+ b.Property("Type")
+ .IsRequired()
+ .HasMaxLength(200);
+
+ b.HasKey("Id");
+
+ b.HasIndex("ApiScopeId");
+
+ b.ToTable("ApiScopeClaims");
+ });
+
+ modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ApiSecret", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd();
+
+ b.Property("ApiResourceId")
+ .IsRequired();
+
+ b.Property("Description")
+ .HasMaxLength(1000);
+
+ b.Property("Expiration");
+
+ b.Property("Type")
+ .HasMaxLength(250);
+
+ b.Property("Value")
+ .HasMaxLength(2000);
+
+ b.HasKey("Id");
+
+ b.HasIndex("ApiResourceId");
+
+ b.ToTable("ApiSecrets");
+ });
+
+ modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.Client", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd();
+
+ b.Property("AbsoluteRefreshTokenLifetime");
+
+ b.Property("AccessTokenLifetime");
+
+ b.Property("AccessTokenType");
+
+ b.Property("AllowAccessTokensViaBrowser");
+
+ b.Property("AllowOfflineAccess");
+
+ b.Property("AllowPlainTextPkce");
+
+ b.Property("AllowRememberConsent");
+
+ b.Property("AlwaysIncludeUserClaimsInIdToken");
+
+ b.Property("AlwaysSendClientClaims");
+
+ b.Property("AuthorizationCodeLifetime");
+
+ b.Property("ClientId")
+ .IsRequired()
+ .HasMaxLength(200);
+
+ b.Property("ClientName")
+ .HasMaxLength(200);
+
+ b.Property("ClientUri")
+ .HasMaxLength(2000);
+
+ b.Property("EnableLocalLogin");
+
+ b.Property("Enabled");
+
+ b.Property("IdentityTokenLifetime");
+
+ b.Property("IncludeJwtId");
+
+ b.Property("LogoUri");
+
+ b.Property("LogoutSessionRequired");
+
+ b.Property("LogoutUri");
+
+ b.Property("PrefixClientClaims");
+
+ b.Property("ProtocolType")
+ .IsRequired()
+ .HasMaxLength(200);
+
+ b.Property("RefreshTokenExpiration");
+
+ b.Property("RefreshTokenUsage");
+
+ b.Property("RequireClientSecret");
+
+ b.Property("RequireConsent");
+
+ b.Property("RequirePkce");
+
+ b.Property("SlidingRefreshTokenLifetime");
+
+ b.Property("UpdateAccessTokenClaimsOnRefresh");
+
+ b.HasKey("Id");
+
+ b.HasIndex("ClientId")
+ .IsUnique();
+
+ b.ToTable("Clients");
+ });
+
+ modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientClaim", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd();
+
+ b.Property("ClientId")
+ .IsRequired();
+
+ b.Property("Type")
+ .IsRequired()
+ .HasMaxLength(250);
+
+ b.Property("Value")
+ .IsRequired()
+ .HasMaxLength(250);
+
+ b.HasKey("Id");
+
+ b.HasIndex("ClientId");
+
+ b.ToTable("ClientClaims");
+ });
+
+ modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientCorsOrigin", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd();
+
+ b.Property("ClientId")
+ .IsRequired();
+
+ b.Property("Origin")
+ .IsRequired()
+ .HasMaxLength(150);
+
+ b.HasKey("Id");
+
+ b.HasIndex("ClientId");
+
+ b.ToTable("ClientCorsOrigins");
+ });
+
+ modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientGrantType", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd();
+
+ b.Property("ClientId")
+ .IsRequired();
+
+ b.Property("GrantType")
+ .IsRequired()
+ .HasMaxLength(250);
+
+ b.HasKey("Id");
+
+ b.HasIndex("ClientId");
+
+ b.ToTable("ClientGrantTypes");
+ });
+
+ modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientIdPRestriction", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd();
+
+ b.Property("ClientId")
+ .IsRequired();
+
+ b.Property("Provider")
+ .IsRequired()
+ .HasMaxLength(200);
+
+ b.HasKey("Id");
+
+ b.HasIndex("ClientId");
+
+ b.ToTable("ClientIdPRestrictions");
+ });
+
+ modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientPostLogoutRedirectUri", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd();
+
+ b.Property("ClientId")
+ .IsRequired();
+
+ b.Property("PostLogoutRedirectUri")
+ .IsRequired()
+ .HasMaxLength(2000);
+
+ b.HasKey("Id");
+
+ b.HasIndex("ClientId");
+
+ b.ToTable("ClientPostLogoutRedirectUris");
+ });
+
+ modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientRedirectUri", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd();
+
+ b.Property("ClientId")
+ .IsRequired();
+
+ b.Property("RedirectUri")
+ .IsRequired()
+ .HasMaxLength(2000);
+
+ b.HasKey("Id");
+
+ b.HasIndex("ClientId");
+
+ b.ToTable("ClientRedirectUris");
+ });
+
+ modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientScope", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd();
+
+ b.Property("ClientId")
+ .IsRequired();
+
+ b.Property("Scope")
+ .IsRequired()
+ .HasMaxLength(200);
+
+ b.HasKey("Id");
+
+ b.HasIndex("ClientId");
+
+ b.ToTable("ClientScopes");
+ });
+
+ modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientSecret", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd();
+
+ b.Property("ClientId")
+ .IsRequired();
+
+ b.Property("Description")
+ .HasMaxLength(2000);
+
+ b.Property("Expiration");
+
+ b.Property("Type")
+ .HasMaxLength(250);
+
+ b.Property("Value")
+ .IsRequired()
+ .HasMaxLength(2000);
+
+ b.HasKey("Id");
+
+ b.HasIndex("ClientId");
+
+ b.ToTable("ClientSecrets");
+ });
+
+ modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.IdentityClaim", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd();
+
+ b.Property("IdentityResourceId")
+ .IsRequired();
+
+ b.Property("Type")
+ .IsRequired()
+ .HasMaxLength(200);
+
+ b.HasKey("Id");
+
+ b.HasIndex("IdentityResourceId");
+
+ b.ToTable("IdentityClaims");
+ });
+
+ modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.IdentityResource", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd();
+
+ b.Property("Description")
+ .HasMaxLength(1000);
+
+ b.Property("DisplayName")
+ .HasMaxLength(200);
+
+ b.Property("Emphasize");
+
+ b.Property("Enabled");
+
+ b.Property("Name")
+ .IsRequired()
+ .HasMaxLength(200);
+
+ b.Property("Required");
+
+ b.Property("ShowInDiscoveryDocument");
+
+ b.HasKey("Id");
+
+ b.HasIndex("Name")
+ .IsUnique();
+
+ b.ToTable("IdentityResources");
+ });
+
+ modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ApiResourceClaim", b =>
+ {
+ b.HasOne("IdentityServer4.EntityFramework.Entities.ApiResource", "ApiResource")
+ .WithMany("UserClaims")
+ .HasForeignKey("ApiResourceId")
+ .OnDelete(DeleteBehavior.Cascade);
+ });
+
+ modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ApiScope", b =>
+ {
+ b.HasOne("IdentityServer4.EntityFramework.Entities.ApiResource", "ApiResource")
+ .WithMany("Scopes")
+ .HasForeignKey("ApiResourceId")
+ .OnDelete(DeleteBehavior.Cascade);
+ });
+
+ modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ApiScopeClaim", b =>
+ {
+ b.HasOne("IdentityServer4.EntityFramework.Entities.ApiScope", "ApiScope")
+ .WithMany("UserClaims")
+ .HasForeignKey("ApiScopeId")
+ .OnDelete(DeleteBehavior.Cascade);
+ });
+
+ modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ApiSecret", b =>
+ {
+ b.HasOne("IdentityServer4.EntityFramework.Entities.ApiResource", "ApiResource")
+ .WithMany("Secrets")
+ .HasForeignKey("ApiResourceId")
+ .OnDelete(DeleteBehavior.Cascade);
+ });
+
+ modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientClaim", b =>
+ {
+ b.HasOne("IdentityServer4.EntityFramework.Entities.Client", "Client")
+ .WithMany("Claims")
+ .HasForeignKey("ClientId")
+ .OnDelete(DeleteBehavior.Cascade);
+ });
+
+ modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientCorsOrigin", b =>
+ {
+ b.HasOne("IdentityServer4.EntityFramework.Entities.Client", "Client")
+ .WithMany("AllowedCorsOrigins")
+ .HasForeignKey("ClientId")
+ .OnDelete(DeleteBehavior.Cascade);
+ });
+
+ modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientGrantType", b =>
+ {
+ b.HasOne("IdentityServer4.EntityFramework.Entities.Client", "Client")
+ .WithMany("AllowedGrantTypes")
+ .HasForeignKey("ClientId")
+ .OnDelete(DeleteBehavior.Cascade);
+ });
+
+ modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientIdPRestriction", b =>
+ {
+ b.HasOne("IdentityServer4.EntityFramework.Entities.Client", "Client")
+ .WithMany("IdentityProviderRestrictions")
+ .HasForeignKey("ClientId")
+ .OnDelete(DeleteBehavior.Cascade);
+ });
+
+ modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientPostLogoutRedirectUri", b =>
+ {
+ b.HasOne("IdentityServer4.EntityFramework.Entities.Client", "Client")
+ .WithMany("PostLogoutRedirectUris")
+ .HasForeignKey("ClientId")
+ .OnDelete(DeleteBehavior.Cascade);
+ });
+
+ modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientRedirectUri", b =>
+ {
+ b.HasOne("IdentityServer4.EntityFramework.Entities.Client", "Client")
+ .WithMany("RedirectUris")
+ .HasForeignKey("ClientId")
+ .OnDelete(DeleteBehavior.Cascade);
+ });
+
+ modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientScope", b =>
+ {
+ b.HasOne("IdentityServer4.EntityFramework.Entities.Client", "Client")
+ .WithMany("AllowedScopes")
+ .HasForeignKey("ClientId")
+ .OnDelete(DeleteBehavior.Cascade);
+ });
+
+ modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientSecret", b =>
+ {
+ b.HasOne("IdentityServer4.EntityFramework.Entities.Client", "Client")
+ .WithMany("ClientSecrets")
+ .HasForeignKey("ClientId")
+ .OnDelete(DeleteBehavior.Cascade);
+ });
+
+ modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.IdentityClaim", b =>
+ {
+ b.HasOne("IdentityServer4.EntityFramework.Entities.IdentityResource", "IdentityResource")
+ .WithMany("UserClaims")
+ .HasForeignKey("IdentityResourceId")
+ .OnDelete(DeleteBehavior.Cascade);
+ });
+ }
+ }
+}
diff --git a/src/Services/Identity/Identity.API/Migrations/ConfigurationDb/20170604151338_Init-configuration.cs b/src/Services/Identity/Identity.API/Migrations/ConfigurationDb/20170604151338_Init-configuration.cs
new file mode 100644
index 000000000..8cf20e865
--- /dev/null
+++ b/src/Services/Identity/Identity.API/Migrations/ConfigurationDb/20170604151338_Init-configuration.cs
@@ -0,0 +1,501 @@
+using System;
+using System.Collections.Generic;
+using Microsoft.EntityFrameworkCore.Migrations;
+using Microsoft.EntityFrameworkCore.Metadata;
+
+namespace Identity.API.Migrations.ConfigurationDb
+{
+ public partial class Initconfiguration : Migration
+ {
+ protected override void Up(MigrationBuilder migrationBuilder)
+ {
+ migrationBuilder.CreateTable(
+ name: "ApiResources",
+ columns: table => new
+ {
+ Id = table.Column(nullable: false)
+ .Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn),
+ Description = table.Column(maxLength: 1000, nullable: true),
+ DisplayName = table.Column(maxLength: 200, nullable: true),
+ Enabled = table.Column(nullable: false),
+ Name = table.Column(maxLength: 200, nullable: false)
+ },
+ constraints: table =>
+ {
+ table.PrimaryKey("PK_ApiResources", x => x.Id);
+ });
+
+ migrationBuilder.CreateTable(
+ name: "Clients",
+ columns: table => new
+ {
+ Id = table.Column(nullable: false)
+ .Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn),
+ AbsoluteRefreshTokenLifetime = table.Column(nullable: false),
+ AccessTokenLifetime = table.Column(nullable: false),
+ AccessTokenType = table.Column(nullable: false),
+ AllowAccessTokensViaBrowser = table.Column(nullable: false),
+ AllowOfflineAccess = table.Column(nullable: false),
+ AllowPlainTextPkce = table.Column(nullable: false),
+ AllowRememberConsent = table.Column(nullable: false),
+ AlwaysIncludeUserClaimsInIdToken = table.Column(nullable: false),
+ AlwaysSendClientClaims = table.Column(nullable: false),
+ AuthorizationCodeLifetime = table.Column(nullable: false),
+ ClientId = table.Column(maxLength: 200, nullable: false),
+ ClientName = table.Column(maxLength: 200, nullable: true),
+ ClientUri = table.Column(maxLength: 2000, nullable: true),
+ EnableLocalLogin = table.Column(nullable: false),
+ Enabled = table.Column(nullable: false),
+ IdentityTokenLifetime = table.Column(nullable: false),
+ IncludeJwtId = table.Column(nullable: false),
+ LogoUri = table.Column(nullable: true),
+ LogoutSessionRequired = table.Column(nullable: false),
+ LogoutUri = table.Column(nullable: true),
+ PrefixClientClaims = table.Column(nullable: false),
+ ProtocolType = table.Column(maxLength: 200, nullable: false),
+ RefreshTokenExpiration = table.Column(nullable: false),
+ RefreshTokenUsage = table.Column(nullable: false),
+ RequireClientSecret = table.Column(nullable: false),
+ RequireConsent = table.Column(nullable: false),
+ RequirePkce = table.Column(nullable: false),
+ SlidingRefreshTokenLifetime = table.Column(nullable: false),
+ UpdateAccessTokenClaimsOnRefresh = table.Column(nullable: false)
+ },
+ constraints: table =>
+ {
+ table.PrimaryKey("PK_Clients", x => x.Id);
+ });
+
+ migrationBuilder.CreateTable(
+ name: "IdentityResources",
+ columns: table => new
+ {
+ Id = table.Column(nullable: false)
+ .Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn),
+ Description = table.Column(maxLength: 1000, nullable: true),
+ DisplayName = table.Column(maxLength: 200, nullable: true),
+ Emphasize = table.Column(nullable: false),
+ Enabled = table.Column(nullable: false),
+ Name = table.Column(maxLength: 200, nullable: false),
+ Required = table.Column(nullable: false),
+ ShowInDiscoveryDocument = table.Column(nullable: false)
+ },
+ constraints: table =>
+ {
+ table.PrimaryKey("PK_IdentityResources", x => x.Id);
+ });
+
+ migrationBuilder.CreateTable(
+ name: "ApiClaims",
+ columns: table => new
+ {
+ Id = table.Column(nullable: false)
+ .Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn),
+ ApiResourceId = table.Column(nullable: false),
+ Type = table.Column(maxLength: 200, nullable: false)
+ },
+ constraints: table =>
+ {
+ table.PrimaryKey("PK_ApiClaims", x => x.Id);
+ table.ForeignKey(
+ name: "FK_ApiClaims_ApiResources_ApiResourceId",
+ column: x => x.ApiResourceId,
+ principalTable: "ApiResources",
+ principalColumn: "Id",
+ onDelete: ReferentialAction.Cascade);
+ });
+
+ migrationBuilder.CreateTable(
+ name: "ApiScopes",
+ columns: table => new
+ {
+ Id = table.Column(nullable: false)
+ .Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn),
+ ApiResourceId = table.Column(nullable: false),
+ Description = table.Column(maxLength: 1000, nullable: true),
+ DisplayName = table.Column(maxLength: 200, nullable: true),
+ Emphasize = table.Column(nullable: false),
+ Name = table.Column(maxLength: 200, nullable: false),
+ Required = table.Column(nullable: false),
+ ShowInDiscoveryDocument = table.Column(nullable: false)
+ },
+ constraints: table =>
+ {
+ table.PrimaryKey("PK_ApiScopes", x => x.Id);
+ table.ForeignKey(
+ name: "FK_ApiScopes_ApiResources_ApiResourceId",
+ column: x => x.ApiResourceId,
+ principalTable: "ApiResources",
+ principalColumn: "Id",
+ onDelete: ReferentialAction.Cascade);
+ });
+
+ migrationBuilder.CreateTable(
+ name: "ApiSecrets",
+ columns: table => new
+ {
+ Id = table.Column(nullable: false)
+ .Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn),
+ ApiResourceId = table.Column(nullable: false),
+ Description = table.Column(maxLength: 1000, nullable: true),
+ Expiration = table.Column(nullable: true),
+ Type = table.Column(maxLength: 250, nullable: true),
+ Value = table.Column(maxLength: 2000, nullable: true)
+ },
+ constraints: table =>
+ {
+ table.PrimaryKey("PK_ApiSecrets", x => x.Id);
+ table.ForeignKey(
+ name: "FK_ApiSecrets_ApiResources_ApiResourceId",
+ column: x => x.ApiResourceId,
+ principalTable: "ApiResources",
+ principalColumn: "Id",
+ onDelete: ReferentialAction.Cascade);
+ });
+
+ migrationBuilder.CreateTable(
+ name: "ClientClaims",
+ columns: table => new
+ {
+ Id = table.Column(nullable: false)
+ .Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn),
+ ClientId = table.Column(nullable: false),
+ Type = table.Column(maxLength: 250, nullable: false),
+ Value = table.Column(maxLength: 250, nullable: false)
+ },
+ constraints: table =>
+ {
+ table.PrimaryKey("PK_ClientClaims", x => x.Id);
+ table.ForeignKey(
+ name: "FK_ClientClaims_Clients_ClientId",
+ column: x => x.ClientId,
+ principalTable: "Clients",
+ principalColumn: "Id",
+ onDelete: ReferentialAction.Cascade);
+ });
+
+ migrationBuilder.CreateTable(
+ name: "ClientCorsOrigins",
+ columns: table => new
+ {
+ Id = table.Column(nullable: false)
+ .Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn),
+ ClientId = table.Column(nullable: false),
+ Origin = table.Column(maxLength: 150, nullable: false)
+ },
+ constraints: table =>
+ {
+ table.PrimaryKey("PK_ClientCorsOrigins", x => x.Id);
+ table.ForeignKey(
+ name: "FK_ClientCorsOrigins_Clients_ClientId",
+ column: x => x.ClientId,
+ principalTable: "Clients",
+ principalColumn: "Id",
+ onDelete: ReferentialAction.Cascade);
+ });
+
+ migrationBuilder.CreateTable(
+ name: "ClientGrantTypes",
+ columns: table => new
+ {
+ Id = table.Column(nullable: false)
+ .Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn),
+ ClientId = table.Column(nullable: false),
+ GrantType = table.Column(maxLength: 250, nullable: false)
+ },
+ constraints: table =>
+ {
+ table.PrimaryKey("PK_ClientGrantTypes", x => x.Id);
+ table.ForeignKey(
+ name: "FK_ClientGrantTypes_Clients_ClientId",
+ column: x => x.ClientId,
+ principalTable: "Clients",
+ principalColumn: "Id",
+ onDelete: ReferentialAction.Cascade);
+ });
+
+ migrationBuilder.CreateTable(
+ name: "ClientIdPRestrictions",
+ columns: table => new
+ {
+ Id = table.Column(nullable: false)
+ .Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn),
+ ClientId = table.Column(nullable: false),
+ Provider = table.Column(maxLength: 200, nullable: false)
+ },
+ constraints: table =>
+ {
+ table.PrimaryKey("PK_ClientIdPRestrictions", x => x.Id);
+ table.ForeignKey(
+ name: "FK_ClientIdPRestrictions_Clients_ClientId",
+ column: x => x.ClientId,
+ principalTable: "Clients",
+ principalColumn: "Id",
+ onDelete: ReferentialAction.Cascade);
+ });
+
+ migrationBuilder.CreateTable(
+ name: "ClientPostLogoutRedirectUris",
+ columns: table => new
+ {
+ Id = table.Column(nullable: false)
+ .Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn),
+ ClientId = table.Column(nullable: false),
+ PostLogoutRedirectUri = table.Column(maxLength: 2000, nullable: false)
+ },
+ constraints: table =>
+ {
+ table.PrimaryKey("PK_ClientPostLogoutRedirectUris", x => x.Id);
+ table.ForeignKey(
+ name: "FK_ClientPostLogoutRedirectUris_Clients_ClientId",
+ column: x => x.ClientId,
+ principalTable: "Clients",
+ principalColumn: "Id",
+ onDelete: ReferentialAction.Cascade);
+ });
+
+ migrationBuilder.CreateTable(
+ name: "ClientRedirectUris",
+ columns: table => new
+ {
+ Id = table.Column(nullable: false)
+ .Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn),
+ ClientId = table.Column(nullable: false),
+ RedirectUri = table.Column(maxLength: 2000, nullable: false)
+ },
+ constraints: table =>
+ {
+ table.PrimaryKey("PK_ClientRedirectUris", x => x.Id);
+ table.ForeignKey(
+ name: "FK_ClientRedirectUris_Clients_ClientId",
+ column: x => x.ClientId,
+ principalTable: "Clients",
+ principalColumn: "Id",
+ onDelete: ReferentialAction.Cascade);
+ });
+
+ migrationBuilder.CreateTable(
+ name: "ClientScopes",
+ columns: table => new
+ {
+ Id = table.Column(nullable: false)
+ .Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn),
+ ClientId = table.Column(nullable: false),
+ Scope = table.Column(maxLength: 200, nullable: false)
+ },
+ constraints: table =>
+ {
+ table.PrimaryKey("PK_ClientScopes", x => x.Id);
+ table.ForeignKey(
+ name: "FK_ClientScopes_Clients_ClientId",
+ column: x => x.ClientId,
+ principalTable: "Clients",
+ principalColumn: "Id",
+ onDelete: ReferentialAction.Cascade);
+ });
+
+ migrationBuilder.CreateTable(
+ name: "ClientSecrets",
+ columns: table => new
+ {
+ Id = table.Column(nullable: false)
+ .Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn),
+ ClientId = table.Column(nullable: false),
+ Description = table.Column(maxLength: 2000, nullable: true),
+ Expiration = table.Column(nullable: true),
+ Type = table.Column(maxLength: 250, nullable: true),
+ Value = table.Column(maxLength: 2000, nullable: false)
+ },
+ constraints: table =>
+ {
+ table.PrimaryKey("PK_ClientSecrets", x => x.Id);
+ table.ForeignKey(
+ name: "FK_ClientSecrets_Clients_ClientId",
+ column: x => x.ClientId,
+ principalTable: "Clients",
+ principalColumn: "Id",
+ onDelete: ReferentialAction.Cascade);
+ });
+
+ migrationBuilder.CreateTable(
+ name: "IdentityClaims",
+ columns: table => new
+ {
+ Id = table.Column(nullable: false)
+ .Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn),
+ IdentityResourceId = table.Column(nullable: false),
+ Type = table.Column(maxLength: 200, nullable: false)
+ },
+ constraints: table =>
+ {
+ table.PrimaryKey("PK_IdentityClaims", x => x.Id);
+ table.ForeignKey(
+ name: "FK_IdentityClaims_IdentityResources_IdentityResourceId",
+ column: x => x.IdentityResourceId,
+ principalTable: "IdentityResources",
+ principalColumn: "Id",
+ onDelete: ReferentialAction.Cascade);
+ });
+
+ migrationBuilder.CreateTable(
+ name: "ApiScopeClaims",
+ columns: table => new
+ {
+ Id = table.Column(nullable: false)
+ .Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn),
+ ApiScopeId = table.Column(nullable: false),
+ Type = table.Column(maxLength: 200, nullable: false)
+ },
+ constraints: table =>
+ {
+ table.PrimaryKey("PK_ApiScopeClaims", x => x.Id);
+ table.ForeignKey(
+ name: "FK_ApiScopeClaims_ApiScopes_ApiScopeId",
+ column: x => x.ApiScopeId,
+ principalTable: "ApiScopes",
+ principalColumn: "Id",
+ onDelete: ReferentialAction.Cascade);
+ });
+
+ migrationBuilder.CreateIndex(
+ name: "IX_ApiResources_Name",
+ table: "ApiResources",
+ column: "Name",
+ unique: true);
+
+ migrationBuilder.CreateIndex(
+ name: "IX_ApiClaims_ApiResourceId",
+ table: "ApiClaims",
+ column: "ApiResourceId");
+
+ migrationBuilder.CreateIndex(
+ name: "IX_ApiScopes_ApiResourceId",
+ table: "ApiScopes",
+ column: "ApiResourceId");
+
+ migrationBuilder.CreateIndex(
+ name: "IX_ApiScopes_Name",
+ table: "ApiScopes",
+ column: "Name",
+ unique: true);
+
+ migrationBuilder.CreateIndex(
+ name: "IX_ApiScopeClaims_ApiScopeId",
+ table: "ApiScopeClaims",
+ column: "ApiScopeId");
+
+ migrationBuilder.CreateIndex(
+ name: "IX_ApiSecrets_ApiResourceId",
+ table: "ApiSecrets",
+ column: "ApiResourceId");
+
+ migrationBuilder.CreateIndex(
+ name: "IX_Clients_ClientId",
+ table: "Clients",
+ column: "ClientId",
+ unique: true);
+
+ migrationBuilder.CreateIndex(
+ name: "IX_ClientClaims_ClientId",
+ table: "ClientClaims",
+ column: "ClientId");
+
+ migrationBuilder.CreateIndex(
+ name: "IX_ClientCorsOrigins_ClientId",
+ table: "ClientCorsOrigins",
+ column: "ClientId");
+
+ migrationBuilder.CreateIndex(
+ name: "IX_ClientGrantTypes_ClientId",
+ table: "ClientGrantTypes",
+ column: "ClientId");
+
+ migrationBuilder.CreateIndex(
+ name: "IX_ClientIdPRestrictions_ClientId",
+ table: "ClientIdPRestrictions",
+ column: "ClientId");
+
+ migrationBuilder.CreateIndex(
+ name: "IX_ClientPostLogoutRedirectUris_ClientId",
+ table: "ClientPostLogoutRedirectUris",
+ column: "ClientId");
+
+ migrationBuilder.CreateIndex(
+ name: "IX_ClientRedirectUris_ClientId",
+ table: "ClientRedirectUris",
+ column: "ClientId");
+
+ migrationBuilder.CreateIndex(
+ name: "IX_ClientScopes_ClientId",
+ table: "ClientScopes",
+ column: "ClientId");
+
+ migrationBuilder.CreateIndex(
+ name: "IX_ClientSecrets_ClientId",
+ table: "ClientSecrets",
+ column: "ClientId");
+
+ migrationBuilder.CreateIndex(
+ name: "IX_IdentityClaims_IdentityResourceId",
+ table: "IdentityClaims",
+ column: "IdentityResourceId");
+
+ migrationBuilder.CreateIndex(
+ name: "IX_IdentityResources_Name",
+ table: "IdentityResources",
+ column: "Name",
+ unique: true);
+ }
+
+ protected override void Down(MigrationBuilder migrationBuilder)
+ {
+ migrationBuilder.DropTable(
+ name: "ApiClaims");
+
+ migrationBuilder.DropTable(
+ name: "ApiScopeClaims");
+
+ migrationBuilder.DropTable(
+ name: "ApiSecrets");
+
+ migrationBuilder.DropTable(
+ name: "ClientClaims");
+
+ migrationBuilder.DropTable(
+ name: "ClientCorsOrigins");
+
+ migrationBuilder.DropTable(
+ name: "ClientGrantTypes");
+
+ migrationBuilder.DropTable(
+ name: "ClientIdPRestrictions");
+
+ migrationBuilder.DropTable(
+ name: "ClientPostLogoutRedirectUris");
+
+ migrationBuilder.DropTable(
+ name: "ClientRedirectUris");
+
+ migrationBuilder.DropTable(
+ name: "ClientScopes");
+
+ migrationBuilder.DropTable(
+ name: "ClientSecrets");
+
+ migrationBuilder.DropTable(
+ name: "IdentityClaims");
+
+ migrationBuilder.DropTable(
+ name: "ApiScopes");
+
+ migrationBuilder.DropTable(
+ name: "Clients");
+
+ migrationBuilder.DropTable(
+ name: "IdentityResources");
+
+ migrationBuilder.DropTable(
+ name: "ApiResources");
+ }
+ }
+}
diff --git a/src/Services/Identity/Identity.API/Migrations/ConfigurationDb/ConfigurationDbContextModelSnapshot.cs b/src/Services/Identity/Identity.API/Migrations/ConfigurationDb/ConfigurationDbContextModelSnapshot.cs
new file mode 100644
index 000000000..7c725f5ae
--- /dev/null
+++ b/src/Services/Identity/Identity.API/Migrations/ConfigurationDb/ConfigurationDbContextModelSnapshot.cs
@@ -0,0 +1,538 @@
+using System;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Infrastructure;
+using Microsoft.EntityFrameworkCore.Metadata;
+using Microsoft.EntityFrameworkCore.Migrations;
+using IdentityServer4.EntityFramework.DbContexts;
+
+namespace Identity.API.Migrations.ConfigurationDb
+{
+ [DbContext(typeof(ConfigurationDbContext))]
+ partial class ConfigurationDbContextModelSnapshot : ModelSnapshot
+ {
+ protected override void BuildModel(ModelBuilder modelBuilder)
+ {
+ modelBuilder
+ .HasAnnotation("ProductVersion", "1.1.2")
+ .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
+
+ modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ApiResource", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd();
+
+ b.Property("Description")
+ .HasMaxLength(1000);
+
+ b.Property("DisplayName")
+ .HasMaxLength(200);
+
+ b.Property("Enabled");
+
+ b.Property("Name")
+ .IsRequired()
+ .HasMaxLength(200);
+
+ b.HasKey("Id");
+
+ b.HasIndex("Name")
+ .IsUnique();
+
+ b.ToTable("ApiResources");
+ });
+
+ modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ApiResourceClaim", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd();
+
+ b.Property("ApiResourceId")
+ .IsRequired();
+
+ b.Property("Type")
+ .IsRequired()
+ .HasMaxLength(200);
+
+ b.HasKey("Id");
+
+ b.HasIndex("ApiResourceId");
+
+ b.ToTable("ApiClaims");
+ });
+
+ modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ApiScope", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd();
+
+ b.Property("ApiResourceId")
+ .IsRequired();
+
+ b.Property("Description")
+ .HasMaxLength(1000);
+
+ b.Property("DisplayName")
+ .HasMaxLength(200);
+
+ b.Property("Emphasize");
+
+ b.Property("Name")
+ .IsRequired()
+ .HasMaxLength(200);
+
+ b.Property("Required");
+
+ b.Property("ShowInDiscoveryDocument");
+
+ b.HasKey("Id");
+
+ b.HasIndex("ApiResourceId");
+
+ b.HasIndex("Name")
+ .IsUnique();
+
+ b.ToTable("ApiScopes");
+ });
+
+ modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ApiScopeClaim", b =>
+ {
+ b.Property