diff --git a/AyCode.Core/AyCode.Core.csproj b/AyCode.Core/AyCode.Core.csproj index 213344f..1966c49 100644 --- a/AyCode.Core/AyCode.Core.csproj +++ b/AyCode.Core/AyCode.Core.csproj @@ -14,4 +14,8 @@ + + + + diff --git a/AyCode.Core/Extensions/SerializeObjectToJsonExtensions.cs b/AyCode.Core/Extensions/SerializeObjectToJsonExtensions.cs new file mode 100644 index 0000000..afd90de --- /dev/null +++ b/AyCode.Core/Extensions/SerializeObjectToJsonExtensions.cs @@ -0,0 +1,22 @@ +using AyCode.Core.Interfaces; +using Newtonsoft.Json; + +namespace AyCode.Core.Extensions; + +public static class SerializeObjectToJsonExtensions +{ + private static string SerializeObjectToJson(T source) + { + JsonSerializerSettings options = new() + { + ReferenceLoopHandling = ReferenceLoopHandling.Ignore, + NullValueHandling = NullValueHandling.Ignore + }; + + return JsonConvert.SerializeObject(source, options); + } + + public static string ToJson(this T source) where T : class, IAcSerializableToJson => SerializeObjectToJson(source); + public static string ToJson(this IQueryable source) where T : class, IAcSerializableToJson => SerializeObjectToJson(source); + public static string ToJson(this IEnumerable source) where T : class, IAcSerializableToJson => SerializeObjectToJson(source); +} \ No newline at end of file diff --git a/AyCode.Database/DataLayers/AcDalBase.cs b/AyCode.Database/DataLayers/AcDalBase.cs index d02bb95..2d40532 100644 --- a/AyCode.Database/DataLayers/AcDalBase.cs +++ b/AyCode.Database/DataLayers/AcDalBase.cs @@ -7,6 +7,8 @@ using AyCode.Core.Extensions; using AyCode.Core.Helpers; using AyCode.Database.DbContexts; using AyCode.Database.Extensions; +using AyCode.Entities; +using AyCode.Interfaces; using AyCode.Interfaces.Entities; using AyCode.Utils.Extensions; using Microsoft.EntityFrameworkCore; @@ -50,6 +52,18 @@ public abstract class AcDalBase : IAcDalBase where TDbCo ctx = null; } + public TModelDto? GetModelDtoById(Guid id) where TModelDto : class, IAcModelDtoBase where TEntity : class, IEntity + => Session(ctx => ctx.GetModelDtoById(id)); + + public Task GetModelDtoByIdAsync(Guid id) where TModelDto : class, IAcModelDtoBase where TEntity : class, IEntity + => SessionAsync(ctx => ctx.GetModelDtoById(id)); + + public List GetAllModelDto() where TModelDto : class, IAcModelDtoBase where TEntity : class, IEntity + => Session(ctx => ctx.GetAllModelDto().ToList()); + public Task> GetAllModelDtoAsync() where TModelDto : class, IAcModelDtoBase where TEntity : class, IEntity + => SessionAsync(ctx => ctx.GetAllModelDto().ToList()); + + public Task SessionAsync(Func callback) => this.SessionAsync(callback); diff --git a/AyCode.Database/DataLayers/Users/AcUserDalBase.cs b/AyCode.Database/DataLayers/Users/AcUserDalBase.cs index 156739a..493b600 100644 --- a/AyCode.Database/DataLayers/Users/AcUserDalBase.cs +++ b/AyCode.Database/DataLayers/Users/AcUserDalBase.cs @@ -33,6 +33,22 @@ namespace AyCode.Database.DataLayers.Users public TUser? GetUserByEmail(string? email, bool onlyConfirmed) => Session(x => x.GetUserByEmail(email, onlyConfirmed)); public Task GetUserByEmailAsync(string? email, bool onlyConfirmed) => SessionAsync(x => x.GetUserByEmail(email, onlyConfirmed)); + public TUserModelDto? GetUserModelDtoById(Guid userId, bool onlyConfirmed) where TUserModelDto : class, IAcUserModelDtoMinBase + => Session(ctx => ctx.GetUserModelDtoById(userId, onlyConfirmed)); + public Task GetUserModelDtoByIdAsync(Guid userId, bool onlyConfirmed) where TUserModelDto : class, IAcUserModelDtoMinBase + => SessionAsync(ctx => ctx.GetUserModelDtoById(userId, onlyConfirmed)); + + public TUserModelDto? GetUserModelDtoByEmail(string email, bool onlyConfirmed) where TUserModelDto : class, IAcUserModelDtoMinBase + => Session(ctx => ctx.GetUserModelDtoByEmail(email, onlyConfirmed)); + public Task GetUserModelDtoByEmailAsync(string email, bool onlyConfirmed) where TUserModelDto : class, IAcUserModelDtoMinBase + => SessionAsync(ctx => ctx.GetUserModelDtoByEmail(email, onlyConfirmed)); + + public List GetAllUserModelDto() where TUserModelDto : class, IAcUserModelDtoMinBase + => GetAllModelDto(); + public Task> GetAllUserModelDtoAsync() where TUserModelDto : class, IAcUserModelDtoMinBase + => GetAllModelDtoAsync(); + + public Task AddUserAsync(TUser user) { return TransactionAsync(ctx => ctx.AddUser(user)); diff --git a/AyCode.Database/DbSets/Messages/AcEmailMessageDbSetExtension.cs b/AyCode.Database/DbSets/Messages/AcEmailMessageDbSetExtension.cs new file mode 100644 index 0000000..292d71b --- /dev/null +++ b/AyCode.Database/DbSets/Messages/AcEmailMessageDbSetExtension.cs @@ -0,0 +1,61 @@ +using AyCode.Interfaces.Messages; +using Microsoft.EntityFrameworkCore; + +namespace AyCode.Database.DbSets.Messages; + +public static class AcEmailMessageDbSetExtension +{ + public static TEmailMessage? GetEmailMessageById(this IAcEmailMessageDbSet ctx, Guid emailMessageId) where TEmailMessage : class, IAcEmailMessageBase + => ctx.EmailMessages.FirstOrDefault(x => x.Id == emailMessageId); + + public static IQueryable GetEmailMessagesByContextId(this IAcEmailMessageDbSet ctx, Guid contextId) where TEmailMessage : class, IAcEmailMessageBase + => ctx.EmailMessages.Where(x => x.ContextId == contextId); + + public static IQueryable GetEmailMessagesBySenderId(this IAcEmailMessageDbSet ctx, Guid senderId) where TEmailMessage : class, IAcEmailMessageBase + => ctx.EmailMessages.Where(x => x.SenderId == senderId); + + public static IQueryable GetEmailMessagesBySenderEmailAddress(this IAcEmailMessageDbSet ctx, string senderEmailAddress) where TEmailMessage : class, IAcEmailMessageBase + => ctx.EmailMessages.Where(x => x.EmailAddress == senderEmailAddress); + + private static IQueryable GetEmailMessages(this IQueryable queryableEmails, Guid userId, Guid userProductMappingId) + where TEmailMessage : class, IAcEmailMessageBase, IAcEmailRecipientsRelation + where TEmailRecipient : IAcEmailRecipientBase + { + return queryableEmails.Where(x => x.SenderId == userId || x.SenderId == userProductMappingId || x.Recipients.Any(recipient => recipient.RecipientId == userId || recipient.RecipientId == userProductMappingId)); + } + + public static IQueryable GetEmailMessages(this IAcEmailMessageDbSet ctx, Guid userId, Guid userProductMappingId) + where TEmailMessage : class, IAcEmailMessageBase, IAcEmailRecipientsRelation + where TEmailRecipient : IAcEmailRecipientBase + { + return ctx.EmailMessages.GetEmailMessages(userId, userProductMappingId); + } + + public static IQueryable GetEmailMessages(this IAcEmailMessageDbSet ctx, Guid contextId, Guid userId, Guid userProductMappingId) + where TEmailMessage : class, IAcEmailMessageBase, IAcEmailRecipientsRelation + where TEmailRecipient : IAcEmailRecipientBase + { + return ctx.GetEmailMessagesByContextId(contextId).GetEmailMessages(userId, userProductMappingId); + } + + #region Add, Update, Remove + + public static bool AddEmailMessage(this IAcEmailMessageDbSet ctx, TEmailMessage emailMessage) where TEmailMessage : class, IAcEmailMessageBase + => ctx.EmailMessages.Add(emailMessage).State == EntityState.Added; + + public static bool UpdateEmailMessage(this IAcEmailMessageDbSet ctx, TEmailMessage emailMessage) where TEmailMessage : class, IAcEmailMessageBase + => ctx.EmailMessages.Update(emailMessage).State == EntityState.Modified; + + public static bool RemoveEmailMessage(this IAcEmailMessageDbSet ctx, Guid emailMessageId) where TEmailMessage : class, IAcEmailMessageBase + { + var emailMessage = ctx.GetEmailMessageById(emailMessageId); + + return emailMessage == null || ctx.RemoveEmailMessage(emailMessage); + } + + public static bool RemoveEmailMessage(this IAcEmailMessageDbSet ctx, TEmailMessage emailMessage) where TEmailMessage : class, IAcEmailMessageBase + => ctx.EmailMessages.Remove(emailMessage).State == EntityState.Deleted; + + #endregion Add, Update, Remove + +} \ No newline at end of file diff --git a/AyCode.Database/DbSets/Messages/IAcEmailMessageDbSet.cs b/AyCode.Database/DbSets/Messages/IAcEmailMessageDbSet.cs new file mode 100644 index 0000000..4de298e --- /dev/null +++ b/AyCode.Database/DbSets/Messages/IAcEmailMessageDbSet.cs @@ -0,0 +1,9 @@ +using AyCode.Interfaces.Messages; +using Microsoft.EntityFrameworkCore; + +namespace AyCode.Database.DbSets.Messages; + +public interface IAcEmailMessageDbSet where TEmailMessage : class, IAcEmailMessageBase +{ + public DbSet EmailMessages { get; set; } +} \ No newline at end of file diff --git a/AyCode.Database/DbSets/Users/AcUserDbSetExtensions.cs b/AyCode.Database/DbSets/Users/AcUserDbSetExtensions.cs index cd2bf6a..fcc56de 100644 --- a/AyCode.Database/DbSets/Users/AcUserDbSetExtensions.cs +++ b/AyCode.Database/DbSets/Users/AcUserDbSetExtensions.cs @@ -1,9 +1,12 @@ using AyCode.Core.Extensions; using AyCode.Core.Logger; +using AyCode.Database.Extensions; +using AyCode.Entities; using AyCode.Entities.Users; using AyCode.Interfaces.Entities; using AyCode.Interfaces.Profiles; using AyCode.Interfaces.Users; +using AyCode.Models.Users; namespace AyCode.Database.DbSets.Users; @@ -14,24 +17,38 @@ public static class AcUserDbSetExtensions if (string.IsNullOrWhiteSpace(email) || string.IsNullOrWhiteSpace(passwordHash)) return null; - return ctx.GetUsersByEmail(email, onlyConfirmed).SingleOrDefault(u => u.Password == passwordHash); + return ctx.GetQueryableUserByEmail(email, onlyConfirmed)?.SingleOrDefault(u => u.Password == passwordHash); } public static TUser? GetUserById(this IAcUserDbSetBase ctx, Guid userId, bool onlyConfirmed) where TUser : class, IAcUserBase - => ctx.GetUsersById(userId, onlyConfirmed).FirstOrDefault(); + => ctx.Users.FirstOrDefault(u => u.Id == userId && (!onlyConfirmed || u.EmailConfirmed)); - public static TUser? GetUserByEmail(this IAcUserDbSetBase ctx, string? email, bool onlyConfirmed) where TUser : class, IAcUserBase + public static TUserModelDto? GetUserModelDtoById(this IAcUserDbSetBase ctx, Guid userId, bool onlyConfirmed) + where TUserModelDto : class, IAcUserModelDtoMinBase + where TUser : class, IAcUserBase { - return string.IsNullOrWhiteSpace(email) ? null : ctx.GetUsersByEmail(email, onlyConfirmed).FirstOrDefault(); + return ctx.GetUserById(userId, onlyConfirmed)?.ToModelDto(); } - public static IQueryable GetUsersById(this IAcUserDbSetBase ctx, Guid userId, bool onlyConfirmed) where TUser : class, IAcUserBase + public static TUser? GetUserByEmail(this IAcUserDbSetBase ctx, string? email, bool onlyConfirmed) where TUser : class, IAcUserBase + => ctx.GetQueryableUserByEmail(email, onlyConfirmed)?.FirstOrDefault(); + + public static TUserModelDto? GetUserModelDtoByEmail(this IAcUserDbSetBase ctx, string? email, bool onlyConfirmed) + where TUserModelDto : class, IAcUserModelDtoMinBase + where TUser : class, IAcUserBase + { + return ctx.GetUserByEmail(email, onlyConfirmed)?.ToModelDto(); + } + + public static IQueryable GetQueryableUsersById(this IAcUserDbSetBase ctx, Guid userId, bool onlyConfirmed) where TUser : class, IAcUserBase => ctx.Users.Where(u => u.Id == userId && (!onlyConfirmed || u.EmailConfirmed)); - public static IQueryable GetUsersByEmail(this IAcUserDbSetBase ctx, string email, bool onlyConfirmed) where TUser : class, IAcUserBase + public static IQueryable? GetQueryableUserByEmail(this IAcUserDbSetBase ctx, string? email, bool onlyConfirmed) where TUser : class, IAcUserBase { Logger.Info($"GetUserByEmail: {email}"); + if (string.IsNullOrWhiteSpace(email)) return null; + var emailLower = email.ToLower(); return ctx.Users.Where(u => u.EmailAddress == emailLower && (!onlyConfirmed || u.EmailConfirmed)); } diff --git a/AyCode.Database/Extensions/AcDbModelDtoExtension.cs b/AyCode.Database/Extensions/AcDbModelDtoExtension.cs new file mode 100644 index 0000000..1e0b5ec --- /dev/null +++ b/AyCode.Database/Extensions/AcDbModelDtoExtension.cs @@ -0,0 +1,18 @@ +using AyCode.Core.Interfaces; +using AyCode.Database.DbContexts; +using AyCode.Database.DbSets.Users; +using AyCode.Entities; +using AyCode.Interfaces; +using AyCode.Interfaces.Entities; +using Microsoft.EntityFrameworkCore; + +namespace AyCode.Database.Extensions; + +public static class AcDbModelDtoExtension +{ + public static TModelDto? GetModelDtoById(this AcDbContextBase ctx, Guid id) where TModelDto : class, IAcModelDtoBase where TEntity : class, IEntity + => ctx.Set().Find(id)?.ToModelDto(); + + public static IEnumerable GetAllModelDto(this AcDbContextBase ctx) where TModelDto : class, IAcModelDtoBase where TEntity : class, IEntity + => ctx.Set().ToModelDto(); +} \ No newline at end of file diff --git a/AyCode.Entities/AcModelDtoExtension.cs b/AyCode.Entities/AcModelDtoExtension.cs new file mode 100644 index 0000000..72932ee --- /dev/null +++ b/AyCode.Entities/AcModelDtoExtension.cs @@ -0,0 +1,13 @@ +using AyCode.Interfaces; +using AyCode.Interfaces.Entities; + +namespace AyCode.Entities; + +public static class AcModelDtoExtension +{ + public static TModelDto? ToModelDto(this TEntity entity) where TModelDto : class, IAcModelDtoBase where TEntity : class, IEntity + => Activator.CreateInstance(typeof(TModelDto), entity) as TModelDto; + + public static IEnumerable ToModelDto(this IEnumerable entities) where TModelDto : class, IAcModelDtoBase where TEntity : class, IEntity + => entities.Select(entity => entity.ToModelDto())!; +} \ No newline at end of file diff --git a/AyCode.Interfaces/Messages/IAcEmailMessageForeignKey.cs b/AyCode.Interfaces/Messages/IAcEmailMessageForeignKey.cs new file mode 100644 index 0000000..35c16c2 --- /dev/null +++ b/AyCode.Interfaces/Messages/IAcEmailMessageForeignKey.cs @@ -0,0 +1,9 @@ +namespace AyCode.Interfaces.Messages; + +public interface IAcEmailMessageForeignKey +{ + public T EmailMessageId { get; set; } +} + +public interface IAcEmailMessageForeignKey : IAcEmailMessageForeignKey +{ } diff --git a/AyCode.Interfaces/Messages/IAcEmailRecipientsRelation.cs b/AyCode.Interfaces/Messages/IAcEmailRecipientsRelation.cs index 33e874b..81c18cd 100644 --- a/AyCode.Interfaces/Messages/IAcEmailRecipientsRelation.cs +++ b/AyCode.Interfaces/Messages/IAcEmailRecipientsRelation.cs @@ -1,6 +1,6 @@ namespace AyCode.Interfaces.Messages; -public interface IAcEmailRecipientsRelation +public interface IAcEmailRecipientsRelation where TEmailRecipient : IAcEmailRecipientBase { public List Recipients { get; set; } } \ No newline at end of file