diff --git a/.dockerignore b/.dockerignore index be95b4e4c..676134dd4 100644 --- a/.dockerignore +++ b/.dockerignore @@ -13,6 +13,7 @@ hosts LICENSE *.testsettings vsts-docs +test ServiceFabric readme k8s @@ -29,4 +30,5 @@ cli-linux **/bower_components/ **/wwwroot/lib/ global.json +**/appsettings.localhost.json src/Web/WebSPA/wwwroot/ \ No newline at end of file diff --git a/.gitignore b/.gitignore index a8d5986bc..6e46dd41b 100644 --- a/.gitignore +++ b/.gitignore @@ -260,3 +260,4 @@ pub/ /src/Web/WebMVC/wwwroot/lib /src/Web/WebMVC/wwwroot/css/site.min.css **/.kube/** +.mfractor diff --git a/docker-compose.dcproj b/docker-compose.dcproj index 5f12f7d62..d1f485b05 100644 --- a/docker-compose.dcproj +++ b/docker-compose.dcproj @@ -7,6 +7,7 @@ webmvc Linux 2.1 + LaunchBrowser diff --git a/docker-compose.override.yml b/docker-compose.override.yml index 4a3ffdd97..e656f753f 100644 --- a/docker-compose.override.yml +++ b/docker-compose.override.yml @@ -57,6 +57,8 @@ services: - MarketingApiClient=http://${ESHOP_EXTERNAL_DNS_NAME_OR_IP}:5110 - BasketApiClient=http://${ESHOP_EXTERNAL_DNS_NAME_OR_IP}:5103 - OrderingApiClient=http://${ESHOP_EXTERNAL_DNS_NAME_OR_IP}:5102 + - MobileShoppingAggClient=http://${ESHOP_EXTERNAL_DNS_NAME_OR_IP}:5120 + - WebShoppingAggClient=http://${ESHOP_EXTERNAL_DNS_NAME_OR_IP}:5121 - UseCustomizationData=True - ApplicationInsights__InstrumentationKey=${INSTRUMENTATION_KEY} - OrchestratorType=${ORCHESTRATOR_TYPE} @@ -83,24 +85,6 @@ services: ports: - "5102:80" - ordering.backgroundtasks: - environment: - - ASPNETCORE_ENVIRONMENT=Development - - ASPNETCORE_URLS=http://0.0.0.0:80 - - ConnectionString=${ESHOP_AZURE_ORDERING_DB:-Server=sql.data;Database=Microsoft.eShopOnContainers.Services.OrderingDb;User Id=sa;Password=Pass@word} - - EventBusConnection=${ESHOP_AZURE_SERVICE_BUS:-rabbitmq} - - EventBusUserName=${ESHOP_SERVICE_BUS_USERNAME} - - EventBusPassword=${ESHOP_SERVICE_BUS_PASSWORD} - - UseCustomizationData=True - - AzureServiceBusEnabled=False - - CheckUpdateTime=30000 - - GracePeriodTime=1 - - ApplicationInsights__InstrumentationKey=${INSTRUMENTATION_KEY} - - OrchestratorType=${ORCHESTRATOR_TYPE} - - UseLoadTest=${USE_LOADTEST:-False} - ports: - - "5111:80" - marketing.api: environment: - ASPNETCORE_ENVIRONMENT=Development @@ -129,12 +113,9 @@ services: environment: - ASPNETCORE_ENVIRONMENT=Development - ASPNETCORE_URLS=http://0.0.0.0:80 - - CatalogUrl=http://${ESHOP_EXTERNAL_DNS_NAME_OR_IP}:5101 - - OrderingUrl=http://${ESHOP_EXTERNAL_DNS_NAME_OR_IP}:5102 - IdentityUrl=http://${ESHOP_EXTERNAL_DNS_NAME_OR_IP}:5105 #Local: You need to open your local dev-machine firewall at range 5100-5105. at range 5100-5105. - - BasketUrl=http://${ESHOP_EXTERNAL_DNS_NAME_OR_IP}:5103 - - MarketingUrl=http://${ESHOP_EXTERNAL_DNS_NAME_OR_IP}:5110 - - LocationsUrl=http://${ESHOP_EXTERNAL_DNS_NAME_OR_IP}:5109 + - PurchaseUrl=http://${ESHOP_EXTERNAL_DNS_NAME_OR_IP}:5202 + - MarketingUrl=http://${ESHOP_EXTERNAL_DNS_NAME_OR_IP}:5203 - CatalogUrlHC=http://catalog.api/hc - OrderingUrlHC=http://ordering.api/hc - IdentityUrlHC=http://identity.api/hc #Local: Use ${ESHOP_PROD_EXTERNAL_DNS_NAME_OR_IP}, if using external IP or DNS name from browser. @@ -151,12 +132,9 @@ services: environment: - ASPNETCORE_ENVIRONMENT=Development - ASPNETCORE_URLS=http://0.0.0.0:80 - - CatalogUrl=http://catalog.api - - OrderingUrl=http://ordering.api - - BasketUrl=http://basket.api - - LocationsUrl=http://locations.api + - PurchaseUrl=http://webshoppingapigw - IdentityUrl=http://10.0.75.1:5105 # Local Mac: Use http://docker.for.mac.localhost:5105 || Local Windows: Use 10.0.75.1 in a "Docker for Windows" environment, if using "localhost" from browser. || #Remote access: Use ${ESHOP_EXTERNAL_DNS_NAME_OR_IP} if using external IP or DNS name from browser. - - MarketingUrl=http://marketing.api + - MarketingUrl=http://webmarketingapigw - CatalogUrlHC=http://catalog.api/hc - OrderingUrlHC=http://ordering.api/hc - IdentityUrlHC=http://identity.api/hc #Local: Use ${ESHOP_PROD_EXTERNAL_DNS_NAME_OR_IP}, if using external IP or DNS name from browser. @@ -239,3 +217,58 @@ services: - "15672:15672" - "5672:5672" + mobileshoppingapigw: + environment: + - ASPNETCORE_ENVIRONMENT=Development + - IdentityUrl=http://identity.api #Local: You need to open your local dev-machine firewall at range 5100-5110. + ports: + - "5200:80" + volumes: + - ./src/ApiGateways/Mobile.Bff.Shopping/apigw:/app/configuration + + mobilemarketingapigw: + environment: + - ASPNETCORE_ENVIRONMENT=Development + - IdentityUrl=http://identity.api #Local: You need to open your local dev-machine firewall at range 5100-5110. + ports: + - "5201:80" + volumes: + - ./src/ApiGateways/Mobile.Bff.Marketing/apigw:/app/configuration + + webshoppingapigw: + environment: + - ASPNETCORE_ENVIRONMENT=Development + - IdentityUrl=http://identity.api #Local: You need to open your local dev-machine firewall at range 5100-5110. + ports: + - "5202:80" + volumes: + - ./src/ApiGateways/Web.Bff.Shopping/apigw:/app/configuration + + webmarketingapigw: + environment: + - ASPNETCORE_ENVIRONMENT=Development + - IdentityUrl=http://identity.api #Local: You need to open your local dev-machine firewall at range 5100-5110. + ports: + - "5203:80" + volumes: + - ./src/ApiGateways/Web.Bff.Marketing/apigw:/app/configuration + + mobileshoppingagg: + environment: + - ASPNETCORE_ENVIRONMENT=Development + - urls__basket=http://basket.api + - urls__catalog=http://catalog.api + - urls__orders=http://ordering.api + - urls__identity=http://identity.api #Local: You need to open your local dev-machine firewall at range 5100-5110. + ports: + - "5120:80" + + webshoppingagg: + environment: + - ASPNETCORE_ENVIRONMENT=Development + - urls__basket=http://basket.api + - urls__catalog=http://catalog.api + - urls__orders=http://ordering.api + - urls__identity=http://identity.api #Local: You need to open your local dev-machine firewall at range 5100-5110. + ports: + - "5121:80" \ No newline at end of file diff --git a/docker-compose.prod.yml b/docker-compose.prod.yml index 1be627e76..b8630ef97 100644 --- a/docker-compose.prod.yml +++ b/docker-compose.prod.yml @@ -64,6 +64,8 @@ services: - MarketingApiClient=http://${ESHOP_PROD_EXTERNAL_DNS_NAME_OR_IP}:5110 - BasketApiClient=http://${ESHOP_PROD_EXTERNAL_DNS_NAME_OR_IP}:5103 - OrderingApiClient=http://${ESHOP_PROD_EXTERNAL_DNS_NAME_OR_IP}:5102 + - MobileShoppingAggClient=http://${ESHOP_EXTERNAL_DNS_NAME_OR_IP}:5120 + - WebShoppingAggClient=http://${ESHOP_EXTERNAL_DNS_NAME_OR_IP}:5120 - UseCustomizationData=True - ApplicationInsights__InstrumentationKey=${INSTRUMENTATION_KEY} - OrchestratorType=${ORCHESTRATOR_TYPE} @@ -156,17 +158,16 @@ services: webmvc: environment: + - ASPNETCORE_ENVIRONMENT=Development - ASPNETCORE_URLS=http://0.0.0.0:80 - - CatalogUrl=http://catalog.api - - OrderingUrl=http://ordering.api - - BasketUrl=http://basket.api + - PurchaseUrl=http://webshoppingapigw/shopping - LocationsUrl=http://locations.api - - IdentityUrl=http://${ESHOP_PROD_EXTERNAL_DNS_NAME_OR_IP}:5105 #Local: Use 10.0.75.1 in a "Docker for Windows" environment, if using "localhost" from browser. #Remote: Use ${ESHOP_PROD_EXTERNAL_DNS_NAME_OR_IP} if using external IP or DNS name from browser. - - MarketingUrl=http://marketing.api + - IdentityUrl=http://${ESHOP_PROD_EXTERNAL_DNS_NAME_OR_IP}:5105 # Local Mac: Use http://docker.for.mac.localhost:5105 || Local Windows: Use 10.0.75.1 in a "Docker for Windows" environment, if using "localhost" from browser. || #Remote access: Use ${ESHOP_EXTERNAL_DNS_NAME_OR_IP} if using external IP or DNS name from browser. + - MarketingUrl=http://marketing.api - CatalogUrlHC=http://catalog.api/hc - OrderingUrlHC=http://ordering.api/hc - - IdentityUrlHC=http://identity.api/hc + - IdentityUrlHC=http://identity.api/hc #Local: Use ${ESHOP_PROD_EXTERNAL_DNS_NAME_OR_IP}, if using external IP or DNS name from browser. - BasketUrlHC=http://basket.api/hc - MarketingUrlHC=http://marketing.api/hc - PaymentUrlHC=http://payment.api/hc diff --git a/docker-compose.yml b/docker-compose.yml index f6f59db25..39a0217be 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -38,15 +38,6 @@ services: - sql.data - rabbitmq - ordering.backgroundtasks: - image: eshop/ordering.backgroundtasks:${TAG:-latest} - build: - context: . - dockerfile: src/Services/Ordering/Ordering.BackgroundTasks/Dockerfile - depends_on: - - sql.data - - rabbitmq - marketing.api: image: eshop/marketing.api:${TAG:-latest} build: @@ -115,4 +106,41 @@ services: image: redis:alpine rabbitmq: - image: rabbitmq:3-management-alpine \ No newline at end of file + image: rabbitmq:3-management-alpine + + mobileshoppingapigw: + image: eshop/ocelotapigw-ms:${TAG:-latest} + build: + context: . + dockerfile: src/ApiGateways/ApiGw-Base/Dockerfile + + mobilemarketingapigw: + image: eshop/ocelotapigw-mm:${TAG:-latest} + build: + context: . + dockerfile: src/ApiGateways/ApiGw-Base/Dockerfile2 + + webshoppingapigw: + image: eshop/ocelotapigw-ws:${TAG:-latest} + build: + context: . + dockerfile: src/ApiGateways/ApiGw-Base/Dockerfile3 + + webmarketingapigw: + image: eshop/ocelotapigw-wm:${TAG:-latest} + build: + context: . + dockerfile: src/ApiGateways/ApiGw-Base/Dockerfile + + mobileshoppingagg: + image: eshop/mobileshoppingagg:${TAG:-latest} + build: + context: . + dockerfile: src/ApiGateways/Mobile.Bff.Shopping/aggregator/Dockerfile + + webshoppingagg: + image: eshop/webshoppingagg:${TAG:-latest} + build: + context: . + dockerfile: src/ApiGateways/Web.Bff.Shopping/aggregator/Dockerfile + diff --git a/eShopOnContainers-ServicesAndWebApps.sln b/eShopOnContainers-ServicesAndWebApps.sln index 353952ff0..c1fe125a5 100644 --- a/eShopOnContainers-ServicesAndWebApps.sln +++ b/eShopOnContainers-ServicesAndWebApps.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 15 -VisualStudioVersion = 15.0.27130.2024 +VisualStudioVersion = 15.0.27130.2027 MinimumVisualStudioVersion = 10.0.40219.1 Project("{E53339B2-1760-4266-BCC7-CA923CBCF16C}") = "docker-compose", "docker-compose.dcproj", "{FEA0C318-FFED-4D39-8781-265718CA43DD}" EndProject @@ -97,7 +97,35 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "WebHost", "WebHost", "{1815 EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WebHost.Customization", "src\BuildingBlocks\WebHostCustomization\WebHost.Customization\WebHost.Customization.csproj", "{15F4B3AA-89B6-4A0D-9051-414305974781}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ordering.BackgroundTasks", "src\Services\Ordering\Ordering.BackgroundTasks\Ordering.BackgroundTasks.csproj", "{2FF56999-0266-48B2-ACC1-FEBC482A5105}" +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ApiGateways", "ApiGateways", "{77849D35-37D4-4802-81DC-9477B2775A40}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ApiGw-Base", "ApiGw-Base", "{EC91ADE9-3D66-4AB2-9FB4-2B585E1F3531}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Mobile.Bff.Marketing", "Mobile.Bff.Marketing", "{DB813A36-11BA-41FE-B258-CA9A7152247B}" + ProjectSection(SolutionItems) = preProject + src\ApiGateways\Mobile.Bff.Marketing\apigw\configuration.json = src\ApiGateways\Mobile.Bff.Marketing\apigw\configuration.json + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Mobile.Bff.Shopping", "Mobile.Bff.Shopping", "{0189E4FB-6E2B-4F2E-9B1D-5473D23FC6DB}" + ProjectSection(SolutionItems) = preProject + src\ApiGateways\Mobile.Bff.Shopping\apigw\configuration.json = src\ApiGateways\Mobile.Bff.Shopping\apigw\configuration.json + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Web.Bff.Marketing", "Web.Bff.Marketing", "{F8F0921C-EE5D-4AED-A4D6-5BF5FAE02CB5}" + ProjectSection(SolutionItems) = preProject + src\ApiGateways\Web.Bff.Marketing\apigw\configuration.json = src\ApiGateways\Web.Bff.Marketing\apigw\configuration.json + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Web.Bff.Shopping", "Web.Bff.Shopping", "{28C0F5C8-4849-4035-80AB-45639424E73F}" + ProjectSection(SolutionItems) = preProject + src\ApiGateways\Web.Bff.Shopping\apigw\configuration.json = src\ApiGateways\Web.Bff.Shopping\apigw\configuration.json + EndProjectSection +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OcelotApiGw", "src\ApiGateways\ApiGw-Base\OcelotApiGw.csproj", "{3F79558C-485D-49E1-BD3E-E12538D3D308}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Mobile.Shopping.HttpAggregator", "src\ApiGateways\Mobile.Bff.Shopping\aggregator\Mobile.Shopping.HttpAggregator.csproj", "{BEA37D6D-4CF2-4AE8-9575-72388E54FBD0}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Web.Shopping.HttpAggregator", "src\ApiGateways\Web.Bff.Shopping\aggregator\Web.Shopping.HttpAggregator.csproj", "{AF0828DB-8BDD-411A-AEEF-B780FBB8D8C1}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -1313,54 +1341,150 @@ Global {15F4B3AA-89B6-4A0D-9051-414305974781}.Release|x64.Build.0 = Release|Any CPU {15F4B3AA-89B6-4A0D-9051-414305974781}.Release|x86.ActiveCfg = Release|Any CPU {15F4B3AA-89B6-4A0D-9051-414305974781}.Release|x86.Build.0 = Release|Any CPU - {2FF56999-0266-48B2-ACC1-FEBC482A5105}.Ad-Hoc|Any CPU.ActiveCfg = Debug|Any CPU - {2FF56999-0266-48B2-ACC1-FEBC482A5105}.Ad-Hoc|Any CPU.Build.0 = Debug|Any CPU - {2FF56999-0266-48B2-ACC1-FEBC482A5105}.Ad-Hoc|ARM.ActiveCfg = Debug|Any CPU - {2FF56999-0266-48B2-ACC1-FEBC482A5105}.Ad-Hoc|ARM.Build.0 = Debug|Any CPU - {2FF56999-0266-48B2-ACC1-FEBC482A5105}.Ad-Hoc|iPhone.ActiveCfg = Debug|Any CPU - {2FF56999-0266-48B2-ACC1-FEBC482A5105}.Ad-Hoc|iPhone.Build.0 = Debug|Any CPU - {2FF56999-0266-48B2-ACC1-FEBC482A5105}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Debug|Any CPU - {2FF56999-0266-48B2-ACC1-FEBC482A5105}.Ad-Hoc|iPhoneSimulator.Build.0 = Debug|Any CPU - {2FF56999-0266-48B2-ACC1-FEBC482A5105}.Ad-Hoc|x64.ActiveCfg = Debug|Any CPU - {2FF56999-0266-48B2-ACC1-FEBC482A5105}.Ad-Hoc|x64.Build.0 = Debug|Any CPU - {2FF56999-0266-48B2-ACC1-FEBC482A5105}.Ad-Hoc|x86.ActiveCfg = Debug|Any CPU - {2FF56999-0266-48B2-ACC1-FEBC482A5105}.Ad-Hoc|x86.Build.0 = Debug|Any CPU - {2FF56999-0266-48B2-ACC1-FEBC482A5105}.AppStore|Any CPU.ActiveCfg = Debug|Any CPU - {2FF56999-0266-48B2-ACC1-FEBC482A5105}.AppStore|Any CPU.Build.0 = Debug|Any CPU - {2FF56999-0266-48B2-ACC1-FEBC482A5105}.AppStore|ARM.ActiveCfg = Debug|Any CPU - {2FF56999-0266-48B2-ACC1-FEBC482A5105}.AppStore|ARM.Build.0 = Debug|Any CPU - {2FF56999-0266-48B2-ACC1-FEBC482A5105}.AppStore|iPhone.ActiveCfg = Debug|Any CPU - {2FF56999-0266-48B2-ACC1-FEBC482A5105}.AppStore|iPhone.Build.0 = Debug|Any CPU - {2FF56999-0266-48B2-ACC1-FEBC482A5105}.AppStore|iPhoneSimulator.ActiveCfg = Debug|Any CPU - {2FF56999-0266-48B2-ACC1-FEBC482A5105}.AppStore|iPhoneSimulator.Build.0 = Debug|Any CPU - {2FF56999-0266-48B2-ACC1-FEBC482A5105}.AppStore|x64.ActiveCfg = Debug|Any CPU - {2FF56999-0266-48B2-ACC1-FEBC482A5105}.AppStore|x64.Build.0 = Debug|Any CPU - {2FF56999-0266-48B2-ACC1-FEBC482A5105}.AppStore|x86.ActiveCfg = Debug|Any CPU - {2FF56999-0266-48B2-ACC1-FEBC482A5105}.AppStore|x86.Build.0 = Debug|Any CPU - {2FF56999-0266-48B2-ACC1-FEBC482A5105}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {2FF56999-0266-48B2-ACC1-FEBC482A5105}.Debug|Any CPU.Build.0 = Debug|Any CPU - {2FF56999-0266-48B2-ACC1-FEBC482A5105}.Debug|ARM.ActiveCfg = Debug|Any CPU - {2FF56999-0266-48B2-ACC1-FEBC482A5105}.Debug|ARM.Build.0 = Debug|Any CPU - {2FF56999-0266-48B2-ACC1-FEBC482A5105}.Debug|iPhone.ActiveCfg = Debug|Any CPU - {2FF56999-0266-48B2-ACC1-FEBC482A5105}.Debug|iPhone.Build.0 = Debug|Any CPU - {2FF56999-0266-48B2-ACC1-FEBC482A5105}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU - {2FF56999-0266-48B2-ACC1-FEBC482A5105}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU - {2FF56999-0266-48B2-ACC1-FEBC482A5105}.Debug|x64.ActiveCfg = Debug|Any CPU - {2FF56999-0266-48B2-ACC1-FEBC482A5105}.Debug|x64.Build.0 = Debug|Any CPU - {2FF56999-0266-48B2-ACC1-FEBC482A5105}.Debug|x86.ActiveCfg = Debug|Any CPU - {2FF56999-0266-48B2-ACC1-FEBC482A5105}.Debug|x86.Build.0 = Debug|Any CPU - {2FF56999-0266-48B2-ACC1-FEBC482A5105}.Release|Any CPU.ActiveCfg = Release|Any CPU - {2FF56999-0266-48B2-ACC1-FEBC482A5105}.Release|Any CPU.Build.0 = Release|Any CPU - {2FF56999-0266-48B2-ACC1-FEBC482A5105}.Release|ARM.ActiveCfg = Release|Any CPU - {2FF56999-0266-48B2-ACC1-FEBC482A5105}.Release|ARM.Build.0 = Release|Any CPU - {2FF56999-0266-48B2-ACC1-FEBC482A5105}.Release|iPhone.ActiveCfg = Release|Any CPU - {2FF56999-0266-48B2-ACC1-FEBC482A5105}.Release|iPhone.Build.0 = Release|Any CPU - {2FF56999-0266-48B2-ACC1-FEBC482A5105}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU - {2FF56999-0266-48B2-ACC1-FEBC482A5105}.Release|iPhoneSimulator.Build.0 = Release|Any CPU - {2FF56999-0266-48B2-ACC1-FEBC482A5105}.Release|x64.ActiveCfg = Release|Any CPU - {2FF56999-0266-48B2-ACC1-FEBC482A5105}.Release|x64.Build.0 = Release|Any CPU - {2FF56999-0266-48B2-ACC1-FEBC482A5105}.Release|x86.ActiveCfg = Release|Any CPU - {2FF56999-0266-48B2-ACC1-FEBC482A5105}.Release|x86.Build.0 = Release|Any CPU + {3F79558C-485D-49E1-BD3E-E12538D3D308}.Ad-Hoc|Any CPU.ActiveCfg = Debug|Any CPU + {3F79558C-485D-49E1-BD3E-E12538D3D308}.Ad-Hoc|Any CPU.Build.0 = Debug|Any CPU + {3F79558C-485D-49E1-BD3E-E12538D3D308}.Ad-Hoc|ARM.ActiveCfg = Debug|Any CPU + {3F79558C-485D-49E1-BD3E-E12538D3D308}.Ad-Hoc|ARM.Build.0 = Debug|Any CPU + {3F79558C-485D-49E1-BD3E-E12538D3D308}.Ad-Hoc|iPhone.ActiveCfg = Debug|Any CPU + {3F79558C-485D-49E1-BD3E-E12538D3D308}.Ad-Hoc|iPhone.Build.0 = Debug|Any CPU + {3F79558C-485D-49E1-BD3E-E12538D3D308}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {3F79558C-485D-49E1-BD3E-E12538D3D308}.Ad-Hoc|iPhoneSimulator.Build.0 = Debug|Any CPU + {3F79558C-485D-49E1-BD3E-E12538D3D308}.Ad-Hoc|x64.ActiveCfg = Debug|Any CPU + {3F79558C-485D-49E1-BD3E-E12538D3D308}.Ad-Hoc|x64.Build.0 = Debug|Any CPU + {3F79558C-485D-49E1-BD3E-E12538D3D308}.Ad-Hoc|x86.ActiveCfg = Debug|Any CPU + {3F79558C-485D-49E1-BD3E-E12538D3D308}.Ad-Hoc|x86.Build.0 = Debug|Any CPU + {3F79558C-485D-49E1-BD3E-E12538D3D308}.AppStore|Any CPU.ActiveCfg = Debug|Any CPU + {3F79558C-485D-49E1-BD3E-E12538D3D308}.AppStore|Any CPU.Build.0 = Debug|Any CPU + {3F79558C-485D-49E1-BD3E-E12538D3D308}.AppStore|ARM.ActiveCfg = Debug|Any CPU + {3F79558C-485D-49E1-BD3E-E12538D3D308}.AppStore|ARM.Build.0 = Debug|Any CPU + {3F79558C-485D-49E1-BD3E-E12538D3D308}.AppStore|iPhone.ActiveCfg = Debug|Any CPU + {3F79558C-485D-49E1-BD3E-E12538D3D308}.AppStore|iPhone.Build.0 = Debug|Any CPU + {3F79558C-485D-49E1-BD3E-E12538D3D308}.AppStore|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {3F79558C-485D-49E1-BD3E-E12538D3D308}.AppStore|iPhoneSimulator.Build.0 = Debug|Any CPU + {3F79558C-485D-49E1-BD3E-E12538D3D308}.AppStore|x64.ActiveCfg = Debug|Any CPU + {3F79558C-485D-49E1-BD3E-E12538D3D308}.AppStore|x64.Build.0 = Debug|Any CPU + {3F79558C-485D-49E1-BD3E-E12538D3D308}.AppStore|x86.ActiveCfg = Debug|Any CPU + {3F79558C-485D-49E1-BD3E-E12538D3D308}.AppStore|x86.Build.0 = Debug|Any CPU + {3F79558C-485D-49E1-BD3E-E12538D3D308}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3F79558C-485D-49E1-BD3E-E12538D3D308}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3F79558C-485D-49E1-BD3E-E12538D3D308}.Debug|ARM.ActiveCfg = Debug|Any CPU + {3F79558C-485D-49E1-BD3E-E12538D3D308}.Debug|ARM.Build.0 = Debug|Any CPU + {3F79558C-485D-49E1-BD3E-E12538D3D308}.Debug|iPhone.ActiveCfg = Debug|Any CPU + {3F79558C-485D-49E1-BD3E-E12538D3D308}.Debug|iPhone.Build.0 = Debug|Any CPU + {3F79558C-485D-49E1-BD3E-E12538D3D308}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {3F79558C-485D-49E1-BD3E-E12538D3D308}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU + {3F79558C-485D-49E1-BD3E-E12538D3D308}.Debug|x64.ActiveCfg = Debug|Any CPU + {3F79558C-485D-49E1-BD3E-E12538D3D308}.Debug|x64.Build.0 = Debug|Any CPU + {3F79558C-485D-49E1-BD3E-E12538D3D308}.Debug|x86.ActiveCfg = Debug|Any CPU + {3F79558C-485D-49E1-BD3E-E12538D3D308}.Debug|x86.Build.0 = Debug|Any CPU + {3F79558C-485D-49E1-BD3E-E12538D3D308}.Release|Any CPU.ActiveCfg = Release|Any CPU + {3F79558C-485D-49E1-BD3E-E12538D3D308}.Release|Any CPU.Build.0 = Release|Any CPU + {3F79558C-485D-49E1-BD3E-E12538D3D308}.Release|ARM.ActiveCfg = Release|Any CPU + {3F79558C-485D-49E1-BD3E-E12538D3D308}.Release|ARM.Build.0 = Release|Any CPU + {3F79558C-485D-49E1-BD3E-E12538D3D308}.Release|iPhone.ActiveCfg = Release|Any CPU + {3F79558C-485D-49E1-BD3E-E12538D3D308}.Release|iPhone.Build.0 = Release|Any CPU + {3F79558C-485D-49E1-BD3E-E12538D3D308}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU + {3F79558C-485D-49E1-BD3E-E12538D3D308}.Release|iPhoneSimulator.Build.0 = Release|Any CPU + {3F79558C-485D-49E1-BD3E-E12538D3D308}.Release|x64.ActiveCfg = Release|Any CPU + {3F79558C-485D-49E1-BD3E-E12538D3D308}.Release|x64.Build.0 = Release|Any CPU + {3F79558C-485D-49E1-BD3E-E12538D3D308}.Release|x86.ActiveCfg = Release|Any CPU + {3F79558C-485D-49E1-BD3E-E12538D3D308}.Release|x86.Build.0 = Release|Any CPU + {BEA37D6D-4CF2-4AE8-9575-72388E54FBD0}.Ad-Hoc|Any CPU.ActiveCfg = Debug|Any CPU + {BEA37D6D-4CF2-4AE8-9575-72388E54FBD0}.Ad-Hoc|Any CPU.Build.0 = Debug|Any CPU + {BEA37D6D-4CF2-4AE8-9575-72388E54FBD0}.Ad-Hoc|ARM.ActiveCfg = Debug|Any CPU + {BEA37D6D-4CF2-4AE8-9575-72388E54FBD0}.Ad-Hoc|ARM.Build.0 = Debug|Any CPU + {BEA37D6D-4CF2-4AE8-9575-72388E54FBD0}.Ad-Hoc|iPhone.ActiveCfg = Debug|Any CPU + {BEA37D6D-4CF2-4AE8-9575-72388E54FBD0}.Ad-Hoc|iPhone.Build.0 = Debug|Any CPU + {BEA37D6D-4CF2-4AE8-9575-72388E54FBD0}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {BEA37D6D-4CF2-4AE8-9575-72388E54FBD0}.Ad-Hoc|iPhoneSimulator.Build.0 = Debug|Any CPU + {BEA37D6D-4CF2-4AE8-9575-72388E54FBD0}.Ad-Hoc|x64.ActiveCfg = Debug|Any CPU + {BEA37D6D-4CF2-4AE8-9575-72388E54FBD0}.Ad-Hoc|x64.Build.0 = Debug|Any CPU + {BEA37D6D-4CF2-4AE8-9575-72388E54FBD0}.Ad-Hoc|x86.ActiveCfg = Debug|Any CPU + {BEA37D6D-4CF2-4AE8-9575-72388E54FBD0}.Ad-Hoc|x86.Build.0 = Debug|Any CPU + {BEA37D6D-4CF2-4AE8-9575-72388E54FBD0}.AppStore|Any CPU.ActiveCfg = Debug|Any CPU + {BEA37D6D-4CF2-4AE8-9575-72388E54FBD0}.AppStore|Any CPU.Build.0 = Debug|Any CPU + {BEA37D6D-4CF2-4AE8-9575-72388E54FBD0}.AppStore|ARM.ActiveCfg = Debug|Any CPU + {BEA37D6D-4CF2-4AE8-9575-72388E54FBD0}.AppStore|ARM.Build.0 = Debug|Any CPU + {BEA37D6D-4CF2-4AE8-9575-72388E54FBD0}.AppStore|iPhone.ActiveCfg = Debug|Any CPU + {BEA37D6D-4CF2-4AE8-9575-72388E54FBD0}.AppStore|iPhone.Build.0 = Debug|Any CPU + {BEA37D6D-4CF2-4AE8-9575-72388E54FBD0}.AppStore|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {BEA37D6D-4CF2-4AE8-9575-72388E54FBD0}.AppStore|iPhoneSimulator.Build.0 = Debug|Any CPU + {BEA37D6D-4CF2-4AE8-9575-72388E54FBD0}.AppStore|x64.ActiveCfg = Debug|Any CPU + {BEA37D6D-4CF2-4AE8-9575-72388E54FBD0}.AppStore|x64.Build.0 = Debug|Any CPU + {BEA37D6D-4CF2-4AE8-9575-72388E54FBD0}.AppStore|x86.ActiveCfg = Debug|Any CPU + {BEA37D6D-4CF2-4AE8-9575-72388E54FBD0}.AppStore|x86.Build.0 = Debug|Any CPU + {BEA37D6D-4CF2-4AE8-9575-72388E54FBD0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {BEA37D6D-4CF2-4AE8-9575-72388E54FBD0}.Debug|Any CPU.Build.0 = Debug|Any CPU + {BEA37D6D-4CF2-4AE8-9575-72388E54FBD0}.Debug|ARM.ActiveCfg = Debug|Any CPU + {BEA37D6D-4CF2-4AE8-9575-72388E54FBD0}.Debug|ARM.Build.0 = Debug|Any CPU + {BEA37D6D-4CF2-4AE8-9575-72388E54FBD0}.Debug|iPhone.ActiveCfg = Debug|Any CPU + {BEA37D6D-4CF2-4AE8-9575-72388E54FBD0}.Debug|iPhone.Build.0 = Debug|Any CPU + {BEA37D6D-4CF2-4AE8-9575-72388E54FBD0}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {BEA37D6D-4CF2-4AE8-9575-72388E54FBD0}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU + {BEA37D6D-4CF2-4AE8-9575-72388E54FBD0}.Debug|x64.ActiveCfg = Debug|Any CPU + {BEA37D6D-4CF2-4AE8-9575-72388E54FBD0}.Debug|x64.Build.0 = Debug|Any CPU + {BEA37D6D-4CF2-4AE8-9575-72388E54FBD0}.Debug|x86.ActiveCfg = Debug|Any CPU + {BEA37D6D-4CF2-4AE8-9575-72388E54FBD0}.Debug|x86.Build.0 = Debug|Any CPU + {BEA37D6D-4CF2-4AE8-9575-72388E54FBD0}.Release|Any CPU.ActiveCfg = Release|Any CPU + {BEA37D6D-4CF2-4AE8-9575-72388E54FBD0}.Release|Any CPU.Build.0 = Release|Any CPU + {BEA37D6D-4CF2-4AE8-9575-72388E54FBD0}.Release|ARM.ActiveCfg = Release|Any CPU + {BEA37D6D-4CF2-4AE8-9575-72388E54FBD0}.Release|ARM.Build.0 = Release|Any CPU + {BEA37D6D-4CF2-4AE8-9575-72388E54FBD0}.Release|iPhone.ActiveCfg = Release|Any CPU + {BEA37D6D-4CF2-4AE8-9575-72388E54FBD0}.Release|iPhone.Build.0 = Release|Any CPU + {BEA37D6D-4CF2-4AE8-9575-72388E54FBD0}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU + {BEA37D6D-4CF2-4AE8-9575-72388E54FBD0}.Release|iPhoneSimulator.Build.0 = Release|Any CPU + {BEA37D6D-4CF2-4AE8-9575-72388E54FBD0}.Release|x64.ActiveCfg = Release|Any CPU + {BEA37D6D-4CF2-4AE8-9575-72388E54FBD0}.Release|x64.Build.0 = Release|Any CPU + {BEA37D6D-4CF2-4AE8-9575-72388E54FBD0}.Release|x86.ActiveCfg = Release|Any CPU + {BEA37D6D-4CF2-4AE8-9575-72388E54FBD0}.Release|x86.Build.0 = Release|Any CPU + {AF0828DB-8BDD-411A-AEEF-B780FBB8D8C1}.Ad-Hoc|Any CPU.ActiveCfg = Debug|Any CPU + {AF0828DB-8BDD-411A-AEEF-B780FBB8D8C1}.Ad-Hoc|Any CPU.Build.0 = Debug|Any CPU + {AF0828DB-8BDD-411A-AEEF-B780FBB8D8C1}.Ad-Hoc|ARM.ActiveCfg = Debug|Any CPU + {AF0828DB-8BDD-411A-AEEF-B780FBB8D8C1}.Ad-Hoc|ARM.Build.0 = Debug|Any CPU + {AF0828DB-8BDD-411A-AEEF-B780FBB8D8C1}.Ad-Hoc|iPhone.ActiveCfg = Debug|Any CPU + {AF0828DB-8BDD-411A-AEEF-B780FBB8D8C1}.Ad-Hoc|iPhone.Build.0 = Debug|Any CPU + {AF0828DB-8BDD-411A-AEEF-B780FBB8D8C1}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {AF0828DB-8BDD-411A-AEEF-B780FBB8D8C1}.Ad-Hoc|iPhoneSimulator.Build.0 = Debug|Any CPU + {AF0828DB-8BDD-411A-AEEF-B780FBB8D8C1}.Ad-Hoc|x64.ActiveCfg = Debug|Any CPU + {AF0828DB-8BDD-411A-AEEF-B780FBB8D8C1}.Ad-Hoc|x64.Build.0 = Debug|Any CPU + {AF0828DB-8BDD-411A-AEEF-B780FBB8D8C1}.Ad-Hoc|x86.ActiveCfg = Debug|Any CPU + {AF0828DB-8BDD-411A-AEEF-B780FBB8D8C1}.Ad-Hoc|x86.Build.0 = Debug|Any CPU + {AF0828DB-8BDD-411A-AEEF-B780FBB8D8C1}.AppStore|Any CPU.ActiveCfg = Debug|Any CPU + {AF0828DB-8BDD-411A-AEEF-B780FBB8D8C1}.AppStore|Any CPU.Build.0 = Debug|Any CPU + {AF0828DB-8BDD-411A-AEEF-B780FBB8D8C1}.AppStore|ARM.ActiveCfg = Debug|Any CPU + {AF0828DB-8BDD-411A-AEEF-B780FBB8D8C1}.AppStore|ARM.Build.0 = Debug|Any CPU + {AF0828DB-8BDD-411A-AEEF-B780FBB8D8C1}.AppStore|iPhone.ActiveCfg = Debug|Any CPU + {AF0828DB-8BDD-411A-AEEF-B780FBB8D8C1}.AppStore|iPhone.Build.0 = Debug|Any CPU + {AF0828DB-8BDD-411A-AEEF-B780FBB8D8C1}.AppStore|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {AF0828DB-8BDD-411A-AEEF-B780FBB8D8C1}.AppStore|iPhoneSimulator.Build.0 = Debug|Any CPU + {AF0828DB-8BDD-411A-AEEF-B780FBB8D8C1}.AppStore|x64.ActiveCfg = Debug|Any CPU + {AF0828DB-8BDD-411A-AEEF-B780FBB8D8C1}.AppStore|x64.Build.0 = Debug|Any CPU + {AF0828DB-8BDD-411A-AEEF-B780FBB8D8C1}.AppStore|x86.ActiveCfg = Debug|Any CPU + {AF0828DB-8BDD-411A-AEEF-B780FBB8D8C1}.AppStore|x86.Build.0 = Debug|Any CPU + {AF0828DB-8BDD-411A-AEEF-B780FBB8D8C1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {AF0828DB-8BDD-411A-AEEF-B780FBB8D8C1}.Debug|Any CPU.Build.0 = Debug|Any CPU + {AF0828DB-8BDD-411A-AEEF-B780FBB8D8C1}.Debug|ARM.ActiveCfg = Debug|Any CPU + {AF0828DB-8BDD-411A-AEEF-B780FBB8D8C1}.Debug|ARM.Build.0 = Debug|Any CPU + {AF0828DB-8BDD-411A-AEEF-B780FBB8D8C1}.Debug|iPhone.ActiveCfg = Debug|Any CPU + {AF0828DB-8BDD-411A-AEEF-B780FBB8D8C1}.Debug|iPhone.Build.0 = Debug|Any CPU + {AF0828DB-8BDD-411A-AEEF-B780FBB8D8C1}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {AF0828DB-8BDD-411A-AEEF-B780FBB8D8C1}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU + {AF0828DB-8BDD-411A-AEEF-B780FBB8D8C1}.Debug|x64.ActiveCfg = Debug|Any CPU + {AF0828DB-8BDD-411A-AEEF-B780FBB8D8C1}.Debug|x64.Build.0 = Debug|Any CPU + {AF0828DB-8BDD-411A-AEEF-B780FBB8D8C1}.Debug|x86.ActiveCfg = Debug|Any CPU + {AF0828DB-8BDD-411A-AEEF-B780FBB8D8C1}.Debug|x86.Build.0 = Debug|Any CPU + {AF0828DB-8BDD-411A-AEEF-B780FBB8D8C1}.Release|Any CPU.ActiveCfg = Release|Any CPU + {AF0828DB-8BDD-411A-AEEF-B780FBB8D8C1}.Release|Any CPU.Build.0 = Release|Any CPU + {AF0828DB-8BDD-411A-AEEF-B780FBB8D8C1}.Release|ARM.ActiveCfg = Release|Any CPU + {AF0828DB-8BDD-411A-AEEF-B780FBB8D8C1}.Release|ARM.Build.0 = Release|Any CPU + {AF0828DB-8BDD-411A-AEEF-B780FBB8D8C1}.Release|iPhone.ActiveCfg = Release|Any CPU + {AF0828DB-8BDD-411A-AEEF-B780FBB8D8C1}.Release|iPhone.Build.0 = Release|Any CPU + {AF0828DB-8BDD-411A-AEEF-B780FBB8D8C1}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU + {AF0828DB-8BDD-411A-AEEF-B780FBB8D8C1}.Release|iPhoneSimulator.Build.0 = Release|Any CPU + {AF0828DB-8BDD-411A-AEEF-B780FBB8D8C1}.Release|x64.ActiveCfg = Release|Any CPU + {AF0828DB-8BDD-411A-AEEF-B780FBB8D8C1}.Release|x64.Build.0 = Release|Any CPU + {AF0828DB-8BDD-411A-AEEF-B780FBB8D8C1}.Release|x86.ActiveCfg = Release|Any CPU + {AF0828DB-8BDD-411A-AEEF-B780FBB8D8C1}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -1407,7 +1531,15 @@ Global {969E793C-C413-490E-9C9D-B2B46DA5AF32} = {EF0337F2-ED00-4643-89FD-EE10863F1870} {1815B651-941C-466B-AE33-D1D7EEB8F77F} = {DB0EFB20-B024-4E5E-A75C-52143C131D25} {15F4B3AA-89B6-4A0D-9051-414305974781} = {1815B651-941C-466B-AE33-D1D7EEB8F77F} - {2FF56999-0266-48B2-ACC1-FEBC482A5105} = {0BD0DB92-2D98-44D9-9AC0-C59186D59B0B} + {77849D35-37D4-4802-81DC-9477B2775A40} = {932D8224-11F6-4D07-B109-DA28AD288A63} + {EC91ADE9-3D66-4AB2-9FB4-2B585E1F3531} = {77849D35-37D4-4802-81DC-9477B2775A40} + {DB813A36-11BA-41FE-B258-CA9A7152247B} = {77849D35-37D4-4802-81DC-9477B2775A40} + {0189E4FB-6E2B-4F2E-9B1D-5473D23FC6DB} = {77849D35-37D4-4802-81DC-9477B2775A40} + {F8F0921C-EE5D-4AED-A4D6-5BF5FAE02CB5} = {77849D35-37D4-4802-81DC-9477B2775A40} + {28C0F5C8-4849-4035-80AB-45639424E73F} = {77849D35-37D4-4802-81DC-9477B2775A40} + {3F79558C-485D-49E1-BD3E-E12538D3D308} = {EC91ADE9-3D66-4AB2-9FB4-2B585E1F3531} + {BEA37D6D-4CF2-4AE8-9575-72388E54FBD0} = {0189E4FB-6E2B-4F2E-9B1D-5473D23FC6DB} + {AF0828DB-8BDD-411A-AEEF-B780FBB8D8C1} = {28C0F5C8-4849-4035-80AB-45639424E73F} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {25728519-5F0F-4973-8A64-0A81EB4EA8D9} diff --git a/k8s/conf_cloud.yml b/k8s/conf_cloud.yml index 624d3a59b..a914105ae 100644 --- a/k8s/conf_cloud.yml +++ b/k8s/conf_cloud.yml @@ -3,14 +3,12 @@ kind: ConfigMap metadata: name: externalcfg labels: - app: eshop + app: eshop data: # Basket.API entries - BasketBus: CONNECTION_STRING (NAME OF RABBITMQ CONTAINER OR Endpoint=sb://XXXX for topic in case of using Azure) - BasketRedisConStr: REDIS CONNECTION STRING FOR BASKET + basket__ConnectionString: REDIS CONNECTION STRING FOR BASKET # Catalog.API entries - CatalogBus: CONNECTION_STRING (NAME OF RABBITMQ CONTAINER OR Endpoint=sb://XXXX for topic in case of using Azure) - CatalogSqlDb: Catalog SQL SERVER CONNECTION STRING (Server=xxxx;Intial Catalog=yyy;....) + catalog__ConnectionString: Catalog SQL SERVER CONNECTION STRING (Server=xxxx;Intial Catalog=yyy;....) # Identity.API entries IdentitySqlDb: Identity SQL SERVER CONNECTION STRING (Server=xxxx;Intial Catalog=yyy;....) # Locations.API entries @@ -30,5 +28,7 @@ data: # Payment.API entries PaymentBus: CONNECTION_STRING (NAME OF RABBITMQ CONTAINER OR Endpoint=sb://XXXX for topic in case of using Azure) # Global entries - UseAzureServiceBus: "TRUE" IF USE AZURE SB ("FALSE" FOR USING RABBITMQ) - keystore: REDIS CONNECTION STRING FOR KEYSTORE \ No newline at end of file + all_UseAzureServiceBus: "TRUE" IF USE AZURE SB ("FALSE" FOR USING RABBITMQ) + keystore: REDIS CONNECTION STRING FOR KEYSTORE + all_EventBusConnection: CONNECTION_STRING (NAME OF RABBITMQ CONTAINER OR Endpoint=sb://XXXX in case of using Azure) + all_InstrumentationKey: APPINSIGHTS KEY diff --git a/k8s/conf_local.yml b/k8s/conf_local.yml index 9a2059e63..615754bcf 100644 --- a/k8s/conf_local.yml +++ b/k8s/conf_local.yml @@ -5,28 +5,23 @@ metadata: labels: app: eshop data: - BasketBus: rabbitmq - BasketRedisConStr: basket-data - CatalogBus: rabbitmq - CatalogSqlDb: Server=sql-data;Initial Catalog=Microsoft.eShopOnContainers.Services.CatalogDb;User Id=sa;Password=Pass@word; - CatalogAzureStorageEnabled: "False" - IdentitySqlDb: Server=sql-data;Initial Catalog=Microsoft.eShopOnContainers.Services.IdentityDb;User Id=sa;Password=Pass@word; - LocationsBus: rabbitmq - LocationsNoSqlDb: mongodb://nosql-data - LocationsNoSqlDbName: LocationsDb - MarketingBus: rabbitmq - MarketingNoSqlDb: mongodb://nosql-data - MarketingNoSqlDbName: MarketingDb - MarketingSqlDb: Server=sql-data;Initial Catalog=Microsoft.eShopOnContainers.Services.MarketingDb;User Id=sa;Password=Pass@word; - OrderingBus: rabbitmq - OrderingSqlDb: Server=sql-data;Initial Catalog=Microsoft.eShopOnContainers.Services.OrderingDb;User Id=sa;Password=Pass@word; - PaymentBus: rabbitmq - UseAzureServiceBus: "False" - EnableLoadTest: "False" + basket__ConnectionString: basket-data + catalog__ConnectionString: Server=sql-data;Initial Catalog=Microsoft.eShopOnContainers.Services.CatalogDb;User Id=sa;Password=Pass@word; + catalog__AzureStorageEnabled: "False" + identity__ConnectionString: Server=sql-data;Initial Catalog=Microsoft.eShopOnContainers.Services.IdentityDb;User Id=sa;Password=Pass@word; + locations__ConnectionString: mongodb://nosql-data + locations__Database: LocationsDb + marketing__MongoConnectionString: mongodb://nosql-data + marketing__MongoDatabase: MarketingDb + marketing__ConnectionString: Server=sql-data;Initial Catalog=Microsoft.eShopOnContainers.Services.MarketingDb;User Id=sa;Password=Pass@word; + ordering__ConnectionString: Server=sql-data;Initial Catalog=Microsoft.eShopOnContainers.Services.OrderingDb;User Id=sa;Password=Pass@word; keystore: keystore-data - GracePeriodManager_GracePeriodTime: "1" - GracePeriodManager_CheckUpdateTime: "15000" - Instrumentation_Key: "" + GracePeriodManager__GracePeriodTime: "1" + GracePeriodManager__CheckUpdateTime: "15000" + all__EventBusConnection: rabbitmq + all__InstrumentationKey: "" + all__EnableLoadTest: "False" + all__UseAzureServiceBus: "False" diff --git a/k8s/deploy.ps1 b/k8s/deploy.ps1 index eed45ee62..0739d7ef0 100644 --- a/k8s/deploy.ps1 +++ b/k8s/deploy.ps1 @@ -65,7 +65,7 @@ if ($buildImages) { docker-compose -p .. -f ../docker-compose.yml build Write-Host "Pushing images to $registry/$dockerOrg..." -ForegroundColor Yellow - $services = ("basket.api", "catalog.api", "identity.api", "ordering.api", "ordering.backgroundtasks", "marketing.api","payment.api","locations.api", "webmvc", "webspa", "webstatus") + $services = ("basket.api", "catalog.api", "identity.api", "ordering.api", "marketing.api","payment.api","locations.api", "webmvc", "webspa", "webstatus", "ocelotapigw-mm", "ocelotapigw-ms", "ocelotapigw-wm", "ocelotapigw-ws", "mobileshoppingagg", "webshoppingagg") foreach ($service in $services) { $imageFqdn = if ($useDockerHub) {"$dockerOrg/${service}"} else {"$registry/$dockerOrg/${service}"} @@ -103,8 +103,10 @@ if (-not [string]::IsNullOrEmpty($dockerUser)) { Write-Host "Removing existing services & deployments.." -ForegroundColor Yellow ExecKube -cmd 'delete deployments --all' ExecKube -cmd 'delete services --all' +ExecKube -cmd 'delete configmap internalurls' ExecKube -cmd 'delete configmap urls' ExecKube -cmd 'delete configmap externalcfg' +ExecKube -cmd 'delete configmap ocelot' # start sql, rabbitmq, frontend deployments if ($deployInfrastructure) { @@ -113,48 +115,35 @@ if ($deployInfrastructure) { } +Write-Host 'Deploying ocelot APIGW' -ForegroundColor Yellow + +ExecKube "create configmap ocelot --from-file=mm=ocelot/configuration-mobile-marketing.json --from-file=ms=ocelot/configuration-mobile-shopping.json --from-file=wm=ocelot/configuration-web-marketing.json --from-file=ws=ocelot/configuration-web-shopping.json " +ExecKube -cmd "apply -f ocelot/deployment.yaml" +ExecKube -cmd "apply -f ocelot/service.yaml" + Write-Host 'Deploying code deployments (Web APIs, Web apps, ...)' -ForegroundColor Yellow ExecKube -cmd 'create -f services.yaml' +ExecKube -cmd 'create -f internalurls.yaml' ExecKube -cmd 'create configmap urls ` - --from-literal=BasketUrl=http://basket ` - --from-literal=BasketHealthCheckUrl=http://basket/hc ` - --from-literal=CatalogUrl=http://$($externalDns)/catalog-api ` - --from-literal=CatalogHealthCheckUrl=http://catalog/hc ` - --from-literal=PicBaseUrl=http://$($externalDns)/catalog-api/api/v1/catalog/items/[0]/pic/ ` - --from-literal=Marketing_PicBaseUrl=http://$($externalDns)/marketing-api/api/v1/campaigns/[0]/pic/ ` - --from-literal=IdentityUrl=http://$($externalDns)/identity ` - --from-literal=IdentityHealthCheckUrl=http://identity/hc ` - --from-literal=OrderingUrl=http://ordering ` - --from-literal=OrderingHealthCheckUrl=http://ordering/hc ` - --from-literal=MvcClientExternalUrl=http://$($externalDns)/webmvc ` - --from-literal=WebMvcHealthCheckUrl=http://webmvc/hc ` - --from-literal=MvcClientOrderingUrl=http://ordering ` - --from-literal=MvcClientCatalogUrl=http://catalog ` - --from-literal=MvcClientBasketUrl=http://basket ` - --from-literal=MvcClientMarketingUrl=http://marketing ` - --from-literal=MvcClientLocationsUrl=http://locations ` - --from-literal=MarketingHealthCheckUrl=http://marketing/hc ` - --from-literal=WebSpaHealthCheckUrl=http://webspa/hc ` - --from-literal=SpaClientMarketingExternalUrl=http://$($externalDns)/marketing-api ` - --from-literal=SpaClientOrderingExternalUrl=http://$($externalDns)/ordering-api ` - --from-literal=SpaClientCatalogExternalUrl=http://$($externalDns)/catalog-api ` - --from-literal=SpaClientBasketExternalUrl=http://$($externalDns)/basket-api ` - --from-literal=SpaClientIdentityExternalUrl=http://$($externalDns)/identity ` - --from-literal=SpaClientLocationsUrl=http://$($externalDns)/locations-api ` - --from-literal=LocationsHealthCheckUrl=http://locations/hc ` - --from-literal=SpaClientExternalUrl=http://$($externalDns) ` - --from-literal=LocationApiClient=http://$($externalDns)/locations-api ` - --from-literal=MarketingApiClient=http://$($externalDns)/marketing-api ` - --from-literal=BasketApiClient=http://$($externalDns)/basket-api ` - --from-literal=OrderingApiClient=http://$($externalDns)/ordering-api ` - --from-literal=PaymentHealthCheckUrl=http://payment/hc' - + --from-literal=PicBaseUrl=http://$($externalDns)/webshoppingapigw/api/v1/c/catalog/items/[0]/pic/ ` + --from-literal=Marketing_PicBaseUrl=http://$($externalDns)/webmarketingapigw/api/v1/m/campaigns/[0]/pic/ ` + --from-literal=mvc_e=http://$($externalDns)/webmvc ` + --from-literal=marketingapigw_e=http://$($externalDns)/webmarketingapigw ` + --from-literal=webshoppingapigw_e=http://$($externalDns)/webshoppingapigw ` + --from-literal=mobileshoppingagg_e=http://$($externalDns)/mobileshoppingagg ` + --from-literal=webshoppingagg_e=http://$($externalDns)/webshoppingagg ` + --from-literal=identity_e=http://$($externalDns)/identity ` + --from-literal=spa_e=http://$($externalDns) ` + --from-literal=locations_e=http://$($externalDns)/locations-api ` + --from-literal=marketing_e=http://$($externalDns)/marketing-api ` + --from-literal=basket_e=http://$($externalDns)/basket-api ` + --from-literal=ordering_e=http://$($externalDns)/ordering-api ` + --from-literal=xamarin_callback_e=http://$($externalDns)/xamarincallback' ExecKube -cmd 'label configmap urls app=eshop' Write-Host "Deploying configuration from $configFile" -ForegroundColor Yellow - ExecKube -cmd "create -f $configFile" Write-Host "Creating deployments..." -ForegroundColor Yellow @@ -178,8 +167,14 @@ ExecKube -cmd 'set image deployments/payment payment=${registryPath}${dockerOrg} ExecKube -cmd 'set image deployments/webmvc webmvc=${registryPath}${dockerOrg}/webmvc:$imageTag' ExecKube -cmd 'set image deployments/webstatus webstatus=${registryPath}${dockerOrg}/webstatus:$imageTag' ExecKube -cmd 'set image deployments/webspa webspa=${registryPath}${dockerOrg}/webspa:$imageTag' -ExecKube -cmd 'set image deployments/orderingbackground orderingbackground=${registryPath}${dockerOrg}/ordering.backgroundtasks:$imageTag' +ExecKube -cmd 'set image deployments/mobileshoppingagg mobileshoppingagg=${registryPath}${dockerOrg}/mobileshoppingagg:$imageTag' +ExecKube -cmd 'set image deployments/webshoppingagg webshoppingagg=${registryPath}${dockerOrg}/webshoppingagg:$imageTag' + +ExecKube -cmd 'set image deployments/apigwmm apigwmm=${registryPath}${dockerOrg}/ocelotapigw-mm:$imageTag' +ExecKube -cmd 'set image deployments/apigwms apigwms=${registryPath}${dockerOrg}/ocelotapigw-ms:$imageTag' +ExecKube -cmd 'set image deployments/apigwwm apigwwm=${registryPath}${dockerOrg}/ocelotapigw-wm:$imageTag' +ExecKube -cmd 'set image deployments/apigwws apigwws=${registryPath}${dockerOrg}/ocelotapigw-ws:$imageTag' Write-Host "Execute rollout..." -ForegroundColor Yellow ExecKube -cmd 'rollout resume deployments/basket' @@ -192,7 +187,12 @@ ExecKube -cmd 'rollout resume deployments/payment' ExecKube -cmd 'rollout resume deployments/webmvc' ExecKube -cmd 'rollout resume deployments/webstatus' ExecKube -cmd 'rollout resume deployments/webspa' -ExecKube -cmd 'rollout resume deployments/orderingbackground' +ExecKube -cmd 'rollout resume deployments/mobileshoppingagg' +ExecKube -cmd 'rollout resume deployments/webshoppingagg' +ExecKube -cmd 'rollout resume deployments/apigwmm' +ExecKube -cmd 'rollout resume deployments/apigwms' +ExecKube -cmd 'rollout resume deployments/apigwwm' +ExecKube -cmd 'rollout resume deployments/apigwws' Write-Host "WebSPA is exposed at http://$externalDns, WebMVC at http://$externalDns/webmvc, WebStatus at http://$externalDns/webstatus" -ForegroundColor Yellow diff --git a/k8s/deployments.yaml b/k8s/deployments.yaml index 034842f8c..a7f2f8d37 100644 --- a/k8s/deployments.yaml +++ b/k8s/deployments.yaml @@ -21,32 +21,32 @@ spec: valueFrom: configMapKeyRef: name: externalcfg - key: BasketRedisConStr + key: basket__ConnectionString - name: EventBusConnection valueFrom: configMapKeyRef: name: externalcfg - key: BasketBus + key: all__EventBusConnection - name: AzureServiceBusEnabled valueFrom: configMapKeyRef: name: externalcfg - key: UseAzureServiceBus + key: all__UseAzureServiceBus - name: ApplicationInsights__InstrumentationKey valueFrom: configMapKeyRef: name: externalcfg - key: Instrumentation_Key + key: all__InstrumentationKey - name: IdentityUrl valueFrom: configMapKeyRef: name: urls - key: IdentityUrl + key: identity_e - name: UseLoadTest valueFrom: configMapKeyRef: name: externalcfg - key: EnableLoadTest + key: all__EnableLoadTest - name: OrchestratorType value: 'K8S' ports: @@ -56,15 +56,8 @@ spec: path: /hc port: 80 scheme: HTTP - initialDelaySeconds: 60 - periodSeconds: 60 - livenessProbe: - httpGet: - path: /liveness - port: 80 - scheme: HTTP - initialDelaySeconds: 120 - periodSeconds: 60 + initialDelaySeconds: 300 + periodSeconds: 240 imagePullSecrets: - name: registry-key --- @@ -91,7 +84,7 @@ spec: valueFrom: configMapKeyRef: name: externalcfg - key: CatalogSqlDb + key: catalog__ConnectionString - name: PicBaseUrl valueFrom: configMapKeyRef: @@ -101,17 +94,17 @@ spec: valueFrom: configMapKeyRef: name: externalcfg - key: CatalogAzureStorageEnabled + key: catalog__AzureStorageEnabled - name: EventBusConnection valueFrom: configMapKeyRef: name: externalcfg - key: CatalogBus + key: all__EventBusConnection - name: ApplicationInsights__InstrumentationKey valueFrom: configMapKeyRef: name: externalcfg - key: Instrumentation_Key + key: all__InstrumentationKey - name: OrchestratorType value: 'K8S' ports: @@ -121,15 +114,8 @@ spec: path: /hc port: 80 scheme: HTTP - initialDelaySeconds: 60 - periodSeconds: 60 - livenessProbe: - httpGet: - path: /liveness - port: 80 - scheme: HTTP - initialDelaySeconds: 120 - periodSeconds: 60 + initialDelaySeconds: 300 + periodSeconds: 240 imagePullSecrets: - name: registry-key --- @@ -156,7 +142,7 @@ spec: valueFrom: configMapKeyRef: name: externalcfg - key: IdentitySqlDb + key: identity__ConnectionString - name: DPConnectionString valueFrom: configMapKeyRef: @@ -168,37 +154,52 @@ spec: valueFrom: configMapKeyRef: name: urls - key: MvcClientExternalUrl + key: mvc_e - name: SpaClient valueFrom: configMapKeyRef: name: urls - key: SpaClientExternalUrl + key: spa_e - name: LocationApiClient valueFrom: configMapKeyRef: name: urls - key: LocationApiClient + key: locations_e - name: MarketingApiClient valueFrom: configMapKeyRef: name: urls - key: MarketingApiClient + key: marketing_e - name: BasketApiClient valueFrom: configMapKeyRef: name: urls - key: BasketApiClient + key: basket_e - name: OrderingApiClient valueFrom: configMapKeyRef: name: urls - key: OrderingApiClient + key: ordering_e + - name: MobileShoppingAggClient + valueFrom: + configMapKeyRef: + name: urls + key: mobileshoppingagg_e + - name: WebShoppingAggClient + valueFrom: + configMapKeyRef: + name: urls + key: webshoppingagg_e + - name: XamarinCallback + valueFrom: + configMapKeyRef: + name: urls + key: xamarin_callback_e - name: ApplicationInsights__InstrumentationKey valueFrom: configMapKeyRef: name: externalcfg - key: Instrumentation_Key + key: all__InstrumentationKey - name: OrchestratorType value: 'K8S' ports: @@ -208,15 +209,8 @@ spec: path: /hc port: 80 scheme: HTTP - initialDelaySeconds: 60 - periodSeconds: 60 - livenessProbe: - httpGet: - path: /liveness - port: 80 - scheme: HTTP - initialDelaySeconds: 120 - periodSeconds: 60 + initialDelaySeconds: 300 + periodSeconds: 240 imagePullSecrets: - name: registry-key --- @@ -243,107 +237,42 @@ spec: valueFrom: configMapKeyRef: name: externalcfg - key: OrderingSqlDb + key: ordering__ConnectionString - name: EventBusConnection valueFrom: configMapKeyRef: name: externalcfg - key: OrderingBus + key: all__EventBusConnection - name: AzureServiceBusEnabled valueFrom: configMapKeyRef: name: externalcfg - key: UseAzureServiceBus + key: all__UseAzureServiceBus - name: IdentityUrl valueFrom: configMapKeyRef: name: urls - key: IdentityUrl - - name: ApplicationInsights__InstrumentationKey - valueFrom: - configMapKeyRef: - name: externalcfg - key: Instrumentation_Key - - name: UseLoadTest - valueFrom: - configMapKeyRef: - name: externalcfg - key: EnableLoadTest - - name: OrchestratorType - value: 'K8S' - ports: - - containerPort: 80 - readinessProbe: - httpGet: - path: /hc - port: 80 - scheme: HTTP - initialDelaySeconds: 60 - periodSeconds: 60 - livenessProbe: - httpGet: - path: /liveness - port: 80 - scheme: HTTP - initialDelaySeconds: 120 - periodSeconds: 60 - imagePullSecrets: - - name: registry-key ---- -apiVersion: extensions/v1beta1 -kind: Deployment -metadata: - name: orderingbackground -spec: - paused: true - template: - metadata: - labels: - app: eshop - component: orderingbackground - spec: - containers: - - name: orderingbackground - image: eshop/ordering.backgroundtasks - imagePullPolicy: Always - env: - - name: PATH_BASE - value: /ordering-backgroundtasks - - name: ConnectionString - valueFrom: - configMapKeyRef: - name: externalcfg - key: OrderingSqlDb - - name: EventBusConnection - valueFrom: - configMapKeyRef: - name: externalcfg - key: OrderingBus - - name: AzureServiceBusEnabled - valueFrom: - configMapKeyRef: - name: externalcfg - key: UseAzureServiceBus + key: identity_e - name: CheckUpdateTime valueFrom: configMapKeyRef: name: externalcfg - key: GracePeriodManager_CheckUpdateTime + key: GracePeriodManager__CheckUpdateTime - name: GracePeriodTime valueFrom: configMapKeyRef: name: externalcfg - key: GracePeriodManager_GracePeriodTime + key: GracePeriodManager__GracePeriodTime - name: ApplicationInsights__InstrumentationKey valueFrom: configMapKeyRef: name: externalcfg - key: Instrumentation_Key + key: all__InstrumentationKey - name: UseLoadTest valueFrom: configMapKeyRef: name: externalcfg - key: EnableLoadTest + key: all__EnableLoadTest - name: OrchestratorType value: 'K8S' ports: @@ -353,15 +282,8 @@ spec: path: /hc port: 80 scheme: HTTP - initialDelaySeconds: 60 - periodSeconds: 60 - livenessProbe: - httpGet: - path: /liveness - port: 80 - scheme: HTTP - initialDelaySeconds: 120 - periodSeconds: 60 + initialDelaySeconds: 300 + periodSeconds: 240 imagePullSecrets: - name: registry-key --- @@ -388,42 +310,42 @@ spec: valueFrom: configMapKeyRef: name: externalcfg - key: LocationsNoSqlDb + key: locations__ConnectionString - name: Database valueFrom: configMapKeyRef: name: externalcfg - key: LocationsNoSqlDbName + key: locations__Database - name: AzureServiceBusEnabled valueFrom: configMapKeyRef: name: externalcfg - key: UseAzureServiceBus + key: all__UseAzureServiceBus - name: EventBusConnection valueFrom: configMapKeyRef: name: externalcfg - key: LocationsBus + key: all__EventBusConnection - name: IdentityUrl valueFrom: configMapKeyRef: - name: urls - key: IdentityUrl + name: internalurls + key: identity - name: IdentityUrlExternal valueFrom: configMapKeyRef: name: urls - key: IdentityUrl + key: identity_e - name: ApplicationInsights__InstrumentationKey valueFrom: configMapKeyRef: name: externalcfg - key: Instrumentation_Key + key: all__InstrumentationKey - name: UseLoadTest valueFrom: configMapKeyRef: name: externalcfg - key: EnableLoadTest + key: all__EnableLoadTest - name: OrchestratorType value: 'K8S' ports: @@ -433,15 +355,8 @@ spec: path: /hc port: 80 scheme: HTTP - initialDelaySeconds: 50 - periodSeconds: 60 - livenessProbe: - httpGet: - path: /liveness - port: 80 - scheme: HTTP - initialDelaySeconds: 120 - periodSeconds: 60 + initialDelaySeconds: 300 + periodSeconds: 240 imagePullSecrets: - name: registry-key --- @@ -468,37 +383,37 @@ spec: valueFrom: configMapKeyRef: name: externalcfg - key: MarketingSqlDb + key: marketing__ConnectionString - name: MongoConnectionString valueFrom: configMapKeyRef: name: externalcfg - key: MarketingNoSqlDb + key: marketing__MongoConnectionString - name: MongoDatabase valueFrom: configMapKeyRef: name: externalcfg - key: MarketingNoSqlDbName + key: marketing__MongoDatabase - name: AzureServiceBusEnabled valueFrom: configMapKeyRef: name: externalcfg - key: UseAzureServiceBus + key: all__UseAzureServiceBus - name: EventBusConnection valueFrom: configMapKeyRef: name: externalcfg - key: MarketingBus + key: all__EventBusConnection - name: IdentityUrl valueFrom: configMapKeyRef: - name: urls - key: IdentityUrl + name: internalurls + key: identity - name: IdentityUrlExternal valueFrom: configMapKeyRef: name: urls - key: IdentityUrl + key: identity_e - name: PicBaseUrl valueFrom: configMapKeyRef: @@ -508,12 +423,12 @@ spec: valueFrom: configMapKeyRef: name: externalcfg - key: Instrumentation_Key + key: all__InstrumentationKey - name: UseLoadTest valueFrom: configMapKeyRef: name: externalcfg - key: EnableLoadTest + key: all__EnableLoadTest - name: OrchestratorType value: 'K8S' ports: @@ -523,15 +438,8 @@ spec: path: /hc port: 80 scheme: HTTP - initialDelaySeconds: 60 - periodSeconds: 60 - livenessProbe: - httpGet: - path: /liveness - port: 80 - scheme: HTTP - initialDelaySeconds: 120 - periodSeconds: 60 + initialDelaySeconds: 300 + periodSeconds: 240 imagePullSecrets: - name: registry-key --- @@ -558,17 +466,17 @@ spec: valueFrom: configMapKeyRef: name: externalcfg - key: UseAzureServiceBus + key: all__UseAzureServiceBus - name: EventBusConnection valueFrom: configMapKeyRef: name: externalcfg - key: PaymentBus + key: all__EventBusConnection - name: ApplicationInsights__InstrumentationKey valueFrom: configMapKeyRef: name: externalcfg - key: Instrumentation_Key + key: all__InstrumentationKey - name: OrchestratorType value: 'K8S' ports: @@ -578,15 +486,8 @@ spec: path: /hc port: 80 scheme: HTTP - initialDelaySeconds: 60 - periodSeconds: 60 - livenessProbe: - httpGet: - path: /liveness - port: 80 - scheme: HTTP - initialDelaySeconds: 120 - periodSeconds: 60 + initialDelaySeconds: 300 + periodSeconds: 240 imagePullSecrets: - name: registry-key --- @@ -616,81 +517,66 @@ spec: key: keystore - name: IsClusterEnv value: 'True' - - name: BasketUrl + - name: PurchaseUrl valueFrom: configMapKeyRef: - name: urls - key: MvcClientBasketUrl + name: internalurls + key: apigwws - name: CallBackUrl valueFrom: configMapKeyRef: name: urls - key: MvcClientExternalUrl - - name: LocationsUrl - valueFrom: - configMapKeyRef: - name: urls - key: MvcClientLocationsUrl - - name: CatalogUrl - valueFrom: - configMapKeyRef: - name: urls - key: MvcClientCatalogUrl + key: mvc_e - name: IdentityUrl valueFrom: configMapKeyRef: name: urls - key: IdentityUrl - - name: OrderingUrl - valueFrom: - configMapKeyRef: - name: urls - key: MvcClientOrderingUrl + key: identity_e - name: MarketingUrl valueFrom: configMapKeyRef: - name: urls - key: MvcClientMarketingUrl + name: internalurls + key: apigwwm - name: BasketUrlHC valueFrom: configMapKeyRef: - name: urls - key: BasketHealthCheckUrl + name: internalurls + key: basket__hc - name: CatalogUrlHC valueFrom: configMapKeyRef: - name: urls - key: CatalogHealthCheckUrl + name: internalurls + key: catalog__hc - name: IdentityUrlHC valueFrom: configMapKeyRef: - name: urls - key: IdentityHealthCheckUrl + name: internalurls + key: identity__hc - name: OrderingUrlHC valueFrom: configMapKeyRef: - name: urls - key: OrderingHealthCheckUrl + name: internalurls + key: ordering__hc - name: MarketingUrlHC valueFrom: configMapKeyRef: - name: urls - key: MarketingHealthCheckUrl + name: internalurls + key: marketing__hc - name: PaymentUrlHC valueFrom: configMapKeyRef: - name: urls - key: PaymentHealthCheckUrl + name: internalurls + key: payment__hc - name: ApplicationInsights__InstrumentationKey valueFrom: configMapKeyRef: name: externalcfg - key: Instrumentation_Key + key: all__InstrumentationKey - name: UseLoadTest valueFrom: configMapKeyRef: name: externalcfg - key: EnableLoadTest + key: all__EnableLoadTest - name: OrchestratorType value: 'K8S' ports: @@ -700,15 +586,8 @@ spec: path: /hc port: 80 scheme: HTTP - initialDelaySeconds: 60 - periodSeconds: 60 - livenessProbe: - httpGet: - path: /liveness - port: 80 - scheme: HTTP - initialDelaySeconds: 120 - periodSeconds: 60 + initialDelaySeconds: 300 + periodSeconds: 240 imagePullSecrets: - name: registry-key --- @@ -734,53 +613,53 @@ spec: - name: BasketUrl valueFrom: configMapKeyRef: - name: urls - key: BasketHealthCheckUrl + name: internalurls + key: basket__hc - name: CatalogUrl valueFrom: configMapKeyRef: - name: urls - key: CatalogHealthCheckUrl + name: internalurls + key: catalog__hc - name: IdentityUrl valueFrom: configMapKeyRef: - name: urls - key: IdentityHealthCheckUrl + name: internalurls + key: identity__hc - name: OrderingUrl valueFrom: configMapKeyRef: - name: urls - key: OrderingHealthCheckUrl + name: internalurls + key: ordering__hc - name: LocationsUrl valueFrom: configMapKeyRef: - name: urls - key: LocationsHealthCheckUrl + name: internalurls + key: locations__hc - name: MarketingUrl valueFrom: configMapKeyRef: - name: urls - key: MarketingHealthCheckUrl + name: internalurls + key: marketing__hc - name: mvc valueFrom: configMapKeyRef: - name: urls - key: WebMvcHealthCheckUrl + name: internalurls + key: mvc__hc - name: spa valueFrom: configMapKeyRef: - name: urls - key: WebSpaHealthCheckUrl + name: internalurls + key: spa__hc - name: PaymentUrl valueFrom: configMapKeyRef: - name: urls - key: PaymentHealthCheckUrl + name: internalurls + key: payment__hc - name: ApplicationInsights__InstrumentationKey valueFrom: configMapKeyRef: name: externalcfg - key: Instrumentation_Key + key: all__InstrumentationKey - name: OrchestratorType value: 'K8S' ports: @@ -814,76 +693,61 @@ spec: key: keystore - name: IsClusterEnv value: 'True' - - name: BasketUrl + - name: PurchaseUrl valueFrom: configMapKeyRef: name: urls - key: SpaClientBasketExternalUrl + key: webshoppingapigw_e - name: CallBackUrl valueFrom: configMapKeyRef: name: urls - key: SpaClientExternalUrl - - name: CatalogUrl - valueFrom: - configMapKeyRef: - name: urls - key: SpaClientCatalogExternalUrl + key: spa_e - name: IdentityUrl valueFrom: configMapKeyRef: name: urls - key: SpaClientIdentityExternalUrl - - name: OrderingUrl - valueFrom: - configMapKeyRef: - name: urls - key: SpaClientOrderingExternalUrl + key: identity_e - name: MarketingUrl valueFrom: configMapKeyRef: name: urls - key: SpaClientMarketingExternalUrl - - name: LocationsUrl - valueFrom: - configMapKeyRef: - name: urls - key: SpaClientLocationsUrl + key: marketingapigw_e - name: BasketUrlHC valueFrom: configMapKeyRef: - name: urls - key: BasketHealthCheckUrl + name: internalurls + key: basket__hc - name: CatalogUrlHC valueFrom: configMapKeyRef: - name: urls - key: CatalogHealthCheckUrl + name: internalurls + key: catalog__hc - name: IdentityUrlHC valueFrom: configMapKeyRef: - name: urls - key: IdentityHealthCheckUrl + name: internalurls + key: identity__hc - name: OrderingUrlHC valueFrom: configMapKeyRef: - name: urls - key: OrderingHealthCheckUrl + name: internalurls + key: ordering__hc - name: MarketingUrlHC valueFrom: configMapKeyRef: - name: urls - key: MarketingHealthCheckUrl + name: internalurls + key: marketing__hc - name: PaymentUrlHC valueFrom: configMapKeyRef: - name: urls - key: PaymentHealthCheckUrl + name: internalurls + key: payment__hc - name: ApplicationInsights__InstrumentationKey valueFrom: configMapKeyRef: name: externalcfg - key: Instrumentation_Key + key: all__InstrumentationKey - name: OrchestratorType value: 'K8S' ports: @@ -893,14 +757,96 @@ spec: path: /hc port: 80 scheme: HTTP - initialDelaySeconds: 60 - periodSeconds: 60 - livenessProbe: - httpGet: - path: /liveness - port: 80 - scheme: HTTP - initialDelaySeconds: 120 - periodSeconds: 60 + initialDelaySeconds: 300 + periodSeconds: 240 + imagePullSecrets: + - name: registry-key +--- +apiVersion: extensions/v1beta1 +kind: Deployment +metadata: + name: webshoppingagg +spec: + paused: true + template: + metadata: + labels: + app: eshop + component: webshoppingagg + spec: + containers: + - name: webshoppingagg + image: eshop/webshoppingagg + imagePullPolicy: Always + env: + - name: ASPNETCORE_URLS + value: http://0.0.0.0:80 + - name: urls__basket + valueFrom: + configMapKeyRef: + name: internalurls + key: basket + - name: urls__catalog + valueFrom: + configMapKeyRef: + name: internalurls + key: catalog + - name: urls__orders + valueFrom: + configMapKeyRef: + name: internalurls + key: ordering + - name: urls__identity + valueFrom: + configMapKeyRef: + name: internalurls + key: identity + ports: + - containerPort: 80 + imagePullSecrets: + - name: registry-key +--- +apiVersion: extensions/v1beta1 +kind: Deployment +metadata: + name: mobileshoppingagg +spec: + paused: true + template: + metadata: + labels: + app: eshop + component: mobileshoppingagg + spec: + containers: + - name: mobileshoppingagg + image: eshop/mobileshoppingagg + imagePullPolicy: Always + env: + - name: ASPNETCORE_URLS + value: http://0.0.0.0:80 + - name: urls__basket + valueFrom: + configMapKeyRef: + name: internalurls + key: basket + - name: urls__catalog + valueFrom: + configMapKeyRef: + name: internalurls + key: catalog + - name: urls__orders + valueFrom: + configMapKeyRef: + name: internalurls + key: ordering + - name: urls__identity + valueFrom: + configMapKeyRef: + name: internalurls + key: identity + ports: + - containerPort: 80 imagePullSecrets: - name: registry-key +--- diff --git a/k8s/frontend.yaml b/k8s/frontend.yaml deleted file mode 100644 index bd244beb2..000000000 --- a/k8s/frontend.yaml +++ /dev/null @@ -1,47 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - labels: - app: eshop - component: frontend - name: frontend -spec: - ports: - - port: 80 - targetPort: 8080 - selector: - app: eshop - component: frontend - type: LoadBalancer ---- -apiVersion: extensions/v1beta1 -kind: Deployment -metadata: - name: frontend -spec: - template: - metadata: - labels: - app: eshop - component: frontend - spec: - containers: - - name: nginx - image: nginx:1.13.8-alpine - imagePullPolicy: IfNotPresent - ports: - - containerPort: 8080 - lifecycle: - preStop: - exec: - command: ["/usr/sbin/nginx","-s","quit"] - volumeMounts: - - name: config - mountPath: /etc/nginx - volumes: - - name: config - configMap: - name: config-files - items: - - key: nginx-conf - path: nginx.conf diff --git a/k8s/gen-k8s-env-aks.ps1 b/k8s/gen-k8s-env-aks.ps1 index a22588fa1..ef36a390d 100644 --- a/k8s/gen-k8s-env-aks.ps1 +++ b/k8s/gen-k8s-env-aks.ps1 @@ -3,11 +3,9 @@ [parameter(Mandatory=$true)][string]$location, [parameter(Mandatory=$false)][string]$registryName, [parameter(Mandatory=$true)][string]$serviceName, - [parameter(Mandatory=$true)][string]$dnsName, [parameter(Mandatory=$true)][string]$createAcr=$true, - [parameter(Mandatory=$false)][int]$nodeCount=2, - [parameter(Mandatory=$false)][string]$nodeVMSize="Standard_D2_v2", - [parameter(Mandatory=$false)][string]$kubernetesVersion="1.7.7" + [parameter(Mandatory=$false)][int]$nodeCount=3, + [parameter(Mandatory=$false)][string]$nodeVMSize="Standard_D2_v2" ) # Create resource group @@ -22,12 +20,12 @@ if ($createAcr -eq $true) { # Create kubernetes orchestrator Write-Host "Creating kubernetes orchestrator..." -ForegroundColor Yellow -az aks create --resource-group=$resourceGroupName --name=$serviceName --dns-name-prefix=$dnsName --generate-ssh-keys --node-count=$nodeCount --node-vm-size=$nodeVMSize --kubernetes-version $kubernetesVersion +az aks create --resource-group=$resourceGroupName --name=$serviceName --generate-ssh-keys --node-count=$nodeCount --node-vm-size=$nodeVMSize -# Retrieve kubernetes cluster configuration and save it under ~/.kube/config +# Retrieve kubernetes cluster configuration and save it under ~/.kube/config az aks get-credentials --resource-group=$resourceGroupName --name=$serviceName if ($createAcr -eq $true) { # Show ACR credentials az acr credential show -n $registryName -} \ No newline at end of file +} diff --git a/k8s/ingress.yaml b/k8s/ingress.yaml index 3c2fe8bad..b5773bb25 100644 --- a/k8s/ingress.yaml +++ b/k8s/ingress.yaml @@ -11,22 +11,10 @@ spec: rules: - http: paths: - - path: /basket-api - backend: - serviceName: basket - servicePort: 80 - - path: /catalog-api - backend: - serviceName: catalog - servicePort: 80 - path: /identity backend: serviceName: identity servicePort: 80 - - path: /ordering-api - backend: - serviceName: ordering - servicePort: 80 - path: /webmvc backend: serviceName: webmvc @@ -35,21 +23,37 @@ spec: backend: serviceName: webstatus servicePort: 80 - - path: /marketing-api + - path: /webshoppingapigw + backend: + serviceName: ocelotapigw-ws + servicePort: 80 + - path: /webmarketingapigw backend: - serviceName: marketing + serviceName: ocelotapigw-wm servicePort: 80 - - path: /payment-api + - path: /mobilemarketingapigw backend: - serviceName: payment + serviceName: ocelotapigw-mm + servicePort: 80 + - path: /mobileshoppingapigw + backend: + serviceName: ocelotapigw-ms + servicePort: 80 + - path: /webshoppingagg + backend: + serviceName: webshoppingagg servicePort: 80 - - path: /locations-api + - path: /mobileshoppingagg backend: - serviceName: locations + serviceName: mobileshoppingagg servicePort: 80 + - path: /payment-api + backend: + serviceName: payment + servicePort: 80 - path: / backend: serviceName: webspa servicePort: 80 - + diff --git a/k8s/internalurls.yaml b/k8s/internalurls.yaml new file mode 100644 index 000000000..e42ef23ec --- /dev/null +++ b/k8s/internalurls.yaml @@ -0,0 +1,31 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: internalurls + labels: + app: eshop +data: +# Internal Services & healthchecks + basket: http://basket + basket__hc: http://basket/hc + catalog: http://catalog + catalog__hc: http://catalog/hc + identity: http://identity + identity__hc: http://identity/hc + ordering: http://ordering + ordering__hc: http://ordering/hc + marketing: http://marketing + marketing__hc: http://marketing/hc + locations: http://locations + locations__hc: http://locations/hc + payment__hc: http://payment/hc + mvc__hc: http://webmvc/hc + spa__hc: http://webspa/hc +# Aggreggators + mobileshoppingagg: http://mobileshoppingagg + webshoppingagg: http://webshoppingagg +# API GWs + apigwmm: http://ocelotapigw-mm + apigwms: http://ocelotapigw-ms + apigwwm: http://ocelotapigw-wm + apigwws: http://ocelotapigw-ws \ No newline at end of file diff --git a/k8s/ocelot/configuration-mobile-marketing.json b/k8s/ocelot/configuration-mobile-marketing.json new file mode 100644 index 000000000..666df1633 --- /dev/null +++ b/k8s/ocelot/configuration-mobile-marketing.json @@ -0,0 +1,34 @@ +{ + "ReRoutes": [ + { + "DownstreamPathTemplate": "/api/{version}/{everything}", + "DownstreamScheme": "http", + "DownstreamHostAndPorts": [ + { + "Host": "marketing", + "Port": 80 + } + ], + "UpstreamPathTemplate": "/api/{version}/m/{everything}", + "UpstreamHttpMethod": [] + }, + { + "DownstreamPathTemplate": "/api/{version}/{everything}", + "DownstreamScheme": "http", + "DownstreamHostAndPorts": [ + { + "Host": "locations", + "Port": 80 + } + ], + "UpstreamPathTemplate": "/api/{version}/l/{everything}", + "UpstreamHttpMethod": [] + } + + ], + "GlobalConfiguration": { + "RequestIdKey": "OcRequestId", + "AdministrationPath": "/administration" + } +} + \ No newline at end of file diff --git a/k8s/ocelot/configuration-mobile-shopping.json b/k8s/ocelot/configuration-mobile-shopping.json new file mode 100644 index 000000000..cf3a48aff --- /dev/null +++ b/k8s/ocelot/configuration-mobile-shopping.json @@ -0,0 +1,142 @@ +{ + "ReRoutes": [ + { + "DownstreamPathTemplate": "/api/{version}/{everything}", + "DownstreamScheme": "http", + "DownstreamHostAndPorts": [ + { + "Host": "catalog", + "Port": 80 + } + ], + "UpstreamPathTemplate": "/api/{version}/c/{everything}", + "UpstreamHttpMethod": [ "GET" ] + }, + { + "DownstreamPathTemplate": "/api/{version}/{everything}", + "DownstreamScheme": "http", + "DownstreamHostAndPorts": [ + { + "Host": "basket", + "Port": 80 + } + ], + "UpstreamPathTemplate": "/api/{version}/b/{everything}", + "UpstreamHttpMethod": [], + "AuthenticationOptions": { + "AuthenticationProviderKey": "IdentityApiKey", + "AllowedScopes": [] + } + }, + { + "DownstreamPathTemplate": "/api/{version}/{everything}", + "DownstreamScheme": "http", + "DownstreamHostAndPorts": [ + { + "Host": "ordering", + "Port": 80 + } + ], + "UpstreamPathTemplate": "/api/{version}/o/{everything}", + "UpstreamHttpMethod": [], + "AuthenticationOptions": { + "AuthenticationProviderKey": "IdentityApiKey", + "AllowedScopes": [] + } + }, + { + "DownstreamPathTemplate": "/{everything}", + "DownstreamScheme": "http", + "DownstreamHostAndPorts": [ + { + "Host": "mobileshoppingagg", + "Port": 80 + } + ], + "UpstreamPathTemplate": "/{everything}", + "UpstreamHttpMethod": [ "POST", "PUT", "GET" ], + "AuthenticationOptions": { + "AuthenticationProviderKey": "IdentityApiKey", + "AllowedScopes": [] + } + }, + { + "DownstreamPathTemplate": "/{everything}", + "DownstreamScheme": "http", + "DownstreamHostAndPorts": [ + { + "Host": "ordering", + "Port": 80 + } + ], + "UpstreamPathTemplate": "/orders-api/{everything}", + "UpstreamHttpMethod": [] + }, + { + "DownstreamPathTemplate": "/{everything}", + "DownstreamScheme": "http", + "DownstreamHostAndPorts": [ + { + "Host": "basket", + "Port": 80 + } + ], + "UpstreamPathTemplate": "/basket-api/{everything}", + "UpstreamHttpMethod": [] + }, + { + "DownstreamPathTemplate": "/{everything}", + "DownstreamScheme": "http", + "DownstreamHostAndPorts": [ + { + "Host": "catalog", + "Port": 80 + } + ], + "UpstreamPathTemplate": "/catalog-api/{everything}", + "UpstreamHttpMethod": [] + }, + { + "DownstreamPathTemplate": "/{everything}", + "DownstreamScheme": "http", + "DownstreamHostAndPorts": [ + { + "Host": "marketing", + "Port": 80 + } + ], + "UpstreamPathTemplate": "/marketing-api/{everything}", + "UpstreamHttpMethod": [] + }, + { + "DownstreamPathTemplate": "/{everything}", + "DownstreamScheme": "http", + "DownstreamHostAndPorts": [ + { + "Host": "payment", + "Port": 80 + } + ], + "UpstreamPathTemplate": "/payment-api/{everything}", + "UpstreamHttpMethod": [] + }, + { + "DownstreamPathTemplate": "/{everything}", + "DownstreamScheme": "http", + "DownstreamHostAndPorts": [ + { + "Host": "locations.api", + "Port": 80 + } + ], + "UpstreamPathTemplate": "/location-api/{everything}", + "UpstreamHttpMethod": [] + } + + ], + "GlobalConfiguration": { + "RequestIdKey": "OcRequestId", + "AdministrationPath": "/administration" + } + } + \ No newline at end of file diff --git a/k8s/ocelot/configuration-web-marketing.json b/k8s/ocelot/configuration-web-marketing.json new file mode 100644 index 000000000..666df1633 --- /dev/null +++ b/k8s/ocelot/configuration-web-marketing.json @@ -0,0 +1,34 @@ +{ + "ReRoutes": [ + { + "DownstreamPathTemplate": "/api/{version}/{everything}", + "DownstreamScheme": "http", + "DownstreamHostAndPorts": [ + { + "Host": "marketing", + "Port": 80 + } + ], + "UpstreamPathTemplate": "/api/{version}/m/{everything}", + "UpstreamHttpMethod": [] + }, + { + "DownstreamPathTemplate": "/api/{version}/{everything}", + "DownstreamScheme": "http", + "DownstreamHostAndPorts": [ + { + "Host": "locations", + "Port": 80 + } + ], + "UpstreamPathTemplate": "/api/{version}/l/{everything}", + "UpstreamHttpMethod": [] + } + + ], + "GlobalConfiguration": { + "RequestIdKey": "OcRequestId", + "AdministrationPath": "/administration" + } +} + \ No newline at end of file diff --git a/k8s/ocelot/configuration-web-shopping.json b/k8s/ocelot/configuration-web-shopping.json new file mode 100644 index 000000000..edf0714a0 --- /dev/null +++ b/k8s/ocelot/configuration-web-shopping.json @@ -0,0 +1,142 @@ +{ + "ReRoutes": [ + { + "DownstreamPathTemplate": "/api/{version}/{everything}", + "DownstreamScheme": "http", + "DownstreamHostAndPorts": [ + { + "Host": "catalog", + "Port": 80 + } + ], + "UpstreamPathTemplate": "/api/{version}/c/{everything}", + "UpstreamHttpMethod": [ "GET" ] + }, + { + "DownstreamPathTemplate": "/api/{version}/{everything}", + "DownstreamScheme": "http", + "DownstreamHostAndPorts": [ + { + "Host": "basket", + "Port": 80 + } + ], + "UpstreamPathTemplate": "/api/{version}/b/{everything}", + "UpstreamHttpMethod": [], + "AuthenticationOptions": { + "AuthenticationProviderKey": "IdentityApiKey", + "AllowedScopes": [] + } + }, + { + "DownstreamPathTemplate": "/api/{version}/{everything}", + "DownstreamScheme": "http", + "DownstreamHostAndPorts": [ + { + "Host": "ordering", + "Port": 80 + } + ], + "UpstreamPathTemplate": "/api/{version}/o/{everything}", + "UpstreamHttpMethod": [], + "AuthenticationOptions": { + "AuthenticationProviderKey": "IdentityApiKey", + "AllowedScopes": [] + } + }, + { + "DownstreamPathTemplate": "/{everything}", + "DownstreamScheme": "http", + "DownstreamHostAndPorts": [ + { + "Host": "webshoppingagg", + "Port": 80 + } + ], + "UpstreamPathTemplate": "/{everything}", + "UpstreamHttpMethod": [ "POST", "PUT", "GET" ], + "AuthenticationOptions": { + "AuthenticationProviderKey": "IdentityApiKey", + "AllowedScopes": [] + } + }, + { + "DownstreamPathTemplate": "/{everything}", + "DownstreamScheme": "http", + "DownstreamHostAndPorts": [ + { + "Host": "ordering", + "Port": 80 + } + ], + "UpstreamPathTemplate": "/orders-api/{everything}", + "UpstreamHttpMethod": [] + }, + { + "DownstreamPathTemplate": "/{everything}", + "DownstreamScheme": "http", + "DownstreamHostAndPorts": [ + { + "Host": "basket", + "Port": 80 + } + ], + "UpstreamPathTemplate": "/basket-api/{everything}", + "UpstreamHttpMethod": [] + }, + { + "DownstreamPathTemplate": "/{everything}", + "DownstreamScheme": "http", + "DownstreamHostAndPorts": [ + { + "Host": "catalog", + "Port": 80 + } + ], + "UpstreamPathTemplate": "/catalog-api/{everything}", + "UpstreamHttpMethod": [] + }, + { + "DownstreamPathTemplate": "/{everything}", + "DownstreamScheme": "http", + "DownstreamHostAndPorts": [ + { + "Host": "marketing", + "Port": 80 + } + ], + "UpstreamPathTemplate": "/marketing-api/{everything}", + "UpstreamHttpMethod": [] + }, + { + "DownstreamPathTemplate": "/{everything}", + "DownstreamScheme": "http", + "DownstreamHostAndPorts": [ + { + "Host": "payment", + "Port": 80 + } + ], + "UpstreamPathTemplate": "/payment-api/{everything}", + "UpstreamHttpMethod": [] + }, + { + "DownstreamPathTemplate": "/{everything}", + "DownstreamScheme": "http", + "DownstreamHostAndPorts": [ + { + "Host": "locations.api", + "Port": 80 + } + ], + "UpstreamPathTemplate": "/location-api/{everything}", + "UpstreamHttpMethod": [] + } + + ], + "GlobalConfiguration": { + "RequestIdKey": "OcRequestId", + "AdministrationPath": "/administration" + } + } + \ No newline at end of file diff --git a/k8s/ocelot/deployment.yaml b/k8s/ocelot/deployment.yaml new file mode 100644 index 000000000..516f91b2f --- /dev/null +++ b/k8s/ocelot/deployment.yaml @@ -0,0 +1,155 @@ +apiVersion: extensions/v1beta1 +kind: Deployment +metadata: + name: apigwmm +spec: + paused: true + template: + metadata: + labels: + app: eshop + component: apigwmm + spec: + containers: + - name: apigwmm + image: eshop/ocelotapigw-mm + imagePullPolicy: Always + env: + - name: PATH_BASE + value: /mobilemarketingapigw + - name: IdentityUrl + valueFrom: + configMapKeyRef: + name: internalurls + key: identity + ports: + - containerPort: 80 + volumeMounts: + - name: config + mountPath: /app/configuration + volumes: + - name: config + configMap: + name: ocelot + items: + - key: mm + path: configuration.json + imagePullSecrets: + - name: registry-key +--- +apiVersion: extensions/v1beta1 +kind: Deployment +metadata: + name: apigwms +spec: + paused: true + template: + metadata: + labels: + app: eshop + component: apigwms + spec: + containers: + - name: apigwms + image: eshop/ocelotapigw-ms + imagePullPolicy: Always + env: + - name: PATH_BASE + value: /mobileshoppingapigw + - name: IdentityUrl + valueFrom: + configMapKeyRef: + name: internalurls + key: identity + ports: + - containerPort: 80 + volumeMounts: + - name: config + mountPath: /app/configuration + volumes: + - name: config + configMap: + name: ocelot + items: + - key: ms + path: configuration.json + imagePullSecrets: + - name: registry-key +--- +apiVersion: extensions/v1beta1 +kind: Deployment +metadata: + name: apigwwm +spec: + paused: true + template: + metadata: + labels: + app: eshop + component: apigwwm + spec: + containers: + - name: apigwwm + image: eshop/ocelotapigw-wm + imagePullPolicy: Always + env: + - name: PATH_BASE + value: /webmarketingapigw + - name: IdentityUrl + valueFrom: + configMapKeyRef: + name: internalurls + key: identity + ports: + - containerPort: 80 + volumeMounts: + - name: config + mountPath: /app/configuration + volumes: + - name: config + configMap: + name: ocelot + items: + - key: wm + path: configuration.json + imagePullSecrets: + - name: registry-key +--- +apiVersion: extensions/v1beta1 +kind: Deployment +metadata: + name: apigwws +spec: + paused: true + template: + metadata: + labels: + app: eshop + component: apigwws + spec: + containers: + - name: apigwws + image: eshop/ocelotapigw-ws + imagePullPolicy: Always + env: + - name: PATH_BASE + value: /webshoppingapigw + - name: IdentityUrl + valueFrom: + configMapKeyRef: + name: internalurls + key: identity + ports: + - containerPort: 80 + volumeMounts: + - name: config + mountPath: /app/configuration + volumes: + - name: config + configMap: + name: ocelot + items: + - key: ws + path: configuration.json + imagePullSecrets: + - name: registry-key \ No newline at end of file diff --git a/k8s/ocelot/service.yaml b/k8s/ocelot/service.yaml new file mode 100644 index 000000000..858b54b21 --- /dev/null +++ b/k8s/ocelot/service.yaml @@ -0,0 +1,55 @@ +apiVersion: v1 +kind: Service +metadata: + labels: + app: eshop + component: ocelotapigw-mm + name: ocelotapigw-mm +spec: + ports: + - port: 80 + selector: + app: eshop + component: apigwmm +--- +apiVersion: v1 +kind: Service +metadata: + labels: + app: eshop + component: ocelotapigw-ms + name: ocelotapigw-ms +spec: + ports: + - port: 80 + selector: + app: eshop + component: apigwms +--- +apiVersion: v1 +kind: Service +metadata: + labels: + app: eshop + component: ocelotapigw-wm + name: ocelotapigw-wm +spec: + ports: + - port: 80 + selector: + app: eshop + component: apigwwm +--- +apiVersion: v1 +kind: Service +metadata: + labels: + app: eshop + component: ocelotapigw-ws + name: ocelotapigw-ws +spec: + ports: + - port: 80 + selector: + app: eshop + component: apigwws diff --git a/k8s/services.yaml b/k8s/services.yaml index 805d3dc85..f7e5f2e45 100644 --- a/k8s/services.yaml +++ b/k8s/services.yaml @@ -112,6 +112,34 @@ spec: --- apiVersion: v1 kind: Service +metadata: + labels: + app: eshop + component: webshoppingagg + name: webshoppingagg +spec: + ports: + - port: 80 + selector: + app: eshop + component: webshoppingagg +--- +apiVersion: v1 +kind: Service +metadata: + labels: + app: eshop + component: mobileshoppingagg + name: mobileshoppingagg +spec: + ports: + - port: 80 + selector: + app: eshop + component: mobileshoppingagg +--- +apiVersion: v1 +kind: Service metadata: labels: app: eshop diff --git a/src/ApiGateways/ApiGw-Base/Dockerfile b/src/ApiGateways/ApiGw-Base/Dockerfile new file mode 100644 index 000000000..f0ff49f43 --- /dev/null +++ b/src/ApiGateways/ApiGw-Base/Dockerfile @@ -0,0 +1,20 @@ +FROM microsoft/aspnetcore:2.0 AS base +WORKDIR /app +ENV ESHOP_API_GW Mobile_Bff_Shopping_ApiGw +EXPOSE 80 + +FROM microsoft/aspnetcore-build:2.0 AS build +WORKDIR /src +COPY src/ApiGateways/ApiGw-Base/OcelotApiGw.csproj src/ApiGateways/ApiGw-Base/ +RUN dotnet restore src/ApiGateways/ApiGw-Base/ +COPY . . +WORKDIR /src/src/ApiGateways/ApiGw-Base/ +RUN dotnet build -c Release -o /app + +FROM build AS publish +RUN dotnet publish -c Release -o /app + +FROM base AS final +WORKDIR /app +COPY --from=publish /app . +ENTRYPOINT ["dotnet", "OcelotApiGw.dll"] diff --git a/src/ApiGateways/ApiGw-Base/Dockerfile2 b/src/ApiGateways/ApiGw-Base/Dockerfile2 new file mode 100644 index 000000000..f127b33d1 --- /dev/null +++ b/src/ApiGateways/ApiGw-Base/Dockerfile2 @@ -0,0 +1,20 @@ +FROM microsoft/aspnetcore:2.0 AS base +WORKDIR /app +ENV ESHOP_API_GW Mobile_Bff_Marketing_ApiGw +EXPOSE 80 + +FROM microsoft/aspnetcore-build:2.0 AS build +WORKDIR /src +COPY src/ApiGateways/ApiGw-Base/OcelotApiGw.csproj src/ApiGateways/ApiGw-Base/ +RUN dotnet restore src/ApiGateways/ApiGw-Base/ +COPY . . +WORKDIR /src/src/ApiGateways/ApiGw-Base/ +RUN dotnet build -c Release -o /app + +FROM build AS publish +RUN dotnet publish -c Release -o /app + +FROM base AS final +WORKDIR /app +COPY --from=publish /app . +ENTRYPOINT ["dotnet", "OcelotApiGw.dll"] diff --git a/src/ApiGateways/ApiGw-Base/Dockerfile3 b/src/ApiGateways/ApiGw-Base/Dockerfile3 new file mode 100644 index 000000000..aff6cc920 --- /dev/null +++ b/src/ApiGateways/ApiGw-Base/Dockerfile3 @@ -0,0 +1,20 @@ +FROM microsoft/aspnetcore:2.0 AS base +WORKDIR /app +ENV ESHOP_API_GW Web_Bff_Shopping_ApiGw +EXPOSE 80 + +FROM microsoft/aspnetcore-build:2.0 AS build +WORKDIR /src +COPY src/ApiGateways/ApiGw-Base/OcelotApiGw.csproj src/ApiGateways/ApiGw-Base/ +RUN dotnet restore src/ApiGateways/ApiGw-Base/ +COPY . . +WORKDIR /src/src/ApiGateways/ApiGw-Base/ +RUN dotnet build -c Release -o /app + +FROM build AS publish +RUN dotnet publish -c Release -o /app + +FROM base AS final +WORKDIR /app +COPY --from=publish /app . +ENTRYPOINT ["dotnet", "OcelotApiGw.dll"] diff --git a/src/ApiGateways/ApiGw-Base/Dockerfile4 b/src/ApiGateways/ApiGw-Base/Dockerfile4 new file mode 100644 index 000000000..4686420d1 --- /dev/null +++ b/src/ApiGateways/ApiGw-Base/Dockerfile4 @@ -0,0 +1,20 @@ +FROM microsoft/aspnetcore:2.0 AS base +WORKDIR /app +ENV ESHOP_API_GW Web_Bff_Marketing_ApiGw +EXPOSE 80 + +FROM microsoft/aspnetcore-build:2.0 AS build +WORKDIR /src +COPY src/ApiGateways/ApiGw-Base/OcelotApiGw.csproj src/ApiGateways/ApiGw-Base/ +RUN dotnet restore src/ApiGateways/ApiGw-Base/ +COPY . . +WORKDIR /src/src/ApiGateways/ApiGw-Base/ +RUN dotnet build -c Release -o /app + +FROM build AS publish +RUN dotnet publish -c Release -o /app + +FROM base AS final +WORKDIR /app +COPY --from=publish /app . +ENTRYPOINT ["dotnet", "OcelotApiGw.dll"] diff --git a/src/ApiGateways/ApiGw-Base/OcelotApiGw.csproj b/src/ApiGateways/ApiGw-Base/OcelotApiGw.csproj new file mode 100644 index 000000000..d72d014b4 --- /dev/null +++ b/src/ApiGateways/ApiGw-Base/OcelotApiGw.csproj @@ -0,0 +1,16 @@ + + + + netcoreapp2.0 + + + + + + + + + + + + diff --git a/src/ApiGateways/ApiGw-Base/Program.cs b/src/ApiGateways/ApiGw-Base/Program.cs new file mode 100644 index 000000000..782681901 --- /dev/null +++ b/src/ApiGateways/ApiGw-Base/Program.cs @@ -0,0 +1,31 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.AspNetCore; +using Microsoft.AspNetCore.Hosting; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.DependencyInjection; + +namespace OcelotApiGw +{ + public class Program + { + public static void Main(string[] args) + { + BuildWebHost(args).Run(); + } + + public static IWebHost BuildWebHost(string[] args) + { + var builder = WebHost.CreateDefaultBuilder(args); + builder.ConfigureServices(s => s.AddSingleton(builder)) + .ConfigureAppConfiguration(ic => ic.AddJsonFile(Path.Combine("configuration", "configuration.json"))) + .UseStartup(); + var host = builder.Build(); + return host; + } + } +} diff --git a/src/ApiGateways/ApiGw-Base/Properties/launchSettings.json b/src/ApiGateways/ApiGw-Base/Properties/launchSettings.json new file mode 100644 index 000000000..2308ca466 --- /dev/null +++ b/src/ApiGateways/ApiGw-Base/Properties/launchSettings.json @@ -0,0 +1,27 @@ +{ + "iisSettings": { + "windowsAuthentication": false, + "anonymousAuthentication": true, + "iisExpress": { + "applicationUrl": "http://localhost:56755/", + "sslPort": 0 + } + }, + "profiles": { + "IIS Express": { + "commandName": "IISExpress", + "launchBrowser": true, + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "OcelotApiGw": { + "commandName": "Project", + "launchBrowser": true, + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + }, + "applicationUrl": "http://localhost:64021/" + } + } +} \ No newline at end of file diff --git a/src/ApiGateways/ApiGw-Base/Startup.cs b/src/ApiGateways/ApiGw-Base/Startup.cs new file mode 100644 index 000000000..f6a36b59e --- /dev/null +++ b/src/ApiGateways/ApiGw-Base/Startup.cs @@ -0,0 +1,91 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using CacheManager.Core; +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Hosting; +using Microsoft.AspNetCore.Http; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; +using Ocelot.DependencyInjection; +using Ocelot.Middleware; + +namespace OcelotApiGw +{ + public class Startup + { + + private readonly IConfiguration _cfg; + + public Startup(IConfiguration configuration) + { + _cfg = configuration; + } + + public void ConfigureServices(IServiceCollection services) + { + var identityUrl = _cfg.GetValue("IdentityUrl"); + var authenticationProviderKey = "IdentityApiKey"; + + services.AddCors(options => + { + options.AddPolicy("CorsPolicy", + builder => builder.AllowAnyOrigin() + .AllowAnyMethod() + .AllowAnyHeader() + .AllowCredentials()); + }); + + services.AddAuthentication() + .AddJwtBearer(authenticationProviderKey, x => + { + x.Authority = identityUrl; + x.RequireHttpsMetadata = false; + x.TokenValidationParameters = new Microsoft.IdentityModel.Tokens.TokenValidationParameters() + { + ValidAudiences = new[] { "orders", "basket", "locations", "marketing", "mobileshoppingagg", "webshoppingagg" } + }; + x.Events = new Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerEvents() + { + OnAuthenticationFailed = async ctx => + { + int i = 0; + }, + OnTokenValidated = async ctx => + { + int i = 0; + }, + + OnMessageReceived = async ctx => + { + int i = 0; + } + }; + }); + + services.AddOcelot(_cfg); + } + + public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory) + { + var pathBase = _cfg["PATH_BASE"]; + if (!string.IsNullOrEmpty(pathBase)) + { + app.UsePathBase(pathBase); + } + + if (env.IsDevelopment()) + { + app.UseDeveloperExceptionPage(); + } + + loggerFactory.AddConsole(_cfg.GetSection("Logging")); + + app.UseCors("CorsPolicy"); + + app.UseOcelot().Wait(); + } + } +} diff --git a/src/ApiGateways/ApiGw-Base/appsettings.json b/src/ApiGateways/ApiGw-Base/appsettings.json new file mode 100644 index 000000000..426750e6a --- /dev/null +++ b/src/ApiGateways/ApiGw-Base/appsettings.json @@ -0,0 +1,10 @@ +{ + "Logging": { + "IncludeScopes": true, + "LogLevel": { + "Default": "Trace", + "System": "Information", + "Microsoft": "Information" + } + } +} \ No newline at end of file diff --git a/src/ApiGateways/Mobile.Bff.Marketing/apigw/configuration.json b/src/ApiGateways/Mobile.Bff.Marketing/apigw/configuration.json new file mode 100644 index 000000000..85d6777e6 --- /dev/null +++ b/src/ApiGateways/Mobile.Bff.Marketing/apigw/configuration.json @@ -0,0 +1,34 @@ +{ + "ReRoutes": [ + { + "DownstreamPathTemplate": "/api/{version}/{everything}", + "DownstreamScheme": "http", + "DownstreamHostAndPorts": [ + { + "Host": "marketing.api", + "Port": 80 + } + ], + "UpstreamPathTemplate": "/api/{version}/m/{everything}", + "UpstreamHttpMethod": [] + }, + { + "DownstreamPathTemplate": "/api/{version}/{everything}", + "DownstreamScheme": "http", + "DownstreamHostAndPorts": [ + { + "Host": "locations.api", + "Port": 80 + } + ], + "UpstreamPathTemplate": "/api/{version}/l/{everything}", + "UpstreamHttpMethod": [] + } + + ], + "GlobalConfiguration": { + "RequestIdKey": "OcRequestId", + "AdministrationPath": "/administration" + } + } + \ No newline at end of file diff --git a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Config/UrlsConfig.cs b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Config/UrlsConfig.cs new file mode 100644 index 000000000..e920fbbb2 --- /dev/null +++ b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Config/UrlsConfig.cs @@ -0,0 +1,31 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Config +{ + public class UrlsConfig + { + public class CatalogOperations + { + public static string GetItemById(int id) => $"/api/v1/catalog/items/{id}"; + public static string GetItemsById(IEnumerable ids) => $"/api/v1/catalog/items?ids={string.Join(',', ids)}"; + } + + public class BasketOperations + { + public static string GetItemById(string id) => $"/api/v1/basket/{id}"; + public static string UpdateBasket() => "/api/v1/basket"; + } + + public class OrdersOperations + { + public static string GetOrderDraft() => "/api/v1/orders/draft"; + } + + public string Basket { get; set; } + public string Catalog { get; set; } + public string Orders { get; set; } + } +} diff --git a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Controllers/BasketController.cs b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Controllers/BasketController.cs new file mode 100644 index 000000000..702c805fb --- /dev/null +++ b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Controllers/BasketController.cs @@ -0,0 +1,133 @@ +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Mvc; +using Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Models; +using Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Services; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Controllers +{ + [Route("api/v1/[controller]")] + [Authorize] + public class BasketController : Controller + { + private readonly ICatalogService _catalog; + private readonly IBasketService _basket; + public BasketController(ICatalogService catalogService, IBasketService basketService) + { + _catalog = catalogService; + _basket = basketService; + } + + [HttpPost] + [HttpPut] + public async Task UpdateAllBasket([FromBody] UpdateBasketRequest data) + { + + if (data.Items == null || !data.Items.Any()) + { + return BadRequest("Need to pass at least one basket line"); + } + + // Retrieve the current basket + var currentBasket = await _basket.GetById(data.BuyerId); + if (currentBasket == null) + { + currentBasket = new BasketData(data.BuyerId); + } + + var catalogItems = await _catalog.GetCatalogItems(data.Items.Select(x => x.ProductId)); + var newBasket = new BasketData(data.BuyerId); + + foreach (var bitem in data.Items) + { + var catalogItem = catalogItems.SingleOrDefault(ci => ci.Id == bitem.ProductId); + if (catalogItem == null) + { + return BadRequest($"Basket refers to a non-existing catalog item ({bitem.ProductId})"); + } + + newBasket.Items.Add(new BasketDataItem() + { + Id = bitem.Id, + ProductId = catalogItem.Id.ToString(), + ProductName = catalogItem.Name, + PictureUrl = catalogItem.PictureUri, + UnitPrice = catalogItem.Price, + Quantity = bitem.Quantity + }); + } + + await _basket.Update(newBasket); + return Ok(newBasket); + } + + [HttpPut] + [Route("items")] + public async Task UpdateQuantities([FromBody] UpdateBasketItemsRequest data) + { + if (!data.Updates.Any()) + { + return BadRequest("No updates sent"); + } + + // Retrieve the current basket + var currentBasket = await _basket.GetById(data.BasketId); + if (currentBasket == null) + { + return BadRequest($"Basket with id {data.BasketId} not found."); + } + + // Update with new quantities + foreach (var update in data.Updates) + { + var basketItem = currentBasket.Items.SingleOrDefault(bitem => bitem.Id == update.BasketItemId); + if (basketItem == null) + { + return BadRequest($"Basket item with id {update.BasketItemId} not found"); + } + basketItem.Quantity = update.NewQty; + } + + // Save the updated basket + await _basket.Update(currentBasket); + return Ok(currentBasket); + } + + [HttpPost] + [Route("items")] + public async Task AddBasketItem([FromBody] AddBasketItemRequest data) + { + if (data == null || data.Quantity == 0) + { + return BadRequest("Invalid payload"); + } + + // Step 1: Get the item from catalog + var item = await _catalog.GetCatalogItem(data.CatalogItemId); + + //item.PictureUri = + + // Step 2: Get current basket status + var currentBasket = (await _basket.GetById(data.BasketId)) ?? new BasketData(data.BasketId); + // Step 3: Merge current status with new product + currentBasket.Items.Add(new BasketDataItem() + { + UnitPrice = item.Price, + PictureUrl = item.PictureUri, + ProductId = item.Id.ToString(), + ProductName = item.Name, + Quantity = data.Quantity, + Id = Guid.NewGuid().ToString() + }); + + // Step 4: Update basket + await _basket.Update(currentBasket); + + + return Ok(); + } + } +} diff --git a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Controllers/HomeController.cs b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Controllers/HomeController.cs new file mode 100644 index 000000000..48a71480a --- /dev/null +++ b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Controllers/HomeController.cs @@ -0,0 +1,18 @@ +using Microsoft.AspNetCore.Mvc; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Controllers +{ + [Route("")] + public class HomeController : Controller + { + [HttpGet()] + public IActionResult Index() + { + return new RedirectResult("~/swagger"); + } + } +} diff --git a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Controllers/OrderController.cs b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Controllers/OrderController.cs new file mode 100644 index 000000000..4c18d25ae --- /dev/null +++ b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Controllers/OrderController.cs @@ -0,0 +1,42 @@ +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Mvc; +using Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Services; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Controllers +{ + [Route("api/v1/[controller]")] + [Authorize] + public class OrderController : Controller + { + private readonly IBasketService _basketService; + private readonly IOrderApiClient _orderClient; + public OrderController(IBasketService basketService, IOrderApiClient orderClient) + { + _basketService = basketService; + _orderClient = orderClient; + } + + [Route("draft/{basketId}")] + [HttpGet] + public async Task GetOrderDraft(string basketId) + { + if (string.IsNullOrEmpty(basketId)) + { + return BadRequest("Need a valid basketid"); + } + // Get the basket data and build a order draft based on it + var basket = await _basketService.GetById(basketId); + if (basket == null) + { + return BadRequest($"No basket found for id {basketId}"); + } + + var orderDraft = await _orderClient.GetOrderDraftFromBasket(basket); + return Ok(orderDraft); + } + } +} diff --git a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Dockerfile b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Dockerfile new file mode 100644 index 000000000..273743cee --- /dev/null +++ b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Dockerfile @@ -0,0 +1,19 @@ +FROM microsoft/aspnetcore:2.0.5 AS base +WORKDIR /app +EXPOSE 80 + +FROM microsoft/aspnetcore-build:2.0 AS build +WORKDIR /src +COPY . . +RUN dotnet restore -nowarn:msb3202,nu1503 +WORKDIR /src/src/ApiGateways/Mobile.Bff.Shopping/aggregator +RUN dotnet build --no-restore -c Release -o /app + +FROM build AS publish +RUN dotnet publish --no-restore -c Release -o /app + +FROM base AS final +WORKDIR /app +COPY --from=publish /app . +ENTRYPOINT ["dotnet", "Mobile.Shopping.HttpAggregator.dll"] + diff --git a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Filters/AuthorizeCheckOperationFilter.cs b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Filters/AuthorizeCheckOperationFilter.cs new file mode 100644 index 000000000..b3a7246aa --- /dev/null +++ b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Filters/AuthorizeCheckOperationFilter.cs @@ -0,0 +1,33 @@ +namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Filters +{ + using Microsoft.AspNetCore.Authorization; + using Swashbuckle.AspNetCore.Swagger; + using Swashbuckle.AspNetCore.SwaggerGen; + using System.Collections.Generic; + using System.Linq; + + namespace Basket.API.Infrastructure.Filters + { + public class AuthorizeCheckOperationFilter : IOperationFilter + { + public void Apply(Operation operation, OperationFilterContext context) + { + // Check for authorize attribute + var hasAuthorize = context.ApiDescription.ControllerAttributes().OfType().Any() || + context.ApiDescription.ActionAttributes().OfType().Any(); + + if (hasAuthorize) + { + operation.Responses.Add("401", new Response { Description = "Unauthorized" }); + operation.Responses.Add("403", new Response { Description = "Forbidden" }); + + operation.Security = new List>>(); + operation.Security.Add(new Dictionary> + { + { "oauth2", new [] { "Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator" } } + }); + } + } + } + } +} diff --git a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Mobile.Shopping.HttpAggregator.csproj b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Mobile.Shopping.HttpAggregator.csproj new file mode 100644 index 000000000..bd6d73950 --- /dev/null +++ b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Mobile.Shopping.HttpAggregator.csproj @@ -0,0 +1,27 @@ + + + + netcoreapp2.0 + Mobile.Shopping.HttpAggregator + Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator + ..\..\..\docker-compose.dcproj + + + + + + + + + + + + + + + + + + + + diff --git a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Models/AddBasketItemRequest.cs b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Models/AddBasketItemRequest.cs new file mode 100644 index 000000000..f81842c09 --- /dev/null +++ b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Models/AddBasketItemRequest.cs @@ -0,0 +1,20 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Models +{ + public class AddBasketItemRequest + { + public int CatalogItemId { get; set; } + public string BasketId { get; set; } + + public int Quantity { get; set; } + + public AddBasketItemRequest() + { + Quantity = 1; + } + } +} diff --git a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Models/BasketData.cs b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Models/BasketData.cs new file mode 100644 index 000000000..1b9348c44 --- /dev/null +++ b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Models/BasketData.cs @@ -0,0 +1,31 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Models +{ + public class BasketData + { + public string BuyerId { get; set; } + public List Items { get; set; } + + public BasketData(string buyerId) + { + BuyerId = buyerId; + Items = new List(); + } + } + + public class BasketDataItem + { + public string Id { get; set; } + public string ProductId { get; set; } + public string ProductName { get; set; } + public decimal UnitPrice { get; set; } + public decimal OldUnitPrice { get; set; } + public int Quantity { get; set; } + public string PictureUrl { get; set; } + + } +} diff --git a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Models/CatalogItem.cs b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Models/CatalogItem.cs new file mode 100644 index 000000000..25f766719 --- /dev/null +++ b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Models/CatalogItem.cs @@ -0,0 +1,20 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Models +{ + public class CatalogItem + { + public int Id { get; set; } + + public string Name { get; set; } + + public decimal Price { get; set; } + + + public string PictureUri { get; set; } + + } +} diff --git a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Models/OrderData.cs b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Models/OrderData.cs new file mode 100644 index 000000000..e87cc18f0 --- /dev/null +++ b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Models/OrderData.cs @@ -0,0 +1,33 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Models +{ + public class OrderData + { + public string OrderNumber { get; set; } + public DateTime Date { get; set; } + public string Status { get; set; } + public decimal Total { get; set; } + public string Description { get; set; } + public string City { get; set; } + public string Street { get; set; } + public string State { get; set; } + public string Country { get; set; } + public string ZipCode { get; set; } + public string CardNumber { get; set; } + public string CardHolderName { get; set; } + public bool IsDraft { get; set; } + public DateTime CardExpiration { get; set; } + public string CardExpirationShort { get; set; } + public string CardSecurityNumber { get; set; } + + public int CardTypeId { get; set; } + + public string Buyer { get; set; } + + public List OrderItems { get; } = new List(); + } +} diff --git a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Models/OrderItemData.cs b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Models/OrderItemData.cs new file mode 100644 index 000000000..b0179e470 --- /dev/null +++ b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Models/OrderItemData.cs @@ -0,0 +1,17 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Models +{ + public class OrderItemData + { + public int ProductId { get; set; } + public string ProductName { get; set; } + public decimal UnitPrice { get; set; } + public decimal Discount { get; set; } + public int Units { get; set; } + public string PictureUrl { get; set; } + } +} diff --git a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Models/UpdateBasketItemsRequest.cs b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Models/UpdateBasketItemsRequest.cs new file mode 100644 index 000000000..43cc81b89 --- /dev/null +++ b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Models/UpdateBasketItemsRequest.cs @@ -0,0 +1,31 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Models +{ + public class UpdateBasketItemsRequest + { + + public string BasketId { get; set; } + + public ICollection Updates { get; set; } + + public UpdateBasketItemsRequest() + { + Updates = new List(); + } + } + + public class UpdateBasketItemData + { + public string BasketItemId { get; set; } + public int NewQty { get; set; } + + public UpdateBasketItemData() + { + NewQty = 0; + } + } +} diff --git a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Models/UpdateBasketRequest.cs b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Models/UpdateBasketRequest.cs new file mode 100644 index 000000000..cb22bf55f --- /dev/null +++ b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Models/UpdateBasketRequest.cs @@ -0,0 +1,21 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Models +{ + public class UpdateBasketRequest + { + public string BuyerId { get; set; } + + public IEnumerable Items { get; set; } + } + + public class UpdateBasketRequestItemData + { + public string Id { get; set; } // Basket id + public int ProductId { get; set; } // Catalog item id + public int Quantity { get; set; } // Quantity + } +} diff --git a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Program.cs b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Program.cs new file mode 100644 index 000000000..0c88fcd7d --- /dev/null +++ b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Program.cs @@ -0,0 +1,36 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.AspNetCore; +using Microsoft.AspNetCore.Hosting; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.Logging; + +namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator +{ + public class Program + { + public static void Main(string[] args) + { + BuildWebHost(args).Run(); + } + + public static IWebHost BuildWebHost(string[] args) => + WebHost + .CreateDefaultBuilder(args) + .ConfigureAppConfiguration(cb => + { + var sources = cb.Sources; + sources.Insert(3, new Microsoft.Extensions.Configuration.Json.JsonConfigurationSource() + { + Optional = true, + Path = "appsettings.localhost.json", + ReloadOnChange = false + }); + }) + .UseStartup() + .Build(); + } +} diff --git a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Properties/launchSettings.json b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Properties/launchSettings.json new file mode 100644 index 000000000..925e70b0d --- /dev/null +++ b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Properties/launchSettings.json @@ -0,0 +1,29 @@ +{ + "iisSettings": { + "windowsAuthentication": false, + "anonymousAuthentication": true, + "iisExpress": { + "applicationUrl": "http://localhost:57425/", + "sslPort": 0 + } + }, + "profiles": { + "IIS Express": { + "commandName": "IISExpress", + "launchBrowser": true, + "launchUrl": "api/values", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "PurchaseForMvc": { + "commandName": "Project", + "launchBrowser": true, + "launchUrl": "api/values", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + }, + "applicationUrl": "http://localhost:61632/" + } + } +} \ No newline at end of file diff --git a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Services/BasketService.cs b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Services/BasketService.cs new file mode 100644 index 000000000..b00fbb52c --- /dev/null +++ b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Services/BasketService.cs @@ -0,0 +1,53 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Authentication; +using Microsoft.AspNetCore.Http; +using Microsoft.eShopOnContainers.BuildingBlocks.Resilience.Http; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; +using Newtonsoft.Json; +using Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Config; +using Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Models; + +namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Services +{ + public class BasketService : IBasketService + { + + private readonly IHttpClient _apiClient; + private readonly ILogger _logger; + private readonly UrlsConfig _urls; + private readonly IHttpContextAccessor _httpContextAccessor; + + public BasketService(IHttpClient httpClient, IHttpContextAccessor httpContextAccessor, ILogger logger, IOptionsSnapshot config) + { + _apiClient = httpClient; + _logger = logger; + _urls = config.Value; + _httpContextAccessor = httpContextAccessor; + } + + public async Task GetById(string id) + { + var token = await GetUserTokenAsync(); + var data = await _apiClient.GetStringAsync(_urls.Basket + UrlsConfig.BasketOperations.GetItemById(id), token); + var basket = !string.IsNullOrEmpty(data) ? JsonConvert.DeserializeObject(data) : null; + return basket; + } + + public async Task Update(BasketData currentBasket) + { + var token = await GetUserTokenAsync(); + var data = await _apiClient.PostAsync(_urls.Basket + UrlsConfig.BasketOperations.UpdateBasket(), currentBasket, token); + int i = 0; + } + + async Task GetUserTokenAsync() + { + var context = _httpContextAccessor.HttpContext; + return await context.GetTokenAsync("access_token"); + } + } +} diff --git a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Services/CatalogService.cs b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Services/CatalogService.cs new file mode 100644 index 000000000..d37b67679 --- /dev/null +++ b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Services/CatalogService.cs @@ -0,0 +1,43 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.eShopOnContainers.BuildingBlocks.Resilience.Http; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; +using Newtonsoft.Json; +using Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Config; +using Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Models; + +namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Services +{ + public class CatalogService : ICatalogService + { + + private readonly IHttpClient _apiClient; + private readonly ILogger _logger; + private readonly UrlsConfig _urls; + + public CatalogService(IHttpClient httpClient, ILogger logger, IOptionsSnapshot config) + { + _apiClient = httpClient; + _logger = logger; + _urls = config.Value; + } + + public async Task GetCatalogItem(int id) + { + var data = await _apiClient.GetStringAsync(_urls.Catalog + UrlsConfig.CatalogOperations.GetItemById(id)); + var item = JsonConvert.DeserializeObject(data); + return item; + } + + public async Task> GetCatalogItems(IEnumerable ids) + { + var data = await _apiClient.GetStringAsync(_urls.Catalog + UrlsConfig.CatalogOperations.GetItemsById(ids)); + var item = JsonConvert.DeserializeObject(data); + return item; + + } + } +} diff --git a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Services/IBasketService.cs b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Services/IBasketService.cs new file mode 100644 index 000000000..6fd6871c1 --- /dev/null +++ b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Services/IBasketService.cs @@ -0,0 +1,15 @@ +using Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Models; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Services +{ + public interface IBasketService + { + Task GetById(string id); + Task Update(BasketData currentBasket); + + } +} diff --git a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Services/ICatalogService.cs b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Services/ICatalogService.cs new file mode 100644 index 000000000..d7e605bfa --- /dev/null +++ b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Services/ICatalogService.cs @@ -0,0 +1,14 @@ +using Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Models; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Services +{ + public interface ICatalogService + { + Task GetCatalogItem(int id); + Task> GetCatalogItems(IEnumerable ids); + } +} diff --git a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Services/IOrderApiClient.cs b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Services/IOrderApiClient.cs new file mode 100644 index 000000000..30ac013b9 --- /dev/null +++ b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Services/IOrderApiClient.cs @@ -0,0 +1,13 @@ +using Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Models; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Services +{ + public interface IOrderApiClient + { + Task GetOrderDraftFromBasket(BasketData basket); + } +} diff --git a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Services/OrderApiClient.cs b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Services/OrderApiClient.cs new file mode 100644 index 000000000..2659e11cc --- /dev/null +++ b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Services/OrderApiClient.cs @@ -0,0 +1,37 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.eShopOnContainers.BuildingBlocks.Resilience.Http; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; +using Newtonsoft.Json; +using Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Config; +using Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Models; + +namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Services +{ + public class OrderApiClient : IOrderApiClient + { + + private readonly IHttpClient _apiClient; + private readonly ILogger _logger; + private readonly UrlsConfig _urls; + + public OrderApiClient(IHttpClient httpClient, ILogger logger, IOptionsSnapshot config) + { + _apiClient = httpClient; + _logger = logger; + _urls = config.Value; + } + + public async Task GetOrderDraftFromBasket(BasketData basket) + { + var url = _urls.Orders + UrlsConfig.OrdersOperations.GetOrderDraft(); + var response = await _apiClient.PostAsync(url, basket); + response.EnsureSuccessStatusCode(); + var jsonResponse = await response.Content.ReadAsStringAsync(); + return JsonConvert.DeserializeObject(jsonResponse); + } + } +} diff --git a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Startup.cs b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Startup.cs new file mode 100644 index 000000000..73b736519 --- /dev/null +++ b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Startup.cs @@ -0,0 +1,138 @@ +using System; +using System.Collections.Generic; +using System.IdentityModel.Tokens.Jwt; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Authentication.JwtBearer; +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Hosting; +using Microsoft.AspNetCore.Http; +using Microsoft.eShopOnContainers.BuildingBlocks.Resilience.Http; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; +using Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Config; +using Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Filters.Basket.API.Infrastructure.Filters; +using Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Services; +using Swashbuckle.AspNetCore.Swagger; + +namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator +{ + public class Startup + { + public Startup(IConfiguration configuration) + { + Configuration = configuration; + } + + public IConfiguration Configuration { get; } + + // This method gets called by the runtime. Use this method to add services to the container. + public void ConfigureServices(IServiceCollection services) + { + services.AddSingleton(); + services.AddSingleton(); + services.AddTransient(); + services.AddTransient(); + services.AddTransient(); + + services.AddOptions(); + services.Configure(Configuration.GetSection("urls")); + + services.AddMvc(); + + services.AddSwaggerGen(options => + { + options.DescribeAllEnumsAsStrings(); + options.SwaggerDoc("v1", new Swashbuckle.AspNetCore.Swagger.Info + { + Title = "Shopping Aggregator for Mobile Clients", + Version = "v1", + Description = "Shopping Aggregator for Mobile Clients", + TermsOfService = "Terms Of Service" + }); + + options.AddSecurityDefinition("oauth2", new OAuth2Scheme + { + Type = "oauth2", + Flow = "implicit", + AuthorizationUrl = $"{Configuration.GetValue("IdentityUrlExternal")}/connect/authorize", + TokenUrl = $"{Configuration.GetValue("IdentityUrlExternal")}/connect/token", + Scopes = new Dictionary() + { + { "mobileshoppingagg", "Shopping Aggregator for Mobile Clients" } + } + }); + + options.OperationFilter(); + }); + + services.AddCors(options => + { + options.AddPolicy("CorsPolicy", + builder => builder.AllowAnyOrigin() + .AllowAnyMethod() + .AllowAnyHeader() + .AllowCredentials()); + }); + + + JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear(); + var identityUrl = Configuration.GetValue("urls:identity"); + services.AddAuthentication(options => + { + options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme; + options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme; + + }).AddJwtBearer(options => + { + options.Authority = identityUrl; + options.RequireHttpsMetadata = false; + options.Audience = "mobileshoppingagg"; + options.Events = new JwtBearerEvents() + { + OnAuthenticationFailed = async ctx => + { + int i = 0; + }, + OnTokenValidated = async ctx => + { + int i = 0; + } + }; + }); + } + + // 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) + { + + var pathBase = Configuration["PATH_BASE"]; + if (!string.IsNullOrEmpty(pathBase)) + { + loggerFactory.CreateLogger("init").LogDebug($"Using PATH BASE '{pathBase}'"); + app.UsePathBase(pathBase); + } + + app.UseCors("CorsPolicy"); + + if (env.IsDevelopment()) + { + app.UseDeveloperExceptionPage(); + } + + app.UseAuthentication(); + + app.UseMvc(); + + app.UseSwagger().UseSwaggerUI(c => + { + c.SwaggerEndpoint($"{ (!string.IsNullOrEmpty(pathBase) ? pathBase : string.Empty) }/swagger/v1/swagger.json", "Purchase BFF V1"); + c.ConfigureOAuth2("Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregatorwaggerui", "", "", "Purchase BFF Swagger UI"); + }); + + + } + } +} diff --git a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/appsettings.json b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/appsettings.json new file mode 100644 index 000000000..26bb0ac7a --- /dev/null +++ b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/appsettings.json @@ -0,0 +1,15 @@ +{ + "Logging": { + "IncludeScopes": false, + "Debug": { + "LogLevel": { + "Default": "Warning" + } + }, + "Console": { + "LogLevel": { + "Default": "Warning" + } + } + } +} diff --git a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/appsettings.localhost.json b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/appsettings.localhost.json new file mode 100644 index 000000000..57b5e894d --- /dev/null +++ b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/appsettings.localhost.json @@ -0,0 +1,8 @@ +{ + "urls": { + "basket": "http://localhost:55105", + "catalog": "http://localhost:55101", + "orders": "http://localhost:55102", + "identity": "http://localhost:55105" + } +} diff --git a/src/ApiGateways/Mobile.Bff.Shopping/apigw/configuration.json b/src/ApiGateways/Mobile.Bff.Shopping/apigw/configuration.json new file mode 100644 index 000000000..870690ed4 --- /dev/null +++ b/src/ApiGateways/Mobile.Bff.Shopping/apigw/configuration.json @@ -0,0 +1,142 @@ +{ + "ReRoutes": [ + { + "DownstreamPathTemplate": "/api/{version}/{everything}", + "DownstreamScheme": "http", + "DownstreamHostAndPorts": [ + { + "Host": "catalog.api", + "Port": 80 + } + ], + "UpstreamPathTemplate": "/api/{version}/c/{everything}", + "UpstreamHttpMethod": [ "GET" ] + }, + { + "DownstreamPathTemplate": "/api/{version}/{everything}", + "DownstreamScheme": "http", + "DownstreamHostAndPorts": [ + { + "Host": "basket.api", + "Port": 80 + } + ], + "UpstreamPathTemplate": "/api/{version}/b/{everything}", + "UpstreamHttpMethod": [], + "AuthenticationOptions": { + "AuthenticationProviderKey": "IdentityApiKey", + "AllowedScopes": [] + } + }, + { + "DownstreamPathTemplate": "/api/{version}/{everything}", + "DownstreamScheme": "http", + "DownstreamHostAndPorts": [ + { + "Host": "ordering.api", + "Port": 80 + } + ], + "UpstreamPathTemplate": "/api/{version}/o/{everything}", + "UpstreamHttpMethod": [], + "AuthenticationOptions": { + "AuthenticationProviderKey": "IdentityApiKey", + "AllowedScopes": [] + } + }, + { + "DownstreamPathTemplate": "/{everything}", + "DownstreamScheme": "http", + "DownstreamHostAndPorts": [ + { + "Host": "mobileshoppingagg", + "Port": 80 + } + ], + "UpstreamPathTemplate": "/{everything}", + "UpstreamHttpMethod": [ "POST", "PUT", "GET" ], + "AuthenticationOptions": { + "AuthenticationProviderKey": "IdentityApiKey", + "AllowedScopes": [] + } + }, + { + "DownstreamPathTemplate": "/{everything}", + "DownstreamScheme": "http", + "DownstreamHostAndPorts": [ + { + "Host": "ordering.api", + "Port": 80 + } + ], + "UpstreamPathTemplate": "/orders-api/{everything}", + "UpstreamHttpMethod": [] + }, + { + "DownstreamPathTemplate": "/{everything}", + "DownstreamScheme": "http", + "DownstreamHostAndPorts": [ + { + "Host": "basket.api", + "Port": 80 + } + ], + "UpstreamPathTemplate": "/basket-api/{everything}", + "UpstreamHttpMethod": [] + }, + { + "DownstreamPathTemplate": "/{everything}", + "DownstreamScheme": "http", + "DownstreamHostAndPorts": [ + { + "Host": "catalog.api", + "Port": 80 + } + ], + "UpstreamPathTemplate": "/catalog-api/{everything}", + "UpstreamHttpMethod": [] + }, + { + "DownstreamPathTemplate": "/{everything}", + "DownstreamScheme": "http", + "DownstreamHostAndPorts": [ + { + "Host": "marketing.api", + "Port": 80 + } + ], + "UpstreamPathTemplate": "/marketing-api/{everything}", + "UpstreamHttpMethod": [] + }, + { + "DownstreamPathTemplate": "/{everything}", + "DownstreamScheme": "http", + "DownstreamHostAndPorts": [ + { + "Host": "payment.api", + "Port": 80 + } + ], + "UpstreamPathTemplate": "/payment-api/{everything}", + "UpstreamHttpMethod": [] + }, + { + "DownstreamPathTemplate": "/{everything}", + "DownstreamScheme": "http", + "DownstreamHostAndPorts": [ + { + "Host": "locations.api", + "Port": 80 + } + ], + "UpstreamPathTemplate": "/location-api/{everything}", + "UpstreamHttpMethod": [] + } + + ], + "GlobalConfiguration": { + "RequestIdKey": "OcRequestId", + "AdministrationPath": "/administration" + } + } + \ No newline at end of file diff --git a/src/ApiGateways/Web.Bff.Marketing/apigw/configuration.json b/src/ApiGateways/Web.Bff.Marketing/apigw/configuration.json new file mode 100644 index 000000000..8afe4a4d6 --- /dev/null +++ b/src/ApiGateways/Web.Bff.Marketing/apigw/configuration.json @@ -0,0 +1,34 @@ +{ + "ReRoutes": [ + { + "DownstreamPathTemplate": "/api/{version}/{everything}", + "DownstreamScheme": "http", + "DownstreamHostAndPorts": [ + { + "Host": "marketing.api", + "Port": 80 + } + ], + "UpstreamPathTemplate": "/api/{version}/m/{everything}", + "UpstreamHttpMethod": [] + }, + { + "DownstreamPathTemplate": "/api/{version}/{everything}", + "DownstreamScheme": "http", + "DownstreamHostAndPorts": [ + { + "Host": "locations.api", + "Port": 80 + } + ], + "UpstreamPathTemplate": "/api/{version}/l/{everything}", + "UpstreamHttpMethod": [] + } + + ], + "GlobalConfiguration": { + "RequestIdKey": "OcRequestId", + "AdministrationPath": "/administration" + } +} + \ No newline at end of file diff --git a/src/ApiGateways/Web.Bff.Shopping/aggregator/Config/UrlsConfig.cs b/src/ApiGateways/Web.Bff.Shopping/aggregator/Config/UrlsConfig.cs new file mode 100644 index 000000000..19be27dce --- /dev/null +++ b/src/ApiGateways/Web.Bff.Shopping/aggregator/Config/UrlsConfig.cs @@ -0,0 +1,31 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Config +{ + public class UrlsConfig + { + public class CatalogOperations + { + public static string GetItemById(int id) => $"/api/v1/catalog/items/{id}"; + public static string GetItemsById(IEnumerable ids) => $"/api/v1/catalog/items?ids={string.Join(',', ids)}"; + } + + public class BasketOperations + { + public static string GetItemById(string id) => $"/api/v1/basket/{id}"; + public static string UpdateBasket() => "/api/v1/basket"; + } + + public class OrdersOperations + { + public static string GetOrderDraft() => "/api/v1/orders/draft"; + } + + public string Basket { get; set; } + public string Catalog { get; set; } + public string Orders { get; set; } + } +} diff --git a/src/ApiGateways/Web.Bff.Shopping/aggregator/Controllers/BasketController.cs b/src/ApiGateways/Web.Bff.Shopping/aggregator/Controllers/BasketController.cs new file mode 100644 index 000000000..bfef55726 --- /dev/null +++ b/src/ApiGateways/Web.Bff.Shopping/aggregator/Controllers/BasketController.cs @@ -0,0 +1,133 @@ +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Mvc; +using Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Models; +using Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Services; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Controllers +{ + [Route("api/v1/[controller]")] + [Authorize] + public class BasketController : Controller + { + private readonly ICatalogService _catalog; + private readonly IBasketService _basket; + public BasketController(ICatalogService catalogService, IBasketService basketService) + { + _catalog = catalogService; + _basket = basketService; + } + + [HttpPost] + [HttpPut] + public async Task UpdateAllBasket([FromBody] UpdateBasketRequest data) + { + + if (data.Items == null || !data.Items.Any()) + { + return BadRequest("Need to pass at least one basket line"); + } + + // Retrieve the current basket + var currentBasket = await _basket.GetById(data.BuyerId); + if (currentBasket == null) + { + currentBasket = new BasketData(data.BuyerId); + } + + var catalogItems = await _catalog.GetCatalogItems(data.Items.Select(x => x.ProductId)); + var newBasket = new BasketData(data.BuyerId); + + foreach (var bitem in data.Items) + { + var catalogItem = catalogItems.SingleOrDefault(ci => ci.Id == bitem.ProductId); + if (catalogItem == null) + { + return BadRequest($"Basket refers to a non-existing catalog item ({bitem.ProductId})"); + } + + newBasket.Items.Add(new BasketDataItem() + { + Id = bitem.Id, + ProductId = catalogItem.Id.ToString(), + ProductName = catalogItem.Name, + PictureUrl = catalogItem.PictureUri, + UnitPrice = catalogItem.Price, + Quantity = bitem.Quantity + }); + } + + await _basket.Update(newBasket); + return Ok(newBasket); + } + + [HttpPut] + [Route("items")] + public async Task UpdateQuantities([FromBody] UpdateBasketItemsRequest data) + { + if (!data.Updates.Any()) + { + return BadRequest("No updates sent"); + } + + // Retrieve the current basket + var currentBasket = await _basket.GetById(data.BasketId); + if (currentBasket == null) + { + return BadRequest($"Basket with id {data.BasketId} not found."); + } + + // Update with new quantities + foreach (var update in data.Updates) + { + var basketItem = currentBasket.Items.SingleOrDefault(bitem => bitem.Id == update.BasketItemId); + if (basketItem == null) + { + return BadRequest($"Basket item with id {update.BasketItemId} not found"); + } + basketItem.Quantity = update.NewQty; + } + + // Save the updated basket + await _basket.Update(currentBasket); + return Ok(currentBasket); + } + + [HttpPost] + [Route("items")] + public async Task AddBasketItem([FromBody] AddBasketItemRequest data) + { + if (data == null || data.Quantity == 0) + { + return BadRequest("Invalid payload"); + } + + // Step 1: Get the item from catalog + var item = await _catalog.GetCatalogItem(data.CatalogItemId); + + //item.PictureUri = + + // Step 2: Get current basket status + var currentBasket = (await _basket.GetById(data.BasketId)) ?? new BasketData(data.BasketId); + // Step 3: Merge current status with new product + currentBasket.Items.Add(new BasketDataItem() + { + UnitPrice = item.Price, + PictureUrl = item.PictureUri, + ProductId = item.Id.ToString(), + ProductName = item.Name, + Quantity = data.Quantity, + Id = Guid.NewGuid().ToString() + }); + + // Step 4: Update basket + await _basket.Update(currentBasket); + + + return Ok(); + } + } +} diff --git a/src/ApiGateways/Web.Bff.Shopping/aggregator/Controllers/HomeController.cs b/src/ApiGateways/Web.Bff.Shopping/aggregator/Controllers/HomeController.cs new file mode 100644 index 000000000..58ed48d1a --- /dev/null +++ b/src/ApiGateways/Web.Bff.Shopping/aggregator/Controllers/HomeController.cs @@ -0,0 +1,18 @@ +using Microsoft.AspNetCore.Mvc; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Controllers +{ + [Route("")] + public class HomeController : Controller + { + [HttpGet()] + public IActionResult Index() + { + return new RedirectResult("~/swagger"); + } + } +} diff --git a/src/ApiGateways/Web.Bff.Shopping/aggregator/Controllers/OrderController.cs b/src/ApiGateways/Web.Bff.Shopping/aggregator/Controllers/OrderController.cs new file mode 100644 index 000000000..fd108ffb8 --- /dev/null +++ b/src/ApiGateways/Web.Bff.Shopping/aggregator/Controllers/OrderController.cs @@ -0,0 +1,42 @@ +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Mvc; +using Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Services; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Controllers +{ + [Route("api/v1/[controller]")] + [Authorize] + public class OrderController : Controller + { + private readonly IBasketService _basketService; + private readonly IOrderApiClient _orderClient; + public OrderController(IBasketService basketService, IOrderApiClient orderClient) + { + _basketService = basketService; + _orderClient = orderClient; + } + + [Route("draft/{basketId}")] + [HttpGet] + public async Task GetOrderDraft(string basketId) + { + if (string.IsNullOrEmpty(basketId)) + { + return BadRequest("Need a valid basketid"); + } + // Get the basket data and build a order draft based on it + var basket = await _basketService.GetById(basketId); + if (basket == null) + { + return BadRequest($"No basket found for id {basketId}"); + } + + var orderDraft = await _orderClient.GetOrderDraftFromBasket(basket); + return Ok(orderDraft); + } + } +} diff --git a/src/ApiGateways/Web.Bff.Shopping/aggregator/Dockerfile b/src/ApiGateways/Web.Bff.Shopping/aggregator/Dockerfile new file mode 100644 index 000000000..ce6f1b155 --- /dev/null +++ b/src/ApiGateways/Web.Bff.Shopping/aggregator/Dockerfile @@ -0,0 +1,18 @@ +FROM microsoft/aspnetcore:2.0.5 AS base +WORKDIR /app +EXPOSE 80 + +FROM microsoft/aspnetcore-build:2.0 AS build +WORKDIR /src +COPY . . +RUN dotnet restore -nowarn:msb3202,nu1503 +WORKDIR /src/src/ApiGateways/Web.Bff.Shopping/aggregator +RUN dotnet build --no-restore -c Release -o /app + +FROM build AS publish +RUN dotnet publish --no-restore -c Release -o /app + +FROM base AS final +WORKDIR /app +COPY --from=publish /app . +ENTRYPOINT ["dotnet", "Web.Shopping.HttpAggregator.dll"] diff --git a/src/ApiGateways/Web.Bff.Shopping/aggregator/Filters/AuthorizeCheckOperationFilter.cs b/src/ApiGateways/Web.Bff.Shopping/aggregator/Filters/AuthorizeCheckOperationFilter.cs new file mode 100644 index 000000000..3f382e5df --- /dev/null +++ b/src/ApiGateways/Web.Bff.Shopping/aggregator/Filters/AuthorizeCheckOperationFilter.cs @@ -0,0 +1,33 @@ +namespace Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Filters +{ + using Microsoft.AspNetCore.Authorization; + using Swashbuckle.AspNetCore.Swagger; + using Swashbuckle.AspNetCore.SwaggerGen; + using System.Collections.Generic; + using System.Linq; + + namespace Basket.API.Infrastructure.Filters + { + public class AuthorizeCheckOperationFilter : IOperationFilter + { + public void Apply(Operation operation, OperationFilterContext context) + { + // Check for authorize attribute + var hasAuthorize = context.ApiDescription.ControllerAttributes().OfType().Any() || + context.ApiDescription.ActionAttributes().OfType().Any(); + + if (hasAuthorize) + { + operation.Responses.Add("401", new Response { Description = "Unauthorized" }); + operation.Responses.Add("403", new Response { Description = "Forbidden" }); + + operation.Security = new List>>(); + operation.Security.Add(new Dictionary> + { + { "oauth2", new [] { "Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator" } } + }); + } + } + } + } +} diff --git a/src/ApiGateways/Web.Bff.Shopping/aggregator/Models/AddBasketItemRequest.cs b/src/ApiGateways/Web.Bff.Shopping/aggregator/Models/AddBasketItemRequest.cs new file mode 100644 index 000000000..88aff245f --- /dev/null +++ b/src/ApiGateways/Web.Bff.Shopping/aggregator/Models/AddBasketItemRequest.cs @@ -0,0 +1,20 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Models +{ + public class AddBasketItemRequest + { + public int CatalogItemId { get; set; } + public string BasketId { get; set; } + + public int Quantity { get; set; } + + public AddBasketItemRequest() + { + Quantity = 1; + } + } +} diff --git a/src/ApiGateways/Web.Bff.Shopping/aggregator/Models/BasketData.cs b/src/ApiGateways/Web.Bff.Shopping/aggregator/Models/BasketData.cs new file mode 100644 index 000000000..01831a5c9 --- /dev/null +++ b/src/ApiGateways/Web.Bff.Shopping/aggregator/Models/BasketData.cs @@ -0,0 +1,31 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Models +{ + public class BasketData + { + public string BuyerId { get; set; } + public List Items { get; set; } + + public BasketData(string buyerId) + { + BuyerId = buyerId; + Items = new List(); + } + } + + public class BasketDataItem + { + public string Id { get; set; } + public string ProductId { get; set; } + public string ProductName { get; set; } + public decimal UnitPrice { get; set; } + public decimal OldUnitPrice { get; set; } + public int Quantity { get; set; } + public string PictureUrl { get; set; } + + } +} diff --git a/src/ApiGateways/Web.Bff.Shopping/aggregator/Models/CatalogItem.cs b/src/ApiGateways/Web.Bff.Shopping/aggregator/Models/CatalogItem.cs new file mode 100644 index 000000000..c6085f934 --- /dev/null +++ b/src/ApiGateways/Web.Bff.Shopping/aggregator/Models/CatalogItem.cs @@ -0,0 +1,20 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Models +{ + public class CatalogItem + { + public int Id { get; set; } + + public string Name { get; set; } + + public decimal Price { get; set; } + + + public string PictureUri { get; set; } + + } +} diff --git a/src/ApiGateways/Web.Bff.Shopping/aggregator/Models/OrderData.cs b/src/ApiGateways/Web.Bff.Shopping/aggregator/Models/OrderData.cs new file mode 100644 index 000000000..e9d5982b9 --- /dev/null +++ b/src/ApiGateways/Web.Bff.Shopping/aggregator/Models/OrderData.cs @@ -0,0 +1,33 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Models +{ + public class OrderData + { + public string OrderNumber { get; set; } + public DateTime Date { get; set; } + public string Status { get; set; } + public decimal Total { get; set; } + public string Description { get; set; } + public string City { get; set; } + public string Street { get; set; } + public string State { get; set; } + public string Country { get; set; } + public string ZipCode { get; set; } + public string CardNumber { get; set; } + public string CardHolderName { get; set; } + public bool IsDraft { get; set; } + public DateTime CardExpiration { get; set; } + public string CardExpirationShort { get; set; } + public string CardSecurityNumber { get; set; } + + public int CardTypeId { get; set; } + + public string Buyer { get; set; } + + public List OrderItems { get; } = new List(); + } +} diff --git a/src/ApiGateways/Web.Bff.Shopping/aggregator/Models/OrderItemData.cs b/src/ApiGateways/Web.Bff.Shopping/aggregator/Models/OrderItemData.cs new file mode 100644 index 000000000..1a40cb8cb --- /dev/null +++ b/src/ApiGateways/Web.Bff.Shopping/aggregator/Models/OrderItemData.cs @@ -0,0 +1,17 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Models +{ + public class OrderItemData + { + public int ProductId { get; set; } + public string ProductName { get; set; } + public decimal UnitPrice { get; set; } + public decimal Discount { get; set; } + public int Units { get; set; } + public string PictureUrl { get; set; } + } +} diff --git a/src/ApiGateways/Web.Bff.Shopping/aggregator/Models/UpdateBasketItemsRequest.cs b/src/ApiGateways/Web.Bff.Shopping/aggregator/Models/UpdateBasketItemsRequest.cs new file mode 100644 index 000000000..b41c069bc --- /dev/null +++ b/src/ApiGateways/Web.Bff.Shopping/aggregator/Models/UpdateBasketItemsRequest.cs @@ -0,0 +1,31 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Models +{ + public class UpdateBasketItemsRequest + { + + public string BasketId { get; set; } + + public ICollection Updates { get; set; } + + public UpdateBasketItemsRequest() + { + Updates = new List(); + } + } + + public class UpdateBasketItemData + { + public string BasketItemId { get; set; } + public int NewQty { get; set; } + + public UpdateBasketItemData() + { + NewQty = 0; + } + } +} diff --git a/src/ApiGateways/Web.Bff.Shopping/aggregator/Models/UpdateBasketRequest.cs b/src/ApiGateways/Web.Bff.Shopping/aggregator/Models/UpdateBasketRequest.cs new file mode 100644 index 000000000..9beeeade4 --- /dev/null +++ b/src/ApiGateways/Web.Bff.Shopping/aggregator/Models/UpdateBasketRequest.cs @@ -0,0 +1,21 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Models +{ + public class UpdateBasketRequest + { + public string BuyerId { get; set; } + + public IEnumerable Items { get; set; } + } + + public class UpdateBasketRequestItemData + { + public string Id { get; set; } // Basket id + public int ProductId { get; set; } // Catalog item id + public int Quantity { get; set; } // Quantity + } +} diff --git a/src/ApiGateways/Web.Bff.Shopping/aggregator/Program.cs b/src/ApiGateways/Web.Bff.Shopping/aggregator/Program.cs new file mode 100644 index 000000000..c865a8b3b --- /dev/null +++ b/src/ApiGateways/Web.Bff.Shopping/aggregator/Program.cs @@ -0,0 +1,36 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.AspNetCore; +using Microsoft.AspNetCore.Hosting; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.Logging; + +namespace Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator +{ + public class Program + { + public static void Main(string[] args) + { + BuildWebHost(args).Run(); + } + + public static IWebHost BuildWebHost(string[] args) => + WebHost + .CreateDefaultBuilder(args) + .ConfigureAppConfiguration(cb => + { + var sources = cb.Sources; + sources.Insert(3, new Microsoft.Extensions.Configuration.Json.JsonConfigurationSource() + { + Optional = true, + Path = "appsettings.localhost.json", + ReloadOnChange = false + }); + }) + .UseStartup() + .Build(); + } +} diff --git a/src/ApiGateways/Web.Bff.Shopping/aggregator/Properties/launchSettings.json b/src/ApiGateways/Web.Bff.Shopping/aggregator/Properties/launchSettings.json new file mode 100644 index 000000000..925e70b0d --- /dev/null +++ b/src/ApiGateways/Web.Bff.Shopping/aggregator/Properties/launchSettings.json @@ -0,0 +1,29 @@ +{ + "iisSettings": { + "windowsAuthentication": false, + "anonymousAuthentication": true, + "iisExpress": { + "applicationUrl": "http://localhost:57425/", + "sslPort": 0 + } + }, + "profiles": { + "IIS Express": { + "commandName": "IISExpress", + "launchBrowser": true, + "launchUrl": "api/values", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "PurchaseForMvc": { + "commandName": "Project", + "launchBrowser": true, + "launchUrl": "api/values", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + }, + "applicationUrl": "http://localhost:61632/" + } + } +} \ No newline at end of file diff --git a/src/ApiGateways/Web.Bff.Shopping/aggregator/Services/BasketService.cs b/src/ApiGateways/Web.Bff.Shopping/aggregator/Services/BasketService.cs new file mode 100644 index 000000000..5ca89a408 --- /dev/null +++ b/src/ApiGateways/Web.Bff.Shopping/aggregator/Services/BasketService.cs @@ -0,0 +1,53 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Authentication; +using Microsoft.AspNetCore.Http; +using Microsoft.eShopOnContainers.BuildingBlocks.Resilience.Http; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; +using Newtonsoft.Json; +using Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Config; +using Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Models; + +namespace Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Services +{ + public class BasketService : IBasketService + { + + private readonly IHttpClient _apiClient; + private readonly ILogger _logger; + private readonly UrlsConfig _urls; + private readonly IHttpContextAccessor _httpContextAccessor; + + public BasketService(IHttpClient httpClient, IHttpContextAccessor httpContextAccessor, ILogger logger, IOptionsSnapshot config) + { + _apiClient = httpClient; + _logger = logger; + _urls = config.Value; + _httpContextAccessor = httpContextAccessor; + } + + public async Task GetById(string id) + { + var token = await GetUserTokenAsync(); + var data = await _apiClient.GetStringAsync(_urls.Basket + UrlsConfig.BasketOperations.GetItemById(id), token); + var basket = !string.IsNullOrEmpty(data) ? JsonConvert.DeserializeObject(data) : null; + return basket; + } + + public async Task Update(BasketData currentBasket) + { + var token = await GetUserTokenAsync(); + var data = await _apiClient.PostAsync(_urls.Basket + UrlsConfig.BasketOperations.UpdateBasket(), currentBasket, token); + int i = 0; + } + + async Task GetUserTokenAsync() + { + var context = _httpContextAccessor.HttpContext; + return await context.GetTokenAsync("access_token"); + } + } +} diff --git a/src/ApiGateways/Web.Bff.Shopping/aggregator/Services/CatalogService.cs b/src/ApiGateways/Web.Bff.Shopping/aggregator/Services/CatalogService.cs new file mode 100644 index 000000000..46d895f68 --- /dev/null +++ b/src/ApiGateways/Web.Bff.Shopping/aggregator/Services/CatalogService.cs @@ -0,0 +1,43 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.eShopOnContainers.BuildingBlocks.Resilience.Http; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; +using Newtonsoft.Json; +using Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Config; +using Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Models; + +namespace Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Services +{ + public class CatalogService : ICatalogService + { + + private readonly IHttpClient _apiClient; + private readonly ILogger _logger; + private readonly UrlsConfig _urls; + + public CatalogService(IHttpClient httpClient, ILogger logger, IOptionsSnapshot config) + { + _apiClient = httpClient; + _logger = logger; + _urls = config.Value; + } + + public async Task GetCatalogItem(int id) + { + var data = await _apiClient.GetStringAsync(_urls.Catalog + UrlsConfig.CatalogOperations.GetItemById(id)); + var item = JsonConvert.DeserializeObject(data); + return item; + } + + public async Task> GetCatalogItems(IEnumerable ids) + { + var data = await _apiClient.GetStringAsync(_urls.Catalog + UrlsConfig.CatalogOperations.GetItemsById(ids)); + var item = JsonConvert.DeserializeObject(data); + return item; + + } + } +} diff --git a/src/ApiGateways/Web.Bff.Shopping/aggregator/Services/IBasketService.cs b/src/ApiGateways/Web.Bff.Shopping/aggregator/Services/IBasketService.cs new file mode 100644 index 000000000..f59c31965 --- /dev/null +++ b/src/ApiGateways/Web.Bff.Shopping/aggregator/Services/IBasketService.cs @@ -0,0 +1,15 @@ +using Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Models; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Services +{ + public interface IBasketService + { + Task GetById(string id); + Task Update(BasketData currentBasket); + + } +} diff --git a/src/ApiGateways/Web.Bff.Shopping/aggregator/Services/ICatalogService.cs b/src/ApiGateways/Web.Bff.Shopping/aggregator/Services/ICatalogService.cs new file mode 100644 index 000000000..7d192f3cc --- /dev/null +++ b/src/ApiGateways/Web.Bff.Shopping/aggregator/Services/ICatalogService.cs @@ -0,0 +1,14 @@ +using Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Models; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Services +{ + public interface ICatalogService + { + Task GetCatalogItem(int id); + Task> GetCatalogItems(IEnumerable ids); + } +} diff --git a/src/ApiGateways/Web.Bff.Shopping/aggregator/Services/IOrderApiClient.cs b/src/ApiGateways/Web.Bff.Shopping/aggregator/Services/IOrderApiClient.cs new file mode 100644 index 000000000..c97eccbbd --- /dev/null +++ b/src/ApiGateways/Web.Bff.Shopping/aggregator/Services/IOrderApiClient.cs @@ -0,0 +1,13 @@ +using Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Models; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Services +{ + public interface IOrderApiClient + { + Task GetOrderDraftFromBasket(BasketData basket); + } +} diff --git a/src/ApiGateways/Web.Bff.Shopping/aggregator/Services/OrderApiClient.cs b/src/ApiGateways/Web.Bff.Shopping/aggregator/Services/OrderApiClient.cs new file mode 100644 index 000000000..220e9afa9 --- /dev/null +++ b/src/ApiGateways/Web.Bff.Shopping/aggregator/Services/OrderApiClient.cs @@ -0,0 +1,37 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.eShopOnContainers.BuildingBlocks.Resilience.Http; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; +using Newtonsoft.Json; +using Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Config; +using Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Models; + +namespace Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Services +{ + public class OrderApiClient : IOrderApiClient + { + + private readonly IHttpClient _apiClient; + private readonly ILogger _logger; + private readonly UrlsConfig _urls; + + public OrderApiClient(IHttpClient httpClient, ILogger logger, IOptionsSnapshot config) + { + _apiClient = httpClient; + _logger = logger; + _urls = config.Value; + } + + public async Task GetOrderDraftFromBasket(BasketData basket) + { + var url = _urls.Orders + UrlsConfig.OrdersOperations.GetOrderDraft(); + var response = await _apiClient.PostAsync(url, basket); + response.EnsureSuccessStatusCode(); + var jsonResponse = await response.Content.ReadAsStringAsync(); + return JsonConvert.DeserializeObject(jsonResponse); + } + } +} diff --git a/src/ApiGateways/Web.Bff.Shopping/aggregator/Startup.cs b/src/ApiGateways/Web.Bff.Shopping/aggregator/Startup.cs new file mode 100644 index 000000000..17f9f90e6 --- /dev/null +++ b/src/ApiGateways/Web.Bff.Shopping/aggregator/Startup.cs @@ -0,0 +1,138 @@ +using System; +using System.Collections.Generic; +using System.IdentityModel.Tokens.Jwt; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Authentication.JwtBearer; +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Hosting; +using Microsoft.AspNetCore.Http; +using Microsoft.eShopOnContainers.BuildingBlocks.Resilience.Http; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; +using Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Config; +using Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Filters.Basket.API.Infrastructure.Filters; +using Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Services; +using Swashbuckle.AspNetCore.Swagger; + +namespace Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator +{ + public class Startup + { + public Startup(IConfiguration configuration) + { + Configuration = configuration; + } + + public IConfiguration Configuration { get; } + + // This method gets called by the runtime. Use this method to add services to the container. + public void ConfigureServices(IServiceCollection services) + { + services.AddSingleton(); + services.AddSingleton(); + services.AddTransient(); + services.AddTransient(); + services.AddTransient(); + + services.AddOptions(); + services.Configure(Configuration.GetSection("urls")); + + services.AddMvc(); + + services.AddSwaggerGen(options => + { + options.DescribeAllEnumsAsStrings(); + options.SwaggerDoc("v1", new Swashbuckle.AspNetCore.Swagger.Info + { + Title = "Shopping Aggregator for Web Clients", + Version = "v1", + Description = "Shopping Aggregator for Web Clients", + TermsOfService = "Terms Of Service" + }); + + options.AddSecurityDefinition("oauth2", new OAuth2Scheme + { + Type = "oauth2", + Flow = "implicit", + AuthorizationUrl = $"{Configuration.GetValue("IdentityUrlExternal")}/connect/authorize", + TokenUrl = $"{Configuration.GetValue("IdentityUrlExternal")}/connect/token", + Scopes = new Dictionary() + { + { "webshoppingagg", "Shopping Aggregator for Web Clients" } + } + }); + + options.OperationFilter(); + }); + + services.AddCors(options => + { + options.AddPolicy("CorsPolicy", + builder => builder.AllowAnyOrigin() + .AllowAnyMethod() + .AllowAnyHeader() + .AllowCredentials()); + }); + + + JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear(); + var identityUrl = Configuration.GetValue("urls:identity"); + services.AddAuthentication(options => + { + options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme; + options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme; + + }).AddJwtBearer(options => + { + options.Authority = identityUrl; + options.RequireHttpsMetadata = false; + options.Audience = "webshoppingagg"; + options.Events = new JwtBearerEvents() + { + OnAuthenticationFailed = async ctx => + { + int i = 0; + }, + OnTokenValidated = async ctx => + { + int i = 0; + } + }; + }); + } + + // 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) + { + + var pathBase = Configuration["PATH_BASE"]; + if (!string.IsNullOrEmpty(pathBase)) + { + loggerFactory.CreateLogger("init").LogDebug($"Using PATH BASE '{pathBase}'"); + app.UsePathBase(pathBase); + } + + app.UseCors("CorsPolicy"); + + if (env.IsDevelopment()) + { + app.UseDeveloperExceptionPage(); + } + + app.UseAuthentication(); + + app.UseMvc(); + + app.UseSwagger().UseSwaggerUI(c => + { + c.SwaggerEndpoint($"{ (!string.IsNullOrEmpty(pathBase) ? pathBase : string.Empty) }/swagger/v1/swagger.json", "Purchase BFF V1"); + c.ConfigureOAuth2("Microsoft.eShopOnContainers.Web.Shopping.HttpAggregatorwaggerui", "", "", "Purchase BFF Swagger UI"); + }); + + + } + } +} diff --git a/src/ApiGateways/Web.Bff.Shopping/aggregator/Web.Shopping.HttpAggregator.csproj b/src/ApiGateways/Web.Bff.Shopping/aggregator/Web.Shopping.HttpAggregator.csproj new file mode 100644 index 000000000..0b6dbf44b --- /dev/null +++ b/src/ApiGateways/Web.Bff.Shopping/aggregator/Web.Shopping.HttpAggregator.csproj @@ -0,0 +1,27 @@ + + + + netcoreapp2.0 + Web.Shopping.HttpAggregator + Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator + ..\..\..\docker-compose.dcproj + + + + + + + + + + + + + + + + + + + + diff --git a/src/ApiGateways/Web.Bff.Shopping/aggregator/appsettings.json b/src/ApiGateways/Web.Bff.Shopping/aggregator/appsettings.json new file mode 100644 index 000000000..26bb0ac7a --- /dev/null +++ b/src/ApiGateways/Web.Bff.Shopping/aggregator/appsettings.json @@ -0,0 +1,15 @@ +{ + "Logging": { + "IncludeScopes": false, + "Debug": { + "LogLevel": { + "Default": "Warning" + } + }, + "Console": { + "LogLevel": { + "Default": "Warning" + } + } + } +} diff --git a/src/ApiGateways/Web.Bff.Shopping/aggregator/appsettings.localhost.json b/src/ApiGateways/Web.Bff.Shopping/aggregator/appsettings.localhost.json new file mode 100644 index 000000000..57b5e894d --- /dev/null +++ b/src/ApiGateways/Web.Bff.Shopping/aggregator/appsettings.localhost.json @@ -0,0 +1,8 @@ +{ + "urls": { + "basket": "http://localhost:55105", + "catalog": "http://localhost:55101", + "orders": "http://localhost:55102", + "identity": "http://localhost:55105" + } +} diff --git a/src/ApiGateways/Web.Bff.Shopping/apigw/configuration.json b/src/ApiGateways/Web.Bff.Shopping/apigw/configuration.json new file mode 100644 index 000000000..63aeb7752 --- /dev/null +++ b/src/ApiGateways/Web.Bff.Shopping/apigw/configuration.json @@ -0,0 +1,142 @@ +{ + "ReRoutes": [ + { + "DownstreamPathTemplate": "/api/{version}/{everything}", + "DownstreamScheme": "http", + "DownstreamHostAndPorts": [ + { + "Host": "catalog.api", + "Port": 80 + } + ], + "UpstreamPathTemplate": "/api/{version}/c/{everything}", + "UpstreamHttpMethod": [ "GET" ] + }, + { + "DownstreamPathTemplate": "/api/{version}/{everything}", + "DownstreamScheme": "http", + "DownstreamHostAndPorts": [ + { + "Host": "basket.api", + "Port": 80 + } + ], + "UpstreamPathTemplate": "/api/{version}/b/{everything}", + "UpstreamHttpMethod": [], + "AuthenticationOptions": { + "AuthenticationProviderKey": "IdentityApiKey", + "AllowedScopes": [] + } + }, + { + "DownstreamPathTemplate": "/api/{version}/{everything}", + "DownstreamScheme": "http", + "DownstreamHostAndPorts": [ + { + "Host": "ordering.api", + "Port": 80 + } + ], + "UpstreamPathTemplate": "/api/{version}/o/{everything}", + "UpstreamHttpMethod": [], + "AuthenticationOptions": { + "AuthenticationProviderKey": "IdentityApiKey", + "AllowedScopes": [] + } + }, + { + "DownstreamPathTemplate": "/{everything}", + "DownstreamScheme": "http", + "DownstreamHostAndPorts": [ + { + "Host": "webshoppingagg", + "Port": 80 + } + ], + "UpstreamPathTemplate": "/{everything}", + "UpstreamHttpMethod": [ "POST", "PUT", "GET" ], + "AuthenticationOptions": { + "AuthenticationProviderKey": "IdentityApiKey", + "AllowedScopes": [] + } + }, + { + "DownstreamPathTemplate": "/{everything}", + "DownstreamScheme": "http", + "DownstreamHostAndPorts": [ + { + "Host": "ordering.api", + "Port": 80 + } + ], + "UpstreamPathTemplate": "/orders-api/{everything}", + "UpstreamHttpMethod": [] + }, + { + "DownstreamPathTemplate": "/{everything}", + "DownstreamScheme": "http", + "DownstreamHostAndPorts": [ + { + "Host": "basket.api", + "Port": 80 + } + ], + "UpstreamPathTemplate": "/basket-api/{everything}", + "UpstreamHttpMethod": [] + }, + { + "DownstreamPathTemplate": "/{everything}", + "DownstreamScheme": "http", + "DownstreamHostAndPorts": [ + { + "Host": "catalog.api", + "Port": 80 + } + ], + "UpstreamPathTemplate": "/catalog-api/{everything}", + "UpstreamHttpMethod": [] + }, + { + "DownstreamPathTemplate": "/{everything}", + "DownstreamScheme": "http", + "DownstreamHostAndPorts": [ + { + "Host": "marketing.api", + "Port": 80 + } + ], + "UpstreamPathTemplate": "/marketing-api/{everything}", + "UpstreamHttpMethod": [] + }, + { + "DownstreamPathTemplate": "/{everything}", + "DownstreamScheme": "http", + "DownstreamHostAndPorts": [ + { + "Host": "payment.api", + "Port": 80 + } + ], + "UpstreamPathTemplate": "/payment-api/{everything}", + "UpstreamHttpMethod": [] + }, + { + "DownstreamPathTemplate": "/{everything}", + "DownstreamScheme": "http", + "DownstreamHostAndPorts": [ + { + "Host": "locations.api", + "Port": 80 + } + ], + "UpstreamPathTemplate": "/location-api/{everything}", + "UpstreamHttpMethod": [] + } + + ], + "GlobalConfiguration": { + "RequestIdKey": "OcRequestId", + "AdministrationPath": "/administration" + } + } + \ No newline at end of file diff --git a/src/BuildingBlocks/Resilience/Resilience.Http/ResilientHttpClient.cs b/src/BuildingBlocks/Resilience/Resilience.Http/ResilientHttpClient.cs index 18051a501..9fa38ee8d 100644 --- a/src/BuildingBlocks/Resilience/Resilience.Http/ResilientHttpClient.cs +++ b/src/BuildingBlocks/Resilience/Resilience.Http/ResilientHttpClient.cs @@ -97,6 +97,11 @@ namespace Microsoft.eShopOnContainers.BuildingBlocks.Resilience.Http throw new HttpRequestException(); } + if (!response.IsSuccessStatusCode) + { + return null; + } + return await response.Content.ReadAsStringAsync(); }); } diff --git a/src/BuildingBlocks/Resilience/Resilience.Http/StandardHttpClient.cs b/src/BuildingBlocks/Resilience/Resilience.Http/StandardHttpClient.cs index a5f6a63c4..578168bff 100644 --- a/src/BuildingBlocks/Resilience/Resilience.Http/StandardHttpClient.cs +++ b/src/BuildingBlocks/Resilience/Resilience.Http/StandardHttpClient.cs @@ -36,6 +36,11 @@ namespace Microsoft.eShopOnContainers.BuildingBlocks.Resilience.Http var response = await _client.SendAsync(requestMessage); + if (!response.IsSuccessStatusCode) + { + return null; + } + return await response.Content.ReadAsStringAsync(); } diff --git a/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Extensions/ObservableExtension.cs b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Extensions/ObservableExtension.cs index ad10bd941..800f9a031 100644 --- a/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Extensions/ObservableExtension.cs +++ b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Extensions/ObservableExtension.cs @@ -15,7 +15,6 @@ namespace eShopOnContainers.Core.Extensions } return collection; - } } } \ No newline at end of file diff --git a/src/Mobile/eShopOnContainers/eShopOnContainers.Core/GlobalSettings.cs b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/GlobalSettings.cs index d501a5d46..e1637d7be 100644 --- a/src/Mobile/eShopOnContainers/eShopOnContainers.Core/GlobalSettings.cs +++ b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/GlobalSettings.cs @@ -4,7 +4,7 @@ { public const string AzureTag = "Azure"; public const string MockTag = "Mock"; - public const string DefaultEndpoint = "http://13.88.8.119"; + public const string DefaultEndpoint = "http://YOUR_IP_OR_DNS_NAME"; // i.e.: "http://YOUR_IP" or "http://YOUR_DNS_NAME" private string _baseEndpoint; private static readonly GlobalSetting _instance = new GlobalSetting(); @@ -38,18 +38,8 @@ public string RegisterWebsite { get; set; } - public string CatalogEndpoint { get; set; } - - public string OrdersEndpoint { get; set; } - - public string BasketEndpoint { get; set; } - public string IdentityEndpoint { get; set; } - public string LocationEndpoint { get; set; } - - public string MarketingEndpoint { get; set; } - public string UserInfoEndpoint { get; set; } public string TokenEndpoint { get; set; } @@ -62,18 +52,17 @@ private void UpdateEndpoint(string baseEndpoint) { - RegisterWebsite = $"{baseEndpoint}:5105/Account/Register"; - CatalogEndpoint = $"{baseEndpoint}:5101"; - OrdersEndpoint = $"{baseEndpoint}:5102"; - BasketEndpoint = $"{baseEndpoint}:5103"; - IdentityEndpoint = $"{baseEndpoint}:5105/connect/authorize"; - UserInfoEndpoint = $"{baseEndpoint}:5105/connect/userinfo"; - TokenEndpoint = $"{baseEndpoint}:5105/connect/token"; - LogoutEndpoint = $"{baseEndpoint}:5105/connect/endsession"; - IdentityCallback = $"{baseEndpoint}:5105/xamarincallback"; - LogoutCallback = $"{baseEndpoint}:5105/Account/Redirecting"; - LocationEndpoint = $"{baseEndpoint}:5109"; - MarketingEndpoint = $"{baseEndpoint}:5110"; + var identityBaseEndpoint = $"{baseEndpoint}/identity"; + RegisterWebsite = $"{identityBaseEndpoint}/Account/Register"; + LogoutCallback = $"{identityBaseEndpoint}/Account/Redirecting"; + + var connectBaseEndpoint = $"{identityBaseEndpoint}/connect"; + IdentityEndpoint = $"{connectBaseEndpoint}/authorize"; + UserInfoEndpoint = $"{connectBaseEndpoint}/userinfo"; + TokenEndpoint = $"{connectBaseEndpoint}/token"; + LogoutEndpoint = $"{connectBaseEndpoint}/endsession"; + + IdentityCallback = $"{baseEndpoint}/xamarincallback"; } } } \ No newline at end of file diff --git a/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Services/Basket/BasketService.cs b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Services/Basket/BasketService.cs index 54f3a03bc..b36488f24 100644 --- a/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Services/Basket/BasketService.cs +++ b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Services/Basket/BasketService.cs @@ -11,7 +11,7 @@ namespace eShopOnContainers.Core.Services.Basket private readonly IRequestProvider _requestProvider; private readonly IFixUriService _fixUriService; - private const string ApiUrlBase = "api/v1/basket"; + private const string ApiUrlBase = "mobileshoppingapigw/api/v1/b/basket"; public BasketService(IRequestProvider requestProvider, IFixUriService fixUriService) { @@ -21,15 +21,23 @@ namespace eShopOnContainers.Core.Services.Basket public async Task GetBasketAsync(string guidUser, string token) { - var builder = new UriBuilder(GlobalSetting.Instance.BasketEndpoint) + var builder = new UriBuilder(GlobalSetting.Instance.BaseEndpoint) { Path = $"{ApiUrlBase}/{guidUser}" }; var uri = builder.ToString(); - CustomerBasket basket = - await _requestProvider.GetAsync(uri, token); + CustomerBasket basket; + + try + { + basket = await _requestProvider.GetAsync(uri, token); + } + catch (HttpRequestExceptionEx exception) when (exception.HttpCode == System.Net.HttpStatusCode.NotFound) + { + basket = null; + } _fixUriService.FixBasketItemPictureUri(basket?.Items); return basket; @@ -37,7 +45,7 @@ namespace eShopOnContainers.Core.Services.Basket public async Task UpdateBasketAsync(CustomerBasket customerBasket, string token) { - var builder = new UriBuilder(GlobalSetting.Instance.BasketEndpoint) + var builder = new UriBuilder(GlobalSetting.Instance.BaseEndpoint) { Path = ApiUrlBase }; @@ -49,7 +57,7 @@ namespace eShopOnContainers.Core.Services.Basket public async Task CheckoutAsync(BasketCheckout basketCheckout, string token) { - var builder = new UriBuilder(GlobalSetting.Instance.BasketEndpoint) + var builder = new UriBuilder(GlobalSetting.Instance.BaseEndpoint) { Path = $"{ApiUrlBase}/checkout" }; @@ -60,7 +68,7 @@ namespace eShopOnContainers.Core.Services.Basket public async Task ClearBasketAsync(string guidUser, string token) { - var builder = new UriBuilder(GlobalSetting.Instance.BasketEndpoint) + var builder = new UriBuilder(GlobalSetting.Instance.BaseEndpoint) { Path = $"{ApiUrlBase}/{guidUser}" }; diff --git a/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Services/Catalog/CatalogService.cs b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Services/Catalog/CatalogService.cs index 2e63e9516..2811416ad 100644 --- a/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Services/Catalog/CatalogService.cs +++ b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Services/Catalog/CatalogService.cs @@ -13,6 +13,8 @@ namespace eShopOnContainers.Core.Services.Catalog { private readonly IRequestProvider _requestProvider; private readonly IFixUriService _fixUriService; + + private const string ApiUrlBase = "mobileshoppingapigw/api/v1/c/catalog"; public CatalogService(IRequestProvider requestProvider, IFixUriService fixUriService) { @@ -22,8 +24,8 @@ namespace eShopOnContainers.Core.Services.Catalog public async Task> FilterAsync(int catalogBrandId, int catalogTypeId) { - UriBuilder builder = new UriBuilder(GlobalSetting.Instance.CatalogEndpoint); - builder.Path = string.Format("api/v1/catalog/items/type/{0}/brand/{1}", catalogTypeId, catalogBrandId); + UriBuilder builder = new UriBuilder(GlobalSetting.Instance.BaseEndpoint); + builder.Path = $"{ApiUrlBase}/items/type/{catalogTypeId}/brand/{catalogBrandId}"; string uri = builder.ToString(); CatalogRoot catalog = await _requestProvider.GetAsync(uri); @@ -36,8 +38,8 @@ namespace eShopOnContainers.Core.Services.Catalog public async Task> GetCatalogAsync() { - UriBuilder builder = new UriBuilder(GlobalSetting.Instance.CatalogEndpoint); - builder.Path = "api/v1/catalog/items"; + UriBuilder builder = new UriBuilder(GlobalSetting.Instance.BaseEndpoint); + builder.Path = $"{ApiUrlBase}/items"; string uri = builder.ToString(); CatalogRoot catalog = await _requestProvider.GetAsync(uri); @@ -53,8 +55,8 @@ namespace eShopOnContainers.Core.Services.Catalog public async Task> GetCatalogBrandAsync() { - UriBuilder builder = new UriBuilder(GlobalSetting.Instance.CatalogEndpoint); - builder.Path = "api/v1/catalog/catalogbrands"; + UriBuilder builder = new UriBuilder(GlobalSetting.Instance.BaseEndpoint); + builder.Path = $"{ApiUrlBase}/catalogbrands"; string uri = builder.ToString(); IEnumerable brands = await _requestProvider.GetAsync>(uri); @@ -67,8 +69,8 @@ namespace eShopOnContainers.Core.Services.Catalog public async Task> GetCatalogTypeAsync() { - UriBuilder builder = new UriBuilder(GlobalSetting.Instance.CatalogEndpoint); - builder.Path = "api/v1/catalog/catalogtypes"; + UriBuilder builder = new UriBuilder(GlobalSetting.Instance.BaseEndpoint); + builder.Path = $"{ApiUrlBase}/catalogtypes"; string uri = builder.ToString(); IEnumerable types = await _requestProvider.GetAsync>(uri); diff --git a/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Services/Location/LocationService.cs b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Services/Location/LocationService.cs index f20ae6339..e18d335c0 100644 --- a/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Services/Location/LocationService.cs +++ b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Services/Location/LocationService.cs @@ -15,8 +15,8 @@ namespace eShopOnContainers.Core.Services.Location public async Task UpdateUserLocation(eShopOnContainers.Core.Models.Location.Location newLocReq, string token) { - UriBuilder builder = new UriBuilder(GlobalSetting.Instance.LocationEndpoint); - builder.Path = "api/v1/locations"; + UriBuilder builder = new UriBuilder(GlobalSetting.Instance.BaseEndpoint); + builder.Path = "/mobilemarketingapigw/api/v1/l/locations"; string uri = builder.ToString(); await _requestProvider.PostAsync(uri, newLocReq, token); } diff --git a/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Services/Marketing/CampaignService.cs b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Services/Marketing/CampaignService.cs index cb74f11b0..2fa5eaa9e 100644 --- a/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Services/Marketing/CampaignService.cs +++ b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Services/Marketing/CampaignService.cs @@ -13,6 +13,8 @@ namespace eShopOnContainers.Core.Services.Marketing private readonly IRequestProvider _requestProvider; private readonly IFixUriService _fixUriService; + private const string ApiUrlBase = "mobilemarketingapigw/api/v1/m/campaigns"; + public CampaignService(IRequestProvider requestProvider, IFixUriService fixUriService) { _requestProvider = requestProvider; @@ -21,8 +23,8 @@ namespace eShopOnContainers.Core.Services.Marketing public async Task> GetAllCampaignsAsync(string token) { - UriBuilder builder = new UriBuilder(GlobalSetting.Instance.MarketingEndpoint); - builder.Path = "api/v1/campaigns/user"; + UriBuilder builder = new UriBuilder(GlobalSetting.Instance.BaseEndpoint); + builder.Path = $"{ApiUrlBase}/user"; string uri = builder.ToString(); CampaignRoot campaign = await _requestProvider.GetAsync(uri, token); @@ -38,8 +40,8 @@ namespace eShopOnContainers.Core.Services.Marketing public async Task GetCampaignByIdAsync(int campaignId, string token) { - UriBuilder builder = new UriBuilder(GlobalSetting.Instance.MarketingEndpoint); - builder.Path = $"api/v1/campaigns/{campaignId}"; + UriBuilder builder = new UriBuilder(GlobalSetting.Instance.BaseEndpoint); + builder.Path = $"{ApiUrlBase}/{campaignId}"; string uri = builder.ToString(); return await _requestProvider.GetAsync(uri, token); } diff --git a/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Services/Order/OrderService.cs b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Services/Order/OrderService.cs index f242971fb..fb9a0c627 100644 --- a/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Services/Order/OrderService.cs +++ b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Services/Order/OrderService.cs @@ -11,6 +11,8 @@ namespace eShopOnContainers.Core.Services.Order { private readonly IRequestProvider _requestProvider; + private const string ApiUrlBase = "mobileshoppingapigw/api/v1/o/orders"; + public OrderService(IRequestProvider requestProvider) { _requestProvider = requestProvider; @@ -23,9 +25,9 @@ namespace eShopOnContainers.Core.Services.Order public async Task> GetOrdersAsync(string token) { - UriBuilder builder = new UriBuilder(GlobalSetting.Instance.OrdersEndpoint); + UriBuilder builder = new UriBuilder(GlobalSetting.Instance.BaseEndpoint); - builder.Path = "api/v1/orders"; + builder.Path = ApiUrlBase; string uri = builder.ToString(); @@ -40,9 +42,9 @@ namespace eShopOnContainers.Core.Services.Order { try { - UriBuilder builder = new UriBuilder(GlobalSetting.Instance.OrdersEndpoint); + UriBuilder builder = new UriBuilder(GlobalSetting.Instance.BaseEndpoint); - builder.Path = string.Format("api/v1/orders/{0}", orderId); + builder.Path = $"{ApiUrlBase}/{orderId}"; string uri = builder.ToString(); @@ -76,9 +78,9 @@ namespace eShopOnContainers.Core.Services.Order public async Task CancelOrderAsync(int orderId, string token) { - UriBuilder builder = new UriBuilder(GlobalSetting.Instance.OrdersEndpoint); + UriBuilder builder = new UriBuilder(GlobalSetting.Instance.BaseEndpoint); - builder.Path = "api/v1/orders/cancel"; + builder.Path = $"{ApiUrlBase}/cancel"; var cancelOrderCommand = new CancelOrderCommand(orderId); diff --git a/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Services/Settings/ISettingsService.cs b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Services/Settings/ISettingsService.cs index 5e2732bf9..69ede7b72 100644 --- a/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Services/Settings/ISettingsService.cs +++ b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Services/Settings/ISettingsService.cs @@ -1,4 +1,6 @@ -namespace eShopOnContainers.Core.Services.Settings +using System.Threading.Tasks; + +namespace eShopOnContainers.Core.Services.Settings { public interface ISettingsService { @@ -10,5 +12,10 @@ string Latitude { get; set; } string Longitude { get; set; } bool AllowGpsLocation { get; set; } + + bool GetValueOrDefault(string key, bool defaultValue); + string GetValueOrDefault(string key, string defaultValue); + Task AddOrUpdateValue(string key, bool value); + Task AddOrUpdateValue(string key, string value); } } diff --git a/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Services/Settings/ISettingsServiceImplementation.cs b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Services/Settings/ISettingsServiceImplementation.cs deleted file mode 100644 index ef9d14ed6..000000000 --- a/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Services/Settings/ISettingsServiceImplementation.cs +++ /dev/null @@ -1,13 +0,0 @@ -namespace eShopOnContainers.Core.Services.Settings -{ - public interface ISettingsServiceImplementation - { - bool GetValueOrDefault(string key, bool defaultValue); - string GetValueOrDefault(string key, string defaultValue); - - bool AddOrUpdateValue(string key, bool value); - bool AddOrUpdateValue(string key, string value); - - void Remove(string key); - } -} diff --git a/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Services/Settings/SettingsService.cs b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Services/Settings/SettingsService.cs index a13f53187..ca3e03c04 100644 --- a/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Services/Settings/SettingsService.cs +++ b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Services/Settings/SettingsService.cs @@ -1,21 +1,11 @@ -using eShopOnContainers.Core.Services.Dependency; +using System; +using System.Threading.Tasks; +using Xamarin.Forms; namespace eShopOnContainers.Core.Services.Settings { public class SettingsService : ISettingsService { - private readonly ISettingsServiceImplementation _settingsService; - - ISettingsServiceImplementation AppSettings - { - get { return _settingsService; } - } - - public SettingsService(IDependencyService dependencyService) - { - _settingsService = dependencyService.Get(); - } - #region Setting Constants private const string AccessToken = "access_token"; @@ -37,52 +27,113 @@ namespace eShopOnContainers.Core.Services.Settings #endregion + #region Settings Properties + public string AuthAccessToken { - get => AppSettings.GetValueOrDefault(AccessToken, AccessTokenDefault); - set => AppSettings.AddOrUpdateValue(AccessToken, value); + get => GetValueOrDefault(AccessToken, AccessTokenDefault); + set => AddOrUpdateValue(AccessToken, value); } public string AuthIdToken { - get => AppSettings.GetValueOrDefault(IdToken, IdTokenDefault); - set => AppSettings.AddOrUpdateValue(IdToken, value); + get => GetValueOrDefault(IdToken, IdTokenDefault); + set => AddOrUpdateValue(IdToken, value); } public bool UseMocks { - get => AppSettings.GetValueOrDefault(IdUseMocks, UseMocksDefault); - set => AppSettings.AddOrUpdateValue(IdUseMocks, value); + get => GetValueOrDefault(IdUseMocks, UseMocksDefault); + set => AddOrUpdateValue(IdUseMocks, value); } public string UrlBase { - get => AppSettings.GetValueOrDefault(IdUrlBase, UrlBaseDefault); - set => AppSettings.AddOrUpdateValue(IdUrlBase, value); + get => GetValueOrDefault(IdUrlBase, UrlBaseDefault); + set => AddOrUpdateValue(IdUrlBase, value); } public bool UseFakeLocation { - get => AppSettings.GetValueOrDefault(IdUseFakeLocation, UseFakeLocationDefault); - set => AppSettings.AddOrUpdateValue(IdUseFakeLocation, value); + get => GetValueOrDefault(IdUseFakeLocation, UseFakeLocationDefault); + set => AddOrUpdateValue(IdUseFakeLocation, value); } public string Latitude { - get => AppSettings.GetValueOrDefault(IdLatitude, FakeLatitudeDefault.ToString()); - set => AppSettings.AddOrUpdateValue(IdLatitude, value); + get => GetValueOrDefault(IdLatitude, FakeLatitudeDefault.ToString()); + set => AddOrUpdateValue(IdLatitude, value); } public string Longitude { - get => AppSettings.GetValueOrDefault(IdLongitude, FakeLongitudeDefault.ToString()); - set => AppSettings.AddOrUpdateValue(IdLongitude, value); + get => GetValueOrDefault(IdLongitude, FakeLongitudeDefault.ToString()); + set => AddOrUpdateValue(IdLongitude, value); } public bool AllowGpsLocation { - get => AppSettings.GetValueOrDefault(IdAllowGpsLocation, AllowGpsLocationDefault); - set => AppSettings.AddOrUpdateValue(IdAllowGpsLocation, value); + get => GetValueOrDefault(IdAllowGpsLocation, AllowGpsLocationDefault); + set => AddOrUpdateValue(IdAllowGpsLocation, value); } + + #endregion + + #region Public Methods + + public Task AddOrUpdateValue(string key, bool value) => AddOrUpdateValueInternal(key, value); + public Task AddOrUpdateValue(string key, string value) => AddOrUpdateValueInternal(key, value); + public bool GetValueOrDefault(string key, bool defaultValue) => GetValueOrDefaultInternal(key, defaultValue); + public string GetValueOrDefault(string key, string defaultValue) => GetValueOrDefaultInternal(key, defaultValue); + + #endregion + + #region Internal Implementation + + async Task AddOrUpdateValueInternal(string key, T value) + { + if (value == null) + { + await Remove(key); + } + + Application.Current.Properties[key] = value; + try + { + await Application.Current.SavePropertiesAsync(); + } + catch (Exception ex) + { + Console.WriteLine("Unable to save: " + key, " Message: " + ex.Message); + } + } + + T GetValueOrDefaultInternal(string key, T defaultValue = default(T)) + { + object value = null; + if (Application.Current.Properties.ContainsKey(key)) + { + value = Application.Current.Properties[key]; + } + return null != value ? (T)value : defaultValue; + } + + async Task Remove(string key) + { + try + { + if (Application.Current.Properties[key] != null) + { + Application.Current.Properties.Remove(key); + await Application.Current.SavePropertiesAsync(); + } + } + catch (Exception ex) + { + Console.WriteLine("Unable to remove: " + key, " Message: " + ex.Message); + } + } + + #endregion } } \ No newline at end of file diff --git a/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Views/LoginView.xaml b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Views/LoginView.xaml index f6b9bd72c..2bccd06d6 100644 --- a/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Views/LoginView.xaml +++ b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Views/LoginView.xaml @@ -337,28 +337,14 @@ Grid.RowSpan="2" IsVisible="{Binding IsLogin}"> + Source="{Binding LoginUrl}" + AbsoluteLayout.LayoutBounds="0, 0, 1, 1" + AbsoluteLayout.LayoutFlags="All"> - - - - - - - - - - - - + diff --git a/src/Mobile/eShopOnContainers/eShopOnContainers.Droid/Extensions/LocationExtensions.cs b/src/Mobile/eShopOnContainers/eShopOnContainers.Droid/Extensions/LocationExtensions.cs index 41ea2ad3e..031c186aa 100644 --- a/src/Mobile/eShopOnContainers/eShopOnContainers.Droid/Extensions/LocationExtensions.cs +++ b/src/Mobile/eShopOnContainers/eShopOnContainers.Droid/Extensions/LocationExtensions.cs @@ -32,7 +32,7 @@ namespace eShopOnContainers.Droid.Extensions { return new DateTimeOffset(Epoch.AddMilliseconds(location.Time)); } - catch (Exception e) + catch (Exception) { return new DateTimeOffset(Epoch); } diff --git a/src/Mobile/eShopOnContainers/eShopOnContainers.Droid/Services/SettingsServiceImplementation.cs b/src/Mobile/eShopOnContainers/eShopOnContainers.Droid/Services/SettingsServiceImplementation.cs deleted file mode 100644 index 7cdce4555..000000000 --- a/src/Mobile/eShopOnContainers/eShopOnContainers.Droid/Services/SettingsServiceImplementation.cs +++ /dev/null @@ -1,149 +0,0 @@ -using Android.App; -using Android.Content; -using Android.Preferences; -using eShopOnContainers.Core.Services.Settings; -using eShopOnContainers.Droid.Services; -using System; - -[assembly: Xamarin.Forms.Dependency(typeof(SettingsServiceImplementation))] -namespace eShopOnContainers.Droid.Services -{ - public class SettingsServiceImplementation : ISettingsServiceImplementation - { - #region Internal Implementation - - readonly object _locker = new object(); - - ISharedPreferences GetSharedPreference() - { - return PreferenceManager.GetDefaultSharedPreferences(Application.Context); - } - - bool AddOrUpdateValueInternal(string key, T value) - { - if (Application.Context == null) - return false; - - if (value == null) - { - Remove(key); - return true; - } - - var type = typeof(T); - if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>)) - { - type = Nullable.GetUnderlyingType(type); - } - var typeCode = Type.GetTypeCode(type); - - lock (_locker) - { - using (var sharedPrefs = GetSharedPreference()) - { - using (var editor = sharedPrefs.Edit()) - { - switch (typeCode) - { - case TypeCode.Boolean: - editor.PutBoolean(key, Convert.ToBoolean(value)); - break; - case TypeCode.String: - editor.PutString(key, Convert.ToString(value)); - break; - default: - throw new ArgumentException($"Value of type {typeCode} is not supported."); - } - editor.Commit(); - } - } - } - return true; - } - - T GetValueOrDefaultInternal(string key, T defaultValue = default(T)) - { - if (Application.Context == null) - return defaultValue; - - if (!Contains(key)) - return defaultValue; - - lock (_locker) - { - using (var sharedPrefs = GetSharedPreference()) - { - var type = typeof(T); - if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>)) - { - type = Nullable.GetUnderlyingType(type); - } - - object value = null; - var typeCode = Type.GetTypeCode(type); - switch (typeCode) - { - case TypeCode.Boolean: - value = sharedPrefs.GetBoolean(key, Convert.ToBoolean(defaultValue)); - break; - case TypeCode.String: - value = sharedPrefs.GetString(key, Convert.ToString(defaultValue)); - break; - default: - throw new ArgumentException($"Value of type {typeCode} is not supported."); - } - - return null != value ? (T)value : defaultValue; - } - } - } - - bool Contains(string key) - { - if (Application.Context == null) - return false; - - lock (_locker) - { - using (var sharedPrefs = GetSharedPreference()) - { - if (sharedPrefs == null) - return false; - return sharedPrefs.Contains(key); - } - } - } - - #endregion - - #region ISettingsServiceImplementation - - public bool AddOrUpdateValue(string key, bool value) => AddOrUpdateValueInternal(key, value); - - public bool AddOrUpdateValue(string key, string value) => AddOrUpdateValueInternal(key, value); - - public bool GetValueOrDefault(string key, bool defaultValue) => GetValueOrDefaultInternal(key, defaultValue); - - public string GetValueOrDefault(string key, string defaultValue) => GetValueOrDefaultInternal(key, defaultValue); - - public void Remove(string key) - { - if (Application.Context == null) - return; - - lock (_locker) - { - using (var sharedPrefs = GetSharedPreference()) - { - using (var editor = sharedPrefs.Edit()) - { - editor.Remove(key); - editor.Commit(); - } - } - } - } - - #endregion - } -} diff --git a/src/Mobile/eShopOnContainers/eShopOnContainers.Droid/eShopOnContainers.Droid.csproj b/src/Mobile/eShopOnContainers/eShopOnContainers.Droid/eShopOnContainers.Droid.csproj index 7d699f9d2..92e2df581 100644 --- a/src/Mobile/eShopOnContainers/eShopOnContainers.Droid/eShopOnContainers.Droid.csproj +++ b/src/Mobile/eShopOnContainers/eShopOnContainers.Droid/eShopOnContainers.Droid.csproj @@ -19,7 +19,7 @@ Off Properties\AndroidManifest.xml true - v8.0 + v8.1 armeabi,armeabi-v7a,x86 @@ -211,7 +211,6 @@ - diff --git a/src/Mobile/eShopOnContainers/eShopOnContainers.Droid/eShopOnContainers.Droid.csproj.bak b/src/Mobile/eShopOnContainers/eShopOnContainers.Droid/eShopOnContainers.Droid.csproj.bak deleted file mode 100644 index 8a2babd2e..000000000 --- a/src/Mobile/eShopOnContainers/eShopOnContainers.Droid/eShopOnContainers.Droid.csproj.bak +++ /dev/null @@ -1,429 +0,0 @@ - - - - - Debug - AnyCPU - 8.0.30703 - 2.0 - {62DBB163-9CA9-4818-B48B-13233DF37C24} - {EFBA0AD7-5A72-4C68-AF49-83D382785DCF};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} - Library - Properties - eShopOnContainers.Droid - eShopOnContainers.Droid - 512 - true - Resources\Resource.Designer.cs - Off - Properties\AndroidManifest.xml - true - v8.0 - armeabi,armeabi-v7a,x86 - - - 1G - - - - - - true - - - True - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - True - None - False - 1G - Xamarin - armeabi;armeabi-v7a;x86 - - - pdbonly - true - bin\Release\ - TRACE - prompt - 4 - False - SdkOnly - - - - ..\..\..\..\packages\Acr.Support.2.1.0\lib\MonoAndroid10\Acr.Support.Android.dll - True - - - ..\..\..\..\packages\AndHUD.1.2.0\lib\MonoAndroid\AndHUD.dll - True - - - ..\..\..\..\packages\Xamarin.FFImageLoading.2.2.9\lib\MonoAndroid10\FFImageLoading.dll - - - ..\..\..\..\packages\Xamarin.FFImageLoading.2.2.9\lib\MonoAndroid10\FFImageLoading.Platform.dll - - - ..\..\..\..\packages\IdentityModel.1.3.1\lib\portable-net45+wp80+win8+wpa81\IdentityModel.Portable.dll - True - - - - ..\..\..\..\packages\modernhttpclient.2.4.2\lib\MonoAndroid\ModernHttpClient.dll - True - - - - - ..\..\..\..\packages\Newtonsoft.Json.9.0.1\lib\portable-net45+wp80+win8+wpa81\Newtonsoft.Json.dll - - - ..\..\..\..\packages\modernhttpclient.2.4.2\lib\MonoAndroid\OkHttp.dll - True - - - ..\..\..\..\packages\PCLCrypto.2.0.147\lib\MonoAndroid23\PCLCrypto.dll - - - ..\..\..\..\packages\PInvoke.BCrypt.0.3.2\lib\portable-net45+win+wpa81+MonoAndroid10+xamarinios10+MonoTouch10\PInvoke.BCrypt.dll - - - ..\..\..\..\packages\PInvoke.Kernel32.0.3.2\lib\portable-net45+win+wpa81+MonoAndroid10+xamarinios10+MonoTouch10\PInvoke.Kernel32.dll - - - ..\..\..\..\packages\PInvoke.NCrypt.0.3.2\lib\portable-net45+win+wpa81+MonoAndroid10+xamarinios10+MonoTouch10\PInvoke.NCrypt.dll - - - ..\..\..\..\packages\PInvoke.Windows.Core.0.3.2\lib\portable-net45+win+wpa81+MonoAndroid10+xamarinios10+MonoTouch10\PInvoke.Windows.Core.dll - - - ..\..\..\..\packages\Plugin.CurrentActivity.1.0.1\lib\MonoAndroid10\Plugin.CurrentActivity.dll - - - ..\..\..\..\packages\Xam.Plugin.Geolocator.3.0.4\lib\MonoAndroid10\Plugin.Geolocator.dll - - - ..\..\..\..\packages\Xam.Plugin.Geolocator.3.0.4\lib\MonoAndroid10\Plugin.Geolocator.Abstractions.dll - - - ..\..\..\..\packages\Plugin.Permissions.1.1.7\lib\MonoAndroid10\Plugin.Permissions.dll - - - ..\..\..\..\packages\Plugin.Permissions.1.1.7\lib\MonoAndroid10\Plugin.Permissions.Abstractions.dll - - - ..\..\..\..\packages\Xam.Plugins.Settings.2.6.0.12-beta\lib\MonoAndroid10\Plugin.Settings.dll - True - - - ..\..\..\..\packages\Xam.Plugins.Settings.2.6.0.12-beta\lib\MonoAndroid10\Plugin.Settings.Abstractions.dll - True - - - ..\..\..\..\packages\SlideOverKit.2.1.4\lib\MonoAndroid10\SlideOverKit.dll - True - - - ..\..\..\..\packages\SlideOverKit.2.1.4\lib\MonoAndroid10\SlideOverKit.Droid.dll - True - - - ..\..\..\..\packages\Splat.1.6.2\lib\monoandroid\Splat.dll - True - - - - - - ..\..\..\..\packages\Microsoft.Net.Http.2.2.29\lib\monoandroid\System.Net.Http.Extensions.dll - True - - - ..\..\..\..\packages\Microsoft.Net.Http.2.2.29\lib\monoandroid\System.Net.Http.Primitives.dll - True - - - - - ..\..\..\..\packages\Validation.2.2.8\lib\dotnet\Validation.dll - - - - ..\..\..\..\packages\Autofac.4.5.0\lib\netstandard1.1\Autofac.dll - - - ..\..\..\..\packages\Acr.UserDialogs.6.3.8\lib\MonoAndroid10\Acr.UserDialogs.dll - - - ..\..\..\..\packages\Acr.UserDialogs.6.3.8\lib\MonoAndroid10\Acr.UserDialogs.Interface.dll - - - ..\..\..\..\packages\Xamarin.Forms.2.5.0.91635\lib\MonoAndroid10\FormsViewGroup.dll - - - ..\..\..\..\packages\Xamarin.Forms.2.5.0.91635\lib\MonoAndroid10\Xamarin.Forms.Core.dll - - - ..\..\..\..\packages\Xamarin.Forms.2.5.0.91635\lib\MonoAndroid10\Xamarin.Forms.Platform.Android.dll - - - ..\..\..\..\packages\Xamarin.Forms.2.5.0.91635\lib\MonoAndroid10\Xamarin.Forms.Platform.dll - - - ..\..\..\..\packages\Xamarin.Forms.2.5.0.91635\lib\MonoAndroid10\Xamarin.Forms.Xaml.dll - - - ..\..\..\..\packages\Xamarin.FFImageLoading.Forms.2.2.9\lib\MonoAndroid10\FFImageLoading.Forms.dll - - - ..\..\..\..\packages\Xamarin.FFImageLoading.Forms.2.2.9\lib\MonoAndroid10\FFImageLoading.Forms.Droid.dll - - - ..\..\..\..\packages\Xamarin.Android.Support.Animated.Vector.Drawable.25.4.0.2\lib\MonoAndroid70\Xamarin.Android.Support.Animated.Vector.Drawable.dll - - - ..\..\..\..\packages\Xamarin.Android.Support.Vector.Drawable.25.4.0.2\lib\MonoAndroid70\Xamarin.Android.Support.Vector.Drawable.dll - - - ..\..\..\..\packages\Xamarin.Android.Support.v7.RecyclerView.25.4.0.2\lib\MonoAndroid70\Xamarin.Android.Support.v7.RecyclerView.dll - - - ..\..\..\..\packages\Xamarin.Android.Support.Annotations.25.4.0.2\lib\MonoAndroid70\Xamarin.Android.Support.Annotations.dll - - - ..\..\..\..\packages\Xamarin.Android.Support.Compat.25.4.0.2\lib\MonoAndroid70\Xamarin.Android.Support.Compat.dll - - - ..\..\..\..\packages\Xamarin.Android.Support.v7.CardView.25.4.0.2\lib\MonoAndroid70\Xamarin.Android.Support.v7.CardView.dll - - - ..\..\..\..\packages\Xamarin.Android.Support.Media.Compat.25.4.0.2\lib\MonoAndroid70\Xamarin.Android.Support.Media.Compat.dll - - - ..\..\..\..\packages\Xamarin.Android.Support.Core.UI.25.4.0.2\lib\MonoAndroid70\Xamarin.Android.Support.Core.UI.dll - - - ..\..\..\..\packages\Xamarin.Android.Support.Core.Utils.25.4.0.2\lib\MonoAndroid70\Xamarin.Android.Support.Core.Utils.dll - - - ..\..\..\..\packages\Xamarin.Android.Support.Fragment.25.4.0.2\lib\MonoAndroid70\Xamarin.Android.Support.Fragment.dll - - - ..\..\..\..\packages\Xamarin.Android.Support.Design.25.4.0.2\lib\MonoAndroid70\Xamarin.Android.Support.Design.dll - - - ..\..\..\..\packages\Xamarin.Android.Support.Transition.25.4.0.2\lib\MonoAndroid70\Xamarin.Android.Support.Transition.dll - - - ..\..\..\..\packages\Xamarin.Android.Support.v4.25.4.0.2\lib\MonoAndroid70\Xamarin.Android.Support.v4.dll - - - ..\..\..\..\packages\Xamarin.Android.Support.v7.Palette.25.4.0.2\lib\MonoAndroid70\Xamarin.Android.Support.v7.Palette.dll - - - ..\..\..\..\packages\Xamarin.Android.Support.v7.AppCompat.25.4.0.2\lib\MonoAndroid70\Xamarin.Android.Support.v7.AppCompat.dll - - - ..\..\..\..\packages\Xamarin.Android.Support.v7.MediaRouter.25.4.0.2\lib\MonoAndroid70\Xamarin.Android.Support.v7.MediaRouter.dll - - - - - - - - - - - - - - - - - - - - - Assets\Montserrat-Bold.ttf - - - Assets\Montserrat-Regular.ttf - - - Assets\SourceSansPro-Regular.ttf - - - - - - - - - Designer - - - Designer - - - Designer - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - {ba96a12c-4ee3-46c4-bb3f-f811b554cd01} - eShopOnContainers.Core - - - - - - This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/Mobile/eShopOnContainers/eShopOnContainers.TestRunner.iOS/eShopOnContainers.TestRunner.iOS.csproj b/src/Mobile/eShopOnContainers/eShopOnContainers.TestRunner.iOS/eShopOnContainers.TestRunner.iOS.csproj index 4a83a29a8..250d836a7 100644 --- a/src/Mobile/eShopOnContainers/eShopOnContainers.TestRunner.iOS/eShopOnContainers.TestRunner.iOS.csproj +++ b/src/Mobile/eShopOnContainers/eShopOnContainers.TestRunner.iOS/eShopOnContainers.TestRunner.iOS.csproj @@ -1,232 +1,232 @@  - - - - Debug - iPhoneSimulator - {B68C2B56-7581-46AE-B55D-D25DDFD3BFE3} - {FEACFBD2-3405-455C-9665-78FE426C6842};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} - Exe - eShopOnContainers.TestRunner.iOS - Resources - eShopOnContainersTestRunneriOS - - - - - true - full - false - bin\iPhoneSimulator\Debug - DEBUG - prompt - 4 - false - x86_64 - None - True - False - False - False - False - False - True - Default - HttpClientHandler - False - - - false - none - true - bin\iPhoneSimulator\Release - prompt - 4 - None - x86_64 - false - - - true - full - false - bin\iPhone\Debug - DEBUG - prompt - 4 - false - ARMv7, ARM64 - Entitlements.plist - iPhone Developer - true - None - - - false - none - true - bin\iPhone\Release - prompt - 4 - Entitlements.plist - ARMv7, ARM64 - false - iPhone Developer - - - none - True - bin\iPhone\Ad-Hoc - prompt - 4 - False - ARMv7, ARM64 - Entitlements.plist - True - Automatic:AdHoc - iPhone Distribution - - - none - True - bin\iPhone\AppStore - prompt - 4 - False - ARMv7, ARM64 - Entitlements.plist - Automatic:AppStore - iPhone Distribution - - - - - - - - - - - - - - - - ..\..\..\..\packages\Xamarin.Forms.2.5.0.122203\lib\Xamarin.iOS10\Xamarin.Forms.Core.dll - - - ..\..\..\..\packages\Xamarin.Forms.2.5.0.122203\lib\Xamarin.iOS10\Xamarin.Forms.Platform.dll - - - ..\..\..\..\packages\Xamarin.Forms.2.5.0.122203\lib\Xamarin.iOS10\Xamarin.Forms.Platform.iOS.dll - - - ..\..\..\..\packages\Xamarin.Forms.2.5.0.122203\lib\Xamarin.iOS10\Xamarin.Forms.Xaml.dll - - - - - - ..\..\..\..\packages\xunit.runner.devices.2.3.3\lib\xamarinios10\xunit.runner.devices.dll - - - ..\..\..\..\packages\xunit.runner.devices.2.3.3\lib\xamarinios10\xunit.runner.utility.netstandard15.dll - - - ..\..\..\..\packages\xunit.abstractions.2.0.1\lib\netstandard1.0\xunit.abstractions.dll - - - ..\..\..\..\packages\xunit.assert.2.3.1\lib\netstandard1.1\xunit.assert.dll - - - ..\..\..\..\packages\xunit.extensibility.core.2.3.1\lib\netstandard1.1\xunit.core.dll - - - ..\..\..\..\packages\xunit.extensibility.execution.2.3.1\lib\netstandard1.1\xunit.execution.dotnet.dll - - - - ..\..\..\..\packages\Newtonsoft.Json.10.0.3\lib\netstandard1.3\Newtonsoft.Json.dll - - - ..\..\..\..\packages\SlideOverKit.2.1.5\lib\Xamarin.iOS10\SlideOverKit.dll - - - ..\..\..\..\packages\SlideOverKit.2.1.5\lib\Xamarin.iOS10\SlideOverKit.iOS.dll - - - ..\..\..\..\packages\IdentityModel.3.0.0\lib\netstandard2.0\IdentityModel.dll - - - ..\..\..\..\packages\Acr.Support.2.1.0\lib\Xamarin.iOS10\Acr.Support.iOS.dll - - - ..\..\..\..\packages\BTProgressHUD.1.2.0.5\lib\Xamarin.iOS10\BTProgressHUD.dll - - - ..\..\..\..\packages\Splat.2.0.0\lib\Xamarin.iOS10\Splat.dll - - - ..\..\..\..\packages\Acr.UserDialogs.6.5.1\lib\Xamarin.iOS10\Acr.UserDialogs.dll - - - ..\..\..\..\packages\Acr.UserDialogs.6.5.1\lib\Xamarin.iOS10\Acr.UserDialogs.Interface.dll - - - ..\..\..\..\packages\WebP.Touch.1.0.7\lib\Xamarin.iOS10\WebP.Touch.dll - - - ..\..\..\..\packages\Xamarin.FFImageLoading.2.3.4\lib\Xamarin.iOS10\FFImageLoading.dll - - - ..\..\..\..\packages\Xamarin.FFImageLoading.2.3.4\lib\Xamarin.iOS10\FFImageLoading.Platform.dll - - - ..\..\..\..\packages\Xamarin.FFImageLoading.Forms.2.3.4\lib\Xamarin.iOS10\FFImageLoading.Forms.dll - - - ..\..\..\..\packages\Xamarin.FFImageLoading.Forms.2.3.4\lib\Xamarin.iOS10\FFImageLoading.Forms.Touch.dll - - - ..\..\..\..\packages\PInvoke.Windows.Core.0.3.2\lib\portable-net45+win+wpa81+MonoAndroid10+xamarinios10+MonoTouch10\PInvoke.Windows.Core.dll - - - ..\..\..\..\packages\PInvoke.Kernel32.0.3.2\lib\portable-net45+win+wpa81+MonoAndroid10+xamarinios10+MonoTouch10\PInvoke.Kernel32.dll - - - ..\..\..\..\packages\PInvoke.BCrypt.0.3.2\lib\portable-net45+win+wpa81+MonoAndroid10+xamarinios10+MonoTouch10\PInvoke.BCrypt.dll - - - ..\..\..\..\packages\PInvoke.NCrypt.0.3.2\lib\portable-net45+win+wpa81+MonoAndroid10+xamarinios10+MonoTouch10\PInvoke.NCrypt.dll - - - ..\..\..\..\packages\Validation.2.2.8\lib\dotnet\Validation.dll - - - ..\..\..\..\packages\PCLCrypto.2.0.147\lib\xamarinios10\PCLCrypto.dll - - - - - - - - {FDD910BC-DF0F-483D-B7D5-C7D831855172} - eShopOnContainers.UnitTests - - - - - - + + - This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + Debug + iPhoneSimulator + {B68C2B56-7581-46AE-B55D-D25DDFD3BFE3} + {FEACFBD2-3405-455C-9665-78FE426C6842};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + Exe + eShopOnContainers.TestRunner.iOS + Resources + eShopOnContainersTestRunneriOS + + + true - - - - - - + + true + full + false + bin\iPhoneSimulator\Debug + DEBUG + prompt + 4 + false + x86_64 + None + True + False + False + False + False + False + True + Default + HttpClientHandler + False + + + false + none + true + bin\iPhoneSimulator\Release + prompt + 4 + None + x86_64 + false + + + true + full + false + bin\iPhone\Debug + DEBUG + prompt + 4 + false + ARMv7, ARM64 + Entitlements.plist + iPhone Developer + true + None + + + false + none + true + bin\iPhone\Release + prompt + 4 + Entitlements.plist + ARMv7, ARM64 + false + iPhone Developer + + + none + True + bin\iPhone\Ad-Hoc + prompt + 4 + False + ARMv7, ARM64 + Entitlements.plist + True + Automatic:AdHoc + iPhone Distribution + + + none + True + bin\iPhone\AppStore + prompt + 4 + False + ARMv7, ARM64 + Entitlements.plist + Automatic:AppStore + iPhone Distribution + + + + + + + + + + + + + + + + ..\..\..\..\packages\Xamarin.Forms.2.5.0.122203\lib\Xamarin.iOS10\Xamarin.Forms.Core.dll + + + ..\..\..\..\packages\Xamarin.Forms.2.5.0.122203\lib\Xamarin.iOS10\Xamarin.Forms.Platform.dll + + + ..\..\..\..\packages\Xamarin.Forms.2.5.0.122203\lib\Xamarin.iOS10\Xamarin.Forms.Platform.iOS.dll + + + ..\..\..\..\packages\Xamarin.Forms.2.5.0.122203\lib\Xamarin.iOS10\Xamarin.Forms.Xaml.dll + + + + + + ..\..\..\..\packages\xunit.runner.devices.2.3.3\lib\xamarinios10\xunit.runner.devices.dll + + + ..\..\..\..\packages\xunit.runner.devices.2.3.3\lib\xamarinios10\xunit.runner.utility.netstandard15.dll + + + ..\..\..\..\packages\xunit.abstractions.2.0.1\lib\netstandard1.0\xunit.abstractions.dll + + + ..\..\..\..\packages\xunit.assert.2.3.1\lib\netstandard1.1\xunit.assert.dll + + + ..\..\..\..\packages\xunit.extensibility.core.2.3.1\lib\netstandard1.1\xunit.core.dll + + + ..\..\..\..\packages\xunit.extensibility.execution.2.3.1\lib\netstandard1.1\xunit.execution.dotnet.dll + + + ..\..\..\..\packages\Newtonsoft.Json.10.0.3\lib\netstandard1.3\Newtonsoft.Json.dll + + + ..\..\..\..\packages\SlideOverKit.2.1.5\lib\Xamarin.iOS10\SlideOverKit.dll + + + ..\..\..\..\packages\SlideOverKit.2.1.5\lib\Xamarin.iOS10\SlideOverKit.iOS.dll + + + ..\..\..\..\packages\IdentityModel.3.0.0\lib\netstandard2.0\IdentityModel.dll + + + ..\..\..\..\packages\Acr.Support.2.1.0\lib\Xamarin.iOS10\Acr.Support.iOS.dll + + + ..\..\..\..\packages\BTProgressHUD.1.2.0.5\lib\Xamarin.iOS10\BTProgressHUD.dll + + + ..\..\..\..\packages\Splat.2.0.0\lib\Xamarin.iOS10\Splat.dll + + + ..\..\..\..\packages\Acr.UserDialogs.6.5.1\lib\Xamarin.iOS10\Acr.UserDialogs.dll + + + ..\..\..\..\packages\Acr.UserDialogs.6.5.1\lib\Xamarin.iOS10\Acr.UserDialogs.Interface.dll + + + ..\..\..\..\packages\WebP.Touch.1.0.7\lib\Xamarin.iOS10\WebP.Touch.dll + + + ..\..\..\..\packages\Xamarin.FFImageLoading.2.3.4\lib\Xamarin.iOS10\FFImageLoading.dll + + + ..\..\..\..\packages\Xamarin.FFImageLoading.2.3.4\lib\Xamarin.iOS10\FFImageLoading.Platform.dll + + + ..\..\..\..\packages\Xamarin.FFImageLoading.Forms.2.3.4\lib\Xamarin.iOS10\FFImageLoading.Forms.dll + + + ..\..\..\..\packages\Xamarin.FFImageLoading.Forms.2.3.4\lib\Xamarin.iOS10\FFImageLoading.Forms.Touch.dll + + + ..\..\..\..\packages\PInvoke.Windows.Core.0.3.2\lib\portable-net45+win+wpa81+MonoAndroid10+xamarinios10+MonoTouch10\PInvoke.Windows.Core.dll + + + ..\..\..\..\packages\PInvoke.Kernel32.0.3.2\lib\portable-net45+win+wpa81+MonoAndroid10+xamarinios10+MonoTouch10\PInvoke.Kernel32.dll + + + ..\..\..\..\packages\PInvoke.BCrypt.0.3.2\lib\portable-net45+win+wpa81+MonoAndroid10+xamarinios10+MonoTouch10\PInvoke.BCrypt.dll + + + ..\..\..\..\packages\PInvoke.NCrypt.0.3.2\lib\portable-net45+win+wpa81+MonoAndroid10+xamarinios10+MonoTouch10\PInvoke.NCrypt.dll + + + ..\..\..\..\packages\Validation.2.2.8\lib\dotnet\Validation.dll + + + ..\..\..\..\packages\PCLCrypto.2.0.147\lib\xamarinios10\PCLCrypto.dll + + + + + + + + {FDD910BC-DF0F-483D-B7D5-C7D831855172} + eShopOnContainers.UnitTests + + + + + + + + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + + + + + \ No newline at end of file diff --git a/src/Mobile/eShopOnContainers/eShopOnContainers.UnitTests/Mocks/MockSettingsService.cs b/src/Mobile/eShopOnContainers/eShopOnContainers.UnitTests/Mocks/MockSettingsService.cs index 23e1cedc5..37bfc125f 100644 --- a/src/Mobile/eShopOnContainers/eShopOnContainers.UnitTests/Mocks/MockSettingsService.cs +++ b/src/Mobile/eShopOnContainers/eShopOnContainers.UnitTests/Mocks/MockSettingsService.cs @@ -1,65 +1,110 @@ using eShopOnContainers.Core.Services.Settings; -using System; +using System.Collections.Generic; +using System.Threading.Tasks; namespace eShopOnContainers.UnitTests.Mocks { public class MockSettingsService : ISettingsService { - string _accessTokenDefault = string.Empty; - string _idTokenDefault = string.Empty; - bool _useMocksDefault = true; - string _urlBaseDefault = "https://13.88.8.119"; - bool _useFakeLocationDefault = false; - bool _allowGpsLocationDefault = false; - double _fakeLatitudeDefault = 47.604610d; - double _fakeLongitudeDefault = -122.315752d; + IDictionary _settings = new Dictionary(); + + const string AccessToken = "access_token"; + const string IdToken = "id_token"; + const string IdUseMocks = "use_mocks"; + const string IdUrlBase = "url_base"; + const string IdUseFakeLocation = "use_fake_location"; + const string IdLatitude = "latitude"; + const string IdLongitude = "longitude"; + const string IdAllowGpsLocation = "allow_gps_location"; + readonly string AccessTokenDefault = string.Empty; + readonly string IdTokenDefault = string.Empty; + readonly bool UseMocksDefault = true; + readonly bool UseFakeLocationDefault = false; + readonly bool AllowGpsLocationDefault = false; + readonly double FakeLatitudeDefault = 47.604610d; + readonly double FakeLongitudeDefault = -122.315752d; + readonly string UrlBaseDefault = "https://13.88.8.119"; public string AuthAccessToken { - get { return _accessTokenDefault; } - set { _accessTokenDefault = value; } + get => GetValueOrDefault(AccessToken, AccessTokenDefault); + set => AddOrUpdateValue(AccessToken, value); } public string AuthIdToken { - get { return _idTokenDefault; } - set { _idTokenDefault = value; } + get => GetValueOrDefault(IdToken, IdTokenDefault); + set => AddOrUpdateValue(IdToken, value); } public bool UseMocks { - get { return _useMocksDefault; } - set { _useMocksDefault = value; } + get => GetValueOrDefault(IdUseMocks, UseMocksDefault); + set => AddOrUpdateValue(IdUseMocks, value); } public string UrlBase { - get { return _urlBaseDefault; } - set { _urlBaseDefault = value; } + get => GetValueOrDefault(IdUrlBase, UrlBaseDefault); + set => AddOrUpdateValue(IdUrlBase, value); } public bool UseFakeLocation { - get { return _useFakeLocationDefault; } - set { _useFakeLocationDefault = value; } + get => GetValueOrDefault(IdUseFakeLocation, UseFakeLocationDefault); + set => AddOrUpdateValue(IdUseFakeLocation, value); } public string Latitude { - get { return _fakeLatitudeDefault.ToString(); } - set { _fakeLatitudeDefault = Convert.ToDouble(value); } + get => GetValueOrDefault(IdLatitude, FakeLatitudeDefault.ToString()); + set => AddOrUpdateValue(IdLatitude, value); } public string Longitude { - get { return _fakeLongitudeDefault.ToString(); } - set { _fakeLongitudeDefault = Convert.ToDouble(value); } + get => GetValueOrDefault(IdLongitude, FakeLongitudeDefault.ToString()); + set => AddOrUpdateValue(IdLongitude, value); } public bool AllowGpsLocation { - get { return _allowGpsLocationDefault; } - set { _allowGpsLocationDefault = value; } + get => GetValueOrDefault(IdAllowGpsLocation, AllowGpsLocationDefault); + set => AddOrUpdateValue(IdAllowGpsLocation, value); + } + + public Task AddOrUpdateValue(string key, bool value) => AddOrUpdateValueInternal(key, value); + public Task AddOrUpdateValue(string key, string value) => AddOrUpdateValueInternal(key, value); + public bool GetValueOrDefault(string key, bool defaultValue) => GetValueOrDefaultInternal(key, defaultValue); + public string GetValueOrDefault(string key, string defaultValue) => GetValueOrDefaultInternal(key, defaultValue); + + Task AddOrUpdateValueInternal(string key, T value) + { + if (value == null) + { + Remove(key); + } + + _settings[key] = value; + return Task.Delay(10); + } + + T GetValueOrDefaultInternal(string key, T defaultValue = default(T)) + { + object value = null; + if (_settings.ContainsKey(key)) + { + value = _settings[key]; + } + return null != value ? (T)value : defaultValue; + } + + void Remove(string key) + { + if (_settings[key] != null) + { + _settings.Remove(key); + } } } } diff --git a/src/Mobile/eShopOnContainers/eShopOnContainers.Windows/Services/SettingsServiceImplementation.cs b/src/Mobile/eShopOnContainers/eShopOnContainers.Windows/Services/SettingsServiceImplementation.cs deleted file mode 100644 index e13fafd9f..000000000 --- a/src/Mobile/eShopOnContainers/eShopOnContainers.Windows/Services/SettingsServiceImplementation.cs +++ /dev/null @@ -1,99 +0,0 @@ -using eShopOnContainers.Core.Services.Settings; -using eShopOnContainers.Windows.Services; -using Windows.Storage; - -[assembly: Xamarin.Forms.Dependency(typeof(SettingsServiceImplementation))] -namespace eShopOnContainers.Windows.Services -{ - public class SettingsServiceImplementation : ISettingsServiceImplementation - { - #region Internal Implementation - - readonly object _locker = new object(); - - ApplicationDataContainer GetAppSettings() - { - return ApplicationData.Current.LocalSettings; - } - - bool AddOrUpdateValueInternal(string key, T value) - { - bool valueChanged = false; - - if (value == null) - { - Remove(key); - return true; - } - - lock (_locker) - { - var settings = GetAppSettings(); - if (settings.Values.ContainsKey(key)) - { - if (settings.Values[key] != (object)value) - { - settings.Values[key] = value; - valueChanged = true; - } - } - else - { - settings.Values[key] = value; - valueChanged = true; - } - } - - return valueChanged; - } - - T GetValueOrDefaultInternal(string key, T defaultValue = default(T)) - { - object value; - - lock (_locker) - { - var settings = GetAppSettings(); - if (settings.Values.ContainsKey(key)) - { - var tempValue = settings.Values[key]; - if (tempValue != null) - value = (T)tempValue; - else - value = defaultValue; - } - else - { - value = defaultValue; - } - } - return null != value ? (T)value : defaultValue; - } - - #endregion - - #region ISettingsServiceImplementation - - public bool AddOrUpdateValue(string key, bool value) => AddOrUpdateValueInternal(key, value); - - public bool AddOrUpdateValue(string key, string value) => AddOrUpdateValueInternal(key, value); - - public bool GetValueOrDefault(string key, bool defaultValue) => GetValueOrDefaultInternal(key, defaultValue); - - public string GetValueOrDefault(string key, string defaultValue) => GetValueOrDefaultInternal(key, defaultValue); - - public void Remove(string key) - { - lock (_locker) - { - var settings = GetAppSettings(); - if (settings.Values.ContainsKey(key)) - { - settings.Values.Remove(key); - } - } - } - - #endregion - } -} diff --git a/src/Mobile/eShopOnContainers/eShopOnContainers.Windows/eShopOnContainers.Windows.csproj b/src/Mobile/eShopOnContainers/eShopOnContainers.Windows/eShopOnContainers.Windows.csproj index b879d31c6..9a1a2d108 100644 --- a/src/Mobile/eShopOnContainers/eShopOnContainers.Windows/eShopOnContainers.Windows.csproj +++ b/src/Mobile/eShopOnContainers/eShopOnContainers.Windows/eShopOnContainers.Windows.csproj @@ -123,7 +123,6 @@ - diff --git a/src/Mobile/eShopOnContainers/eShopOnContainers.iOS/Services/SettingsServiceImplementation.cs b/src/Mobile/eShopOnContainers/eShopOnContainers.iOS/Services/SettingsServiceImplementation.cs deleted file mode 100644 index ee17b8ff7..000000000 --- a/src/Mobile/eShopOnContainers/eShopOnContainers.iOS/Services/SettingsServiceImplementation.cs +++ /dev/null @@ -1,128 +0,0 @@ -using eShopOnContainers.Core.Services.Settings; -using eShopOnContainers.iOS.Services; -using Foundation; -using System; - -[assembly: Xamarin.Forms.Dependency(typeof(SettingsServiceImplementation))] -namespace eShopOnContainers.iOS.Services -{ - public class SettingsServiceImplementation : ISettingsServiceImplementation - { - #region Internal Implementation - - readonly object _locker = new object(); - - NSUserDefaults GetUserDefaults() => NSUserDefaults.StandardUserDefaults; - - bool AddOrUpdateValueInternal(string key, T value) - { - if (value == null) - { - Remove(key); - return true; - } - - var type = typeof(T); - if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>)) - { - type = Nullable.GetUnderlyingType(type); - } - var typeCode = Type.GetTypeCode(type); - - lock (_locker) - { - var defaults = GetUserDefaults(); - switch (typeCode) - { - case TypeCode.Boolean: - defaults.SetBool(Convert.ToBoolean(value), key); - break; - case TypeCode.String: - defaults.SetString(Convert.ToString(value), key); - break; - default: - throw new ArgumentException($"Value of type {typeCode} is unsupported."); - } - - try - { - defaults.Synchronize(); - } - catch (Exception ex) - { - Console.WriteLine("Unable to save: " + key, " Message: " + ex.Message); - } - } - return true; - } - - T GetValueOrDefaultInternal(string key, T defaultValue = default(T)) - { - lock (_locker) - { - var defaults = GetUserDefaults(); - - if (defaults[key] == null) - { - return defaultValue; - } - - var type = typeof(T); - if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>)) - { - type = Nullable.GetUnderlyingType(type); - } - - object value = null; - var typeCode = Type.GetTypeCode(type); - switch (typeCode) - { - case TypeCode.Boolean: - value = defaults.BoolForKey(key); - break; - case TypeCode.String: - value = defaults.StringForKey(key); - break; - default: - throw new ArgumentException($"Value of type {typeCode} is unsupported."); - } - - return null != value ? (T)value : defaultValue; - } - } - - #endregion - - #region ISettingsServiceImplementation - - public bool AddOrUpdateValue(string key, bool value) => AddOrUpdateValueInternal(key, value); - - public bool AddOrUpdateValue(string key, string value) => AddOrUpdateValueInternal(key, value); - - public bool GetValueOrDefault(string key, bool defaultValue) => GetValueOrDefaultInternal(key, defaultValue); - - public string GetValueOrDefault(string key, string defaultValue) => GetValueOrDefaultInternal(key, defaultValue); - - public void Remove(string key) - { - lock (_locker) - { - var defaults = GetUserDefaults(); - try - { - if (defaults[key] != null) - { - defaults.RemoveObject(key); - defaults.Synchronize(); - } - } - catch (Exception ex) - { - Console.WriteLine("Unable to remove: " + key, " Message: " + ex.Message); - } - } - } - - #endregion - } -} diff --git a/src/Mobile/eShopOnContainers/eShopOnContainers.iOS/eShopOnContainers.iOS.csproj b/src/Mobile/eShopOnContainers/eShopOnContainers.iOS/eShopOnContainers.iOS.csproj index 6ea0a4465..3d18f3a5c 100644 --- a/src/Mobile/eShopOnContainers/eShopOnContainers.iOS/eShopOnContainers.iOS.csproj +++ b/src/Mobile/eShopOnContainers/eShopOnContainers.iOS/eShopOnContainers.iOS.csproj @@ -1,429 +1,428 @@  - - - Debug - iPhoneSimulator - 8.0.30703 - 2.0 - {6EEB23DC-7063-4444-9AF8-90DF24F549C0} - {FEACFBD2-3405-455C-9665-78FE426C6842};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} - Exe - eShopOnContainers.iOS - Resources - eShopOnContainersiOS - - - true - - - true - full - false - bin\iPhoneSimulator\Debug - DEBUG - prompt - 4 - false - i386, x86_64 - None - True - False - False - False - False - False - True - Default - HttpClientHandler - False - - - none - true - bin\iPhoneSimulator\Release - prompt - 4 - None - i386, x86_64 - false - - - true - full - false - bin\iPhone\Debug - DEBUG - prompt - 4 - false - ARMv7, ARM64 - iPhone Developer - true - Entitlements.plist - None - - - none - true - bin\iPhone\Release - prompt - 4 - ARMv7, ARM64 - false - iPhone Developer - Entitlements.plist - - - none - True - bin\iPhone\Ad-Hoc - prompt - 4 - False - ARMv7, ARM64 - True - Automatic:AdHoc - iPhone Distribution - Entitlements.plist - - - none - True - bin\iPhone\AppStore - prompt - 4 - False - ARMv7, ARM64 - Automatic:AppStore - iPhone Distribution - Entitlements.plist - - - - - - - Resources\fonts\Montserrat-Bold.ttf - - - Resources\fonts\Montserrat-Regular.ttf - - - Resources\fonts\SourceSansPro-Regular.ttf - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ..\..\..\..\packages\Xamarin.Forms.2.5.0.122203\lib\Xamarin.iOS10\Xamarin.Forms.Core.dll - - - ..\..\..\..\packages\Xamarin.Forms.2.5.0.122203\lib\Xamarin.iOS10\Xamarin.Forms.Platform.dll - - - ..\..\..\..\packages\Xamarin.Forms.2.5.0.122203\lib\Xamarin.iOS10\Xamarin.Forms.Platform.iOS.dll - - - ..\..\..\..\packages\Xamarin.Forms.2.5.0.122203\lib\Xamarin.iOS10\Xamarin.Forms.Xaml.dll - - - ..\..\..\..\packages\WebP.Touch.1.0.7\lib\Xamarin.iOS10\WebP.Touch.dll - - - ..\..\..\..\packages\Xamarin.FFImageLoading.2.3.4\lib\Xamarin.iOS10\FFImageLoading.dll - - - ..\..\..\..\packages\Xamarin.FFImageLoading.2.3.4\lib\Xamarin.iOS10\FFImageLoading.Platform.dll - - - ..\..\..\..\packages\Xamarin.FFImageLoading.Forms.2.3.4\lib\Xamarin.iOS10\FFImageLoading.Forms.dll - - - ..\..\..\..\packages\Xamarin.FFImageLoading.Forms.2.3.4\lib\Xamarin.iOS10\FFImageLoading.Forms.Touch.dll - - - ..\..\..\..\packages\SlideOverKit.2.1.5\lib\Xamarin.iOS10\SlideOverKit.dll - - - ..\..\..\..\packages\SlideOverKit.2.1.5\lib\Xamarin.iOS10\SlideOverKit.iOS.dll - - - ..\..\..\..\packages\Xam.Plugins.Settings.3.1.1\lib\Xamarin.iOS10\Plugin.Settings.Abstractions.dll - - - ..\..\..\..\packages\Xam.Plugins.Settings.3.1.1\lib\Xamarin.iOS10\Plugin.Settings.dll - - - - ..\..\..\..\packages\Newtonsoft.Json.10.0.3\lib\netstandard1.3\Newtonsoft.Json.dll - - - ..\..\..\..\packages\Acr.Support.2.1.0\lib\Xamarin.iOS10\Acr.Support.iOS.dll - - - ..\..\..\..\packages\BTProgressHUD.1.2.0.5\lib\Xamarin.iOS10\BTProgressHUD.dll - - - ..\..\..\..\packages\Splat.2.0.0\lib\Xamarin.iOS10\Splat.dll - - - ..\..\..\..\packages\Acr.UserDialogs.6.5.1\lib\Xamarin.iOS10\Acr.UserDialogs.dll - - - ..\..\..\..\packages\Acr.UserDialogs.6.5.1\lib\Xamarin.iOS10\Acr.UserDialogs.Interface.dll - - - ..\..\..\..\packages\PInvoke.Windows.Core.0.3.2\lib\portable-net45+win+wpa81+MonoAndroid10+xamarinios10+MonoTouch10\PInvoke.Windows.Core.dll - - - ..\..\..\..\packages\PInvoke.Kernel32.0.3.2\lib\portable-net45+win+wpa81+MonoAndroid10+xamarinios10+MonoTouch10\PInvoke.Kernel32.dll - - - ..\..\..\..\packages\PInvoke.BCrypt.0.3.2\lib\portable-net45+win+wpa81+MonoAndroid10+xamarinios10+MonoTouch10\PInvoke.BCrypt.dll - - - ..\..\..\..\packages\PInvoke.NCrypt.0.3.2\lib\portable-net45+win+wpa81+MonoAndroid10+xamarinios10+MonoTouch10\PInvoke.NCrypt.dll - - - ..\..\..\..\packages\Validation.2.2.8\lib\dotnet\Validation.dll - - - ..\..\..\..\packages\PCLCrypto.2.0.147\lib\xamarinios10\PCLCrypto.dll - - - ..\..\..\..\packages\IdentityModel.3.0.0\lib\netstandard2.0\IdentityModel.dll - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - false - - - false - - - false - - - false - - - false - - - false - - - false - - - false - - - false - - - false - - - false - - - false - - - false - - - false - - - false - - - false - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - {76C5F2A7-6CD5-49EA-9F33-EC44DE6539C7} - eShopOnContainers.Core - - - - - - - - - + - This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + Debug + iPhoneSimulator + 8.0.30703 + 2.0 + {6EEB23DC-7063-4444-9AF8-90DF24F549C0} + {FEACFBD2-3405-455C-9665-78FE426C6842};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + Exe + eShopOnContainers.iOS + Resources + eShopOnContainersiOS + + + true + true - - - + + true + full + false + bin\iPhoneSimulator\Debug + DEBUG + prompt + 4 + false + i386, x86_64 + None + True + False + False + False + False + False + True + Default + HttpClientHandler + False + + + none + true + bin\iPhoneSimulator\Release + prompt + 4 + None + i386, x86_64 + false + + + true + full + false + bin\iPhone\Debug + DEBUG + prompt + 4 + false + ARMv7, ARM64 + iPhone Developer + true + Entitlements.plist + None + + + none + true + bin\iPhone\Release + prompt + 4 + ARMv7, ARM64 + false + iPhone Developer + Entitlements.plist + + + none + True + bin\iPhone\Ad-Hoc + prompt + 4 + False + ARMv7, ARM64 + True + Automatic:AdHoc + iPhone Distribution + Entitlements.plist + + + none + True + bin\iPhone\AppStore + prompt + 4 + False + ARMv7, ARM64 + Automatic:AppStore + iPhone Distribution + Entitlements.plist + + + + + + + Resources\fonts\Montserrat-Bold.ttf + + + Resources\fonts\Montserrat-Regular.ttf + + + Resources\fonts\SourceSansPro-Regular.ttf + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ..\..\..\..\packages\Xamarin.Forms.2.5.0.122203\lib\Xamarin.iOS10\Xamarin.Forms.Core.dll + + + ..\..\..\..\packages\Xamarin.Forms.2.5.0.122203\lib\Xamarin.iOS10\Xamarin.Forms.Platform.dll + + + ..\..\..\..\packages\Xamarin.Forms.2.5.0.122203\lib\Xamarin.iOS10\Xamarin.Forms.Platform.iOS.dll + + + ..\..\..\..\packages\Xamarin.Forms.2.5.0.122203\lib\Xamarin.iOS10\Xamarin.Forms.Xaml.dll + + + ..\..\..\..\packages\WebP.Touch.1.0.7\lib\Xamarin.iOS10\WebP.Touch.dll + + + ..\..\..\..\packages\Xamarin.FFImageLoading.2.3.4\lib\Xamarin.iOS10\FFImageLoading.dll + + + ..\..\..\..\packages\Xamarin.FFImageLoading.2.3.4\lib\Xamarin.iOS10\FFImageLoading.Platform.dll + + + ..\..\..\..\packages\Xamarin.FFImageLoading.Forms.2.3.4\lib\Xamarin.iOS10\FFImageLoading.Forms.dll + + + ..\..\..\..\packages\Xamarin.FFImageLoading.Forms.2.3.4\lib\Xamarin.iOS10\FFImageLoading.Forms.Touch.dll + + + ..\..\..\..\packages\SlideOverKit.2.1.5\lib\Xamarin.iOS10\SlideOverKit.dll + + + ..\..\..\..\packages\SlideOverKit.2.1.5\lib\Xamarin.iOS10\SlideOverKit.iOS.dll + + + ..\..\..\..\packages\Xam.Plugins.Settings.3.1.1\lib\Xamarin.iOS10\Plugin.Settings.Abstractions.dll + + + ..\..\..\..\packages\Xam.Plugins.Settings.3.1.1\lib\Xamarin.iOS10\Plugin.Settings.dll + + + ..\..\..\..\packages\Newtonsoft.Json.10.0.3\lib\netstandard1.3\Newtonsoft.Json.dll + + + ..\..\..\..\packages\Acr.Support.2.1.0\lib\Xamarin.iOS10\Acr.Support.iOS.dll + + + ..\..\..\..\packages\BTProgressHUD.1.2.0.5\lib\Xamarin.iOS10\BTProgressHUD.dll + + + ..\..\..\..\packages\Splat.2.0.0\lib\Xamarin.iOS10\Splat.dll + + + ..\..\..\..\packages\Acr.UserDialogs.6.5.1\lib\Xamarin.iOS10\Acr.UserDialogs.dll + + + ..\..\..\..\packages\Acr.UserDialogs.6.5.1\lib\Xamarin.iOS10\Acr.UserDialogs.Interface.dll + + + ..\..\..\..\packages\PInvoke.Windows.Core.0.3.2\lib\portable-net45+win+wpa81+MonoAndroid10+xamarinios10+MonoTouch10\PInvoke.Windows.Core.dll + + + ..\..\..\..\packages\PInvoke.Kernel32.0.3.2\lib\portable-net45+win+wpa81+MonoAndroid10+xamarinios10+MonoTouch10\PInvoke.Kernel32.dll + + + ..\..\..\..\packages\PInvoke.BCrypt.0.3.2\lib\portable-net45+win+wpa81+MonoAndroid10+xamarinios10+MonoTouch10\PInvoke.BCrypt.dll + + + ..\..\..\..\packages\PInvoke.NCrypt.0.3.2\lib\portable-net45+win+wpa81+MonoAndroid10+xamarinios10+MonoTouch10\PInvoke.NCrypt.dll + + + ..\..\..\..\packages\Validation.2.2.8\lib\dotnet\Validation.dll + + + ..\..\..\..\packages\PCLCrypto.2.0.147\lib\xamarinios10\PCLCrypto.dll + + + ..\..\..\..\packages\IdentityModel.3.0.0\lib\netstandard2.0\IdentityModel.dll + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + false + + + false + + + false + + + false + + + false + + + false + + + false + + + false + + + false + + + false + + + false + + + false + + + false + + + false + + + false + + + false + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {76C5F2A7-6CD5-49EA-9F33-EC44DE6539C7} + eShopOnContainers.Core + + + + + + + + + + + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + + \ No newline at end of file diff --git a/src/Services/Basket/Basket.API/Controllers/BasketController.cs b/src/Services/Basket/Basket.API/Controllers/BasketController.cs index 11ecac7c2..48ad68903 100644 --- a/src/Services/Basket/Basket.API/Controllers/BasketController.cs +++ b/src/Services/Basket/Basket.API/Controllers/BasketController.cs @@ -34,6 +34,10 @@ namespace Microsoft.eShopOnContainers.Services.Basket.API.Controllers public async Task Get(string id) { var basket = await _repository.GetBasketAsync(id); + if (basket == null) + { + return NotFound(); + } return Ok(basket); } diff --git a/src/Services/Basket/Basket.API/Properties/launchSettings.json b/src/Services/Basket/Basket.API/Properties/launchSettings.json index 36effc287..60a56b153 100644 --- a/src/Services/Basket/Basket.API/Properties/launchSettings.json +++ b/src/Services/Basket/Basket.API/Properties/launchSettings.json @@ -3,7 +3,7 @@ "windowsAuthentication": false, "anonymousAuthentication": true, "iisExpress": { - "applicationUrl": "http://localhost:5103/", + "applicationUrl": "http://localhost:58017/", "sslPort": 0 } }, @@ -19,7 +19,7 @@ "Microsoft.eShopOnContainers.Services.Basket.API": { "commandName": "Project", "launchBrowser": true, - "launchUrl": "http://localhost:5000/swagger", + "launchUrl": "http://localhost:55103/", "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" } diff --git a/src/Services/Catalog/Catalog.API/Controllers/CatalogController.cs b/src/Services/Catalog/Catalog.API/Controllers/CatalogController.cs index 1b53171d0..71f700762 100644 --- a/src/Services/Catalog/Catalog.API/Controllers/CatalogController.cs +++ b/src/Services/Catalog/Catalog.API/Controllers/CatalogController.cs @@ -32,11 +32,16 @@ namespace Microsoft.eShopOnContainers.Services.Catalog.API.Controllers // GET api/v1/[controller]/items[?pageSize=3&pageIndex=10] [HttpGet] - [Route("[action]")] + [Route("items")] [ProducesResponseType(typeof(PaginatedItemsViewModel), (int)HttpStatusCode.OK)] - public async Task Items([FromQuery]int pageSize = 10, [FromQuery]int pageIndex = 0) - + [ProducesResponseType(typeof(IEnumerable), (int)HttpStatusCode.OK)] + public async Task Items([FromQuery]int pageSize = 10, [FromQuery]int pageIndex = 0, [FromQuery] string ids = null) { + if (!string.IsNullOrEmpty(ids)) + { + return GetItemsByIds(ids); + } + var totalItems = await _catalogContext.CatalogItems .LongCountAsync(); @@ -54,6 +59,23 @@ namespace Microsoft.eShopOnContainers.Services.Catalog.API.Controllers return Ok(model); } + private IActionResult GetItemsByIds(string ids) + { + var numIds = ids.Split(',') + .Select(id => (Ok: int.TryParse(id, out int x), Value: x)); + if (!numIds.All(nid => nid.Ok)) + { + return BadRequest("ids value invalid. Must be comma-separated list of numbers"); + } + + var idsToSelect = numIds.Select(id => id.Value); + var items = _catalogContext.CatalogItems.Where(ci => idsToSelect.Contains(ci.Id)).ToList(); + + items = ChangeUriPlaceholder(items); + return Ok(items); + + } + [HttpGet] [Route("items/{id:int}")] [ProducesResponseType((int)HttpStatusCode.NotFound)] @@ -66,6 +88,11 @@ namespace Microsoft.eShopOnContainers.Services.Catalog.API.Controllers } var item = await _catalogContext.CatalogItems.SingleOrDefaultAsync(ci => ci.Id == id); + + var baseUri = _settings.PicBaseUrl; + var azureStorageEnabled = _settings.AzureStorageEnabled; + item.FillProductUrl(baseUri, azureStorageEnabled: azureStorageEnabled); + if (item != null) { return Ok(item); @@ -244,13 +271,12 @@ namespace Microsoft.eShopOnContainers.Services.Catalog.API.Controllers private List ChangeUriPlaceholder(List items) { var baseUri = _settings.PicBaseUrl; + var azureStorageEnabled = _settings.AzureStorageEnabled; - items.ForEach(catalogItem => + foreach (var item in items) { - catalogItem.PictureUri = _settings.AzureStorageEnabled - ? baseUri + catalogItem.PictureFileName - : baseUri.Replace("[0]", catalogItem.Id.ToString()); - }); + item.FillProductUrl(baseUri, azureStorageEnabled: azureStorageEnabled); + } return items; } diff --git a/src/Services/Catalog/Catalog.API/Extensions/CatalogItemExtensions.cs b/src/Services/Catalog/Catalog.API/Extensions/CatalogItemExtensions.cs new file mode 100644 index 000000000..71b9d88a3 --- /dev/null +++ b/src/Services/Catalog/Catalog.API/Extensions/CatalogItemExtensions.cs @@ -0,0 +1,17 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace Microsoft.eShopOnContainers.Services.Catalog.API.Model +{ + public static class CatalogItemExtensions + { + public static void FillProductUrl(this CatalogItem item, string picBaseUrl, bool azureStorageEnabled) + { + item.PictureUri = azureStorageEnabled + ? picBaseUrl + item.PictureFileName + : picBaseUrl.Replace("[0]", item.Id.ToString()); + } + } +} diff --git a/src/Services/Catalog/Catalog.API/Properties/launchSettings.json b/src/Services/Catalog/Catalog.API/Properties/launchSettings.json index 1bf8eb1f3..2b21ca280 100644 --- a/src/Services/Catalog/Catalog.API/Properties/launchSettings.json +++ b/src/Services/Catalog/Catalog.API/Properties/launchSettings.json @@ -3,7 +3,7 @@ "windowsAuthentication": false, "anonymousAuthentication": true, "iisExpress": { - "applicationUrl": "http://localhost:5101", + "applicationUrl": "http://localhost:57424/", "sslPort": 0 } }, @@ -19,6 +19,7 @@ "Microsoft.eShopOnContainers.Services.Catalog.API": { "commandName": "Project", "launchBrowser": true, + "launchUrl": "http://localhost:55101/", "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" } diff --git a/src/Services/Identity/Identity.API/Configuration/Config.cs b/src/Services/Identity/Identity.API/Configuration/Config.cs index 969b86aa1..3bc705995 100644 --- a/src/Services/Identity/Identity.API/Configuration/Config.cs +++ b/src/Services/Identity/Identity.API/Configuration/Config.cs @@ -14,7 +14,9 @@ namespace Microsoft.eShopOnContainers.Services.Identity.API.Configuration new ApiResource("orders", "Orders Service"), new ApiResource("basket", "Basket Service"), new ApiResource("marketing", "Marketing Service"), - new ApiResource("locations", "Locations Service") + new ApiResource("locations", "Locations Service"), + new ApiResource("mobileshoppingagg", "Mobile Shopping Aggregator"), + new ApiResource("webshoppingagg", "Web Shopping Aggregator") }; } @@ -52,7 +54,8 @@ namespace Microsoft.eShopOnContainers.Services.Identity.API.Configuration "orders", "basket", "locations", - "marketing" + "marketing", + "webshoppingagg" } }, new Client @@ -78,7 +81,8 @@ namespace Microsoft.eShopOnContainers.Services.Identity.API.Configuration "orders", "basket", "locations", - "marketing" + "marketing", + "mobileshoppingagg" }, //Allow requesting refresh tokens for long lived API access AllowOfflineAccess = true, @@ -114,7 +118,8 @@ namespace Microsoft.eShopOnContainers.Services.Identity.API.Configuration "orders", "basket", "locations", - "marketing" + "marketing", + "webshoppingagg" }, }, new Client @@ -146,7 +151,8 @@ namespace Microsoft.eShopOnContainers.Services.Identity.API.Configuration "orders", "basket", "locations", - "marketing" + "marketing", + "webshoppingagg" }, }, new Client @@ -208,7 +214,38 @@ namespace Microsoft.eShopOnContainers.Services.Identity.API.Configuration { "orders" } + }, + new Client + { + ClientId = "mobileshoppingaggswaggerui", + ClientName = "Mobile Shopping Aggregattor Swagger UI", + AllowedGrantTypes = GrantTypes.Implicit, + AllowAccessTokensViaBrowser = true, + + RedirectUris = { $"{clientsUrl["MobileShoppingAgg"]}/swagger/o2c.html" }, + PostLogoutRedirectUris = { $"{clientsUrl["MobileShoppingAgg"]}/swagger/" }, + + AllowedScopes = + { + "mobileshoppingagg" + } + }, + new Client + { + ClientId = "webshoppingaggswaggerui", + ClientName = "Web Shopping Aggregattor Swagger UI", + AllowedGrantTypes = GrantTypes.Implicit, + AllowAccessTokensViaBrowser = true, + + RedirectUris = { $"{clientsUrl["WebShoppingAgg"]}/swagger/o2c.html" }, + PostLogoutRedirectUris = { $"{clientsUrl["WebShoppingAgg"]}/swagger/" }, + + AllowedScopes = + { + "webshoppingagg" + } } + }; } } diff --git a/src/Services/Identity/Identity.API/Data/ConfigurationDbContextSeed.cs b/src/Services/Identity/Identity.API/Data/ConfigurationDbContextSeed.cs index b109bf896..a5a4383bd 100644 --- a/src/Services/Identity/Identity.API/Data/ConfigurationDbContextSeed.cs +++ b/src/Services/Identity/Identity.API/Data/ConfigurationDbContextSeed.cs @@ -1,7 +1,6 @@ using IdentityServer4.EntityFramework.DbContexts; using IdentityServer4.EntityFramework.Mappers; using Microsoft.eShopOnContainers.Services.Identity.API.Configuration; -using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Configuration; using System.Collections.Generic; using System.Linq; @@ -11,36 +10,49 @@ namespace Microsoft.eShopOnContainers.Services.Identity.API.Data { public class ConfigurationDbContextSeed { - public async Task SeedAsync(ConfigurationDbContext context, IConfiguration configuration) + public async Task SeedAsync(ConfigurationDbContext context,IConfiguration configuration) { + //callbacks urls from config: - var clientUrls = new Dictionary - { - {"Mvc", configuration.GetValue("MvcClient")}, - {"Spa", configuration.GetValue("SpaClient")}, - {"Xamarin", configuration.GetValue("XamarinCallback")}, - {"LocationsApi", configuration.GetValue("LocationApiClient")}, - {"MarketingApi", configuration.GetValue("MarketingApiClient")}, - {"BasketApi", configuration.GetValue("BasketApiClient")}, - {"OrderingApi", configuration.GetValue("OrderingApiClient")} - }; + var clientUrls = new Dictionary(); + + clientUrls.Add("Mvc", configuration.GetValue("MvcClient")); + clientUrls.Add("Spa", configuration.GetValue("SpaClient")); + clientUrls.Add("Xamarin", configuration.GetValue("XamarinCallback")); + clientUrls.Add("LocationsApi", configuration.GetValue("LocationApiClient")); + clientUrls.Add("MarketingApi", configuration.GetValue("MarketingApiClient")); + clientUrls.Add("BasketApi", configuration.GetValue("BasketApiClient")); + clientUrls.Add("OrderingApi", configuration.GetValue("OrderingApiClient")); + clientUrls.Add("MobileShoppingAgg", configuration.GetValue("MobileShoppingAggClient")); + clientUrls.Add("WebShoppingAgg", configuration.GetValue("WebShoppingAggClient")); - if (!await context.Clients.AnyAsync()) + if (!context.Clients.Any()) { - context.Clients.AddRange(Config.GetClients(clientUrls).Select(client => client.ToEntity())); + foreach (var client in Config.GetClients(clientUrls)) + { + await context.Clients.AddAsync(client.ToEntity()); + } + await context.SaveChangesAsync(); } - if (!await context.IdentityResources.AnyAsync()) + if (!context.IdentityResources.Any()) { - context.IdentityResources.AddRange(Config.GetResources().Select(resource => resource.ToEntity())); + foreach (var resource in Config.GetResources()) + { + await context.IdentityResources.AddAsync(resource.ToEntity()); + } + await context.SaveChangesAsync(); } - if (!await context.ApiResources.AnyAsync()) + if (!context.ApiResources.Any()) { - context.ApiResources.AddRange(Config.GetApis().Select(api => api.ToEntity())); - } + foreach (var api in Config.GetApis()) + { + await context.ApiResources.AddAsync(api.ToEntity()); + } - await context.SaveChangesAsync(); + await context.SaveChangesAsync(); + } } } } diff --git a/src/Services/Identity/Identity.API/Properties/launchSettings.json b/src/Services/Identity/Identity.API/Properties/launchSettings.json index 91f06fd57..e52e9f99c 100644 --- a/src/Services/Identity/Identity.API/Properties/launchSettings.json +++ b/src/Services/Identity/Identity.API/Properties/launchSettings.json @@ -3,7 +3,7 @@ "windowsAuthentication": false, "anonymousAuthentication": true, "iisExpress": { - "applicationUrl": "http://localhost:5105", + "applicationUrl": "http://localhost:54010/", "sslPort": 0 } }, @@ -11,7 +11,7 @@ "IIS Express": { "commandName": "IISExpress", "launchBrowser": true, - "launchUrl": "http://localhost:5105", + "launchUrl": "http://localhost:55105", "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" } @@ -19,7 +19,7 @@ "eShopOnContainers.Identity": { "commandName": "Project", "launchBrowser": true, - "launchUrl": "http://localhost:5000", + "launchUrl": "http://localhost:55105", "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" } diff --git a/src/Services/Location/Locations.API/Properties/launchSettings.json b/src/Services/Location/Locations.API/Properties/launchSettings.json index 45b637914..1c86a33b1 100644 --- a/src/Services/Location/Locations.API/Properties/launchSettings.json +++ b/src/Services/Location/Locations.API/Properties/launchSettings.json @@ -1,9 +1,9 @@ -{ +{ "iisSettings": { "windowsAuthentication": false, "anonymousAuthentication": true, "iisExpress": { - "applicationUrl": "http://localhost:3278/", + "applicationUrl": "http://localhost:54020/", "sslPort": 0 } }, @@ -26,4 +26,4 @@ "applicationUrl": "http://localhost:3279" } } -} +} \ No newline at end of file diff --git a/src/Services/Marketing/Marketing.API/Properties/launchSettings.json b/src/Services/Marketing/Marketing.API/Properties/launchSettings.json index e222e065d..dea046099 100644 --- a/src/Services/Marketing/Marketing.API/Properties/launchSettings.json +++ b/src/Services/Marketing/Marketing.API/Properties/launchSettings.json @@ -3,7 +3,7 @@ "windowsAuthentication": false, "anonymousAuthentication": true, "iisExpress": { - "applicationUrl": "http://localhost:5110", + "applicationUrl": "http://localhost:63455/", "sslPort": 0 } }, diff --git a/src/Services/Ordering/Ordering.API/Application/Commands/CreateOrderCommand.cs b/src/Services/Ordering/Ordering.API/Application/Commands/CreateOrderCommand.cs index 980f9d0b6..437212b8d 100644 --- a/src/Services/Ordering/Ordering.API/Application/Commands/CreateOrderCommand.cs +++ b/src/Services/Ordering/Ordering.API/Application/Commands/CreateOrderCommand.cs @@ -4,6 +4,7 @@ using System.Collections.Generic; using System.Runtime.Serialization; using System.Collections; using Ordering.API.Application.Models; +using System.Linq; namespace Microsoft.eShopOnContainers.Services.Ordering.API.Application.Commands { @@ -68,7 +69,7 @@ namespace Microsoft.eShopOnContainers.Services.Ordering.API.Application.Commands string cardNumber, string cardHolderName, DateTime cardExpiration, string cardSecurityNumber, int cardTypeId) : this() { - _orderItems = MapToOrderItems(basketItems); + _orderItems = basketItems.ToOrderItemsDTO().ToList(); UserId = userId; City = city; Street = street; @@ -83,20 +84,6 @@ namespace Microsoft.eShopOnContainers.Services.Ordering.API.Application.Commands CardExpiration = cardExpiration; } - private List MapToOrderItems(List basketItems) - { - var result = new List(); - basketItems.ForEach((item) => { - result.Add(new OrderItemDTO() { - ProductId = int.TryParse(item.ProductId, out int id) ? id : -1, - ProductName = item.ProductName, - PictureUrl = item.PictureUrl, - UnitPrice = item.UnitPrice, - Units = item.Quantity - }); - }); - return result; - } public class OrderItemDTO { diff --git a/src/Services/Ordering/Ordering.API/Application/Commands/CreateOrderDraftCommand.cs b/src/Services/Ordering/Ordering.API/Application/Commands/CreateOrderDraftCommand.cs new file mode 100644 index 000000000..1d3d52c63 --- /dev/null +++ b/src/Services/Ordering/Ordering.API/Application/Commands/CreateOrderDraftCommand.cs @@ -0,0 +1,27 @@ +using MediatR; +using Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.OrderAggregate; +using Ordering.API.Application.Models; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.Serialization; +using System.Threading.Tasks; +using static Microsoft.eShopOnContainers.Services.Ordering.API.Application.Commands.CreateOrderCommand; + +namespace Microsoft.eShopOnContainers.Services.Ordering.API.Application.Commands +{ + public class CreateOrderDraftCommand : IRequest + { + + public string BuyerId { get; private set; } + + public IEnumerable Items { get; private set; } + + public CreateOrderDraftCommand(string buyerId, IEnumerable items) + { + BuyerId = buyerId; + Items = items; + } + } + +} diff --git a/src/Services/Ordering/Ordering.API/Application/Commands/CreateOrderDraftCommandHandler.cs b/src/Services/Ordering/Ordering.API/Application/Commands/CreateOrderDraftCommandHandler.cs new file mode 100644 index 000000000..2c315248b --- /dev/null +++ b/src/Services/Ordering/Ordering.API/Application/Commands/CreateOrderDraftCommandHandler.cs @@ -0,0 +1,72 @@ +namespace Microsoft.eShopOnContainers.Services.Ordering.API.Application.Commands +{ + using Domain.AggregatesModel.OrderAggregate; + using global::Ordering.API.Application.Models; + using MediatR; + using Microsoft.eShopOnContainers.Services.Ordering.API.Infrastructure.Services; + using Microsoft.eShopOnContainers.Services.Ordering.Infrastructure.Idempotency; + using System; + using System.Collections.Generic; + using System.Linq; + using System.Threading; + using System.Threading.Tasks; + using static Microsoft.eShopOnContainers.Services.Ordering.API.Application.Commands.CreateOrderCommand; + + // Regular CommandHandler + public class CreateOrderDraftCommandHandler + : IRequestHandler + { + private readonly IOrderRepository _orderRepository; + private readonly IIdentityService _identityService; + private readonly IMediator _mediator; + + // Using DI to inject infrastructure persistence Repositories + public CreateOrderDraftCommandHandler(IMediator mediator, IIdentityService identityService) + { + _identityService = identityService ?? throw new ArgumentNullException(nameof(identityService)); + _mediator = mediator ?? throw new ArgumentNullException(nameof(mediator)); + } + + public Task Handle(CreateOrderDraftCommand message, CancellationToken cancellationToken) + { + + var order = Order.NewDraft(); + var orderItems = message.Items.Select(i => i.ToOrderItemDTO()); + foreach (var item in orderItems) + { + order.AddOrderItem(item.ProductId, item.ProductName, item.UnitPrice, item.Discount, item.PictureUrl, item.Units); + } + + return Task.FromResult(OrderDraftDTO.FromOrder(order)); + } + } + + + public class OrderDraftDTO + { + public IEnumerable OrderItems { get; set; } + public decimal Total { get; set; } + + public static OrderDraftDTO FromOrder(Order order) + { + return new OrderDraftDTO() + { + OrderItems = order.OrderItems.Select(oi => new OrderItemDTO + { + Discount = oi.GetCurrentDiscount(), + ProductId = oi.ProductId, + UnitPrice = oi.GetUnitPrice(), + PictureUrl = oi.GetPictureUri(), + Units = oi.GetUnits(), + ProductName = oi.GetOrderItemProductName() + }), + Total = order.GetTotal() + }; + } + + } + + + + +} diff --git a/src/Services/Ordering/Ordering.API/Controllers/OrdersController.cs b/src/Services/Ordering/Ordering.API/Controllers/OrdersController.cs index 993986543..ac179c97f 100644 --- a/src/Services/Ordering/Ordering.API/Controllers/OrdersController.cs +++ b/src/Services/Ordering/Ordering.API/Controllers/OrdersController.cs @@ -5,6 +5,7 @@ using Microsoft.eShopOnContainers.Services.Ordering.API.Application.Commands; using Microsoft.eShopOnContainers.Services.Ordering.API.Application.Queries; using Microsoft.eShopOnContainers.Services.Ordering.API.Infrastructure.Services; using Ordering.API.Application.Commands; +using Ordering.API.Application.Models; using System; using System.Collections.Generic; using System.Net; @@ -101,6 +102,14 @@ namespace Microsoft.eShopOnContainers.Services.Ordering.API.Controllers return Ok(cardTypes); } + + [Route("draft")] + [HttpPost] + public async Task GetOrderDraftFromBasketData([FromBody] CreateOrderDraftCommand createOrderDraftCommand) + { + var draft = await _mediator.Send(createOrderDraftCommand); + return Ok(draft); + } } } diff --git a/src/Services/Ordering/Ordering.API/Extensions/BasketItemExtensions.cs b/src/Services/Ordering/Ordering.API/Extensions/BasketItemExtensions.cs new file mode 100644 index 000000000..56f280978 --- /dev/null +++ b/src/Services/Ordering/Ordering.API/Extensions/BasketItemExtensions.cs @@ -0,0 +1,32 @@ + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using static Microsoft.eShopOnContainers.Services.Ordering.API.Application.Commands.CreateOrderCommand; + +namespace Ordering.API.Application.Models +{ + public static class BasketItemExtensions + { + public static IEnumerable ToOrderItemsDTO(this IEnumerable basketItems) + { + foreach (var item in basketItems) + { + yield return item.ToOrderItemDTO(); + } + } + + public static OrderItemDTO ToOrderItemDTO(this BasketItem item) + { + return new OrderItemDTO() + { + ProductId = int.TryParse(item.ProductId, out int id) ? id : -1, + ProductName = item.ProductName, + PictureUrl = item.PictureUrl, + UnitPrice = item.UnitPrice, + Units = item.Quantity + }; + } + } +} diff --git a/src/Services/Ordering/Ordering.API/Properties/launchSettings.json b/src/Services/Ordering/Ordering.API/Properties/launchSettings.json index a6e47ca2d..9d9a76490 100644 --- a/src/Services/Ordering/Ordering.API/Properties/launchSettings.json +++ b/src/Services/Ordering/Ordering.API/Properties/launchSettings.json @@ -3,7 +3,7 @@ "windowsAuthentication": false, "anonymousAuthentication": true, "iisExpress": { - "applicationUrl": "http://localhost:5102/", + "applicationUrl": "http://localhost:55102/", "sslPort": 0 } }, @@ -19,7 +19,7 @@ "Microsoft.eShopOnContainers.Services.Ordering.API": { "commandName": "Project", "launchBrowser": true, - "launchUrl": "http://localhost:5000/api/environmentInfo/machinename", + "launchUrl": "http://localhost:55102/", "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" } diff --git a/src/Services/Ordering/Ordering.Domain/AggregatesModel/OrderAggregate/Order.cs b/src/Services/Ordering/Ordering.Domain/AggregatesModel/OrderAggregate/Order.cs index 428d97580..82e5744dd 100644 --- a/src/Services/Ordering/Ordering.Domain/AggregatesModel/OrderAggregate/Order.cs +++ b/src/Services/Ordering/Ordering.Domain/AggregatesModel/OrderAggregate/Order.cs @@ -25,6 +25,10 @@ namespace Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.O private string _description; + + // Draft orders have this set to true. Currently we don't check anywhere the draft status of an Order, but we could do it if needed + private bool _isDraft; + // DDD Patterns comment // Using a private collection field, better for DDD Aggregate's encapsulation // so OrderItems cannot be added from "outside the AggregateRoot" directly to the collection, @@ -34,12 +38,21 @@ namespace Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.O private int? _paymentMethodId; - protected Order() { _orderItems = new List(); } + public static Order NewDraft() + { + var order = new Order(); + order._isDraft = true; + return order; + } + + protected Order() { + _orderItems = new List(); + _isDraft = false; + } public Order(string userId, Address address, int cardTypeId, string cardNumber, string cardSecurityNumber, - string cardHolderName, DateTime cardExpiration, int? buyerId = null, int? paymentMethodId = null) + string cardHolderName, DateTime cardExpiration, int? buyerId = null, int? paymentMethodId = null) : this() { - _orderItems = new List(); _buyerId = buyerId; _paymentMethodId = paymentMethodId; _orderStatusId = OrderStatus.Submitted.Id; @@ -92,35 +105,34 @@ namespace Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.O } public void SetAwaitingValidationStatus() - { + { if (_orderStatusId == OrderStatus.Submitted.Id) { - _orderStatusId = OrderStatus.AwaitingValidation.Id; - AddDomainEvent(new OrderStatusChangedToAwaitingValidationDomainEvent(Id, _orderItems)); - } + _orderStatusId = OrderStatus.AwaitingValidation.Id; + } } public void SetStockConfirmedStatus() { if (_orderStatusId == OrderStatus.AwaitingValidation.Id) { + AddDomainEvent(new OrderStatusChangedToStockConfirmedDomainEvent(Id)); + _orderStatusId = OrderStatus.StockConfirmed.Id; _description = "All the items were confirmed with available stock."; - - AddDomainEvent(new OrderStatusChangedToStockConfirmedDomainEvent(Id)); - } + } } public void SetPaidStatus() { if (_orderStatusId == OrderStatus.StockConfirmed.Id) { + AddDomainEvent(new OrderStatusChangedToPaidDomainEvent(Id, OrderItems)); + _orderStatusId = OrderStatus.Paid.Id; _description = "The payment was performed at a simulated \"American Bank checking bank account endinf on XX35071\""; - - AddDomainEvent(new OrderStatusChangedToPaidDomainEvent(Id, OrderItems)); - } + } } public void SetShippedStatus() @@ -158,13 +170,13 @@ namespace Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.O var itemsStockRejectedDescription = string.Join(", ", itemsStockRejectedProductNames); _description = $"The product items don't have stock: ({itemsStockRejectedDescription})."; - } + } } private void AddOrderStartedDomainEvent(string userId, int cardTypeId, string cardNumber, string cardSecurityNumber, string cardHolderName, DateTime cardExpiration) { - var orderStartedDomainEvent = new OrderStartedDomainEvent(this, userId, cardTypeId, + var orderStartedDomainEvent = new OrderStartedDomainEvent(this, userId, cardTypeId, cardNumber, cardSecurityNumber, cardHolderName, cardExpiration); diff --git a/src/Services/Ordering/Ordering.Domain/AggregatesModel/OrderAggregate/OrderItem.cs b/src/Services/Ordering/Ordering.Domain/AggregatesModel/OrderAggregate/OrderItem.cs index 1b7896dcc..b3b7435e3 100644 --- a/src/Services/Ordering/Ordering.Domain/AggregatesModel/OrderAggregate/OrderItem.cs +++ b/src/Services/Ordering/Ordering.Domain/AggregatesModel/OrderAggregate/OrderItem.cs @@ -41,13 +41,7 @@ namespace Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.O _pictureUrl = PictureUrl; } - public void SetPictureUri(string pictureUri) - { - if (!String.IsNullOrWhiteSpace(pictureUri)) - { - _pictureUrl = pictureUri; - } - } + public string GetPictureUri() => _pictureUrl; public decimal GetCurrentDiscount() { diff --git a/src/Services/Payment/Payment.API/Properties/launchSettings.json b/src/Services/Payment/Payment.API/Properties/launchSettings.json index faf310f83..5eac4c092 100644 --- a/src/Services/Payment/Payment.API/Properties/launchSettings.json +++ b/src/Services/Payment/Payment.API/Properties/launchSettings.json @@ -1,9 +1,9 @@ -{ +{ "iisSettings": { "windowsAuthentication": false, "anonymousAuthentication": true, "iisExpress": { - "applicationUrl": "http://localhost:3330/", + "applicationUrl": "http://localhost:63336/", "sslPort": 0 } }, @@ -26,4 +26,4 @@ "applicationUrl": "http://localhost:3331" } } -} +} \ No newline at end of file diff --git a/src/Web/WebMVC/AppSettings.cs b/src/Web/WebMVC/AppSettings.cs index 42100ab62..1f11e750e 100644 --- a/src/Web/WebMVC/AppSettings.cs +++ b/src/Web/WebMVC/AppSettings.cs @@ -8,11 +8,9 @@ namespace Microsoft.eShopOnContainers.WebMVC public class AppSettings { public Connectionstrings ConnectionStrings { get; set; } - public string CatalogUrl { get; set; } - public string OrderingUrl { get; set; } - public string BasketUrl { get; set; } public string MarketingUrl { get; set; } - public string LocationsUrl { get; set; } + + public string PurchaseUrl { get; set; } public bool ActivateCampaignDetailFunction { get; set; } public Logging Logging { get; set; } public bool UseCustomizationData { get; set; } diff --git a/src/Web/WebMVC/Controllers/CartController.cs b/src/Web/WebMVC/Controllers/CartController.cs index 8b41c5320..660da1d56 100644 --- a/src/Web/WebMVC/Controllers/CartController.cs +++ b/src/Web/WebMVC/Controllers/CartController.cs @@ -49,11 +49,8 @@ namespace Microsoft.eShopOnContainers.WebMVC.Controllers { var user = _appUserParser.Parse(HttpContext.User); var basket = await _basketSvc.SetQuantities(user, quantities); - var vm = await _basketSvc.UpdateBasket(basket); - if (action == "[ Checkout ]") { - var order = _basketSvc.MapBasketToOrder(basket); return RedirectToAction("Create", "Order"); } } @@ -70,19 +67,11 @@ namespace Microsoft.eShopOnContainers.WebMVC.Controllers { try { - if (productDetails.Id != null) + if (productDetails?.Id != null) { var user = _appUserParser.Parse(HttpContext.User); - var product = new BasketItem() - { - Id = Guid.NewGuid().ToString(), - Quantity = 1, - ProductName = productDetails.Name, - PictureUrl = productDetails.PictureUri, - UnitPrice = productDetails.Price, - ProductId = productDetails.Id - }; - await _basketSvc.AddItemToBasket(user, product); + await _basketSvc.AddItemToBasket(user, productDetails.Id); + //await _basketSvc.AddItemToBasket(user, product); } return RedirectToAction("Index", "Catalog"); } diff --git a/src/Web/WebMVC/Controllers/OrderController.cs b/src/Web/WebMVC/Controllers/OrderController.cs index 11e688728..a5bf4785e 100644 --- a/src/Web/WebMVC/Controllers/OrderController.cs +++ b/src/Web/WebMVC/Controllers/OrderController.cs @@ -27,9 +27,9 @@ namespace Microsoft.eShopOnContainers.WebMVC.Controllers public async Task Create() { + var user = _appUserParser.Parse(HttpContext.User); - var basket = await _basketSvc.GetBasket(user); - var order = _basketSvc.MapBasketToOrder(basket); + var order = await _basketSvc.GetOrderDraft(user.Id); var vm = _orderSvc.MapUserInfoIntoOrder(user, order); vm.CardExpirationShortFormat(); diff --git a/src/Web/WebMVC/Controllers/TestController.cs b/src/Web/WebMVC/Controllers/TestController.cs new file mode 100644 index 000000000..1b35d5d2b --- /dev/null +++ b/src/Web/WebMVC/Controllers/TestController.cs @@ -0,0 +1,56 @@ +using Microsoft.AspNetCore.Authentication; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Mvc; +using Microsoft.eShopOnContainers.BuildingBlocks.Resilience.Http; +using Microsoft.eShopOnContainers.WebMVC.Services; +using Microsoft.eShopOnContainers.WebMVC.ViewModels; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace WebMVC.Controllers +{ + class TestPayload + { + public int CatalogItemId { get; set; } + public string BasketId { get; set; } + + public int Quantity { get; set; } + } + + [Authorize] + public class TestController : Controller + { + private readonly IHttpClient _client; + private readonly IIdentityParser _appUserParser; + public TestController(IHttpClient client, IIdentityParser identityParser) + { + _client = client; + _appUserParser = identityParser; + } + + public async Task Ocelot() + { + var url = "http://apigw/shopping/api/v1/basket/items"; + var payload = new TestPayload() + { + CatalogItemId = 1, + Quantity = 1, + BasketId = _appUserParser.Parse(User).Id + }; + var token = await HttpContext.GetTokenAsync("access_token"); + var response = await _client.PostAsync(url, payload, token); + + if (response.IsSuccessStatusCode) + { + var str = await response.Content.ReadAsStringAsync(); + return Ok(str); + } + else + { + return Ok(new { response.StatusCode, response.ReasonPhrase }); + } + } + } +} diff --git a/src/Web/WebMVC/Infrastructure/API.cs b/src/Web/WebMVC/Infrastructure/API.cs index edb2c5ed5..d6f485e21 100644 --- a/src/Web/WebMVC/Infrastructure/API.cs +++ b/src/Web/WebMVC/Infrastructure/API.cs @@ -4,27 +4,21 @@ namespace WebMVC.Infrastructure { public static class API { - public static class Basket - { - public static string GetBasket(string baseUri, string basketId) - { - return $"{baseUri}/{basketId}"; - } - public static string UpdateBasket(string baseUri) - { - return baseUri; - } + public static class Purchase + { + public static string AddItemToBasket(string baseUri) => $"{baseUri}/basket/items"; + public static string UpdateBasketItem(string baseUri) => $"{baseUri}/basket/items"; - public static string CheckoutBasket(string baseUri) - { - return $"{baseUri}/checkout"; - } + public static string GetOrderDraft(string baseUri, string basketId) => $"{baseUri}/order/draft/{basketId}"; + } - public static string CleanBasket(string baseUri, string basketId) - { - return $"{baseUri}/{basketId}"; - } + public static class Basket + { + public static string GetBasket(string baseUri, string basketId) => $"{baseUri}/{basketId}"; + public static string UpdateBasket(string baseUri) => baseUri; + public static string CheckoutBasket(string baseUri) => $"{baseUri}/checkout"; + public static string CleanBasket(string baseUri, string basketId) => $"{baseUri}/{basketId}"; } public static class Order @@ -100,7 +94,7 @@ namespace WebMVC.Infrastructure public static string CreateOrUpdateUserLocation(string baseUri) { return baseUri; - } + } } } } \ No newline at end of file diff --git a/src/Web/WebMVC/Services/BasketService.cs b/src/Web/WebMVC/Services/BasketService.cs index 6c8524800..54287a796 100644 --- a/src/Web/WebMVC/Services/BasketService.cs +++ b/src/Web/WebMVC/Services/BasketService.cs @@ -5,6 +5,7 @@ using Microsoft.eShopOnContainers.WebMVC.ViewModels; using Microsoft.Extensions.Options; using Newtonsoft.Json; using System.Collections.Generic; +using System.Linq; using System.Threading.Tasks; using WebMVC.Infrastructure; using WebMVC.Models; @@ -14,14 +15,19 @@ namespace Microsoft.eShopOnContainers.WebMVC.Services public class BasketService : IBasketService { private readonly IOptionsSnapshot _settings; - private IHttpClient _apiClient; - private readonly string _remoteServiceBaseUrl; - private IHttpContextAccessor _httpContextAccesor; + private readonly IHttpClient _apiClient; + private readonly string _basketByPassUrl; + private readonly string _purchaseUrl; + private readonly IHttpContextAccessor _httpContextAccesor; - public BasketService(IOptionsSnapshot settings, IHttpContextAccessor httpContextAccesor, IHttpClient httpClient) + private readonly string _bffUrl; + + public BasketService(IOptionsSnapshot settings, + IHttpContextAccessor httpContextAccesor, IHttpClient httpClient) { _settings = settings; - _remoteServiceBaseUrl = $"{_settings.Value.BasketUrl}/api/v1/basket"; + _basketByPassUrl = $"{_settings.Value.PurchaseUrl}/api/v1/b/basket"; + _purchaseUrl = $"{_settings.Value.PurchaseUrl}/api/v1"; _httpContextAccesor = httpContextAccesor; _apiClient = httpClient; } @@ -29,24 +35,19 @@ namespace Microsoft.eShopOnContainers.WebMVC.Services public async Task GetBasket(ApplicationUser user) { var token = await GetUserTokenAsync(); - var getBasketUri = API.Basket.GetBasket(_remoteServiceBaseUrl, user.Id); + var getBasketUri = API.Basket.GetBasket(_basketByPassUrl, user.Id); var dataString = await _apiClient.GetStringAsync(getBasketUri, token); - // Use the ?? Null conditional operator to simplify the initialization of response - var response = JsonConvert.DeserializeObject(dataString) ?? - new Basket() - { - BuyerId = user.Id - }; - - return response; + return string.IsNullOrEmpty(dataString) ? + new Basket() { BuyerId = user.Id} : + JsonConvert.DeserializeObject(dataString); } public async Task UpdateBasket(Basket basket) { var token = await GetUserTokenAsync(); - var updateBasketUri = API.Basket.UpdateBasket(_remoteServiceBaseUrl); + var updateBasketUri = API.Basket.UpdateBasket(_basketByPassUrl); var response = await _apiClient.PostAsync(updateBasketUri, basket, token); @@ -58,7 +59,7 @@ namespace Microsoft.eShopOnContainers.WebMVC.Services public async Task Checkout(BasketDTO basket) { var token = await GetUserTokenAsync(); - var updateBasketUri = API.Basket.CheckoutBasket(_remoteServiceBaseUrl); + var updateBasketUri = API.Basket.CheckoutBasket(_basketByPassUrl); var response = await _apiClient.PostAsync(updateBasketUri, basket, token); @@ -67,60 +68,50 @@ namespace Microsoft.eShopOnContainers.WebMVC.Services public async Task SetQuantities(ApplicationUser user, Dictionary quantities) { - var basket = await GetBasket(user); - basket.Items.ForEach(x => + var token = await GetUserTokenAsync(); + var updateBasketUri = API.Purchase.UpdateBasketItem(_purchaseUrl); + var userId = user.Id; + + var response = await _apiClient.PutAsync(updateBasketUri, new { - // Simplify this logic by using the - // new out variable initializer. - if (quantities.TryGetValue(x.Id, out var quantity)) + BasketId = userId, + Updates = quantities.Select(kvp => new { - x.Quantity = quantity; - } - }); + BasketItemId = kvp.Key, + NewQty = kvp.Value + }).ToArray() + }, token); - return basket; + response.EnsureSuccessStatusCode(); + var jsonResponse = await response.Content.ReadAsStringAsync(); + return JsonConvert.DeserializeObject(jsonResponse); } - public Order MapBasketToOrder(Basket basket) + public async Task GetOrderDraft(string basketId) { - var order = new Order(); - order.Total = 0; - - basket.Items.ForEach(x => - { - order.OrderItems.Add(new OrderItem() - { - ProductId = int.Parse(x.ProductId), + var token = await GetUserTokenAsync(); + var draftOrderUri = API.Purchase.GetOrderDraft(_purchaseUrl, basketId); + var json = await _apiClient.GetStringAsync(draftOrderUri, token); + return JsonConvert.DeserializeObject(json); + } - PictureUrl = x.PictureUrl, - ProductName = x.ProductName, - Units = x.Quantity, - UnitPrice = x.UnitPrice - }); - order.Total += (x.Quantity * x.UnitPrice); - }); - return order; - } - public async Task AddItemToBasket(ApplicationUser user, BasketItem product) + public async Task AddItemToBasket(ApplicationUser user, int productId) { - var basket = await GetBasket(user); + var token = await GetUserTokenAsync(); + var updateBasketUri = API.Purchase.AddItemToBasket(_purchaseUrl); + var userId = user.Id; - if (basket == null) + var response = await _apiClient.PostAsync(updateBasketUri, new { - basket = new Basket() - { - BuyerId = user.Id, - Items = new List() - }; - } + CatalogItemId = productId, + BasketId = userId, + Quantity = 1 + }, token); - basket.Items.Add(product); - - await UpdateBasket(basket); - } + } async Task GetUserTokenAsync() { diff --git a/src/Web/WebMVC/Services/CampaignService.cs b/src/Web/WebMVC/Services/CampaignService.cs index 6190e74d6..7d61c9e7a 100644 --- a/src/Web/WebMVC/Services/CampaignService.cs +++ b/src/Web/WebMVC/Services/CampaignService.cs @@ -26,7 +26,7 @@ _apiClient = httpClient; _logger = logger; - _remoteServiceBaseUrl = $"{_settings.Value.MarketingUrl}/api/v1/campaigns/"; + _remoteServiceBaseUrl = $"{_settings.Value.MarketingUrl}/api/v1/m/campaigns/"; _httpContextAccesor = httpContextAccesor ?? throw new ArgumentNullException(nameof(httpContextAccesor)); } diff --git a/src/Web/WebMVC/Services/CatalogService.cs b/src/Web/WebMVC/Services/CatalogService.cs index 2af428e2e..5b6fbe26b 100644 --- a/src/Web/WebMVC/Services/CatalogService.cs +++ b/src/Web/WebMVC/Services/CatalogService.cs @@ -25,7 +25,7 @@ namespace Microsoft.eShopOnContainers.WebMVC.Services _apiClient = httpClient; _logger = logger; - _remoteServiceBaseUrl = $"{_settings.Value.CatalogUrl}/api/v1/catalog/"; + _remoteServiceBaseUrl = $"{_settings.Value.PurchaseUrl}/api/v1/c/catalog/"; } public async Task GetCatalogItems(int page, int take, int? brand, int? type) diff --git a/src/Web/WebMVC/Services/IBasketService.cs b/src/Web/WebMVC/Services/IBasketService.cs index 13921909a..cfbea5ff0 100644 --- a/src/Web/WebMVC/Services/IBasketService.cs +++ b/src/Web/WebMVC/Services/IBasketService.cs @@ -10,10 +10,10 @@ namespace Microsoft.eShopOnContainers.WebMVC.Services public interface IBasketService { Task GetBasket(ApplicationUser user); - Task AddItemToBasket(ApplicationUser user, BasketItem product); + Task AddItemToBasket(ApplicationUser user, int productId); Task UpdateBasket(Basket basket); Task Checkout(BasketDTO basket); Task SetQuantities(ApplicationUser user, Dictionary quantities); - Order MapBasketToOrder(Basket basket); + Task GetOrderDraft(string basketId); } } diff --git a/src/Web/WebMVC/Services/LocationService.cs b/src/Web/WebMVC/Services/LocationService.cs index 652484f4b..8bbdf743a 100644 --- a/src/Web/WebMVC/Services/LocationService.cs +++ b/src/Web/WebMVC/Services/LocationService.cs @@ -27,7 +27,7 @@ namespace WebMVC.Services _apiClient = httpClient; _logger = logger; - _remoteServiceBaseUrl = $"{_settings.Value.LocationsUrl}/api/v1/locations/"; + _remoteServiceBaseUrl = $"{_settings.Value.MarketingUrl}/api/v1/l/locations/"; _httpContextAccesor = httpContextAccesor ?? throw new ArgumentNullException(nameof(httpContextAccesor)); } diff --git a/src/Web/WebMVC/Services/OrderingService.cs b/src/Web/WebMVC/Services/OrderingService.cs index f36f1410d..ec9d2e8fd 100644 --- a/src/Web/WebMVC/Services/OrderingService.cs +++ b/src/Web/WebMVC/Services/OrderingService.cs @@ -21,7 +21,7 @@ namespace Microsoft.eShopOnContainers.WebMVC.Services public OrderingService(IOptionsSnapshot settings, IHttpContextAccessor httpContextAccesor, IHttpClient httpClient) { - _remoteServiceBaseUrl = $"{settings.Value.OrderingUrl}/api/v1/orders"; + _remoteServiceBaseUrl = $"{settings.Value.PurchaseUrl}/api/v1/o/orders"; _settings = settings; _httpContextAccesor = httpContextAccesor; _apiClient = httpClient; diff --git a/src/Web/WebMVC/Startup.cs b/src/Web/WebMVC/Startup.cs index 105b1ed9e..4bc2d8b88 100644 --- a/src/Web/WebMVC/Startup.cs +++ b/src/Web/WebMVC/Startup.cs @@ -130,6 +130,7 @@ namespace Microsoft.eShopOnContainers.WebMVC options.Scope.Add("basket"); options.Scope.Add("marketing"); options.Scope.Add("locations"); + options.Scope.Add("webshoppingagg"); }); } diff --git a/src/Web/WebMVC/ViewModels/CatalogItem.cs b/src/Web/WebMVC/ViewModels/CatalogItem.cs index 6dd216d1d..c869b7382 100644 --- a/src/Web/WebMVC/ViewModels/CatalogItem.cs +++ b/src/Web/WebMVC/ViewModels/CatalogItem.cs @@ -4,7 +4,7 @@ namespace Microsoft.eShopOnContainers.WebMVC.ViewModels { public class CatalogItem { - public string Id { get; set; } + public int Id { get; set; } public string Name { get; set; } public string Description { get; set; } public decimal Price { get; set; } diff --git a/src/Web/WebMVC/Views/Catalog/_product.cshtml b/src/Web/WebMVC/Views/Catalog/_product.cshtml index 11138b55d..0fb1c39c4 100644 --- a/src/Web/WebMVC/Views/Catalog/_product.cshtml +++ b/src/Web/WebMVC/Views/Catalog/_product.cshtml @@ -12,13 +12,5 @@
@Model.Price.ToString("N2")
- - - - - - - - diff --git a/src/Web/WebSPA/AppSettings.cs b/src/Web/WebSPA/AppSettings.cs index fd254c3ae..c3fbd3b80 100644 --- a/src/Web/WebSPA/AppSettings.cs +++ b/src/Web/WebSPA/AppSettings.cs @@ -7,13 +7,13 @@ namespace eShopOnContainers.WebSPA { public class AppSettings { - public string BaseUrl { get; set; } - public string CatalogUrl { get; set; } - public string OrderingUrl { get; set; } public string IdentityUrl { get; set; } public string BasketUrl { get; set; } public string MarketingUrl { get; set; } + + public string PurchaseUrl { get; set; } + public string ActivateCampaignDetailFunction { get; set; } - public bool UseCustomizationData { get; set; } + public bool UseCustomizationData { get; set; } } } diff --git a/src/Web/WebSPA/Client/modules/basket/basket.service.ts b/src/Web/WebSPA/Client/modules/basket/basket.service.ts index 864915541..fef74974e 100644 --- a/src/Web/WebSPA/Client/modules/basket/basket.service.ts +++ b/src/Web/WebSPA/Client/modules/basket/basket.service.ts @@ -23,6 +23,7 @@ import { Subject } from 'rxjs/Subject'; @Injectable() export class BasketService { private basketUrl: string = ''; + private purchaseUrl: string = ''; basket: IBasket = { buyerId: '', items: [] @@ -40,12 +41,14 @@ export class BasketService { if (this.authService.UserData) { this.basket.buyerId = this.authService.UserData.sub; if (this.configurationService.isReady) { - this.basketUrl = this.configurationService.serverSettings.basketUrl; + this.basketUrl = this.configurationService.serverSettings.purchaseUrl; + this.purchaseUrl = this.configurationService.serverSettings.purchaseUrl; this.loadData(); } else { this.configurationService.settingsLoaded$.subscribe(x => { - this.basketUrl = this.configurationService.serverSettings.basketUrl; + this.basketUrl = this.configurationService.serverSettings.purchaseUrl; + this.purchaseUrl = this.configurationService.serverSettings.purchaseUrl; this.loadData(); }); } @@ -63,7 +66,7 @@ export class BasketService { } setBasket(basket): Observable { - let url = this.basketUrl + '/api/v1/basket/'; + let url = this.purchaseUrl + '/api/v1/basket/'; this.basket = basket; return this.service.post(url, basket).map((response: Response) => { return true; @@ -71,7 +74,7 @@ export class BasketService { } setBasketCheckout(basketCheckout): Observable { - let url = this.basketUrl + '/api/v1/basket/checkout'; + let url = this.basketUrl + '/api/v1/b/basket/checkout'; return this.service.postWithId(url, basketCheckout).map((response: Response) => { this.basketEvents.orderCreated(); return true; @@ -79,7 +82,7 @@ export class BasketService { } getBasket(): Observable { - let url = this.basketUrl + '/api/v1/basket/' + this.basket.buyerId; + let url = this.basketUrl + '/api/v1/b/basket/' + this.basket.buyerId; return this.service.get(url).map((response: Response) => { if (response.status === 204) { return null; diff --git a/src/Web/WebSPA/Client/modules/campaigns/campaigns.service.ts b/src/Web/WebSPA/Client/modules/campaigns/campaigns.service.ts index bd1678f44..2a8973322 100644 --- a/src/Web/WebSPA/Client/modules/campaigns/campaigns.service.ts +++ b/src/Web/WebSPA/Client/modules/campaigns/campaigns.service.ts @@ -33,7 +33,7 @@ export class CampaignsService { } getCampaigns(pageIndex: number, pageSize: number): Observable { - let url = this.marketingUrl + '/api/v1/campaigns/user'; + let url = this.marketingUrl + '/api/v1/m/campaigns/user'; url = url + '?pageIndex=' + pageIndex + '&pageSize=' + pageSize; return this.service.get(url).map((response: Response) => { @@ -42,7 +42,7 @@ export class CampaignsService { } getCampaign(id: number): Observable { - let url = this.marketingUrl + '/api/v1/campaigns/' + id; + let url = this.marketingUrl + '/api/v1/m/campaigns/' + id; return this.service.get(url).map((response: Response) => { return response.json(); diff --git a/src/Web/WebSPA/Client/modules/catalog/catalog.service.ts b/src/Web/WebSPA/Client/modules/catalog/catalog.service.ts index bdcb9d664..fc5bc4c5e 100644 --- a/src/Web/WebSPA/Client/modules/catalog/catalog.service.ts +++ b/src/Web/WebSPA/Client/modules/catalog/catalog.service.ts @@ -21,9 +21,9 @@ export class CatalogService { constructor(private service: DataService, private configurationService: ConfigurationService) { this.configurationService.settingsLoaded$.subscribe(x => { - this.catalogUrl = this.configurationService.serverSettings.catalogUrl + '/api/v1/catalog/items'; - this.brandUrl = this.configurationService.serverSettings.catalogUrl + '/api/v1/catalog/catalogbrands'; - this.typesUrl = this.configurationService.serverSettings.catalogUrl + '/api/v1/catalog/catalogtypes'; + this.catalogUrl = this.configurationService.serverSettings.purchaseUrl + '/api/v1/c/catalog/items'; + this.brandUrl = this.configurationService.serverSettings.purchaseUrl + '/api/v1/c/catalog/catalogbrands'; + this.typesUrl = this.configurationService.serverSettings.purchaseUrl + '/api/v1/c/catalog/catalogtypes'; }); } diff --git a/src/Web/WebSPA/Client/modules/orders/orders.service.ts b/src/Web/WebSPA/Client/modules/orders/orders.service.ts index 5eda7c8ce..5c563f836 100644 --- a/src/Web/WebSPA/Client/modules/orders/orders.service.ts +++ b/src/Web/WebSPA/Client/modules/orders/orders.service.ts @@ -22,14 +22,14 @@ export class OrdersService { constructor(private service: DataService, private basketService: BasketWrapperService, private identityService: SecurityService, private configurationService: ConfigurationService) { if (this.configurationService.isReady) - this.ordersUrl = this.configurationService.serverSettings.orderingUrl; + this.ordersUrl = this.configurationService.serverSettings.purchaseUrl; else - this.configurationService.settingsLoaded$.subscribe(x => this.ordersUrl = this.configurationService.serverSettings.orderingUrl); + this.configurationService.settingsLoaded$.subscribe(x => this.ordersUrl = this.configurationService.serverSettings.purchaseUrl); } getOrders(): Observable { - let url = this.ordersUrl + '/api/v1/orders'; + let url = this.ordersUrl + '/api/v1/o/orders'; return this.service.get(url).map((response: Response) => { return response.json(); @@ -37,7 +37,7 @@ export class OrdersService { } getOrder(id: number): Observable { - let url = this.ordersUrl + '/api/v1/orders/' + id; + let url = this.ordersUrl + '/api/v1/o/orders/' + id; return this.service.get(url).map((response: Response) => { return response.json(); diff --git a/src/Web/WebSPA/Client/modules/shared/models/configuration.model.ts b/src/Web/WebSPA/Client/modules/shared/models/configuration.model.ts index f22b28a3e..49950e9d6 100644 --- a/src/Web/WebSPA/Client/modules/shared/models/configuration.model.ts +++ b/src/Web/WebSPA/Client/modules/shared/models/configuration.model.ts @@ -1,8 +1,6 @@ export interface IConfiguration { - catalogUrl: string, - orderingUrl: string, identityUrl: string, - basketUrl: string, marketingUrl: string, + purchaseUrl: string, activateCampaignDetailFunction: boolean } \ No newline at end of file diff --git a/src/Web/WebSPA/Client/modules/shared/services/configuration.service.ts b/src/Web/WebSPA/Client/modules/shared/services/configuration.service.ts index d41786859..ea95275e0 100644 --- a/src/Web/WebSPA/Client/modules/shared/services/configuration.service.ts +++ b/src/Web/WebSPA/Client/modules/shared/services/configuration.service.ts @@ -28,11 +28,9 @@ export class ConfigurationService { console.log('server settings loaded'); this.serverSettings = response.json(); console.log(this.serverSettings); - this.storageService.store('basketUrl', this.serverSettings.basketUrl); - this.storageService.store('catalogUrl', this.serverSettings.catalogUrl); this.storageService.store('identityUrl', this.serverSettings.identityUrl); - this.storageService.store('orderingUrl', this.serverSettings.orderingUrl); this.storageService.store('marketingUrl', this.serverSettings.marketingUrl); + this.storageService.store('purchaseUrl', this.serverSettings.purchaseUrl); this.storageService.store('activateCampaignDetailFunction', this.serverSettings.activateCampaignDetailFunction); this.isReady = true; this.settingsLoadedSource.next(); diff --git a/src/Web/WebSPA/Client/modules/shared/services/security.service.ts b/src/Web/WebSPA/Client/modules/shared/services/security.service.ts index 483ea4ae4..45007b5d1 100644 --- a/src/Web/WebSPA/Client/modules/shared/services/security.service.ts +++ b/src/Web/WebSPA/Client/modules/shared/services/security.service.ts @@ -82,7 +82,7 @@ export class SecurityService { let client_id = 'js'; let redirect_uri = location.origin + '/'; let response_type = 'id_token token'; - let scope = 'openid profile orders basket marketing locations'; + let scope = 'openid profile orders basket marketing locations webshoppingagg'; let nonce = 'N' + Math.random() + '' + Date.now(); let state = Date.now() + '' + Math.random(); diff --git a/src/Web/WebSPA/Properties/launchSettings.json b/src/Web/WebSPA/Properties/launchSettings.json index fd33f59ec..eff752f63 100644 --- a/src/Web/WebSPA/Properties/launchSettings.json +++ b/src/Web/WebSPA/Properties/launchSettings.json @@ -3,7 +3,7 @@ "windowsAuthentication": false, "anonymousAuthentication": true, "iisExpress": { - "applicationUrl": "http://localhost:5104/", + "applicationUrl": "http://localhost:58018/", "sslPort": 0 } }, diff --git a/src/Web/WebSPA/appsettings.json b/src/Web/WebSPA/appsettings.json index 7b1930f84..75f17ac35 100644 --- a/src/Web/WebSPA/appsettings.json +++ b/src/Web/WebSPA/appsettings.json @@ -1,10 +1,8 @@ { - "CatalogUrl": "http://localhost:5101", - "OrderingUrl": "http://localhost:5102", - "BasketUrl": "http://localhost:5103", "IdentityUrl": "http://localhost:5105", "MarketingUrl": "http://localhost:5110", "CallBackUrl": "http://localhost:5104/", + "PurchaseUrl": "http://localhost:5200", "UseCustomizationData": true, "IsClusterEnv": "False", "ActivateCampaignDetailFunction": true, diff --git a/src/Web/WebSPA/package-lock.json b/src/Web/WebSPA/package-lock.json index 313a88257..550b77da7 100644 --- a/src/Web/WebSPA/package-lock.json +++ b/src/Web/WebSPA/package-lock.json @@ -1176,6 +1176,7 @@ "requires": { "anymatch": "1.3.2", "async-each": "1.0.1", + "fsevents": "1.1.3", "glob-parent": "2.0.0", "inherits": "2.0.3", "is-binary-path": "1.0.1", @@ -2806,6 +2807,910 @@ "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", "dev": true }, + "fsevents": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.1.3.tgz", + "integrity": "sha512-WIr7iDkdmdbxu/Gh6eKEZJL6KPE74/5MEsf2whTOFNxbIoIixogroLdKYqB6FDav4Wavh/lZdzzd3b2KxIXC5Q==", + "dev": true, + "optional": true, + "requires": { + "nan": "2.6.2", + "node-pre-gyp": "0.6.39" + }, + "dependencies": { + "abbrev": { + "version": "1.1.0", + "bundled": true, + "dev": true, + "optional": true + }, + "ajv": { + "version": "4.11.8", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "co": "4.6.0", + "json-stable-stringify": "1.0.1" + } + }, + "ansi-regex": { + "version": "2.1.1", + "bundled": true, + "dev": true + }, + "aproba": { + "version": "1.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "are-we-there-yet": { + "version": "1.1.4", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "delegates": "1.0.0", + "readable-stream": "2.2.9" + } + }, + "asn1": { + "version": "0.2.3", + "bundled": true, + "dev": true, + "optional": true + }, + "assert-plus": { + "version": "0.2.0", + "bundled": true, + "dev": true, + "optional": true + }, + "asynckit": { + "version": "0.4.0", + "bundled": true, + "dev": true, + "optional": true + }, + "aws-sign2": { + "version": "0.6.0", + "bundled": true, + "dev": true, + "optional": true + }, + "aws4": { + "version": "1.6.0", + "bundled": true, + "dev": true, + "optional": true + }, + "balanced-match": { + "version": "0.4.2", + "bundled": true, + "dev": true + }, + "bcrypt-pbkdf": { + "version": "1.0.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "tweetnacl": "0.14.5" + } + }, + "block-stream": { + "version": "0.0.9", + "bundled": true, + "dev": true, + "requires": { + "inherits": "2.0.3" + } + }, + "boom": { + "version": "2.10.1", + "bundled": true, + "dev": true, + "requires": { + "hoek": "2.16.3" + } + }, + "brace-expansion": { + "version": "1.1.7", + "bundled": true, + "dev": true, + "requires": { + "balanced-match": "0.4.2", + "concat-map": "0.0.1" + } + }, + "buffer-shims": { + "version": "1.0.0", + "bundled": true, + "dev": true + }, + "caseless": { + "version": "0.12.0", + "bundled": true, + "dev": true, + "optional": true + }, + "co": { + "version": "4.6.0", + "bundled": true, + "dev": true, + "optional": true + }, + "code-point-at": { + "version": "1.1.0", + "bundled": true, + "dev": true + }, + "combined-stream": { + "version": "1.0.5", + "bundled": true, + "dev": true, + "requires": { + "delayed-stream": "1.0.0" + } + }, + "concat-map": { + "version": "0.0.1", + "bundled": true, + "dev": true + }, + "console-control-strings": { + "version": "1.1.0", + "bundled": true, + "dev": true + }, + "core-util-is": { + "version": "1.0.2", + "bundled": true, + "dev": true + }, + "cryptiles": { + "version": "2.0.5", + "bundled": true, + "dev": true, + "requires": { + "boom": "2.10.1" + } + }, + "dashdash": { + "version": "1.14.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "assert-plus": "1.0.0" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + } + } + }, + "debug": { + "version": "2.6.8", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "ms": "2.0.0" + } + }, + "deep-extend": { + "version": "0.4.2", + "bundled": true, + "dev": true, + "optional": true + }, + "delayed-stream": { + "version": "1.0.0", + "bundled": true, + "dev": true + }, + "delegates": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "detect-libc": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "ecc-jsbn": { + "version": "0.1.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "jsbn": "0.1.1" + } + }, + "extend": { + "version": "3.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "extsprintf": { + "version": "1.0.2", + "bundled": true, + "dev": true + }, + "forever-agent": { + "version": "0.6.1", + "bundled": true, + "dev": true, + "optional": true + }, + "form-data": { + "version": "2.1.4", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "asynckit": "0.4.0", + "combined-stream": "1.0.5", + "mime-types": "2.1.15" + } + }, + "fs.realpath": { + "version": "1.0.0", + "bundled": true, + "dev": true + }, + "fstream": { + "version": "1.0.11", + "bundled": true, + "dev": true, + "requires": { + "graceful-fs": "4.1.11", + "inherits": "2.0.3", + "mkdirp": "0.5.1", + "rimraf": "2.6.1" + } + }, + "fstream-ignore": { + "version": "1.0.5", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "fstream": "1.0.11", + "inherits": "2.0.3", + "minimatch": "3.0.4" + } + }, + "gauge": { + "version": "2.7.4", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "aproba": "1.1.1", + "console-control-strings": "1.1.0", + "has-unicode": "2.0.1", + "object-assign": "4.1.1", + "signal-exit": "3.0.2", + "string-width": "1.0.2", + "strip-ansi": "3.0.1", + "wide-align": "1.1.2" + } + }, + "getpass": { + "version": "0.1.7", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "assert-plus": "1.0.0" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + } + } + }, + "glob": { + "version": "7.1.2", + "bundled": true, + "dev": true, + "requires": { + "fs.realpath": "1.0.0", + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" + } + }, + "graceful-fs": { + "version": "4.1.11", + "bundled": true, + "dev": true + }, + "har-schema": { + "version": "1.0.5", + "bundled": true, + "dev": true, + "optional": true + }, + "har-validator": { + "version": "4.2.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "ajv": "4.11.8", + "har-schema": "1.0.5" + } + }, + "has-unicode": { + "version": "2.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "hawk": { + "version": "3.1.3", + "bundled": true, + "dev": true, + "requires": { + "boom": "2.10.1", + "cryptiles": "2.0.5", + "hoek": "2.16.3", + "sntp": "1.0.9" + } + }, + "hoek": { + "version": "2.16.3", + "bundled": true, + "dev": true + }, + "http-signature": { + "version": "1.1.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "assert-plus": "0.2.0", + "jsprim": "1.4.0", + "sshpk": "1.13.0" + } + }, + "inflight": { + "version": "1.0.6", + "bundled": true, + "dev": true, + "requires": { + "once": "1.4.0", + "wrappy": "1.0.2" + } + }, + "inherits": { + "version": "2.0.3", + "bundled": true, + "dev": true + }, + "ini": { + "version": "1.3.4", + "bundled": true, + "dev": true, + "optional": true + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "requires": { + "number-is-nan": "1.0.1" + } + }, + "is-typedarray": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "isarray": { + "version": "1.0.0", + "bundled": true, + "dev": true + }, + "isstream": { + "version": "0.1.2", + "bundled": true, + "dev": true, + "optional": true + }, + "jodid25519": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "jsbn": "0.1.1" + } + }, + "jsbn": { + "version": "0.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "json-schema": { + "version": "0.2.3", + "bundled": true, + "dev": true, + "optional": true + }, + "json-stable-stringify": { + "version": "1.0.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "jsonify": "0.0.0" + } + }, + "json-stringify-safe": { + "version": "5.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "jsonify": { + "version": "0.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "jsprim": { + "version": "1.4.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "assert-plus": "1.0.0", + "extsprintf": "1.0.2", + "json-schema": "0.2.3", + "verror": "1.3.6" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + } + } + }, + "mime-db": { + "version": "1.27.0", + "bundled": true, + "dev": true + }, + "mime-types": { + "version": "2.1.15", + "bundled": true, + "dev": true, + "requires": { + "mime-db": "1.27.0" + } + }, + "minimatch": { + "version": "3.0.4", + "bundled": true, + "dev": true, + "requires": { + "brace-expansion": "1.1.7" + } + }, + "minimist": { + "version": "0.0.8", + "bundled": true, + "dev": true + }, + "mkdirp": { + "version": "0.5.1", + "bundled": true, + "dev": true, + "requires": { + "minimist": "0.0.8" + } + }, + "ms": { + "version": "2.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "node-pre-gyp": { + "version": "0.6.39", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "detect-libc": "1.0.2", + "hawk": "3.1.3", + "mkdirp": "0.5.1", + "nopt": "4.0.1", + "npmlog": "4.1.0", + "rc": "1.2.1", + "request": "2.81.0", + "rimraf": "2.6.1", + "semver": "5.3.0", + "tar": "2.2.1", + "tar-pack": "3.4.0" + } + }, + "nopt": { + "version": "4.0.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "abbrev": "1.1.0", + "osenv": "0.1.4" + } + }, + "npmlog": { + "version": "4.1.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "are-we-there-yet": "1.1.4", + "console-control-strings": "1.1.0", + "gauge": "2.7.4", + "set-blocking": "2.0.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "bundled": true, + "dev": true + }, + "oauth-sign": { + "version": "0.8.2", + "bundled": true, + "dev": true, + "optional": true + }, + "object-assign": { + "version": "4.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "once": { + "version": "1.4.0", + "bundled": true, + "dev": true, + "requires": { + "wrappy": "1.0.2" + } + }, + "os-homedir": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "os-tmpdir": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "osenv": { + "version": "0.1.4", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "os-homedir": "1.0.2", + "os-tmpdir": "1.0.2" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "bundled": true, + "dev": true + }, + "performance-now": { + "version": "0.2.0", + "bundled": true, + "dev": true, + "optional": true + }, + "process-nextick-args": { + "version": "1.0.7", + "bundled": true, + "dev": true + }, + "punycode": { + "version": "1.4.1", + "bundled": true, + "dev": true, + "optional": true + }, + "qs": { + "version": "6.4.0", + "bundled": true, + "dev": true, + "optional": true + }, + "rc": { + "version": "1.2.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "deep-extend": "0.4.2", + "ini": "1.3.4", + "minimist": "1.2.0", + "strip-json-comments": "2.0.1" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "bundled": true, + "dev": true, + "optional": true + } + } + }, + "readable-stream": { + "version": "2.2.9", + "bundled": true, + "dev": true, + "requires": { + "buffer-shims": "1.0.0", + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "1.0.7", + "string_decoder": "1.0.1", + "util-deprecate": "1.0.2" + } + }, + "request": { + "version": "2.81.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "aws-sign2": "0.6.0", + "aws4": "1.6.0", + "caseless": "0.12.0", + "combined-stream": "1.0.5", + "extend": "3.0.1", + "forever-agent": "0.6.1", + "form-data": "2.1.4", + "har-validator": "4.2.1", + "hawk": "3.1.3", + "http-signature": "1.1.1", + "is-typedarray": "1.0.0", + "isstream": "0.1.2", + "json-stringify-safe": "5.0.1", + "mime-types": "2.1.15", + "oauth-sign": "0.8.2", + "performance-now": "0.2.0", + "qs": "6.4.0", + "safe-buffer": "5.0.1", + "stringstream": "0.0.5", + "tough-cookie": "2.3.2", + "tunnel-agent": "0.6.0", + "uuid": "3.0.1" + } + }, + "rimraf": { + "version": "2.6.1", + "bundled": true, + "dev": true, + "requires": { + "glob": "7.1.2" + } + }, + "safe-buffer": { + "version": "5.0.1", + "bundled": true, + "dev": true + }, + "semver": { + "version": "5.3.0", + "bundled": true, + "dev": true, + "optional": true + }, + "set-blocking": { + "version": "2.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "signal-exit": { + "version": "3.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "sntp": { + "version": "1.0.9", + "bundled": true, + "dev": true, + "requires": { + "hoek": "2.16.3" + } + }, + "sshpk": { + "version": "1.13.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "asn1": "0.2.3", + "assert-plus": "1.0.0", + "bcrypt-pbkdf": "1.0.1", + "dashdash": "1.14.1", + "ecc-jsbn": "0.1.1", + "getpass": "0.1.7", + "jodid25519": "1.0.2", + "jsbn": "0.1.1", + "tweetnacl": "0.14.5" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + } + } + }, + "string-width": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "requires": { + "code-point-at": "1.1.0", + "is-fullwidth-code-point": "1.0.0", + "strip-ansi": "3.0.1" + } + }, + "string_decoder": { + "version": "1.0.1", + "bundled": true, + "dev": true, + "requires": { + "safe-buffer": "5.0.1" + } + }, + "stringstream": { + "version": "0.0.5", + "bundled": true, + "dev": true, + "optional": true + }, + "strip-ansi": { + "version": "3.0.1", + "bundled": true, + "dev": true, + "requires": { + "ansi-regex": "2.1.1" + } + }, + "strip-json-comments": { + "version": "2.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "tar": { + "version": "2.2.1", + "bundled": true, + "dev": true, + "requires": { + "block-stream": "0.0.9", + "fstream": "1.0.11", + "inherits": "2.0.3" + } + }, + "tar-pack": { + "version": "3.4.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "debug": "2.6.8", + "fstream": "1.0.11", + "fstream-ignore": "1.0.5", + "once": "1.4.0", + "readable-stream": "2.2.9", + "rimraf": "2.6.1", + "tar": "2.2.1", + "uid-number": "0.0.6" + } + }, + "tough-cookie": { + "version": "2.3.2", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "punycode": "1.4.1" + } + }, + "tunnel-agent": { + "version": "0.6.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "safe-buffer": "5.0.1" + } + }, + "tweetnacl": { + "version": "0.14.5", + "bundled": true, + "dev": true, + "optional": true + }, + "uid-number": { + "version": "0.0.6", + "bundled": true, + "dev": true, + "optional": true + }, + "util-deprecate": { + "version": "1.0.2", + "bundled": true, + "dev": true + }, + "uuid": { + "version": "3.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "verror": { + "version": "1.3.6", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "extsprintf": "1.0.2" + } + }, + "wide-align": { + "version": "1.1.2", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "string-width": "1.0.2" + } + }, + "wrappy": { + "version": "1.0.2", + "bundled": true, + "dev": true + } + } + }, "fstream": { "version": "1.0.11", "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.11.tgz", diff --git a/test/Services/UnitTest/Basket/Application/CartControllerTest.cs b/test/Services/UnitTest/Basket/Application/CartControllerTest.cs index 6bdd2c43c..63f74cf35 100644 --- a/test/Services/UnitTest/Basket/Application/CartControllerTest.cs +++ b/test/Services/UnitTest/Basket/Application/CartControllerTest.cs @@ -92,7 +92,7 @@ namespace UnitTest.Basket.Application //Arrange var fakeCatalogItem = GetFakeCatalogItem(); - _basketServiceMock.Setup(x => x.AddItemToBasket(It.IsAny(), It.IsAny())) + _basketServiceMock.Setup(x => x.AddItemToBasket(It.IsAny(), It.IsAny())) .Returns(Task.FromResult(1)); //Act @@ -118,7 +118,7 @@ namespace UnitTest.Basket.Application { return new CatalogItem() { - Id = "1", + Id = 1, Name = "fakeName", CatalogBrand = "fakeBrand", CatalogType = "fakeType", diff --git a/test/Services/UnitTest/Catalog/Application/CatalogControllerTest.cs b/test/Services/UnitTest/Catalog/Application/CatalogControllerTest.cs index 58d32c212..7410551e4 100644 --- a/test/Services/UnitTest/Catalog/Application/CatalogControllerTest.cs +++ b/test/Services/UnitTest/Catalog/Application/CatalogControllerTest.cs @@ -67,19 +67,19 @@ namespace UnitTest.Catalog.Application { new CatalogItem() { - Id = "1", + Id = 1, Name = "fakeItemA", CatalogTypeId = 1 }, new CatalogItem() { - Id = "2", + Id = 2, Name = "fakeItemB", CatalogTypeId = 1 }, new CatalogItem() { - Id = "3", + Id = 3, Name = "fakeItemC", CatalogTypeId = 1 } diff --git a/test/Services/UnitTest/Ordering/Application/OrderControllerTest.cs b/test/Services/UnitTest/Ordering/Application/OrderControllerTest.cs index 12f2be395..a60ce3bb3 100644 --- a/test/Services/UnitTest/Ordering/Application/OrderControllerTest.cs +++ b/test/Services/UnitTest/Ordering/Application/OrderControllerTest.cs @@ -68,40 +68,7 @@ namespace UnitTest.Ordering.Application Assert.IsAssignableFrom(viewResult.ViewData.Model); } - [Fact] - public async Task Get_create_order_success() - { - //Arrange - var fakeBuyerId = "1"; - var fakeBasket = GetFakeBasket(fakeBuyerId); - var fakeOrder = GetFakeOrder(); - - _basketServiceMock.Setup(x => x.GetBasket(It.IsAny())) - .Returns(Task.FromResult(fakeBasket)); - - _basketServiceMock.Setup(x => x.MapBasketToOrder(It.IsAny())) - .Returns(fakeOrder); - - _orderServiceMock.Setup(x => x.MapUserInfoIntoOrder(It.IsAny(), It.IsAny())) - .Returns(fakeOrder); - - //Act - var orderController = new OrderController(_orderServiceMock.Object, _basketServiceMock.Object, _identityParserMock.Object); - orderController.ControllerContext.HttpContext = _contextMock.Object; - var actionResult = await orderController.Create(); - - //Assert - var viewResult = Assert.IsType(actionResult); - Assert.IsAssignableFrom(viewResult.ViewData.Model); - } - - private BasketModel GetFakeBasket(string buyerId) - { - return new BasketModel() - { - BuyerId = buyerId - }; - } + private Order GetFakeOrder() { diff --git a/xglobal.json b/xglobal.json new file mode 100644 index 000000000..2ab18dceb --- /dev/null +++ b/xglobal.json @@ -0,0 +1,5 @@ +{ + "sdk": { + "version":"2.1.2" + } +} \ No newline at end of file