From 750263d4669a7b90a509924bea8608daccde3067 Mon Sep 17 00:00:00 2001 From: Maksym Sadovnychyy Date: Fri, 16 Sep 2022 22:55:47 +0200 Subject: [PATCH] (refactor): service base and log spanId --- postman/reactredux.postman_collection.json | 339 +++++++++++++----- .../Abstractions/DomainObjects/PersonBase.cs | 2 +- .../Abstractions/Models/RequestModelBase.cs | 6 + webapi/Core/Abstractions/ServiceBase.cs | 19 + webapi/Core/Core.csproj | 4 + webapi/Core/DomainObjects/Image.cs | 8 +- webapi/Core/DomainObjects/MediaAttachment.cs | 22 ++ .../PageSections/TitleSection.cs | 2 +- .../Collections/UserDataProvider.cs | 17 + .../Extensions/ServiceCollectionExtensions.cs | 1 + webapi/ReverseProxy/appsettings.json | 26 +- .../Extensions/ServiceCollectionExtensions.cs | 11 + webapi/Services/HashService/HashService.cs | 5 +- .../Services/HashService/HashService.csproj | 11 +- .../Extensions/ServiceCollectionExtensions.cs | 14 + .../Services/JWTService/IJWTServiceConfig.cs | 17 + .../JWTService/IJWTServiceConfiguration.cs | 7 - webapi/Services/JWTService/JWTService.cs | 84 +++-- webapi/Services/JWTService/JWTService.csproj | 5 +- webapi/WeatherForecast/Configuration.cs | 6 +- .../Controllers/AuthenticationController.cs | 43 +++ .../Controllers/BlogItemController.cs | 2 +- .../Controllers/BlogItemsController.cs | 1 + .../Controllers/CategoryItemController.cs | 4 +- .../Controllers/CategoryItemsController.cs | 3 +- .../Controllers/FileController.cs | 2 +- .../Controllers/FilesController.cs | 2 +- .../Controllers/LoginController.cs | 31 -- .../Controllers/PasswordController.cs | 38 ++ .../Controllers/ShopCartItemController.cs | 2 +- .../Controllers/ShopCartItemsController.cs | 2 +- .../Controllers/ShopItemController.cs | 3 +- .../Controllers/ShopItemsController.cs | 85 ++--- .../Controllers/WeatherForecastController.cs | 2 + .../Requests/AuthenticationRequestModel.cs | 36 ++ .../Models/Requests/PasswordRequestModel.cs | 27 ++ webapi/WeatherForecast/Program.cs | 4 +- .../Abstractions/PostItemServiceBase.cs | 9 +- .../Services/AutheticationService.cs | 66 ++++ .../Services/BlogItemService.cs | 16 +- .../Services/BlogItemsService.cs | 12 +- .../Services/CategoryItemService.cs | 10 +- .../Services/CategoryItemsService.cs | 10 +- .../Services/ContentService.cs | 7 +- .../WeatherForecast/Services/FileService.cs | 14 +- .../WeatherForecast/Services/FilesService.cs | 13 +- .../WeatherForecast/Services/ImageService.cs | 13 +- .../Services/PasswordService.cs | 73 ++++ .../Services/ShopCartItemService.cs | 6 +- .../Services/ShopCartItemsService.cs | 9 +- .../Services/ShopItemService.cs | 10 +- .../Services/ShopItemsService.cs | 12 +- webapi/WeatherForecast/Startup.cs | 10 +- webapi/WeatherForecast/WeatherForecast.csproj | 3 + webapi/WeatherForecast/appsettings.json | 8 +- 55 files changed, 893 insertions(+), 301 deletions(-) create mode 100644 webapi/Core/Abstractions/ServiceBase.cs create mode 100644 webapi/Core/DomainObjects/MediaAttachment.cs create mode 100644 webapi/DataProviders/Collections/UserDataProvider.cs create mode 100644 webapi/Services/HashService/Extensions/ServiceCollectionExtensions.cs create mode 100644 webapi/Services/JWTService/Extensions/ServiceCollectionExtensions.cs create mode 100644 webapi/Services/JWTService/IJWTServiceConfig.cs delete mode 100644 webapi/Services/JWTService/IJWTServiceConfiguration.cs create mode 100644 webapi/WeatherForecast/Controllers/AuthenticationController.cs delete mode 100644 webapi/WeatherForecast/Controllers/LoginController.cs create mode 100644 webapi/WeatherForecast/Controllers/PasswordController.cs create mode 100644 webapi/WeatherForecast/Models/Requests/AuthenticationRequestModel.cs create mode 100644 webapi/WeatherForecast/Models/Requests/PasswordRequestModel.cs create mode 100644 webapi/WeatherForecast/Services/AutheticationService.cs create mode 100644 webapi/WeatherForecast/Services/PasswordService.cs diff --git a/postman/reactredux.postman_collection.json b/postman/reactredux.postman_collection.json index f735f1c..990c408 100644 --- a/postman/reactredux.postman_collection.json +++ b/postman/reactredux.postman_collection.json @@ -25,11 +25,12 @@ } ], "url": { - "raw": "{{baseUrl}}/Content/{{siteId}}?locale=en-US", + "raw": "{{reverseProxy}}/api/Content/{{siteId}}?locale=en-US", "host": [ - "{{baseUrl}}" + "{{reverseProxy}}" ], "path": [ + "api", "Content", "{{siteId}}" ], @@ -65,12 +66,12 @@ } ], "url": { - "raw": "{{baseUrl}}//CategoryItem/{{siteId}}/e154e33f-3cc7-468d-bb66-e0390ddb9ae0", + "raw": "{{reverseProxy}}/api/CategoryItem/{{siteId}}/e154e33f-3cc7-468d-bb66-e0390ddb9ae0", "host": [ - "{{baseUrl}}" + "{{reverseProxy}}" ], "path": [ - "", + "api", "CategoryItem", "{{siteId}}", "e154e33f-3cc7-468d-bb66-e0390ddb9ae0" @@ -96,11 +97,12 @@ } ], "url": { - "raw": "{{baseUrl}}/CategoryItem/{{siteId}}?slug=default", + "raw": "{{reverseProxy}}/api/CategoryItem/{{siteId}}?slug=default", "host": [ - "{{baseUrl}}" + "{{reverseProxy}}" ], "path": [ + "api", "CategoryItem", "{{siteId}}" ], @@ -135,12 +137,12 @@ "raw": "{\r\n \"l10n\": [\r\n {\r\n \"locale\": \"\",\r\n \"slug\": \"guides\",\r\n \"text\": \"Guides\"\r\n }\r\n ]\r\n}" }, "url": { - "raw": "{{baseUrl}}//CategoryItem/{{siteId}}", + "raw": "{{reverseProxy}}/api/CategoryItem/{{siteId}}", "host": [ - "{{baseUrl}}" + "{{reverseProxy}}" ], "path": [ - "", + "api", "CategoryItem", "{{siteId}}" ] @@ -169,12 +171,12 @@ "raw": "{\r\n \"l10n\": [\r\n {\r\n \"locale\": \"en-US\",\r\n \"slug\": \"guides\",\r\n \"text\": \"Guides\"\r\n },\r\n {\r\n \"locale\": \"it-IT\",\r\n \"slug\": \"guide\",\r\n \"text\": \"Guide\"\r\n }\r\n ]\r\n}" }, "url": { - "raw": "{{baseUrl}}//CategoryItem/{{siteId}}/2c50f4de-70f2-4414-aabc-7a0d2eb0e203", + "raw": "{{reverseProxy}}/api/CategoryItem/{{siteId}}/2c50f4de-70f2-4414-aabc-7a0d2eb0e203", "host": [ - "{{baseUrl}}" + "{{reverseProxy}}" ], "path": [ - "", + "api", "CategoryItem", "{{siteId}}", "2c50f4de-70f2-4414-aabc-7a0d2eb0e203" @@ -200,11 +202,12 @@ } ], "url": { - "raw": "{{baseUrl}}/CategoryItem/{{siteId}}/e154e33f-3cc7-468d-bb66-e0390ddb9ae0", + "raw": "{{reverseProxy}}/api/CategoryItem/{{siteId}}/e154e33f-3cc7-468d-bb66-e0390ddb9ae0", "host": [ - "{{baseUrl}}" + "{{reverseProxy}}" ], "path": [ + "api", "CategoryItem", "{{siteId}}", "e154e33f-3cc7-468d-bb66-e0390ddb9ae0" @@ -235,11 +238,12 @@ } ], "url": { - "raw": "{{baseUrl}}/CategoryItems/{{siteId}}", + "raw": "{{reverseProxy}}/api/CategoryItems/{{siteId}}", "host": [ - "{{baseUrl}}" + "{{reverseProxy}}" ], "path": [ + "api", "CategoryItems", "{{siteId}}" ] @@ -264,11 +268,12 @@ } ], "url": { - "raw": "{{baseUrl}}/CategoryItems/{{siteId}}?locale=en-US", + "raw": "{{reverseProxy}}/api/CategoryItems/{{siteId}}?locale=en-US", "host": [ - "{{baseUrl}}" + "{{reverseProxy}}" ], "path": [ + "api", "CategoryItems", "{{siteId}}" ], @@ -299,11 +304,12 @@ } ], "url": { - "raw": "{{baseUrl}}/CategoryItems/{{siteId}}", + "raw": "{{reverseProxy}}/api/CategoryItems/{{siteId}}", "host": [ - "{{baseUrl}}" + "{{reverseProxy}}" ], "path": [ + "api", "CategoryItems", "{{siteId}}" ] @@ -337,11 +343,12 @@ "raw": "{\r\n \"siteId\": \"404c8232-9048-4519-bfba-6e78dc7005ca\",\r\n \"l10n\": [\r\n {\r\n \"locale\": \"en-US\",\r\n \"slug\": \"shop-catalog-item-05\",\r\n \"description\": \"Lorem ipsum, dolor sit amet consectetur adipisicing elit.\",\r\n \"title\": \"Shop item title\",\r\n \"shortText\": \"Lorem ipsum, dolor sit amet consectetur adipisicing elit. Eaque fugit ratione dicta mollitia. Officiis ad...\",\r\n \"text\": \"

Lorem ipsum, dolor sit amet consectetur adipisicing elit.

\",\r\n \"textFormat\": \"HTML\",\r\n \"plainText\": \"Lorem ipsum, dolor sit amet consectetur adipisicing elit.\",\r\n \"badges\": [\r\n \"sale\"\r\n ]\r\n }\r\n ],\r\n\t\"mediaAttachments\": [\r\n\t {\r\n\t\t\"src\": \"api/Image/450x300/5033d24e-a7c3-4960-ac3c-f396d6773692\",\r\n\t\t\"mediaType\": \"image\",\r\n\t\t\"l10n\": [\r\n {\r\n \"locale\": \"en-US\",\r\n \"alt\": \"...\",\r\n\t\t\t\"target\": \"/title-image\",\r\n\t\t\t\"title\": \"Title image\",\r\n\t\t\t\"description\": \"Title image description.\"\r\n\t }\r\n ]\r\n\t }\r\n\t],\r\n \"author\": \"fdc5aa50-ee68-4bae-a8e6-b8ae2c258f60\",\r\n \"created\": {\r\n \"$date\": \"2022-01-01T00:00:00.000Z\"\r\n },\r\n \"tags\": [\r\n \"react\",\r\n \"redux\",\r\n \"webapi\"\r\n ],\r\n \"brandName\": \"Mongodb Brand & Name\",\r\n \"sku\": \"SKU-05\",\r\n \"rating\": 4.5,\r\n \"price\": 20,\r\n \"newPrice\": 10,\r\n \"quantity\": 100\r\n }" }, "url": { - "raw": "{{baseUrl}}/ShopItem/{{siteId}}/SKU-05", + "raw": "{{reverseProxy}}/api/ShopItem/{{siteId}}/SKU-05", "host": [ - "{{baseUrl}}" + "{{reverseProxy}}" ], "path": [ + "api", "ShopItem", "{{siteId}}", "SKU-05" @@ -367,12 +374,12 @@ } ], "url": { - "raw": "{{baseUrl}}//ShopItem/{{siteId}}/SKU-05", + "raw": "{{reverseProxy}}/api/ShopItem/{{siteId}}/SKU-05", "host": [ - "{{baseUrl}}" + "{{reverseProxy}}" ], "path": [ - "", + "api", "ShopItem", "{{siteId}}", "SKU-05" @@ -398,12 +405,12 @@ } ], "url": { - "raw": "{{baseUrl}}/ShopItem/{{siteId}}?slug=shop-catalog-item-05", + "raw": "{{reverseProxy}}/api/ShopItem/{{siteId}}?slug=shop-catalog-item-05", "host": [ - "{{baseUrl}}" + "{{reverseProxy}}" ], "path": [ - "", + "api", "ShopItem", "{{siteId}}" ], @@ -438,11 +445,12 @@ "raw": "{\r\n \"siteId\": \"404c8232-9048-4519-bfba-6e78dc7005ca\",\r\n \"l10n\": [\r\n {\r\n \"locale\": \"en-US\",\r\n \"slug\": \"shop-catalog-item-05\",\r\n \"description\": \"Lorem ipsum, dolor sit amet consectetur adipisicing elit.\",\r\n \"title\": \"Shop item title\",\r\n \"shortText\": \"Lorem ipsum, dolor sit amet consectetur adipisicing elit. Eaque fugit ratione dicta mollitia. Officiis ad...\",\r\n \"text\": \"

Lorem ipsum, dolor sit amet consectetur adipisicing elit.

\",\r\n \"textFormat\": \"HTML\",\r\n \"plainText\": \"Lorem ipsum, dolor sit amet consectetur adipisicing elit.\",\r\n \"badges\": [\r\n \"sale\"\r\n ]\r\n }\r\n ],\r\n\t\"mediaAttachments\": [\r\n\t {\r\n\t\t\"src\": \"api/Image/450x300/5033d24e-a7c3-4960-ac3c-f396d6773692\",\r\n\t\t\"mediaType\": \"image\",\r\n\t\t\"l10n\": [\r\n {\r\n \"locale\": \"en-US\",\r\n \"alt\": \"...\",\r\n\t\t\t\"target\": \"/title-image\",\r\n\t\t\t\"title\": \"Title image\",\r\n\t\t\t\"description\": \"Title image description.\"\r\n\t }\r\n ]\r\n\t }\r\n\t],\r\n \"author\": \"fdc5aa50-ee68-4bae-a8e6-b8ae2c258f60\",\r\n \"created\": {\r\n \"$date\": \"2022-01-01T00:00:00.000Z\"\r\n },\r\n \"tags\": [\r\n \"react\",\r\n \"redux\",\r\n \"webapi\"\r\n ],\r\n \"categories\": [\r\n \"e154e33f-3cc7-468d-bb66-e0390ddb9ae0\"\r\n ],\r\n \"brandName\": \"Mongodb Brand & Name\",\r\n \"sku\": \"SKU-05\",\r\n \"rating\": 4.5,\r\n \"price\": 20,\r\n \"newPrice\": 10,\r\n \"quantity\": 100\r\n }" }, "url": { - "raw": "{{baseUrl}}/ShopItem/{{siteId}}/SKU-05", + "raw": "{{reverseProxy}}/api/ShopItem/{{siteId}}/SKU-05", "host": [ - "{{baseUrl}}" + "{{reverseProxy}}" ], "path": [ + "api", "ShopItem", "{{siteId}}", "SKU-05" @@ -468,11 +476,12 @@ } ], "url": { - "raw": "{{baseUrl}}/ShopItem/{{siteId}}/SKU-05", + "raw": "{{reverseProxy}}/api/ShopItem/{{siteId}}/SKU-05", "host": [ - "{{baseUrl}}" + "{{reverseProxy}}" ], "path": [ + "api", "ShopItem", "{{siteId}}", "SKU-05" @@ -503,11 +512,12 @@ } ], "url": { - "raw": "{{baseUrl}}/ShopItems/{{siteId}}?currentPage=1&itemsPerPage=4", + "raw": "{{reverseProxy}}/api/ShopItems/{{siteId}}?currentPage=1&itemsPerPage=4", "host": [ - "{{baseUrl}}" + "{{reverseProxy}}" ], "path": [ + "api", "ShopItems", "{{siteId}}" ], @@ -542,11 +552,12 @@ } ], "url": { - "raw": "{{baseUrl}}/ShopItems/{{siteId}}?currentPage=2&itemsPerPage=2&locale=en-US", + "raw": "{{reverseProxy}}/api/ShopItems/{{siteId}}?currentPage=2&itemsPerPage=2&locale=en-US", "host": [ - "{{baseUrl}}" + "{{reverseProxy}}" ], "path": [ + "api", "ShopItems", "{{siteId}}" ], @@ -585,11 +596,12 @@ } ], "url": { - "raw": "{{baseUrl}}/ShopItems/{{siteId}}", + "raw": "{{reverseProxy}}/api/ShopItems/{{siteId}}", "host": [ - "{{baseUrl}}" + "{{reverseProxy}}" ], "path": [ + "api", "ShopItems", "{{siteId}}" ] @@ -619,11 +631,12 @@ } ], "url": { - "raw": "{{baseUrl}}/ShopCartItem/{{siteId}}/fdc5aa50-ee68-4bae-a8e6-b8ae2c258f60/SKU-04?locale=en-US", + "raw": "{{reverseProxy}}/api/ShopCartItem/{{siteId}}/fdc5aa50-ee68-4bae-a8e6-b8ae2c258f60/SKU-04?locale=en-US", "host": [ - "{{baseUrl}}" + "{{reverseProxy}}" ], "path": [ + "api", "ShopCartItem", "{{siteId}}", "fdc5aa50-ee68-4bae-a8e6-b8ae2c258f60", @@ -660,12 +673,12 @@ "raw": "{\r\n \"quantity\": 1\r\n}" }, "url": { - "raw": "{{baseUrl}}//ShopCartItem/{{siteId}}/fdc5aa50-ee68-4bae-a8e6-b8ae2c258f60/SKU-05", + "raw": "{{reverseProxy}}/api/ShopCartItem/{{siteId}}/fdc5aa50-ee68-4bae-a8e6-b8ae2c258f60/SKU-05", "host": [ - "{{baseUrl}}" + "{{reverseProxy}}" ], "path": [ - "", + "api", "ShopCartItem", "{{siteId}}", "fdc5aa50-ee68-4bae-a8e6-b8ae2c258f60", @@ -696,11 +709,12 @@ "raw": "{\r\n \"quantity\": 5\r\n}" }, "url": { - "raw": "{{baseUrl}}/ShopCartItem/{{siteId}}/fdc5aa50-ee68-4bae-a8e6-b8ae2c258f60/SKU-04", + "raw": "{{reverseProxy}}/api/ShopCartItem/{{siteId}}/fdc5aa50-ee68-4bae-a8e6-b8ae2c258f60/SKU-04", "host": [ - "{{baseUrl}}" + "{{reverseProxy}}" ], "path": [ + "api", "ShopCartItem", "{{siteId}}", "fdc5aa50-ee68-4bae-a8e6-b8ae2c258f60", @@ -727,11 +741,12 @@ } ], "url": { - "raw": "{{baseUrl}}/ShopCartItem/{{siteId}}/fdc5aa50-ee68-4bae-a8e6-b8ae2c258f60/SKU-04", + "raw": "{{reverseProxy}}/api/ShopCartItem/{{siteId}}/fdc5aa50-ee68-4bae-a8e6-b8ae2c258f60/SKU-04", "host": [ - "{{baseUrl}}" + "{{reverseProxy}}" ], "path": [ + "api", "ShopCartItem", "{{siteId}}", "fdc5aa50-ee68-4bae-a8e6-b8ae2c258f60", @@ -763,11 +778,12 @@ } ], "url": { - "raw": "{{baseUrl}}/ShopCartItems/{{siteId}}/fdc5aa50-ee68-4bae-a8e6-b8ae2c258f60?locale=en-US", + "raw": "{{reverseProxy}}/api/ShopCartItems/{{siteId}}/fdc5aa50-ee68-4bae-a8e6-b8ae2c258f60?locale=en-US", "host": [ - "{{baseUrl}}" + "{{reverseProxy}}" ], "path": [ + "api", "ShopCartItems", "{{siteId}}", "fdc5aa50-ee68-4bae-a8e6-b8ae2c258f60" @@ -799,11 +815,12 @@ } ], "url": { - "raw": "{{baseUrl}}/ShopCartItems/{{siteId}}/fdc5aa50-ee68-4bae-a8e6-b8ae2c258f60", + "raw": "{{reverseProxy}}/api/ShopCartItems/{{siteId}}/fdc5aa50-ee68-4bae-a8e6-b8ae2c258f60", "host": [ - "{{baseUrl}}" + "{{reverseProxy}}" ], "path": [ + "api", "ShopCartItems", "{{siteId}}", "fdc5aa50-ee68-4bae-a8e6-b8ae2c258f60" @@ -834,11 +851,12 @@ } ], "url": { - "raw": "{{baseUrl}}/BlogItem/{{siteId}}/11f2f5f8-1270-4640-b082-c2e7ea8e60b4", + "raw": "{{reverseProxy}}/api/BlogItem/{{siteId}}/11f2f5f8-1270-4640-b082-c2e7ea8e60b4", "host": [ - "{{baseUrl}}" + "{{reverseProxy}}" ], "path": [ + "api", "BlogItem", "{{siteId}}", "11f2f5f8-1270-4640-b082-c2e7ea8e60b4" @@ -864,11 +882,12 @@ } ], "url": { - "raw": "{{baseUrl}}/BlogItem/{{siteId}}?slug=privacy-terms-and-conditions", + "raw": "{{reverseProxy}}/api/BlogItem/{{siteId}}?slug=privacy-terms-and-conditions", "host": [ - "{{baseUrl}}" + "{{reverseProxy}}" ], "path": [ + "api", "BlogItem", "{{siteId}}" ], @@ -903,11 +922,12 @@ "raw": "{\r\n\r\n \"l10n\": [\r\n {\r\n \"locale\": \"en-US\",\r\n \"slug\": \"hello-world\",\r\n \"description\": \"Hello world description\",\r\n \"title\": \"Hello world title\",\r\n \"shortText\": \"Hello world short text\",\r\n \"text\": \"

Hello World

\",\r\n \"contentType\": \"HTML\",\r\n \"badges\": [\r\n \"post\"\r\n ]\r\n }\r\n ],\r\n \"images\": [\r\n {\r\n \"l10n\": [\r\n {\r\n \"locale\": \"en-US\",\r\n \"alt\": \"...\"\r\n },\r\n {\r\n \"locale\": \"it-IT\",\r\n \"alt\": \"...\"\r\n }\r\n ]\r\n }\r\n ],\r\n \"tags\": [\r\n \"privacy\",\r\n \"terms\"\r\n ],\r\n \"categories\": [\r\n \"e154e33f-3cc7-468d-bb66-e0390ddb9ae0\" \r\n ],\r\n \"familyFriendly\": true\r\n}" }, "url": { - "raw": "{{baseUrl}}/BlogItem/{{siteId}}", + "raw": "{{reverseProxy}}/api/BlogItem/{{siteId}}", "host": [ - "{{baseUrl}}" + "{{reverseProxy}}" ], "path": [ + "api", "BlogItem", "{{siteId}}" ] @@ -936,11 +956,12 @@ "raw": "{\r\n\r\n \"l10n\": [\r\n {\r\n \"locale\": \"en-US\",\r\n \"slug\": \"hello-world\",\r\n \"description\": \"Hello world description\",\r\n \"title\": \"Hello world title\",\r\n \"shortText\": \"Hello world short text\",\r\n \"text\": \"

New Hello World

\",\r\n \"contentType\": \"HTML\",\r\n \"badges\": [\r\n \"post\"\r\n ]\r\n }\r\n ],\r\n \"images\": [\r\n {\r\n \"l10n\": [\r\n {\r\n \"locale\": \"en-US\",\r\n \"alt\": \"...\"\r\n },\r\n {\r\n \"locale\": \"it-IT\",\r\n \"alt\": \"...\"\r\n }\r\n ]\r\n }\r\n ],\r\n \"tags\": [\r\n \"privacy\",\r\n \"terms\"\r\n ],\r\n \"categories\": [\r\n \"e154e33f-3cc7-468d-bb66-e0390ddb9ae0\" \r\n ],\r\n \"familyFriendly\": true\r\n}" }, "url": { - "raw": "{{baseUrl}}/BlogItem/{{siteId}}/94feda90-ddf6-4717-8879-9c7139e7ff30", + "raw": "{{reverseProxy}}/api/BlogItem/{{siteId}}/94feda90-ddf6-4717-8879-9c7139e7ff30", "host": [ - "{{baseUrl}}" + "{{reverseProxy}}" ], "path": [ + "api", "BlogItem", "{{siteId}}", "94feda90-ddf6-4717-8879-9c7139e7ff30" @@ -966,11 +987,12 @@ } ], "url": { - "raw": "{{baseUrl}}/BlogItem/{{siteId}}/94feda90-ddf6-4717-8879-9c7139e7ff30", + "raw": "{{reverseProxy}}/api/BlogItem/{{siteId}}/94feda90-ddf6-4717-8879-9c7139e7ff30", "host": [ - "{{baseUrl}}" + "{{reverseProxy}}" ], "path": [ + "api", "BlogItem", "{{siteId}}", "94feda90-ddf6-4717-8879-9c7139e7ff30" @@ -1001,11 +1023,12 @@ } ], "url": { - "raw": "{{baseUrl}}/BlogItems/{{siteId}}?currentPage=2&itemsPerPage=2", + "raw": "{{reverseProxy}}/api/BlogItems/{{siteId}}?currentPage=2&itemsPerPage=2", "host": [ - "{{baseUrl}}" + "{{reverseProxy}}" ], "path": [ + "api", "BlogItems", "{{siteId}}" ], @@ -1040,11 +1063,12 @@ } ], "url": { - "raw": "{{baseUrl}}/BlogItems/{{siteId}}?currentPage=2&itemsPerPage=2&locale=en-US", + "raw": "{{reverseProxy}}/api/BlogItems/{{siteId}}?currentPage=2&itemsPerPage=2&locale=en-US", "host": [ - "{{baseUrl}}" + "{{reverseProxy}}" ], "path": [ + "api", "BlogItems", "{{siteId}}" ], @@ -1083,11 +1107,12 @@ } ], "url": { - "raw": "{{baseUrl}}/BlogItems/{{siteId}}", + "raw": "{{reverseProxy}}/api/BlogItems/{{siteId}}", "host": [ - "{{baseUrl}}" + "{{reverseProxy}}" ], "path": [ + "api", "BlogItems", "{{siteId}}" ] @@ -1117,15 +1142,16 @@ } ], "url": { - "raw": "{{baseUrl}}/File/{{siteId}}/fdc5aa50-ee68-4bae-a8e6-b8ae2c258f60/4f163ea9-1786-4192-8efa-3b8ea9ca88fa", + "raw": "{{reverseProxy}}/api/File/{{siteId}}/fdc5aa50-ee68-4bae-a8e6-b8ae2c258f60/55ecc564-c086-4e77-a8b2-ef32c2a8c280", "host": [ - "{{baseUrl}}" + "{{reverseProxy}}" ], "path": [ + "api", "File", "{{siteId}}", "fdc5aa50-ee68-4bae-a8e6-b8ae2c258f60", - "4f163ea9-1786-4192-8efa-3b8ea9ca88fa" + "55ecc564-c086-4e77-a8b2-ef32c2a8c280" ] } }, @@ -1158,11 +1184,12 @@ ] }, "url": { - "raw": "{{baseUrl}}/File/{{siteId}}/fdc5aa50-ee68-4bae-a8e6-b8ae2c258f60", + "raw": "{{reverseProxy}}/api/File/{{siteId}}/fdc5aa50-ee68-4bae-a8e6-b8ae2c258f60", "host": [ - "{{baseUrl}}" + "{{reverseProxy}}" ], "path": [ + "api", "File", "{{siteId}}", "fdc5aa50-ee68-4bae-a8e6-b8ae2c258f60" @@ -1188,11 +1215,12 @@ } ], "url": { - "raw": "{{baseUrl}}/File/{{siteId}}/fdc5aa50-ee68-4bae-a8e6-b8ae2c258f60/3930ff55-67e1-4763-be59-37407f91e0a9", + "raw": "{{reverseProxy}}/api/File/{{siteId}}/fdc5aa50-ee68-4bae-a8e6-b8ae2c258f60/3930ff55-67e1-4763-be59-37407f91e0a9", "host": [ - "{{baseUrl}}" + "{{reverseProxy}}" ], "path": [ + "api", "File", "{{siteId}}", "fdc5aa50-ee68-4bae-a8e6-b8ae2c258f60", @@ -1235,11 +1263,12 @@ ] }, "url": { - "raw": "{{baseUrl}}/Files/{{siteId}}/fdc5aa50-ee68-4bae-a8e6-b8ae2c258f60", + "raw": "{{reverseProxy}}/api/Files/{{siteId}}/fdc5aa50-ee68-4bae-a8e6-b8ae2c258f60", "host": [ - "{{baseUrl}}" + "{{reverseProxy}}" ], "path": [ + "api", "Files", "{{siteId}}", "fdc5aa50-ee68-4bae-a8e6-b8ae2c258f60" @@ -1276,11 +1305,12 @@ ] }, "url": { - "raw": "{{baseUrl}}/Files/{{siteId}}/fdc5aa50-ee68-4bae-a8e6-b8ae2c258f60", + "raw": "{{reverseProxy}}/api/Files/{{siteId}}/fdc5aa50-ee68-4bae-a8e6-b8ae2c258f60", "host": [ - "{{baseUrl}}" + "{{reverseProxy}}" ], "path": [ + "api", "Files", "{{siteId}}", "fdc5aa50-ee68-4bae-a8e6-b8ae2c258f60" @@ -1300,11 +1330,12 @@ "method": "GET", "header": [], "url": { - "raw": "{{baseUrl}}/Image/{{siteId}}/450x300/55ecc564-c086-4e77-a8b2-ef32c2a8c280", + "raw": "{{reverseProxy}}/api/Image/{{siteId}}/450x300/55ecc564-c086-4e77-a8b2-ef32c2a8c280", "host": [ - "{{baseUrl}}" + "{{reverseProxy}}" ], "path": [ + "api", "Image", "{{siteId}}", "450x300", @@ -1313,17 +1344,148 @@ } }, "response": [] + }, + { + "name": "01-Get YARP", + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{reverseProxy}}/image/{{siteId}}/450x300/55ecc564-c086-4e77-a8b2-ef32c2a8c280", + "host": [ + "{{reverseProxy}}" + ], + "path": [ + "image", + "{{siteId}}", + "450x300", + "55ecc564-c086-4e77-a8b2-ef32c2a8c280" + ] + } + }, + "response": [] + } + ] + }, + { + "name": "Password", + "item": [ + { + "name": "01-Post", + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "type": "default" + }, + { + "key": "Accept", + "value": "application/json", + "type": "default" + } + ], + "body": { + "mode": "raw", + "raw": "{\r\n \"password\": \"password\"\r\n}" + }, + "url": { + "raw": "{{reverseProxy}}/api/Password/{{siteId}}/fdc5aa50-ee68-4bae-a8e6-b8ae2c258f60", + "host": [ + "{{reverseProxy}}" + ], + "path": [ + "api", + "Password", + "{{siteId}}", + "fdc5aa50-ee68-4bae-a8e6-b8ae2c258f60" + ] + } + }, + "response": [] + } + ] + }, + { + "name": "Authentication", + "item": [ + { + "name": "01-Post", + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "type": "default" + }, + { + "key": "Accept", + "value": "application/json", + "type": "default" + } + ], + "body": { + "mode": "raw", + "raw": "{\r\n \"username\": \"Admin\",\r\n \"password\": \"Password\"\r\n}" + }, + "url": { + "raw": "{{reverseProxy}}/api/Authentication/{{siteId}}", + "host": [ + "{{reverseProxy}}" + ], + "path": [ + "api", + "Authentication", + "{{siteId}}" + ] + } + }, + "response": [] } ] } ], + "auth": { + "type": "bearer", + "bearer": [ + { + "key": "token", + "value": "{{access_token}}", + "type": "string" + } + ] + }, "event": [ { "listen": "prerequest", "script": { "type": "text/javascript", "exec": [ - "" + "const postRequest = {", + " url: pm.collectionVariables.get(\"tokenEndpoint\"),", + " method: \"post\",", + " header: {", + " \"Content-Type\": \"application/json\",", + " \"Accept\": \"application/json\"", + " },", + " body: {", + " mode: \"raw\",", + " raw: {", + " \"username\": \"Admin\",", + " \"password\": \"Password\"", + " },", + " },", + "};", + "", + "pm.sendRequest(postRequest, (error, response) => {", + " if (error) {", + " console.log(error);", + " } else {", + " pm.collectionVariables.set(\"access_token\", response);", + " }", + "});" ] } }, @@ -1339,14 +1501,23 @@ ], "variable": [ { - "key": "baseUrl", - "value": "https://localhost:7151/api", + "key": "reverseProxy", + "value": "https://localhost:7174", "type": "default" }, { "key": "siteId", "value": "404c8232-9048-4519-bfba-6e78dc7005ca", "type": "default" + }, + { + "key": "tokenEndpoint", + "value": "https://localhost:7174/api/Authentication/404c8232-9048-4519-bfba-6e78dc7005ca", + "type": "default" + }, + { + "key": "access_token", + "value": "" } ] } \ No newline at end of file diff --git a/webapi/Core/Abstractions/DomainObjects/PersonBase.cs b/webapi/Core/Abstractions/DomainObjects/PersonBase.cs index 9f47e84..aebfd55 100644 --- a/webapi/Core/Abstractions/DomainObjects/PersonBase.cs +++ b/webapi/Core/Abstractions/DomainObjects/PersonBase.cs @@ -3,6 +3,6 @@ namespace Core.Abstractions.DomainObjects { public abstract class PersonBase : DomainObjectBase { public Guid Id { get; set; } - public MediaAttachment? Image { get; set; } + public Image? Image { get; set; } } } diff --git a/webapi/Core/Abstractions/Models/RequestModelBase.cs b/webapi/Core/Abstractions/Models/RequestModelBase.cs index 6164b60..26f35ee 100644 --- a/webapi/Core/Abstractions/Models/RequestModelBase.cs +++ b/webapi/Core/Abstractions/Models/RequestModelBase.cs @@ -2,6 +2,12 @@ using System.Diagnostics.CodeAnalysis; namespace Core.Abstractions.Models { + + public abstract class RequestModelBase : ModelBase, IValidatableObject { + public abstract IEnumerable Validate(ValidationContext validationContext); + } + + public abstract class RequestModelBase : ModelBase, IValidatableObject { public abstract T ToDomainObject(); public abstract IEnumerable Validate(ValidationContext validationContext); diff --git a/webapi/Core/Abstractions/ServiceBase.cs b/webapi/Core/Abstractions/ServiceBase.cs new file mode 100644 index 0000000..0eda579 --- /dev/null +++ b/webapi/Core/Abstractions/ServiceBase.cs @@ -0,0 +1,19 @@ +using Microsoft.Extensions.Logging; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Core.Abstractions { + public abstract class ServiceBase { + + protected readonly ILogger _logger; + + public ServiceBase( + ILogger logger + ) { + _logger = logger; + } + } +} diff --git a/webapi/Core/Core.csproj b/webapi/Core/Core.csproj index 27ac386..e984ac7 100644 --- a/webapi/Core/Core.csproj +++ b/webapi/Core/Core.csproj @@ -6,4 +6,8 @@ enable + + + + diff --git a/webapi/Core/DomainObjects/Image.cs b/webapi/Core/DomainObjects/Image.cs index d0a640d..01d7ecf 100644 --- a/webapi/Core/DomainObjects/Image.cs +++ b/webapi/Core/DomainObjects/Image.cs @@ -6,15 +6,15 @@ namespace Core.DomainObjects { - public class MediaAttachment : DomainObjectBase { + public class Image : DomainObjectBase { public string Src { get; set; } - public MediaTypes MediaType { get; set; } - public List L10n { get; set; } + + public string Alt { get; set; } public override int GetHashCode() { int hash = 17; hash = hash * 23 + Src.GetHashCode(); - hash = hash * 23 + L10n.GetHashCode(); + hash = hash * 23 + Alt.GetHashCode(); return hash; } } diff --git a/webapi/Core/DomainObjects/MediaAttachment.cs b/webapi/Core/DomainObjects/MediaAttachment.cs new file mode 100644 index 0000000..e3ba881 --- /dev/null +++ b/webapi/Core/DomainObjects/MediaAttachment.cs @@ -0,0 +1,22 @@ +using Core.Abstractions.DomainObjects; +using Core.DomainObjects.L10n; +using Core.Enumerations; + +namespace Core.DomainObjects { + + + + public class MediaAttachment : DomainObjectBase { + public string Src { get; set; } + + public MediaTypes MediaType { get; set; } + public List L10n { get; set; } + + public override int GetHashCode() { + int hash = 17; + hash = hash * 23 + Src.GetHashCode(); + hash = hash * 23 + L10n.GetHashCode(); + return hash; + } + } +} diff --git a/webapi/Core/DomainObjects/PageSections/TitleSection.cs b/webapi/Core/DomainObjects/PageSections/TitleSection.cs index 1601ce8..6e4bd0d 100644 --- a/webapi/Core/DomainObjects/PageSections/TitleSection.cs +++ b/webapi/Core/DomainObjects/PageSections/TitleSection.cs @@ -2,7 +2,7 @@ namespace Core.DomainObjects.PageSections { public class TitleSection : PageSectionBase { - public MediaAttachment? Image { get; set; } + public Image? Image { get; set; } public Link? PrimaryLink { get; set; } public Link? SecondaryLink { get; set; } public string? PostedOnBy { get; set; } diff --git a/webapi/DataProviders/Collections/UserDataProvider.cs b/webapi/DataProviders/Collections/UserDataProvider.cs new file mode 100644 index 0000000..7d3fde6 --- /dev/null +++ b/webapi/DataProviders/Collections/UserDataProvider.cs @@ -0,0 +1,17 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace DataProviders.Collections { + + public interface IUserDataProvider { + + } + + internal class UserDataProvider : IUserDataProvider { + + + } +} diff --git a/webapi/DataProviders/Extensions/ServiceCollectionExtensions.cs b/webapi/DataProviders/Extensions/ServiceCollectionExtensions.cs index b7e5a13..dc1d34a 100644 --- a/webapi/DataProviders/Extensions/ServiceCollectionExtensions.cs +++ b/webapi/DataProviders/Extensions/ServiceCollectionExtensions.cs @@ -26,6 +26,7 @@ namespace DataProviders.Extensions services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); + services.AddSingleton(); #endregion #region Buckets diff --git a/webapi/ReverseProxy/appsettings.json b/webapi/ReverseProxy/appsettings.json index 14b4b49..7eb8d1c 100644 --- a/webapi/ReverseProxy/appsettings.json +++ b/webapi/ReverseProxy/appsettings.json @@ -12,7 +12,22 @@ "route1": { "ClusterId": "cluster1", "Match": { - "Path": "{**catch-all}" + "Path": "api/{**catchall}" + } + }, + "route2": { + "ClusterId": "cluster1", + "Match": { + "Path": "image/{**catchall}" + }, + "Transforms": [ + { "PathPattern": "/api/Image/{**catchall}" } + ] + }, + "route3": { + "ClusterId": "cluster2", + "Match": { + "Path": "{**catchall}" } } }, @@ -20,7 +35,14 @@ "cluster1": { "Destinations": { "destination1": { - "Address": "https://example.com/" + "Address": "https://localhost:7151/" + } + } + }, + "cluster2": { + "Destinations": { + "destination1": { + "Address": "http://localhost:3000/" } } } diff --git a/webapi/Services/HashService/Extensions/ServiceCollectionExtensions.cs b/webapi/Services/HashService/Extensions/ServiceCollectionExtensions.cs new file mode 100644 index 0000000..540cdbb --- /dev/null +++ b/webapi/Services/HashService/Extensions/ServiceCollectionExtensions.cs @@ -0,0 +1,11 @@ +using Microsoft.Extensions.DependencyInjection; + +namespace HashService.Extensions { + public static class ServiceCollectionExtensions { + + public static void RegisterHashService(this IServiceCollection services) { + + services.AddSingleton(); + } + } +} diff --git a/webapi/Services/HashService/HashService.cs b/webapi/Services/HashService/HashService.cs index 9f21b2a..87afdee 100644 --- a/webapi/Services/HashService/HashService.cs +++ b/webapi/Services/HashService/HashService.cs @@ -2,7 +2,7 @@ using System.Security.Cryptography; using Microsoft.AspNetCore.Cryptography.KeyDerivation; -namespace Services { +namespace HashService { public interface IHashService { (string, string) CreateSaltedHash(string value); @@ -35,6 +35,7 @@ namespace Services { return (salt, hash); } - public bool ValidateHash(string value, string salt, string hash) => CreateHash(value, salt) == hash; + public bool ValidateHash(string value, string salt, string hash) => + CreateHash(value, salt) == hash; } } diff --git a/webapi/Services/HashService/HashService.csproj b/webapi/Services/HashService/HashService.csproj index 0a6de5f..f69d928 100644 --- a/webapi/Services/HashService/HashService.csproj +++ b/webapi/Services/HashService/HashService.csproj @@ -1,4 +1,4 @@ - + net6.0 @@ -7,7 +7,12 @@ - - + + + + + + + diff --git a/webapi/Services/JWTService/Extensions/ServiceCollectionExtensions.cs b/webapi/Services/JWTService/Extensions/ServiceCollectionExtensions.cs new file mode 100644 index 0000000..0eb0447 --- /dev/null +++ b/webapi/Services/JWTService/Extensions/ServiceCollectionExtensions.cs @@ -0,0 +1,14 @@ +using Microsoft.Extensions.DependencyInjection; + +namespace JWTService.Extensions { + public static class ServiceCollectionExtensions { + public static void RegisterJWTService(this IServiceCollection services, IJWTServiceConfig appSettings) { + var config = appSettings.JwtConfig; + + if(config == null) throw new NullReferenceException(); + + services.AddSingleton(x => config); + services.AddSingleton(); + } + } +} diff --git a/webapi/Services/JWTService/IJWTServiceConfig.cs b/webapi/Services/JWTService/IJWTServiceConfig.cs new file mode 100644 index 0000000..2ccee90 --- /dev/null +++ b/webapi/Services/JWTService/IJWTServiceConfig.cs @@ -0,0 +1,17 @@ +using System.IO; + +namespace JWTService { + public interface IJWTServiceConfig { + public JwtConfig? JwtConfig { get; set; } + } + + public interface IJwtConfig { + public string? Secret { get; set; } + public double? Expires { get; set; } + } + + public class JwtConfig : IJwtConfig { + public string? Secret { get; set; } + public double? Expires { get; set; } + } +} diff --git a/webapi/Services/JWTService/IJWTServiceConfiguration.cs b/webapi/Services/JWTService/IJWTServiceConfiguration.cs deleted file mode 100644 index 1d4376c..0000000 --- a/webapi/Services/JWTService/IJWTServiceConfiguration.cs +++ /dev/null @@ -1,7 +0,0 @@ -using System.IO; - -namespace Services { - public interface IJwtServiceSettings { - string Secret { get; set; } - } -} diff --git a/webapi/Services/JWTService/JWTService.cs b/webapi/Services/JWTService/JWTService.cs index 8e0ccb7..b6099db 100644 --- a/webapi/Services/JWTService/JWTService.cs +++ b/webapi/Services/JWTService/JWTService.cs @@ -1,51 +1,87 @@ using System.IdentityModel.Tokens.Jwt; using System.Security.Claims; - - +using Microsoft.Extensions.Logging; using Microsoft.IdentityModel.Tokens; -namespace Services { +namespace JWTService { - public interface IJwtService { - string CreateJwtToken(IEnumerable issuer, DateTime expires, string userId, string userEmail, string userName, IEnumerable userRoles); + public interface IJWTService { + string CreateJwtToken(); JwtSecurityToken ReadJwtToken(string token); } - public class JwtService : IJwtService { - private readonly JwtSecurityTokenHandler _tokenHandler; - private readonly IJwtServiceSettings _serviceSettings; + public class JWTService : IJWTService { - public JwtService(IJwtServiceSettings serviceSettings) { - _serviceSettings = serviceSettings; + private readonly ILogger _logger; + + private readonly JwtSecurityTokenHandler _tokenHandler; + private readonly IJwtConfig _serviceConfig; + + /// + /// + /// + /// + public JWTService( + ILogger logger, + IJwtConfig serviceConfig + + ) { + _logger = logger; + _serviceConfig = serviceConfig; _tokenHandler = new JwtSecurityTokenHandler(); } - public string CreateJwtToken(IEnumerable issuer, DateTime expires, string userId, string userEmail, string userName, IEnumerable userRoles) { - var key = Convert.FromBase64String(_serviceSettings.Secret); + public string? CreateJwtToken() { + if (_serviceConfig.Secret == null) + return null; + + if (_serviceConfig.Expires == null) + return null; + + + var key = Convert.FromBase64String(_serviceConfig.Secret); // add roles to claims identity from database - var claims = new List() { - new Claim(ClaimTypes.Actor, userId), - new Claim(ClaimTypes.Email, userEmail), - new Claim(ClaimTypes.NameIdentifier, userName), - // new Claim(ClaimTypes.Webpage, issuer) - }; + var claims = new List() {}; - foreach (var role in userRoles) - claims.Add(new Claim(ClaimTypes.Role, role)); - - foreach (var iss in issuer) - claims.Add(new Claim(ClaimTypes.Webpage, iss)); var token = _tokenHandler.CreateToken(new SecurityTokenDescriptor { IssuedAt = DateTime.UtcNow, Subject = new ClaimsIdentity(claims), - Expires = expires, + Expires = DateTime.UtcNow.AddDays(_serviceConfig.Expires.Value), SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha512Signature), }); return _tokenHandler.WriteToken(token); } + + //public string CreateJwtToken(IEnumerable issuer, DateTime expires, string userId, string userEmail, string userName, IEnumerable userRoles) { + // var key = Convert.FromBase64String(_serviceConfig.Secret); + + // // add roles to claims identity from database + // var claims = new List() { + // new Claim(ClaimTypes.Actor, userId), + // new Claim(ClaimTypes.Email, userEmail), + // new Claim(ClaimTypes.NameIdentifier, userName), + // // new Claim(ClaimTypes.Webpage, issuer) + // }; + + // foreach (var role in userRoles) + // claims.Add(new Claim(ClaimTypes.Role, role)); + + // foreach (var iss in issuer) + // claims.Add(new Claim(ClaimTypes.Webpage, iss)); + + // var token = _tokenHandler.CreateToken(new SecurityTokenDescriptor { + // IssuedAt = DateTime.UtcNow, + // Subject = new ClaimsIdentity(claims), + // Expires = expires, + // SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha512Signature), + // }); + + // return _tokenHandler.WriteToken(token); + //} + public JwtSecurityToken ReadJwtToken(string token) => _tokenHandler.ReadJwtToken(token); } } diff --git a/webapi/Services/JWTService/JWTService.csproj b/webapi/Services/JWTService/JWTService.csproj index 9b54a3d..26e8c73 100644 --- a/webapi/Services/JWTService/JWTService.csproj +++ b/webapi/Services/JWTService/JWTService.csproj @@ -1,4 +1,4 @@ - + net6.0 @@ -7,6 +7,9 @@ + + + diff --git a/webapi/WeatherForecast/Configuration.cs b/webapi/WeatherForecast/Configuration.cs index ea8dace..2ebf90b 100644 --- a/webapi/WeatherForecast/Configuration.cs +++ b/webapi/WeatherForecast/Configuration.cs @@ -1,20 +1,22 @@ using DataProviders; +using JWTService; namespace WeatherForecast { /// /// /// - public class Configuration : IDataProvidersConfig{ + public class Configuration : IDataProvidersConfig, IJWTServiceConfig { /// /// /// - public string? Secret { get; set; } + public JwtConfig? JwtConfig { get; set; } /// /// /// public Database? Database { get; set; } + } } diff --git a/webapi/WeatherForecast/Controllers/AuthenticationController.cs b/webapi/WeatherForecast/Controllers/AuthenticationController.cs new file mode 100644 index 0000000..e0afe63 --- /dev/null +++ b/webapi/WeatherForecast/Controllers/AuthenticationController.cs @@ -0,0 +1,43 @@ + +using DomainResults.Mvc; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Mvc; + +using WeatherForecast.Models.Requests; +using WeatherForecast.Services; + +namespace WeatherForecast.Controllers { + + /// + /// + /// + [AllowAnonymous] + [ApiController] + [Route("api/[controller]")] + public class AuthenticationController : ControllerBase { + + private readonly IAuthenticationService _authenticationService; + + /// + /// + /// + /// + public AuthenticationController( + IAuthenticationService authenticationService + ) { + _authenticationService = authenticationService; + } + + /// + /// + /// + /// + /// + /// + [HttpPost("{siteId}")] + public IActionResult Post([FromRoute] Guid siteId, [FromBody] AuthenticationRequestModel requestData) { + var result = _authenticationService.Post(siteId, requestData); + return result.ToActionResult(); + } + } +} diff --git a/webapi/WeatherForecast/Controllers/BlogItemController.cs b/webapi/WeatherForecast/Controllers/BlogItemController.cs index fad234d..efa94ea 100644 --- a/webapi/WeatherForecast/Controllers/BlogItemController.cs +++ b/webapi/WeatherForecast/Controllers/BlogItemController.cs @@ -12,7 +12,7 @@ namespace WeatherForecast.Controllers { /// /// /// - [AllowAnonymous] + [Authorize] [ApiController] [Route("api/[controller]")] public class BlogItemController : ControllerBase { diff --git a/webapi/WeatherForecast/Controllers/BlogItemsController.cs b/webapi/WeatherForecast/Controllers/BlogItemsController.cs index 6230e07..3b0751f 100644 --- a/webapi/WeatherForecast/Controllers/BlogItemsController.cs +++ b/webapi/WeatherForecast/Controllers/BlogItemsController.cs @@ -48,6 +48,7 @@ public class BlogItemsController : ControllerBase { /// /// /// + [Authorize] [HttpDelete("{siteId}")] public IActionResult Delete([FromRoute] Guid siteId) { var result = _blogItemsService.Delete(siteId); diff --git a/webapi/WeatherForecast/Controllers/CategoryItemController.cs b/webapi/WeatherForecast/Controllers/CategoryItemController.cs index a0efb1f..5f52e89 100644 --- a/webapi/WeatherForecast/Controllers/CategoryItemController.cs +++ b/webapi/WeatherForecast/Controllers/CategoryItemController.cs @@ -11,7 +11,7 @@ namespace WeatherForecast.Controllers { /// /// /// - [AllowAnonymous] + [Authorize] [ApiController] [Route("api/[controller]")] public class CategoryItemController : ControllerBase { @@ -56,7 +56,7 @@ namespace WeatherForecast.Controllers { /// /// /// - /// + [AllowAnonymous] [HttpGet("{siteId}")] public IActionResult GetSlug([FromRoute] Guid siteId, [FromQuery] string slug) { var result = _categoryItemService.GetSlug(siteId, slug); diff --git a/webapi/WeatherForecast/Controllers/CategoryItemsController.cs b/webapi/WeatherForecast/Controllers/CategoryItemsController.cs index 96270b8..5dcd939 100644 --- a/webapi/WeatherForecast/Controllers/CategoryItemsController.cs +++ b/webapi/WeatherForecast/Controllers/CategoryItemsController.cs @@ -10,7 +10,7 @@ namespace WeatherForecast.Controllers { /// /// /// - [AllowAnonymous] + [Authorize] [ApiController] [Route("api/[controller]")] public class CategoryItemsController : ControllerBase { @@ -44,6 +44,7 @@ namespace WeatherForecast.Controllers { /// /// /// + [AllowAnonymous] [HttpDelete("{siteId}")] public IActionResult Delete([FromRoute] Guid siteId) { var result = _categoryItemsService.Delete(siteId); diff --git a/webapi/WeatherForecast/Controllers/FileController.cs b/webapi/WeatherForecast/Controllers/FileController.cs index 79c5343..a85ea4d 100644 --- a/webapi/WeatherForecast/Controllers/FileController.cs +++ b/webapi/WeatherForecast/Controllers/FileController.cs @@ -9,7 +9,7 @@ namespace WeatherForecast.Controllers { /// /// /// - [ApiController] + [Authorize] [AllowAnonymous] [Route("api/[controller]")] public class FileController : Controller { diff --git a/webapi/WeatherForecast/Controllers/FilesController.cs b/webapi/WeatherForecast/Controllers/FilesController.cs index e473552..bda1d78 100644 --- a/webapi/WeatherForecast/Controllers/FilesController.cs +++ b/webapi/WeatherForecast/Controllers/FilesController.cs @@ -8,7 +8,7 @@ namespace WeatherForecast.Controllers { /// /// /// - [ApiController] + [Authorize] [AllowAnonymous] [Route("api/[controller]")] public class FilesController : Controller { diff --git a/webapi/WeatherForecast/Controllers/LoginController.cs b/webapi/WeatherForecast/Controllers/LoginController.cs deleted file mode 100644 index a76ea2b..0000000 --- a/webapi/WeatherForecast/Controllers/LoginController.cs +++ /dev/null @@ -1,31 +0,0 @@ -using Core.Abstractions.Models; -using Microsoft.AspNetCore.Mvc; - -using WeatherForecast.Models; - -namespace WeatherForecast.Controllers { - -//public class PostLoginRequest : RequestModelBase { -// public string Username { get; set; } -// public string Password { get; set; } - -//} - - -//[ApiController] -//[Route("[controller]")] -//public class LoginController : ControllerBase { - -// private readonly ILogger _logger; - -// public LoginController(ILogger logger) { -// _logger = logger; -// } - -// [HttpPost(Name = "Login")] -// public IActionResult Post([FromBody] PostLoginRequest requestBody) { -// return BadRequest(); -// } - - -} diff --git a/webapi/WeatherForecast/Controllers/PasswordController.cs b/webapi/WeatherForecast/Controllers/PasswordController.cs new file mode 100644 index 0000000..72153d5 --- /dev/null +++ b/webapi/WeatherForecast/Controllers/PasswordController.cs @@ -0,0 +1,38 @@ +using DomainResults.Mvc; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using WeatherForecast.Models.Requests; +using WeatherForecast.Services; + +namespace WeatherForecast.Controllers { + /// + /// + /// + [Authorize] + [Route("api/[controller]")] + [ApiController] + public class PasswordController : ControllerBase { + + private readonly IPasswordService _passwordService; + + public PasswordController( + IPasswordService passwordService + ) { + _passwordService = passwordService; + } + + /// + /// + /// + /// + /// + /// + /// + [HttpPost("{siteId}/{userId}")] + public IActionResult Post([FromRoute] Guid siteId, [FromRoute] Guid userId, [FromBody] PasswordRequestModel requestData) { + var result = _passwordService.Post(siteId, userId, requestData); + return result.ToActionResult(); + } + } +} diff --git a/webapi/WeatherForecast/Controllers/ShopCartItemController.cs b/webapi/WeatherForecast/Controllers/ShopCartItemController.cs index dd0ac2d..caa1ae5 100644 --- a/webapi/WeatherForecast/Controllers/ShopCartItemController.cs +++ b/webapi/WeatherForecast/Controllers/ShopCartItemController.cs @@ -12,7 +12,7 @@ namespace WeatherForecast.Controllers { /// /// /// - [ApiController] + [Authorize] [AllowAnonymous] [Route("api/[controller]")] public class ShopCartItemController : ControllerBase { diff --git a/webapi/WeatherForecast/Controllers/ShopCartItemsController.cs b/webapi/WeatherForecast/Controllers/ShopCartItemsController.cs index 0e84366..b467e70 100644 --- a/webapi/WeatherForecast/Controllers/ShopCartItemsController.cs +++ b/webapi/WeatherForecast/Controllers/ShopCartItemsController.cs @@ -11,7 +11,7 @@ namespace WeatherForecast.Controllers { /// /// /// - [ApiController] + [Authorize] [AllowAnonymous] [Route("api/[controller]")] public class ShopCartItemsController : ControllerBase { diff --git a/webapi/WeatherForecast/Controllers/ShopItemController.cs b/webapi/WeatherForecast/Controllers/ShopItemController.cs index 01de26b..0f61c11 100644 --- a/webapi/WeatherForecast/Controllers/ShopItemController.cs +++ b/webapi/WeatherForecast/Controllers/ShopItemController.cs @@ -11,7 +11,7 @@ namespace WeatherForecast.Controllers { /// /// /// - [AllowAnonymous] + [Authorize] [ApiController] [Route("api/[controller]")] public class ShopItemController : ControllerBase { @@ -59,6 +59,7 @@ namespace WeatherForecast.Controllers { /// /// /// + [AllowAnonymous] [HttpGet("{siteId}")] public IActionResult GetSlug([FromRoute] Guid siteId, [FromQuery] string slug) { var result = _shopItemService.GetSlug(siteId, slug); diff --git a/webapi/WeatherForecast/Controllers/ShopItemsController.cs b/webapi/WeatherForecast/Controllers/ShopItemsController.cs index b89a615..db9cccc 100644 --- a/webapi/WeatherForecast/Controllers/ShopItemsController.cs +++ b/webapi/WeatherForecast/Controllers/ShopItemsController.cs @@ -5,52 +5,53 @@ using DomainResults.Mvc; using WeatherForecast.Services; -namespace WeatherForecast.Controllers; - -/// -/// -/// -[AllowAnonymous] -[ApiController] -[Route("api/[controller]")] -public class ShopItemsController : ControllerBase { - - private readonly IShopItemsService _shopItemsService; +namespace WeatherForecast.Controllers { /// /// /// - /// - public ShopItemsController( - IShopItemsService shopCatalogService - ) { - _shopItemsService = shopCatalogService; - } + [Authorize] + [ApiController] + [Route("api/[controller]")] + public class ShopItemsController : ControllerBase { - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - [HttpGet("{siteId}")] - public IActionResult Get([FromRoute] Guid siteId, [FromQuery] Guid? category, [FromQuery] int? currentPage, [FromQuery] int? itemsPerPage, [FromQuery] string? locale, [FromQuery] string? searchText) { - var result = _shopItemsService.Get(siteId, category, currentPage ?? 1, itemsPerPage ?? 8, locale, searchText); - return result.ToActionResult(); - } + private readonly IShopItemsService _shopItemsService; - /// - /// - /// - /// - /// - [HttpDelete("{siteId}")] - public IActionResult Delete([FromRoute] Guid siteId) { - var result = _shopItemsService.Delete(siteId); - return result.ToActionResult(); + /// + /// + /// + /// + public ShopItemsController( + IShopItemsService shopCatalogService + ) { + _shopItemsService = shopCatalogService; + } + + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + [HttpGet("{siteId}")] + public IActionResult Get([FromRoute] Guid siteId, [FromQuery] Guid? category, [FromQuery] int? currentPage, [FromQuery] int? itemsPerPage, [FromQuery] string? locale, [FromQuery] string? searchText) { + var result = _shopItemsService.Get(siteId, category, currentPage ?? 1, itemsPerPage ?? 8, locale, searchText); + return result.ToActionResult(); + } + + /// + /// + /// + /// + /// + [HttpDelete("{siteId}")] + public IActionResult Delete([FromRoute] Guid siteId) { + var result = _shopItemsService.Delete(siteId); + return result.ToActionResult(); + } } -} +} \ No newline at end of file diff --git a/webapi/WeatherForecast/Controllers/WeatherForecastController.cs b/webapi/WeatherForecast/Controllers/WeatherForecastController.cs index e74f658..4167175 100644 --- a/webapi/WeatherForecast/Controllers/WeatherForecastController.cs +++ b/webapi/WeatherForecast/Controllers/WeatherForecastController.cs @@ -1,3 +1,4 @@ +using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using WeatherForecast.Models.Responses; @@ -7,6 +8,7 @@ namespace WeatherForecast.Controllers; /// /// /// +[AllowAnonymous] [ApiController] [Route("[controller]")] public class WeatherForecastController : ControllerBase { diff --git a/webapi/WeatherForecast/Models/Requests/AuthenticationRequestModel.cs b/webapi/WeatherForecast/Models/Requests/AuthenticationRequestModel.cs new file mode 100644 index 0000000..684b270 --- /dev/null +++ b/webapi/WeatherForecast/Models/Requests/AuthenticationRequestModel.cs @@ -0,0 +1,36 @@ +using Core.Abstractions.Models; +using Core.Enumerations; +using System.ComponentModel.DataAnnotations; + +namespace WeatherForecast.Models.Requests { + + /// + /// + /// + public class AuthenticationRequestModel : RequestModelBase { + + /// + /// + /// + public string? Username { get; set; } + + /// + /// + /// + public string? Password { get; set; } + + /// + /// + /// + /// + /// + public override IEnumerable Validate(ValidationContext validationContext) { + if(string.IsNullOrWhiteSpace(Username)) + yield return new ValidationResult($"{nameof(Username)} ${Errors.NullOrEmpty}"); + + if (string.IsNullOrWhiteSpace(Password)) + yield return new ValidationResult($"{nameof(Password)} ${Errors.NullOrEmpty}"); + } + } +} + diff --git a/webapi/WeatherForecast/Models/Requests/PasswordRequestModel.cs b/webapi/WeatherForecast/Models/Requests/PasswordRequestModel.cs new file mode 100644 index 0000000..99fbc5d --- /dev/null +++ b/webapi/WeatherForecast/Models/Requests/PasswordRequestModel.cs @@ -0,0 +1,27 @@ +using Core.Abstractions.Models; +using Core.Enumerations; +using System.ComponentModel.DataAnnotations; + +namespace WeatherForecast.Models.Requests { + + /// + /// + /// + public class PasswordRequestModel : RequestModelBase { + + /// + /// + /// + public string? Password { get; set; } + + /// + /// + /// + /// + /// + public override IEnumerable Validate(ValidationContext validationContext) { + if (string.IsNullOrWhiteSpace(Password)) + yield return new ValidationResult($"{nameof(Password)} ${Errors.NullOrEmpty}"); + } + } +} diff --git a/webapi/WeatherForecast/Program.cs b/webapi/WeatherForecast/Program.cs index f3e6bf3..835f2d6 100644 --- a/webapi/WeatherForecast/Program.cs +++ b/webapi/WeatherForecast/Program.cs @@ -1,4 +1,5 @@ using Serilog; +using Serilog.Enrichers.Span; namespace WeatherForecast { @@ -24,7 +25,8 @@ namespace WeatherForecast { Host.CreateDefaultBuilder(args) .UseSerilog((hostContext, services, configuration) => { configuration.ReadFrom.Configuration(hostContext.Configuration) - .Enrich.FromLogContext(); + .Enrich.FromLogContext() + .Enrich.WithSpan(); }) .ConfigureWebHostDefaults(webBuilder => { webBuilder.UseStartup(); diff --git a/webapi/WeatherForecast/Services/Abstractions/PostItemServiceBase.cs b/webapi/WeatherForecast/Services/Abstractions/PostItemServiceBase.cs index 192cf63..d12df22 100644 --- a/webapi/WeatherForecast/Services/Abstractions/PostItemServiceBase.cs +++ b/webapi/WeatherForecast/Services/Abstractions/PostItemServiceBase.cs @@ -1,4 +1,5 @@ -using DataProviders.Collections; +using Core.Abstractions; +using DataProviders.Collections; using DomainResults.Common; namespace WeatherForecast.Services.Abstractions { @@ -6,7 +7,7 @@ namespace WeatherForecast.Services.Abstractions { /// /// /// - public abstract class PostItemServiceBase { + public abstract class PostItemServiceBase : ServiceBase { /// /// @@ -16,10 +17,12 @@ namespace WeatherForecast.Services.Abstractions { /// /// /// + /// /// public PostItemServiceBase( + ILogger logger, ICategoryDataProvider categoryDataProvider - ) { + ) : base(logger) { _categoryDataProvider = categoryDataProvider; } diff --git a/webapi/WeatherForecast/Services/AutheticationService.cs b/webapi/WeatherForecast/Services/AutheticationService.cs new file mode 100644 index 0000000..866c617 --- /dev/null +++ b/webapi/WeatherForecast/Services/AutheticationService.cs @@ -0,0 +1,66 @@ +using Core.Abstractions; +using DataProviders.Collections; +using DomainResults.Common; +using JWTService; +using WeatherForecast.Models.Requests; + +namespace WeatherForecast.Services { + + /// + /// + /// + public interface IAuthenticationService { + + /// + /// + /// + /// + /// + /// + (string?, IDomainResult) Post(Guid siteId, AuthenticationRequestModel requestData); + } + + /// + /// + /// + public class AutheticationService : ServiceBase, IAuthenticationService { + + private readonly IUserDataProvider _userDataProvider; + private readonly IJWTService _jwtService; + + /// + /// + /// + /// + /// + /// + public AutheticationService ( + ILogger logger, + IUserDataProvider userDataProvider, + IJWTService jwtService + ) : base(logger) { + _userDataProvider = userDataProvider; + _jwtService = jwtService; + } + + /// + /// + /// + /// + /// + /// + public (string?, IDomainResult) Post (Guid siteId, AuthenticationRequestModel requestData) { + try { + var token = _jwtService.CreateJwtToken(); + + return token != null + ? IDomainResult.Success(token) + : IDomainResult.Failed(); + } + catch (Exception ex) { + _logger.LogError("Unhandled exception", ex); + return IDomainResult.Failed(); + } + } + } +} diff --git a/webapi/WeatherForecast/Services/BlogItemService.cs b/webapi/WeatherForecast/Services/BlogItemService.cs index ed4f743..bc56497 100644 --- a/webapi/WeatherForecast/Services/BlogItemService.cs +++ b/webapi/WeatherForecast/Services/BlogItemService.cs @@ -1,16 +1,11 @@ using DomainResults.Common; -using ExtensionMethods; -using DataProviders; - -using Core.DomainObjects; -using Core.DomainObjects.Documents; -using Core.DomainObjects.L10n; using Core.Enumerations; +using ExtensionMethods; +using DataProviders.Collections; using WeatherForecast.Models.Requests; using WeatherForecast.Models.Responses; -using DataProviders.Collections; using WeatherForecast.Services.Abstractions; namespace WeatherForecast.Services { @@ -64,8 +59,8 @@ namespace WeatherForecast.Services { /// /// /// - public class BlogItemService : PostItemServiceBase, IBlogItemService { - private readonly ILogger _logger; + public class BlogItemService : PostItemServiceBase, IBlogItemService { + private readonly IBlogCatalogDataProvider _blogCatalogDataProvider; /// @@ -78,8 +73,7 @@ namespace WeatherForecast.Services { ILogger logger, IBlogCatalogDataProvider blogCatalogDataProvider, ICategoryDataProvider categoryDataProvider - ) : base(categoryDataProvider) { - _logger = logger; + ) : base(logger, categoryDataProvider) { _blogCatalogDataProvider = blogCatalogDataProvider; } diff --git a/webapi/WeatherForecast/Services/BlogItemsService.cs b/webapi/WeatherForecast/Services/BlogItemsService.cs index fde97cc..96b1750 100644 --- a/webapi/WeatherForecast/Services/BlogItemsService.cs +++ b/webapi/WeatherForecast/Services/BlogItemsService.cs @@ -1,14 +1,10 @@ using DomainResults.Common; -using DataProviders; - using Core.Abstractions; -using Core.DomainObjects; using Core.Enumerations; +using DataProviders.Collections; using WeatherForecast.Models.Responses; -using DataProviders.Collections; -using Core.DomainObjects.Documents; namespace WeatherForecast.Services { @@ -40,9 +36,8 @@ namespace WeatherForecast.Services { /// /// /// - public class BlogItemsService : IBlogItemsService { + public class BlogItemsService : ServiceBase, IBlogItemsService { - private readonly ILogger _logger; private readonly IBlogCatalogDataProvider _blogCatalogDataProvider; private readonly ICategoryDataProvider _categoryDataProvider; @@ -56,8 +51,7 @@ namespace WeatherForecast.Services { ILogger logger, IBlogCatalogDataProvider blogCatalogDataProvider, ICategoryDataProvider categoryDataProvider - ) { - _logger = logger; + ) : base(logger) { _blogCatalogDataProvider = blogCatalogDataProvider; _categoryDataProvider = categoryDataProvider; } diff --git a/webapi/WeatherForecast/Services/CategoryItemService.cs b/webapi/WeatherForecast/Services/CategoryItemService.cs index 5bf4ed8..6dab5db 100644 --- a/webapi/WeatherForecast/Services/CategoryItemService.cs +++ b/webapi/WeatherForecast/Services/CategoryItemService.cs @@ -1,12 +1,12 @@ using DomainResults.Common; -using DataProviders; +using DataProviders.Collections; using Core.Enumerations; using WeatherForecast.Models.Requests; using WeatherForecast.Models.Responses; -using DataProviders.Collections; +using Core.Abstractions; namespace WeatherForecast.Services { @@ -60,9 +60,8 @@ namespace WeatherForecast.Services { /// /// /// - public class CategoryItemService : ICategoryItemService { + public class CategoryItemService : ServiceBase, ICategoryItemService { - private readonly ILogger _logger; private readonly ICategoryDataProvider _categoryDataProvider; /// @@ -73,8 +72,7 @@ namespace WeatherForecast.Services { public CategoryItemService( ILogger logger, ICategoryDataProvider categoryDataProvider - ) { - _logger = logger; + ) : base(logger) { _categoryDataProvider = categoryDataProvider; } diff --git a/webapi/WeatherForecast/Services/CategoryItemsService.cs b/webapi/WeatherForecast/Services/CategoryItemsService.cs index 393de15..bb18750 100644 --- a/webapi/WeatherForecast/Services/CategoryItemsService.cs +++ b/webapi/WeatherForecast/Services/CategoryItemsService.cs @@ -1,12 +1,12 @@ using DomainResults.Common; -using DataProviders; +using DataProviders.Collections; using Core.Abstractions; using Core.Enumerations; using WeatherForecast.Models.Responses; -using DataProviders.Collections; + namespace WeatherForecast.Services { @@ -34,9 +34,8 @@ namespace WeatherForecast.Services { /// /// /// - public class CategoryItemsService : ICategoryItemsService { + public class CategoryItemsService : ServiceBase, ICategoryItemsService { - private readonly ILogger _logger; private readonly ICategoryDataProvider _categoryDataProvider; /// @@ -47,8 +46,7 @@ namespace WeatherForecast.Services { public CategoryItemsService( ILogger logger, ICategoryDataProvider categoryDataProvider - ) { - _logger = logger; + ) : base(logger) { _categoryDataProvider = categoryDataProvider; } diff --git a/webapi/WeatherForecast/Services/ContentService.cs b/webapi/WeatherForecast/Services/ContentService.cs index b138718..cca8425 100644 --- a/webapi/WeatherForecast/Services/ContentService.cs +++ b/webapi/WeatherForecast/Services/ContentService.cs @@ -3,6 +3,7 @@ using DataProviders.Collections; using WeatherForecast.Models.Responses; +using Core.Abstractions; namespace WeatherForecast.Services { @@ -23,9 +24,8 @@ namespace WeatherForecast.Services { /// /// /// - public class ContentService : IContentService { + public class ContentService : ServiceBase, IContentService { - private readonly ILogger _logger; private readonly IContentDataProvider _contentDataProvider; /// @@ -36,8 +36,7 @@ namespace WeatherForecast.Services { public ContentService( ILogger logger, IContentDataProvider contentDataprovider - ) { - _logger = logger; + ) : base(logger) { _contentDataProvider = contentDataprovider; } diff --git a/webapi/WeatherForecast/Services/FileService.cs b/webapi/WeatherForecast/Services/FileService.cs index 8e4da78..127cf37 100644 --- a/webapi/WeatherForecast/Services/FileService.cs +++ b/webapi/WeatherForecast/Services/FileService.cs @@ -1,6 +1,8 @@ -using DataProviders; +using DomainResults.Common; + +using DataProviders; using DataProviders.Buckets; -using DomainResults.Common; +using Core.Abstractions; namespace WeatherForecast.Services { @@ -40,9 +42,8 @@ namespace WeatherForecast.Services { /// /// /// - public class FileService : IFileService { + public class FileService : ServiceBase, IFileService { - private readonly ILogger _logger; private readonly IFilesService _filesService; private readonly IImageBucketDataProvider _imageBucketDataProvider; @@ -53,11 +54,10 @@ namespace WeatherForecast.Services { /// /// public FileService( - ILogger logger, + ILogger logger, IFilesService filesService, IImageBucketDataProvider imageBucketDataProvider - ) { - _logger = logger; + ) : base(logger) { _filesService = filesService; _imageBucketDataProvider = imageBucketDataProvider; } diff --git a/webapi/WeatherForecast/Services/FilesService.cs b/webapi/WeatherForecast/Services/FilesService.cs index e3cb55b..062c662 100644 --- a/webapi/WeatherForecast/Services/FilesService.cs +++ b/webapi/WeatherForecast/Services/FilesService.cs @@ -1,7 +1,10 @@ -using DataProviders; +using DomainResults.Common; + +using DataProviders; using DataProviders.Buckets; -using DomainResults.Common; + using FileSecurityService; +using Core.Abstractions; namespace WeatherForecast.Services { @@ -31,9 +34,8 @@ namespace WeatherForecast.Services { /// /// /// - public class FilesService : IFilesService { + public class FilesService : ServiceBase, IFilesService { - private readonly ILogger _logger; private readonly IFileSecurityService _fileSecurityService; private readonly IImageBucketDataProvider _imageBucketDataProvider; @@ -46,8 +48,7 @@ namespace WeatherForecast.Services { ILogger logger, IFileSecurityService fileSecurityService, IImageBucketDataProvider imageBucketDataProvider - ) { - _logger = logger; + ) : base(logger) { _fileSecurityService = fileSecurityService; _imageBucketDataProvider = imageBucketDataProvider; } diff --git a/webapi/WeatherForecast/Services/ImageService.cs b/webapi/WeatherForecast/Services/ImageService.cs index b331401..9973cd3 100644 --- a/webapi/WeatherForecast/Services/ImageService.cs +++ b/webapi/WeatherForecast/Services/ImageService.cs @@ -1,10 +1,12 @@ - +using DomainResults.Common; + using DataProviders; using DataProviders.Buckets; using DataProviders.Collections; -using DomainResults.Common; + using ImageProvider; using ImageProvider.Fonts; +using Core.Abstractions; namespace WeatherForecast.Services { @@ -26,9 +28,8 @@ namespace WeatherForecast.Services { /// /// /// - public class ImageService : IImageService { + public class ImageService : ServiceBase, IImageService { - private readonly ILogger _logger; private readonly IImageBucketDataProvider _imageBucketDataProvider; private readonly IImageProvider _imageProvider; private readonly IContentDataProvider _contentDataProvider; @@ -44,9 +45,7 @@ namespace WeatherForecast.Services { IImageBucketDataProvider imageBucketDataProvider, IImageProvider imageProvider, IContentDataProvider contentDataProvider - - ) { - _logger = logger; + ) : base(logger) { _imageBucketDataProvider = imageBucketDataProvider; _imageProvider = imageProvider; _contentDataProvider = contentDataProvider; diff --git a/webapi/WeatherForecast/Services/PasswordService.cs b/webapi/WeatherForecast/Services/PasswordService.cs new file mode 100644 index 0000000..d1c89fa --- /dev/null +++ b/webapi/WeatherForecast/Services/PasswordService.cs @@ -0,0 +1,73 @@ +using DomainResults.Common; + +using DataProviders.Collections; + +using HashService; +using JWTService; +using WeatherForecast.Models.Requests; +using Core.Abstractions; + +namespace WeatherForecast.Services { + /// + /// + /// + public interface IPasswordService { + /// + /// + /// + /// + /// + /// + /// + (Guid?, IDomainResult) Post(Guid siteId, Guid userId, PasswordRequestModel requestData); + } + + /// + /// + /// + public class PasswordService : ServiceBase, IPasswordService { + + private readonly IHashService _hashService; + private readonly IUserDataProvider _userDataProvider; + + /// + /// + /// + /// + /// + /// + /// + public PasswordService( + ILogger logger, + IHashService hashService, + + IUserDataProvider userDataProvider + ) : base(logger) { + _hashService = hashService; + + _userDataProvider = userDataProvider; + } + + /// + /// + /// + /// + /// + /// + public (Guid?, IDomainResult) Post(Guid siteId, Guid userId, PasswordRequestModel requestData) { + try { + + + var (salt, hash) = _hashService.CreateSaltedHash(requestData.Password); + + + + return IDomainResult.Success(Guid.NewGuid()); + } + catch (Exception ex) { + _logger.LogError("Unhandled exception", ex); + return IDomainResult.Failed(); + } + } + } +} diff --git a/webapi/WeatherForecast/Services/ShopCartItemService.cs b/webapi/WeatherForecast/Services/ShopCartItemService.cs index 5956275..7bdd911 100644 --- a/webapi/WeatherForecast/Services/ShopCartItemService.cs +++ b/webapi/WeatherForecast/Services/ShopCartItemService.cs @@ -58,9 +58,8 @@ namespace WeatherForecast.Services { /// /// /// - public class ShopCartItemService : IShopCartItemService { + public class ShopCartItemService : ServiceBase, IShopCartItemService { - private readonly ILogger _logger; private readonly IShopCatalogDataProvider _shopCatalogDataProvider; private readonly IShopCartDataProvider _shopCartDataProvider; @@ -74,8 +73,7 @@ namespace WeatherForecast.Services { ILogger logger, IShopCatalogDataProvider shopCatalogDataProvider, IShopCartDataProvider shopCartDataprovider - ) { - _logger = logger; + ) : base(logger) { _shopCatalogDataProvider = shopCatalogDataProvider; _shopCartDataProvider = shopCartDataprovider; } diff --git a/webapi/WeatherForecast/Services/ShopCartItemsService.cs b/webapi/WeatherForecast/Services/ShopCartItemsService.cs index 13e82b6..8ef8ae1 100644 --- a/webapi/WeatherForecast/Services/ShopCartItemsService.cs +++ b/webapi/WeatherForecast/Services/ShopCartItemsService.cs @@ -1,12 +1,11 @@ using DomainResults.Common; -using DataProviders; +using DataProviders.Collections; using Core.Enumerations; using Core.Abstractions; using WeatherForecast.Models.Responses; -using DataProviders.Collections; namespace WeatherForecast.Services { @@ -36,9 +35,8 @@ namespace WeatherForecast.Services { /// /// /// - public class ShopCartItemsService : IShopCartItemsService { + public class ShopCartItemsService : ServiceBase, IShopCartItemsService { - private readonly ILogger _logger; private readonly IShopCatalogDataProvider _shopCatalogDataProvider; private readonly IShopCartDataProvider _shopCartDataProvider; @@ -52,8 +50,7 @@ namespace WeatherForecast.Services { ILogger logger, IShopCatalogDataProvider shopCatalogDataProvider, IShopCartDataProvider shopCartDataprovider - ) { - _logger = logger; + ) : base(logger) { _shopCatalogDataProvider = shopCatalogDataProvider; _shopCartDataProvider = shopCartDataprovider; } diff --git a/webapi/WeatherForecast/Services/ShopItemService.cs b/webapi/WeatherForecast/Services/ShopItemService.cs index 2fe03a0..ea1e5c3 100644 --- a/webapi/WeatherForecast/Services/ShopItemService.cs +++ b/webapi/WeatherForecast/Services/ShopItemService.cs @@ -1,13 +1,13 @@ using DomainResults.Common; +using DataProviders.Collections; + using ExtensionMethods; using Core.Enumerations; using WeatherForecast.Models; using WeatherForecast.Models.Requests; -using DataProviders.Collections; -using Core.DomainObjects.Documents; using WeatherForecast.Services.Abstractions; namespace WeatherForecast.Services { @@ -63,9 +63,8 @@ namespace WeatherForecast.Services { /// /// /// - public class ShopItemService : PostItemServiceBase, IShopItemService { + public class ShopItemService : PostItemServiceBase, IShopItemService { - private readonly ILogger _logger; private readonly IShopCatalogDataProvider _shopCatalogDataProvider; /// @@ -78,8 +77,7 @@ namespace WeatherForecast.Services { ILogger logger, IShopCatalogDataProvider shopCatalogDataProvider, ICategoryDataProvider categoryDataProvider - ) : base(categoryDataProvider) { - _logger = logger; + ) : base(logger, categoryDataProvider) { _shopCatalogDataProvider = shopCatalogDataProvider; } diff --git a/webapi/WeatherForecast/Services/ShopItemsService.cs b/webapi/WeatherForecast/Services/ShopItemsService.cs index 25a205a..3353ce3 100644 --- a/webapi/WeatherForecast/Services/ShopItemsService.cs +++ b/webapi/WeatherForecast/Services/ShopItemsService.cs @@ -1,15 +1,12 @@ using DomainResults.Common; -using DataProviders; +using DataProviders.Collections; using Core.Abstractions; -using Core.DomainObjects; using Core.Enumerations; using WeatherForecast.Models; using WeatherForecast.Models.Responses; -using DataProviders.Collections; -using Core.DomainObjects.Documents; namespace WeatherForecast.Services { @@ -41,8 +38,8 @@ namespace WeatherForecast.Services { /// /// /// - public class ShopItemsService : IShopItemsService { - private readonly ILogger _logger; + public class ShopItemsService : ServiceBase, IShopItemsService { + private readonly IShopCatalogDataProvider _shopCatalogDataProvider; private readonly ICategoryDataProvider _categoryDataProvider; @@ -56,8 +53,7 @@ namespace WeatherForecast.Services { ILogger logger, IShopCatalogDataProvider shopCatalogDataprovider, ICategoryDataProvider categoryDataProvider - ) { - _logger = logger; + ) : base(logger) { _shopCatalogDataProvider = shopCatalogDataprovider; _categoryDataProvider = categoryDataProvider; } diff --git a/webapi/WeatherForecast/Startup.cs b/webapi/WeatherForecast/Startup.cs index c2d8c57..e305ed1 100644 --- a/webapi/WeatherForecast/Startup.cs +++ b/webapi/WeatherForecast/Startup.cs @@ -8,6 +8,8 @@ using DataProviders.Extensions; using System.Text.Json.Serialization; using FileSecurityService.Extensions; using ImageProvider.Extensions; +using JWTService.Extensions; +using HashService.Extensions; namespace WeatherForecast { @@ -52,7 +54,7 @@ namespace WeatherForecast { options.JsonSerializerOptions.DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull); #region configure jwt authentication - if (appSettings.Secret != null) { + if (appSettings.JwtConfig?.Secret != null) { services.AddAuthentication(options => { options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme; options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme; @@ -61,7 +63,7 @@ namespace WeatherForecast { options.SaveToken = true; options.TokenValidationParameters = new TokenValidationParameters { ValidateIssuerSigningKey = true, - IssuerSigningKey = new SymmetricSecurityKey(Convert.FromBase64String(appSettings.Secret)), + IssuerSigningKey = new SymmetricSecurityKey(Convert.FromBase64String(appSettings.JwtConfig.Secret)), ValidateIssuer = false, ValidateAudience = false }; @@ -85,10 +87,14 @@ namespace WeatherForecast { services.AddScoped(); services.AddScoped(); services.AddScoped(); + services.AddScoped(); + services.AddScoped(); services.RegisterDataproviders(appSettings); services.RegisterFileSecurityService(); services.RegisterImageProvider(); + services.RegisterJWTService(appSettings); + services.RegisterHashService(); #region Swagger services.ConfigureSwaggerGen(options => { diff --git a/webapi/WeatherForecast/WeatherForecast.csproj b/webapi/WeatherForecast/WeatherForecast.csproj index d424e55..a147823 100644 --- a/webapi/WeatherForecast/WeatherForecast.csproj +++ b/webapi/WeatherForecast/WeatherForecast.csproj @@ -16,6 +16,7 @@ + @@ -29,7 +30,9 @@ + + diff --git a/webapi/WeatherForecast/appsettings.json b/webapi/WeatherForecast/appsettings.json index 5693491..33b44e7 100644 --- a/webapi/WeatherForecast/appsettings.json +++ b/webapi/WeatherForecast/appsettings.json @@ -8,14 +8,18 @@ "Name": "Console", "Args": { "restrictedToMinimumLevel": "Information", - "outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level}] ({SourceContext}.{Method}) {Message}{NewLine}{Exception}" + "outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} Level=[{Level}] SpanId=[{SpanId}] ({SourceContext}.{Method}) {Message}{NewLine}{Exception}" } } ] }, "AllowedHosts": "*", "Configuration": { - "Secret": "TUlJQ1d3SUJBQUtCZ0djczU2dnIzTWRwa0VYczYvYjIyemxMWlhSaFdrSWtyN0dqUHB4ZkNpQk9FU2Q3L2VxcA==", + "JwtConfig": { + "Secret": "TUlJQ1d3SUJBQUtCZ0djczU2dnIzTWRwa0VYczYvYjIyemxMWlhSaFdrSWtyN0dqUHB4ZkNpQk9FU2Q3L2VxcA==", + "Expires": "365" + }, + "Database": { "ConnectionString": "mongodb://localhost:27017"