diff --git a/.env b/.env index d9482516b..e2358c823 100644 --- a/.env +++ b/.env @@ -5,4 +5,20 @@ # The IP below should be swapped to your real IP or DNS name, like 192.168.88.248, etc. if testing from remote browsers or mobile devices ESHOP_EXTERNAL_DNS_NAME_OR_IP=localhost -ESHOP_PROD_EXTERNAL_DNS_NAME_OR_IP=10.121.122.92 \ No newline at end of file +ESHOP_PROD_EXTERNAL_DNS_NAME_OR_IP=10.121.122.92 + +#ESHOP_AZURE_REDIS_BASKET_DB= +#ESHOP_AZURE_STORAGE_CATALOG= +#ESHOP_AZURE_STORAGE_MARKETING= +#ESHOP_AZURE_SERVICE_BUS= +#ESHOP_AZURE_COSMOSDB= +#ESHOP_AZURE_CATALOG_DB= +#ESHOP_AZURE_IDENTITY_DB= +#ESHOP_AZURE_ORDERING_DB= +#ESHOP_AZURE_MARKETING_DB= +#ESHOP_AZUREFUNC_CAMPAIGN_DETAILS_URI= +#ESHOP_AZURE_STORAGE_CATALOG_NAME= +#ESHOP_AZURE_STORAGE_CATALOG_KEY= +#ESHOP_AZURE_STORAGE_MARKETING_NAME= +#ESHOP_AZURE_STORAGE_MARKETING_KEY= + diff --git a/docker-compose.dcproj b/docker-compose.dcproj index f7f04c5b4..23547b577 100644 --- a/docker-compose.dcproj +++ b/docker-compose.dcproj @@ -5,6 +5,8 @@ True http://localhost:5100 webmvc + Linux + 2.0 @@ -14,12 +16,6 @@ docker-compose.yml - - docker-compose.yml - - - docker-compose.yml - \ No newline at end of file diff --git a/docker-compose.override.yml b/docker-compose.override.yml index ccfec8b3b..11cf0ff68 100644 --- a/docker-compose.override.yml +++ b/docker-compose.override.yml @@ -9,15 +9,17 @@ version: '2.1' services: graceperiodmanager: environment: + - ASPNETCORE_ENVIRONMENT=Development + - ASPNETCORE_URLS=http://0.0.0.0:80 - ConnectionString=Server=sql.data;Database=Microsoft.eShopOnContainers.Services.OrderingDb;User Id=sa;Password=Pass@word - - EventBusConnection=rabbitmq + - EventBusConnection=${ESHOP_AZURE_SERVICE_BUS:-rabbitmq} basket.api: environment: - ASPNETCORE_ENVIRONMENT=Development - ASPNETCORE_URLS=http://0.0.0.0:80 - - ConnectionString=${ESHOP_AZURE_REDIS:-basket.data} - - identityUrl=http://identity.api #Local: You need to open your local dev-machine firewall at range 5100-5105. at range 5100-5105. + - ConnectionString=${ESHOP_AZURE_REDIS_BASKET_DB:-basket.data} + - identityUrl=http://identity.api #Local: You need to open your local dev-machine firewall at range 5100-5110. - EventBusConnection=${ESHOP_AZURE_SERVICE_BUS:-rabbitmq} ports: - "5103:80" @@ -26,8 +28,8 @@ services: environment: - ASPNETCORE_ENVIRONMENT=Development - ASPNETCORE_URLS=http://0.0.0.0:80 - - ConnectionString=Server=sql.data;Database=Microsoft.eShopOnContainers.Services.CatalogDb;User Id=sa;Password=Pass@word - - PicBaseUrl=${ESHOP_AZURE_STORAGE_ACCOUNT:-http://localhost:5101/api/v1/pic/} #Local: You need to open your local dev-machine firewall at range 5100-5105. at range 5100-5105. + - ConnectionString=${ESHOP_AZURE_CATALOG_DB:-Server=sql.data;Database=Microsoft.eShopOnContainers.Services.CatalogDb;User Id=sa;Password=Pass@word} + - PicBaseUrl=${ESHOP_AZURE_STORAGE_CATALOG:-http://localhost:5101/api/v1/pic/} #Local: You need to open your local dev-machine firewall at range 5100-5110. - EventBusConnection=${ESHOP_AZURE_SERVICE_BUS:-rabbitmq} - AzureStorageAccountName=${ESHOP_AZURE_STORAGE_ACCOUNT_NAME} - AzureStorageAccountKey=${ESHOP_AZURE_STORAGE_ACCOUNT_KEY} @@ -41,8 +43,8 @@ services: - ASPNETCORE_URLS=http://0.0.0.0:80 - SpaClient=http://${ESHOP_EXTERNAL_DNS_NAME_OR_IP}:5104 - XamarinCallback=http://${ESHOP_PROD_EXTERNAL_DNS_NAME_OR_IP}:5105/xamarincallback #localhost do not work for UWP login, so we have to use "external" IP always - - ConnectionStrings__DefaultConnection=Server=sql.data;Database=Microsoft.eShopOnContainers.Service.IdentityDb;User Id=sa;Password=Pass@word - - MvcClient=http://${ESHOP_EXTERNAL_DNS_NAME_OR_IP}:5100 #Local: You need to open your local dev-machine firewall at range 5100-5105. + - ConnectionStrings__DefaultConnection=${ESHOP_AZURE_IDENTITY_DB:-Server=sql.data;Database=Microsoft.eShopOnContainers.Service.IdentityDb;User Id=sa;Password=Pass@word} + - MvcClient=http://${ESHOP_EXTERNAL_DNS_NAME_OR_IP}:5100 #Local: You need to open your local dev-machine firewall at range 5100-5110. - UseCustomizationData=True ports: - "5105:80" @@ -51,8 +53,8 @@ services: environment: - ASPNETCORE_ENVIRONMENT=Development - ASPNETCORE_URLS=http://0.0.0.0:80 - - ConnectionString=Server=sql.data;Database=Microsoft.eShopOnContainers.Services.OrderingDb;User Id=sa;Password=Pass@word - - identityUrl=http://identity.api #Local: You need to open your local dev-machine firewall at range 5100-5105. at range 5100-5105. + - ConnectionString=${ESHOP_AZURE_ORDERING_DB:-Server=sql.data;Database=Microsoft.eShopOnContainers.Services.OrderingDb;User Id=sa;Password=Pass@word} + - identityUrl=http://identity.api #Local: You need to open your local dev-machine firewall at range 5100-5110. - EventBusConnection=${ESHOP_AZURE_SERVICE_BUS:-rabbitmq} - UseCustomizationData=True ports: @@ -62,15 +64,18 @@ services: environment: - ASPNETCORE_ENVIRONMENT=Development - ASPNETCORE_URLS=http://0.0.0.0:80 - - ConnectionString=Server=sql.data;Database=Microsoft.eShopOnContainers.Services.MarketingDb;User Id=sa;Password=Pass@word - - MongoConnectionString=mongodb://nosql.data + - ConnectionString=${ESHOP_AZURE_MARKETING_DB:-Server=sql.data;Database=Microsoft.eShopOnContainers.Services.MarketingDb;User Id=sa;Password=Pass@word} + - MongoConnectionString=${ESHOP_AZURE_COSMOSDB:-mongodb://nosql.data} - MongoDatabase=MarketingDb - - EventBusConnection=rabbitmq - - ExternalCatalogBaseUrl=http://${ESHOP_EXTERNAL_DNS_NAME_OR_IP}:5110 #Local: You need to open your local dev-machine firewall at range 5100-5105. at range 5100-5105. - - identityUrl=http://identity.api #Local: You need to open your local dev-machine firewall at range 5100-5105. at range 5100-5105. + - EventBusConnection=${ESHOP_AZURE_SERVICE_BUS:-rabbitmq} + - identityUrl=http://identity.api #Local: You need to open your local dev-machine firewall at range 5100-5110. + - CampaignDetailFunctionUri=${ESHOP_AZUREFUNC_CAMPAIGN_DETAILS_URI} + - PicBaseUrl=${ESHOP_AZURE_STORAGE_MARKETING:-http://localhost:5110/api/v1/pic/} + - AzureStorageAccountName=${ESHOP_AZURE_STORAGE_MARKETING_NAME} + - AzureStorageAccountKey=${ESHOP_AZURE_STORAGE_MARKETING_KEY} ports: - "5110:80" - + webspa: environment: - ASPNETCORE_ENVIRONMENT=Development @@ -133,7 +138,7 @@ services: environment: - ASPNETCORE_ENVIRONMENT=Development - ASPNETCORE_URLS=http://0.0.0.0:5108 - - EventBusConnection=rabbitmq + - EventBusConnection=${ESHOP_AZURE_SERVICE_BUS:-rabbitmq} ports: - "5108:80" @@ -141,9 +146,9 @@ services: environment: - ASPNETCORE_ENVIRONMENT=Development - ASPNETCORE_URLS=http://0.0.0.0:80 - - ConnectionString=mongodb://nosql.data + - ConnectionString=${ESHOP_AZURE_COSMOSDB:-mongodb://nosql.data} - Database=LocationsDb - - identityUrl=http://identity.api #Local: You need to open your local dev-machine firewall at range 5100-5105. at range 5100-5105. - - EventBusConnection=rabbitmq + - identityUrl=http://identity.api #Local: You need to open your local dev-machine firewall at range 5100-5110. + - EventBusConnection=${ESHOP_AZURE_SERVICE_BUS:-rabbitmq} ports: - "5109:80" diff --git a/docker-compose.prod.yml b/docker-compose.prod.yml index 1fac4f5e6..974dee651 100644 --- a/docker-compose.prod.yml +++ b/docker-compose.prod.yml @@ -12,13 +12,19 @@ version: '2.1' # docker-compose -f docker-compose.yml -f docker-compose.prod.yml up -d services: + graceperiodmanager: + environment: + - ASPNETCORE_ENVIRONMENT=Production + - ASPNETCORE_URLS=http://0.0.0.0:80 + - ConnectionString=Server=sql.data;Database=Microsoft.eShopOnContainers.Services.OrderingDb;User Id=sa;Password=Pass@word + - EventBusConnection=${ESHOP_AZURE_SERVICE_BUS:-rabbitmq} basket.api: environment: - ASPNETCORE_ENVIRONMENT=Production - ASPNETCORE_URLS=http://0.0.0.0:80 - - ConnectionString=${ESHOP_AZURE_REDIS:-basket.data} - - identityUrl=http://identity.api #Local: You need to open your host's firewall at range 5100-5105. at range 5100-5105. + - ConnectionString=${ESHOP_AZURE_REDIS_BASKET_DB:-basket.data} + - identityUrl=http://identity.api #Local: You need to open your local dev-machine firewall at range 5100-5110. - EventBusConnection=${ESHOP_AZURE_SERVICE_BUS:-rabbitmq} ports: - "5103:80" @@ -26,10 +32,13 @@ services: catalog.api: environment: - ASPNETCORE_ENVIRONMENT=Production - - ASPNETCORE_URLS=http://0.0.0.0:80 - - ConnectionString=Server=sql.data;Database=Microsoft.eShopOnContainers.Services.CatalogDb;User Id=sa;Password=Pass@word - - ExternalCatalogBaseUrl=http://${ESHOP_PROD_EXTERNAL_DNS_NAME_OR_IP}:5101 #Local: You need to open your host's firewall at range 5100-5105. at range 5100-5105. + ASPNETCORE_URLS=http://0.0.0.0:80 + - ConnectionString=${ESHOP_AZURE_CATALOG_DB:-Server=sql.data;Database=Microsoft.eShopOnContainers.Services.CatalogDb;User Id=sa;Password=Pass@word} + - PicBaseUrl=${ESHOP_AZURE_STORAGE_CATALOG:-http://localhost:5101/api/v1/pic/} #Local: You need to open your local dev-machine firewall at range 5100-5110. - EventBusConnection=${ESHOP_AZURE_SERVICE_BUS:-rabbitmq} + - AzureStorageAccountName=${ESHOP_AZURE_STORAGE_ACCOUNT_NAME} + - AzureStorageAccountKey=${ESHOP_AZURE_STORAGE_ACCOUNT_KEY} + - UseCustomizationData=True ports: - "5101:80" @@ -38,9 +47,10 @@ services: - ASPNETCORE_ENVIRONMENT=Production - ASPNETCORE_URLS=http://0.0.0.0:80 - SpaClient=http://${ESHOP_PROD_EXTERNAL_DNS_NAME_OR_IP}:5104 - - ConnectionStrings__DefaultConnection=Server=sql.data;Database=Microsoft.eShopOnContainers.Service.IdentityDb;User Id=sa;Password=Pass@word - - MvcClient=http://${ESHOP_PROD_EXTERNAL_DNS_NAME_OR_IP}:5100 #Local: You need to open your host's firewall at range 5100-5105. + - ConnectionStrings__DefaultConnection=${ESHOP_AZURE_IDENTITY_DB:-Server=sql.data;Database=Microsoft.eShopOnContainers.Service.IdentityDb;User Id=sa;Password=Pass@word} + - MvcClient=http://${ESHOP_PROD_EXTERNAL_DNS_NAME_OR_IP}:5100 #Local: You need to open your host's firewall at range 5100-5110. - XamarinCallback=http://${ESHOP_PROD_EXTERNAL_DNS_NAME_OR_IP}:5105/xamarincallback + - UseCustomizationData=True ports: - "5105:80" @@ -48,9 +58,10 @@ services: environment: - ASPNETCORE_ENVIRONMENT=Production - ASPNETCORE_URLS=http://0.0.0.0:80 - - ConnectionString=Server=sql.data;Database=Microsoft.eShopOnContainers.Services.OrderingDb;User Id=sa;Password=Pass@word - - identityUrl=http://identity.api #Local: You need to open your host's firewall at range 5100-5105. at range 5100-5105. + - ConnectionString=${ESHOP_AZURE_ORDERING_DB:-Server=sql.data;Database=Microsoft.eShopOnContainers.Services.OrderingDb;User Id=sa;Password=Pass@word} + - identityUrl=http://identity.api #Local: You need to open your local dev-machine firewall at range 5100-5110. - EventBusConnection=${ESHOP_AZURE_SERVICE_BUS:-rabbitmq} + - UseCustomizationData=True ports: - "5102:80" @@ -58,11 +69,15 @@ services: environment: - ASPNETCORE_ENVIRONMENT=Production - ASPNETCORE_URLS=http://0.0.0.0:80 - - ConnectionString=Server=sql.data;Database=Microsoft.eShopOnContainers.Services.MarketingDb;User Id=sa;Password=Pass@word - - MongoConnectionString=mongodb://nosql.data + - ConnectionString=${ESHOP_AZURE_MARKETING_DB:-Server=sql.data;Database=Microsoft.eShopOnContainers.Services.MarketingDb;User Id=sa;Password=Pass@word} + - MongoConnectionString=${ESHOP_AZURE_COSMOSDB:-mongodb://nosql.data} - MongoDatabase=MarketingDb - - EventBusConnection=rabbitmq - - identityUrl=http://identity.api #Local: You need to open your local dev-machine firewall at range 5100-5105. at range 5100-5105. + - EventBusConnection=${ESHOP_AZURE_SERVICE_BUS:-rabbitmq} + - identityUrl=http://identity.api #Local: You need to open your local dev-machine firewall at range 5100-5110. + - CampaignDetailFunctionUri=${ESHOP_AZUREFUNC_CAMPAIGN_DETAILS_URI} + - PicBaseUrl=${ESHOP_AZURE_STORAGE_MARKETING:-http://localhost:5110/api/v1/pic/} + - AzureStorageAccountName=${ESHOP_AZURE_STORAGE_MARKETING_NAME} + - AzureStorageAccountKey=${ESHOP_AZURE_STORAGE_MARKETING_KEY} ports: - "5110:80" @@ -72,12 +87,14 @@ services: - ASPNETCORE_URLS=http://0.0.0.0:80 - CatalogUrl=http://${ESHOP_PROD_EXTERNAL_DNS_NAME_OR_IP}:5101 - OrderingUrl=http://${ESHOP_PROD_EXTERNAL_DNS_NAME_OR_IP}:5102 - - IdentityUrl=http://${ESHOP_PROD_EXTERNAL_DNS_NAME_OR_IP}:5105 #Local: You need to open your host's firewall at range 5100-5105. at range 5100-5105. + - IdentityUrl=http://${ESHOP_PROD_EXTERNAL_DNS_NAME_OR_IP}:5105 #Local: You need to open your host's firewall at range 5100-5110. - BasketUrl=http://${ESHOP_PROD_EXTERNAL_DNS_NAME_OR_IP}:5103 - 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. - BasketUrlHC=http://basket.api/hc + - MarketingUrlHC=http://marketing.api/hc + - UseCustomizationData=True ports: - "5104:80" @@ -89,6 +106,7 @@ services: - OrderingUrl=http://ordering.api - IdentityUrl=http://${ESHOP_PROD_EXTERNAL_DNS_NAME_OR_IP}:5105 #Local: Use ${ESHOP_PROD_EXTERNAL_DNS_NAME_OR_IP}, if using external IP or DNS name from browser. - BasketUrl=http://basket.api + - MarketingUrl=http://marketing.api ports: - "5100:80" @@ -99,6 +117,10 @@ services: ports: - "5433:1433" + nosql.data: + ports: + - "27017:27017" + webstatus: environment: - ASPNETCORE_ENVIRONMENT=Production @@ -106,9 +128,30 @@ services: - CatalogUrl=http://catalog.api/hc - OrderingUrl=http://ordering.api/hc - BasketUrl=http://basket.api/hc - - IdentityUrl=http://identity.api/hc + - IdentityUrl=http://identity.api/hc + - LocationsUrl=http://locations.api/hc + - MarketingUrl=http://marketing.api/hc - mvc=http://webmvc/hc - spa=http://webspa/hc ports: - - "5107:80" \ No newline at end of file + - "5107:80" + +payment.api: + environment: + - ASPNETCORE_ENVIRONMENT=Production + - ASPNETCORE_URLS=http://0.0.0.0:5108 + - EventBusConnection=${ESHOP_AZURE_SERVICE_BUS:-rabbitmq} + ports: + - "5108:80" + + locations.api: + environment: + - ASPNETCORE_ENVIRONMENT=Production + - ASPNETCORE_URLS=http://0.0.0.0:80 + - ConnectionString=${ESHOP_AZURE_COSMOSDB:-mongodb://nosql.data} + - Database=LocationsDb + - identityUrl=http://identity.api #Local: You need to open your local dev-machine firewall at range 5100-5110. + - EventBusConnection=${ESHOP_AZURE_SERVICE_BUS:-rabbitmq} + ports: + - "5109:80" \ No newline at end of file diff --git a/eShopOnContainers-AzureFunctions.sln b/eShopOnContainers-AzureFunctions.sln new file mode 100644 index 000000000..7e14fc19d --- /dev/null +++ b/eShopOnContainers-AzureFunctions.sln @@ -0,0 +1,96 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 15 +VisualStudioVersion = 15.0.26608.5 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Infrastructure", "Infrastructure", "{5B1011EC-CEE5-47AA-B336-99381D573679}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "AzureFunctions", "AzureFunctions", "{106B787C-2CFF-4484-8C07-D14589859E94}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "marketing-functions", "src\Services\Marketing\Infrastructure\AzureFunctions\marketing-functions.csproj", "{B363EF31-DD1A-46C8-ADDF-CD30A756E97B}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Ad-Hoc|Any CPU = Ad-Hoc|Any CPU + Ad-Hoc|ARM = Ad-Hoc|ARM + Ad-Hoc|iPhone = Ad-Hoc|iPhone + Ad-Hoc|iPhoneSimulator = Ad-Hoc|iPhoneSimulator + Ad-Hoc|x64 = Ad-Hoc|x64 + Ad-Hoc|x86 = Ad-Hoc|x86 + AppStore|Any CPU = AppStore|Any CPU + AppStore|ARM = AppStore|ARM + AppStore|iPhone = AppStore|iPhone + AppStore|iPhoneSimulator = AppStore|iPhoneSimulator + AppStore|x64 = AppStore|x64 + AppStore|x86 = AppStore|x86 + Debug|Any CPU = Debug|Any CPU + Debug|ARM = Debug|ARM + Debug|iPhone = Debug|iPhone + Debug|iPhoneSimulator = Debug|iPhoneSimulator + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|Any CPU = Release|Any CPU + Release|ARM = Release|ARM + Release|iPhone = Release|iPhone + Release|iPhoneSimulator = Release|iPhoneSimulator + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {B363EF31-DD1A-46C8-ADDF-CD30A756E97B}.Ad-Hoc|Any CPU.ActiveCfg = Debug|Any CPU + {B363EF31-DD1A-46C8-ADDF-CD30A756E97B}.Ad-Hoc|Any CPU.Build.0 = Debug|Any CPU + {B363EF31-DD1A-46C8-ADDF-CD30A756E97B}.Ad-Hoc|ARM.ActiveCfg = Debug|Any CPU + {B363EF31-DD1A-46C8-ADDF-CD30A756E97B}.Ad-Hoc|ARM.Build.0 = Debug|Any CPU + {B363EF31-DD1A-46C8-ADDF-CD30A756E97B}.Ad-Hoc|iPhone.ActiveCfg = Debug|Any CPU + {B363EF31-DD1A-46C8-ADDF-CD30A756E97B}.Ad-Hoc|iPhone.Build.0 = Debug|Any CPU + {B363EF31-DD1A-46C8-ADDF-CD30A756E97B}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {B363EF31-DD1A-46C8-ADDF-CD30A756E97B}.Ad-Hoc|iPhoneSimulator.Build.0 = Debug|Any CPU + {B363EF31-DD1A-46C8-ADDF-CD30A756E97B}.Ad-Hoc|x64.ActiveCfg = Debug|Any CPU + {B363EF31-DD1A-46C8-ADDF-CD30A756E97B}.Ad-Hoc|x64.Build.0 = Debug|Any CPU + {B363EF31-DD1A-46C8-ADDF-CD30A756E97B}.Ad-Hoc|x86.ActiveCfg = Debug|Any CPU + {B363EF31-DD1A-46C8-ADDF-CD30A756E97B}.Ad-Hoc|x86.Build.0 = Debug|Any CPU + {B363EF31-DD1A-46C8-ADDF-CD30A756E97B}.AppStore|Any CPU.ActiveCfg = Debug|Any CPU + {B363EF31-DD1A-46C8-ADDF-CD30A756E97B}.AppStore|Any CPU.Build.0 = Debug|Any CPU + {B363EF31-DD1A-46C8-ADDF-CD30A756E97B}.AppStore|ARM.ActiveCfg = Debug|Any CPU + {B363EF31-DD1A-46C8-ADDF-CD30A756E97B}.AppStore|ARM.Build.0 = Debug|Any CPU + {B363EF31-DD1A-46C8-ADDF-CD30A756E97B}.AppStore|iPhone.ActiveCfg = Debug|Any CPU + {B363EF31-DD1A-46C8-ADDF-CD30A756E97B}.AppStore|iPhone.Build.0 = Debug|Any CPU + {B363EF31-DD1A-46C8-ADDF-CD30A756E97B}.AppStore|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {B363EF31-DD1A-46C8-ADDF-CD30A756E97B}.AppStore|iPhoneSimulator.Build.0 = Debug|Any CPU + {B363EF31-DD1A-46C8-ADDF-CD30A756E97B}.AppStore|x64.ActiveCfg = Debug|Any CPU + {B363EF31-DD1A-46C8-ADDF-CD30A756E97B}.AppStore|x64.Build.0 = Debug|Any CPU + {B363EF31-DD1A-46C8-ADDF-CD30A756E97B}.AppStore|x86.ActiveCfg = Debug|Any CPU + {B363EF31-DD1A-46C8-ADDF-CD30A756E97B}.AppStore|x86.Build.0 = Debug|Any CPU + {B363EF31-DD1A-46C8-ADDF-CD30A756E97B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B363EF31-DD1A-46C8-ADDF-CD30A756E97B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B363EF31-DD1A-46C8-ADDF-CD30A756E97B}.Debug|ARM.ActiveCfg = Debug|Any CPU + {B363EF31-DD1A-46C8-ADDF-CD30A756E97B}.Debug|ARM.Build.0 = Debug|Any CPU + {B363EF31-DD1A-46C8-ADDF-CD30A756E97B}.Debug|iPhone.ActiveCfg = Debug|Any CPU + {B363EF31-DD1A-46C8-ADDF-CD30A756E97B}.Debug|iPhone.Build.0 = Debug|Any CPU + {B363EF31-DD1A-46C8-ADDF-CD30A756E97B}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {B363EF31-DD1A-46C8-ADDF-CD30A756E97B}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU + {B363EF31-DD1A-46C8-ADDF-CD30A756E97B}.Debug|x64.ActiveCfg = Debug|Any CPU + {B363EF31-DD1A-46C8-ADDF-CD30A756E97B}.Debug|x64.Build.0 = Debug|Any CPU + {B363EF31-DD1A-46C8-ADDF-CD30A756E97B}.Debug|x86.ActiveCfg = Debug|Any CPU + {B363EF31-DD1A-46C8-ADDF-CD30A756E97B}.Debug|x86.Build.0 = Debug|Any CPU + {B363EF31-DD1A-46C8-ADDF-CD30A756E97B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B363EF31-DD1A-46C8-ADDF-CD30A756E97B}.Release|Any CPU.Build.0 = Release|Any CPU + {B363EF31-DD1A-46C8-ADDF-CD30A756E97B}.Release|ARM.ActiveCfg = Release|Any CPU + {B363EF31-DD1A-46C8-ADDF-CD30A756E97B}.Release|ARM.Build.0 = Release|Any CPU + {B363EF31-DD1A-46C8-ADDF-CD30A756E97B}.Release|iPhone.ActiveCfg = Release|Any CPU + {B363EF31-DD1A-46C8-ADDF-CD30A756E97B}.Release|iPhone.Build.0 = Release|Any CPU + {B363EF31-DD1A-46C8-ADDF-CD30A756E97B}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU + {B363EF31-DD1A-46C8-ADDF-CD30A756E97B}.Release|iPhoneSimulator.Build.0 = Release|Any CPU + {B363EF31-DD1A-46C8-ADDF-CD30A756E97B}.Release|x64.ActiveCfg = Release|Any CPU + {B363EF31-DD1A-46C8-ADDF-CD30A756E97B}.Release|x64.Build.0 = Release|Any CPU + {B363EF31-DD1A-46C8-ADDF-CD30A756E97B}.Release|x86.ActiveCfg = Release|Any CPU + {B363EF31-DD1A-46C8-ADDF-CD30A756E97B}.Release|x86.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {106B787C-2CFF-4484-8C07-D14589859E94} = {5B1011EC-CEE5-47AA-B336-99381D573679} + {B363EF31-DD1A-46C8-ADDF-CD30A756E97B} = {106B787C-2CFF-4484-8C07-D14589859E94} + EndGlobalSection +EndGlobal diff --git a/src/Services/Basket/Basket.API/Startup.cs b/src/Services/Basket/Basket.API/Startup.cs index 9ac2f9bd4..771ed212d 100644 --- a/src/Services/Basket/Basket.API/Startup.cs +++ b/src/Services/Basket/Basket.API/Startup.cs @@ -82,10 +82,10 @@ namespace Microsoft.eShopOnContainers.Services.Basket.API { services.AddSingleton(sp => { - var settings = sp.GetRequiredService>().Value; var logger = sp.GetRequiredService>(); - var serviceBusConnection = new ServiceBusConnectionStringBuilder(settings.EventBusConnection); + var serviceBusConnectionString = Configuration["EventBusConnection"]; + var serviceBusConnection = new ServiceBusConnectionStringBuilder(serviceBusConnectionString); return new DefaultServiceBusPersisterConnection(serviceBusConnection, logger); }); @@ -94,17 +94,19 @@ namespace Microsoft.eShopOnContainers.Services.Basket.API { services.AddSingleton(sp => { - var settings = sp.GetRequiredService>().Value; var logger = sp.GetRequiredService>(); + var factory = new ConnectionFactory() { - HostName = settings.EventBusConnection + HostName = Configuration["EventBusConnection"] }; return new DefaultRabbitMQPersistentConnection(factory, logger); }); } + RegisterEventBus(services); + services.AddSwaggerGen(options => { @@ -130,7 +132,6 @@ namespace Microsoft.eShopOnContainers.Services.Basket.API services.AddTransient(); services.AddTransient(); - RegisterEventBus(services); services.AddOptions(); var container = new ContainerBuilder(); diff --git a/src/Services/Catalog/Catalog.API/Startup.cs b/src/Services/Catalog/Catalog.API/Startup.cs index db8fd3668..e32b27e53 100644 --- a/src/Services/Catalog/Catalog.API/Startup.cs +++ b/src/Services/Catalog/Catalog.API/Startup.cs @@ -239,14 +239,14 @@ } services.AddSingleton(); - services.AddTransient, - OrderStatusChangedToAwaitingValidationIntegrationEventHandler>(); - services.AddTransient, - OrderStatusChangedToPaidIntegrationEventHandler>(); + services.AddTransient(); + services.AddTransient(); } protected virtual void ConfigureEventBus(IApplicationBuilder app) { var eventBus = app.ApplicationServices.GetRequiredService(); + eventBus.Subscribe(); + eventBus.Subscribe(); } } } diff --git a/src/Services/Catalog/Catalog.API/settings.json b/src/Services/Catalog/Catalog.API/settings.json index 8ad31e765..9c7bc4ee0 100644 --- a/src/Services/Catalog/Catalog.API/settings.json +++ b/src/Services/Catalog/Catalog.API/settings.json @@ -11,6 +11,6 @@ } }, "AzureServiceBusEnabled": false, - "AzureStorageEnabled": true, + "AzureStorageEnabled": false, "SubscriptionClientName": "Catalog" } diff --git a/src/Services/GracePeriod/GracePeriodManager/GracePeriodManager.csproj b/src/Services/GracePeriod/GracePeriodManager/GracePeriodManager.csproj index d057a6b54..0fa866642 100644 --- a/src/Services/GracePeriod/GracePeriodManager/GracePeriodManager.csproj +++ b/src/Services/GracePeriod/GracePeriodManager/GracePeriodManager.csproj @@ -22,6 +22,7 @@ + diff --git a/src/Services/GracePeriod/GracePeriodManager/Program.cs b/src/Services/GracePeriod/GracePeriodManager/Program.cs index eecdd80ea..88fb1547e 100644 --- a/src/Services/GracePeriod/GracePeriodManager/Program.cs +++ b/src/Services/GracePeriod/GracePeriodManager/Program.cs @@ -14,6 +14,8 @@ using Microsoft.Extensions.Options; using RabbitMQ.Client; using Services; + using Microsoft.eShopOnContainers.BuildingBlocks.EventBusServiceBus; + using Microsoft.Azure.ServiceBus; public class Program { @@ -58,20 +60,36 @@ services.AddLogging() .AddOptions() .Configure(Configuration) - .AddSingleton() - .AddSingleton(sp => + .AddSingleton(); + + if (Configuration.GetValue("AzureServiceBusEnabled")) + { + services.AddSingleton(sp => + { + var logger = sp.GetRequiredService>(); + + var serviceBusConnectionString = Configuration["EventBusConnection"]; + var serviceBusConnection = new ServiceBusConnectionStringBuilder(serviceBusConnectionString); + + return new DefaultServiceBusPersisterConnection(serviceBusConnection, logger); + }); + } + else + { + services.AddSingleton(sp => { - var settings = sp.GetRequiredService>().Value; var logger = sp.GetRequiredService>(); + var factory = new ConnectionFactory() { - HostName = settings.EventBusConnection + HostName = Configuration["EventBusConnection"] }; return new DefaultRabbitMQPersistentConnection(factory, logger); }); + } - RegisterEventBus(services); + RegisterEventBus(services); var container = new ContainerBuilder(); container.Populate(services); @@ -87,7 +105,25 @@ private static void RegisterEventBus(IServiceCollection services) { - services.AddSingleton(); + if (Configuration.GetValue("AzureServiceBusEnabled")) + { + services.AddSingleton(sp => + { + var serviceBusPersisterConnection = sp.GetRequiredService(); + var iLifetimeScope = sp.GetRequiredService(); + var logger = sp.GetRequiredService>(); + var eventBusSubcriptionsManager = sp.GetRequiredService(); + var subscriptionClientName = Configuration["SubscriptionClientName"]; + + return new EventBusServiceBus(serviceBusPersisterConnection, logger, + eventBusSubcriptionsManager, subscriptionClientName, iLifetimeScope); + }); + } + else + { + services.AddSingleton(); + } + services.AddSingleton(); } } diff --git a/src/Services/GracePeriod/GracePeriodManager/appsettings.json b/src/Services/GracePeriod/GracePeriodManager/appsettings.json index 273437a8e..76703a77e 100644 --- a/src/Services/GracePeriod/GracePeriodManager/appsettings.json +++ b/src/Services/GracePeriod/GracePeriodManager/appsettings.json @@ -9,5 +9,7 @@ }, "ConnectionString": "Server=tcp:127.0.0.1,5433;Database=Microsoft.eShopOnContainers.Services.OrderingDb;User Id=sa;Password=Pass@word;", "GracePeriodTime": "1", - "CheckUpdateTime": "30000" + "CheckUpdateTime": "30000", + "AzureServiceBusEnabled": false, + "SubscriptionClientName": "GracePeriod" } diff --git a/src/Services/Identity/Identity.API/Configuration/Config.cs b/src/Services/Identity/Identity.API/Configuration/Config.cs index 4aa12d4ce..035ac5177 100644 --- a/src/Services/Identity/Identity.API/Configuration/Config.cs +++ b/src/Services/Identity/Identity.API/Configuration/Config.cs @@ -114,6 +114,21 @@ namespace Identity.API.Configuration "locations", "marketing" }, + }, + new Client + { + ClientId = "swaggerui", + ClientName = "Swagger UI", + AllowedGrantTypes = GrantTypes.Implicit, + AllowAccessTokensViaBrowser = true, + + RedirectUris = { "http://localhost:5109/swagger/o2c.html" }, + PostLogoutRedirectUris = { "http://localhost:5109/swagger/" }, + + AllowedScopes = + { + "locations" + } } }; } diff --git a/src/Services/Location/Locations.API/Controllers/LocationsController.cs b/src/Services/Location/Locations.API/Controllers/LocationsController.cs index a6cb8bdad..a61c7f2d0 100644 --- a/src/Services/Location/Locations.API/Controllers/LocationsController.cs +++ b/src/Services/Location/Locations.API/Controllers/LocationsController.cs @@ -46,7 +46,7 @@ namespace Locations.API.Controllers var location = await _locationsService.GetLocation(locationId); return Ok(location); } - + //POST api/v1/[controller]/ [Route("")] [HttpPost] diff --git a/src/Services/Location/Locations.API/Infrastructure/Filters/AuthorizeCheckOperationFilter.cs b/src/Services/Location/Locations.API/Infrastructure/Filters/AuthorizeCheckOperationFilter.cs new file mode 100644 index 000000000..5a9d9e12a --- /dev/null +++ b/src/Services/Location/Locations.API/Infrastructure/Filters/AuthorizeCheckOperationFilter.cs @@ -0,0 +1,31 @@ + +using Microsoft.AspNetCore.Authorization; +using Swashbuckle.AspNetCore.Swagger; +using Swashbuckle.AspNetCore.SwaggerGen; +using System.Collections.Generic; +using System.Linq; + +namespace Microsoft.eShopOnContainers.Services.Locations.API.Infrastructure.Filters +{ + internal 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 [] { "api1" } } + }); + } + } + } +} diff --git a/src/Services/Location/Locations.API/Infrastructure/Repositories/LocationsRepository.cs b/src/Services/Location/Locations.API/Infrastructure/Repositories/LocationsRepository.cs index 47d443718..9f8d42ad4 100644 --- a/src/Services/Location/Locations.API/Infrastructure/Repositories/LocationsRepository.cs +++ b/src/Services/Location/Locations.API/Infrastructure/Repositories/LocationsRepository.cs @@ -1,6 +1,5 @@ namespace Microsoft.eShopOnContainers.Services.Locations.API.Infrastructure.Repositories { - using Microsoft.EntityFrameworkCore; using Microsoft.eShopOnContainers.Services.Locations.API.Model; using Microsoft.Extensions.Options; using MongoDB.Bson; diff --git a/src/Services/Location/Locations.API/Infrastructure/Services/IIdentityService.cs b/src/Services/Location/Locations.API/Infrastructure/Services/IIdentityService.cs index d49abe111..a2b79d8d1 100644 --- a/src/Services/Location/Locations.API/Infrastructure/Services/IIdentityService.cs +++ b/src/Services/Location/Locations.API/Infrastructure/Services/IIdentityService.cs @@ -1,9 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; - -namespace Microsoft.eShopOnContainers.Services.Locations.API.Infrastructure.Services +namespace Microsoft.eShopOnContainers.Services.Locations.API.Infrastructure.Services { public interface IIdentityService { diff --git a/src/Services/Location/Locations.API/Infrastructure/Services/IdentityService.cs b/src/Services/Location/Locations.API/Infrastructure/Services/IdentityService.cs index bcb7a84f8..d06b44a4f 100644 --- a/src/Services/Location/Locations.API/Infrastructure/Services/IdentityService.cs +++ b/src/Services/Location/Locations.API/Infrastructure/Services/IdentityService.cs @@ -1,14 +1,11 @@ using Microsoft.AspNetCore.Http; using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; namespace Microsoft.eShopOnContainers.Services.Locations.API.Infrastructure.Services { public class IdentityService : IIdentityService { - private IHttpContextAccessor _context; + private readonly IHttpContextAccessor _context; public IdentityService(IHttpContextAccessor context) { diff --git a/src/Services/Location/Locations.API/Infrastructure/Services/LocationsService.cs b/src/Services/Location/Locations.API/Infrastructure/Services/LocationsService.cs index 4b88e1927..81bc16489 100644 --- a/src/Services/Location/Locations.API/Infrastructure/Services/LocationsService.cs +++ b/src/Services/Location/Locations.API/Infrastructure/Services/LocationsService.cs @@ -1,15 +1,14 @@ namespace Microsoft.eShopOnContainers.Services.Locations.API.Infrastructure.Services { + using Microsoft.eShopOnContainers.Services.Locations.API.IntegrationEvents.Events; + using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Abstractions; + using Microsoft.eShopOnContainers.Services.Locations.API.Infrastructure.Exceptions; using Microsoft.eShopOnContainers.Services.Locations.API.Infrastructure.Repositories; - using Microsoft.eShopOnContainers.Services.Locations.API.ViewModel; using Microsoft.eShopOnContainers.Services.Locations.API.Model; + using Microsoft.eShopOnContainers.Services.Locations.API.ViewModel; using System; - using System.Threading.Tasks; - using System.Linq; - using Microsoft.eShopOnContainers.Services.Locations.API.Infrastructure.Exceptions; using System.Collections.Generic; - using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Abstractions; - using Microsoft.eShopOnContainers.Services.Locations.API.IntegrationEvents.Events; + using System.Threading.Tasks; public class LocationsService : ILocationsService { diff --git a/src/Services/Location/Locations.API/IntegrationEvents/Events/UserLocationUpdatedIntegrationEvent.cs b/src/Services/Location/Locations.API/IntegrationEvents/Events/UserLocationUpdatedIntegrationEvent.cs index d4112a54d..7c3e72769 100644 --- a/src/Services/Location/Locations.API/IntegrationEvents/Events/UserLocationUpdatedIntegrationEvent.cs +++ b/src/Services/Location/Locations.API/IntegrationEvents/Events/UserLocationUpdatedIntegrationEvent.cs @@ -1,13 +1,13 @@ namespace Microsoft.eShopOnContainers.Services.Locations.API.IntegrationEvents.Events { + using Locations.API.Model; using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events; - using Microsoft.eShopOnContainers.Services.Locations.API.Model; using System.Collections.Generic; public class UserLocationUpdatedIntegrationEvent : IntegrationEvent { - public string UserId { get; private set; } - public List LocationList { get; private set; } + public string UserId { get; set; } + public List LocationList { get; set; } public UserLocationUpdatedIntegrationEvent(string userId, List locationList) { diff --git a/src/Services/Location/Locations.API/Locations.API.csproj b/src/Services/Location/Locations.API/Locations.API.csproj index 402cc0da5..e43a12dcc 100644 --- a/src/Services/Location/Locations.API/Locations.API.csproj +++ b/src/Services/Location/Locations.API/Locations.API.csproj @@ -40,6 +40,7 @@ + diff --git a/src/Services/Location/Locations.API/Model/UserLocationDetails.cs b/src/Services/Location/Locations.API/Model/UserLocationDetails.cs index 6e152fe1b..7983e8e59 100644 --- a/src/Services/Location/Locations.API/Model/UserLocationDetails.cs +++ b/src/Services/Location/Locations.API/Model/UserLocationDetails.cs @@ -1,9 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; - -namespace Microsoft.eShopOnContainers.Services.Locations.API.Model +namespace Microsoft.eShopOnContainers.Services.Locations.API.Model { public class UserLocationDetails { @@ -11,4 +6,4 @@ namespace Microsoft.eShopOnContainers.Services.Locations.API.Model public string Code { get; set; } public string Description { get; set; } } -} +} \ No newline at end of file diff --git a/src/Services/Location/Locations.API/Startup.cs b/src/Services/Location/Locations.API/Startup.cs index 8bfaa44b4..da95f8b09 100644 --- a/src/Services/Location/Locations.API/Startup.cs +++ b/src/Services/Location/Locations.API/Startup.cs @@ -16,6 +16,10 @@ using Microsoft.Extensions.Logging; using RabbitMQ.Client; using System.Reflection; using System; +using Microsoft.eShopOnContainers.BuildingBlocks.EventBusServiceBus; +using Microsoft.Azure.ServiceBus; +using System.Collections.Generic; +using Swashbuckle.AspNetCore.Swagger; using Microsoft.Extensions.HealthChecks; using System.Threading.Tasks; @@ -53,24 +57,39 @@ namespace Microsoft.eShopOnContainers.Services.Locations.API services.Configure(Configuration); - services.AddHealthChecks(checks => + if (Configuration.GetValue("AzureServiceBusEnabled")) { - checks.AddValueTaskCheck("HTTP Endpoint", () => new ValueTask(HealthCheckResult.Healthy("Ok"))); - }); + services.AddSingleton(sp => + { + var logger = sp.GetRequiredService>(); - services.AddSingleton(sp => - { - var logger = sp.GetRequiredService>(); + var serviceBusConnectionString = Configuration["EventBusConnection"]; + var serviceBusConnection = new ServiceBusConnectionStringBuilder(serviceBusConnectionString); - var factory = new ConnectionFactory() + return new DefaultServiceBusPersisterConnection(serviceBusConnection, logger); + }); + } + else + { + services.AddSingleton(sp => { - HostName = Configuration["EventBusConnection"] - }; + var logger = sp.GetRequiredService>(); + + var factory = new ConnectionFactory + { + HostName = Configuration["EventBusConnection"] + }; + + return new DefaultRabbitMQPersistentConnection(factory, logger); + }); + } - return new DefaultRabbitMQPersistentConnection(factory, logger); + services.AddHealthChecks(checks => + { + checks.AddValueTaskCheck("HTTP Endpoint", () => new ValueTask(HealthCheckResult.Healthy("Ok"))); }); - RegisterServiceBus(services); + RegisterEventBus(services); // Add framework services. services.AddSwaggerGen(options => @@ -83,6 +102,21 @@ namespace Microsoft.eShopOnContainers.Services.Locations.API Description = "The Location Microservice HTTP API. This is a Data-Driven/CRUD microservice sample", TermsOfService = "Terms Of Service" }); + + options.AddSecurityDefinition("oauth2", new OAuth2Scheme + { + Type = "oauth2", + Flow = "implicit", + AuthorizationUrl = "http://localhost:5105/connect/authorize", + TokenUrl = "http://localhost:5105/connect/token", + Scopes = new Dictionary() + { + { "locations", "Locations API" } + } + }); + + options.OperationFilter(); + }); services.AddCors(options => @@ -124,6 +158,7 @@ namespace Microsoft.eShopOnContainers.Services.Locations.API .UseSwaggerUI(c => { c.SwaggerEndpoint("/swagger/v1/swagger.json", "My API V1"); + c.ConfigureOAuth2("swaggerui", "", "", "Swagger UI"); }); LocationsContextSeed.SeedAsync(app, loggerFactory) @@ -141,10 +176,28 @@ namespace Microsoft.eShopOnContainers.Services.Locations.API }); } - private void RegisterServiceBus(IServiceCollection services) + private void RegisterEventBus(IServiceCollection services) { - services.AddSingleton(); + if (Configuration.GetValue("AzureServiceBusEnabled")) + { + services.AddSingleton(sp => + { + var serviceBusPersisterConnection = sp.GetRequiredService(); + var iLifetimeScope = sp.GetRequiredService(); + var logger = sp.GetRequiredService>(); + var eventBusSubcriptionsManager = sp.GetRequiredService(); + var subscriptionClientName = Configuration["SubscriptionClientName"]; + + return new EventBusServiceBus(serviceBusPersisterConnection, logger, + eventBusSubcriptionsManager, subscriptionClientName, iLifetimeScope); + }); + } + else + { + services.AddSingleton(); + } + services.AddSingleton(); - } + } } } diff --git a/src/Services/Location/Locations.API/appsettings.json b/src/Services/Location/Locations.API/appsettings.json index a280150a3..511bb5c6a 100644 --- a/src/Services/Location/Locations.API/appsettings.json +++ b/src/Services/Location/Locations.API/appsettings.json @@ -9,5 +9,7 @@ "System": "Information", "Microsoft": "Information" } - } + }, + "AzureServiceBusEnabled": false, + "SubscriptionClientName": "Locations" } \ No newline at end of file diff --git a/src/Services/Marketing/Infrastructure/AzureFunctions/MarketingDetailsHttpTrigger/function.json b/src/Services/Marketing/Infrastructure/AzureFunctions/MarketingDetailsHttpTrigger/function.json new file mode 100644 index 000000000..70b31994a --- /dev/null +++ b/src/Services/Marketing/Infrastructure/AzureFunctions/MarketingDetailsHttpTrigger/function.json @@ -0,0 +1,16 @@ +{ + "bindings": [ + { + "authLevel": "function", + "name": "req", + "type": "httpTrigger", + "direction": "in" + }, + { + "name": "$return", + "type": "http", + "direction": "out" + } + ], + "disabled": false +} \ No newline at end of file diff --git a/src/Services/Marketing/Infrastructure/AzureFunctions/MarketingDetailsHttpTrigger/project.json b/src/Services/Marketing/Infrastructure/AzureFunctions/MarketingDetailsHttpTrigger/project.json new file mode 100644 index 000000000..97c3bba09 --- /dev/null +++ b/src/Services/Marketing/Infrastructure/AzureFunctions/MarketingDetailsHttpTrigger/project.json @@ -0,0 +1,21 @@ +{ + + "frameworks": { + + "net46":{ + + "dependencies": { + + "Dapper": "1.50.2", + + "System.Data.SqlClient":"4.1.0", + + "Microsoft.WindowsAzure.ConfigurationManager":"3.2.1" + + } + + } + + } + +} \ No newline at end of file diff --git a/src/Services/Marketing/Infrastructure/AzureFunctions/MarketingDetailsHttpTrigger/run.csx b/src/Services/Marketing/Infrastructure/AzureFunctions/MarketingDetailsHttpTrigger/run.csx new file mode 100644 index 000000000..9ca9b5a3b --- /dev/null +++ b/src/Services/Marketing/Infrastructure/AzureFunctions/MarketingDetailsHttpTrigger/run.csx @@ -0,0 +1,91 @@ +using System.Net; +using System.Net.Http.Headers; +using System.Configuration; +using Dapper; +using System.Data.SqlClient; + +public static async Task Run(HttpRequestMessage req, TraceWriter log) +{ + log.Info($"Campaign HTTP trigger function processed a request. RequestUri={req.RequestUri}"); + + string htmlResponse = string.Empty; + + // parse query parameter + string campaignId = req.GetQueryNameValuePairs() + .FirstOrDefault(q => string.Compare(q.Key, "campaignId", true) == 0) + .Value; + + string userId = req.GetQueryNameValuePairs() + .FirstOrDefault(q => string.Compare(q.Key, "userId", true) == 0) + .Value; + + var cnnString = ConfigurationManager.ConnectionStrings["SqlConnection"].ConnectionString; + + using (var conn = new SqlConnection(cnnString)) + { + await conn.OpenAsync(); + var sql = "SELECT * FROM [dbo].[Campaign] WHERE Id = @CampaignId;"; + var campaign = (await conn.QueryAsync(sql, new { CampaignId = campaignId })).FirstOrDefault(); + htmlResponse = BuildHtmlResponse(campaign); + } + + var response = new HttpResponseMessage(HttpStatusCode.OK); + response.Content = new ByteArrayContent(System.Text.Encoding.UTF8.GetBytes(htmlResponse)); + response.Content.Headers.ContentType = new MediaTypeHeaderValue("text/html"); + + return response; +} + +private static string BuildHtmlResponse(Campaign campaign) +{ + var marketingStorageUri = ConfigurationManager.AppSettings["MarketingStorageUri"]; + + return string.Format(@" + + + + +
+ Campaign Details +
+ +
+
+
+
+ Card image cap +
+

{1}

+

{2}

+ +
+
+
+
+ + ", + $"{marketingStorageUri}{campaign.PictureName}", + campaign.Name, + campaign.Description, + campaign.From.ToString("MMMM dd, yyyy"), + campaign.From.ToString("MMMM dd, yyyy")); +} + +public class Campaign +{ + public int Id { get; set; } + + public string Name { get; set; } + + public string Description { get; set; } + + public DateTime From { get; set; } + + public DateTime To { get; set; } + + public string PictureUri { get; set; } + + public string PictureName { get; set; } +} diff --git a/src/Services/Marketing/Infrastructure/AzureFunctions/host.json b/src/Services/Marketing/Infrastructure/AzureFunctions/host.json new file mode 100644 index 000000000..9e26dfeeb --- /dev/null +++ b/src/Services/Marketing/Infrastructure/AzureFunctions/host.json @@ -0,0 +1 @@ +{} \ No newline at end of file diff --git a/src/Services/Marketing/Infrastructure/AzureFunctions/local.settings.json b/src/Services/Marketing/Infrastructure/AzureFunctions/local.settings.json new file mode 100644 index 000000000..92d59f7e2 --- /dev/null +++ b/src/Services/Marketing/Infrastructure/AzureFunctions/local.settings.json @@ -0,0 +1,17 @@ +{ + "IsEncrypted": false, + "Value": { + "APPSETTING_FUNCTIONS_EXTENSION_VERSION": "~1", + "APPSETTING_ScmType": "None", + "APPSETTING_WEBSITE_AUTH_ENABLED": "False", + "APPSETTING_REMOTEDEBUGGINGVERSION": "11.0.611103.400", + "APPSETTING_AzureWebJobsDashboard": "", + "APPSETTING_MarketingStorageUri": "", + "APPSETTING_WEBSITE_NODE_DEFAULT_VERSION": "6.5.0", + "APPSETTING_WEBSITE_CONTENTAZUREFILECONNECTIONSTRING": "", + "APPSETTING_WEBSITE_CONTENTSHARE": "", + "APPSETTING_WEBSITE_SLOT_NAME": "", + "APPSETTING_AzureWebJobsStorage": "", + "APPSETTING_WEBSITE_SITE_NAME": "" + } +} \ No newline at end of file diff --git a/src/Services/Marketing/Infrastructure/AzureFunctions/marketing-functions.csproj b/src/Services/Marketing/Infrastructure/AzureFunctions/marketing-functions.csproj new file mode 100644 index 000000000..e159feb69 --- /dev/null +++ b/src/Services/Marketing/Infrastructure/AzureFunctions/marketing-functions.csproj @@ -0,0 +1,33 @@ + + + net461 + + + + + + + + + + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + diff --git a/src/Services/Marketing/Marketing.API/Controllers/CampaignsController.cs b/src/Services/Marketing/Marketing.API/Controllers/CampaignsController.cs index 9b8526a93..4887ac87c 100644 --- a/src/Services/Marketing/Marketing.API/Controllers/CampaignsController.cs +++ b/src/Services/Marketing/Marketing.API/Controllers/CampaignsController.cs @@ -15,6 +15,7 @@ namespace Microsoft.eShopOnContainers.Services.Marketing.API.Controllers using AspNetCore.Authorization; using Extensions.Options; using Microsoft.eShopOnContainers.Services.Marketing.API.ViewModel; + using Microsoft.AspNetCore.Http; [Route("api/v1/[controller]")] [Authorize] @@ -182,15 +183,23 @@ namespace Microsoft.eShopOnContainers.Services.Marketing.API.Controllers private CampaignDTO MapCampaignModelToDto(Campaign campaign) { - return new CampaignDTO + var userId = _identityService.GetUserIdentity(); + var dto = new CampaignDTO { Id = campaign.Id, Name = campaign.Name, Description = campaign.Description, From = campaign.From, To = campaign.To, - PictureUri = GetUriPlaceholder(campaign.PictureUri) + PictureUri = GetUriPlaceholder(campaign), }; + + if (!string.IsNullOrEmpty(_settings.CampaignDetailFunctionUri)) + { + dto.DetailsUri = $"{_settings.CampaignDetailFunctionUri}&campaignId={campaign.Id}&userId={userId}"; + } + + return dto; } private Campaign MapCampaignDtoToModel(CampaignDTO campaignDto) @@ -206,13 +215,13 @@ namespace Microsoft.eShopOnContainers.Services.Marketing.API.Controllers }; } - private string GetUriPlaceholder(string campaignUri) + private string GetUriPlaceholder(Campaign campaign) { - var baseUri = _settings.ExternalCatalogBaseUrl; - - campaignUri = campaignUri.Replace("http://externalcatalogbaseurltobereplaced", baseUri); + var baseUri = _settings.PicBaseUrl; - return campaignUri; + return _settings.AzureStorageEnabled + ? baseUri + campaign.PictureName + : baseUri + campaign.Id; } } } \ No newline at end of file diff --git a/src/Services/Marketing/Marketing.API/Dto/CampaignDTO.cs b/src/Services/Marketing/Marketing.API/Dto/CampaignDTO.cs index 829011ce5..3c409c8a9 100644 --- a/src/Services/Marketing/Marketing.API/Dto/CampaignDTO.cs +++ b/src/Services/Marketing/Marketing.API/Dto/CampaignDTO.cs @@ -15,5 +15,6 @@ public DateTime To { get; set; } public string PictureUri { get; set; } + public string DetailsUri { get; set; } } } \ No newline at end of file diff --git a/src/Services/Marketing/Marketing.API/Infrastructure/MarketingContextSeed.cs b/src/Services/Marketing/Marketing.API/Infrastructure/MarketingContextSeed.cs index fc8c02b4c..ecb3f3c80 100644 --- a/src/Services/Marketing/Marketing.API/Infrastructure/MarketingContextSeed.cs +++ b/src/Services/Marketing/Marketing.API/Infrastructure/MarketingContextSeed.cs @@ -38,6 +38,7 @@ From = DateTime.Now, To = DateTime.Now.AddDays(7), PictureUri = "http://externalcatalogbaseurltobereplaced/api/v1/campaigns/1/pic", + PictureName = "1.png", Rules = new List { new UserLocationRule @@ -54,6 +55,7 @@ From = DateTime.Now.AddDays(-7), To = DateTime.Now.AddDays(14), PictureUri = "http://externalcatalogbaseurltobereplaced/api/v1/campaigns/2/pic", + PictureName = "2.png", Rules = new List { new UserLocationRule diff --git a/src/Services/Marketing/Marketing.API/Infrastructure/MarketingMigrations/20170629102516_added-campaign-details.Designer.cs b/src/Services/Marketing/Marketing.API/Infrastructure/MarketingMigrations/20170629102516_added-campaign-details.Designer.cs new file mode 100644 index 000000000..342d1d02f --- /dev/null +++ b/src/Services/Marketing/Marketing.API/Infrastructure/MarketingMigrations/20170629102516_added-campaign-details.Designer.cs @@ -0,0 +1,121 @@ +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.eShopOnContainers.Services.Marketing.API.Infrastructure; + +namespace Microsoft.eShopOnContainers.Services.Marketing.API.Infrastructure.MarketingMigrations +{ + [DbContext(typeof(MarketingContext))] + [Migration("20170629102516_added-campaign-details")] + partial class addedcampaigndetails + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { + modelBuilder + .HasAnnotation("ProductVersion", "1.1.2") + .HasAnnotation("SqlServer:Sequence:.campaign_hilo", "'campaign_hilo', '', '1', '10', '', '', 'Int64', 'False'") + .HasAnnotation("SqlServer:Sequence:.rule_hilo", "'rule_hilo', '', '1', '10', '', '', 'Int64', 'False'") + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); + + modelBuilder.Entity("Microsoft.eShopOnContainers.Services.Marketing.API.Model.Campaign", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasAnnotation("SqlServer:HiLoSequenceName", "campaign_hilo") + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.SequenceHiLo); + + b.Property("Description") + .IsRequired() + .HasColumnName("Description"); + + b.Property("DetailsUri"); + + b.Property("From") + .HasColumnName("From"); + + b.Property("Name") + .IsRequired() + .HasColumnName("Name"); + + b.Property("PictureName"); + + b.Property("PictureUri") + .IsRequired() + .HasColumnName("PictureUri"); + + b.Property("To") + .HasColumnName("To"); + + b.HasKey("Id"); + + b.ToTable("Campaign"); + }); + + modelBuilder.Entity("Microsoft.eShopOnContainers.Services.Marketing.API.Model.Rule", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasAnnotation("SqlServer:HiLoSequenceName", "rule_hilo") + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.SequenceHiLo); + + b.Property("CampaignId"); + + b.Property("Description") + .IsRequired() + .HasColumnName("Description"); + + b.Property("RuleTypeId"); + + b.HasKey("Id"); + + b.HasIndex("CampaignId"); + + b.ToTable("Rule"); + + b.HasDiscriminator("RuleTypeId"); + }); + + modelBuilder.Entity("Microsoft.eShopOnContainers.Services.Marketing.API.Model.PurchaseHistoryRule", b => + { + b.HasBaseType("Microsoft.eShopOnContainers.Services.Marketing.API.Model.Rule"); + + + b.ToTable("PurchaseHistoryRule"); + + b.HasDiscriminator().HasValue(2); + }); + + modelBuilder.Entity("Microsoft.eShopOnContainers.Services.Marketing.API.Model.UserLocationRule", b => + { + b.HasBaseType("Microsoft.eShopOnContainers.Services.Marketing.API.Model.Rule"); + + b.Property("LocationId") + .HasColumnName("LocationId"); + + b.ToTable("UserLocationRule"); + + b.HasDiscriminator().HasValue(3); + }); + + modelBuilder.Entity("Microsoft.eShopOnContainers.Services.Marketing.API.Model.UserProfileRule", b => + { + b.HasBaseType("Microsoft.eShopOnContainers.Services.Marketing.API.Model.Rule"); + + + b.ToTable("UserProfileRule"); + + b.HasDiscriminator().HasValue(1); + }); + + modelBuilder.Entity("Microsoft.eShopOnContainers.Services.Marketing.API.Model.Rule", b => + { + b.HasOne("Microsoft.eShopOnContainers.Services.Marketing.API.Model.Campaign", "Campaign") + .WithMany("Rules") + .HasForeignKey("CampaignId") + .OnDelete(DeleteBehavior.Cascade); + }); + } + } +} diff --git a/src/Services/Marketing/Marketing.API/Infrastructure/MarketingMigrations/20170629102516_added-campaign-details.cs b/src/Services/Marketing/Marketing.API/Infrastructure/MarketingMigrations/20170629102516_added-campaign-details.cs new file mode 100644 index 000000000..9d6ddf399 --- /dev/null +++ b/src/Services/Marketing/Marketing.API/Infrastructure/MarketingMigrations/20170629102516_added-campaign-details.cs @@ -0,0 +1,33 @@ +using System; +using System.Collections.Generic; +using Microsoft.EntityFrameworkCore.Migrations; + +namespace Microsoft.eShopOnContainers.Services.Marketing.API.Infrastructure.MarketingMigrations +{ + public partial class addedcampaigndetails : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "DetailsUri", + table: "Campaign", + nullable: true); + + migrationBuilder.AddColumn( + name: "PictureName", + table: "Campaign", + nullable: true); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "DetailsUri", + table: "Campaign"); + + migrationBuilder.DropColumn( + name: "PictureName", + table: "Campaign"); + } + } +} diff --git a/src/Services/Marketing/Marketing.API/Infrastructure/MarketingMigrations/MarketingContextModelSnapshot.cs b/src/Services/Marketing/Marketing.API/Infrastructure/MarketingMigrations/MarketingContextModelSnapshot.cs index bcac40659..3866a63ab 100644 --- a/src/Services/Marketing/Marketing.API/Infrastructure/MarketingMigrations/MarketingContextModelSnapshot.cs +++ b/src/Services/Marketing/Marketing.API/Infrastructure/MarketingMigrations/MarketingContextModelSnapshot.cs @@ -29,6 +29,8 @@ namespace Microsoft.eShopOnContainers.Services.Marketing.API.Infrastructure.Mark .IsRequired() .HasColumnName("Description"); + b.Property("DetailsUri"); + b.Property("From") .HasColumnName("From"); @@ -36,6 +38,8 @@ namespace Microsoft.eShopOnContainers.Services.Marketing.API.Infrastructure.Mark .IsRequired() .HasColumnName("Name"); + b.Property("PictureName"); + b.Property("PictureUri") .IsRequired() .HasColumnName("PictureUri"); diff --git a/src/Services/Marketing/Marketing.API/Infrastructure/Services/IIdentityService.cs b/src/Services/Marketing/Marketing.API/Infrastructure/Services/IIdentityService.cs index d49abe111..a2b79d8d1 100644 --- a/src/Services/Marketing/Marketing.API/Infrastructure/Services/IIdentityService.cs +++ b/src/Services/Marketing/Marketing.API/Infrastructure/Services/IIdentityService.cs @@ -1,9 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; - -namespace Microsoft.eShopOnContainers.Services.Locations.API.Infrastructure.Services +namespace Microsoft.eShopOnContainers.Services.Locations.API.Infrastructure.Services { public interface IIdentityService { diff --git a/src/Services/Marketing/Marketing.API/Infrastructure/Services/IdentityService.cs b/src/Services/Marketing/Marketing.API/Infrastructure/Services/IdentityService.cs index bcb7a84f8..9f5ea24f1 100644 --- a/src/Services/Marketing/Marketing.API/Infrastructure/Services/IdentityService.cs +++ b/src/Services/Marketing/Marketing.API/Infrastructure/Services/IdentityService.cs @@ -1,11 +1,8 @@ -using Microsoft.AspNetCore.Http; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; - -namespace Microsoft.eShopOnContainers.Services.Locations.API.Infrastructure.Services +namespace Microsoft.eShopOnContainers.Services.Locations.API.Infrastructure.Services { + using AspNetCore.Http; + using System; + public class IdentityService : IIdentityService { private IHttpContextAccessor _context; @@ -20,4 +17,4 @@ namespace Microsoft.eShopOnContainers.Services.Locations.API.Infrastructure.Serv return _context.HttpContext.User.FindFirst("sub").Value; } } -} +} \ No newline at end of file diff --git a/src/Services/Marketing/Marketing.API/IntegrationEvents/Events/UserLocationUpdatedIntegrationEvent.cs b/src/Services/Marketing/Marketing.API/IntegrationEvents/Events/UserLocationUpdatedIntegrationEvent.cs index a7ab0cafd..f894d903f 100644 --- a/src/Services/Marketing/Marketing.API/IntegrationEvents/Events/UserLocationUpdatedIntegrationEvent.cs +++ b/src/Services/Marketing/Marketing.API/IntegrationEvents/Events/UserLocationUpdatedIntegrationEvent.cs @@ -1,13 +1,13 @@ namespace Microsoft.eShopOnContainers.Services.Marketing.API.IntegrationEvents.Events { - using Model; + using Marketing.API.Model; + using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events; using System.Collections.Generic; - using BuildingBlocks.EventBus.Events; public class UserLocationUpdatedIntegrationEvent : IntegrationEvent { - public string UserId { get; private set; } - public List LocationList { get; private set; } + public string UserId { get; set; } + public List LocationList { get; set; } public UserLocationUpdatedIntegrationEvent(string userId, List locationList) { diff --git a/src/Services/Marketing/Marketing.API/IntegrationEvents/Handlers/UserLocationUpdatedIntegrationEventHandler.cs b/src/Services/Marketing/Marketing.API/IntegrationEvents/Handlers/UserLocationUpdatedIntegrationEventHandler.cs index 7879c3d96..5393608a0 100644 --- a/src/Services/Marketing/Marketing.API/IntegrationEvents/Handlers/UserLocationUpdatedIntegrationEventHandler.cs +++ b/src/Services/Marketing/Marketing.API/IntegrationEvents/Handlers/UserLocationUpdatedIntegrationEventHandler.cs @@ -1,12 +1,13 @@ namespace Microsoft.eShopOnContainers.Services.Marketing.API.IntegrationEvents.Handlers { - using BuildingBlocks.EventBus.Abstractions; - using System.Threading.Tasks; - using Events; + using Marketing.API.IntegrationEvents.Events; + using Marketing.API.Model; + using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Abstractions; + using Microsoft.eShopOnContainers.Services.Marketing.API.Infrastructure.Repositories; + using Microsoft.eShopOnContainers.Services.Marketing.API.Model; using System; - using Infrastructure.Repositories; - using Model; using System.Collections.Generic; + using System.Threading.Tasks; public class UserLocationUpdatedIntegrationEventHandler : IIntegrationEventHandler diff --git a/src/Services/Marketing/Marketing.API/Marketing.API.csproj b/src/Services/Marketing/Marketing.API/Marketing.API.csproj index 72b18c397..d3cf1691a 100644 --- a/src/Services/Marketing/Marketing.API/Marketing.API.csproj +++ b/src/Services/Marketing/Marketing.API/Marketing.API.csproj @@ -58,6 +58,7 @@ +
diff --git a/src/Services/Marketing/Marketing.API/MarketingSettings.cs b/src/Services/Marketing/Marketing.API/MarketingSettings.cs index f83200019..20e5d9c44 100644 --- a/src/Services/Marketing/Marketing.API/MarketingSettings.cs +++ b/src/Services/Marketing/Marketing.API/MarketingSettings.cs @@ -6,5 +6,8 @@ public string MongoConnectionString { get; set; } public string MongoDatabase { get; set; } public string ExternalCatalogBaseUrl { get; set; } + public string CampaignDetailFunctionUri { get; set; } + public string PicBaseUrl { get; set; } + public bool AzureStorageEnabled { get; set; } } } diff --git a/src/Services/Marketing/Marketing.API/Model/Campaign.cs b/src/Services/Marketing/Marketing.API/Model/Campaign.cs index 51a4c017c..841580427 100644 --- a/src/Services/Marketing/Marketing.API/Model/Campaign.cs +++ b/src/Services/Marketing/Marketing.API/Model/Campaign.cs @@ -15,8 +15,12 @@ public DateTime To { get; set; } + public string PictureName { get; set; } + public string PictureUri { get; set; } + public string DetailsUri { get; set; } + public List Rules { get; set; } diff --git a/src/Services/Marketing/Marketing.API/Program.cs b/src/Services/Marketing/Marketing.API/Program.cs index 8bac1bbae..dbde65b27 100644 --- a/src/Services/Marketing/Marketing.API/Program.cs +++ b/src/Services/Marketing/Marketing.API/Program.cs @@ -1,8 +1,7 @@ namespace Microsoft.eShopOnContainers.Services.Marketing.API { using System.IO; - using Microsoft.AspNetCore.Builder; - using Microsoft.AspNetCore.Hosting; + using AspNetCore.Hosting; public class Program { diff --git a/src/Services/Marketing/Marketing.API/Startup.cs b/src/Services/Marketing/Marketing.API/Startup.cs index 5550ef507..044c9c190 100644 --- a/src/Services/Marketing/Marketing.API/Startup.cs +++ b/src/Services/Marketing/Marketing.API/Startup.cs @@ -1,32 +1,34 @@ -using Microsoft.AspNetCore.Http; -using Microsoft.eShopOnContainers.Services.Locations.API.Infrastructure.Services; - -namespace Microsoft.eShopOnContainers.Services.Marketing.API +namespace Microsoft.eShopOnContainers.Services.Marketing.API { - using Microsoft.AspNetCore.Builder; - using Microsoft.AspNetCore.Hosting; - using Microsoft.EntityFrameworkCore.Infrastructure; - using Microsoft.EntityFrameworkCore; - using Microsoft.eShopOnContainers.Services.Marketing.API.Infrastructure; - using Microsoft.Extensions.Configuration; - using Microsoft.Extensions.DependencyInjection; - using Microsoft.Extensions.Logging; - using System.Reflection; - using System; - using Microsoft.eShopOnContainers.Services.Marketing.API.Infrastructure.Filters; - using Microsoft.eShopOnContainers.BuildingBlocks.EventBusRabbitMQ; - using RabbitMQ.Client; - using BuildingBlocks.EventBus.Abstractions; - using BuildingBlocks.EventBus; - using IntegrationEvents.Events; - using IntegrationEvents.Handlers; - using Infrastructure.Repositories; using Autofac; using Autofac.Extensions.DependencyInjection; + using IntegrationEvents.Events; + using AspNetCore.Builder; + using AspNetCore.Hosting; + using AspNetCore.Http; + using Azure.ServiceBus; + using EntityFrameworkCore; + using EntityFrameworkCore.Infrastructure; + using BuildingBlocks.EventBus; + using BuildingBlocks.EventBus.Abstractions; + using BuildingBlocks.EventBusRabbitMQ; + using BuildingBlocks.EventBusServiceBus; + using Infrastructure; + using Infrastructure.Filters; + using Infrastructure.Repositories; + using Locations.API.Infrastructure.Services; + using Extensions.Configuration; + using Extensions.DependencyInjection; + using Extensions.Logging; using Polly; - using System.Threading.Tasks; + using RabbitMQ.Client; + using System; using System.Data.SqlClient; - using Microsoft.Extensions.HealthChecks; + using System.Reflection; + using System.Threading.Tasks; + using Extensions.HealthChecks; + using Marketing.API.IntegrationEvents.Handlers; + public class Startup { @@ -82,19 +84,32 @@ namespace Microsoft.eShopOnContainers.Services.Marketing.API //Check Client vs. Server evaluation: https://docs.microsoft.com/en-us/ef/core/querying/client-eval }); - services.AddSingleton(sp => + if (Configuration.GetValue("AzureServiceBusEnabled")) { - var logger = sp.GetRequiredService>(); + services.AddSingleton(sp => + { + var logger = sp.GetRequiredService>(); + + var serviceBusConnectionString = Configuration["EventBusConnection"]; + var serviceBusConnection = new ServiceBusConnectionStringBuilder(serviceBusConnectionString); - var factory = new ConnectionFactory() + return new DefaultServiceBusPersisterConnection(serviceBusConnection, logger); + }); + } + else + { + services.AddSingleton(sp => { - HostName = Configuration["EventBusConnection"] - }; + var logger = sp.GetRequiredService>(); - return new DefaultRabbitMQPersistentConnection(factory, logger); - }); + var factory = new ConnectionFactory() + { + HostName = Configuration["EventBusConnection"] + }; - RegisterServiceBus(services); + return new DefaultRabbitMQPersistentConnection(factory, logger); + }); + } // Add framework services. services.AddSwaggerGen(options => @@ -118,10 +133,14 @@ namespace Microsoft.eShopOnContainers.Services.Marketing.API .AllowCredentials()); }); + RegisterEventBus(services); + services.AddTransient(); services.AddSingleton(); services.AddTransient(); + services.AddOptions(); + //configure autofac var container = new ContainerBuilder(); container.Populate(services); @@ -145,7 +164,7 @@ namespace Microsoft.eShopOnContainers.Services.Marketing.API .UseSwaggerUI(c => { c.SwaggerEndpoint("/swagger/v1/swagger.json", "My API V1"); - }); + }); var context = (MarketingContext)app .ApplicationServices.GetService(typeof(MarketingContext)); @@ -166,21 +185,35 @@ namespace Microsoft.eShopOnContainers.Services.Marketing.API }); } - private void RegisterServiceBus(IServiceCollection services) + private void RegisterEventBus(IServiceCollection services) { - services.AddSingleton(); - services.AddSingleton(); + if (Configuration.GetValue("AzureServiceBusEnabled")) + { + services.AddSingleton(sp => + { + var serviceBusPersisterConnection = sp.GetRequiredService(); + var iLifetimeScope = sp.GetRequiredService(); + var logger = sp.GetRequiredService>(); + var eventBusSubcriptionsManager = sp.GetRequiredService(); + var subscriptionClientName = Configuration["SubscriptionClientName"]; + + return new EventBusServiceBus(serviceBusPersisterConnection, logger, + eventBusSubcriptionsManager, subscriptionClientName, iLifetimeScope); + }); + } + else + { + services.AddSingleton(); + } - services.AddTransient, - UserLocationUpdatedIntegrationEventHandler>(); + services.AddSingleton(); + services.AddTransient(); } private void ConfigureEventBus(IApplicationBuilder app) { var eventBus = app.ApplicationServices.GetRequiredService(); - eventBus.Subscribe>(); + eventBus.Subscribe(); } private async Task WaitForSqlAvailabilityAsync(MarketingContext ctx, ILoggerFactory loggerFactory, IApplicationBuilder app, int retries = 0) diff --git a/src/Services/Marketing/Marketing.API/appsettings.json b/src/Services/Marketing/Marketing.API/appsettings.json index a05a01836..0137a2ae8 100644 --- a/src/Services/Marketing/Marketing.API/appsettings.json +++ b/src/Services/Marketing/Marketing.API/appsettings.json @@ -9,5 +9,8 @@ "MongoConnectionString": "mongodb://nosql.data", "MongoDatabase": "MarketingDb", "IdentityUrl": "http://localhost:5105", - "ExternalCatalogBaseUrl": "http://localhost:5110" + "ExternalCatalogBaseUrl": "http://localhost:5110", + "AzureServiceBusEnabled": false, + "SubscriptionClientName": "Marketing", + "AzureStorageEnabled": false } diff --git a/src/Services/Ordering/Ordering.API/Startup.cs b/src/Services/Ordering/Ordering.API/Startup.cs index cb33d9991..15a966c1a 100644 --- a/src/Services/Ordering/Ordering.API/Startup.cs +++ b/src/Services/Ordering/Ordering.API/Startup.cs @@ -4,11 +4,8 @@ using Autofac; using Autofac.Extensions.DependencyInjection; using global::Ordering.API.Application.IntegrationEvents; - using global::Ordering.API.Application.IntegrationEvents.EventHandling; using global::Ordering.API.Application.IntegrationEvents.Events; - using global::Ordering.API.Infrastructure.Middlewares; using Infrastructure; - using Infrastructure.Auth; using Infrastructure.AutofacModules; using Infrastructure.Filters; using Infrastructure.Services; diff --git a/src/Services/Payment/Payment.API/Payment.API.csproj b/src/Services/Payment/Payment.API/Payment.API.csproj index dc8aad80d..3a1c4e248 100644 --- a/src/Services/Payment/Payment.API/Payment.API.csproj +++ b/src/Services/Payment/Payment.API/Payment.API.csproj @@ -27,6 +27,7 @@ + diff --git a/src/Services/Payment/Payment.API/Startup.cs b/src/Services/Payment/Payment.API/Startup.cs index 32d0fc8c4..9cba1415d 100644 --- a/src/Services/Payment/Payment.API/Startup.cs +++ b/src/Services/Payment/Payment.API/Startup.cs @@ -12,6 +12,8 @@ using RabbitMQ.Client; using Microsoft.eShopOnContainers.BuildingBlocks.EventBus; using Payment.API.IntegrationEvents.Events; using Payment.API.IntegrationEvents.EventHandling; +using Microsoft.eShopOnContainers.BuildingBlocks.EventBusServiceBus; +using Microsoft.Azure.ServiceBus; namespace Payment.API { @@ -35,19 +37,34 @@ namespace Payment.API // Add framework services. services.AddMvc(); services.Configure(Configuration); - services.AddSingleton(sp => + if (Configuration.GetValue("AzureServiceBusEnabled")) { - var logger = sp.GetRequiredService>(); + services.AddSingleton(sp => + { + var logger = sp.GetRequiredService>(); + + var serviceBusConnectionString = Configuration["EventBusConnection"]; + var serviceBusConnection = new ServiceBusConnectionStringBuilder(serviceBusConnectionString); - var factory = new ConnectionFactory() + return new DefaultServiceBusPersisterConnection(serviceBusConnection, logger); + }); + } + else + { + services.AddSingleton(sp => { - HostName = Configuration["EventBusConnection"] - }; + var logger = sp.GetRequiredService>(); - return new DefaultRabbitMQPersistentConnection(factory, logger); - }); + var factory = new ConnectionFactory() + { + HostName = Configuration["EventBusConnection"] + }; + + return new DefaultRabbitMQPersistentConnection(factory, logger); + }); + } - RegisterServiceBus(services); + RegisterEventBus(services); services.AddSwaggerGen(options => { @@ -84,20 +101,35 @@ namespace Payment.API ConfigureEventBus(app); } - private void RegisterServiceBus(IServiceCollection services) + private void RegisterEventBus(IServiceCollection services) { - services.AddSingleton(); - services.AddSingleton(); + if (Configuration.GetValue("AzureServiceBusEnabled")) + { + services.AddSingleton(sp => + { + var serviceBusPersisterConnection = sp.GetRequiredService(); + var iLifetimeScope = sp.GetRequiredService(); + var logger = sp.GetRequiredService>(); + var eventBusSubcriptionsManager = sp.GetRequiredService(); + var subscriptionClientName = Configuration["SubscriptionClientName"]; + + return new EventBusServiceBus(serviceBusPersisterConnection, logger, + eventBusSubcriptionsManager, subscriptionClientName, iLifetimeScope); + }); + } + else + { + services.AddSingleton(); + } - services.AddTransient, - OrderStatusChangedToStockConfirmedIntegrationEventHandler>(); + services.AddTransient(); + services.AddSingleton(); } private void ConfigureEventBus(IApplicationBuilder app) { var eventBus = app.ApplicationServices.GetRequiredService(); - eventBus.Subscribe>(); + eventBus.Subscribe(); } } } \ No newline at end of file diff --git a/src/Services/Payment/Payment.API/appsettings.json b/src/Services/Payment/Payment.API/appsettings.json index 601eaa246..9aef99a14 100644 --- a/src/Services/Payment/Payment.API/appsettings.json +++ b/src/Services/Payment/Payment.API/appsettings.json @@ -5,5 +5,7 @@ "Default": "Warning" } }, - "PaymentSucceded": "true" + "PaymentSucceded": true, + "AzureServiceBusEnabled": false, + "SubscriptionClientName": "Payment" } diff --git a/src/Web/WebMVC/AppSettings.cs b/src/Web/WebMVC/AppSettings.cs index 19c8b9a93..42946262f 100644 --- a/src/Web/WebMVC/AppSettings.cs +++ b/src/Web/WebMVC/AppSettings.cs @@ -12,6 +12,7 @@ namespace Microsoft.eShopOnContainers.WebMVC public string OrderingUrl { get; set; } public string BasketUrl { get; set; } public string MarketingUrl { get; set; } + public bool ActivateCampaignDetailFunction { get; set; } public Logging Logging { get; set; } public bool UseCustomizationData { get; set; } } diff --git a/src/Web/WebMVC/Controllers/CampaignsController.cs b/src/Web/WebMVC/Controllers/CampaignsController.cs index 8f291bb49..cbb08e051 100644 --- a/src/Web/WebMVC/Controllers/CampaignsController.cs +++ b/src/Web/WebMVC/Controllers/CampaignsController.cs @@ -11,19 +11,29 @@ namespace Microsoft.eShopOnContainers.WebMVC.Controllers using System; using ViewModels.Pagination; using global::WebMVC.ViewModels; + using Microsoft.Extensions.Options; [Authorize] public class CampaignsController : Controller { private readonly ICampaignService _campaignService; + private readonly AppSettings _settings; - public CampaignsController(ICampaignService campaignService) => + public CampaignsController(ICampaignService campaignService, IOptionsSnapshot settings) + { _campaignService = campaignService; + _settings = settings.Value; + } public async Task Index(int page = 0, int pageSize = 10) { var campaignList = await _campaignService.GetCampaigns(pageSize, page); + if(campaignList is null) + { + return View(); + } + var totalPages = (int) Math.Ceiling((decimal) campaignList.Count / pageSize); var vm = new CampaignViewModel @@ -40,6 +50,8 @@ namespace Microsoft.eShopOnContainers.WebMVC.Controllers } }; + ViewBag.IsCampaignDetailFunctionActive = _settings.ActivateCampaignDetailFunction; + return View(vm); } diff --git a/src/Web/WebMVC/ViewModels/CampaignItem.cs b/src/Web/WebMVC/ViewModels/CampaignItem.cs index a0bfbaf66..04e220229 100644 --- a/src/Web/WebMVC/ViewModels/CampaignItem.cs +++ b/src/Web/WebMVC/ViewModels/CampaignItem.cs @@ -15,5 +15,6 @@ public DateTime To { get; set; } public string PictureUri { get; set; } + public string DetailsUri { get; set; } } } \ No newline at end of file diff --git a/src/Web/WebMVC/Views/Campaigns/Index.cshtml b/src/Web/WebMVC/Views/Campaigns/Index.cshtml index d4c8abe48..bca288ed6 100644 --- a/src/Web/WebMVC/Views/Campaigns/Index.cshtml +++ b/src/Web/WebMVC/Views/Campaigns/Index.cshtml @@ -13,10 +13,8 @@ new Header() { Controller = "Catalog", Text = "Back to catalog" } })
- @if (Model.CampaignItems != null && Model.CampaignItems.Any()) + @if(Model != null && Model.CampaignItems.Any()) { - @Html.Partial("_pagination", Model.PaginationInfo) -
@foreach (var catalogItem in Model.CampaignItems) { diff --git a/src/Web/WebMVC/Views/Campaigns/_campaign.cshtml b/src/Web/WebMVC/Views/Campaigns/_campaign.cshtml index de3b52657..c0a074b12 100644 --- a/src/Web/WebMVC/Views/Campaigns/_campaign.cshtml +++ b/src/Web/WebMVC/Views/Campaigns/_campaign.cshtml @@ -1,17 +1,21 @@ @model CampaignItem - -

@Model.Name

@Model.Name - + @if (ViewBag.IsCampaignDetailFunctionActive == true) + { + + } + else + { + + }
+
diff --git a/src/Web/WebMVC/Views/Order/Index.cshtml b/src/Web/WebMVC/Views/Order/Index.cshtml index 61a871f26..9d190e9a0 100644 --- a/src/Web/WebMVC/Views/Order/Index.cshtml +++ b/src/Web/WebMVC/Views/Order/Index.cshtml @@ -19,7 +19,8 @@
Status
- + @if (Model != null && Model.Any()) + { @foreach (var item in Model) {
@@ -38,6 +39,7 @@
} + }