diff --git a/db/DML/sites.json b/db/DML/sites.json new file mode 100644 index 0000000..8dad6f5 --- /dev/null +++ b/db/DML/sites.json @@ -0,0 +1,47 @@ +[ + { + "_id": "404c8232-9048-4519-bfba-6e78dc7005ca", + "locale": 0, + "name": "Contoso", + "hosts": [ + "localhost:7174", + "maks-it.com" + ], + "address": { + "street": "123 456th St", + "city": "New York", + "region": "NY" + "postCode": "10001", + "country": "US" + }, + "poweredBy": { + "target": "https://maks-it.com", + "anchorText": "MAKS-IT.com" + }, + "passwordRecoverySettings": { + "smtpSettings": { + "server": "smtp.ionos.it", + "port": 587 + "useSsl": true, + "userName": "commercial@maks-it.com", + "password": "nECbzrWqwzM5Lv4zCxV91g==" + }, + "dkimSettings": { + "hostName": "maks-it.com", + "selector": "default", + "dkimId": "0c5527ca-c10f-45a1-b1b2-4b153e89e209" + }, + "templateId": "", + "email": { + "type": 0, + "name": "support", + "value": "support@maks-it.com" + }, + "subject": "Password recovery service", + "paragraphs": [ + "Your recovery link: {{recoveryLink}}" + ] + + } + } +] diff --git a/postman/dkims/maks-it.com b/postman/dkims/maks-it.com.key similarity index 100% rename from postman/dkims/maks-it.com rename to postman/dkims/maks-it.com.key diff --git a/postman/templates/email-inlined.html b/postman/templates/email-inlined.html deleted file mode 100644 index dc611bb..0000000 --- a/postman/templates/email-inlined.html +++ /dev/null @@ -1,152 +0,0 @@ - - - - - - Simple Transactional Email - - - - - - - - - - - - - diff --git a/postman/templates/password-recovery-template.html b/postman/templates/password-recovery-template.html new file mode 100644 index 0000000..8dbd6eb --- /dev/null +++ b/postman/templates/password-recovery-template.html @@ -0,0 +1,145 @@ + + + + + + {{subject}} + + + + + + + + + + + + + diff --git a/src/DataProviders/Buckets/DkimBucketDataProvider.cs b/src/DataProviders/Buckets/DkimBucketDataProvider.cs index f677cc2..47a8015 100644 --- a/src/DataProviders/Buckets/DkimBucketDataProvider.cs +++ b/src/DataProviders/Buckets/DkimBucketDataProvider.cs @@ -1,5 +1,4 @@ - -using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging; using DomainResults.Common; @@ -27,8 +26,20 @@ namespace DataProviders.Buckets { /// /// (BucketFile?, IDomainResult) Download(Guid siteId, Guid fileId); + + /// + /// + /// + /// + /// + /// + /// + IDomainResult DeleteOne(Guid siteId, Guid fileId); } + /// + /// + /// public class DkimBucketDataProvider : BucketDataProviderBase, IDkimBucketDataProvider { /// @@ -60,5 +71,15 @@ namespace DataProviders.Buckets { return (list.First(), result); } + + + public IDomainResult DeleteOne(Guid siteId, Guid fileId) => + DeleteOneAsync(siteId, fileId).Result; + + public Task DeleteOneAsync(Guid siteId, Guid fileId) => + DeleteAsync(Builders.Filter.And( + Builders.Filter.Eq(x => x.Metadata["siteId"], $"{siteId}"), + Builders.Filter.Eq(x => x.Filename, $"{fileId}") + )); } } diff --git a/src/DataProviders/Buckets/TemplateBucketDataProvider.cs b/src/DataProviders/Buckets/TemplateBucketDataProvider.cs index 372ae13..a5096d9 100644 --- a/src/DataProviders/Buckets/TemplateBucketDataProvider.cs +++ b/src/DataProviders/Buckets/TemplateBucketDataProvider.cs @@ -1,13 +1,11 @@ -using DataProviders.Buckets.Abstractions; +using Microsoft.Extensions.Logging; + using DomainResults.Common; -using Microsoft.Extensions.Logging; + using MongoDB.Driver; using MongoDB.Driver.GridFS; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; + +using DataProviders.Buckets.Abstractions; namespace DataProviders.Buckets { @@ -32,6 +30,14 @@ namespace DataProviders.Buckets { /// /// (BucketFile?, IDomainResult) Download(Guid siteId, Guid fileId); + + /// + /// + /// + /// + /// + /// + IDomainResult DeleteOne(Guid siteId, Guid fileId); } public class TemplateBucketDataProvider : BucketDataProviderBase, ITemplateBucketDataProvider { @@ -40,6 +46,14 @@ namespace DataProviders.Buckets { IMongoClient client ) : base(logger, client, "reactredux", "templates") { } + // TODO: Manage TempleteTypes Enumeration and Metadata in Model and DataProvider + + /// + /// + /// + /// + /// + /// public (BucketFile?, IDomainResult) Download(Guid siteId, Guid fileId) { var filter = Builders.Filter.And( Builders.Filter.Eq(x => x.Metadata["siteId"], $"{siteId}"), @@ -54,5 +68,25 @@ namespace DataProviders.Buckets { return (list.First(), result); } + /// + /// + /// + /// + /// + /// + public IDomainResult DeleteOne(Guid siteId, Guid fileId) => + DeleteOneAsync(siteId, fileId).Result; + + /// + /// + /// + /// + /// + /// + public Task DeleteOneAsync(Guid siteId, Guid fileId) => + DeleteAsync(Builders.Filter.And( + Builders.Filter.Eq(x => x.Metadata["siteId"], $"{siteId}"), + Builders.Filter.Eq(x => x.Filename, $"{fileId}") + )); } } diff --git a/src/DataProviders/Collections/BlogCatalogDataProvider.cs b/src/DataProviders/Collections/BlogCatalogDataProvider.cs index 80bbe6b..fd20855 100644 --- a/src/DataProviders/Collections/BlogCatalogDataProvider.cs +++ b/src/DataProviders/Collections/BlogCatalogDataProvider.cs @@ -4,9 +4,8 @@ using DomainResults.Common; using MongoDB.Bson.Serialization; using MongoDB.Driver; - -using DomainObjects.Documents; using DataProviders.Collections.Abstractions; +using DomainObjects.Documents.Posts; namespace DataProviders.Collections { diff --git a/src/DataProviders/Collections/CategoryDataProvider.cs b/src/DataProviders/Collections/CategoryDataProvider.cs index a9b2249..0d7774d 100644 --- a/src/DataProviders/Collections/CategoryDataProvider.cs +++ b/src/DataProviders/Collections/CategoryDataProvider.cs @@ -4,33 +4,33 @@ using MongoDB.Driver; using MongoDB.Bson.Serialization; using DomainResults.Common; -using DomainObjects.Documents; -using DomainObjects.L10n; using DomainObjects.Enumerations; using DataProviders.Collections.Abstractions; +using DomainObjects.Documents.Categories; +using DomainObjects.Documents.Categories.L10n; namespace DataProviders.Collections { public interface ICategoryDataProvider { - (Guid?, IDomainResult) Insert(CategoryDocument obj); + (Guid?, IDomainResult) Insert(Category obj); (Guid?, IDomainResult) CreateDefault(Guid siteId); - (CategoryDocument?, IDomainResult) Get(Guid siteId, Guid categoryId); - (List?, IDomainResult) GetMany(Guid siteId, List categoryIds); - (CategoryDocument?, IDomainResult) GetBySlug(Guid siteId, string slug); - (List?, IDomainResult) GetBySlugs(Guid siteId, List slugs); - (List?, IDomainResult) GetAll(Guid siteId); - (Guid?, IDomainResult) Update(CategoryDocument obj); + (Category?, IDomainResult) Get(Guid siteId, Guid categoryId); + (List?, IDomainResult) GetMany(Guid siteId, List categoryIds); + (Category?, IDomainResult) GetBySlug(Guid siteId, string slug); + (List?, IDomainResult) GetBySlugs(Guid siteId, List slugs); + (List?, IDomainResult) GetAll(Guid siteId); + (Guid?, IDomainResult) Update(Category obj); IDomainResult Delete(Guid id); IDomainResult DeleteAll(Guid siteId); } - public class CategoryDataProvider : CollectionDataProviderBase, ICategoryDataProvider { + public class CategoryDataProvider : CollectionDataProviderBase, ICategoryDataProvider { private const string _databaseName = "reactredux"; private const string _collectionName = "categories"; public CategoryDataProvider( - ILogger> logger, + ILogger> logger, IMongoClient client, IIdGenerator idGenerator, ISessionService sessionService) : base(logger, client, idGenerator, sessionService, _databaseName, _collectionName) { @@ -42,7 +42,7 @@ namespace DataProviders.Collections if (result.IsSuccess && list != null) return (list.First().Id, result); - return Insert(new CategoryDocument { + return Insert(new Category { SiteId = siteId, L10n = new List { new CategoryL10n { @@ -54,7 +54,7 @@ namespace DataProviders.Collections }); } - public (CategoryDocument?, IDomainResult) Get(Guid siteId, Guid categoryId) { + public (Category?, IDomainResult) Get(Guid siteId, Guid categoryId) { var (list, result) = GetWithPredicate(x => x.SiteId == siteId && x.Id == categoryId, x => x); if (!result.IsSuccess || list == null) @@ -63,10 +63,10 @@ namespace DataProviders.Collections return (list.First(), result); } - public (List?, IDomainResult) GetMany(Guid siteId, List categoryIds) => + public (List?, IDomainResult) GetMany(Guid siteId, List categoryIds) => GetWithPredicate(x => x.SiteId == siteId && categoryIds.Contains(x.Id), x => x); - public (CategoryDocument?, IDomainResult) GetBySlug(Guid siteId, string slug) { + public (Category?, IDomainResult) GetBySlug(Guid siteId, string slug) { var (list, result) = GetBySlugs(siteId, new List { slug }); if (!result.IsSuccess || list == null) @@ -75,13 +75,13 @@ namespace DataProviders.Collections return (list.First(), result); } - public (List?, IDomainResult) GetBySlugs(Guid siteId, List slugs) => + public (List?, IDomainResult) GetBySlugs(Guid siteId, List slugs) => GetWithPredicate(x => x.SiteId == siteId && x.L10n.Any(y => slugs.Contains(y.Slug)), x => x); - public (List?, IDomainResult) GetAll(Guid siteId) => + public (List?, IDomainResult) GetAll(Guid siteId) => GetWithPredicate(x => x.SiteId == siteId, x => x); - public (Guid?, IDomainResult) Update(CategoryDocument obj) => + public (Guid?, IDomainResult) Update(Category obj) => UpdateWithPredicate(obj, x => x.Id == obj.Id); public IDomainResult Delete(Guid id) => diff --git a/src/DataProviders/Collections/ShopCatalogDataProvider.cs b/src/DataProviders/Collections/ShopCatalogDataProvider.cs index a0fb020..e59014f 100644 --- a/src/DataProviders/Collections/ShopCatalogDataProvider.cs +++ b/src/DataProviders/Collections/ShopCatalogDataProvider.cs @@ -4,8 +4,8 @@ using DomainResults.Common; using MongoDB.Bson.Serialization; using MongoDB.Driver; -using DomainObjects.Documents; using DataProviders.Collections.Abstractions; +using DomainObjects.Documents.Posts; namespace DataProviders.Collections { diff --git a/src/DataProviders/Mappings.cs b/src/DataProviders/Mappings.cs index 44f55b0..8be2a38 100644 --- a/src/DataProviders/Mappings.cs +++ b/src/DataProviders/Mappings.cs @@ -12,6 +12,9 @@ using DomainObjects.Pages; using DomainObjects.Documents; using DomainObjects.Documents.Users; using DomainObjects.Documents.Sites; +using DomainObjects.Documents.Categories; +using DomainObjects.Documents.Categories.L10n; +using DomainObjects.Documents.Posts; namespace DataProviders { @@ -70,8 +73,8 @@ namespace DataProviders }); } - if (!BsonClassMap.IsClassMapRegistered(typeof(CategoryDocument))) { - BsonClassMap.RegisterClassMap(cm => { + if (!BsonClassMap.IsClassMapRegistered(typeof(Category))) { + BsonClassMap.RegisterClassMap(cm => { cm.AutoMap(); }); } diff --git a/src/DomainObjects/Contact.cs b/src/DomainObjects/Contact.cs index 029daff..2d40d2b 100644 --- a/src/DomainObjects/Contact.cs +++ b/src/DomainObjects/Contact.cs @@ -5,8 +5,13 @@ namespace DomainObjects; public class Contact : DomainObjectBase { public ContactTypes Type { get; set; } + + public string? Name { get; set; } + public string Value { get; set; } + public bool? Confirmed { get; set; } + public bool? Primary { get; set; } public Contact(ContactTypes type, string value) { diff --git a/src/DomainObjects/Documents/Address.cs b/src/DomainObjects/Documents/Address.cs index 7f05b4a..1fc384d 100644 --- a/src/DomainObjects/Documents/Address.cs +++ b/src/DomainObjects/Documents/Address.cs @@ -4,6 +4,7 @@ public class Address { public string Street { get; set; } public string City { get; set; } + public string Region { get; set; } public string PostCode { get; set; } public string Country { get; set; } } diff --git a/src/DomainObjects/Documents/BlogDocument.cs b/src/DomainObjects/Documents/BlogDocument.cs deleted file mode 100644 index 9dd4211..0000000 --- a/src/DomainObjects/Documents/BlogDocument.cs +++ /dev/null @@ -1,34 +0,0 @@ -using DomainObjects.Abstractions; - -namespace DomainObjects.Documents; - -public class BlogDocument : PostItemBase { - - public uint? ReadTime { get; set; } - - public uint? Likes { get; set; } - - public override int GetHashCode() { - unchecked { - int hash = 17; - hash = hash * 23 + Id.GetHashCode(); - hash = hash * 23 + SiteId.GetHashCode(); - hash = hash * 23 + L10n.GetHashCode(); - if (MediaAttachments != null) - hash = hash * 23 + MediaAttachments.Sum(x => x.GetHashCode()); - hash = hash * 23 + Author.GetHashCode(); - hash = hash * 23 + Created.GetHashCode(); - if(Tags != null) - hash = hash * 23 + Tags.Sum(x => x.GetHashCode()); - - if(Categories != null) - hash = hash * 23 + Categories.Sum(x => x.GetHashCode()); - - hash = hash * 23 + ReadTime.GetHashCode(); - hash = hash * 23 + Likes.GetHashCode(); - - return hash; - } - } -} - diff --git a/src/DomainObjects/Documents/Categories/Category.cs b/src/DomainObjects/Documents/Categories/Category.cs new file mode 100644 index 0000000..5665e96 --- /dev/null +++ b/src/DomainObjects/Documents/Categories/Category.cs @@ -0,0 +1,22 @@ +using DomainObjects.Abstractions; +using DomainObjects.Documents.Categories.L10n; + +namespace DomainObjects.Documents.Categories +{ + public class Category : DomainObjectDocumentBase + { + public Guid SiteId { get; set; } + public List L10n { get; set; } + + public override int GetHashCode() + { + unchecked + { + int hash = 17; + hash = hash * 23 + Id.GetHashCode(); + hash += L10n.Sum(x => x.GetHashCode() * 23); + return hash; + } + } + } +} diff --git a/src/DomainObjects/Documents/Categories/L10n/CategoryL10n.cs b/src/DomainObjects/Documents/Categories/L10n/CategoryL10n.cs new file mode 100644 index 0000000..fc5d50d --- /dev/null +++ b/src/DomainObjects/Documents/Categories/L10n/CategoryL10n.cs @@ -0,0 +1,24 @@ +using DomainObjects.Abstractions; +using DomainObjects.Enumerations; + +namespace DomainObjects.Documents.Categories.L10n; + +public class CategoryL10n : DomainObjectBase +{ + public Locales Locale { get; set; } + public string Slug { get; set; } + public string Text { get; set; } + + public override int GetHashCode() + { + unchecked + { + int hash = 17; + hash = hash * 23 + Locale.GetHashCode(); + hash = hash * 23 + Slug.GetHashCode(); + hash = hash * 23 + Text.GetHashCode(); + return hash; + } + } +} + diff --git a/src/DomainObjects/Documents/CategoryDocument.cs b/src/DomainObjects/Documents/CategoryDocument.cs deleted file mode 100644 index f4cfb8e..0000000 --- a/src/DomainObjects/Documents/CategoryDocument.cs +++ /dev/null @@ -1,18 +0,0 @@ -using DomainObjects.Abstractions; -using DomainObjects.L10n; - -namespace DomainObjects.Documents { - public class CategoryDocument : DomainObjectDocumentBase { - public Guid SiteId { get; set; } - public List L10n { get; set; } - - public override int GetHashCode() { - unchecked { - int hash = 17; - hash = hash * 23 + Id.GetHashCode(); - hash += L10n.Sum(x => x.GetHashCode() * 23); - return hash; - } - } - } -} diff --git a/src/DomainObjects/Documents/MailboxConnectionSettings.cs b/src/DomainObjects/Documents/MailboxConnectionSettings.cs index c9845dc..d641702 100644 --- a/src/DomainObjects/Documents/MailboxConnectionSettings.cs +++ b/src/DomainObjects/Documents/MailboxConnectionSettings.cs @@ -1,10 +1,5 @@ using CryptoProvider; using DomainObjects.Abstractions; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; namespace DomainObjects.Documents; @@ -19,10 +14,17 @@ public class MailboxConnectionSettings : DomainObjectBase + SetPassword(aesKey.IV, aesKey.Key, password); + public void SetPassword(string iv, string key, string password) { Password = AesService.EncryptString(iv, key, password); } + public string GetPassword(IAesKey aesKey) => + GetPassword(aesKey.IV, aesKey.Key); + public string GetPassword(string iv, string key) => AesService.DecryptString(iv, key, Password); diff --git a/src/DomainObjects/Documents/Posts/BlogDocument.cs b/src/DomainObjects/Documents/Posts/BlogDocument.cs new file mode 100644 index 0000000..b85df91 --- /dev/null +++ b/src/DomainObjects/Documents/Posts/BlogDocument.cs @@ -0,0 +1,37 @@ +using DomainObjects.Abstractions; + +namespace DomainObjects.Documents.Posts; + +public class BlogDocument : PostItemBase +{ + + public uint? ReadTime { get; set; } + + public uint? Likes { get; set; } + + public override int GetHashCode() + { + unchecked + { + int hash = 17; + hash = hash * 23 + Id.GetHashCode(); + hash = hash * 23 + SiteId.GetHashCode(); + hash = hash * 23 + L10n.GetHashCode(); + if (MediaAttachments != null) + hash = hash * 23 + MediaAttachments.Sum(x => x.GetHashCode()); + hash = hash * 23 + Author.GetHashCode(); + hash = hash * 23 + Created.GetHashCode(); + if (Tags != null) + hash = hash * 23 + Tags.Sum(x => x.GetHashCode()); + + if (Categories != null) + hash = hash * 23 + Categories.Sum(x => x.GetHashCode()); + + hash = hash * 23 + ReadTime.GetHashCode(); + hash = hash * 23 + Likes.GetHashCode(); + + return hash; + } + } +} + diff --git a/src/DomainObjects/Documents/Posts/ShopDocument.cs b/src/DomainObjects/Documents/Posts/ShopDocument.cs new file mode 100644 index 0000000..5ed4240 --- /dev/null +++ b/src/DomainObjects/Documents/Posts/ShopDocument.cs @@ -0,0 +1,39 @@ +using DomainObjects.Abstractions; + +namespace DomainObjects.Documents.Posts; + +public class ShopDocument : PostItemBase +{ + public string BrandName { get; set; } + public string Sku { get; set; } + public decimal? Rating { get; set; } + public decimal Price { get; set; } + public decimal? NewPrice { get; set; } + public uint Quantity { get; set; } + + public override int GetHashCode() + { + unchecked + { + int hash = 17; + hash = hash * 23 + Id.GetHashCode(); + hash = hash * 23 + SiteId.GetHashCode(); + hash = hash * 23 + L10n.GetHashCode(); + if (MediaAttachments != null) + hash = hash * 23 + MediaAttachments.Sum(x => x.GetHashCode()); + hash = hash * 23 + Author.GetHashCode(); + hash = hash * 23 + Created.GetHashCode(); + hash = hash * 23 + Tags.GetHashCode(); + hash = hash * 23 + Categories.Sum(x => x.GetHashCode()); + + hash = hash * 23 + BrandName.GetHashCode(); + hash = hash * 23 + Sku.GetHashCode(); + hash = hash * 23 + Rating.GetHashCode(); + hash = hash * 23 + Price.GetHashCode(); + hash = hash * 23 + NewPrice.GetHashCode(); + hash = hash * 23 + Quantity.GetHashCode(); + + return hash; + } + } +} diff --git a/src/DomainObjects/Documents/ShopDocument.cs b/src/DomainObjects/Documents/ShopDocument.cs deleted file mode 100644 index 57548ed..0000000 --- a/src/DomainObjects/Documents/ShopDocument.cs +++ /dev/null @@ -1,36 +0,0 @@ -using DomainObjects.Abstractions; - -namespace DomainObjects.Documents; - -public class ShopDocument : PostItemBase { - public string BrandName { get; set; } - public string Sku { get; set; } - public decimal? Rating { get; set; } - public decimal Price { get; set; } - public decimal? NewPrice { get; set; } - public uint Quantity { get; set; } - - public override int GetHashCode() { - unchecked { - int hash = 17; - hash = hash * 23 + Id.GetHashCode(); - hash = hash * 23 + SiteId.GetHashCode(); - hash = hash * 23 + L10n.GetHashCode(); - if (MediaAttachments != null) - hash = hash * 23 + MediaAttachments.Sum(x => x.GetHashCode()); - hash = hash * 23 + Author.GetHashCode(); - hash = hash * 23 + Created.GetHashCode(); - hash = hash * 23 + Tags.GetHashCode(); - hash = hash * 23 + Categories.Sum(x => x.GetHashCode()); - - hash = hash * 23 + BrandName.GetHashCode(); - hash = hash * 23 + Sku.GetHashCode(); - hash = hash * 23 + Rating.GetHashCode(); - hash = hash * 23 + Price.GetHashCode(); - hash = hash * 23 + NewPrice.GetHashCode(); - hash = hash * 23 + Quantity.GetHashCode(); - - return hash; - } - } -} diff --git a/src/DomainObjects/Documents/Sites/PassworRecoverySettings.cs b/src/DomainObjects/Documents/Sites/PassworRecoverySettings.cs index 793ef88..0a20521 100644 --- a/src/DomainObjects/Documents/Sites/PassworRecoverySettings.cs +++ b/src/DomainObjects/Documents/Sites/PassworRecoverySettings.cs @@ -4,6 +4,8 @@ namespace DomainObjects.Documents.Sites; public class PassworRecoverySettings : DomainObjectBase { + public MailboxConnectionSettings SmtpSettings { get; set; } + /// /// DomainKeys Identified Mail (DKIM) is an email authentication method designed to detect forged sender addresses in email (email spoofing),
/// a technique often used in phishing and email spam. @@ -12,14 +14,16 @@ public class PassworRecoverySettings : DomainObjectBase public Guid TemplateId { get; set; } - public string Name { get; set; } - public Contact Email { get; set; } + public string Subject { get; set; } public List Paragraphs { get; set; } + + + public override int GetHashCode() { throw new NotImplementedException(); } diff --git a/src/DomainObjects/Documents/Sites/Site.cs b/src/DomainObjects/Documents/Sites/Site.cs index 81ff66f..9333f33 100644 --- a/src/DomainObjects/Documents/Sites/Site.cs +++ b/src/DomainObjects/Documents/Sites/Site.cs @@ -1,20 +1,19 @@ using DomainObjects.Abstractions; +using DomainObjects.Enumerations; namespace DomainObjects.Documents.Sites { public class Site : DomainObjectDocumentBase { + public Locales Locale { get; set; } + public string Name { get; set; } public List Hosts { get; set; } public Address Address { get; set; } - public string PoweredBy { get; set; } - - public MailboxConnectionSettings SmtpSettings { get; set; } - - public MailboxConnectionSettings ImapSettings { get; set; } + public Link PoweredBy { get; set; } public PassworRecoverySettings PassworRecoverySettings { get; set; } diff --git a/src/DomainObjects/L10n/CategoryL10n.cs b/src/DomainObjects/L10n/CategoryL10n.cs deleted file mode 100644 index 908332b..0000000 --- a/src/DomainObjects/L10n/CategoryL10n.cs +++ /dev/null @@ -1,21 +0,0 @@ -using DomainObjects.Abstractions; -using DomainObjects.Enumerations; - -namespace DomainObjects.L10n; - -public class CategoryL10n : DomainObjectBase { - public Locales Locale { get; set; } - public string Slug { get; set; } - public string Text { get; set; } - - public override int GetHashCode() { - unchecked { - int hash = 17; - hash = hash * 23 + Locale.GetHashCode(); - hash = hash * 23 + Slug.GetHashCode(); - hash = hash * 23 + Text.GetHashCode(); - return hash; - } - } -} - diff --git a/src/WeatherForecast/Configuration.cs b/src/WeatherForecast/Configuration.cs index 5a2f5e7..4148e9c 100644 --- a/src/WeatherForecast/Configuration.cs +++ b/src/WeatherForecast/Configuration.cs @@ -50,6 +50,11 @@ namespace WeatherForecast { ///
public AesKey? JwtTokenEncryption { get; set; } + /// + /// + /// + public AesKey? MailPasswordEncryption { get; set; } + /// /// /// diff --git a/src/WeatherForecast/Controllers/BlogItemController.cs b/src/WeatherForecast/Controllers/BlogItemController.cs index 398d9f7..34f6543 100644 --- a/src/WeatherForecast/Controllers/BlogItemController.cs +++ b/src/WeatherForecast/Controllers/BlogItemController.cs @@ -10,7 +10,7 @@ using Core.Enumerations; using DataProviders.Collections; using Extensions; using DomainResults.Common; -using DomainObjects.Documents; +using DomainObjects.Documents.Posts; namespace WeatherForecast.Controllers; diff --git a/src/WeatherForecast/Controllers/DkimController.cs b/src/WeatherForecast/Controllers/DkimController.cs index 1bf65f1..4debdfa 100644 --- a/src/WeatherForecast/Controllers/DkimController.cs +++ b/src/WeatherForecast/Controllers/DkimController.cs @@ -34,7 +34,7 @@ public class DkimController : ControllerBase { } /// - /// Allows to upload private dkim certificate + /// /// /// /// @@ -52,4 +52,17 @@ public class DkimController : ControllerBase { return result.ToActionResult(); } + + /// + /// Delete private dkim cert + /// + /// + /// + /// + [HttpDelete("{siteId}/{fileId}")] + public IActionResult Delete([FromRoute] Guid siteId, [FromRoute] Guid fileId) { + + var result = _dkimService.Delete(siteId, fileId); + return result.ToActionResult(); + } } diff --git a/src/WeatherForecast/Controllers/ShopItemController.cs b/src/WeatherForecast/Controllers/ShopItemController.cs index 2258155..6fd3dad 100644 --- a/src/WeatherForecast/Controllers/ShopItemController.cs +++ b/src/WeatherForecast/Controllers/ShopItemController.cs @@ -8,9 +8,9 @@ using WeatherForecast.Models.Requests; using WeatherForecast.Policies; using Core.Enumerations; using DataProviders.Collections; -using DomainObjects.Documents; using DomainResults.Common; using Extensions; +using DomainObjects.Documents.Posts; namespace WeatherForecast.Controllers; diff --git a/src/WeatherForecast/Controllers/TemplateController.cs b/src/WeatherForecast/Controllers/TemplateController.cs index b206568..624ede1 100644 --- a/src/WeatherForecast/Controllers/TemplateController.cs +++ b/src/WeatherForecast/Controllers/TemplateController.cs @@ -53,4 +53,18 @@ public class TemplateController : ControllerBase { return result.ToActionResult(); } + + + /// + /// Delete template + /// + /// + /// + /// + [HttpDelete("{siteId}/{fileId}")] + public IActionResult Delete([FromRoute] Guid siteId, [FromRoute] Guid fileId) { + + var result = _templateService.Delete(siteId, fileId); + return result.ToActionResult(); + } } diff --git a/src/WeatherForecast/Controllers/UtilsController.cs b/src/WeatherForecast/Controllers/UtilsController.cs index d445f30..ffa8864 100644 --- a/src/WeatherForecast/Controllers/UtilsController.cs +++ b/src/WeatherForecast/Controllers/UtilsController.cs @@ -6,6 +6,7 @@ using DomainResults.Mvc; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using WeatherForecast.Models.Initialization.Requests; +using WeatherForecast.Models.Utils.Requests; using WeatherForecast.Services; namespace WeatherForecast.Controllers; @@ -27,5 +28,19 @@ public class UtilsController : ControllerBase { return Ok(AesService.GenerateKey()); } + /// + /// + /// + /// + /// + [HttpPost("[action]")] + public IActionResult EncryptStringAes([FromBody] EncryptStringAesRequestModel requestData) { + var result = AesService.EncryptString(requestData.IV, requestData.Key, requestData.InputString); + if(result != null) + return Ok(result); + + return BadRequest(); + } + } diff --git a/src/WeatherForecast/Models/Abstractions/PostItem/Responsens/PostItemResponseModelBase.cs b/src/WeatherForecast/Models/Abstractions/PostItem/Responsens/PostItemResponseModelBase.cs index 89cd2c2..e27b507 100644 --- a/src/WeatherForecast/Models/Abstractions/PostItem/Responsens/PostItemResponseModelBase.cs +++ b/src/WeatherForecast/Models/Abstractions/PostItem/Responsens/PostItemResponseModelBase.cs @@ -1,19 +1,19 @@ using DomainObjects.Abstractions; -using DomainObjects.Documents; using DomainObjects.Enumerations; using Core.Abstractions.Models; using WeatherForecast.Models.Category.Responses; +using DomainObjects.Documents.Categories; +namespace WeatherForecast.Models.Abstractions.PostItem.Responses +{ -namespace WeatherForecast.Models.Abstractions.PostItem.Responses { - - /// - /// - /// - /// - public abstract class PostItemResponseModelBase : ResponseModelBase { + /// + /// + /// + /// + public abstract class PostItemResponseModelBase : ResponseModelBase { /// /// @@ -122,7 +122,7 @@ namespace WeatherForecast.Models.Abstractions.PostItem.Responses { /// /// /// - public PostItemResponseModelBase(PostItemBase postItem, List categories) : this(postItem) { + public PostItemResponseModelBase(PostItemBase postItem, List categories) : this(postItem) { L10n = postItem.L10n.Select(x => new PostItemL10nModel(x)).ToList(); Categories = categories.Select(x => new CategoryItemResponseModel(x)).ToList(); MediaAttachemnts = postItem.MediaAttachments?.Select(x => new MediaAttachmentResponseModel(x)).ToList(); @@ -134,7 +134,7 @@ namespace WeatherForecast.Models.Abstractions.PostItem.Responses { /// /// /// - public PostItemResponseModelBase(PostItemBase postItem, List categories, Locales locale) : this(postItem) { + public PostItemResponseModelBase(PostItemBase postItem, List categories, Locales locale) : this(postItem) { var postItemL10n = postItem.L10n.Single(x => x.Locale == locale); diff --git a/src/WeatherForecast/Models/BlogItem/Requests/BlogItemRequestModel.cs b/src/WeatherForecast/Models/BlogItem/Requests/BlogItemRequestModel.cs index a32155a..0979dc4 100644 --- a/src/WeatherForecast/Models/BlogItem/Requests/BlogItemRequestModel.cs +++ b/src/WeatherForecast/Models/BlogItem/Requests/BlogItemRequestModel.cs @@ -1,15 +1,16 @@ -using DomainObjects.Documents; -using Core.Enumerations; +using Core.Enumerations; using Extensions; using System.ComponentModel.DataAnnotations; using WeatherForecast.Models.Abstractions.PostItem.Requests; +using DomainObjects.Documents.Posts; -namespace WeatherForecast.Models.Blog.Requests { +namespace WeatherForecast.Models.Blog.Requests +{ - /// - /// - /// - public class BlogItemRequestModel : PostItemRequestModelBase { + /// + /// + /// + public class BlogItemRequestModel : PostItemRequestModelBase { /// /// diff --git a/src/WeatherForecast/Models/BlogItem/Responses/BlogItemResponseModel.cs b/src/WeatherForecast/Models/BlogItem/Responses/BlogItemResponseModel.cs index 5a53022..f7425f6 100644 --- a/src/WeatherForecast/Models/BlogItem/Responses/BlogItemResponseModel.cs +++ b/src/WeatherForecast/Models/BlogItem/Responses/BlogItemResponseModel.cs @@ -1,14 +1,15 @@ -using DomainObjects.Documents; - -using WeatherForecast.Models.Abstractions.PostItem.Responses; +using WeatherForecast.Models.Abstractions.PostItem.Responses; using DomainObjects.Enumerations; +using DomainObjects.Documents.Categories; +using DomainObjects.Documents.Posts; -namespace WeatherForecast.Models.Blog.Responses { +namespace WeatherForecast.Models.Blog.Responses +{ - /// - /// - /// - public class BlogItemResponseModel : PostItemResponseModelBase { + /// + /// + /// + public class BlogItemResponseModel : PostItemResponseModelBase { /// /// @@ -25,7 +26,7 @@ namespace WeatherForecast.Models.Blog.Responses { /// /// /// - public BlogItemResponseModel(BlogDocument blogItem, List categories) : base(blogItem, categories) { + public BlogItemResponseModel(BlogDocument blogItem, List categories) : base(blogItem, categories) { ReadTime = blogItem.ReadTime; Likes = blogItem.Likes; } @@ -36,7 +37,7 @@ namespace WeatherForecast.Models.Blog.Responses { /// /// /// - public BlogItemResponseModel(BlogDocument blogItem, List categories, Locales locale) : base(blogItem, categories, locale) { + public BlogItemResponseModel(BlogDocument blogItem, List categories, Locales locale) : base(blogItem, categories, locale) { ReadTime = blogItem.ReadTime; Likes = blogItem.Likes; } diff --git a/src/WeatherForecast/Models/CategoryItem/Requests/CategoryItemRequestModel.cs b/src/WeatherForecast/Models/CategoryItem/Requests/CategoryItemRequestModel.cs index 62d1997..cb26bcc 100644 --- a/src/WeatherForecast/Models/CategoryItem/Requests/CategoryItemRequestModel.cs +++ b/src/WeatherForecast/Models/CategoryItem/Requests/CategoryItemRequestModel.cs @@ -1,15 +1,16 @@ using Core.Abstractions.Models; -using DomainObjects.Documents; using Core.Enumerations; using Extensions; using System.ComponentModel.DataAnnotations; +using DomainObjects.Documents.Categories; -namespace WeatherForecast.Models.Category.Requests { +namespace WeatherForecast.Models.Category.Requests +{ - /// - /// - /// - public class CategoryItemRequestModel : RequestModelBase { + /// + /// + /// + public class CategoryItemRequestModel : RequestModelBase { /// /// @@ -20,7 +21,7 @@ namespace WeatherForecast.Models.Category.Requests { /// /// /// - public CategoryDocument ToDomainObject(Guid siteId) => new CategoryDocument() { + public DomainObjects.Documents.Categories.Category ToDomainObject(Guid siteId) => new DomainObjects.Documents.Categories.Category() { SiteId = siteId, L10n = L10n.Select(x => x.ToDomainObject()).ToList() diff --git a/src/WeatherForecast/Models/CategoryItem/Requests/CategoryL10nModel.cs b/src/WeatherForecast/Models/CategoryItem/Requests/CategoryL10nModel.cs index cfc692c..a1bd5f5 100644 --- a/src/WeatherForecast/Models/CategoryItem/Requests/CategoryL10nModel.cs +++ b/src/WeatherForecast/Models/CategoryItem/Requests/CategoryL10nModel.cs @@ -2,16 +2,17 @@ using System.Diagnostics.CodeAnalysis; using Core.Abstractions; using Core.Abstractions.Models; -using DomainObjects.L10n; using Core.Enumerations; using DomainObjects.Enumerations; +using DomainObjects.Documents.Categories.L10n; -namespace WeatherForecast.Models.Category.Requests { +namespace WeatherForecast.Models.Category.Requests +{ - /// - /// - /// - public class CategoryL10nModel : RequestModelBase { + /// + /// + /// + public class CategoryL10nModel : RequestModelBase { /// /// diff --git a/src/WeatherForecast/Models/CategoryItem/Responses/CategoryItemResponseModel.cs b/src/WeatherForecast/Models/CategoryItem/Responses/CategoryItemResponseModel.cs index a4b059d..91b3b2b 100644 --- a/src/WeatherForecast/Models/CategoryItem/Responses/CategoryItemResponseModel.cs +++ b/src/WeatherForecast/Models/CategoryItem/Responses/CategoryItemResponseModel.cs @@ -1,14 +1,14 @@ -using DomainObjects.Documents; - -using Core.Abstractions.Models; +using Core.Abstractions.Models; using DomainObjects.Enumerations; +using DomainObjects.Documents.Categories; -namespace WeatherForecast.Models.Category.Responses { +namespace WeatherForecast.Models.Category.Responses +{ - /// - /// - /// - public class CategoryItemResponseModel : ResponseModelBase { + /// + /// + /// + public class CategoryItemResponseModel : ResponseModelBase { /// /// @@ -39,7 +39,7 @@ namespace WeatherForecast.Models.Category.Responses { /// /// /// - public CategoryItemResponseModel(CategoryDocument category) { + public CategoryItemResponseModel(DomainObjects.Documents.Categories.Category category) { Id = category.Id; SiteId = category.SiteId; @@ -51,7 +51,7 @@ namespace WeatherForecast.Models.Category.Responses { /// /// /// - public CategoryItemResponseModel(CategoryDocument category, Locales locale) { + public CategoryItemResponseModel(DomainObjects.Documents.Categories.Category category, Locales locale) { Id = category.Id; SiteId = category.SiteId; diff --git a/src/WeatherForecast/Models/CategoryItem/Responses/CategoryL10nModel.cs b/src/WeatherForecast/Models/CategoryItem/Responses/CategoryL10nModel.cs index 33fc86c..544e1dd 100644 --- a/src/WeatherForecast/Models/CategoryItem/Responses/CategoryL10nModel.cs +++ b/src/WeatherForecast/Models/CategoryItem/Responses/CategoryL10nModel.cs @@ -1,12 +1,13 @@ using Core.Abstractions.Models; -using DomainObjects.L10n; +using DomainObjects.Documents.Categories.L10n; -namespace WeatherForecast.Models.Category.Responses { +namespace WeatherForecast.Models.Category.Responses +{ - /// - /// - /// - public class CategoryL10nModel : ResponseModelBase { + /// + /// + /// + public class CategoryL10nModel : ResponseModelBase { /// /// diff --git a/src/WeatherForecast/Models/Initialization/Requests/InitializeSystemRequestModel.cs b/src/WeatherForecast/Models/Initialization/Requests/InitializeSystemRequestModel.cs index d61a056..c597e59 100644 --- a/src/WeatherForecast/Models/Initialization/Requests/InitializeSystemRequestModel.cs +++ b/src/WeatherForecast/Models/Initialization/Requests/InitializeSystemRequestModel.cs @@ -41,15 +41,8 @@ namespace WeatherForecast.Models.Initialization.Requests { /// public string RePassword { get; set; } - /// - /// - /// - public string DkimBase64 { get; set; } - /// - /// - /// - public string ServiceEmlTemplateBase64 { get; set; } + /// /// @@ -88,11 +81,11 @@ namespace WeatherForecast.Models.Initialization.Requests { if (string.Compare(Password, RePassword) != 0) yield return new ValidationResult($"{nameof(Password)} and {nameof(RePassword)} ${Errors.NotMatched}"); - if (string.IsNullOrWhiteSpace(DkimBase64)) - yield return new ValidationResult($"{nameof(DkimBase64)} {Errors.NullOrWhiteSpace}"); + //if (string.IsNullOrWhiteSpace(DkimBase64)) + // yield return new ValidationResult($"{nameof(DkimBase64)} {Errors.NullOrWhiteSpace}"); - if (string.IsNullOrWhiteSpace(ServiceEmlTemplateBase64)) - yield return new ValidationResult($"{nameof(ServiceEmlTemplateBase64)} {Errors.NullOrWhiteSpace}"); + //if (string.IsNullOrWhiteSpace(ServiceEmlTemplateBase64)) + // yield return new ValidationResult($"{nameof(ServiceEmlTemplateBase64)} {Errors.NullOrWhiteSpace}"); } } } diff --git a/src/WeatherForecast/Models/Shop/Requests/ShopItemRequestModel.cs b/src/WeatherForecast/Models/Shop/Requests/ShopItemRequestModel.cs index feb5ee0..fb23fbe 100644 --- a/src/WeatherForecast/Models/Shop/Requests/ShopItemRequestModel.cs +++ b/src/WeatherForecast/Models/Shop/Requests/ShopItemRequestModel.cs @@ -1,16 +1,16 @@ using System.ComponentModel.DataAnnotations; - -using DomainObjects.Documents; using Core.Enumerations; using Extensions; using WeatherForecast.Models.Abstractions.PostItem.Requests; +using DomainObjects.Documents.Posts; -namespace WeatherForecast.Models.Requests { +namespace WeatherForecast.Models.Requests +{ - /// - /// - /// - public class ShopItemRequestModel : PostItemRequestModelBase { + /// + /// + /// + public class ShopItemRequestModel : PostItemRequestModelBase { /// /// diff --git a/src/WeatherForecast/Models/Shop/Responses/ShopCartItemResponseModel.cs b/src/WeatherForecast/Models/Shop/Responses/ShopCartItemResponseModel.cs index 3bcc125..3bf79cd 100644 --- a/src/WeatherForecast/Models/Shop/Responses/ShopCartItemResponseModel.cs +++ b/src/WeatherForecast/Models/Shop/Responses/ShopCartItemResponseModel.cs @@ -1,14 +1,16 @@ using Core.Abstractions.Models; using DomainObjects.Documents; +using DomainObjects.Documents.Posts; using DomainObjects.Enumerations; using WeatherForecast.Models.Abstractions.PostItem.Responses; -namespace WeatherForecast.Models.Responses { +namespace WeatherForecast.Models.Responses +{ - /// - /// - /// - public class ShopCartItemResponseModel : ResponseModelBase { + /// + /// + /// + public class ShopCartItemResponseModel : ResponseModelBase { /// /// diff --git a/src/WeatherForecast/Models/Shop/Responses/ShopItemResponseModel.cs b/src/WeatherForecast/Models/Shop/Responses/ShopItemResponseModel.cs index ad9c45a..deb9ec5 100644 --- a/src/WeatherForecast/Models/Shop/Responses/ShopItemResponseModel.cs +++ b/src/WeatherForecast/Models/Shop/Responses/ShopItemResponseModel.cs @@ -1,13 +1,15 @@ -using DomainObjects.Documents; +using DomainObjects.Documents.Categories; +using DomainObjects.Documents.Posts; using DomainObjects.Enumerations; using WeatherForecast.Models.Abstractions.PostItem.Responses; -namespace WeatherForecast.Models.Shop.Responses { +namespace WeatherForecast.Models.Shop.Responses +{ - /// - /// - /// - public class ShopItemResponseModel : PostItemResponseModelBase { + /// + /// + /// + public class ShopItemResponseModel : PostItemResponseModelBase { /// /// @@ -39,7 +41,7 @@ namespace WeatherForecast.Models.Shop.Responses { /// /// /// - public ShopItemResponseModel(ShopDocument shopCatalogItem, List categories) : base(shopCatalogItem, categories) { + public ShopItemResponseModel(ShopDocument shopCatalogItem, List categories) : base(shopCatalogItem, categories) { Sku = shopCatalogItem.Sku; Rating = shopCatalogItem.Rating; Price = shopCatalogItem.Price; @@ -53,7 +55,7 @@ namespace WeatherForecast.Models.Shop.Responses { /// /// /// - public ShopItemResponseModel(ShopDocument shopCatalogItem, List categories, Locales locale) : base(shopCatalogItem, categories, locale) { + public ShopItemResponseModel(ShopDocument shopCatalogItem, List categories, Locales locale) : base(shopCatalogItem, categories, locale) { Sku = shopCatalogItem.Sku; Rating = shopCatalogItem.Rating; Price = shopCatalogItem.Price; diff --git a/src/WeatherForecast/Models/Utils/Requests/EncryptStringAesRequestModel.cs b/src/WeatherForecast/Models/Utils/Requests/EncryptStringAesRequestModel.cs new file mode 100644 index 0000000..ea94937 --- /dev/null +++ b/src/WeatherForecast/Models/Utils/Requests/EncryptStringAesRequestModel.cs @@ -0,0 +1,45 @@ +using Core.Abstractions.Models; +using Core.Enumerations; +using Extensions; +using System.ComponentModel.DataAnnotations; + +namespace WeatherForecast.Models.Utils.Requests { + + /// + /// + /// + public class EncryptStringAesRequestModel : RequestModelBase { + + /// + /// String to encrypt + /// + public string InputString { get; set; } = string.Empty; + + /// + /// + /// + public string IV { get; set; } = string.Empty; + + /// + /// + /// + public string Key { get; set; } = string.Empty; + + /// + /// + /// + /// + /// + /// + public override IEnumerable Validate(ValidationContext validationContext) { + if (string.IsNullOrEmpty(InputString)) + yield return new ValidationResult($"{nameof(InputString)} {Errors.NullOrEmpty}"); + + if (string.IsNullOrEmpty(IV)) + yield return new ValidationResult($"{nameof(IV)} {Errors.NullOrEmpty}"); + + if (string.IsNullOrEmpty(Key)) + yield return new ValidationResult($"{nameof(Key)} {Errors.NullOrEmpty}"); + } + } +} diff --git a/src/WeatherForecast/Policies/BlogAuthorizationHandler.cs b/src/WeatherForecast/Policies/BlogAuthorizationHandler.cs index 6d4c3ff..403fcef 100644 --- a/src/WeatherForecast/Policies/BlogAuthorizationHandler.cs +++ b/src/WeatherForecast/Policies/BlogAuthorizationHandler.cs @@ -1,6 +1,4 @@ using Microsoft.AspNetCore.Authorization; - -using DomainObjects.Documents; using Core.Enumerations; using DataProviders.Collections; @@ -8,6 +6,7 @@ using DataProviders.Collections; using WeatherForecast.Policies.Abstractions; using Microsoft.Extensions.Options; using DomainObjects.Documents.Users; +using DomainObjects.Documents.Posts; namespace WeatherForecast.Policies; diff --git a/src/WeatherForecast/Policies/ShopAuthorizationHandler.cs b/src/WeatherForecast/Policies/ShopAuthorizationHandler.cs index 0615a66..0ef8716 100644 --- a/src/WeatherForecast/Policies/ShopAuthorizationHandler.cs +++ b/src/WeatherForecast/Policies/ShopAuthorizationHandler.cs @@ -1,12 +1,13 @@ using Core.Enumerations; using DataProviders.Collections; -using DomainObjects.Documents; +using DomainObjects.Documents.Posts; using DomainObjects.Documents.Users; using Microsoft.AspNetCore.Authorization; using Microsoft.Extensions.Options; using WeatherForecast.Policies.Abstractions; -namespace WeatherForecast.Policies { +namespace WeatherForecast.Policies +{ /// /// diff --git a/src/WeatherForecast/Services/AccountService.cs b/src/WeatherForecast/Services/AccountService.cs index b1e55f0..e2620d1 100644 --- a/src/WeatherForecast/Services/AccountService.cs +++ b/src/WeatherForecast/Services/AccountService.cs @@ -55,7 +55,9 @@ namespace WeatherForecast.Services { /// public class AccountService : ServiceBase, IAccountService { - private readonly IAesKey _aesKey; + private readonly IAesKey _jwtTokenEncryption; + private readonly IAesKey _mailPasswordEncryption; + private readonly IJwtConfig _jwtConfig; private readonly IUserDataProvider _userDataProvider; @@ -84,9 +86,16 @@ namespace WeatherForecast.Services { if (options.Value.JwtTokenEncryption == null) throw new ArgumentNullException(); - _aesKey = options.Value.JwtTokenEncryption; + _jwtTokenEncryption = options.Value.JwtTokenEncryption; - if(options.Value.JwtConfig == null) + + if (options.Value.MailPasswordEncryption == null) + throw new ArgumentNullException(); + + _mailPasswordEncryption = options.Value.MailPasswordEncryption; + + + if (options.Value.JwtConfig == null) throw new ArgumentNullException(); _jwtConfig = options.Value.JwtConfig; @@ -104,12 +113,6 @@ namespace WeatherForecast.Services { /// public (string?, IDomainResult) Authenticate(AuthenticationRequestModel requestData) { - if (_aesKey?.IV == null || _aesKey?.Key == null) - return IDomainResult.Failed("IV or Key are not set"); - - if (_jwtConfig?.Secret == null || _jwtConfig?.Expires == null) - return IDomainResult.Failed("Secret or Expires are not set"); - // Retrieve user from database by userName var (user, getUserResult) = _userDataProvider.GetByUsername(requestData.Username); if (!getUserResult.IsSuccess || user == null) @@ -119,7 +122,7 @@ namespace WeatherForecast.Services { if (!user.Authentication.ValidatePassword(requestData.Password)) return IDomainResult.Unauthorized(); - var token = user.AddToken(_aesKey.IV, _aesKey.Key, _jwtConfig.Secret, _jwtConfig.Expires); + var token = user.AddToken(_jwtTokenEncryption.IV, _jwtTokenEncryption.Key, _jwtConfig.Secret, _jwtConfig.Expires); var (_, usdateUserResult) = _userDataProvider.Update(user); if (!usdateUserResult.IsSuccess) @@ -166,7 +169,7 @@ namespace WeatherForecast.Services { _userDataProvider.Update(user); var emailBuilder = new EmailMessageBuilder(); - emailBuilder.AddFrom(site.PassworRecoverySettings.Name, site.PassworRecoverySettings.Email.Value); + emailBuilder.AddFrom(site.PassworRecoverySettings.Email.Name ?? site.PassworRecoverySettings.Email.Value, site.PassworRecoverySettings.Email.Value); emailBuilder.AddTo(user.Username, email.Value); emailBuilder.AddSubject(site.PassworRecoverySettings.Subject); emailBuilder.AddHtmlBody(htmlBody); @@ -174,9 +177,9 @@ namespace WeatherForecast.Services { using var smtpService = new SMTPService(); - // TODO: change email password and manage configs inside database - smtpService.Connect(site.SmtpSettings.Server, site.SmtpSettings.Port, site.SmtpSettings.UseSsl); - //smtpService.Authenticate(site.PassworRecoverySettings.SmtpSettings.UserName, site.PassworRecoverySettings.SmtpSettings.GetPassword()); + var smtpSettings = site.PassworRecoverySettings.SmtpSettings; + smtpService.Connect(smtpSettings.Server, smtpSettings.Port, smtpSettings.UseSsl); + smtpService.Authenticate(smtpSettings.UserName, smtpSettings.GetPassword(_mailPasswordEncryption)); smtpService.Send(emailBuilder.Build()); diff --git a/src/WeatherForecast/Services/BlogItemService.cs b/src/WeatherForecast/Services/BlogItemService.cs index 6c2b7ce..8674162 100644 --- a/src/WeatherForecast/Services/BlogItemService.cs +++ b/src/WeatherForecast/Services/BlogItemService.cs @@ -2,18 +2,18 @@ using DataProviders.Collections; -using DomainObjects.Documents; - using WeatherForecast.Services.Abstractions; using WeatherForecast.Models.Blog.Responses; using WeatherForecast.Models.Blog.Requests; +using DomainObjects.Documents.Posts; -namespace WeatherForecast.Services { +namespace WeatherForecast.Services +{ - /// - /// - /// - public interface IBlogItemService { + /// + /// + /// + public interface IBlogItemService { /// /// diff --git a/src/WeatherForecast/Services/DkimService.cs b/src/WeatherForecast/Services/DkimService.cs index d74a1d8..3cc9db5 100644 --- a/src/WeatherForecast/Services/DkimService.cs +++ b/src/WeatherForecast/Services/DkimService.cs @@ -16,6 +16,14 @@ namespace WeatherForecast.Services { /// /// (Guid?, IDomainResult) Post(BucketFile file); + + /// + /// + /// + /// + /// + /// + IDomainResult Delete(Guid siteId, Guid fileId); } /// @@ -38,7 +46,7 @@ namespace WeatherForecast.Services { } /// - /// + /// Upload dkim private cert for website /// /// /// @@ -50,5 +58,20 @@ namespace WeatherForecast.Services { return IDomainResult.Success(fileId); } + + /// + /// + /// + /// + /// + /// + /// + public IDomainResult Delete(Guid siteId, Guid fileId) { + var result = _dkimBucketDataProvider.DeleteOne(siteId, fileId); + if (!result.IsSuccess) + return IDomainResult.Failed(); + + return IDomainResult.Success(); + } } } diff --git a/src/WeatherForecast/Services/ImageService.cs b/src/WeatherForecast/Services/ImageService.cs index 0c0e43c..e953358 100644 --- a/src/WeatherForecast/Services/ImageService.cs +++ b/src/WeatherForecast/Services/ImageService.cs @@ -42,6 +42,7 @@ namespace WeatherForecast.Services { /// /// /// + /// public ImageService( ILogger logger, IImageBucketDataProvider imageBucketDataProvider, diff --git a/src/WeatherForecast/Services/InitializationService.cs b/src/WeatherForecast/Services/InitializationService.cs index b03d552..328244a 100644 --- a/src/WeatherForecast/Services/InitializationService.cs +++ b/src/WeatherForecast/Services/InitializationService.cs @@ -57,7 +57,15 @@ public class InitializationService : ServiceBase, IInitia IDkimBucketDataProvider dkimBucketDataProvider, ITemplateBucketDataProvider serviceEmlTemplateBucketDataProvider ) : base(logger) { + + if (options.Value.JwtTokenEncryption == null) + throw new ArgumentNullException(nameof(options.Value.JwtTokenEncryption)); + _aesKey = options.Value.JwtTokenEncryption; + + if (options.Value.JwtConfig == null) + throw new ArgumentNullException(nameof(options.Value.JwtConfig)); + _jwtConfig = options.Value.JwtConfig; _siteDataProvider = siteDataProvider; _userDataProvider = userDataProvider; @@ -76,46 +84,46 @@ public class InitializationService : ServiceBase, IInitia var userId = "fdc5aa50-ee68-4bae-a8e6-b8ae2c258f60".ToGuid(); var siteId = "404c8232-9048-4519-bfba-6e78dc7005ca".ToGuid(); - #region Upload dkim for service email - var (_, dkimUpdloadResult) = _dkimBucketDataProvider.Upload(new BucketFile( - siteId, - requestData.Host, - Convert.FromBase64String(requestData.DkimBase64), - "application/x-pem-file" - )); + //#region Upload dkim for service email + //var (_, dkimUpdloadResult) = _dkimBucketDataProvider.Upload(new BucketFile( + // siteId, + // requestData.Host, + // Convert.FromBase64String(requestData.DkimBase64), + // "application/x-pem-file" + //)); - if (!dkimUpdloadResult.IsSuccess) - return IDomainResult.Failed(); - #endregion + //if (!dkimUpdloadResult.IsSuccess) + // return IDomainResult.Failed(); + //#endregion - #region Upload basic service email templates - var (templateId, _) = _serviceEmlTemplateBucketDataProvider.Upload(new BucketFile( - siteId, - "template.html", - Convert.FromBase64String(requestData.ServiceEmlTemplateBase64), - "text/html" - )); + //#region Upload basic service email templates + //var (templateId, _) = _serviceEmlTemplateBucketDataProvider.Upload(new BucketFile( + // siteId, + // "template.html", + // Convert.FromBase64String(requestData.ServiceEmlTemplateBase64), + // "text/html" + //)); - if (!dkimUpdloadResult.IsSuccess || templateId == null) - return IDomainResult.Failed(); - #endregion + //if (!dkimUpdloadResult.IsSuccess || templateId == null) + // return IDomainResult.Failed(); + //#endregion - var (_, siteInsetResult) = _siteDataProvider.Insert(new Site(requestData.SiteName, new List { requestData.Host }) { - Id = siteId, - PassworRecoverySettings = new PassworRecoverySettings { - Name = "Password recovery support", - Email = new Contact(ContactTypes.Email, $"support@{requestData.Host}"), - TemplateId = templateId.Value - } - }); + //var (_, siteInsetResult) = _siteDataProvider.Insert(new Site(requestData.SiteName, new List { requestData.Host }) { + // Id = siteId, + // PassworRecoverySettings = new PassworRecoverySettings { + // Name = "Password recovery support", + // Email = new Contact(ContactTypes.Email, $"support@{requestData.Host}"), + // TemplateId = templateId.Value + // } + //}); - var user = new User(new List { new SiteRole(siteId, Roles.Admin) }, requestData.Username, requestData.Email, requestData.Password) { - Id = userId - }; + //var user = new User(new List { new SiteRole(siteId, Roles.Admin) }, requestData.Username, requestData.Email, requestData.Password) { + // Id = userId + //}; - user.Contacts.ForEach(x => x.Confirmed = true); + //user.Contacts.ForEach(x => x.Confirmed = true); - var (_, userInsertResult) = _userDataProvider.Insert(user); + //var (_, userInsertResult) = _userDataProvider.Insert(user); return IDomainResult.Success(); } diff --git a/src/WeatherForecast/Services/ShopItemService.cs b/src/WeatherForecast/Services/ShopItemService.cs index ff47e73..59d3d6b 100644 --- a/src/WeatherForecast/Services/ShopItemService.cs +++ b/src/WeatherForecast/Services/ShopItemService.cs @@ -4,16 +4,17 @@ using DataProviders.Collections; using WeatherForecast.Models.Requests; using WeatherForecast.Services.Abstractions; -using DomainObjects.Documents; using WeatherForecast.Models.Shop.Responses; using DomainObjects.Enumerations; +using DomainObjects.Documents.Posts; -namespace WeatherForecast.Services { +namespace WeatherForecast.Services +{ - /// - /// - /// - public interface IShopItemService { + /// + /// + /// + public interface IShopItemService { /// /// diff --git a/src/WeatherForecast/Services/TemplateService.cs b/src/WeatherForecast/Services/TemplateService.cs index 34622b2..b07c7e1 100644 --- a/src/WeatherForecast/Services/TemplateService.cs +++ b/src/WeatherForecast/Services/TemplateService.cs @@ -2,53 +2,74 @@ using DataProviders.Buckets; using DomainResults.Common; -namespace WeatherForecast.Services { +namespace WeatherForecast.Services; + +/// +/// +/// +public interface ITemplateService { /// /// /// - public interface ITemplateService { + /// + /// + (Guid?, IDomainResult) Post(BucketFile file); - /// - /// - /// - /// - /// - (Guid?, IDomainResult) Post(BucketFile file); + /// + /// + /// + /// + /// + /// + IDomainResult Delete(Guid siteId, Guid fileId); +} + +/// +/// +/// +public class TemplateService : ServiceBase, ITemplateService { + + + private readonly ITemplateBucketDataProvider _templateBucketDataProvider; + + /// + /// + /// + /// + /// + public TemplateService( + ILogger logger, + ITemplateBucketDataProvider templateBucketDataProvider + ) : base(logger) { + _templateBucketDataProvider = templateBucketDataProvider; } /// /// /// - public class TemplateService : ServiceBase, ITemplateService { + /// + /// + public (Guid?, IDomainResult) Post(BucketFile file) { + var (fileId, uploadFileResult) = _templateBucketDataProvider.Upload(file); + if (!uploadFileResult.IsSuccess || fileId == null) + return IDomainResult.Failed(); - private readonly ITemplateBucketDataProvider _templateBucketDataProvider; + return IDomainResult.Success(fileId); + } - /// - /// - /// - /// - /// - public TemplateService( - ILogger logger, - ITemplateBucketDataProvider templateBucketDataProvider - ) : base(logger) { - _templateBucketDataProvider = templateBucketDataProvider; - } + /// + /// + /// + /// + /// + /// + public IDomainResult Delete(Guid siteId, Guid fileId) { + var result = _templateBucketDataProvider.DeleteOne(siteId, fileId); + if (!result.IsSuccess) + return IDomainResult.Failed(); - /// - /// - /// - /// - /// - public (Guid?, IDomainResult) Post(BucketFile file) { - - var (fileId, uploadFileResult) = _templateBucketDataProvider.Upload(file); - if (!uploadFileResult.IsSuccess || fileId == null) - return IDomainResult.Failed(); - - return IDomainResult.Success(fileId); - } + return IDomainResult.Success(); } } diff --git a/src/WeatherForecast/appsettings.json b/src/WeatherForecast/appsettings.json index a12d0e4..9005ad9 100644 --- a/src/WeatherForecast/appsettings.json +++ b/src/WeatherForecast/appsettings.json @@ -25,6 +25,11 @@ "Key": "KBsLNL2/pju3uX6Wtjkf2zUS1TbJ0YiD84zusIyPVUM=" }, + "MailPasswordEncryption": { + "IV": "1DCr+7GMT1skaTTTNSO3lA==", + "Key": "36m7ZAWCZdQC05xOyUvqBmz3sgzGShSCDTBmwvNEWNM=" + }, + "Database": { "ConnectionString": "mongodb://root:example@mongo:27017" diff --git a/src/docker-compose.dcproj b/src/docker-compose.dcproj index be68195..7f80434 100644 --- a/src/docker-compose.dcproj +++ b/src/docker-compose.dcproj @@ -5,7 +5,7 @@ Linux 7fc6f0ba-2dcb-4b53-a3b3-61ceef42b9d0 LaunchBrowser - {Scheme}://localhost:{ServicePort} + {Scheme}://localhost:{ServicePort}/swagger reverseproxy diff --git a/src/docker-compose/mongo/data/db/WiredTiger.turtle b/src/docker-compose/mongo/data/db/WiredTiger.turtle index af66381..30117f5 100644 --- a/src/docker-compose/mongo/data/db/WiredTiger.turtle +++ b/src/docker-compose/mongo/data/db/WiredTiger.turtle @@ -3,4 +3,4 @@ WiredTiger 10.0.2: (December 21, 2021) WiredTiger version major=10,minor=0,patch=2 file:WiredTiger.wt -access_pattern_hint=none,allocation_size=4KB,app_metadata=,assert=(commit_timestamp=none,durable_timestamp=none,read_timestamp=none,write_timestamp=off),block_allocation=best,block_compressor=,cache_resident=false,checksum=on,collator=,columns=,dictionary=0,encryption=(keyid=,name=),format=btree,huffman_key=,huffman_value=,id=0,ignore_in_memory_cache_size=false,internal_item_max=0,internal_key_max=0,internal_key_truncate=true,internal_page_max=4KB,key_format=S,key_gap=10,leaf_item_max=0,leaf_key_max=0,leaf_page_max=32KB,leaf_value_max=0,log=(enabled=true),memory_page_image_max=0,memory_page_max=5MB,os_cache_dirty_max=0,os_cache_max=0,prefix_compression=false,prefix_compression_min=4,readonly=false,split_deepen_min_child=0,split_deepen_per_child=0,split_pct=90,tiered_object=false,tiered_storage=(auth_token=,bucket=,bucket_prefix=,cache_directory=,local_retention=300,name=,object_target_size=0),value_format=S,verbose=[],version=(major=1,minor=1),write_timestamp_usage=none,checkpoint=(WiredTigerCheckpoint.98221=(addr="018081e4af72785d8181e4aac961f88281e479ff3f5b808080e301bfc0e2dfc0",order=98221,time=1674344889,size=69632,newest_start_durable_ts=0,oldest_start_ts=0,newest_txn=202,newest_stop_durable_ts=0,newest_stop_ts=-1,newest_stop_txn=-11,prepare=0,write_gen=295056,run_write_gen=294763)),checkpoint_backup_info=,checkpoint_lsn=(38,77312) +access_pattern_hint=none,allocation_size=4KB,app_metadata=,assert=(commit_timestamp=none,durable_timestamp=none,read_timestamp=none,write_timestamp=off),block_allocation=best,block_compressor=,cache_resident=false,checksum=on,collator=,columns=,dictionary=0,encryption=(keyid=,name=),format=btree,huffman_key=,huffman_value=,id=0,ignore_in_memory_cache_size=false,internal_item_max=0,internal_key_max=0,internal_key_truncate=true,internal_page_max=4KB,key_format=S,key_gap=10,leaf_item_max=0,leaf_key_max=0,leaf_page_max=32KB,leaf_value_max=0,log=(enabled=true),memory_page_image_max=0,memory_page_max=5MB,os_cache_dirty_max=0,os_cache_max=0,prefix_compression=false,prefix_compression_min=4,readonly=false,split_deepen_min_child=0,split_deepen_per_child=0,split_pct=90,tiered_object=false,tiered_storage=(auth_token=,bucket=,bucket_prefix=,cache_directory=,local_retention=300,name=,object_target_size=0),value_format=S,verbose=[],version=(major=1,minor=1),write_timestamp_usage=none,checkpoint=(WiredTigerCheckpoint.99539=(addr="018081e4760268df8181e4e314ef2b8281e4f0cb9f65808080e301ffc0e3010fc0",order=99539,time=1674424019,size=81920,newest_start_durable_ts=0,oldest_start_ts=0,newest_txn=3110,newest_stop_durable_ts=0,newest_stop_ts=-1,newest_stop_txn=-11,prepare=0,write_gen=299042,run_write_gen=294763)),checkpoint_backup_info=,checkpoint_lsn=(38,1188480) diff --git a/src/docker-compose/mongo/data/db/WiredTiger.wt b/src/docker-compose/mongo/data/db/WiredTiger.wt index 36bcd8c..3d595e1 100644 Binary files a/src/docker-compose/mongo/data/db/WiredTiger.wt and b/src/docker-compose/mongo/data/db/WiredTiger.wt differ diff --git a/src/docker-compose/mongo/data/db/_mdb_catalog.wt b/src/docker-compose/mongo/data/db/_mdb_catalog.wt index b67b580..5e6be18 100644 Binary files a/src/docker-compose/mongo/data/db/_mdb_catalog.wt and b/src/docker-compose/mongo/data/db/_mdb_catalog.wt differ diff --git a/src/docker-compose/mongo/data/db/collection-0--6471522924120802764.wt b/src/docker-compose/mongo/data/db/collection-0--6471522924120802764.wt new file mode 100644 index 0000000..eaacfaa Binary files /dev/null and b/src/docker-compose/mongo/data/db/collection-0--6471522924120802764.wt differ diff --git a/src/docker-compose/mongo/data/db/collection-3--6471522924120802764.wt b/src/docker-compose/mongo/data/db/collection-3--6471522924120802764.wt new file mode 100644 index 0000000..f5f29ca Binary files /dev/null and b/src/docker-compose/mongo/data/db/collection-3--6471522924120802764.wt differ diff --git a/src/docker-compose/mongo/data/db/collection-4--4715807334585891142.wt b/src/docker-compose/mongo/data/db/collection-4--4715807334585891142.wt index e298ba4..f2d83d4 100644 Binary files a/src/docker-compose/mongo/data/db/collection-4--4715807334585891142.wt and b/src/docker-compose/mongo/data/db/collection-4--4715807334585891142.wt differ diff --git a/src/docker-compose/mongo/data/db/collection-4-597769541568262742.wt b/src/docker-compose/mongo/data/db/collection-4-597769541568262742.wt index 67ba24b..3389d0a 100644 Binary files a/src/docker-compose/mongo/data/db/collection-4-597769541568262742.wt and b/src/docker-compose/mongo/data/db/collection-4-597769541568262742.wt differ diff --git a/src/docker-compose/mongo/data/db/diagnostic.data/metrics.interim b/src/docker-compose/mongo/data/db/diagnostic.data/metrics.interim index 353a9c3..cb8cd16 100644 Binary files a/src/docker-compose/mongo/data/db/diagnostic.data/metrics.interim and b/src/docker-compose/mongo/data/db/diagnostic.data/metrics.interim differ diff --git a/src/docker-compose/mongo/data/db/index-1--6471522924120802764.wt b/src/docker-compose/mongo/data/db/index-1--6471522924120802764.wt new file mode 100644 index 0000000..7d0bec0 Binary files /dev/null and b/src/docker-compose/mongo/data/db/index-1--6471522924120802764.wt differ diff --git a/src/docker-compose/mongo/data/db/index-2--6471522924120802764.wt b/src/docker-compose/mongo/data/db/index-2--6471522924120802764.wt new file mode 100644 index 0000000..ac11f4d Binary files /dev/null and b/src/docker-compose/mongo/data/db/index-2--6471522924120802764.wt differ diff --git a/src/docker-compose/mongo/data/db/index-4--6471522924120802764.wt b/src/docker-compose/mongo/data/db/index-4--6471522924120802764.wt new file mode 100644 index 0000000..13852c3 Binary files /dev/null and b/src/docker-compose/mongo/data/db/index-4--6471522924120802764.wt differ diff --git a/src/docker-compose/mongo/data/db/index-5--4715807334585891142.wt b/src/docker-compose/mongo/data/db/index-5--4715807334585891142.wt index 97cc3ae..3b78ef3 100644 Binary files a/src/docker-compose/mongo/data/db/index-5--4715807334585891142.wt and b/src/docker-compose/mongo/data/db/index-5--4715807334585891142.wt differ diff --git a/src/docker-compose/mongo/data/db/index-5--6471522924120802764.wt b/src/docker-compose/mongo/data/db/index-5--6471522924120802764.wt new file mode 100644 index 0000000..0633b24 Binary files /dev/null and b/src/docker-compose/mongo/data/db/index-5--6471522924120802764.wt differ diff --git a/src/docker-compose/mongo/data/db/index-6--4715807334585891142.wt b/src/docker-compose/mongo/data/db/index-6--4715807334585891142.wt index 81befa6..630ad6a 100644 Binary files a/src/docker-compose/mongo/data/db/index-6--4715807334585891142.wt and b/src/docker-compose/mongo/data/db/index-6--4715807334585891142.wt differ diff --git a/src/docker-compose/mongo/data/db/journal/WiredTigerLog.0000000038 b/src/docker-compose/mongo/data/db/journal/WiredTigerLog.0000000038 index 24a35a6..cae36e5 100644 Binary files a/src/docker-compose/mongo/data/db/journal/WiredTigerLog.0000000038 and b/src/docker-compose/mongo/data/db/journal/WiredTigerLog.0000000038 differ diff --git a/src/docker-compose/mongo/data/db/sizeStorer.wt b/src/docker-compose/mongo/data/db/sizeStorer.wt index 40b0b6f..64baa9e 100644 Binary files a/src/docker-compose/mongo/data/db/sizeStorer.wt and b/src/docker-compose/mongo/data/db/sizeStorer.wt differ