Merge from Dev
This commit is contained in:
commit
395160e6d1
@ -21,6 +21,6 @@ try {
|
|||||||
Write-Host "Rule found"
|
Write-Host "Rule found"
|
||||||
}
|
}
|
||||||
catch [Exception] {
|
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-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-5105 -Protocol tcp -RemoteAddress Any -RemotePort Any -Direction Outbound
|
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
|
||||||
}
|
}
|
@ -80,4 +80,19 @@ services:
|
|||||||
- SA_PASSWORD=Pass@word
|
- SA_PASSWORD=Pass@word
|
||||||
- ACCEPT_EULA=Y
|
- ACCEPT_EULA=Y
|
||||||
ports:
|
ports:
|
||||||
- "5433:1433"
|
- "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"
|
@ -53,9 +53,20 @@ services:
|
|||||||
- ordering.api
|
- ordering.api
|
||||||
- identity.api
|
- identity.api
|
||||||
- basket.api
|
- basket.api
|
||||||
|
|
||||||
|
locations.api:
|
||||||
|
image: locations.api
|
||||||
|
build:
|
||||||
|
context: ./src/Services/Location/Locations.API
|
||||||
|
dockerfile: Dockerfile
|
||||||
|
depends_on:
|
||||||
|
- nosql.data
|
||||||
|
|
||||||
sql.data:
|
sql.data:
|
||||||
image: microsoft/mssql-server-windows
|
image: microsoft/mssql-server-windows
|
||||||
|
|
||||||
|
nosql.data:
|
||||||
|
image: mongo:windowsservercore
|
||||||
|
|
||||||
basket.data:
|
basket.data:
|
||||||
image: redis:nanoserver
|
image: redis:nanoserver
|
||||||
|
@ -49,6 +49,15 @@ services:
|
|||||||
ports:
|
ports:
|
||||||
- "5102:80"
|
- "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:
|
webspa:
|
||||||
environment:
|
environment:
|
||||||
- ASPNETCORE_ENVIRONMENT=Development
|
- ASPNETCORE_ENVIRONMENT=Development
|
||||||
@ -83,6 +92,10 @@ services:
|
|||||||
ports:
|
ports:
|
||||||
- "5433:1433"
|
- "5433:1433"
|
||||||
|
|
||||||
|
nosql.data:
|
||||||
|
ports:
|
||||||
|
- "27017:27017"
|
||||||
|
|
||||||
webstatus:
|
webstatus:
|
||||||
environment:
|
environment:
|
||||||
- ASPNETCORE_ENVIRONMENT=Development
|
- ASPNETCORE_ENVIRONMENT=Development
|
||||||
@ -95,3 +108,14 @@ services:
|
|||||||
- spa=http://webspa/hc
|
- spa=http://webspa/hc
|
||||||
ports:
|
ports:
|
||||||
- "5107:80"
|
- "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"
|
@ -54,6 +54,15 @@ services:
|
|||||||
ports:
|
ports:
|
||||||
- "5102:80"
|
- "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:
|
webspa:
|
||||||
environment:
|
environment:
|
||||||
- ASPNETCORE_ENVIRONMENT=Production
|
- ASPNETCORE_ENVIRONMENT=Production
|
||||||
|
@ -61,6 +61,22 @@ services:
|
|||||||
labels:
|
labels:
|
||||||
- "com.microsoft.visualstudio.targetoperatingsystem=linux"
|
- "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:
|
webspa:
|
||||||
image: eshop/webspa:dev
|
image: eshop/webspa:dev
|
||||||
build:
|
build:
|
||||||
@ -105,3 +121,18 @@ services:
|
|||||||
entrypoint: tail -f /dev/null
|
entrypoint: tail -f /dev/null
|
||||||
labels:
|
labels:
|
||||||
- "com.microsoft.visualstudio.targetoperatingsystem=linux"
|
- "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"
|
||||||
|
@ -41,6 +41,16 @@ services:
|
|||||||
labels:
|
labels:
|
||||||
- "com.microsoft.visualstudio.targetoperatingsystem=linux"
|
- "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:
|
webspa:
|
||||||
build:
|
build:
|
||||||
args:
|
args:
|
||||||
@ -70,3 +80,13 @@ services:
|
|||||||
entrypoint: tail -f /dev/null
|
entrypoint: tail -f /dev/null
|
||||||
labels:
|
labels:
|
||||||
- "com.microsoft.visualstudio.targetoperatingsystem=linux"
|
- "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"
|
||||||
|
@ -36,6 +36,15 @@ services:
|
|||||||
depends_on:
|
depends_on:
|
||||||
- sql.data
|
- sql.data
|
||||||
|
|
||||||
|
marketing.api:
|
||||||
|
image: eshop/marketing.api
|
||||||
|
build:
|
||||||
|
context: ./src/Services/Marketing/Marketing.API
|
||||||
|
dockerfile: Dockerfile
|
||||||
|
depends_on:
|
||||||
|
- sql.data
|
||||||
|
- identity.api
|
||||||
|
|
||||||
webspa:
|
webspa:
|
||||||
image: eshop/webspa
|
image: eshop/webspa
|
||||||
build:
|
build:
|
||||||
@ -59,6 +68,9 @@ services:
|
|||||||
sql.data:
|
sql.data:
|
||||||
image: microsoft/mssql-server-linux
|
image: microsoft/mssql-server-linux
|
||||||
|
|
||||||
|
nosql.data:
|
||||||
|
image: mongo
|
||||||
|
|
||||||
basket.data:
|
basket.data:
|
||||||
image: redis
|
image: redis
|
||||||
ports:
|
ports:
|
||||||
@ -74,4 +86,11 @@ services:
|
|||||||
build:
|
build:
|
||||||
context: ./src/Web/WebStatus
|
context: ./src/Web/WebStatus
|
||||||
dockerfile: Dockerfile
|
dockerfile: Dockerfile
|
||||||
|
|
||||||
|
locations.api:
|
||||||
|
image: locations.api
|
||||||
|
build:
|
||||||
|
context: ./src/Services/Location/Locations.API
|
||||||
|
dockerfile: Dockerfile
|
||||||
|
depends_on:
|
||||||
|
- nosql.data
|
@ -76,6 +76,18 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Extensions.Health
|
|||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EventBus.Tests", "src\BuildingBlocks\EventBus\EventBus.Tests\EventBus.Tests.csproj", "{89D80DF1-32E1-4AAF-970F-DA0AA6881F9D}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EventBus.Tests", "src\BuildingBlocks\EventBus\EventBus.Tests\EventBus.Tests.csproj", "{89D80DF1-32E1-4AAF-970F-DA0AA6881F9D}"
|
||||||
EndProject
|
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
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
Ad-Hoc|Any CPU = Ad-Hoc|Any CPU
|
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|x64.Build.0 = Release|Any CPU
|
||||||
{89D80DF1-32E1-4AAF-970F-DA0AA6881F9D}.Release|x86.ActiveCfg = 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
|
{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
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
@ -1038,5 +1194,15 @@ Global
|
|||||||
{22A0F9C1-2D4A-4107-95B7-8459E6688BC5} = {A81ECBC2-6B00-4DCD-8388-469174033379}
|
{22A0F9C1-2D4A-4107-95B7-8459E6688BC5} = {A81ECBC2-6B00-4DCD-8388-469174033379}
|
||||||
{4BD76717-3102-4969-8C2C-BAAA3F0263B6} = {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}
|
{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
|
EndGlobalSection
|
||||||
EndGlobal
|
EndGlobal
|
||||||
|
@ -58,7 +58,7 @@ ExecKube -cmd 'delete configmap urls'
|
|||||||
# start sql, rabbitmq, frontend deploymentsExecKube -cmd 'delete configmap config-files'
|
# start sql, rabbitmq, frontend deploymentsExecKube -cmd 'delete configmap config-files'
|
||||||
ExecKube -cmd 'create configmap config-files --from-file=nginx-conf=nginx.conf'
|
ExecKube -cmd 'create configmap config-files --from-file=nginx-conf=nginx.conf'
|
||||||
ExecKube -cmd 'label configmap config-files app=eshop'
|
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
|
# building and publishing docker images not necessary when deploying through CI VSTS
|
||||||
if(-not $deployCI) {
|
if(-not $deployCI) {
|
||||||
|
@ -85,6 +85,10 @@ spec:
|
|||||||
value: http://0.0.0.0:80/identity
|
value: http://0.0.0.0:80/identity
|
||||||
- name: ConnectionStrings__DefaultConnection
|
- name: ConnectionStrings__DefaultConnection
|
||||||
value: "Server=sql-data;Initial Catalog=Microsoft.eShopOnContainers.Services.IdentityDb;User Id=sa;Password=Pass@word"
|
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
|
- name: MvcClient
|
||||||
valueFrom:
|
valueFrom:
|
||||||
configMapKeyRef:
|
configMapKeyRef:
|
||||||
@ -152,6 +156,10 @@ spec:
|
|||||||
env:
|
env:
|
||||||
- name: ASPNETCORE_URLS
|
- name: ASPNETCORE_URLS
|
||||||
value: http://0.0.0.0:80/webmvc
|
value: http://0.0.0.0:80/webmvc
|
||||||
|
- name: DPConnectionString
|
||||||
|
value: keystore-data
|
||||||
|
- name: IsClusterEnv
|
||||||
|
value: 'True'
|
||||||
- name: BasketUrl
|
- name: BasketUrl
|
||||||
valueFrom:
|
valueFrom:
|
||||||
configMapKeyRef:
|
configMapKeyRef:
|
||||||
@ -255,6 +263,10 @@ spec:
|
|||||||
env:
|
env:
|
||||||
- name: ASPNETCORE_URLS
|
- name: ASPNETCORE_URLS
|
||||||
value: http://0.0.0.0:80
|
value: http://0.0.0.0:80
|
||||||
|
- name: DPConnectionString
|
||||||
|
value: keystore-data
|
||||||
|
- name: IsClusterEnv
|
||||||
|
value: 'True'
|
||||||
- name: BasketUrl
|
- name: BasketUrl
|
||||||
valueFrom:
|
valueFrom:
|
||||||
configMapKeyRef:
|
configMapKeyRef:
|
||||||
|
29
k8s/keystore-data.yaml
Normal file
29
k8s/keystore-data.yaml
Normal file
@ -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
|
||||||
|
|
@ -0,0 +1,13 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>netcoreapp1.1</TargetFramework>
|
||||||
|
<RootNamespace>Microsoft.eShopOnContainers.BuildingBlocks</RootNamespace>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Microsoft.AspNetCore.DataProtection" Version="1.1.2" />
|
||||||
|
<PackageReference Include="StackExchange.Redis" Version="1.2.3" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
@ -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;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Extension methods for <see cref="IDataProtectionBuilder"/> for configuring
|
||||||
|
/// data protection options.
|
||||||
|
/// </summary>
|
||||||
|
public static class DataProtectionBuilderExtensions
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Sets up data protection to persist session keys in Redis.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="builder">The <see cref="IDataProtectionBuilder"/> used to set up data protection options.</param>
|
||||||
|
/// <param name="redisConnectionString">The connection string specifying the Redis instance and database for key storage.</param>
|
||||||
|
/// <returns>
|
||||||
|
/// The <paramref name="builder" /> for continued configuration.
|
||||||
|
/// </returns>
|
||||||
|
/// <exception cref="System.ArgumentNullException">
|
||||||
|
/// Thrown if <paramref name="builder" /> or <paramref name="redisConnectionString" /> is <see langword="null" />.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.ArgumentException">
|
||||||
|
/// Thrown if <paramref name="redisConnectionString" /> is empty.
|
||||||
|
/// </exception>
|
||||||
|
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<IXmlRepository>(services =>
|
||||||
|
new RedisXmlRepository(ips.First().ToString(), services.GetRequiredService<ILogger<RedisXmlRepository>>())));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Updates an <see cref="IDataProtectionBuilder"/> to use the service of
|
||||||
|
/// a specific type, removing all other services of that type.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="builder">The <see cref="IDataProtectionBuilder"/> that should use the specified service.</param>
|
||||||
|
/// <param name="descriptor">The <see cref="ServiceDescriptor"/> with the service the <paramref name="builder" /> should use.</param>
|
||||||
|
/// <returns>
|
||||||
|
/// The <paramref name="builder" /> for continued configuration.
|
||||||
|
/// </returns>
|
||||||
|
/// <exception cref="System.ArgumentNullException">
|
||||||
|
/// Thrown if <paramref name="builder" /> or <paramref name="descriptor" /> is <see langword="null" />.
|
||||||
|
/// </exception>
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -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;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Key repository that stores XML encrypted keys in a Redis distributed cache.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// <para>
|
||||||
|
/// 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.)
|
||||||
|
/// </para>
|
||||||
|
/// <para>
|
||||||
|
/// 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.
|
||||||
|
/// </para>
|
||||||
|
/// <para>
|
||||||
|
/// Consumers of the repository are responsible for caching the XML items as needed.
|
||||||
|
/// Typically repositories are consumed by things like <see cref="Microsoft.AspNetCore.DataProtection.KeyManagement.KeyRingProvider"/>
|
||||||
|
/// which generates <see cref="Microsoft.AspNetCore.DataProtection.KeyManagement.Internal.CacheableKeyRing"/>
|
||||||
|
/// values that get cached. The mechanism is already optimized for caching so there's
|
||||||
|
/// no need to create a redundant cache.
|
||||||
|
/// </para>
|
||||||
|
/// </remarks>
|
||||||
|
/// <seealso cref="Microsoft.AspNetCore.DataProtection.Repositories.IXmlRepository" />
|
||||||
|
/// <seealso cref="System.IDisposable" />
|
||||||
|
public class RedisXmlRepository : IXmlRepository, IDisposable
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The root cache key for XML items stored in Redis
|
||||||
|
/// </summary>
|
||||||
|
public static readonly string RedisHashKey = "DataProtectionXmlRepository";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The connection to the Redis backing store.
|
||||||
|
/// </summary>
|
||||||
|
private IConnectionMultiplexer _connection;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Flag indicating whether the object has been disposed.
|
||||||
|
/// </summary>
|
||||||
|
private bool _disposed = false;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="RedisXmlRepository"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="connectionString">
|
||||||
|
/// The Redis connection string.
|
||||||
|
/// </param>
|
||||||
|
/// <param name="logger">
|
||||||
|
/// The <see cref="ILogger{T}"/> used to log diagnostic messages.
|
||||||
|
/// </param>
|
||||||
|
/// <exception cref="System.ArgumentNullException">
|
||||||
|
/// Thrown if <paramref name="connectionString" /> or <paramref name="logger" /> is <see langword="null" />.
|
||||||
|
/// </exception>
|
||||||
|
public RedisXmlRepository(string connectionString, ILogger<RedisXmlRepository> logger)
|
||||||
|
: this(ConnectionMultiplexer.Connect(connectionString), logger)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="RedisXmlRepository"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="connection">
|
||||||
|
/// The Redis database connection.
|
||||||
|
/// </param>
|
||||||
|
/// <param name="logger">
|
||||||
|
/// The <see cref="ILogger{T}"/> used to log diagnostic messages.
|
||||||
|
/// </param>
|
||||||
|
/// <exception cref="System.ArgumentNullException">
|
||||||
|
/// Thrown if <paramref name="connection" /> or <paramref name="logger" /> is <see langword="null" />.
|
||||||
|
/// </exception>
|
||||||
|
public RedisXmlRepository(IConnectionMultiplexer connection, ILogger<RedisXmlRepository> 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the logger.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>
|
||||||
|
/// The <see cref="ILogger{T}"/> used to log diagnostic messages.
|
||||||
|
/// </value>
|
||||||
|
public ILogger<RedisXmlRepository> Logger { get; private set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Performs application-defined tasks associated with freeing, releasing,
|
||||||
|
/// or resetting unmanaged resources.
|
||||||
|
/// </summary>
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
this.Dispose(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets all top-level XML elements in the repository.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>
|
||||||
|
/// An <see cref="IReadOnlyCollection{T}"/> with the set of elements
|
||||||
|
/// stored in the repository.
|
||||||
|
/// </returns>
|
||||||
|
public IReadOnlyCollection<XElement> GetAllElements()
|
||||||
|
{
|
||||||
|
var database = this._connection.GetDatabase();
|
||||||
|
var hash = database.HashGetAll(RedisHashKey);
|
||||||
|
var elements = new List<XElement>();
|
||||||
|
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Adds a top-level XML element to the repository.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="element">The element to add.</param>
|
||||||
|
/// <param name="friendlyName">
|
||||||
|
/// 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.
|
||||||
|
/// </param>
|
||||||
|
/// <remarks>
|
||||||
|
/// The <paramref name="friendlyName" /> parameter must be unique if specified.
|
||||||
|
/// For instance, it could be the ID of the key being stored.
|
||||||
|
/// </remarks>
|
||||||
|
/// <exception cref="System.ArgumentNullException">
|
||||||
|
/// Thrown if <paramref name="element" /> is <see langword="null" />.
|
||||||
|
/// </exception>
|
||||||
|
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());
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Releases unmanaged and - optionally - managed resources.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="disposing">
|
||||||
|
/// <see langword="true" /> to release both managed and unmanaged resources;
|
||||||
|
/// <see langword="false" /> to release only unmanaged resources.
|
||||||
|
/// </param>
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -43,6 +43,8 @@
|
|||||||
|
|
||||||
public string IdentityEndpoint { get; set; }
|
public string IdentityEndpoint { get; set; }
|
||||||
|
|
||||||
|
public string LocationEndpoint { get; set; }
|
||||||
|
|
||||||
public string UserInfoEndpoint { get; set; }
|
public string UserInfoEndpoint { get; set; }
|
||||||
|
|
||||||
public string LogoutEndpoint { get; set; }
|
public string LogoutEndpoint { get; set; }
|
||||||
@ -62,6 +64,7 @@
|
|||||||
LogoutEndpoint = string.Format("{0}:5105/connect/endsession", baseEndpoint);
|
LogoutEndpoint = string.Format("{0}:5105/connect/endsession", baseEndpoint);
|
||||||
IdentityCallback = string.Format("{0}:5105/xamarincallback", baseEndpoint);
|
IdentityCallback = string.Format("{0}:5105/xamarincallback", baseEndpoint);
|
||||||
LogoutCallback = string.Format("{0}:5105/Account/Redirecting", baseEndpoint);
|
LogoutCallback = string.Format("{0}:5105/Account/Redirecting", baseEndpoint);
|
||||||
|
LocationEndpoint = string.Format("{0}:5109", baseEndpoint);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -24,9 +24,13 @@ namespace eShopOnContainers.Core.Helpers
|
|||||||
private const string IdToken = "id_token";
|
private const string IdToken = "id_token";
|
||||||
private const string IdUseMocks = "use_mocks";
|
private const string IdUseMocks = "use_mocks";
|
||||||
private const string IdUrlBase = "url_base";
|
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 AccessTokenDefault = string.Empty;
|
||||||
private static readonly string IdTokenDefault = string.Empty;
|
private static readonly string IdTokenDefault = string.Empty;
|
||||||
private static readonly bool UseMocksDefault = true;
|
private static readonly bool UseMocksDefault = true;
|
||||||
|
private static readonly bool UseFakeLocationDefault = false;
|
||||||
private static readonly string UrlBaseDefault = GlobalSetting.Instance.BaseEndpoint;
|
private static readonly string UrlBaseDefault = GlobalSetting.Instance.BaseEndpoint;
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
@ -78,5 +82,40 @@ namespace eShopOnContainers.Core.Helpers
|
|||||||
AppSettings.AddOrUpdateValue<string>(IdUrlBase, value);
|
AppSettings.AddOrUpdateValue<string>(IdUrlBase, value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static bool UseFakeLocation
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return AppSettings.GetValueOrDefault<bool>(IdUseFakeLocation, UseFakeLocationDefault);
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
AppSettings.AddOrUpdateValue<bool>(IdUseFakeLocation, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static double FakeLatitude
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return AppSettings.GetValueOrDefault<double>(IdFakeLatitude);
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
AppSettings.AddOrUpdateValue<double>(IdFakeLatitude, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public static double FakeLongitude
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return AppSettings.GetValueOrDefault<double>(IdFakeLongitude);
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
AppSettings.AddOrUpdateValue<double>(IdFakeLongitude, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -0,0 +1,8 @@
|
|||||||
|
namespace eShopOnContainers.Core.Models.Location
|
||||||
|
{
|
||||||
|
public class LocationRequest
|
||||||
|
{
|
||||||
|
public double Longitude { get; set; }
|
||||||
|
public double Latitude { get; set; }
|
||||||
|
}
|
||||||
|
}
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -11,6 +11,7 @@ using eShopOnContainers.Core.Services.Identity;
|
|||||||
using eShopOnContainers.Core.Services.Order;
|
using eShopOnContainers.Core.Services.Order;
|
||||||
using eShopOnContainers.Core.Services.User;
|
using eShopOnContainers.Core.Services.User;
|
||||||
using Xamarin.Forms;
|
using Xamarin.Forms;
|
||||||
|
using eShopOnContainers.Core.Services.Location;
|
||||||
|
|
||||||
namespace eShopOnContainers.Core.ViewModels.Base
|
namespace eShopOnContainers.Core.ViewModels.Base
|
||||||
{
|
{
|
||||||
@ -53,24 +54,25 @@ namespace eShopOnContainers.Core.ViewModels.Base
|
|||||||
builder.RegisterType<OpenUrlService>().As<IOpenUrlService>();
|
builder.RegisterType<OpenUrlService>().As<IOpenUrlService>();
|
||||||
builder.RegisterType<IdentityService>().As<IIdentityService>();
|
builder.RegisterType<IdentityService>().As<IIdentityService>();
|
||||||
builder.RegisterType<RequestProvider>().As<IRequestProvider>();
|
builder.RegisterType<RequestProvider>().As<IRequestProvider>();
|
||||||
|
builder.RegisterType<LocationService>().As<ILocationService>().SingleInstance();
|
||||||
|
|
||||||
if (useMockServices)
|
if (useMockServices)
|
||||||
{
|
{
|
||||||
builder.RegisterInstance(new CatalogMockService()).As<ICatalogService>();
|
builder.RegisterInstance(new CatalogMockService()).As<ICatalogService>();
|
||||||
builder.RegisterInstance(new BasketMockService()).As<IBasketService>();
|
builder.RegisterInstance(new BasketMockService()).As<IBasketService>();
|
||||||
builder.RegisterInstance(new OrderMockService()).As<IOrderService>();
|
builder.RegisterInstance(new OrderMockService()).As<IOrderService>();
|
||||||
builder.RegisterInstance(new UserMockService()).As<IUserService>();
|
builder.RegisterInstance(new UserMockService()).As<IUserService>();
|
||||||
|
|
||||||
UseMockService = true;
|
UseMockService = true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
builder.RegisterType<CatalogService>().As<ICatalogService>().SingleInstance();
|
builder.RegisterType<CatalogService>().As<ICatalogService>().SingleInstance();
|
||||||
builder.RegisterType<BasketService>().As<IBasketService>().SingleInstance();
|
builder.RegisterType<BasketService>().As<IBasketService>().SingleInstance();
|
||||||
builder.RegisterType<OrderService>().As<IOrderService>().SingleInstance();
|
builder.RegisterType<OrderService>().As<IOrderService>().SingleInstance();
|
||||||
builder.RegisterType<UserService>().As<IUserService>().SingleInstance();
|
builder.RegisterType<UserService>().As<IUserService>().SingleInstance();
|
||||||
|
|
||||||
UseMockService = false;
|
UseMockService = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_container != null)
|
if (_container != null)
|
||||||
|
@ -4,38 +4,51 @@ using Xamarin.Forms;
|
|||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using eShopOnContainers.Core.Helpers;
|
using eShopOnContainers.Core.Helpers;
|
||||||
using eShopOnContainers.Core.Models.User;
|
using eShopOnContainers.Core.Models.User;
|
||||||
|
using System;
|
||||||
|
using eShopOnContainers.Core.Models.Location;
|
||||||
|
using eShopOnContainers.Core.Services.Location;
|
||||||
|
|
||||||
namespace eShopOnContainers.Core.ViewModels
|
namespace eShopOnContainers.Core.ViewModels
|
||||||
{
|
{
|
||||||
public class SettingsViewModel : ViewModelBase
|
public class SettingsViewModel : ViewModelBase
|
||||||
{
|
{
|
||||||
private string _title;
|
private string _titleUseAzureServices;
|
||||||
private string _description;
|
private string _descriptionUseAzureServices;
|
||||||
private bool _useAzureServices;
|
private bool _useAzureServices;
|
||||||
|
private string _titleUseFakeLocation;
|
||||||
|
private string _descriptionUseFakeLocation;
|
||||||
|
private bool _useFakeLocation;
|
||||||
private string _endpoint;
|
private string _endpoint;
|
||||||
|
private double _latitude;
|
||||||
|
private double _longitude;
|
||||||
|
private ILocationService _locationService;
|
||||||
|
|
||||||
public SettingsViewModel()
|
public SettingsViewModel(ILocationService locationService)
|
||||||
{
|
{
|
||||||
UseAzureServices = !Settings.UseMocks;
|
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
|
set
|
||||||
{
|
{
|
||||||
_title = value;
|
_titleUseAzureServices = value;
|
||||||
RaisePropertyChanged(() => Title);
|
RaisePropertyChanged(() => TitleUseAzureServices);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public string Description
|
public string DescriptionUseAzureServices
|
||||||
{
|
{
|
||||||
get { return _description; }
|
get { return _descriptionUseAzureServices; }
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
_description = value;
|
_descriptionUseAzureServices = value;
|
||||||
RaisePropertyChanged(() => Description);
|
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
|
public string Endpoint
|
||||||
{
|
{
|
||||||
get { return _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 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)
|
public override Task InitializeAsync(object navigationData)
|
||||||
{
|
{
|
||||||
UpdateInfo();
|
UpdateInfo();
|
||||||
|
UpdateInfoFakeLocation();
|
||||||
|
|
||||||
Endpoint = Settings.UrlBase;
|
Endpoint = Settings.UrlBase;
|
||||||
|
_latitude = Settings.FakeLatitude;
|
||||||
|
_longitude = Settings.FakeLongitude;
|
||||||
|
_useFakeLocation = Settings.UseFakeLocation;
|
||||||
return base.InitializeAsync(navigationData);
|
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)
|
if (!UseAzureServices)
|
||||||
{
|
{
|
||||||
Title = "Use Mock Services";
|
TitleUseAzureServices = "Use Mock Services";
|
||||||
Description = "Mock Services are simulated objects that mimic the behavior of real services using a controlled approach.";
|
DescriptionUseAzureServices = "Mock Services are simulated objects that mimic the behavior of real services using a controlled approach.";
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Title = "Use Microservices/Containers from eShopOnContainers";
|
TitleUseAzureServices = "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.";
|
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)
|
// Update remote endpoint (save to local storage)
|
||||||
Settings.UrlBase = endpoint;
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -108,11 +108,11 @@
|
|||||||
Grid.Column="0"
|
Grid.Column="0"
|
||||||
Grid.Row="1">
|
Grid.Row="1">
|
||||||
<Label
|
<Label
|
||||||
Text="{Binding Title}"
|
Text="{Binding TitleUseAzureServices}"
|
||||||
TextColor="{StaticResource GreenColor}"
|
TextColor="{StaticResource GreenColor}"
|
||||||
Style="{StaticResource SettingsTitleStyle}"/>
|
Style="{StaticResource SettingsTitleStyle}"/>
|
||||||
<Label
|
<Label
|
||||||
Text="{Binding Description}"
|
Text="{Binding DescriptionUseAzureServices}"
|
||||||
Style="{StaticResource SettingsDescriptionStyle}"/>
|
Style="{StaticResource SettingsDescriptionStyle}"/>
|
||||||
</StackLayout>
|
</StackLayout>
|
||||||
<!-- ON / OFF -->
|
<!-- ON / OFF -->
|
||||||
@ -160,8 +160,79 @@
|
|||||||
<Grid
|
<Grid
|
||||||
Grid.Row="3"
|
Grid.Row="3"
|
||||||
Grid.Column="0"
|
Grid.Column="0"
|
||||||
|
Grid.ColumnSpan="2"/>
|
||||||
|
<StackLayout
|
||||||
|
Grid.Column="0"
|
||||||
|
Grid.Row="4">
|
||||||
|
<Label
|
||||||
|
Text="{Binding TitleUseFakeLocation}"
|
||||||
|
TextColor="{StaticResource GreenColor}"
|
||||||
|
Style="{StaticResource SettingsTitleStyle}"/>
|
||||||
|
<Label
|
||||||
|
Text="{Binding DescriptionUseFakeLocation}"
|
||||||
|
Style="{StaticResource SettingsDescriptionStyle}"/>
|
||||||
|
</StackLayout>
|
||||||
|
<!-- ON / OFF -->
|
||||||
|
<controls:ToggleButton
|
||||||
|
Grid.Column="1"
|
||||||
|
Grid.Row="4"
|
||||||
|
Animate="True"
|
||||||
|
Checked="{Binding UseFakeLocation, Mode=TwoWay}"
|
||||||
|
Command="{Binding ToggleFakeLocationCommand}"
|
||||||
|
Style="{StaticResource SettingsToggleButtonStyle}">
|
||||||
|
<controls:ToggleButton.CheckedImage>
|
||||||
|
<OnPlatform x:TypeArguments="ImageSource"
|
||||||
|
Android="switch_on.png"
|
||||||
|
iOS="switchOn.png"
|
||||||
|
WinPhone="Assets/switchOn.png"/>
|
||||||
|
</controls:ToggleButton.CheckedImage>
|
||||||
|
<controls:ToggleButton.UnCheckedImage>
|
||||||
|
<OnPlatform x:TypeArguments="ImageSource"
|
||||||
|
Android="switch_off.png"
|
||||||
|
iOS="switchOff.png"
|
||||||
|
WinPhone="Assets/switchOff.png"/>
|
||||||
|
</controls:ToggleButton.UnCheckedImage>
|
||||||
|
</controls:ToggleButton>
|
||||||
|
<!-- ENDPOINT -->
|
||||||
|
<StackLayout
|
||||||
|
Grid.Row="5"
|
||||||
|
Grid.Column="0"
|
||||||
Grid.ColumnSpan="2"
|
Grid.ColumnSpan="2"
|
||||||
BackgroundColor="Gray"/>
|
Margin="12, 0, 12, 12"
|
||||||
|
IsVisible="{Binding UseFakeLocation}">
|
||||||
|
<Label
|
||||||
|
Text="Latitude"
|
||||||
|
Style="{StaticResource HeaderLabelStyle}"/>
|
||||||
|
<Entry
|
||||||
|
Text="{Binding Latitude, Mode=TwoWay}"
|
||||||
|
Keyboard="Numeric">
|
||||||
|
<Entry.Style>
|
||||||
|
<OnPlatform
|
||||||
|
x:TypeArguments="Style"
|
||||||
|
iOS="{StaticResource EntryStyle}"
|
||||||
|
Android="{StaticResource EntryStyle}"
|
||||||
|
WinPhone="{StaticResource UwpEntryStyle}"/>
|
||||||
|
</Entry.Style>
|
||||||
|
</Entry>
|
||||||
|
<Label
|
||||||
|
Text="Longitude"
|
||||||
|
Style="{StaticResource HeaderLabelStyle}"/>
|
||||||
|
<Entry
|
||||||
|
Text="{Binding Longitude, Mode=TwoWay}"
|
||||||
|
Keyboard="Numeric">
|
||||||
|
<Entry.Style>
|
||||||
|
<OnPlatform
|
||||||
|
x:TypeArguments="Style"
|
||||||
|
iOS="{StaticResource EntryStyle}"
|
||||||
|
Android="{StaticResource EntryStyle}"
|
||||||
|
WinPhone="{StaticResource UwpEntryStyle}"/>
|
||||||
|
</Entry.Style>
|
||||||
|
</Entry>
|
||||||
|
<Button
|
||||||
|
Command="{Binding ToggleSendLocationCommand}"
|
||||||
|
Text="Send Location"/>
|
||||||
|
</StackLayout>
|
||||||
|
|
||||||
</Grid>
|
</Grid>
|
||||||
</StackLayout>
|
</StackLayout>
|
||||||
</ScrollView>
|
</ScrollView>
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
@ -70,6 +70,7 @@
|
|||||||
<Compile Include="Models\Catalog\CatalogItem.cs" />
|
<Compile Include="Models\Catalog\CatalogItem.cs" />
|
||||||
<Compile Include="Models\Catalog\CatalogRoot.cs" />
|
<Compile Include="Models\Catalog\CatalogRoot.cs" />
|
||||||
<Compile Include="Models\Catalog\CatalogType.cs" />
|
<Compile Include="Models\Catalog\CatalogType.cs" />
|
||||||
|
<Compile Include="Models\Location\LocationRequest.cs" />
|
||||||
<Compile Include="Models\Navigation\TabParameter.cs" />
|
<Compile Include="Models\Navigation\TabParameter.cs" />
|
||||||
<Compile Include="Models\Orders\CardType.CS" />
|
<Compile Include="Models\Orders\CardType.CS" />
|
||||||
<Compile Include="Models\Orders\Order.cs" />
|
<Compile Include="Models\Orders\Order.cs" />
|
||||||
@ -91,6 +92,8 @@
|
|||||||
<Compile Include="Services\Dialog\IDialogService.cs" />
|
<Compile Include="Services\Dialog\IDialogService.cs" />
|
||||||
<Compile Include="Services\Identity\IdentityService.cs" />
|
<Compile Include="Services\Identity\IdentityService.cs" />
|
||||||
<Compile Include="Services\Identity\IIdentityService.cs" />
|
<Compile Include="Services\Identity\IIdentityService.cs" />
|
||||||
|
<Compile Include="Services\Location\ILocationService.cs" />
|
||||||
|
<Compile Include="Services\Location\LocationService.cs" />
|
||||||
<Compile Include="Services\Navigation\INavigationService.cs" />
|
<Compile Include="Services\Navigation\INavigationService.cs" />
|
||||||
<Compile Include="Services\Navigation\NavigationService.cs" />
|
<Compile Include="Services\Navigation\NavigationService.cs" />
|
||||||
<Compile Include="Services\OpenUrl\IOpenUrlService.cs" />
|
<Compile Include="Services\OpenUrl\IOpenUrlService.cs" />
|
||||||
|
@ -30,6 +30,7 @@
|
|||||||
<PackageReference Include="Microsoft.AspNetCore.Diagnostics.Abstractions" Version="1.1.2" />
|
<PackageReference Include="Microsoft.AspNetCore.Diagnostics.Abstractions" Version="1.1.2" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Server.IISIntegration" Version="1.1.2" />
|
<PackageReference Include="Microsoft.AspNetCore.Server.IISIntegration" Version="1.1.2" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Server.Kestrel" Version="1.1.2" />
|
<PackageReference Include="Microsoft.AspNetCore.Server.Kestrel" Version="1.1.2" />
|
||||||
|
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer.Design" Version="1.1.2" />
|
||||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="1.1.1" />
|
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="1.1.1" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="1.1.2" />
|
<PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="1.1.2" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Configuration.FileExtensions" Version="1.1.2" />
|
<PackageReference Include="Microsoft.Extensions.Configuration.FileExtensions" Version="1.1.2" />
|
||||||
|
@ -12,7 +12,9 @@ namespace Identity.API.Configuration
|
|||||||
return new List<ApiResource>
|
return new List<ApiResource>
|
||||||
{
|
{
|
||||||
new ApiResource("orders", "Orders Service"),
|
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.Profile,
|
||||||
IdentityServerConstants.StandardScopes.OfflineAccess,
|
IdentityServerConstants.StandardScopes.OfflineAccess,
|
||||||
"orders",
|
"orders",
|
||||||
"basket"
|
"basket",
|
||||||
|
"locations"
|
||||||
},
|
},
|
||||||
//Allow requesting refresh tokens for long lived API access
|
//Allow requesting refresh tokens for long lived API access
|
||||||
AllowOfflineAccess = true
|
AllowOfflineAccess = true
|
||||||
@ -86,6 +89,7 @@ namespace Identity.API.Configuration
|
|||||||
},
|
},
|
||||||
ClientUri = $"{clientsUrl["Mvc"]}", // public uri of the client
|
ClientUri = $"{clientsUrl["Mvc"]}", // public uri of the client
|
||||||
AllowedGrantTypes = GrantTypes.Hybrid,
|
AllowedGrantTypes = GrantTypes.Hybrid,
|
||||||
|
AllowAccessTokensViaBrowser = false,
|
||||||
RequireConsent = false,
|
RequireConsent = false,
|
||||||
AllowOfflineAccess = true,
|
AllowOfflineAccess = true,
|
||||||
RedirectUris = new List<string>
|
RedirectUris = new List<string>
|
||||||
@ -102,7 +106,8 @@ namespace Identity.API.Configuration
|
|||||||
IdentityServerConstants.StandardScopes.Profile,
|
IdentityServerConstants.StandardScopes.Profile,
|
||||||
IdentityServerConstants.StandardScopes.OfflineAccess,
|
IdentityServerConstants.StandardScopes.OfflineAccess,
|
||||||
"orders",
|
"orders",
|
||||||
"basket"
|
"basket",
|
||||||
|
"locations"
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -58,6 +58,7 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\..\..\BuildingBlocks\DataProtection\DataProtection\DataProtection.csproj" />
|
||||||
<ProjectReference Include="..\..\..\BuildingBlocks\HealthChecks\src\Microsoft.AspNetCore.HealthChecks\Microsoft.AspNetCore.HealthChecks.csproj" />
|
<ProjectReference Include="..\..\..\BuildingBlocks\HealthChecks\src\Microsoft.AspNetCore.HealthChecks\Microsoft.AspNetCore.HealthChecks.csproj" />
|
||||||
<ProjectReference Include="..\..\..\BuildingBlocks\HealthChecks\src\Microsoft.Extensions.HealthChecks.SqlServer\Microsoft.Extensions.HealthChecks.SqlServer.csproj" />
|
<ProjectReference Include="..\..\..\BuildingBlocks\HealthChecks\src\Microsoft.Extensions.HealthChecks.SqlServer\Microsoft.Extensions.HealthChecks.SqlServer.csproj" />
|
||||||
<ProjectReference Include="..\..\..\BuildingBlocks\HealthChecks\src\Microsoft.Extensions.HealthChecks\Microsoft.Extensions.HealthChecks.csproj" />
|
<ProjectReference Include="..\..\..\BuildingBlocks\HealthChecks\src\Microsoft.Extensions.HealthChecks\Microsoft.Extensions.HealthChecks.csproj" />
|
||||||
@ -69,4 +70,9 @@
|
|||||||
</None>
|
</None>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Folder Include="Extensions\" />
|
||||||
|
<Folder Include="Extensions\" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
52
src/Services/Identity/Identity.API/Migrations/20170604151240_Init-persisted-grant.Designer.cs
generated
Normal file
52
src/Services/Identity/Identity.API/Migrations/20170604151240_Init-persisted-grant.Designer.cs
generated
Normal file
@ -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<string>("Key")
|
||||||
|
.HasMaxLength(200);
|
||||||
|
|
||||||
|
b.Property<string>("ClientId")
|
||||||
|
.IsRequired()
|
||||||
|
.HasMaxLength(200);
|
||||||
|
|
||||||
|
b.Property<DateTime>("CreationTime");
|
||||||
|
|
||||||
|
b.Property<string>("Data")
|
||||||
|
.IsRequired()
|
||||||
|
.HasMaxLength(50000);
|
||||||
|
|
||||||
|
b.Property<DateTime?>("Expiration");
|
||||||
|
|
||||||
|
b.Property<string>("SubjectId")
|
||||||
|
.HasMaxLength(200);
|
||||||
|
|
||||||
|
b.Property<string>("Type")
|
||||||
|
.IsRequired()
|
||||||
|
.HasMaxLength(50);
|
||||||
|
|
||||||
|
b.HasKey("Key");
|
||||||
|
|
||||||
|
b.HasIndex("SubjectId", "ClientId", "Type");
|
||||||
|
|
||||||
|
b.ToTable("PersistedGrants");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -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<string>(maxLength: 200, nullable: false),
|
||||||
|
ClientId = table.Column<string>(maxLength: 200, nullable: false),
|
||||||
|
CreationTime = table.Column<DateTime>(nullable: false),
|
||||||
|
Data = table.Column<string>(maxLength: 50000, nullable: false),
|
||||||
|
Expiration = table.Column<DateTime>(nullable: true),
|
||||||
|
SubjectId = table.Column<string>(maxLength: 200, nullable: true),
|
||||||
|
Type = table.Column<string>(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");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -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<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<string>("Description")
|
||||||
|
.HasMaxLength(1000);
|
||||||
|
|
||||||
|
b.Property<string>("DisplayName")
|
||||||
|
.HasMaxLength(200);
|
||||||
|
|
||||||
|
b.Property<bool>("Enabled");
|
||||||
|
|
||||||
|
b.Property<string>("Name")
|
||||||
|
.IsRequired()
|
||||||
|
.HasMaxLength(200);
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("Name")
|
||||||
|
.IsUnique();
|
||||||
|
|
||||||
|
b.ToTable("ApiResources");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ApiResourceClaim", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<int?>("ApiResourceId")
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Property<string>("Type")
|
||||||
|
.IsRequired()
|
||||||
|
.HasMaxLength(200);
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("ApiResourceId");
|
||||||
|
|
||||||
|
b.ToTable("ApiClaims");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ApiScope", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<int?>("ApiResourceId")
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Property<string>("Description")
|
||||||
|
.HasMaxLength(1000);
|
||||||
|
|
||||||
|
b.Property<string>("DisplayName")
|
||||||
|
.HasMaxLength(200);
|
||||||
|
|
||||||
|
b.Property<bool>("Emphasize");
|
||||||
|
|
||||||
|
b.Property<string>("Name")
|
||||||
|
.IsRequired()
|
||||||
|
.HasMaxLength(200);
|
||||||
|
|
||||||
|
b.Property<bool>("Required");
|
||||||
|
|
||||||
|
b.Property<bool>("ShowInDiscoveryDocument");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("ApiResourceId");
|
||||||
|
|
||||||
|
b.HasIndex("Name")
|
||||||
|
.IsUnique();
|
||||||
|
|
||||||
|
b.ToTable("ApiScopes");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ApiScopeClaim", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<int?>("ApiScopeId")
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Property<string>("Type")
|
||||||
|
.IsRequired()
|
||||||
|
.HasMaxLength(200);
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("ApiScopeId");
|
||||||
|
|
||||||
|
b.ToTable("ApiScopeClaims");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ApiSecret", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<int?>("ApiResourceId")
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Property<string>("Description")
|
||||||
|
.HasMaxLength(1000);
|
||||||
|
|
||||||
|
b.Property<DateTime?>("Expiration");
|
||||||
|
|
||||||
|
b.Property<string>("Type")
|
||||||
|
.HasMaxLength(250);
|
||||||
|
|
||||||
|
b.Property<string>("Value")
|
||||||
|
.HasMaxLength(2000);
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("ApiResourceId");
|
||||||
|
|
||||||
|
b.ToTable("ApiSecrets");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.Client", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<int>("AbsoluteRefreshTokenLifetime");
|
||||||
|
|
||||||
|
b.Property<int>("AccessTokenLifetime");
|
||||||
|
|
||||||
|
b.Property<int>("AccessTokenType");
|
||||||
|
|
||||||
|
b.Property<bool>("AllowAccessTokensViaBrowser");
|
||||||
|
|
||||||
|
b.Property<bool>("AllowOfflineAccess");
|
||||||
|
|
||||||
|
b.Property<bool>("AllowPlainTextPkce");
|
||||||
|
|
||||||
|
b.Property<bool>("AllowRememberConsent");
|
||||||
|
|
||||||
|
b.Property<bool>("AlwaysIncludeUserClaimsInIdToken");
|
||||||
|
|
||||||
|
b.Property<bool>("AlwaysSendClientClaims");
|
||||||
|
|
||||||
|
b.Property<int>("AuthorizationCodeLifetime");
|
||||||
|
|
||||||
|
b.Property<string>("ClientId")
|
||||||
|
.IsRequired()
|
||||||
|
.HasMaxLength(200);
|
||||||
|
|
||||||
|
b.Property<string>("ClientName")
|
||||||
|
.HasMaxLength(200);
|
||||||
|
|
||||||
|
b.Property<string>("ClientUri")
|
||||||
|
.HasMaxLength(2000);
|
||||||
|
|
||||||
|
b.Property<bool>("EnableLocalLogin");
|
||||||
|
|
||||||
|
b.Property<bool>("Enabled");
|
||||||
|
|
||||||
|
b.Property<int>("IdentityTokenLifetime");
|
||||||
|
|
||||||
|
b.Property<bool>("IncludeJwtId");
|
||||||
|
|
||||||
|
b.Property<string>("LogoUri");
|
||||||
|
|
||||||
|
b.Property<bool>("LogoutSessionRequired");
|
||||||
|
|
||||||
|
b.Property<string>("LogoutUri");
|
||||||
|
|
||||||
|
b.Property<bool>("PrefixClientClaims");
|
||||||
|
|
||||||
|
b.Property<string>("ProtocolType")
|
||||||
|
.IsRequired()
|
||||||
|
.HasMaxLength(200);
|
||||||
|
|
||||||
|
b.Property<int>("RefreshTokenExpiration");
|
||||||
|
|
||||||
|
b.Property<int>("RefreshTokenUsage");
|
||||||
|
|
||||||
|
b.Property<bool>("RequireClientSecret");
|
||||||
|
|
||||||
|
b.Property<bool>("RequireConsent");
|
||||||
|
|
||||||
|
b.Property<bool>("RequirePkce");
|
||||||
|
|
||||||
|
b.Property<int>("SlidingRefreshTokenLifetime");
|
||||||
|
|
||||||
|
b.Property<bool>("UpdateAccessTokenClaimsOnRefresh");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("ClientId")
|
||||||
|
.IsUnique();
|
||||||
|
|
||||||
|
b.ToTable("Clients");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientClaim", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<int?>("ClientId")
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Property<string>("Type")
|
||||||
|
.IsRequired()
|
||||||
|
.HasMaxLength(250);
|
||||||
|
|
||||||
|
b.Property<string>("Value")
|
||||||
|
.IsRequired()
|
||||||
|
.HasMaxLength(250);
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("ClientId");
|
||||||
|
|
||||||
|
b.ToTable("ClientClaims");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientCorsOrigin", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<int?>("ClientId")
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Property<string>("Origin")
|
||||||
|
.IsRequired()
|
||||||
|
.HasMaxLength(150);
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("ClientId");
|
||||||
|
|
||||||
|
b.ToTable("ClientCorsOrigins");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientGrantType", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<int?>("ClientId")
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Property<string>("GrantType")
|
||||||
|
.IsRequired()
|
||||||
|
.HasMaxLength(250);
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("ClientId");
|
||||||
|
|
||||||
|
b.ToTable("ClientGrantTypes");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientIdPRestriction", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<int?>("ClientId")
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Property<string>("Provider")
|
||||||
|
.IsRequired()
|
||||||
|
.HasMaxLength(200);
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("ClientId");
|
||||||
|
|
||||||
|
b.ToTable("ClientIdPRestrictions");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientPostLogoutRedirectUri", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<int?>("ClientId")
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Property<string>("PostLogoutRedirectUri")
|
||||||
|
.IsRequired()
|
||||||
|
.HasMaxLength(2000);
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("ClientId");
|
||||||
|
|
||||||
|
b.ToTable("ClientPostLogoutRedirectUris");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientRedirectUri", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<int?>("ClientId")
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Property<string>("RedirectUri")
|
||||||
|
.IsRequired()
|
||||||
|
.HasMaxLength(2000);
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("ClientId");
|
||||||
|
|
||||||
|
b.ToTable("ClientRedirectUris");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientScope", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<int?>("ClientId")
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Property<string>("Scope")
|
||||||
|
.IsRequired()
|
||||||
|
.HasMaxLength(200);
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("ClientId");
|
||||||
|
|
||||||
|
b.ToTable("ClientScopes");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientSecret", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<int?>("ClientId")
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Property<string>("Description")
|
||||||
|
.HasMaxLength(2000);
|
||||||
|
|
||||||
|
b.Property<DateTime?>("Expiration");
|
||||||
|
|
||||||
|
b.Property<string>("Type")
|
||||||
|
.HasMaxLength(250);
|
||||||
|
|
||||||
|
b.Property<string>("Value")
|
||||||
|
.IsRequired()
|
||||||
|
.HasMaxLength(2000);
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("ClientId");
|
||||||
|
|
||||||
|
b.ToTable("ClientSecrets");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.IdentityClaim", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<int?>("IdentityResourceId")
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Property<string>("Type")
|
||||||
|
.IsRequired()
|
||||||
|
.HasMaxLength(200);
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("IdentityResourceId");
|
||||||
|
|
||||||
|
b.ToTable("IdentityClaims");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.IdentityResource", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<string>("Description")
|
||||||
|
.HasMaxLength(1000);
|
||||||
|
|
||||||
|
b.Property<string>("DisplayName")
|
||||||
|
.HasMaxLength(200);
|
||||||
|
|
||||||
|
b.Property<bool>("Emphasize");
|
||||||
|
|
||||||
|
b.Property<bool>("Enabled");
|
||||||
|
|
||||||
|
b.Property<string>("Name")
|
||||||
|
.IsRequired()
|
||||||
|
.HasMaxLength(200);
|
||||||
|
|
||||||
|
b.Property<bool>("Required");
|
||||||
|
|
||||||
|
b.Property<bool>("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);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -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<int>(nullable: false)
|
||||||
|
.Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn),
|
||||||
|
Description = table.Column<string>(maxLength: 1000, nullable: true),
|
||||||
|
DisplayName = table.Column<string>(maxLength: 200, nullable: true),
|
||||||
|
Enabled = table.Column<bool>(nullable: false),
|
||||||
|
Name = table.Column<string>(maxLength: 200, nullable: false)
|
||||||
|
},
|
||||||
|
constraints: table =>
|
||||||
|
{
|
||||||
|
table.PrimaryKey("PK_ApiResources", x => x.Id);
|
||||||
|
});
|
||||||
|
|
||||||
|
migrationBuilder.CreateTable(
|
||||||
|
name: "Clients",
|
||||||
|
columns: table => new
|
||||||
|
{
|
||||||
|
Id = table.Column<int>(nullable: false)
|
||||||
|
.Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn),
|
||||||
|
AbsoluteRefreshTokenLifetime = table.Column<int>(nullable: false),
|
||||||
|
AccessTokenLifetime = table.Column<int>(nullable: false),
|
||||||
|
AccessTokenType = table.Column<int>(nullable: false),
|
||||||
|
AllowAccessTokensViaBrowser = table.Column<bool>(nullable: false),
|
||||||
|
AllowOfflineAccess = table.Column<bool>(nullable: false),
|
||||||
|
AllowPlainTextPkce = table.Column<bool>(nullable: false),
|
||||||
|
AllowRememberConsent = table.Column<bool>(nullable: false),
|
||||||
|
AlwaysIncludeUserClaimsInIdToken = table.Column<bool>(nullable: false),
|
||||||
|
AlwaysSendClientClaims = table.Column<bool>(nullable: false),
|
||||||
|
AuthorizationCodeLifetime = table.Column<int>(nullable: false),
|
||||||
|
ClientId = table.Column<string>(maxLength: 200, nullable: false),
|
||||||
|
ClientName = table.Column<string>(maxLength: 200, nullable: true),
|
||||||
|
ClientUri = table.Column<string>(maxLength: 2000, nullable: true),
|
||||||
|
EnableLocalLogin = table.Column<bool>(nullable: false),
|
||||||
|
Enabled = table.Column<bool>(nullable: false),
|
||||||
|
IdentityTokenLifetime = table.Column<int>(nullable: false),
|
||||||
|
IncludeJwtId = table.Column<bool>(nullable: false),
|
||||||
|
LogoUri = table.Column<string>(nullable: true),
|
||||||
|
LogoutSessionRequired = table.Column<bool>(nullable: false),
|
||||||
|
LogoutUri = table.Column<string>(nullable: true),
|
||||||
|
PrefixClientClaims = table.Column<bool>(nullable: false),
|
||||||
|
ProtocolType = table.Column<string>(maxLength: 200, nullable: false),
|
||||||
|
RefreshTokenExpiration = table.Column<int>(nullable: false),
|
||||||
|
RefreshTokenUsage = table.Column<int>(nullable: false),
|
||||||
|
RequireClientSecret = table.Column<bool>(nullable: false),
|
||||||
|
RequireConsent = table.Column<bool>(nullable: false),
|
||||||
|
RequirePkce = table.Column<bool>(nullable: false),
|
||||||
|
SlidingRefreshTokenLifetime = table.Column<int>(nullable: false),
|
||||||
|
UpdateAccessTokenClaimsOnRefresh = table.Column<bool>(nullable: false)
|
||||||
|
},
|
||||||
|
constraints: table =>
|
||||||
|
{
|
||||||
|
table.PrimaryKey("PK_Clients", x => x.Id);
|
||||||
|
});
|
||||||
|
|
||||||
|
migrationBuilder.CreateTable(
|
||||||
|
name: "IdentityResources",
|
||||||
|
columns: table => new
|
||||||
|
{
|
||||||
|
Id = table.Column<int>(nullable: false)
|
||||||
|
.Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn),
|
||||||
|
Description = table.Column<string>(maxLength: 1000, nullable: true),
|
||||||
|
DisplayName = table.Column<string>(maxLength: 200, nullable: true),
|
||||||
|
Emphasize = table.Column<bool>(nullable: false),
|
||||||
|
Enabled = table.Column<bool>(nullable: false),
|
||||||
|
Name = table.Column<string>(maxLength: 200, nullable: false),
|
||||||
|
Required = table.Column<bool>(nullable: false),
|
||||||
|
ShowInDiscoveryDocument = table.Column<bool>(nullable: false)
|
||||||
|
},
|
||||||
|
constraints: table =>
|
||||||
|
{
|
||||||
|
table.PrimaryKey("PK_IdentityResources", x => x.Id);
|
||||||
|
});
|
||||||
|
|
||||||
|
migrationBuilder.CreateTable(
|
||||||
|
name: "ApiClaims",
|
||||||
|
columns: table => new
|
||||||
|
{
|
||||||
|
Id = table.Column<int>(nullable: false)
|
||||||
|
.Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn),
|
||||||
|
ApiResourceId = table.Column<int>(nullable: false),
|
||||||
|
Type = table.Column<string>(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<int>(nullable: false)
|
||||||
|
.Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn),
|
||||||
|
ApiResourceId = table.Column<int>(nullable: false),
|
||||||
|
Description = table.Column<string>(maxLength: 1000, nullable: true),
|
||||||
|
DisplayName = table.Column<string>(maxLength: 200, nullable: true),
|
||||||
|
Emphasize = table.Column<bool>(nullable: false),
|
||||||
|
Name = table.Column<string>(maxLength: 200, nullable: false),
|
||||||
|
Required = table.Column<bool>(nullable: false),
|
||||||
|
ShowInDiscoveryDocument = table.Column<bool>(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<int>(nullable: false)
|
||||||
|
.Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn),
|
||||||
|
ApiResourceId = table.Column<int>(nullable: false),
|
||||||
|
Description = table.Column<string>(maxLength: 1000, nullable: true),
|
||||||
|
Expiration = table.Column<DateTime>(nullable: true),
|
||||||
|
Type = table.Column<string>(maxLength: 250, nullable: true),
|
||||||
|
Value = table.Column<string>(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<int>(nullable: false)
|
||||||
|
.Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn),
|
||||||
|
ClientId = table.Column<int>(nullable: false),
|
||||||
|
Type = table.Column<string>(maxLength: 250, nullable: false),
|
||||||
|
Value = table.Column<string>(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<int>(nullable: false)
|
||||||
|
.Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn),
|
||||||
|
ClientId = table.Column<int>(nullable: false),
|
||||||
|
Origin = table.Column<string>(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<int>(nullable: false)
|
||||||
|
.Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn),
|
||||||
|
ClientId = table.Column<int>(nullable: false),
|
||||||
|
GrantType = table.Column<string>(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<int>(nullable: false)
|
||||||
|
.Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn),
|
||||||
|
ClientId = table.Column<int>(nullable: false),
|
||||||
|
Provider = table.Column<string>(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<int>(nullable: false)
|
||||||
|
.Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn),
|
||||||
|
ClientId = table.Column<int>(nullable: false),
|
||||||
|
PostLogoutRedirectUri = table.Column<string>(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<int>(nullable: false)
|
||||||
|
.Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn),
|
||||||
|
ClientId = table.Column<int>(nullable: false),
|
||||||
|
RedirectUri = table.Column<string>(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<int>(nullable: false)
|
||||||
|
.Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn),
|
||||||
|
ClientId = table.Column<int>(nullable: false),
|
||||||
|
Scope = table.Column<string>(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<int>(nullable: false)
|
||||||
|
.Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn),
|
||||||
|
ClientId = table.Column<int>(nullable: false),
|
||||||
|
Description = table.Column<string>(maxLength: 2000, nullable: true),
|
||||||
|
Expiration = table.Column<DateTime>(nullable: true),
|
||||||
|
Type = table.Column<string>(maxLength: 250, nullable: true),
|
||||||
|
Value = table.Column<string>(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<int>(nullable: false)
|
||||||
|
.Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn),
|
||||||
|
IdentityResourceId = table.Column<int>(nullable: false),
|
||||||
|
Type = table.Column<string>(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<int>(nullable: false)
|
||||||
|
.Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn),
|
||||||
|
ApiScopeId = table.Column<int>(nullable: false),
|
||||||
|
Type = table.Column<string>(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");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -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<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<string>("Description")
|
||||||
|
.HasMaxLength(1000);
|
||||||
|
|
||||||
|
b.Property<string>("DisplayName")
|
||||||
|
.HasMaxLength(200);
|
||||||
|
|
||||||
|
b.Property<bool>("Enabled");
|
||||||
|
|
||||||
|
b.Property<string>("Name")
|
||||||
|
.IsRequired()
|
||||||
|
.HasMaxLength(200);
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("Name")
|
||||||
|
.IsUnique();
|
||||||
|
|
||||||
|
b.ToTable("ApiResources");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ApiResourceClaim", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<int?>("ApiResourceId")
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Property<string>("Type")
|
||||||
|
.IsRequired()
|
||||||
|
.HasMaxLength(200);
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("ApiResourceId");
|
||||||
|
|
||||||
|
b.ToTable("ApiClaims");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ApiScope", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<int?>("ApiResourceId")
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Property<string>("Description")
|
||||||
|
.HasMaxLength(1000);
|
||||||
|
|
||||||
|
b.Property<string>("DisplayName")
|
||||||
|
.HasMaxLength(200);
|
||||||
|
|
||||||
|
b.Property<bool>("Emphasize");
|
||||||
|
|
||||||
|
b.Property<string>("Name")
|
||||||
|
.IsRequired()
|
||||||
|
.HasMaxLength(200);
|
||||||
|
|
||||||
|
b.Property<bool>("Required");
|
||||||
|
|
||||||
|
b.Property<bool>("ShowInDiscoveryDocument");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("ApiResourceId");
|
||||||
|
|
||||||
|
b.HasIndex("Name")
|
||||||
|
.IsUnique();
|
||||||
|
|
||||||
|
b.ToTable("ApiScopes");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ApiScopeClaim", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<int?>("ApiScopeId")
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Property<string>("Type")
|
||||||
|
.IsRequired()
|
||||||
|
.HasMaxLength(200);
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("ApiScopeId");
|
||||||
|
|
||||||
|
b.ToTable("ApiScopeClaims");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ApiSecret", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<int?>("ApiResourceId")
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Property<string>("Description")
|
||||||
|
.HasMaxLength(1000);
|
||||||
|
|
||||||
|
b.Property<DateTime?>("Expiration");
|
||||||
|
|
||||||
|
b.Property<string>("Type")
|
||||||
|
.HasMaxLength(250);
|
||||||
|
|
||||||
|
b.Property<string>("Value")
|
||||||
|
.HasMaxLength(2000);
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("ApiResourceId");
|
||||||
|
|
||||||
|
b.ToTable("ApiSecrets");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.Client", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<int>("AbsoluteRefreshTokenLifetime");
|
||||||
|
|
||||||
|
b.Property<int>("AccessTokenLifetime");
|
||||||
|
|
||||||
|
b.Property<int>("AccessTokenType");
|
||||||
|
|
||||||
|
b.Property<bool>("AllowAccessTokensViaBrowser");
|
||||||
|
|
||||||
|
b.Property<bool>("AllowOfflineAccess");
|
||||||
|
|
||||||
|
b.Property<bool>("AllowPlainTextPkce");
|
||||||
|
|
||||||
|
b.Property<bool>("AllowRememberConsent");
|
||||||
|
|
||||||
|
b.Property<bool>("AlwaysIncludeUserClaimsInIdToken");
|
||||||
|
|
||||||
|
b.Property<bool>("AlwaysSendClientClaims");
|
||||||
|
|
||||||
|
b.Property<int>("AuthorizationCodeLifetime");
|
||||||
|
|
||||||
|
b.Property<string>("ClientId")
|
||||||
|
.IsRequired()
|
||||||
|
.HasMaxLength(200);
|
||||||
|
|
||||||
|
b.Property<string>("ClientName")
|
||||||
|
.HasMaxLength(200);
|
||||||
|
|
||||||
|
b.Property<string>("ClientUri")
|
||||||
|
.HasMaxLength(2000);
|
||||||
|
|
||||||
|
b.Property<bool>("EnableLocalLogin");
|
||||||
|
|
||||||
|
b.Property<bool>("Enabled");
|
||||||
|
|
||||||
|
b.Property<int>("IdentityTokenLifetime");
|
||||||
|
|
||||||
|
b.Property<bool>("IncludeJwtId");
|
||||||
|
|
||||||
|
b.Property<string>("LogoUri");
|
||||||
|
|
||||||
|
b.Property<bool>("LogoutSessionRequired");
|
||||||
|
|
||||||
|
b.Property<string>("LogoutUri");
|
||||||
|
|
||||||
|
b.Property<bool>("PrefixClientClaims");
|
||||||
|
|
||||||
|
b.Property<string>("ProtocolType")
|
||||||
|
.IsRequired()
|
||||||
|
.HasMaxLength(200);
|
||||||
|
|
||||||
|
b.Property<int>("RefreshTokenExpiration");
|
||||||
|
|
||||||
|
b.Property<int>("RefreshTokenUsage");
|
||||||
|
|
||||||
|
b.Property<bool>("RequireClientSecret");
|
||||||
|
|
||||||
|
b.Property<bool>("RequireConsent");
|
||||||
|
|
||||||
|
b.Property<bool>("RequirePkce");
|
||||||
|
|
||||||
|
b.Property<int>("SlidingRefreshTokenLifetime");
|
||||||
|
|
||||||
|
b.Property<bool>("UpdateAccessTokenClaimsOnRefresh");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("ClientId")
|
||||||
|
.IsUnique();
|
||||||
|
|
||||||
|
b.ToTable("Clients");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientClaim", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<int?>("ClientId")
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Property<string>("Type")
|
||||||
|
.IsRequired()
|
||||||
|
.HasMaxLength(250);
|
||||||
|
|
||||||
|
b.Property<string>("Value")
|
||||||
|
.IsRequired()
|
||||||
|
.HasMaxLength(250);
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("ClientId");
|
||||||
|
|
||||||
|
b.ToTable("ClientClaims");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientCorsOrigin", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<int?>("ClientId")
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Property<string>("Origin")
|
||||||
|
.IsRequired()
|
||||||
|
.HasMaxLength(150);
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("ClientId");
|
||||||
|
|
||||||
|
b.ToTable("ClientCorsOrigins");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientGrantType", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<int?>("ClientId")
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Property<string>("GrantType")
|
||||||
|
.IsRequired()
|
||||||
|
.HasMaxLength(250);
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("ClientId");
|
||||||
|
|
||||||
|
b.ToTable("ClientGrantTypes");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientIdPRestriction", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<int?>("ClientId")
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Property<string>("Provider")
|
||||||
|
.IsRequired()
|
||||||
|
.HasMaxLength(200);
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("ClientId");
|
||||||
|
|
||||||
|
b.ToTable("ClientIdPRestrictions");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientPostLogoutRedirectUri", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<int?>("ClientId")
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Property<string>("PostLogoutRedirectUri")
|
||||||
|
.IsRequired()
|
||||||
|
.HasMaxLength(2000);
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("ClientId");
|
||||||
|
|
||||||
|
b.ToTable("ClientPostLogoutRedirectUris");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientRedirectUri", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<int?>("ClientId")
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Property<string>("RedirectUri")
|
||||||
|
.IsRequired()
|
||||||
|
.HasMaxLength(2000);
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("ClientId");
|
||||||
|
|
||||||
|
b.ToTable("ClientRedirectUris");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientScope", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<int?>("ClientId")
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Property<string>("Scope")
|
||||||
|
.IsRequired()
|
||||||
|
.HasMaxLength(200);
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("ClientId");
|
||||||
|
|
||||||
|
b.ToTable("ClientScopes");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientSecret", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<int?>("ClientId")
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Property<string>("Description")
|
||||||
|
.HasMaxLength(2000);
|
||||||
|
|
||||||
|
b.Property<DateTime?>("Expiration");
|
||||||
|
|
||||||
|
b.Property<string>("Type")
|
||||||
|
.HasMaxLength(250);
|
||||||
|
|
||||||
|
b.Property<string>("Value")
|
||||||
|
.IsRequired()
|
||||||
|
.HasMaxLength(2000);
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("ClientId");
|
||||||
|
|
||||||
|
b.ToTable("ClientSecrets");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.IdentityClaim", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<int?>("IdentityResourceId")
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Property<string>("Type")
|
||||||
|
.IsRequired()
|
||||||
|
.HasMaxLength(200);
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("IdentityResourceId");
|
||||||
|
|
||||||
|
b.ToTable("IdentityClaims");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.IdentityResource", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<string>("Description")
|
||||||
|
.HasMaxLength(1000);
|
||||||
|
|
||||||
|
b.Property<string>("DisplayName")
|
||||||
|
.HasMaxLength(200);
|
||||||
|
|
||||||
|
b.Property<bool>("Emphasize");
|
||||||
|
|
||||||
|
b.Property<bool>("Enabled");
|
||||||
|
|
||||||
|
b.Property<string>("Name")
|
||||||
|
.IsRequired()
|
||||||
|
.HasMaxLength(200);
|
||||||
|
|
||||||
|
b.Property<bool>("Required");
|
||||||
|
|
||||||
|
b.Property<bool>("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);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,51 @@
|
|||||||
|
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))]
|
||||||
|
partial class PersistedGrantDbContextModelSnapshot : ModelSnapshot
|
||||||
|
{
|
||||||
|
protected override void BuildModel(ModelBuilder modelBuilder)
|
||||||
|
{
|
||||||
|
modelBuilder
|
||||||
|
.HasAnnotation("ProductVersion", "1.1.2")
|
||||||
|
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
|
||||||
|
|
||||||
|
modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.PersistedGrant", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("Key")
|
||||||
|
.HasMaxLength(200);
|
||||||
|
|
||||||
|
b.Property<string>("ClientId")
|
||||||
|
.IsRequired()
|
||||||
|
.HasMaxLength(200);
|
||||||
|
|
||||||
|
b.Property<DateTime>("CreationTime");
|
||||||
|
|
||||||
|
b.Property<string>("Data")
|
||||||
|
.IsRequired()
|
||||||
|
.HasMaxLength(50000);
|
||||||
|
|
||||||
|
b.Property<DateTime?>("Expiration");
|
||||||
|
|
||||||
|
b.Property<string>("SubjectId")
|
||||||
|
.HasMaxLength(200);
|
||||||
|
|
||||||
|
b.Property<string>("Type")
|
||||||
|
.IsRequired()
|
||||||
|
.HasMaxLength(50);
|
||||||
|
|
||||||
|
b.HasKey("Key");
|
||||||
|
|
||||||
|
b.HasIndex("SubjectId", "ClientId", "Type");
|
||||||
|
|
||||||
|
b.ToTable("PersistedGrants");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,24 +1,27 @@
|
|||||||
using System;
|
using Identity.API.Certificate;
|
||||||
using System.Collections.Generic;
|
using Identity.API.Configuration;
|
||||||
using System.Linq;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Microsoft.AspNetCore.Builder;
|
|
||||||
using Microsoft.AspNetCore.Hosting;
|
|
||||||
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
|
|
||||||
using Microsoft.EntityFrameworkCore;
|
|
||||||
using Microsoft.Extensions.Configuration;
|
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
|
||||||
using Microsoft.Extensions.Logging;
|
|
||||||
using Identity.API.Data;
|
using Identity.API.Data;
|
||||||
using Identity.API.Models;
|
using Identity.API.Models;
|
||||||
using Identity.API.Services;
|
using Identity.API.Services;
|
||||||
using Identity.API.Configuration;
|
using IdentityServer4.EntityFramework.DbContexts;
|
||||||
|
using IdentityServer4.EntityFramework.Mappers;
|
||||||
using IdentityServer4.Services;
|
using IdentityServer4.Services;
|
||||||
using System.Threading;
|
using Microsoft.AspNetCore.Builder;
|
||||||
using Microsoft.eShopOnContainers.Services.Catalog.API.Infrastructure;
|
using Microsoft.AspNetCore.Hosting;
|
||||||
using Microsoft.AspNetCore.Identity;
|
using Microsoft.AspNetCore.Identity;
|
||||||
|
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.eShopOnContainers.BuildingBlocks;
|
||||||
|
using Microsoft.eShopOnContainers.Services.Catalog.API.Infrastructure;
|
||||||
|
using Microsoft.Extensions.Configuration;
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using Microsoft.Extensions.HealthChecks;
|
using Microsoft.Extensions.HealthChecks;
|
||||||
using Identity.API.Certificate;
|
using Microsoft.Extensions.Logging;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace eShopOnContainers.Identity
|
namespace eShopOnContainers.Identity
|
||||||
{
|
{
|
||||||
@ -45,8 +48,7 @@ namespace eShopOnContainers.Identity
|
|||||||
|
|
||||||
// This method gets called by the runtime. Use this method to add services to the container.
|
// This method gets called by the runtime. Use this method to add services to the container.
|
||||||
public void ConfigureServices(IServiceCollection services)
|
public void ConfigureServices(IServiceCollection services)
|
||||||
{
|
{
|
||||||
|
|
||||||
// Add framework services.
|
// Add framework services.
|
||||||
services.AddDbContext<ApplicationDbContext>(options =>
|
services.AddDbContext<ApplicationDbContext>(options =>
|
||||||
options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
|
options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
|
||||||
@ -57,13 +59,17 @@ namespace eShopOnContainers.Identity
|
|||||||
|
|
||||||
services.Configure<AppSettings>(Configuration);
|
services.Configure<AppSettings>(Configuration);
|
||||||
|
|
||||||
services.AddDataProtection(opts =>
|
|
||||||
{
|
|
||||||
opts.ApplicationDiscriminator = "eshop.identity";
|
|
||||||
});
|
|
||||||
|
|
||||||
services.AddMvc();
|
services.AddMvc();
|
||||||
|
|
||||||
|
if (Configuration.GetValue<string>("IsClusterEnv") == bool.TrueString)
|
||||||
|
{
|
||||||
|
services.AddDataProtection(opts =>
|
||||||
|
{
|
||||||
|
opts.ApplicationDiscriminator = "eshop.identity";
|
||||||
|
})
|
||||||
|
.PersistKeysToRedis(Configuration["DPConnectionString"]);
|
||||||
|
}
|
||||||
|
|
||||||
services.AddHealthChecks(checks =>
|
services.AddHealthChecks(checks =>
|
||||||
{
|
{
|
||||||
var minutes = 1;
|
var minutes = 1;
|
||||||
@ -79,20 +85,20 @@ namespace eShopOnContainers.Identity
|
|||||||
services.AddTransient<ILoginService<ApplicationUser>, EFLoginService>();
|
services.AddTransient<ILoginService<ApplicationUser>, EFLoginService>();
|
||||||
services.AddTransient<IRedirectService, RedirectService>();
|
services.AddTransient<IRedirectService, RedirectService>();
|
||||||
|
|
||||||
//callbacks urls from config:
|
var connectionString = Configuration.GetConnectionString("DefaultConnection");
|
||||||
Dictionary<string, string> clientUrls = new Dictionary<string, string>();
|
var migrationsAssembly = typeof(Startup).GetTypeInfo().Assembly.GetName().Name;
|
||||||
clientUrls.Add("Mvc", Configuration.GetValue<string>("MvcClient"));
|
|
||||||
clientUrls.Add("Spa", Configuration.GetValue<string>("SpaClient"));
|
|
||||||
clientUrls.Add("Xamarin", Configuration.GetValue<string>("XamarinCallback"));
|
|
||||||
|
|
||||||
// Adds IdentityServer
|
// Adds IdentityServer
|
||||||
services.AddIdentityServer(x => x.IssuerUri = "null")
|
services.AddIdentityServer(x => x.IssuerUri = "null")
|
||||||
.AddSigningCredential(Certificate.Get())
|
.AddSigningCredential(Certificate.Get())
|
||||||
.AddInMemoryApiResources(Config.GetApis())
|
|
||||||
.AddInMemoryIdentityResources(Config.GetResources())
|
|
||||||
.AddInMemoryClients(Config.GetClients(clientUrls))
|
|
||||||
.AddAspNetIdentity<ApplicationUser>()
|
.AddAspNetIdentity<ApplicationUser>()
|
||||||
.Services.AddTransient<IProfileService, ProfileService>();
|
.AddConfigurationStore(builder =>
|
||||||
|
builder.UseSqlServer(connectionString, options =>
|
||||||
|
options.MigrationsAssembly(migrationsAssembly)))
|
||||||
|
.AddOperationalStore(builder =>
|
||||||
|
builder.UseSqlServer(connectionString, options =>
|
||||||
|
options.MigrationsAssembly(migrationsAssembly)))
|
||||||
|
.Services.AddTransient<IProfileService, ProfileService>();
|
||||||
}
|
}
|
||||||
|
|
||||||
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
|
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
|
||||||
@ -134,10 +140,55 @@ namespace eShopOnContainers.Identity
|
|||||||
template: "{controller=Home}/{action=Index}/{id?}");
|
template: "{controller=Home}/{action=Index}/{id?}");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Store idsrv grant config into db
|
||||||
|
InitializeGrantStoreAndConfiguration(app).Wait();
|
||||||
|
|
||||||
//Seed Data
|
//Seed Data
|
||||||
var hasher = new PasswordHasher<ApplicationUser>();
|
var hasher = new PasswordHasher<ApplicationUser>();
|
||||||
new ApplicationContextSeed(hasher).SeedAsync(app, loggerFactory)
|
new ApplicationContextSeed(hasher).SeedAsync(app, loggerFactory).Wait();
|
||||||
.Wait();
|
}
|
||||||
|
|
||||||
|
private async Task InitializeGrantStoreAndConfiguration(IApplicationBuilder app)
|
||||||
|
{
|
||||||
|
//callbacks urls from config:
|
||||||
|
Dictionary<string, string> clientUrls = new Dictionary<string, string>();
|
||||||
|
clientUrls.Add("Mvc", Configuration.GetValue<string>("MvcClient"));
|
||||||
|
clientUrls.Add("Spa", Configuration.GetValue<string>("SpaClient"));
|
||||||
|
clientUrls.Add("Xamarin", Configuration.GetValue<string>("XamarinCallback"));
|
||||||
|
|
||||||
|
using (var serviceScope = app.ApplicationServices.GetService<IServiceScopeFactory>().CreateScope())
|
||||||
|
{
|
||||||
|
serviceScope.ServiceProvider.GetRequiredService<PersistedGrantDbContext>().Database.Migrate();
|
||||||
|
var context = serviceScope.ServiceProvider.GetRequiredService<ConfigurationDbContext>();
|
||||||
|
context.Database.Migrate();
|
||||||
|
|
||||||
|
if (!context.Clients.Any())
|
||||||
|
{
|
||||||
|
foreach (var client in Config.GetClients(clientUrls))
|
||||||
|
{
|
||||||
|
await context.Clients.AddAsync(client.ToEntity());
|
||||||
|
}
|
||||||
|
await context.SaveChangesAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!context.IdentityResources.Any())
|
||||||
|
{
|
||||||
|
foreach (var resource in Config.GetResources())
|
||||||
|
{
|
||||||
|
await context.IdentityResources.AddAsync(resource.ToEntity());
|
||||||
|
}
|
||||||
|
await context.SaveChangesAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!context.ApiResources.Any())
|
||||||
|
{
|
||||||
|
foreach (var api in Config.GetApis())
|
||||||
|
{
|
||||||
|
await context.ApiResources.AddAsync(api.ToEntity());
|
||||||
|
}
|
||||||
|
await context.SaveChangesAsync();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,9 +2,10 @@
|
|||||||
"ConnectionStrings": {
|
"ConnectionStrings": {
|
||||||
"DefaultConnection": "Server=tcp:127.0.0.1,5433;Database=Microsoft.eShopOnContainers.Services.IdentityDb;User Id=sa;Password=Pass@word;"
|
"DefaultConnection": "Server=tcp:127.0.0.1,5433;Database=Microsoft.eShopOnContainers.Services.IdentityDb;User Id=sa;Password=Pass@word;"
|
||||||
},
|
},
|
||||||
|
"IsClusterEnv": "False",
|
||||||
"MvcClient": "http://localhost:5100",
|
"MvcClient": "http://localhost:5100",
|
||||||
"SpaClient": "http://localhost:5104",
|
"SpaClient": "http://localhost:5104",
|
||||||
"XamarinCallback": "http://localhost:5105/xamarincallback",
|
"XamarinCallback": "http://localhost:5105/xamarincallback",
|
||||||
"Logging": {
|
"Logging": {
|
||||||
"IncludeScopes": false,
|
"IncludeScopes": false,
|
||||||
"LogLevel": {
|
"LogLevel": {
|
||||||
|
3
src/Services/Location/Locations.API/.dockerignore
Normal file
3
src/Services/Location/Locations.API/.dockerignore
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
*
|
||||||
|
!obj/Docker/publish/*
|
||||||
|
!obj/Docker/empty/
|
@ -0,0 +1,19 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
|
||||||
|
// For more information on enabling MVC for empty projects, visit https://go.microsoft.com/fwlink/?LinkID=397860
|
||||||
|
|
||||||
|
namespace Microsoft.eShopOnContainers.Services.Locations.API.Controllers
|
||||||
|
{
|
||||||
|
public class HomeController : Controller
|
||||||
|
{
|
||||||
|
// GET: /<controller>/
|
||||||
|
public IActionResult Index()
|
||||||
|
{
|
||||||
|
return new RedirectResult("~/swagger");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,62 @@
|
|||||||
|
using Microsoft.AspNetCore.Authorization;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using Microsoft.eShopOnContainers.Services.Locations.API.Infrastructure.Services;
|
||||||
|
using Microsoft.eShopOnContainers.Services.Locations.API.ViewModel;
|
||||||
|
using System;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Locations.API.Controllers
|
||||||
|
{
|
||||||
|
[Route("api/v1/[controller]")]
|
||||||
|
[Authorize]
|
||||||
|
public class LocationsController : ControllerBase
|
||||||
|
{
|
||||||
|
private readonly ILocationsService _locationsService;
|
||||||
|
private readonly IIdentityService _identityService;
|
||||||
|
|
||||||
|
public LocationsController(ILocationsService locationsService, IIdentityService identityService)
|
||||||
|
{
|
||||||
|
_locationsService = locationsService ?? throw new ArgumentNullException(nameof(locationsService));
|
||||||
|
_identityService = identityService ?? throw new ArgumentNullException(nameof(identityService));
|
||||||
|
}
|
||||||
|
|
||||||
|
//GET api/v1/[controller]/user/1
|
||||||
|
[Route("user/{userId:int}")]
|
||||||
|
[HttpGet]
|
||||||
|
public async Task<IActionResult> GetUserLocation(int userId)
|
||||||
|
{
|
||||||
|
var userLocation = await _locationsService.GetUserLocation(userId);
|
||||||
|
return Ok(userLocation);
|
||||||
|
}
|
||||||
|
|
||||||
|
//GET api/v1/[controller]/
|
||||||
|
[Route("")]
|
||||||
|
[HttpGet]
|
||||||
|
public async Task<IActionResult> GetAllLocations()
|
||||||
|
{
|
||||||
|
var locations = await _locationsService.GetAllLocation();
|
||||||
|
return Ok(locations);
|
||||||
|
}
|
||||||
|
|
||||||
|
//GET api/v1/[controller]/1
|
||||||
|
[Route("{locationId}")]
|
||||||
|
[HttpGet]
|
||||||
|
public async Task<IActionResult> GetLocation(string locationId)
|
||||||
|
{
|
||||||
|
var location = await _locationsService.GetLocation(locationId);
|
||||||
|
return Ok(location);
|
||||||
|
}
|
||||||
|
|
||||||
|
//POST api/v1/[controller]/
|
||||||
|
[Route("")]
|
||||||
|
[HttpPost]
|
||||||
|
public async Task<IActionResult> CreateOrUpdateUserLocation([FromBody]LocationRequest newLocReq)
|
||||||
|
{
|
||||||
|
var userId = _identityService.GetUserIdentity();
|
||||||
|
var result = await _locationsService.AddOrUpdateUserLocation(userId, newLocReq);
|
||||||
|
return result ?
|
||||||
|
(IActionResult)Ok() :
|
||||||
|
(IActionResult)BadRequest();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
6
src/Services/Location/Locations.API/Dockerfile
Normal file
6
src/Services/Location/Locations.API/Dockerfile
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
FROM microsoft/aspnetcore:1.1
|
||||||
|
ARG source
|
||||||
|
WORKDIR /app
|
||||||
|
EXPOSE 80
|
||||||
|
COPY ${source:-obj/Docker/publish} .
|
||||||
|
ENTRYPOINT ["dotnet", "Locations.API.dll"]
|
@ -0,0 +1,14 @@
|
|||||||
|
using Microsoft.AspNetCore.Http;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
|
||||||
|
namespace Microsoft.eShopOnContainers.Services.Locations.API.Infrastructure.ActionResults
|
||||||
|
{
|
||||||
|
public class InternalServerErrorObjectResult : ObjectResult
|
||||||
|
{
|
||||||
|
public InternalServerErrorObjectResult(object error)
|
||||||
|
: base(error)
|
||||||
|
{
|
||||||
|
StatusCode = StatusCodes.Status500InternalServerError;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,21 @@
|
|||||||
|
namespace Microsoft.eShopOnContainers.Services.Locations.API.Infrastructure.Exceptions
|
||||||
|
{
|
||||||
|
using System;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Exception type for app exceptions
|
||||||
|
/// </summary>
|
||||||
|
public class LocationDomainException : Exception
|
||||||
|
{
|
||||||
|
public LocationDomainException()
|
||||||
|
{ }
|
||||||
|
|
||||||
|
public LocationDomainException(string message)
|
||||||
|
: base(message)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
public LocationDomainException(string message, Exception innerException)
|
||||||
|
: base(message, innerException)
|
||||||
|
{ }
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,67 @@
|
|||||||
|
namespace Microsoft.eShopOnContainers.Services.Locations.API.Infrastructure.Filters
|
||||||
|
{
|
||||||
|
using AspNetCore.Mvc;
|
||||||
|
using Microsoft.AspNetCore.Hosting;
|
||||||
|
using Microsoft.AspNetCore.Mvc.Filters;
|
||||||
|
using Microsoft.eShopOnContainers.Services.Locations.API.Infrastructure.ActionResults;
|
||||||
|
using Microsoft.eShopOnContainers.Services.Locations.API.Infrastructure.Exceptions;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
using System.Net;
|
||||||
|
|
||||||
|
public class HttpGlobalExceptionFilter : IExceptionFilter
|
||||||
|
{
|
||||||
|
private readonly IHostingEnvironment env;
|
||||||
|
private readonly ILogger<HttpGlobalExceptionFilter> logger;
|
||||||
|
|
||||||
|
public HttpGlobalExceptionFilter(IHostingEnvironment env, ILogger<HttpGlobalExceptionFilter> logger)
|
||||||
|
{
|
||||||
|
this.env = env;
|
||||||
|
this.logger = logger;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnException(ExceptionContext context)
|
||||||
|
{
|
||||||
|
logger.LogError(new EventId(context.Exception.HResult),
|
||||||
|
context.Exception,
|
||||||
|
context.Exception.Message);
|
||||||
|
|
||||||
|
if (context.Exception.GetType() == typeof(LocationDomainException))
|
||||||
|
{
|
||||||
|
var json = new JsonErrorResponse
|
||||||
|
{
|
||||||
|
Messages = new[] { context.Exception.Message }
|
||||||
|
};
|
||||||
|
|
||||||
|
// Result asigned to a result object but in destiny the response is empty. This is a known bug of .net core 1.1
|
||||||
|
//It will be fixed in .net core 1.1.2. See https://github.com/aspnet/Mvc/issues/5594 for more information
|
||||||
|
context.Result = new BadRequestObjectResult(json);
|
||||||
|
context.HttpContext.Response.StatusCode = (int)HttpStatusCode.BadRequest;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var json = new JsonErrorResponse
|
||||||
|
{
|
||||||
|
Messages = new[] { "An error occur.Try it again." }
|
||||||
|
};
|
||||||
|
|
||||||
|
if (env.IsDevelopment())
|
||||||
|
{
|
||||||
|
json.DeveloperMessage = context.Exception;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Result asigned to a result object but in destiny the response is empty. This is a known bug of .net core 1.1
|
||||||
|
// It will be fixed in .net core 1.1.2. See https://github.com/aspnet/Mvc/issues/5594 for more information
|
||||||
|
context.Result = new InternalServerErrorObjectResult(json);
|
||||||
|
context.HttpContext.Response.StatusCode = (int)HttpStatusCode.InternalServerError;
|
||||||
|
}
|
||||||
|
context.ExceptionHandled = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private class JsonErrorResponse
|
||||||
|
{
|
||||||
|
public string[] Messages { get; set; }
|
||||||
|
|
||||||
|
public object DeveloperMessage { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,34 @@
|
|||||||
|
namespace Microsoft.eShopOnContainers.Services.Locations.API.Infrastructure
|
||||||
|
{
|
||||||
|
using Microsoft.eShopOnContainers.Services.Locations.API.Model;
|
||||||
|
using Microsoft.Extensions.Options;
|
||||||
|
using MongoDB.Driver;
|
||||||
|
|
||||||
|
public class LocationsContext
|
||||||
|
{
|
||||||
|
private readonly IMongoDatabase _database = null;
|
||||||
|
|
||||||
|
public LocationsContext(IOptions<LocationSettings> settings)
|
||||||
|
{
|
||||||
|
var client = new MongoClient(settings.Value.ConnectionString);
|
||||||
|
if (client != null)
|
||||||
|
_database = client.GetDatabase(settings.Value.Database);
|
||||||
|
}
|
||||||
|
|
||||||
|
public IMongoCollection<UserLocation> UserLocation
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return _database.GetCollection<UserLocation>("UserLocation");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public IMongoCollection<Locations> Locations
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return _database.GetCollection<Locations>("Locations");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,145 @@
|
|||||||
|
namespace Microsoft.eShopOnContainers.Services.Locations.API.Infrastructure
|
||||||
|
{
|
||||||
|
using Microsoft.AspNetCore.Builder;
|
||||||
|
using Microsoft.eShopOnContainers.Services.Locations.API.Model;
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
using Microsoft.Extensions.Options;
|
||||||
|
using MongoDB.Driver;
|
||||||
|
using MongoDB.Driver.GeoJsonObjectModel;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
public class LocationsContextSeed
|
||||||
|
{
|
||||||
|
private static LocationsContext ctx;
|
||||||
|
public static async Task SeedAsync(IApplicationBuilder applicationBuilder, ILoggerFactory loggerFactory)
|
||||||
|
{
|
||||||
|
var config = applicationBuilder
|
||||||
|
.ApplicationServices.GetRequiredService<IOptions<LocationSettings>>();
|
||||||
|
|
||||||
|
ctx = new LocationsContext(config);
|
||||||
|
|
||||||
|
if (!ctx.Locations.Database.GetCollection<Locations>(nameof(Locations)).AsQueryable().Any())
|
||||||
|
{
|
||||||
|
await SetIndexes();
|
||||||
|
await SetUSLocations();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static async Task SetUSLocations()
|
||||||
|
{
|
||||||
|
var us = new Locations()
|
||||||
|
{
|
||||||
|
Code = "US",
|
||||||
|
Description = "United States"
|
||||||
|
};
|
||||||
|
us.SetLocation(-101.357386, 41.650455);
|
||||||
|
us.SetArea(GetUSPoligon());
|
||||||
|
await ctx.Locations.InsertOneAsync(us);
|
||||||
|
await SetWashingtonLocations(us.Id);
|
||||||
|
}
|
||||||
|
|
||||||
|
static async Task SetWashingtonLocations(string parentId)
|
||||||
|
{
|
||||||
|
var wht = new Locations()
|
||||||
|
{
|
||||||
|
Parent_Id = parentId,
|
||||||
|
Code = "WHT",
|
||||||
|
Description = "Washington"
|
||||||
|
};
|
||||||
|
wht.SetLocation(-119.542781, 47.223652);
|
||||||
|
wht.SetArea(GetWashingtonPoligon());
|
||||||
|
await ctx.Locations.InsertOneAsync(wht);
|
||||||
|
await SetSeattleLocations(wht.Id);
|
||||||
|
await SetRedmondLocations(wht.Id);
|
||||||
|
}
|
||||||
|
|
||||||
|
static async Task SetSeattleLocations(string parentId)
|
||||||
|
{
|
||||||
|
var stl = new Locations()
|
||||||
|
{
|
||||||
|
Parent_Id = parentId,
|
||||||
|
Code = "SEAT",
|
||||||
|
Description = "Seattle"
|
||||||
|
};
|
||||||
|
stl.SetArea(GetSeattlePoligon());
|
||||||
|
stl.SetLocation(-122.330747, 47.603111);
|
||||||
|
await ctx.Locations.InsertOneAsync(stl);
|
||||||
|
}
|
||||||
|
|
||||||
|
static async Task SetRedmondLocations(string parentId)
|
||||||
|
{
|
||||||
|
var rdm = new Locations()
|
||||||
|
{
|
||||||
|
Parent_Id = parentId,
|
||||||
|
Code = "REDM",
|
||||||
|
Description = "Redmond"
|
||||||
|
};
|
||||||
|
rdm.SetLocation(-122.122887, 47.674961);
|
||||||
|
rdm.SetArea(GetRedmondPoligon());
|
||||||
|
await ctx.Locations.InsertOneAsync(rdm);
|
||||||
|
}
|
||||||
|
|
||||||
|
static async Task SetIndexes()
|
||||||
|
{
|
||||||
|
// Set location indexes
|
||||||
|
var builder = Builders<Locations>.IndexKeys;
|
||||||
|
var keys = builder.Geo2DSphere(prop => prop.Location);
|
||||||
|
await ctx.Locations.Indexes.CreateOneAsync(keys);
|
||||||
|
}
|
||||||
|
|
||||||
|
static List<GeoJson2DGeographicCoordinates> GetUSPoligon()
|
||||||
|
{
|
||||||
|
return new List<GeoJson2DGeographicCoordinates>()
|
||||||
|
{
|
||||||
|
new GeoJson2DGeographicCoordinates(-62.88205, 48.7985),
|
||||||
|
new GeoJson2DGeographicCoordinates(-129.3132, 48.76513),
|
||||||
|
new GeoJson2DGeographicCoordinates(-120.9496, 30.12256),
|
||||||
|
new GeoJson2DGeographicCoordinates(-111.3944, 30.87114),
|
||||||
|
new GeoJson2DGeographicCoordinates(-78.11975, 24.24979),
|
||||||
|
new GeoJson2DGeographicCoordinates(-62.88205, 48.7985)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
static List<GeoJson2DGeographicCoordinates> GetSeattlePoligon()
|
||||||
|
{
|
||||||
|
return new List<GeoJson2DGeographicCoordinates>()
|
||||||
|
{
|
||||||
|
new GeoJson2DGeographicCoordinates(-122.36238,47.82929),
|
||||||
|
new GeoJson2DGeographicCoordinates(-122.42091,47.6337),
|
||||||
|
new GeoJson2DGeographicCoordinates(-122.37371,47.45224),
|
||||||
|
new GeoJson2DGeographicCoordinates(-122.20788,47.50259),
|
||||||
|
new GeoJson2DGeographicCoordinates(-122.26934,47.73644),
|
||||||
|
new GeoJson2DGeographicCoordinates(-122.36238,47.82929)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
static List<GeoJson2DGeographicCoordinates> GetRedmondPoligon()
|
||||||
|
{
|
||||||
|
return new List<GeoJson2DGeographicCoordinates>()
|
||||||
|
{
|
||||||
|
new GeoJson2DGeographicCoordinates(-122.15432, 47.73148),
|
||||||
|
new GeoJson2DGeographicCoordinates(-122.17673, 47.72559),
|
||||||
|
new GeoJson2DGeographicCoordinates(-122.16904, 47.67851),
|
||||||
|
new GeoJson2DGeographicCoordinates(-122.16136, 47.65036),
|
||||||
|
new GeoJson2DGeographicCoordinates(-122.15604, 47.62746),
|
||||||
|
new GeoJson2DGeographicCoordinates(-122.01562, 47.63463),
|
||||||
|
new GeoJson2DGeographicCoordinates(-122.04961, 47.74244),
|
||||||
|
new GeoJson2DGeographicCoordinates(-122.15432, 47.73148)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
static List<GeoJson2DGeographicCoordinates> GetWashingtonPoligon()
|
||||||
|
{
|
||||||
|
return new List<GeoJson2DGeographicCoordinates>()
|
||||||
|
{
|
||||||
|
new GeoJson2DGeographicCoordinates(-124.68633, 48.8943),
|
||||||
|
new GeoJson2DGeographicCoordinates(-124.32962, 45.66613),
|
||||||
|
new GeoJson2DGeographicCoordinates(-116.73824, 45.93384),
|
||||||
|
new GeoJson2DGeographicCoordinates(-116.96912, 49.04282),
|
||||||
|
new GeoJson2DGeographicCoordinates(-124.68633, 48.8943)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,23 @@
|
|||||||
|
namespace Microsoft.eShopOnContainers.Services.Locations.API.Infrastructure.Repositories
|
||||||
|
{
|
||||||
|
using Microsoft.eShopOnContainers.Services.Locations.API.Model;
|
||||||
|
using ViewModel;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
public interface ILocationsRepository
|
||||||
|
{
|
||||||
|
Task<Locations> GetAsync(string locationId);
|
||||||
|
|
||||||
|
Task<List<Locations>> GetLocationListAsync();
|
||||||
|
|
||||||
|
Task<UserLocation> GetUserLocationAsync(int userId);
|
||||||
|
|
||||||
|
Task<List<Locations>> GetCurrentUserRegionsListAsync(LocationRequest currentPosition);
|
||||||
|
|
||||||
|
Task AddUserLocationAsync(UserLocation location);
|
||||||
|
|
||||||
|
Task UpdateUserLocationAsync(UserLocation userLocation);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,66 @@
|
|||||||
|
namespace Microsoft.eShopOnContainers.Services.Locations.API.Infrastructure.Repositories
|
||||||
|
{
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.eShopOnContainers.Services.Locations.API.Model;
|
||||||
|
using Microsoft.Extensions.Options;
|
||||||
|
using MongoDB.Bson;
|
||||||
|
using MongoDB.Driver;
|
||||||
|
using MongoDB.Driver.GeoJsonObjectModel;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using ViewModel;
|
||||||
|
|
||||||
|
public class LocationsRepository
|
||||||
|
: ILocationsRepository
|
||||||
|
{
|
||||||
|
private readonly LocationsContext _context;
|
||||||
|
|
||||||
|
public LocationsRepository(IOptions<LocationSettings> settings)
|
||||||
|
{
|
||||||
|
_context = new LocationsContext(settings);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<Locations> GetAsync(string locationId)
|
||||||
|
{
|
||||||
|
var filter = Builders<Locations>.Filter.Eq("Id", ObjectId.Parse(locationId));
|
||||||
|
return await _context.Locations
|
||||||
|
.Find(filter)
|
||||||
|
.FirstOrDefaultAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<UserLocation> GetUserLocationAsync(int userId)
|
||||||
|
{
|
||||||
|
var filter = Builders<UserLocation>.Filter.Eq("UserId", userId);
|
||||||
|
return await _context.UserLocation
|
||||||
|
.Find(filter)
|
||||||
|
.FirstOrDefaultAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<List<Locations>> GetLocationListAsync()
|
||||||
|
{
|
||||||
|
return await _context.Locations.Find(new BsonDocument()).ToListAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<List<Locations>> GetCurrentUserRegionsListAsync(LocationRequest currentPosition)
|
||||||
|
{
|
||||||
|
var point = GeoJson.Point(GeoJson.Geographic(currentPosition.Longitude, currentPosition.Latitude));
|
||||||
|
var orderByDistanceQuery = new FilterDefinitionBuilder<Locations>().Near(x => x.Location, point);
|
||||||
|
var withinAreaQuery = new FilterDefinitionBuilder<Locations>().GeoIntersects("Polygon", point);
|
||||||
|
var filter = Builders<Locations>.Filter.And(orderByDistanceQuery, withinAreaQuery);
|
||||||
|
return await _context.Locations.Find(filter).ToListAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task AddUserLocationAsync(UserLocation location)
|
||||||
|
{
|
||||||
|
await _context.UserLocation.InsertOneAsync(location);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task UpdateUserLocationAsync(UserLocation userLocation)
|
||||||
|
{
|
||||||
|
await _context.UserLocation.ReplaceOneAsync(
|
||||||
|
doc => doc.UserId == userLocation.UserId,
|
||||||
|
userLocation,
|
||||||
|
new UpdateOptions { IsUpsert = true });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,12 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Microsoft.eShopOnContainers.Services.Locations.API.Infrastructure.Services
|
||||||
|
{
|
||||||
|
public interface IIdentityService
|
||||||
|
{
|
||||||
|
string GetUserIdentity();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,18 @@
|
|||||||
|
namespace Microsoft.eShopOnContainers.Services.Locations.API.Infrastructure.Services
|
||||||
|
{
|
||||||
|
using Microsoft.eShopOnContainers.Services.Locations.API.Model;
|
||||||
|
using Microsoft.eShopOnContainers.Services.Locations.API.ViewModel;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
public interface ILocationsService
|
||||||
|
{
|
||||||
|
Task<Locations> GetLocation(string locationId);
|
||||||
|
|
||||||
|
Task<UserLocation> GetUserLocation(int id);
|
||||||
|
|
||||||
|
Task<List<Locations>> GetAllLocation();
|
||||||
|
|
||||||
|
Task<bool> AddOrUpdateUserLocation(string userId, LocationRequest locRequest);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,23 @@
|
|||||||
|
using Microsoft.AspNetCore.Http;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Microsoft.eShopOnContainers.Services.Locations.API.Infrastructure.Services
|
||||||
|
{
|
||||||
|
public class IdentityService : IIdentityService
|
||||||
|
{
|
||||||
|
private IHttpContextAccessor _context;
|
||||||
|
|
||||||
|
public IdentityService(IHttpContextAccessor context)
|
||||||
|
{
|
||||||
|
_context = context ?? throw new ArgumentNullException(nameof(context));
|
||||||
|
}
|
||||||
|
|
||||||
|
public string GetUserIdentity()
|
||||||
|
{
|
||||||
|
return _context.HttpContext.User.FindFirst("sub").Value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,63 @@
|
|||||||
|
namespace Microsoft.eShopOnContainers.Services.Locations.API.Infrastructure.Services
|
||||||
|
{
|
||||||
|
using Microsoft.eShopOnContainers.Services.Locations.API.Infrastructure.Repositories;
|
||||||
|
using Microsoft.eShopOnContainers.Services.Locations.API.ViewModel;
|
||||||
|
using Microsoft.eShopOnContainers.Services.Locations.API.Model;
|
||||||
|
using System;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using System.Linq;
|
||||||
|
using Microsoft.eShopOnContainers.Services.Locations.API.Infrastructure.Exceptions;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
public class LocationsService : ILocationsService
|
||||||
|
{
|
||||||
|
private ILocationsRepository _locationsRepository;
|
||||||
|
|
||||||
|
public LocationsService(ILocationsRepository locationsRepository)
|
||||||
|
{
|
||||||
|
_locationsRepository = locationsRepository ?? throw new ArgumentNullException(nameof(locationsRepository));
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<Locations> GetLocation(string locationId)
|
||||||
|
{
|
||||||
|
return await _locationsRepository.GetAsync(locationId);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<UserLocation> GetUserLocation(int id)
|
||||||
|
{
|
||||||
|
return await _locationsRepository.GetUserLocationAsync(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<List<Locations>> GetAllLocation()
|
||||||
|
{
|
||||||
|
return await _locationsRepository.GetLocationListAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<bool> AddOrUpdateUserLocation(string id, LocationRequest currentPosition)
|
||||||
|
{
|
||||||
|
if (!int.TryParse(id, out int userId))
|
||||||
|
{
|
||||||
|
throw new ArgumentException("Not valid userId");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the list of ordered regions the user currently is within
|
||||||
|
var currentUserAreaLocationList = await _locationsRepository.GetCurrentUserRegionsListAsync(currentPosition);
|
||||||
|
|
||||||
|
if(currentUserAreaLocationList is null)
|
||||||
|
{
|
||||||
|
throw new LocationDomainException("User current area not found");
|
||||||
|
}
|
||||||
|
|
||||||
|
// If current area found, then update user location
|
||||||
|
var locationAncestors = new List<string>();
|
||||||
|
var userLocation = await _locationsRepository.GetUserLocationAsync(userId);
|
||||||
|
userLocation = userLocation ?? new UserLocation();
|
||||||
|
userLocation.UserId = userId;
|
||||||
|
userLocation.LocationId = currentUserAreaLocationList[0].Id;
|
||||||
|
userLocation.UpdateDate = DateTime.UtcNow;
|
||||||
|
await _locationsRepository.UpdateUserLocationAsync(userLocation);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
15
src/Services/Location/Locations.API/LocationSettings.cs
Normal file
15
src/Services/Location/Locations.API/LocationSettings.cs
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Microsoft.eShopOnContainers.Services.Locations.API
|
||||||
|
{
|
||||||
|
public class LocationSettings
|
||||||
|
{
|
||||||
|
public string ExternalCatalogBaseUrl { get; set; }
|
||||||
|
public string EventBusConnection { get; set; }
|
||||||
|
public string ConnectionString { get; set; }
|
||||||
|
public string Database { get; set; }
|
||||||
|
}
|
||||||
|
}
|
41
src/Services/Location/Locations.API/Locations.API.csproj
Normal file
41
src/Services/Location/Locations.API/Locations.API.csproj
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>netcoreapp1.1</TargetFramework>
|
||||||
|
<DockerComposeProjectPath>..\..\..\..\docker-compose.dcproj</DockerComposeProjectPath>
|
||||||
|
<RootNamespace>Microsoft.eShopOnContainers.Services.Locations.API</RootNamespace>
|
||||||
|
<UserSecretsId>aspnet-Locations.API-20161122013619</UserSecretsId>
|
||||||
|
</PropertyGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Folder Include="wwwroot\" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="IdentityServer4.AccessTokenValidation" Version="1.2.0" />
|
||||||
|
<PackageReference Include="Microsoft.ApplicationInsights.AspNetCore" Version="2.0.0" />
|
||||||
|
<PackageReference Include="Microsoft.AspNetCore" Version="1.1.2" />
|
||||||
|
<PackageReference Include="Microsoft.AspNetCore.Mvc" Version="1.1.3" />
|
||||||
|
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="1.1.2" />
|
||||||
|
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="1.1.2" />
|
||||||
|
<PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="1.1.2" />
|
||||||
|
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="1.1.2" />
|
||||||
|
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer.Design" Version="1.1.2" />
|
||||||
|
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="1.1.1" />
|
||||||
|
<PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="1.1.2" />
|
||||||
|
<PackageReference Include="Microsoft.Extensions.Configuration.UserSecrets" Version="1.1.2" />
|
||||||
|
<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="1.1.2" />
|
||||||
|
<PackageReference Include="Microsoft.Extensions.Options" Version="1.1.2" />
|
||||||
|
<PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="1.1.2" />
|
||||||
|
<PackageReference Include="mongocsharpdriver" Version="2.4.3" />
|
||||||
|
<PackageReference Include="MongoDB.Bson" Version="2.4.3" />
|
||||||
|
<PackageReference Include="MongoDB.Driver" Version="2.4.3" />
|
||||||
|
<PackageReference Include="MongoDB.Driver.Core" Version="2.4.3" />
|
||||||
|
<PackageReference Include="Swashbuckle.AspNetCore" Version="1.0.0" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<DotNetCliToolReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Tools" Version="1.0.1" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<DotNetCliToolReference Include="Microsoft.EntityFrameworkCore.Tools.DotNet" Version="1.0.0" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
37
src/Services/Location/Locations.API/Model/Locations.cs
Normal file
37
src/Services/Location/Locations.API/Model/Locations.cs
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
namespace Microsoft.eShopOnContainers.Services.Locations.API.Model
|
||||||
|
{
|
||||||
|
using MongoDB.Bson;
|
||||||
|
using MongoDB.Driver.GeoJsonObjectModel;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using MongoDB.Bson.Serialization.Attributes;
|
||||||
|
|
||||||
|
public class Locations
|
||||||
|
{
|
||||||
|
[BsonRepresentation(BsonType.ObjectId)]
|
||||||
|
public string Id { get; set; }
|
||||||
|
public string Code { get; set; }
|
||||||
|
[BsonRepresentation(BsonType.ObjectId)]
|
||||||
|
public string Parent_Id { get; set; }
|
||||||
|
public string Description { get; set; }
|
||||||
|
public double Latitude { get; set; }
|
||||||
|
public double Longitude { get; set; }
|
||||||
|
public GeoJsonPoint<GeoJson2DGeographicCoordinates> Location { get; private set; }
|
||||||
|
public GeoJsonPolygon<GeoJson2DGeographicCoordinates> Polygon { get; private set; }
|
||||||
|
public void SetLocation(double lon, double lat) => SetPosition(lon, lat);
|
||||||
|
public void SetArea(List<GeoJson2DGeographicCoordinates> coordinatesList) => SetPolygon(coordinatesList);
|
||||||
|
|
||||||
|
private void SetPosition(double lon, double lat)
|
||||||
|
{
|
||||||
|
Latitude = lat;
|
||||||
|
Longitude = lon;
|
||||||
|
Location = new GeoJsonPoint<GeoJson2DGeographicCoordinates>(
|
||||||
|
new GeoJson2DGeographicCoordinates(lon, lat));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SetPolygon(List<GeoJson2DGeographicCoordinates> coordinatesList)
|
||||||
|
{
|
||||||
|
Polygon = new GeoJsonPolygon<GeoJson2DGeographicCoordinates>(new GeoJsonPolygonCoordinates<GeoJson2DGeographicCoordinates>(
|
||||||
|
new GeoJsonLinearRingCoordinates<GeoJson2DGeographicCoordinates>(coordinatesList)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
17
src/Services/Location/Locations.API/Model/UserLocation.cs
Normal file
17
src/Services/Location/Locations.API/Model/UserLocation.cs
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
namespace Microsoft.eShopOnContainers.Services.Locations.API.Model
|
||||||
|
{
|
||||||
|
using MongoDB.Bson;
|
||||||
|
using MongoDB.Bson.Serialization.Attributes;
|
||||||
|
using System;
|
||||||
|
|
||||||
|
public class UserLocation
|
||||||
|
{
|
||||||
|
[BsonIgnoreIfDefault]
|
||||||
|
[BsonRepresentation(BsonType.ObjectId)]
|
||||||
|
public string Id { get; set; }
|
||||||
|
public int UserId { get; set; } = 0;
|
||||||
|
[BsonRepresentation(BsonType.ObjectId)]
|
||||||
|
public string LocationId { get; set; }
|
||||||
|
public DateTime UpdateDate { get; set; }
|
||||||
|
}
|
||||||
|
}
|
25
src/Services/Location/Locations.API/Program.cs
Normal file
25
src/Services/Location/Locations.API/Program.cs
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.AspNetCore.Builder;
|
||||||
|
using Microsoft.AspNetCore.Hosting;
|
||||||
|
|
||||||
|
namespace Microsoft.eShopOnContainers.Services.Locations.API
|
||||||
|
{
|
||||||
|
public class Program
|
||||||
|
{
|
||||||
|
public static void Main(string[] args)
|
||||||
|
{
|
||||||
|
var host = new WebHostBuilder()
|
||||||
|
.UseKestrel()
|
||||||
|
.UseContentRoot(Directory.GetCurrentDirectory())
|
||||||
|
.UseStartup<Startup>()
|
||||||
|
.UseApplicationInsights()
|
||||||
|
.Build();
|
||||||
|
|
||||||
|
host.Run();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,29 @@
|
|||||||
|
{
|
||||||
|
"iisSettings": {
|
||||||
|
"windowsAuthentication": false,
|
||||||
|
"anonymousAuthentication": true,
|
||||||
|
"iisExpress": {
|
||||||
|
"applicationUrl": "http://localhost:3278/",
|
||||||
|
"sslPort": 0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"profiles": {
|
||||||
|
"IIS Express": {
|
||||||
|
"commandName": "IISExpress",
|
||||||
|
"launchBrowser": true,
|
||||||
|
"launchUrl": "api/values",
|
||||||
|
"environmentVariables": {
|
||||||
|
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Locations.API": {
|
||||||
|
"commandName": "Project",
|
||||||
|
"launchBrowser": true,
|
||||||
|
"launchUrl": "api/values",
|
||||||
|
"environmentVariables": {
|
||||||
|
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||||
|
},
|
||||||
|
"applicationUrl": "http://localhost:3279"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
113
src/Services/Location/Locations.API/Startup.cs
Normal file
113
src/Services/Location/Locations.API/Startup.cs
Normal file
@ -0,0 +1,113 @@
|
|||||||
|
using Microsoft.AspNetCore.Builder;
|
||||||
|
using Microsoft.AspNetCore.Hosting;
|
||||||
|
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.eShopOnContainers.Services.Locations.API.Infrastructure;
|
||||||
|
using Microsoft.Extensions.Configuration;
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
using System.Reflection;
|
||||||
|
using System;
|
||||||
|
using Microsoft.eShopOnContainers.Services.Locations.API.Infrastructure.Services;
|
||||||
|
using Microsoft.eShopOnContainers.Services.Locations.API.Infrastructure.Repositories;
|
||||||
|
using Microsoft.AspNetCore.Http;
|
||||||
|
using Microsoft.eShopOnContainers.Services.Locations.API.Infrastructure.Filters;
|
||||||
|
|
||||||
|
namespace Microsoft.eShopOnContainers.Services.Locations.API
|
||||||
|
{
|
||||||
|
public class Startup
|
||||||
|
{
|
||||||
|
public IConfigurationRoot Configuration { get; }
|
||||||
|
|
||||||
|
public Startup(IHostingEnvironment env)
|
||||||
|
{
|
||||||
|
var builder = new ConfigurationBuilder()
|
||||||
|
.SetBasePath(env.ContentRootPath)
|
||||||
|
.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
|
||||||
|
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true);
|
||||||
|
|
||||||
|
if (env.IsDevelopment())
|
||||||
|
{
|
||||||
|
builder.AddUserSecrets(typeof(Startup).GetTypeInfo().Assembly);
|
||||||
|
}
|
||||||
|
|
||||||
|
builder.AddEnvironmentVariables();
|
||||||
|
|
||||||
|
Configuration = builder.Build();
|
||||||
|
}
|
||||||
|
|
||||||
|
// This method gets called by the runtime. Use this method to add services to the container.
|
||||||
|
public void ConfigureServices(IServiceCollection services)
|
||||||
|
{
|
||||||
|
// Add framework services.
|
||||||
|
services.AddMvc(options =>
|
||||||
|
{
|
||||||
|
options.Filters.Add(typeof(HttpGlobalExceptionFilter));
|
||||||
|
}).AddControllersAsServices();
|
||||||
|
|
||||||
|
services.Configure<LocationSettings>(Configuration);
|
||||||
|
|
||||||
|
// Add framework services.
|
||||||
|
services.AddSwaggerGen(options =>
|
||||||
|
{
|
||||||
|
options.DescribeAllEnumsAsStrings();
|
||||||
|
options.SwaggerDoc("v1", new Swashbuckle.AspNetCore.Swagger.Info
|
||||||
|
{
|
||||||
|
Title = "eShopOnContainers - Location HTTP API",
|
||||||
|
Version = "v1",
|
||||||
|
Description = "The Location Microservice HTTP API. This is a Data-Driven/CRUD microservice sample",
|
||||||
|
TermsOfService = "Terms Of Service"
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
services.AddCors(options =>
|
||||||
|
{
|
||||||
|
options.AddPolicy("CorsPolicy",
|
||||||
|
builder => builder.AllowAnyOrigin()
|
||||||
|
.AllowAnyMethod()
|
||||||
|
.AllowAnyHeader()
|
||||||
|
.AllowCredentials());
|
||||||
|
});
|
||||||
|
|
||||||
|
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
|
||||||
|
services.AddTransient<IIdentityService, IdentityService>();
|
||||||
|
services.AddTransient<ILocationsService, LocationsService>();
|
||||||
|
services.AddTransient<ILocationsRepository, LocationsRepository>();
|
||||||
|
}
|
||||||
|
|
||||||
|
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
|
||||||
|
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
|
||||||
|
{
|
||||||
|
//Configure logs
|
||||||
|
|
||||||
|
loggerFactory.AddConsole(Configuration.GetSection("Logging"));
|
||||||
|
loggerFactory.AddDebug();
|
||||||
|
|
||||||
|
app.UseCors("CorsPolicy");
|
||||||
|
|
||||||
|
ConfigureAuth(app);
|
||||||
|
|
||||||
|
app.UseMvcWithDefaultRoute();
|
||||||
|
|
||||||
|
app.UseSwagger()
|
||||||
|
.UseSwaggerUI(c =>
|
||||||
|
{
|
||||||
|
c.SwaggerEndpoint("/swagger/v1/swagger.json", "My API V1");
|
||||||
|
});
|
||||||
|
|
||||||
|
LocationsContextSeed.SeedAsync(app, loggerFactory)
|
||||||
|
.Wait();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected virtual void ConfigureAuth(IApplicationBuilder app)
|
||||||
|
{
|
||||||
|
var identityUrl = Configuration.GetValue<string>("IdentityUrl");
|
||||||
|
app.UseIdentityServerAuthentication(new IdentityServerAuthenticationOptions
|
||||||
|
{
|
||||||
|
Authority = identityUrl.ToString(),
|
||||||
|
ApiName = "locations",
|
||||||
|
RequireHttpsMetadata = false
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,13 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Microsoft.eShopOnContainers.Services.Locations.API.ViewModel
|
||||||
|
{
|
||||||
|
public class LocationRequest
|
||||||
|
{
|
||||||
|
public double Longitude { get; set; }
|
||||||
|
public double Latitude { get; set; }
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,10 @@
|
|||||||
|
{
|
||||||
|
"Logging": {
|
||||||
|
"IncludeScopes": false,
|
||||||
|
"LogLevel": {
|
||||||
|
"Default": "Debug",
|
||||||
|
"System": "Information",
|
||||||
|
"Microsoft": "Information"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
13
src/Services/Location/Locations.API/appsettings.json
Normal file
13
src/Services/Location/Locations.API/appsettings.json
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
{
|
||||||
|
"ConnectionString": "mongodb://nosql.data",
|
||||||
|
"Database": "LocationsDb",
|
||||||
|
"IdentityUrl": "http://localhost:5105",
|
||||||
|
"Logging": {
|
||||||
|
"IncludeScopes": false,
|
||||||
|
"LogLevel": {
|
||||||
|
"Default": "Debug",
|
||||||
|
"System": "Information",
|
||||||
|
"Microsoft": "Information"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
3
src/Services/Marketing/Marketing.API/.dockerignore
Normal file
3
src/Services/Marketing/Marketing.API/.dockerignore
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
*
|
||||||
|
!obj/Docker/publish/*
|
||||||
|
!obj/Docker/empty/
|
@ -0,0 +1,151 @@
|
|||||||
|
namespace Microsoft.eShopOnContainers.Services.Marketing.API.Controllers
|
||||||
|
{
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using Microsoft.eShopOnContainers.Services.Marketing.API.Infrastructure;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.eShopOnContainers.Services.Marketing.API.Model;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.eShopOnContainers.Services.Marketing.API.Dto;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Microsoft.AspNetCore.Authorization;
|
||||||
|
|
||||||
|
[Route("api/v1/[controller]")]
|
||||||
|
[Authorize]
|
||||||
|
public class CampaignsController : Controller
|
||||||
|
{
|
||||||
|
private readonly MarketingContext _context;
|
||||||
|
|
||||||
|
public CampaignsController(MarketingContext context)
|
||||||
|
{
|
||||||
|
_context = context;
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpGet]
|
||||||
|
public async Task<IActionResult> GetAllCampaigns()
|
||||||
|
{
|
||||||
|
var campaignList = await _context.Campaigns
|
||||||
|
.ToListAsync();
|
||||||
|
|
||||||
|
if (campaignList is null)
|
||||||
|
{
|
||||||
|
return Ok();
|
||||||
|
}
|
||||||
|
|
||||||
|
var campaignDtoList = MapCampaignModelListToDtoList(campaignList);
|
||||||
|
|
||||||
|
return Ok(campaignDtoList);
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpGet("{id:int}")]
|
||||||
|
public async Task<IActionResult> GetCampaignById(int id)
|
||||||
|
{
|
||||||
|
var campaign = await _context.Campaigns
|
||||||
|
.SingleOrDefaultAsync(c => c.Id == id);
|
||||||
|
|
||||||
|
if (campaign is null)
|
||||||
|
{
|
||||||
|
return NotFound();
|
||||||
|
}
|
||||||
|
|
||||||
|
var campaignDto = MapCampaignModelToDto(campaign);
|
||||||
|
|
||||||
|
return Ok(campaignDto);
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpPost]
|
||||||
|
public async Task<IActionResult> CreateCampaign([FromBody] CampaignDTO campaignDto)
|
||||||
|
{
|
||||||
|
if (campaignDto is null)
|
||||||
|
{
|
||||||
|
return BadRequest();
|
||||||
|
}
|
||||||
|
|
||||||
|
var campaign = MapCampaignDtoToModel(campaignDto);
|
||||||
|
|
||||||
|
await _context.Campaigns.AddAsync(campaign);
|
||||||
|
await _context.SaveChangesAsync();
|
||||||
|
|
||||||
|
return CreatedAtAction(nameof(GetCampaignById), new { id = campaign.Id }, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpPut("{id:int}")]
|
||||||
|
public async Task<IActionResult> UpdateCampaign(int id, [FromBody] CampaignDTO campaignDto)
|
||||||
|
{
|
||||||
|
if (id < 1 || campaignDto is null)
|
||||||
|
{
|
||||||
|
return BadRequest();
|
||||||
|
}
|
||||||
|
|
||||||
|
var campaignToUpdate = await _context.Campaigns.FindAsync(id);
|
||||||
|
if (campaignToUpdate is null)
|
||||||
|
{
|
||||||
|
return NotFound();
|
||||||
|
}
|
||||||
|
|
||||||
|
campaignToUpdate.Description = campaignDto.Description;
|
||||||
|
campaignToUpdate.From = campaignDto.From;
|
||||||
|
campaignToUpdate.To = campaignDto.To;
|
||||||
|
campaignToUpdate.Url = campaignDto.Url;
|
||||||
|
|
||||||
|
await _context.SaveChangesAsync();
|
||||||
|
|
||||||
|
return CreatedAtAction(nameof(GetCampaignById), new { id = campaignToUpdate.Id }, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpDelete("{id:int}")]
|
||||||
|
public async Task<IActionResult> Delete(int id)
|
||||||
|
{
|
||||||
|
if (id < 1)
|
||||||
|
{
|
||||||
|
return BadRequest();
|
||||||
|
}
|
||||||
|
|
||||||
|
var campaignToDelete = await _context.Campaigns.FindAsync(id);
|
||||||
|
if (campaignToDelete is null)
|
||||||
|
{
|
||||||
|
return NotFound();
|
||||||
|
}
|
||||||
|
|
||||||
|
_context.Campaigns.Remove(campaignToDelete);
|
||||||
|
await _context.SaveChangesAsync();
|
||||||
|
|
||||||
|
return NoContent();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
private List<CampaignDTO> MapCampaignModelListToDtoList(List<Campaign> campaignList)
|
||||||
|
{
|
||||||
|
var campaignDtoList = new List<CampaignDTO>();
|
||||||
|
|
||||||
|
campaignList.ForEach(campaign => campaignDtoList
|
||||||
|
.Add(MapCampaignModelToDto(campaign)));
|
||||||
|
|
||||||
|
return campaignDtoList;
|
||||||
|
}
|
||||||
|
|
||||||
|
private CampaignDTO MapCampaignModelToDto(Campaign campaign)
|
||||||
|
{
|
||||||
|
return new CampaignDTO
|
||||||
|
{
|
||||||
|
Id = campaign.Id,
|
||||||
|
Description = campaign.Description,
|
||||||
|
From = campaign.From,
|
||||||
|
To = campaign.To,
|
||||||
|
Url = campaign.Url,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private Campaign MapCampaignDtoToModel(CampaignDTO campaignDto)
|
||||||
|
{
|
||||||
|
return new Campaign
|
||||||
|
{
|
||||||
|
Id = campaignDto.Id,
|
||||||
|
Description = campaignDto.Description,
|
||||||
|
From = campaignDto.From,
|
||||||
|
To = campaignDto.To,
|
||||||
|
Url = campaignDto.Url
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,13 @@
|
|||||||
|
namespace Microsoft.eShopOnContainers.Services.Marketing.API.Controllers
|
||||||
|
{
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
|
||||||
|
// GET: /<controller>/
|
||||||
|
public class HomeController : Controller
|
||||||
|
{
|
||||||
|
public IActionResult Index()
|
||||||
|
{
|
||||||
|
return new RedirectResult("~/swagger");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,146 @@
|
|||||||
|
namespace Microsoft.eShopOnContainers.Services.Marketing.API.Controllers
|
||||||
|
{
|
||||||
|
using Microsoft.AspNetCore.Authorization;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using Microsoft.eShopOnContainers.Services.Marketing.API.Dto;
|
||||||
|
using Microsoft.eShopOnContainers.Services.Marketing.API.Infrastructure;
|
||||||
|
using Microsoft.eShopOnContainers.Services.Marketing.API.Model;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
[Authorize]
|
||||||
|
public class LocationsController : Controller
|
||||||
|
{
|
||||||
|
private readonly MarketingContext _context;
|
||||||
|
|
||||||
|
public LocationsController(MarketingContext context)
|
||||||
|
{
|
||||||
|
_context = context;
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpGet]
|
||||||
|
[Route("api/v1/campaigns/{campaignId:int}/locations/{userLocationRuleId:int}")]
|
||||||
|
public IActionResult GetLocationByCampaignAndLocationRuleId(int campaignId,
|
||||||
|
int userLocationRuleId)
|
||||||
|
{
|
||||||
|
if (campaignId < 1 || userLocationRuleId < 1)
|
||||||
|
{
|
||||||
|
return BadRequest();
|
||||||
|
}
|
||||||
|
|
||||||
|
var location = _context.Rules
|
||||||
|
.OfType<UserLocationRule>()
|
||||||
|
.SingleOrDefault(c => c.CampaignId == campaignId && c.Id == userLocationRuleId);
|
||||||
|
|
||||||
|
if (location is null)
|
||||||
|
{
|
||||||
|
return NotFound();
|
||||||
|
}
|
||||||
|
|
||||||
|
var locationDto = MapUserLocationRuleModelToDto(location);
|
||||||
|
|
||||||
|
return Ok(locationDto);
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpGet]
|
||||||
|
[Route("api/v1/campaigns/{campaignId:int}/locations")]
|
||||||
|
public IActionResult GetAllLocationsByCampaignId(int campaignId)
|
||||||
|
{
|
||||||
|
if (campaignId < 1)
|
||||||
|
{
|
||||||
|
return BadRequest();
|
||||||
|
}
|
||||||
|
|
||||||
|
var locationList = _context.Rules
|
||||||
|
.OfType<UserLocationRule>()
|
||||||
|
.Where(c => c.CampaignId == campaignId)
|
||||||
|
.ToList();
|
||||||
|
|
||||||
|
if(locationList is null)
|
||||||
|
{
|
||||||
|
return Ok();
|
||||||
|
}
|
||||||
|
|
||||||
|
var locationDtoList = MapUserLocationRuleModelListToDtoList(locationList);
|
||||||
|
|
||||||
|
return Ok(locationDtoList);
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpPost]
|
||||||
|
[Route("api/v1/campaigns/{campaignId:int}/locations")]
|
||||||
|
public async Task<IActionResult> CreateLocation(int campaignId,
|
||||||
|
[FromBody] UserLocationRuleDTO locationRuleDto)
|
||||||
|
{
|
||||||
|
if (campaignId < 1 || locationRuleDto is null)
|
||||||
|
{
|
||||||
|
return BadRequest();
|
||||||
|
}
|
||||||
|
|
||||||
|
var locationRule = MapUserLocationRuleDtoToModel(locationRuleDto);
|
||||||
|
locationRule.CampaignId = campaignId;
|
||||||
|
|
||||||
|
await _context.Rules.AddAsync(locationRule);
|
||||||
|
await _context.SaveChangesAsync();
|
||||||
|
|
||||||
|
return CreatedAtAction(nameof(GetLocationByCampaignAndLocationRuleId),
|
||||||
|
new { campaignId = campaignId, locationRuleId = locationRule.Id }, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpDelete]
|
||||||
|
[Route("api/v1/campaigns/{campaignId:int}/locations/{userLocationRuleId:int}")]
|
||||||
|
public async Task<IActionResult> DeleteLocationById(int campaignId, int userLocationRuleId)
|
||||||
|
{
|
||||||
|
if (campaignId < 1 || userLocationRuleId < 1)
|
||||||
|
{
|
||||||
|
return BadRequest();
|
||||||
|
}
|
||||||
|
|
||||||
|
var locationToDelete = _context.Rules
|
||||||
|
.OfType<UserLocationRule>()
|
||||||
|
.SingleOrDefault(c => c.CampaignId == campaignId && c.Id == userLocationRuleId);
|
||||||
|
|
||||||
|
if (locationToDelete is null)
|
||||||
|
{
|
||||||
|
return NotFound();
|
||||||
|
}
|
||||||
|
|
||||||
|
_context.Rules.Remove(locationToDelete);
|
||||||
|
await _context.SaveChangesAsync();
|
||||||
|
|
||||||
|
return NoContent();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
private List<UserLocationRuleDTO> MapUserLocationRuleModelListToDtoList(List<UserLocationRule> userLocationRuleList)
|
||||||
|
{
|
||||||
|
var userLocationRuleDtoList = new List<UserLocationRuleDTO>();
|
||||||
|
|
||||||
|
userLocationRuleList.ForEach(userLocationRule => userLocationRuleDtoList
|
||||||
|
.Add(MapUserLocationRuleModelToDto(userLocationRule)));
|
||||||
|
|
||||||
|
return userLocationRuleDtoList;
|
||||||
|
}
|
||||||
|
|
||||||
|
private UserLocationRuleDTO MapUserLocationRuleModelToDto(UserLocationRule userLocationRule)
|
||||||
|
{
|
||||||
|
return new UserLocationRuleDTO
|
||||||
|
{
|
||||||
|
Id = userLocationRule.Id,
|
||||||
|
Description = userLocationRule.Description,
|
||||||
|
LocationId = userLocationRule.LocationId
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private UserLocationRule MapUserLocationRuleDtoToModel(UserLocationRuleDTO userLocationRuleDto)
|
||||||
|
{
|
||||||
|
return new UserLocationRule
|
||||||
|
{
|
||||||
|
Id = userLocationRuleDto.Id,
|
||||||
|
Description = userLocationRuleDto.Description,
|
||||||
|
LocationId = userLocationRuleDto.LocationId
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
6
src/Services/Marketing/Marketing.API/Dockerfile
Normal file
6
src/Services/Marketing/Marketing.API/Dockerfile
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
FROM microsoft/aspnetcore:1.1.2
|
||||||
|
ARG source
|
||||||
|
WORKDIR /app
|
||||||
|
EXPOSE 80
|
||||||
|
COPY ${source:-obj/Docker/publish} .
|
||||||
|
ENTRYPOINT ["dotnet", "Marketing.API.dll"]
|
17
src/Services/Marketing/Marketing.API/Dto/CampaignDTO.cs
Normal file
17
src/Services/Marketing/Marketing.API/Dto/CampaignDTO.cs
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
namespace Microsoft.eShopOnContainers.Services.Marketing.API.Dto
|
||||||
|
{
|
||||||
|
using System;
|
||||||
|
|
||||||
|
public class CampaignDTO
|
||||||
|
{
|
||||||
|
public int Id { get; set; }
|
||||||
|
|
||||||
|
public string Description { get; set; }
|
||||||
|
|
||||||
|
public DateTime From { get; set; }
|
||||||
|
|
||||||
|
public DateTime To { get; set; }
|
||||||
|
|
||||||
|
public string Url { get; set; }
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,11 @@
|
|||||||
|
namespace Microsoft.eShopOnContainers.Services.Marketing.API.Dto
|
||||||
|
{
|
||||||
|
public class UserLocationRuleDTO
|
||||||
|
{
|
||||||
|
public int Id { get; set; }
|
||||||
|
|
||||||
|
public int LocationId { get; set; }
|
||||||
|
|
||||||
|
public string Description { get; set; }
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,14 @@
|
|||||||
|
namespace Microsoft.eShopOnContainers.Services.Marketing.API.Infrastructure.ActionResults
|
||||||
|
{
|
||||||
|
using AspNetCore.Http;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
|
||||||
|
public class InternalServerErrorObjectResult : ObjectResult
|
||||||
|
{
|
||||||
|
public InternalServerErrorObjectResult(object error)
|
||||||
|
: base(error)
|
||||||
|
{
|
||||||
|
StatusCode = StatusCodes.Status500InternalServerError;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,21 @@
|
|||||||
|
namespace Microsoft.eShopOnContainers.Services.Marketing.API.Infrastructure.Exceptions
|
||||||
|
{
|
||||||
|
using System;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Exception type for app exceptions
|
||||||
|
/// </summary>
|
||||||
|
public class MarketingDomainException : Exception
|
||||||
|
{
|
||||||
|
public MarketingDomainException()
|
||||||
|
{ }
|
||||||
|
|
||||||
|
public MarketingDomainException(string message)
|
||||||
|
: base(message)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
public MarketingDomainException(string message, Exception innerException)
|
||||||
|
: base(message, innerException)
|
||||||
|
{ }
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,67 @@
|
|||||||
|
namespace Microsoft.eShopOnContainers.Services.Marketing.API.Infrastructure.Filters
|
||||||
|
{
|
||||||
|
using AspNetCore.Mvc;
|
||||||
|
using global::Microsoft.eShopOnContainers.Services.Marketing.API.Infrastructure.Exceptions;
|
||||||
|
using Microsoft.AspNetCore.Hosting;
|
||||||
|
using Microsoft.AspNetCore.Mvc.Filters;
|
||||||
|
using Microsoft.eShopOnContainers.Services.Marketing.API.Infrastructure.ActionResults;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
using System.Net;
|
||||||
|
|
||||||
|
public class HttpGlobalExceptionFilter : IExceptionFilter
|
||||||
|
{
|
||||||
|
private readonly IHostingEnvironment env;
|
||||||
|
private readonly ILogger<HttpGlobalExceptionFilter> logger;
|
||||||
|
|
||||||
|
public HttpGlobalExceptionFilter(IHostingEnvironment env, ILogger<HttpGlobalExceptionFilter> logger)
|
||||||
|
{
|
||||||
|
this.env = env;
|
||||||
|
this.logger = logger;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnException(ExceptionContext context)
|
||||||
|
{
|
||||||
|
logger.LogError(new EventId(context.Exception.HResult),
|
||||||
|
context.Exception,
|
||||||
|
context.Exception.Message);
|
||||||
|
|
||||||
|
if (context.Exception.GetType() == typeof(MarketingDomainException))
|
||||||
|
{
|
||||||
|
var json = new JsonErrorResponse
|
||||||
|
{
|
||||||
|
Messages = new[] { context.Exception.Message }
|
||||||
|
};
|
||||||
|
|
||||||
|
// Result asigned to a result object but in destiny the response is empty. This is a known bug of .net core 1.1
|
||||||
|
//It will be fixed in .net core 1.1.2. See https://github.com/aspnet/Mvc/issues/5594 for more information
|
||||||
|
context.Result = new BadRequestObjectResult(json);
|
||||||
|
context.HttpContext.Response.StatusCode = (int)HttpStatusCode.BadRequest;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var json = new JsonErrorResponse
|
||||||
|
{
|
||||||
|
Messages = new[] { "An error occur.Try it again." }
|
||||||
|
};
|
||||||
|
|
||||||
|
if (env.IsDevelopment())
|
||||||
|
{
|
||||||
|
json.DeveloperMessage = context.Exception;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Result asigned to a result object but in destiny the response is empty. This is a known bug of .net core 1.1
|
||||||
|
// It will be fixed in .net core 1.1.2. See https://github.com/aspnet/Mvc/issues/5594 for more information
|
||||||
|
context.Result = new InternalServerErrorObjectResult(json);
|
||||||
|
context.HttpContext.Response.StatusCode = (int)HttpStatusCode.InternalServerError;
|
||||||
|
}
|
||||||
|
context.ExceptionHandled = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private class JsonErrorResponse
|
||||||
|
{
|
||||||
|
public string[] Messages { get; set; }
|
||||||
|
|
||||||
|
public object DeveloperMessage { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,83 @@
|
|||||||
|
namespace Microsoft.eShopOnContainers.Services.Marketing.API.Infrastructure
|
||||||
|
{
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Metadata.Builders;
|
||||||
|
using Microsoft.eShopOnContainers.Services.Marketing.API.Model;
|
||||||
|
|
||||||
|
public class MarketingContext : DbContext
|
||||||
|
{
|
||||||
|
public MarketingContext(DbContextOptions<MarketingContext> options) : base(options)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public DbSet<Campaign> Campaigns { get; set; }
|
||||||
|
|
||||||
|
public DbSet<Rule> Rules { get; set; }
|
||||||
|
|
||||||
|
protected override void OnModelCreating(ModelBuilder builder)
|
||||||
|
{
|
||||||
|
builder.Entity<Campaign>(ConfigureCampaigns);
|
||||||
|
builder.Entity<Rule>(ConfigureRules);
|
||||||
|
builder.Entity<UserLocationRule>(ConfigureUserLocationRules);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ConfigureCampaigns(EntityTypeBuilder<Campaign> builder)
|
||||||
|
{
|
||||||
|
builder.ToTable("Campaign");
|
||||||
|
|
||||||
|
builder.HasKey(m => m.Id);
|
||||||
|
|
||||||
|
builder.Property(m => m.Id)
|
||||||
|
.ForSqlServerUseSequenceHiLo("campaign_hilo")
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
builder.Property(m => m.Description)
|
||||||
|
.HasColumnName("Description")
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
builder.Property(m => m.From)
|
||||||
|
.HasColumnName("From")
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
builder.Property(m => m.To)
|
||||||
|
.HasColumnName("To")
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
builder.Property(m => m.Description)
|
||||||
|
.HasColumnName("Description")
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
builder.HasMany(m => m.Rules)
|
||||||
|
.WithOne(r => r.Campaign)
|
||||||
|
.HasForeignKey(r => r.CampaignId)
|
||||||
|
.IsRequired();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ConfigureRules(EntityTypeBuilder<Rule> builder)
|
||||||
|
{
|
||||||
|
builder.ToTable("Rule");
|
||||||
|
|
||||||
|
builder.HasKey(r => r.Id);
|
||||||
|
|
||||||
|
builder.Property(r => r.Id)
|
||||||
|
.ForSqlServerUseSequenceHiLo("rule_hilo")
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
builder.HasDiscriminator<int>("RuleTypeId")
|
||||||
|
.HasValue<UserProfileRule>((int)RuleTypeEnum.UserProfileRule)
|
||||||
|
.HasValue<PurchaseHistoryRule>((int)RuleTypeEnum.PurchaseHistoryRule)
|
||||||
|
.HasValue<UserLocationRule>((int)RuleTypeEnum.UserLocationRule);
|
||||||
|
|
||||||
|
builder.Property(r => r.Description)
|
||||||
|
.HasColumnName("Description")
|
||||||
|
.IsRequired();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ConfigureUserLocationRules(EntityTypeBuilder<UserLocationRule> builder)
|
||||||
|
{
|
||||||
|
builder.Property(r => r.LocationId)
|
||||||
|
.HasColumnName("LocationId")
|
||||||
|
.IsRequired();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,67 @@
|
|||||||
|
namespace Microsoft.eShopOnContainers.Services.Marketing.API.Infrastructure
|
||||||
|
{
|
||||||
|
using Microsoft.AspNetCore.Builder;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.eShopOnContainers.Services.Marketing.API.Model;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
public class MarketingContextSeed
|
||||||
|
{
|
||||||
|
public static async Task SeedAsync(IApplicationBuilder applicationBuilder, ILoggerFactory loggerFactory, int? retry = 0)
|
||||||
|
{
|
||||||
|
var context = (MarketingContext)applicationBuilder
|
||||||
|
.ApplicationServices.GetService(typeof(MarketingContext));
|
||||||
|
|
||||||
|
context.Database.Migrate();
|
||||||
|
|
||||||
|
if (!context.Campaigns.Any())
|
||||||
|
{
|
||||||
|
context.Campaigns.AddRange(
|
||||||
|
GetPreconfiguredMarketings());
|
||||||
|
|
||||||
|
await context.SaveChangesAsync();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static List<Campaign> GetPreconfiguredMarketings()
|
||||||
|
{
|
||||||
|
return new List<Campaign>
|
||||||
|
{
|
||||||
|
new Campaign
|
||||||
|
{
|
||||||
|
Description = "Campaign1",
|
||||||
|
From = DateTime.Now,
|
||||||
|
To = DateTime.Now.AddDays(7),
|
||||||
|
Url = "http://CampaignUrl.test/12f09ed3cef54187123f500ad",
|
||||||
|
Rules = new List<Rule>
|
||||||
|
{
|
||||||
|
new UserLocationRule
|
||||||
|
{
|
||||||
|
Description = "UserLocationRule1",
|
||||||
|
LocationId = 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
new Campaign
|
||||||
|
{
|
||||||
|
Description = "Campaign2",
|
||||||
|
From = DateTime.Now.AddDays(7),
|
||||||
|
To = DateTime.Now.AddDays(14),
|
||||||
|
Url = "http://CampaignUrl.test/02a59eda65f241871239000ff",
|
||||||
|
Rules = new List<Rule>
|
||||||
|
{
|
||||||
|
new UserLocationRule
|
||||||
|
{
|
||||||
|
Description = "UserLocationRule2",
|
||||||
|
LocationId = 3
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,111 @@
|
|||||||
|
using System;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||||
|
using Microsoft.EntityFrameworkCore.Metadata;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
using Microsoft.eShopOnContainers.Services.Marketing.API.Infrastructure;
|
||||||
|
|
||||||
|
namespace Microsoft.eShopOnContainers.Services.Marketing.API.Infrastructure.MarketingMigrations
|
||||||
|
{
|
||||||
|
[DbContext(typeof(MarketingContext))]
|
||||||
|
[Migration("20170609104915_Initial")]
|
||||||
|
partial class Initial
|
||||||
|
{
|
||||||
|
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||||
|
{
|
||||||
|
modelBuilder
|
||||||
|
.HasAnnotation("ProductVersion", "1.1.2")
|
||||||
|
.HasAnnotation("SqlServer:Sequence:.campaign_hilo", "'campaign_hilo', '', '1', '10', '', '', 'Int64', 'False'")
|
||||||
|
.HasAnnotation("SqlServer:Sequence:.rule_hilo", "'rule_hilo', '', '1', '10', '', '', 'Int64', 'False'")
|
||||||
|
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.eShopOnContainers.Services.Marketing.API.Model.Campaign", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasAnnotation("SqlServer:HiLoSequenceName", "campaign_hilo")
|
||||||
|
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.SequenceHiLo);
|
||||||
|
|
||||||
|
b.Property<string>("Description")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnName("Description");
|
||||||
|
|
||||||
|
b.Property<DateTime>("From")
|
||||||
|
.HasColumnName("From");
|
||||||
|
|
||||||
|
b.Property<DateTime>("To")
|
||||||
|
.HasColumnName("To");
|
||||||
|
|
||||||
|
b.Property<string>("Url");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("Campaign");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.eShopOnContainers.Services.Marketing.API.Model.Rule", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasAnnotation("SqlServer:HiLoSequenceName", "rule_hilo")
|
||||||
|
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.SequenceHiLo);
|
||||||
|
|
||||||
|
b.Property<int>("CampaignId");
|
||||||
|
|
||||||
|
b.Property<string>("Description")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnName("Description");
|
||||||
|
|
||||||
|
b.Property<int>("RuleTypeId");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("CampaignId");
|
||||||
|
|
||||||
|
b.ToTable("Rule");
|
||||||
|
|
||||||
|
b.HasDiscriminator<int>("RuleTypeId");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.eShopOnContainers.Services.Marketing.API.Model.PurchaseHistoryRule", b =>
|
||||||
|
{
|
||||||
|
b.HasBaseType("Microsoft.eShopOnContainers.Services.Marketing.API.Model.Rule");
|
||||||
|
|
||||||
|
|
||||||
|
b.ToTable("PurchaseHistoryRule");
|
||||||
|
|
||||||
|
b.HasDiscriminator().HasValue(2);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.eShopOnContainers.Services.Marketing.API.Model.UserLocationRule", b =>
|
||||||
|
{
|
||||||
|
b.HasBaseType("Microsoft.eShopOnContainers.Services.Marketing.API.Model.Rule");
|
||||||
|
|
||||||
|
b.Property<int>("LocationId")
|
||||||
|
.HasColumnName("LocationId");
|
||||||
|
|
||||||
|
b.ToTable("UserLocationRule");
|
||||||
|
|
||||||
|
b.HasDiscriminator().HasValue(3);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.eShopOnContainers.Services.Marketing.API.Model.UserProfileRule", b =>
|
||||||
|
{
|
||||||
|
b.HasBaseType("Microsoft.eShopOnContainers.Services.Marketing.API.Model.Rule");
|
||||||
|
|
||||||
|
|
||||||
|
b.ToTable("UserProfileRule");
|
||||||
|
|
||||||
|
b.HasDiscriminator().HasValue(1);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.eShopOnContainers.Services.Marketing.API.Model.Rule", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Microsoft.eShopOnContainers.Services.Marketing.API.Model.Campaign", "Campaign")
|
||||||
|
.WithMany("Rules")
|
||||||
|
.HasForeignKey("CampaignId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,76 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
|
||||||
|
namespace Microsoft.eShopOnContainers.Services.Marketing.API.Infrastructure.MarketingMigrations
|
||||||
|
{
|
||||||
|
public partial class Initial : Migration
|
||||||
|
{
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.CreateSequence(
|
||||||
|
name: "campaign_hilo",
|
||||||
|
incrementBy: 10);
|
||||||
|
|
||||||
|
migrationBuilder.CreateSequence(
|
||||||
|
name: "rule_hilo",
|
||||||
|
incrementBy: 10);
|
||||||
|
|
||||||
|
migrationBuilder.CreateTable(
|
||||||
|
name: "Campaign",
|
||||||
|
columns: table => new
|
||||||
|
{
|
||||||
|
Id = table.Column<int>(nullable: false),
|
||||||
|
Description = table.Column<string>(nullable: false),
|
||||||
|
From = table.Column<DateTime>(nullable: false),
|
||||||
|
To = table.Column<DateTime>(nullable: false),
|
||||||
|
Url = table.Column<string>(nullable: true)
|
||||||
|
},
|
||||||
|
constraints: table =>
|
||||||
|
{
|
||||||
|
table.PrimaryKey("PK_Campaign", x => x.Id);
|
||||||
|
});
|
||||||
|
|
||||||
|
migrationBuilder.CreateTable(
|
||||||
|
name: "Rule",
|
||||||
|
columns: table => new
|
||||||
|
{
|
||||||
|
Id = table.Column<int>(nullable: false),
|
||||||
|
CampaignId = table.Column<int>(nullable: false),
|
||||||
|
Description = table.Column<string>(nullable: false),
|
||||||
|
RuleTypeId = table.Column<int>(nullable: false),
|
||||||
|
LocationId = table.Column<int>(nullable: true)
|
||||||
|
},
|
||||||
|
constraints: table =>
|
||||||
|
{
|
||||||
|
table.PrimaryKey("PK_Rule", x => x.Id);
|
||||||
|
table.ForeignKey(
|
||||||
|
name: "FK_Rule_Campaign_CampaignId",
|
||||||
|
column: x => x.CampaignId,
|
||||||
|
principalTable: "Campaign",
|
||||||
|
principalColumn: "Id",
|
||||||
|
onDelete: ReferentialAction.Cascade);
|
||||||
|
});
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_Rule_CampaignId",
|
||||||
|
table: "Rule",
|
||||||
|
column: "CampaignId");
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DropTable(
|
||||||
|
name: "Rule");
|
||||||
|
|
||||||
|
migrationBuilder.DropTable(
|
||||||
|
name: "Campaign");
|
||||||
|
|
||||||
|
migrationBuilder.DropSequence(
|
||||||
|
name: "campaign_hilo");
|
||||||
|
|
||||||
|
migrationBuilder.DropSequence(
|
||||||
|
name: "rule_hilo");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,110 @@
|
|||||||
|
using System;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||||
|
using Microsoft.EntityFrameworkCore.Metadata;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
using Microsoft.eShopOnContainers.Services.Marketing.API.Infrastructure;
|
||||||
|
|
||||||
|
namespace Microsoft.eShopOnContainers.Services.Marketing.API.Infrastructure.MarketingMigrations
|
||||||
|
{
|
||||||
|
[DbContext(typeof(MarketingContext))]
|
||||||
|
partial class MarketingContextModelSnapshot : ModelSnapshot
|
||||||
|
{
|
||||||
|
protected override void BuildModel(ModelBuilder modelBuilder)
|
||||||
|
{
|
||||||
|
modelBuilder
|
||||||
|
.HasAnnotation("ProductVersion", "1.1.2")
|
||||||
|
.HasAnnotation("SqlServer:Sequence:.campaign_hilo", "'campaign_hilo', '', '1', '10', '', '', 'Int64', 'False'")
|
||||||
|
.HasAnnotation("SqlServer:Sequence:.rule_hilo", "'rule_hilo', '', '1', '10', '', '', 'Int64', 'False'")
|
||||||
|
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.eShopOnContainers.Services.Marketing.API.Model.Campaign", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasAnnotation("SqlServer:HiLoSequenceName", "campaign_hilo")
|
||||||
|
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.SequenceHiLo);
|
||||||
|
|
||||||
|
b.Property<string>("Description")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnName("Description");
|
||||||
|
|
||||||
|
b.Property<DateTime>("From")
|
||||||
|
.HasColumnName("From");
|
||||||
|
|
||||||
|
b.Property<DateTime>("To")
|
||||||
|
.HasColumnName("To");
|
||||||
|
|
||||||
|
b.Property<string>("Url");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("Campaign");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.eShopOnContainers.Services.Marketing.API.Model.Rule", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasAnnotation("SqlServer:HiLoSequenceName", "rule_hilo")
|
||||||
|
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.SequenceHiLo);
|
||||||
|
|
||||||
|
b.Property<int>("CampaignId");
|
||||||
|
|
||||||
|
b.Property<string>("Description")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnName("Description");
|
||||||
|
|
||||||
|
b.Property<int>("RuleTypeId");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("CampaignId");
|
||||||
|
|
||||||
|
b.ToTable("Rule");
|
||||||
|
|
||||||
|
b.HasDiscriminator<int>("RuleTypeId");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.eShopOnContainers.Services.Marketing.API.Model.PurchaseHistoryRule", b =>
|
||||||
|
{
|
||||||
|
b.HasBaseType("Microsoft.eShopOnContainers.Services.Marketing.API.Model.Rule");
|
||||||
|
|
||||||
|
|
||||||
|
b.ToTable("PurchaseHistoryRule");
|
||||||
|
|
||||||
|
b.HasDiscriminator().HasValue(2);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.eShopOnContainers.Services.Marketing.API.Model.UserLocationRule", b =>
|
||||||
|
{
|
||||||
|
b.HasBaseType("Microsoft.eShopOnContainers.Services.Marketing.API.Model.Rule");
|
||||||
|
|
||||||
|
b.Property<int>("LocationId")
|
||||||
|
.HasColumnName("LocationId");
|
||||||
|
|
||||||
|
b.ToTable("UserLocationRule");
|
||||||
|
|
||||||
|
b.HasDiscriminator().HasValue(3);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.eShopOnContainers.Services.Marketing.API.Model.UserProfileRule", b =>
|
||||||
|
{
|
||||||
|
b.HasBaseType("Microsoft.eShopOnContainers.Services.Marketing.API.Model.Rule");
|
||||||
|
|
||||||
|
|
||||||
|
b.ToTable("UserProfileRule");
|
||||||
|
|
||||||
|
b.HasDiscriminator().HasValue(1);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.eShopOnContainers.Services.Marketing.API.Model.Rule", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Microsoft.eShopOnContainers.Services.Marketing.API.Model.Campaign", "Campaign")
|
||||||
|
.WithMany("Rules")
|
||||||
|
.HasForeignKey("CampaignId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
50
src/Services/Marketing/Marketing.API/Marketing.API.csproj
Normal file
50
src/Services/Marketing/Marketing.API/Marketing.API.csproj
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>netcoreapp1.1</TargetFramework>
|
||||||
|
<RuntimeFrameworkVersion>1.1.2</RuntimeFrameworkVersion>
|
||||||
|
<OutputType>Exe</OutputType>
|
||||||
|
<DockerComposeProjectPath>..\..\..\..\docker-compose.dcproj</DockerComposeProjectPath>
|
||||||
|
<RootNamespace>Microsoft.eShopOnContainers.Services.Marketing.API</RootNamespace>
|
||||||
|
<PackageTargetFallback>portable-net45+win8</PackageTargetFallback>
|
||||||
|
<UserSecretsId>aspnet-Marketing.API-20161122013619</UserSecretsId>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Folder Include="Infrastructure\MarketingMigrations\" />
|
||||||
|
<Folder Include="IntegrationEvents\EventHandling\" />
|
||||||
|
<Folder Include="IntegrationEvents\Events\" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="IdentityServer4.AccessTokenValidation" Version="1.2.0" />
|
||||||
|
<PackageReference Include="Microsoft.AspNetCore" Version="1.1.2" />
|
||||||
|
<PackageReference Include="Microsoft.AspNetCore.Mvc" Version="1.1.3" />
|
||||||
|
<PackageReference Include="Microsoft.AspNetCore.StaticFiles" Version="1.1.2" />
|
||||||
|
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="1.1.2" />
|
||||||
|
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="1.1.2" />
|
||||||
|
<PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="1.1.2" />
|
||||||
|
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="1.1.2" />
|
||||||
|
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer.Design" Version="1.1.2" />
|
||||||
|
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="1.1.1" />
|
||||||
|
<PackageReference Include="Microsoft.Extensions.Configuration" Version="1.1.2" />
|
||||||
|
<PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="1.1.2" />
|
||||||
|
<PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="1.1.2" />
|
||||||
|
<PackageReference Include="Microsoft.Extensions.Configuration.FileExtensions" Version="1.1.2" />
|
||||||
|
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="1.1.2" />
|
||||||
|
<PackageReference Include="Microsoft.Extensions.Configuration.UserSecrets" Version="1.1.2" />
|
||||||
|
<PackageReference Include="Microsoft.Extensions.Logging" Version="1.1.2" />
|
||||||
|
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="1.1.2" />
|
||||||
|
<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="1.1.2" />
|
||||||
|
<PackageReference Include="Microsoft.Extensions.Options" Version="1.1.2" />
|
||||||
|
<PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="1.1.2" />
|
||||||
|
<PackageReference Include="Microsoft.VisualStudio.Web.BrowserLink" Version="1.1.2" />
|
||||||
|
<PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="1.1.1" />
|
||||||
|
<PackageReference Include="Swashbuckle.AspNetCore" Version="1.0.0" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<DotNetCliToolReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Tools" Version="1.0.1" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<DotNetCliToolReference Include="Microsoft.EntityFrameworkCore.Tools.DotNet" Version="1.0.0" />
|
||||||
|
</ItemGroup>
|
||||||
|
</Project>
|
@ -0,0 +1,7 @@
|
|||||||
|
namespace Microsoft.eShopOnContainers.Services.Marketing.API
|
||||||
|
{
|
||||||
|
public class MarketingSettings
|
||||||
|
{
|
||||||
|
public string ConnectionString { get; set; }
|
||||||
|
}
|
||||||
|
}
|
26
src/Services/Marketing/Marketing.API/Model/Campaign.cs
Normal file
26
src/Services/Marketing/Marketing.API/Model/Campaign.cs
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
namespace Microsoft.eShopOnContainers.Services.Marketing.API.Model
|
||||||
|
{
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
public class Campaign
|
||||||
|
{
|
||||||
|
public int Id { get; set; }
|
||||||
|
|
||||||
|
public string Description { get; set; }
|
||||||
|
|
||||||
|
public DateTime From { get; set; }
|
||||||
|
|
||||||
|
public DateTime To { get; set; }
|
||||||
|
|
||||||
|
public string Url { get; set; }
|
||||||
|
|
||||||
|
public List<Rule> Rules { get; set; }
|
||||||
|
|
||||||
|
|
||||||
|
public Campaign()
|
||||||
|
{
|
||||||
|
Rules = new List<Rule>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
27
src/Services/Marketing/Marketing.API/Model/Rule.cs
Normal file
27
src/Services/Marketing/Marketing.API/Model/Rule.cs
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
namespace Microsoft.eShopOnContainers.Services.Marketing.API.Model
|
||||||
|
{
|
||||||
|
public abstract class Rule
|
||||||
|
{
|
||||||
|
public int Id { get; set; }
|
||||||
|
|
||||||
|
public int CampaignId { get; set; }
|
||||||
|
|
||||||
|
public Campaign Campaign { get; set; }
|
||||||
|
|
||||||
|
public string Description { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public class UserProfileRule : Rule
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public class PurchaseHistoryRule : Rule
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public class UserLocationRule : Rule
|
||||||
|
{
|
||||||
|
public int LocationId { get; set; }
|
||||||
|
}
|
||||||
|
}
|
20
src/Services/Marketing/Marketing.API/Model/RuleTypeEnum.cs
Normal file
20
src/Services/Marketing/Marketing.API/Model/RuleTypeEnum.cs
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
namespace Microsoft.eShopOnContainers.Services.Marketing.API.Model
|
||||||
|
{
|
||||||
|
using Microsoft.eShopOnContainers.Services.Marketing.API.Infrastructure.Exceptions;
|
||||||
|
using System;
|
||||||
|
|
||||||
|
public enum RuleTypeEnum { UserProfileRule = 1, PurchaseHistoryRule = 2, UserLocationRule = 3 }
|
||||||
|
|
||||||
|
public static class RuleType
|
||||||
|
{
|
||||||
|
public static RuleTypeEnum From(int id)
|
||||||
|
{
|
||||||
|
if (!Enum.IsDefined(typeof(RuleTypeEnum), id))
|
||||||
|
{
|
||||||
|
throw new MarketingDomainException($"Invalid value for RuleType, RuleTypeId: {id}");
|
||||||
|
}
|
||||||
|
|
||||||
|
return (RuleTypeEnum)id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
20
src/Services/Marketing/Marketing.API/Program.cs
Normal file
20
src/Services/Marketing/Marketing.API/Program.cs
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
namespace Microsoft.eShopOnContainers.Services.Marketing.API
|
||||||
|
{
|
||||||
|
using System.IO;
|
||||||
|
using Microsoft.AspNetCore.Builder;
|
||||||
|
using Microsoft.AspNetCore.Hosting;
|
||||||
|
|
||||||
|
public class Program
|
||||||
|
{
|
||||||
|
public static void Main(string[] args)
|
||||||
|
{
|
||||||
|
var host = new WebHostBuilder()
|
||||||
|
.UseKestrel()
|
||||||
|
.UseContentRoot(Directory.GetCurrentDirectory())
|
||||||
|
.UseStartup<Startup>()
|
||||||
|
.Build();
|
||||||
|
|
||||||
|
host.Run();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,29 @@
|
|||||||
|
{
|
||||||
|
"iisSettings": {
|
||||||
|
"windowsAuthentication": false,
|
||||||
|
"anonymousAuthentication": true,
|
||||||
|
"iisExpress": {
|
||||||
|
"applicationUrl": "http://localhost:5110",
|
||||||
|
"sslPort": 0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"profiles": {
|
||||||
|
"IIS Express": {
|
||||||
|
"commandName": "IISExpress",
|
||||||
|
"launchBrowser": true,
|
||||||
|
"launchUrl": "api/values",
|
||||||
|
"environmentVariables": {
|
||||||
|
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Marketing.API": {
|
||||||
|
"commandName": "Project",
|
||||||
|
"launchBrowser": true,
|
||||||
|
"launchUrl": "api/values",
|
||||||
|
"environmentVariables": {
|
||||||
|
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||||
|
},
|
||||||
|
"applicationUrl": "http://localhost:52059"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
119
src/Services/Marketing/Marketing.API/Startup.cs
Normal file
119
src/Services/Marketing/Marketing.API/Startup.cs
Normal file
@ -0,0 +1,119 @@
|
|||||||
|
namespace Microsoft.eShopOnContainers.Services.Marketing.API
|
||||||
|
{
|
||||||
|
using Microsoft.AspNetCore.Builder;
|
||||||
|
using Microsoft.AspNetCore.Hosting;
|
||||||
|
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.eShopOnContainers.Services.Marketing.API.Infrastructure;
|
||||||
|
using Microsoft.Extensions.Configuration;
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
using System.Reflection;
|
||||||
|
using System;
|
||||||
|
using Microsoft.eShopOnContainers.Services.Marketing.API.Infrastructure.Filters;
|
||||||
|
|
||||||
|
public class Startup
|
||||||
|
{
|
||||||
|
public Startup(IHostingEnvironment env)
|
||||||
|
{
|
||||||
|
var builder = new ConfigurationBuilder()
|
||||||
|
.SetBasePath(env.ContentRootPath)
|
||||||
|
.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
|
||||||
|
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true)
|
||||||
|
.AddEnvironmentVariables();
|
||||||
|
|
||||||
|
if (env.IsDevelopment())
|
||||||
|
{
|
||||||
|
builder.AddUserSecrets(typeof(Startup).GetTypeInfo().Assembly);
|
||||||
|
}
|
||||||
|
|
||||||
|
builder.AddEnvironmentVariables();
|
||||||
|
|
||||||
|
Configuration = builder.Build();
|
||||||
|
}
|
||||||
|
|
||||||
|
public IConfigurationRoot Configuration { get; }
|
||||||
|
|
||||||
|
// This method gets called by the runtime. Use this method to add services to the container.
|
||||||
|
public void ConfigureServices(IServiceCollection services)
|
||||||
|
{
|
||||||
|
// Add framework services.
|
||||||
|
services.AddMvc(options =>
|
||||||
|
{
|
||||||
|
options.Filters.Add(typeof(HttpGlobalExceptionFilter));
|
||||||
|
}).AddControllersAsServices(); //Injecting Controllers themselves thru DIFor further info see: http://docs.autofac.org/en/latest/integration/aspnetcore.html#controllers-as-services
|
||||||
|
|
||||||
|
services.AddDbContext<MarketingContext>(options =>
|
||||||
|
{
|
||||||
|
options.UseSqlServer(Configuration["ConnectionString"],
|
||||||
|
sqlServerOptionsAction: sqlOptions =>
|
||||||
|
{
|
||||||
|
sqlOptions.MigrationsAssembly(typeof(Startup).GetTypeInfo().Assembly.GetName().Name);
|
||||||
|
//Configuring Connection Resiliency: https://docs.microsoft.com/en-us/ef/core/miscellaneous/connection-resiliency
|
||||||
|
sqlOptions.EnableRetryOnFailure(maxRetryCount: 5, maxRetryDelay: TimeSpan.FromSeconds(30), errorNumbersToAdd: null);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Changing default behavior when client evaluation occurs to throw.
|
||||||
|
// Default in EF Core would be to log a warning when client evaluation is performed.
|
||||||
|
options.ConfigureWarnings(warnings => warnings.Throw(RelationalEventId.QueryClientEvaluationWarning));
|
||||||
|
//Check Client vs. Server evaluation: https://docs.microsoft.com/en-us/ef/core/querying/client-eval
|
||||||
|
});
|
||||||
|
|
||||||
|
// Add framework services.
|
||||||
|
services.AddSwaggerGen(options =>
|
||||||
|
{
|
||||||
|
options.DescribeAllEnumsAsStrings();
|
||||||
|
options.SwaggerDoc("v1", new Swashbuckle.AspNetCore.Swagger.Info
|
||||||
|
{
|
||||||
|
Title = "Marketing HTTP API",
|
||||||
|
Version = "v1",
|
||||||
|
Description = "The Marketing Service HTTP API",
|
||||||
|
TermsOfService = "Terms Of Service"
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
services.AddCors(options =>
|
||||||
|
{
|
||||||
|
options.AddPolicy("CorsPolicy",
|
||||||
|
builder => builder.AllowAnyOrigin()
|
||||||
|
.AllowAnyMethod()
|
||||||
|
.AllowAnyHeader()
|
||||||
|
.AllowCredentials());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
|
||||||
|
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
|
||||||
|
{
|
||||||
|
loggerFactory.AddConsole(Configuration.GetSection("Logging"));
|
||||||
|
loggerFactory.AddDebug();
|
||||||
|
|
||||||
|
app.UseCors("CorsPolicy");
|
||||||
|
|
||||||
|
ConfigureAuth(app);
|
||||||
|
|
||||||
|
app.UseMvcWithDefaultRoute();
|
||||||
|
|
||||||
|
app.UseSwagger()
|
||||||
|
.UseSwaggerUI(c =>
|
||||||
|
{
|
||||||
|
c.SwaggerEndpoint("/swagger/v1/swagger.json", "My API V1");
|
||||||
|
});
|
||||||
|
|
||||||
|
MarketingContextSeed.SeedAsync(app, loggerFactory)
|
||||||
|
.Wait();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
protected virtual void ConfigureAuth(IApplicationBuilder app)
|
||||||
|
{
|
||||||
|
var identityUrl = Configuration.GetValue<string>("IdentityUrl");
|
||||||
|
app.UseIdentityServerAuthentication(new IdentityServerAuthenticationOptions
|
||||||
|
{
|
||||||
|
Authority = identityUrl.ToString(),
|
||||||
|
ApiName = "marketing",
|
||||||
|
RequireHttpsMetadata = false
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"Logging": {
|
||||||
|
"IncludeScopes": false,
|
||||||
|
"LogLevel": {
|
||||||
|
"Default": "Warning"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
10
src/Services/Marketing/Marketing.API/appsettings.json
Normal file
10
src/Services/Marketing/Marketing.API/appsettings.json
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
{
|
||||||
|
"Logging": {
|
||||||
|
"IncludeScopes": false,
|
||||||
|
"LogLevel": {
|
||||||
|
"Default": "Warning"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"ConnectionString": "127.0.0.1",
|
||||||
|
"IdentityUrl": "http://localhost:5105"
|
||||||
|
}
|
@ -4,6 +4,8 @@ using Microsoft.AspNetCore.Mvc;
|
|||||||
using Microsoft.eShopOnContainers.WebMVC.ViewModels;
|
using Microsoft.eShopOnContainers.WebMVC.ViewModels;
|
||||||
using Microsoft.eShopOnContainers.WebMVC.Services;
|
using Microsoft.eShopOnContainers.WebMVC.Services;
|
||||||
using Microsoft.AspNetCore.Http.Authentication;
|
using Microsoft.AspNetCore.Http.Authentication;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.AspNetCore.Authentication;
|
||||||
|
|
||||||
namespace Microsoft.eShopOnContainers.WebMVC.Controllers
|
namespace Microsoft.eShopOnContainers.WebMVC.Controllers
|
||||||
{
|
{
|
||||||
@ -17,15 +19,14 @@ namespace Microsoft.eShopOnContainers.WebMVC.Controllers
|
|||||||
public ActionResult Index() => View();
|
public ActionResult Index() => View();
|
||||||
|
|
||||||
[Authorize]
|
[Authorize]
|
||||||
public IActionResult SignIn(string returnUrl)
|
public async Task<IActionResult> SignIn(string returnUrl)
|
||||||
{
|
{
|
||||||
var user = User as ClaimsPrincipal;
|
var user = User as ClaimsPrincipal;
|
||||||
|
var token = await HttpContext.Authentication.GetTokenAsync("access_token");
|
||||||
//TODO - Not retrieving AccessToken yet
|
|
||||||
var token = user.FindFirst("access_token");
|
|
||||||
if (token != null)
|
if (token != null)
|
||||||
{
|
{
|
||||||
ViewData["access_token"] = token.Value;
|
ViewData["access_token"] = token;
|
||||||
}
|
}
|
||||||
|
|
||||||
// "Catalog" because UrlHelper doesn't support nameof() for controllers
|
// "Catalog" because UrlHelper doesn't support nameof() for controllers
|
||||||
|
@ -1,22 +1,17 @@
|
|||||||
using System;
|
using Microsoft.AspNetCore.Builder;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Microsoft.AspNetCore.Builder;
|
|
||||||
using Microsoft.AspNetCore.Hosting;
|
using Microsoft.AspNetCore.Hosting;
|
||||||
using Microsoft.Extensions.Configuration;
|
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
|
||||||
using Microsoft.Extensions.Logging;
|
|
||||||
using Microsoft.eShopOnContainers.WebMVC.ViewModels;
|
|
||||||
using Microsoft.eShopOnContainers.WebMVC.Services;
|
|
||||||
using System.IdentityModel.Tokens.Jwt;
|
|
||||||
using Microsoft.IdentityModel.Tokens;
|
|
||||||
using Microsoft.AspNetCore.Http;
|
using Microsoft.AspNetCore.Http;
|
||||||
using System.Threading;
|
using Microsoft.eShopOnContainers.BuildingBlocks;
|
||||||
using Microsoft.Extensions.Options;
|
|
||||||
using Microsoft.Extensions.HealthChecks;
|
|
||||||
using Microsoft.eShopOnContainers.BuildingBlocks.Resilience.Http;
|
using Microsoft.eShopOnContainers.BuildingBlocks.Resilience.Http;
|
||||||
using Microsoft.eShopOnContainers.WebMVC.Infrastructure;
|
using Microsoft.eShopOnContainers.WebMVC.Infrastructure;
|
||||||
|
using Microsoft.eShopOnContainers.WebMVC.Services;
|
||||||
|
using Microsoft.eShopOnContainers.WebMVC.ViewModels;
|
||||||
|
using Microsoft.Extensions.Configuration;
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using Microsoft.Extensions.HealthChecks;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
using System;
|
||||||
|
using System.IdentityModel.Tokens.Jwt;
|
||||||
|
|
||||||
namespace Microsoft.eShopOnContainers.WebMVC
|
namespace Microsoft.eShopOnContainers.WebMVC
|
||||||
{
|
{
|
||||||
@ -44,12 +39,17 @@ namespace Microsoft.eShopOnContainers.WebMVC
|
|||||||
// This method gets called by the runtime. Use this method to add services to the container.
|
// This method gets called by the runtime. Use this method to add services to the container.
|
||||||
public void ConfigureServices(IServiceCollection services)
|
public void ConfigureServices(IServiceCollection services)
|
||||||
{
|
{
|
||||||
services.AddDataProtection(opts =>
|
|
||||||
{
|
|
||||||
opts.ApplicationDiscriminator = "eshop.webmvc";
|
|
||||||
});
|
|
||||||
|
|
||||||
services.AddMvc();
|
services.AddMvc();
|
||||||
|
|
||||||
|
if (Configuration.GetValue<string>("IsClusterEnv") == bool.TrueString)
|
||||||
|
{
|
||||||
|
services.AddDataProtection(opts =>
|
||||||
|
{
|
||||||
|
opts.ApplicationDiscriminator = "eshop.webmvc";
|
||||||
|
})
|
||||||
|
.PersistKeysToRedis(Configuration["DPConnectionString"]);
|
||||||
|
}
|
||||||
|
|
||||||
services.Configure<AppSettings>(Configuration);
|
services.Configure<AppSettings>(Configuration);
|
||||||
|
|
||||||
services.AddHealthChecks(checks =>
|
services.AddHealthChecks(checks =>
|
||||||
|
@ -54,6 +54,7 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\..\BuildingBlocks\DataProtection\DataProtection\DataProtection.csproj" />
|
||||||
<ProjectReference Include="..\..\BuildingBlocks\HealthChecks\src\Microsoft.AspNetCore.HealthChecks\Microsoft.AspNetCore.HealthChecks.csproj" />
|
<ProjectReference Include="..\..\BuildingBlocks\HealthChecks\src\Microsoft.AspNetCore.HealthChecks\Microsoft.AspNetCore.HealthChecks.csproj" />
|
||||||
<ProjectReference Include="..\..\BuildingBlocks\HealthChecks\src\Microsoft.Extensions.HealthChecks\Microsoft.Extensions.HealthChecks.csproj" />
|
<ProjectReference Include="..\..\BuildingBlocks\HealthChecks\src\Microsoft.Extensions.HealthChecks\Microsoft.Extensions.HealthChecks.csproj" />
|
||||||
<ProjectReference Include="..\..\BuildingBlocks\Resilience\Resilience.Http\Resilience.Http.csproj" />
|
<ProjectReference Include="..\..\BuildingBlocks\Resilience\Resilience.Http\Resilience.Http.csproj" />
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
"BasketUrl": "http://localhost:5103",
|
"BasketUrl": "http://localhost:5103",
|
||||||
"IdentityUrl": "http://localhost:5105",
|
"IdentityUrl": "http://localhost:5105",
|
||||||
"CallBackUrl": "http://localhost:5100/",
|
"CallBackUrl": "http://localhost:5100/",
|
||||||
|
"IsClusterEnv": "False",
|
||||||
"UseResilientHttp": "True",
|
"UseResilientHttp": "True",
|
||||||
"Logging": {
|
"Logging": {
|
||||||
"IncludeScopes": false,
|
"IncludeScopes": false,
|
||||||
|
2
src/Web/WebMVC/wwwroot/css/site.min.css
vendored
2
src/Web/WebMVC/wwwroot/css/site.min.css
vendored
File diff suppressed because one or more lines are too long
@ -10,6 +10,7 @@ using Microsoft.Extensions.Logging;
|
|||||||
using Microsoft.Extensions.HealthChecks;
|
using Microsoft.Extensions.HealthChecks;
|
||||||
using Newtonsoft.Json.Serialization;
|
using Newtonsoft.Json.Serialization;
|
||||||
using eShopOnContainers.WebSPA;
|
using eShopOnContainers.WebSPA;
|
||||||
|
using Microsoft.eShopOnContainers.BuildingBlocks;
|
||||||
|
|
||||||
namespace eShopConContainers.WebSPA
|
namespace eShopConContainers.WebSPA
|
||||||
{
|
{
|
||||||
@ -59,10 +60,14 @@ namespace eShopConContainers.WebSPA
|
|||||||
|
|
||||||
services.Configure<AppSettings>(Configuration);
|
services.Configure<AppSettings>(Configuration);
|
||||||
|
|
||||||
services.AddDataProtection(opts =>
|
if (Configuration.GetValue<string>("IsClusterEnv") == bool.TrueString)
|
||||||
{
|
{
|
||||||
opts.ApplicationDiscriminator = "eshop.webspa";
|
services.AddDataProtection(opts =>
|
||||||
});
|
{
|
||||||
|
opts.ApplicationDiscriminator = "eshop.webspa";
|
||||||
|
})
|
||||||
|
.PersistKeysToRedis(Configuration["DPConnectionString"]);
|
||||||
|
}
|
||||||
|
|
||||||
services.AddAntiforgery(options => options.HeaderName = "X-XSRF-TOKEN");
|
services.AddAntiforgery(options => options.HeaderName = "X-XSRF-TOKEN");
|
||||||
|
|
||||||
|
@ -79,6 +79,7 @@
|
|||||||
-->
|
-->
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\..\BuildingBlocks\DataProtection\DataProtection\DataProtection.csproj" />
|
||||||
<ProjectReference Include="..\..\BuildingBlocks\HealthChecks\src\Microsoft.AspNetCore.HealthChecks\Microsoft.AspNetCore.HealthChecks.csproj" />
|
<ProjectReference Include="..\..\BuildingBlocks\HealthChecks\src\Microsoft.AspNetCore.HealthChecks\Microsoft.AspNetCore.HealthChecks.csproj" />
|
||||||
<ProjectReference Include="..\..\BuildingBlocks\HealthChecks\src\Microsoft.Extensions.HealthChecks\Microsoft.Extensions.HealthChecks.csproj" />
|
<ProjectReference Include="..\..\BuildingBlocks\HealthChecks\src\Microsoft.Extensions.HealthChecks\Microsoft.Extensions.HealthChecks.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
"BasketUrl": "http://localhost:5103",
|
"BasketUrl": "http://localhost:5103",
|
||||||
"IdentityUrl": "http://localhost:5105",
|
"IdentityUrl": "http://localhost:5105",
|
||||||
"CallBackUrl": "http://localhost:5104/",
|
"CallBackUrl": "http://localhost:5104/",
|
||||||
|
"IsClusterEnv": "False",
|
||||||
"Logging": {
|
"Logging": {
|
||||||
"IncludeScopes": false,
|
"IncludeScopes": false,
|
||||||
"LogLevel": {
|
"LogLevel": {
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Remove="Services\Catalog\settings.json" />
|
<None Remove="Services\Catalog\settings.json" />
|
||||||
|
<None Remove="Services\Locations\appsettings.json" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
@ -20,6 +21,12 @@
|
|||||||
<Content Include="Services\Catalog\settings.json">
|
<Content Include="Services\Catalog\settings.json">
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
</Content>
|
</Content>
|
||||||
|
<Content Include="Services\Marketing\appsettings.json">
|
||||||
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
|
</Content>
|
||||||
|
<Content Include="Services\Locations\appsettings.json">
|
||||||
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
|
</Content>
|
||||||
<Content Include="Services\Ordering\settings.json">
|
<Content Include="Services\Ordering\settings.json">
|
||||||
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
|
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
|
||||||
</Content>
|
</Content>
|
||||||
@ -28,6 +35,8 @@
|
|||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\..\..\src\Services\Basket\Basket.API\Basket.API.csproj" />
|
<ProjectReference Include="..\..\..\src\Services\Basket\Basket.API\Basket.API.csproj" />
|
||||||
<ProjectReference Include="..\..\..\src\Services\Catalog\Catalog.API\Catalog.API.csproj" />
|
<ProjectReference Include="..\..\..\src\Services\Catalog\Catalog.API\Catalog.API.csproj" />
|
||||||
|
<ProjectReference Include="..\..\..\src\Services\Location\Locations.API\Locations.API.csproj" />
|
||||||
|
<ProjectReference Include="..\..\..\src\Services\Marketing\Marketing.API\Marketing.API.csproj" />
|
||||||
<ProjectReference Include="..\..\..\src\Services\Ordering\Ordering.API\Ordering.API.csproj" />
|
<ProjectReference Include="..\..\..\src\Services\Ordering\Ordering.API\Ordering.API.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
@ -0,0 +1,41 @@
|
|||||||
|
using Microsoft.AspNetCore.Hosting;
|
||||||
|
using Microsoft.AspNetCore.TestHost;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace IntegrationTests.Services.Locations
|
||||||
|
{
|
||||||
|
public class LocationsScenarioBase
|
||||||
|
{
|
||||||
|
public TestServer CreateServer()
|
||||||
|
{
|
||||||
|
var webHostBuilder = new WebHostBuilder();
|
||||||
|
webHostBuilder.UseContentRoot(Directory.GetCurrentDirectory() + "\\Services\\Locations");
|
||||||
|
webHostBuilder.UseStartup<LocationsTestsStartup>();
|
||||||
|
|
||||||
|
return new TestServer(webHostBuilder);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Get
|
||||||
|
{
|
||||||
|
public static string Locations = "api/v1/locations";
|
||||||
|
|
||||||
|
public static string LocationBy(string id)
|
||||||
|
{
|
||||||
|
return $"api/v1/locations/{id}";
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string UserLocationBy(int id)
|
||||||
|
{
|
||||||
|
return $"api/v1/locations/user/{id}";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Post
|
||||||
|
{
|
||||||
|
public static string AddNewLocation = "api/v1/locations/";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,138 @@
|
|||||||
|
using Microsoft.eShopOnContainers.Services.Locations.API.Model;
|
||||||
|
using Microsoft.eShopOnContainers.Services.Locations.API.ViewModel;
|
||||||
|
using Location = Microsoft.eShopOnContainers.Services.Locations.API.Model.Locations;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using System.Net.Http;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Xunit;
|
||||||
|
|
||||||
|
namespace IntegrationTests.Services.Locations
|
||||||
|
{
|
||||||
|
public class LocationsScenarios
|
||||||
|
: LocationsScenarioBase
|
||||||
|
{
|
||||||
|
[Fact]
|
||||||
|
public async Task Set_new_user_seattle_location_response_ok_status_code()
|
||||||
|
{
|
||||||
|
using (var server = CreateServer())
|
||||||
|
{
|
||||||
|
var userId = 1234;
|
||||||
|
var content = new StringContent(BuildLocationsRequest(-122.315752, 47.604610), UTF8Encoding.UTF8, "application/json");
|
||||||
|
|
||||||
|
// Expected result
|
||||||
|
var expectedLocation = "SEAT";
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var response = await server.CreateClient()
|
||||||
|
.PostAsync(Post.AddNewLocation, content);
|
||||||
|
|
||||||
|
var userLocationResponse = await server.CreateClient()
|
||||||
|
.GetAsync(Get.UserLocationBy(userId));
|
||||||
|
|
||||||
|
var responseBody = await userLocationResponse.Content.ReadAsStringAsync();
|
||||||
|
var userLocation = JsonConvert.DeserializeObject<UserLocation>(responseBody);
|
||||||
|
|
||||||
|
var locationResponse = await server.CreateClient()
|
||||||
|
.GetAsync(Get.LocationBy(userLocation.LocationId));
|
||||||
|
|
||||||
|
responseBody = await locationResponse.Content.ReadAsStringAsync();
|
||||||
|
var location = JsonConvert.DeserializeObject<Location>(responseBody);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.Equal(expectedLocation, location.Code);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task Set_new_user_readmond_location_response_ok_status_code()
|
||||||
|
{
|
||||||
|
using (var server = CreateServer())
|
||||||
|
{
|
||||||
|
var userId = 1234;
|
||||||
|
var content = new StringContent(BuildLocationsRequest(-122.119998, 47.690876), UTF8Encoding.UTF8, "application/json");
|
||||||
|
|
||||||
|
// Expected result
|
||||||
|
var expectedLocation = "REDM";
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var response = await server.CreateClient()
|
||||||
|
.PostAsync(Post.AddNewLocation, content);
|
||||||
|
|
||||||
|
var userLocationResponse = await server.CreateClient()
|
||||||
|
.GetAsync(Get.UserLocationBy(userId));
|
||||||
|
|
||||||
|
var responseBody = await userLocationResponse.Content.ReadAsStringAsync();
|
||||||
|
var userLocation = JsonConvert.DeserializeObject<UserLocation>(responseBody);
|
||||||
|
|
||||||
|
var locationResponse = await server.CreateClient()
|
||||||
|
.GetAsync(Get.LocationBy(userLocation.LocationId));
|
||||||
|
|
||||||
|
responseBody = await locationResponse.Content.ReadAsStringAsync();
|
||||||
|
var location = JsonConvert.DeserializeObject<Location>(responseBody);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.Equal(expectedLocation, location.Code);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task Set_new_user_Washington_location_response_ok_status_code()
|
||||||
|
{
|
||||||
|
using (var server = CreateServer())
|
||||||
|
{
|
||||||
|
var userId = 1234;
|
||||||
|
var content = new StringContent(BuildLocationsRequest(-121.040360, 48.091631), UTF8Encoding.UTF8, "application/json");
|
||||||
|
|
||||||
|
// Expected result
|
||||||
|
var expectedLocation = "WHT";
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var response = await server.CreateClient()
|
||||||
|
.PostAsync(Post.AddNewLocation, content);
|
||||||
|
|
||||||
|
var userLocationResponse = await server.CreateClient()
|
||||||
|
.GetAsync(Get.UserLocationBy(userId));
|
||||||
|
|
||||||
|
var responseBody = await userLocationResponse.Content.ReadAsStringAsync();
|
||||||
|
var userLocation = JsonConvert.DeserializeObject<UserLocation>(responseBody);
|
||||||
|
|
||||||
|
var locationResponse = await server.CreateClient()
|
||||||
|
.GetAsync(Get.LocationBy(userLocation.LocationId));
|
||||||
|
|
||||||
|
responseBody = await locationResponse.Content.ReadAsStringAsync();
|
||||||
|
var location = JsonConvert.DeserializeObject<Location>(responseBody);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.Equal(expectedLocation, location.Code);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task Get_all_locations_response_ok_status_code()
|
||||||
|
{
|
||||||
|
using (var server = CreateServer())
|
||||||
|
{
|
||||||
|
var response = await server.CreateClient()
|
||||||
|
.GetAsync(Get.Locations);
|
||||||
|
|
||||||
|
var responseBody = await response.Content.ReadAsStringAsync();
|
||||||
|
var locations = JsonConvert.DeserializeObject<List<Location>>(responseBody);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.NotEmpty(locations);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
string BuildLocationsRequest(double lon, double lat)
|
||||||
|
{
|
||||||
|
var location = new LocationRequest()
|
||||||
|
{
|
||||||
|
Longitude = lon,
|
||||||
|
Latitude = lat
|
||||||
|
};
|
||||||
|
return JsonConvert.SerializeObject(location);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,26 @@
|
|||||||
|
namespace IntegrationTests.Services.Locations
|
||||||
|
{
|
||||||
|
using IntegrationTests.Middleware;
|
||||||
|
using Microsoft.AspNetCore.Builder;
|
||||||
|
using Microsoft.AspNetCore.Hosting;
|
||||||
|
using Microsoft.eShopOnContainers.Services.Locations.API;
|
||||||
|
|
||||||
|
public class LocationsTestsStartup : Startup
|
||||||
|
{
|
||||||
|
public LocationsTestsStartup(IHostingEnvironment env) : base(env)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void ConfigureAuth(IApplicationBuilder app)
|
||||||
|
{
|
||||||
|
if (Configuration["isTest"] == bool.TrueString.ToLowerInvariant())
|
||||||
|
{
|
||||||
|
app.UseMiddleware<AutoAuthorizeMiddleware>();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
base.ConfigureAuth(app);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"ConnectionString": "mongodb://localhost:27017",
|
||||||
|
"Database": "LocationsDb",
|
||||||
|
"ExternalCatalogBaseUrl": "http://localhost:5101",
|
||||||
|
"IdentityUrl": "http://localhost:5105",
|
||||||
|
"isTest": "true",
|
||||||
|
"EventBusConnection": "localhost"
|
||||||
|
}
|
@ -0,0 +1,30 @@
|
|||||||
|
namespace IntegrationTests.Services.Marketing
|
||||||
|
{
|
||||||
|
public class CampaignScenarioBase : MarketingScenarioBase
|
||||||
|
{
|
||||||
|
public static class Get
|
||||||
|
{
|
||||||
|
public static string Campaigns = CampaignsUrlBase;
|
||||||
|
|
||||||
|
public static string CampaignBy(int id)
|
||||||
|
=> $"{CampaignsUrlBase}/{id}";
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Post
|
||||||
|
{
|
||||||
|
public static string AddNewCampaign = CampaignsUrlBase;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Put
|
||||||
|
{
|
||||||
|
public static string CampaignBy(int id)
|
||||||
|
=> $"{CampaignsUrlBase}/{id}";
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Delete
|
||||||
|
{
|
||||||
|
public static string CampaignBy(int id)
|
||||||
|
=> $"{CampaignsUrlBase}/{id}";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,127 @@
|
|||||||
|
namespace IntegrationTests.Services.Marketing
|
||||||
|
{
|
||||||
|
using System.Net.Http;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Xunit;
|
||||||
|
using System;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using System.Net;
|
||||||
|
using Microsoft.eShopOnContainers.Services.Marketing.API.Dto;
|
||||||
|
|
||||||
|
public class CampaignScenarios
|
||||||
|
: CampaignScenarioBase
|
||||||
|
{
|
||||||
|
[Fact]
|
||||||
|
public async Task Get_get_all_campaigns_and_response_ok_status_code()
|
||||||
|
{
|
||||||
|
using (var server = CreateServer())
|
||||||
|
{
|
||||||
|
var response = await server.CreateClient()
|
||||||
|
.GetAsync(Get.Campaigns);
|
||||||
|
|
||||||
|
response.EnsureSuccessStatusCode();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task Get_get_campaign_by_id_and_response_ok_status_code()
|
||||||
|
{
|
||||||
|
var campaignId = 1;
|
||||||
|
using (var server = CreateServer())
|
||||||
|
{
|
||||||
|
var response = await server.CreateClient()
|
||||||
|
.GetAsync(Get.CampaignBy(campaignId));
|
||||||
|
|
||||||
|
response.EnsureSuccessStatusCode();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task Get_get_campaign_by_id_and_response_not_found_status_code()
|
||||||
|
{
|
||||||
|
using (var server = CreateServer())
|
||||||
|
{
|
||||||
|
var response = await server.CreateClient()
|
||||||
|
.GetAsync(Get.CampaignBy(int.MaxValue));
|
||||||
|
|
||||||
|
Assert.True(response.StatusCode == HttpStatusCode.NotFound);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task Post_add_new_campaign_and_response_ok_status_code()
|
||||||
|
{
|
||||||
|
using (var server = CreateServer())
|
||||||
|
{
|
||||||
|
var fakeCampaignDto = GetFakeCampaignDto();
|
||||||
|
var content = new StringContent(JsonConvert.SerializeObject(fakeCampaignDto), Encoding.UTF8, "application/json");
|
||||||
|
var response = await server.CreateClient()
|
||||||
|
.PostAsync(Post.AddNewCampaign, content);
|
||||||
|
|
||||||
|
response.EnsureSuccessStatusCode();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task Delete_delete_campaign_and_response_not_content_status_code()
|
||||||
|
{
|
||||||
|
using (var server = CreateServer())
|
||||||
|
{
|
||||||
|
var fakeCampaignDto = GetFakeCampaignDto();
|
||||||
|
var content = new StringContent(JsonConvert.SerializeObject(fakeCampaignDto), Encoding.UTF8, "application/json");
|
||||||
|
|
||||||
|
//add campaign
|
||||||
|
var campaignResponse = await server.CreateClient()
|
||||||
|
.PostAsync(Post.AddNewCampaign, content);
|
||||||
|
|
||||||
|
if (int.TryParse(campaignResponse.Headers.Location.Segments[4], out int id))
|
||||||
|
{
|
||||||
|
var response = await server.CreateClient()
|
||||||
|
.DeleteAsync(Delete.CampaignBy(id));
|
||||||
|
|
||||||
|
Assert.True(response.StatusCode == HttpStatusCode.NoContent);
|
||||||
|
}
|
||||||
|
|
||||||
|
campaignResponse.EnsureSuccessStatusCode();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task Put_update_campaign_and_response_not_content_status_code()
|
||||||
|
{
|
||||||
|
using (var server = CreateServer())
|
||||||
|
{
|
||||||
|
var fakeCampaignDto = GetFakeCampaignDto();
|
||||||
|
var content = new StringContent(JsonConvert.SerializeObject(fakeCampaignDto), Encoding.UTF8, "application/json");
|
||||||
|
|
||||||
|
//add campaign
|
||||||
|
var campaignResponse = await server.CreateClient()
|
||||||
|
.PostAsync(Post.AddNewCampaign, content);
|
||||||
|
|
||||||
|
if (int.TryParse(campaignResponse.Headers.Location.Segments[4], out int id))
|
||||||
|
{
|
||||||
|
fakeCampaignDto.Description = "FakeCampaignUpdatedDescription";
|
||||||
|
content = new StringContent(JsonConvert.SerializeObject(fakeCampaignDto), Encoding.UTF8, "application/json");
|
||||||
|
var response = await server.CreateClient()
|
||||||
|
.PutAsync(Put.CampaignBy(id), content);
|
||||||
|
|
||||||
|
Assert.True(response.StatusCode == HttpStatusCode.Created);
|
||||||
|
}
|
||||||
|
|
||||||
|
campaignResponse.EnsureSuccessStatusCode();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static CampaignDTO GetFakeCampaignDto()
|
||||||
|
{
|
||||||
|
return new CampaignDTO()
|
||||||
|
{
|
||||||
|
Description = "FakeCampaignDescription",
|
||||||
|
From = DateTime.Now,
|
||||||
|
To = DateTime.Now.AddDays(7),
|
||||||
|
Url = "http://CampaignUrl.test/fdaf91ad0cef5419719f50198",
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user