Compare commits

..

No commits in common. "master" and "Fullepi_Sandbox" have entirely different histories.

203 changed files with 870 additions and 6726 deletions

View File

@ -1,16 +1,9 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
</PropertyGroup>
<Import Project="..//AyCode.Core.targets" />
<ItemGroup>
<PackageReference Include="MessagePack" Version="3.1.4" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\AyCode.Core\AyCode.Core.csproj" />
</ItemGroup>
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
</Project>

View File

@ -1,76 +0,0 @@
using System.Runtime.CompilerServices;
using AyCode.Core.Enums;
using AyCode.Core.Loggers;
namespace AyCode.Core.Server.Loggers
{
public sealed class AcGlobalLoggerBase : AcLoggerBase
{ }
public sealed class GlobalLogger //: IAcLogWriterBase
{
private readonly AcGlobalLoggerBase _logger = new();
private static readonly GlobalLogger Instance = new();
public static LogLevel LogLevel => Instance._logger.LogLevel;
public static AppType AppType => Instance._logger.AppType;
private const string DefaultCategoryName = "GLOBAL_LOGGER";
static GlobalLogger()
{ }
private GlobalLogger()
{ }
public static List<IAcLogWriterBase> GetWriters => Instance._logger.GetWriters;
public static TLogWriter? Writer<TLogWriter>() where TLogWriter : IAcLogWriterBase => Instance._logger.Writer<TLogWriter>();
public static void Detail(string? text, string? categoryName = null, [CallerMemberName] string? memberName = null)
=> Instance._logger.Detail(text, categoryName ?? DefaultCategoryName, memberName);
//public static void Detail<TCallerClassType>(string? text, [CallerMemberName] string? memberName = null) where TCallerClassType : class
// => Detail(text, typeof(TCallerClassType).Name, memberName);
public static void Debug(string? text, string? categoryName = null, [CallerMemberName] string? memberName = null)
=> Instance._logger.Debug(text, categoryName ?? DefaultCategoryName, memberName);
//public static void Debug<TCallerClassType>(string? text, [CallerMemberName] string? memberName = null) where TCallerClassType : class
// => Debug(text, typeof(TCallerClassType).Name, memberName);
public static void Info(string? text, string? categoryName = null, [CallerMemberName] string? memberName = null)
=> Instance._logger.Info(text, categoryName ?? DefaultCategoryName, memberName);
//public static void Info<TCallerClassType>(string? text, [CallerMemberName] string? memberName = null) where TCallerClassType : class
// => Info(text, typeof(TCallerClassType).Name, memberName);
public static void Warning(string? text, string? categoryName = null, [CallerMemberName] string? memberName = null)
=> Instance._logger.Warning(text, categoryName ?? DefaultCategoryName, memberName);
//public static void Warning<TCallerClassType>(string? text, [CallerMemberName] string? memberName = null) where TCallerClassType : class
// => Warning(text, typeof(TCallerClassType).Name, memberName);
public static void Suggest(string? text, string? categoryName = null, [CallerMemberName] string? memberName = null)
=> Instance._logger.Suggest(text, categoryName ?? DefaultCategoryName, memberName);
//public static void Suggest<TCallerClassType>(string? text, [CallerMemberName] string? memberName = null) where TCallerClassType : class
// => Suggest(text, typeof(TCallerClassType).Name, memberName);
//public static void Error<TCallerClassType>(string? text, Exception? ex = null, [CallerMemberName] string? memberName = null) where TCallerClassType : class
// => Error(text, ex, typeof(TCallerClassType).Name, memberName);
public static void Error(string? text, Exception? ex = null, string? categoryName = null, [CallerMemberName] string? memberName = null)
=> Instance._logger.Error(text, ex, categoryName ?? DefaultCategoryName, memberName);
public static void Write(AppType appType, LogLevel logLevel, string? logText, string? callerMemberName, string? categoryName)
=> Write(appType, logLevel, logText, callerMemberName, categoryName, null, null);
public static void Write(AppType appType, LogLevel logLevel, string? logText, string? callerMemberName, string? categoryName, Exception? ex)
=> Write(appType, logLevel, logText, callerMemberName, categoryName, ex?.GetType().Name, ex?.ToString());
public static void Write(AppType appType, LogLevel logLevel, string? logText, string? callerMemberName, string? categoryName, string? errorType, string? exMessage)
=> Instance._logger.Write(appType, logLevel, logText, callerMemberName, categoryName, errorType, exMessage);
}
}

View File

@ -1,37 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<IsPackable>false</IsPackable>
<IsTestProject>true</IsTestProject>
</PropertyGroup>
<Import Project="..//AyCode.Core.targets" />
<ItemGroup>
<PackageReference Include="coverlet.collector" Version="6.0.4">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="9.0.8" />
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="9.0.8" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.14.1" />
<PackageReference Include="MSTest.TestAdapter" Version="3.10.3" />
<PackageReference Include="MSTest.TestFramework" Version="3.10.3" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\AyCode.Core.Server\AyCode.Core.Server.csproj" />
<ProjectReference Include="..\AyCode.Core.Tests\AyCode.Core.Tests.csproj" />
<ProjectReference Include="..\AyCode.Core\AyCode.Core.csproj" />
<ProjectReference Include="..\AyCode.Entities.Server\AyCode.Entities.Server.csproj" />
<ProjectReference Include="..\AyCode.Entities\AyCode.Entities.csproj" />
<ProjectReference Include="..\AyCode.Interfaces.Server\AyCode.Interfaces.Server.csproj" />
<ProjectReference Include="..\AyCode.Interfaces\AyCode.Interfaces.csproj" />
</ItemGroup>
<ItemGroup>
<Using Include="Microsoft.VisualStudio.TestTools.UnitTesting" />
</ItemGroup>
</Project>

View File

@ -1,16 +0,0 @@
using System.Runtime.CompilerServices;
using AyCode.Entities.Addresses;
using AyCode.Interfaces.Addresses;
using AyCode.Interfaces.Addresses.Dtos;
[assembly: InternalsVisibleTo("AyCode.Database.Tests")]
[assembly: InternalsVisibleTo("AyCode.Database.Tests.Users")]
[assembly: InternalsVisibleTo("AyCode.Database.Tests.Users.Internals")]
[assembly: InternalsVisibleTo("AyCode.Database.Tests.Users.Internals.UserDbContext")]
namespace AyCode.Core.Tests.Internal.Entities;
public class Address : AcAddress, IAcAddress, IAcAddressDtoBase
{
}

View File

@ -1,14 +0,0 @@
using System.Runtime.CompilerServices;
using AyCode.Entities.ServiceProviders;
[assembly: InternalsVisibleTo("AyCode.Database.Tests")]
[assembly: InternalsVisibleTo("AyCode.Database.Tests.Users")]
[assembly: InternalsVisibleTo("AyCode.Database.Tests.Users.Internals")]
[assembly: InternalsVisibleTo("AyCode.Database.Tests.Users.Internals.UserDbContext")]
namespace AyCode.Core.Tests.Internal.Entities;
public class Company : AcCompany<User, UserToCompany, Profile, Address>
{
}

View File

@ -1,14 +0,0 @@
using System.Runtime.CompilerServices;
using AyCode.Entities.Messages;
[assembly: InternalsVisibleTo("AyCode.Database.Tests")]
[assembly: InternalsVisibleTo("AyCode.Database.Tests.Users")]
[assembly: InternalsVisibleTo("AyCode.Database.Tests.Users.Internals")]
[assembly: InternalsVisibleTo("AyCode.Database.Tests.Users.Internals.UserDbContext")]
namespace AyCode.Core.Tests.Internal.Entities;
public class EmailMessage : AcEmailMessage<EmailRecipient>
{
}

View File

@ -1,14 +0,0 @@
using AyCode.Entities.Messages;
namespace AyCode.Core.Tests.Internal.Entities;
public class EmailRecipient : AcEmailRecipient<EmailMessage>
{
public EmailRecipient()
{
}
public EmailRecipient(Guid id, Guid recipientId, Guid emailMessageId, string emailAddress) : base(id, recipientId, emailMessageId, emailAddress)
{
}
}

View File

@ -1,14 +0,0 @@
using System.Runtime.CompilerServices;
using AyCode.Entities.Profiles;
[assembly: InternalsVisibleTo("AyCode.Database.Tests")]
[assembly: InternalsVisibleTo("AyCode.Database.Tests.Users")]
[assembly: InternalsVisibleTo("AyCode.Database.Tests.Users.Internals")]
[assembly: InternalsVisibleTo("AyCode.Database.Tests.Users.Internals.UserDbContext")]
namespace AyCode.Core.Tests.Internal.Entities;
public class Profile : AcProfile<Address>
{
}

View File

@ -1,22 +0,0 @@
using System.Runtime.CompilerServices;
using AyCode.Entities.Users;
[assembly: InternalsVisibleTo("AyCode.Database.Tests")]
[assembly: InternalsVisibleTo("AyCode.Database.Tests.Users")]
[assembly: InternalsVisibleTo("AyCode.Database.Tests.Users.Internals")]
[assembly: InternalsVisibleTo("AyCode.Database.Tests.Users.Internals.UserDbContext")]
namespace AyCode.Core.Tests.Internal.Entities;
public class User : AcUser<Profile, Company, UserToCompany, Address>
{
public User() { }
public User(string email, string password) : this(Guid.NewGuid(), email, password) { }
public User(Guid id, string email, string password) : base(id, email, password)
{ }
public User(Guid id, string email, string phoneNumber, string password) : base(id, email, phoneNumber, password)
{ }
public User(Guid id, string email, string phoneNumber, string password, string refreshToken) : base(id, email, phoneNumber, password, refreshToken)
{ }
}

View File

@ -1,14 +0,0 @@
using System.Runtime.CompilerServices;
using AyCode.Entities.Users;
[assembly: InternalsVisibleTo("AyCode.Database.Tests")]
[assembly: InternalsVisibleTo("AyCode.Database.Tests.Users")]
[assembly: InternalsVisibleTo("AyCode.Database.Tests.Users.Internals")]
[assembly: InternalsVisibleTo("AyCode.Database.Tests.Users.Internals.UserDbContext")]
namespace AyCode.Core.Tests.Internal.Entities;
public class UserToCompany: AcUserToCompany<User, Company>
{
}

View File

@ -1,14 +0,0 @@
using System.Runtime.CompilerServices;
using AyCode.Entities.Users;
[assembly: InternalsVisibleTo("AyCode.Database.Tests")]
[assembly: InternalsVisibleTo("AyCode.Database.Tests.Users")]
[assembly: InternalsVisibleTo("AyCode.Database.Tests.Users.Internals")]
[assembly: InternalsVisibleTo("AyCode.Database.Tests.Users.Internals.UserDbContext")]
namespace AyCode.Core.Tests.Internal.Entities;
public class UserToken : AcUserTokenBase
{
}

View File

@ -1,31 +1,22 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<IsPackable>false</IsPackable>
<IsTestProject>true</IsTestProject>
</PropertyGroup>
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<Import Project="..//AyCode.Core.targets" />
<IsPackable>false</IsPackable>
<IsTestProject>true</IsTestProject>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="9.0.8" />
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="9.0.8" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.14.1" />
<PackageReference Include="MSTest.TestAdapter" Version="3.10.3" />
<PackageReference Include="MSTest.TestFramework" Version="3.10.3" />
<PackageReference Include="coverlet.collector" Version="6.0.4">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\AyCode.Core.Server\AyCode.Core.Server.csproj" />
<ProjectReference Include="..\AyCode.Core\AyCode.Core.csproj" />
<ProjectReference Include="..\AyCode.Entities.Server\AyCode.Entities.Server.csproj" />
<ProjectReference Include="..\AyCode.Entities\AyCode.Entities.csproj" />
<ProjectReference Include="..\AyCode.Interfaces.Server\AyCode.Interfaces.Server.csproj" />
<ProjectReference Include="..\AyCode.Interfaces\AyCode.Interfaces.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.8.0" />
<PackageReference Include="MSTest.TestAdapter" Version="3.1.1" />
<PackageReference Include="MSTest.TestFramework" Version="3.1.1" />
<PackageReference Include="coverlet.collector" Version="6.0.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
</ItemGroup>
</Project>

View File

@ -1,7 +1,4 @@
using AyCode.Core.Consts;
using Microsoft.Extensions.Configuration;
namespace AyCode.Core.Tests;
namespace AyCode.Core.Tests;
public abstract class TestModelBase
{

View File

@ -25,130 +25,80 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AyCode.Database.Tests", "Ay
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AyCode.Core.Tests", "AyCode.Core.Tests\AyCode.Core.Tests.csproj", "{320A245F-6731-476D-A9D8-77888E6B5D9C}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AyCode.Models", "AyCode.Models\AyCode.Models.csproj", "{21392620-7D0E-44B6-9485-93C57F944C20}"
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AyCode.Models", "AyCode.Models\AyCode.Models.csproj", "{21392620-7D0E-44B6-9485-93C57F944C20}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AyCode.Services", "AyCode.Services\AyCode.Services.csproj", "{58C8A6A7-D624-4E32-93B9-16B879405CAA}"
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AyCode.Services", "AyCode.Services\AyCode.Services.csproj", "{58C8A6A7-D624-4E32-93B9-16B879405CAA}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AyCode.Models.Server", "AyCode.Models.Server\AyCode.Models.Server.csproj", "{44CF90C8-76E4-4BD6-A957-E8F7AE019B06}"
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AyCode.Models.Server", "AyCode.Models.Server\AyCode.Models.Server.csproj", "{44CF90C8-76E4-4BD6-A957-E8F7AE019B06}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AyCode.Services.Server", "AyCode.Services.Server\AyCode.Services.Server.csproj", "{3C74C94F-2FEB-47F7-ABB3-B0C9CBCCC876}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AyCode.Services.Server.Tests", "AyCode.Services.Server.Tests\AyCode.Services.Server.Tests.csproj", "{9AC9AF60-280A-4871-A7FA-69AB4D0C858A}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AyCode.Core.Tests.Internal", "AyCode.Core.Tests.Internal\AyCode.Core.Tests.Internal.csproj", "{DE2DD6A4-A906-4BA6-8AAA-2A0433DF523F}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AyCode.Database.Tests.Internal", "AyCode.Database.Tests.Internal\AyCode.Database.Tests.Internal.csproj", "{73261A8C-FB41-4C4C-90D4-ED5EEC991413}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{8EC462FD-D22E-90A8-E5CE-7E832BA40C5D}"
ProjectSection(SolutionItems) = preProject
AyCode.Core.targets = AyCode.Core.targets
EndProjectSection
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AyCode.Services.Server", "AyCode.Services.Server\AyCode.Services.Server.csproj", "{3C74C94F-2FEB-47F7-ABB3-B0C9CBCCC876}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Product|Any CPU = Product|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{8CCC4969-7306-4747-8A58-80AC5A062EE1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{8CCC4969-7306-4747-8A58-80AC5A062EE1}.Debug|Any CPU.Build.0 = Debug|Any CPU
{8CCC4969-7306-4747-8A58-80AC5A062EE1}.Product|Any CPU.ActiveCfg = Product|Any CPU
{8CCC4969-7306-4747-8A58-80AC5A062EE1}.Product|Any CPU.Build.0 = Product|Any CPU
{8CCC4969-7306-4747-8A58-80AC5A062EE1}.Release|Any CPU.ActiveCfg = Release|Any CPU
{8CCC4969-7306-4747-8A58-80AC5A062EE1}.Release|Any CPU.Build.0 = Release|Any CPU
{A2105535-1397-4307-B61B-E49C983353B9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A2105535-1397-4307-B61B-E49C983353B9}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A2105535-1397-4307-B61B-E49C983353B9}.Product|Any CPU.ActiveCfg = Product|Any CPU
{A2105535-1397-4307-B61B-E49C983353B9}.Product|Any CPU.Build.0 = Product|Any CPU
{A2105535-1397-4307-B61B-E49C983353B9}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A2105535-1397-4307-B61B-E49C983353B9}.Release|Any CPU.Build.0 = Release|Any CPU
{FB027D80-8949-403B-9A86-8E99F305016E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{FB027D80-8949-403B-9A86-8E99F305016E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{FB027D80-8949-403B-9A86-8E99F305016E}.Product|Any CPU.ActiveCfg = Product|Any CPU
{FB027D80-8949-403B-9A86-8E99F305016E}.Product|Any CPU.Build.0 = Product|Any CPU
{FB027D80-8949-403B-9A86-8E99F305016E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{FB027D80-8949-403B-9A86-8E99F305016E}.Release|Any CPU.Build.0 = Release|Any CPU
{CAB60420-9F66-42D9-B67E-8E837DBA1F30}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{CAB60420-9F66-42D9-B67E-8E837DBA1F30}.Debug|Any CPU.Build.0 = Debug|Any CPU
{CAB60420-9F66-42D9-B67E-8E837DBA1F30}.Product|Any CPU.ActiveCfg = Product|Any CPU
{CAB60420-9F66-42D9-B67E-8E837DBA1F30}.Product|Any CPU.Build.0 = Product|Any CPU
{CAB60420-9F66-42D9-B67E-8E837DBA1F30}.Release|Any CPU.ActiveCfg = Release|Any CPU
{CAB60420-9F66-42D9-B67E-8E837DBA1F30}.Release|Any CPU.Build.0 = Release|Any CPU
{DC42F79D-EEF0-4F32-8608-230F24C6F22A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{DC42F79D-EEF0-4F32-8608-230F24C6F22A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{DC42F79D-EEF0-4F32-8608-230F24C6F22A}.Product|Any CPU.ActiveCfg = Product|Any CPU
{DC42F79D-EEF0-4F32-8608-230F24C6F22A}.Product|Any CPU.Build.0 = Product|Any CPU
{DC42F79D-EEF0-4F32-8608-230F24C6F22A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{DC42F79D-EEF0-4F32-8608-230F24C6F22A}.Release|Any CPU.Build.0 = Release|Any CPU
{0B5AC35E-3E71-42DC-B503-80D6D3089F91}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{0B5AC35E-3E71-42DC-B503-80D6D3089F91}.Debug|Any CPU.Build.0 = Debug|Any CPU
{0B5AC35E-3E71-42DC-B503-80D6D3089F91}.Product|Any CPU.ActiveCfg = Product|Any CPU
{0B5AC35E-3E71-42DC-B503-80D6D3089F91}.Product|Any CPU.Build.0 = Product|Any CPU
{0B5AC35E-3E71-42DC-B503-80D6D3089F91}.Release|Any CPU.ActiveCfg = Release|Any CPU
{0B5AC35E-3E71-42DC-B503-80D6D3089F91}.Release|Any CPU.Build.0 = Release|Any CPU
{F8ECCA33-B5EA-490D-B1A1-D33B5E4238A5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{F8ECCA33-B5EA-490D-B1A1-D33B5E4238A5}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F8ECCA33-B5EA-490D-B1A1-D33B5E4238A5}.Product|Any CPU.ActiveCfg = Product|Any CPU
{F8ECCA33-B5EA-490D-B1A1-D33B5E4238A5}.Product|Any CPU.Build.0 = Product|Any CPU
{F8ECCA33-B5EA-490D-B1A1-D33B5E4238A5}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F8ECCA33-B5EA-490D-B1A1-D33B5E4238A5}.Release|Any CPU.Build.0 = Release|Any CPU
{35D47907-CE4F-435B-823E-A02BE59C16D7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{35D47907-CE4F-435B-823E-A02BE59C16D7}.Debug|Any CPU.Build.0 = Debug|Any CPU
{35D47907-CE4F-435B-823E-A02BE59C16D7}.Product|Any CPU.ActiveCfg = Product|Any CPU
{35D47907-CE4F-435B-823E-A02BE59C16D7}.Product|Any CPU.Build.0 = Product|Any CPU
{35D47907-CE4F-435B-823E-A02BE59C16D7}.Release|Any CPU.ActiveCfg = Release|Any CPU
{35D47907-CE4F-435B-823E-A02BE59C16D7}.Release|Any CPU.Build.0 = Release|Any CPU
{EBC6371C-9454-473D-9547-DF9DECEB2D2A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{EBC6371C-9454-473D-9547-DF9DECEB2D2A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{EBC6371C-9454-473D-9547-DF9DECEB2D2A}.Product|Any CPU.ActiveCfg = Product|Any CPU
{EBC6371C-9454-473D-9547-DF9DECEB2D2A}.Product|Any CPU.Build.0 = Product|Any CPU
{EBC6371C-9454-473D-9547-DF9DECEB2D2A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{EBC6371C-9454-473D-9547-DF9DECEB2D2A}.Release|Any CPU.Build.0 = Release|Any CPU
{15272F57-771E-47BE-A960-AD75935254D0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{15272F57-771E-47BE-A960-AD75935254D0}.Debug|Any CPU.Build.0 = Debug|Any CPU
{15272F57-771E-47BE-A960-AD75935254D0}.Product|Any CPU.ActiveCfg = Product|Any CPU
{15272F57-771E-47BE-A960-AD75935254D0}.Release|Any CPU.ActiveCfg = Release|Any CPU
{15272F57-771E-47BE-A960-AD75935254D0}.Release|Any CPU.Build.0 = Release|Any CPU
{320A245F-6731-476D-A9D8-77888E6B5D9C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{320A245F-6731-476D-A9D8-77888E6B5D9C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{320A245F-6731-476D-A9D8-77888E6B5D9C}.Product|Any CPU.ActiveCfg = Product|Any CPU
{320A245F-6731-476D-A9D8-77888E6B5D9C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{320A245F-6731-476D-A9D8-77888E6B5D9C}.Release|Any CPU.Build.0 = Release|Any CPU
{21392620-7D0E-44B6-9485-93C57F944C20}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{21392620-7D0E-44B6-9485-93C57F944C20}.Debug|Any CPU.Build.0 = Debug|Any CPU
{21392620-7D0E-44B6-9485-93C57F944C20}.Product|Any CPU.ActiveCfg = Product|Any CPU
{21392620-7D0E-44B6-9485-93C57F944C20}.Product|Any CPU.Build.0 = Product|Any CPU
{21392620-7D0E-44B6-9485-93C57F944C20}.Release|Any CPU.ActiveCfg = Release|Any CPU
{21392620-7D0E-44B6-9485-93C57F944C20}.Release|Any CPU.Build.0 = Release|Any CPU
{58C8A6A7-D624-4E32-93B9-16B879405CAA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{58C8A6A7-D624-4E32-93B9-16B879405CAA}.Debug|Any CPU.Build.0 = Debug|Any CPU
{58C8A6A7-D624-4E32-93B9-16B879405CAA}.Product|Any CPU.ActiveCfg = Product|Any CPU
{58C8A6A7-D624-4E32-93B9-16B879405CAA}.Product|Any CPU.Build.0 = Product|Any CPU
{58C8A6A7-D624-4E32-93B9-16B879405CAA}.Release|Any CPU.ActiveCfg = Release|Any CPU
{58C8A6A7-D624-4E32-93B9-16B879405CAA}.Release|Any CPU.Build.0 = Release|Any CPU
{44CF90C8-76E4-4BD6-A957-E8F7AE019B06}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{44CF90C8-76E4-4BD6-A957-E8F7AE019B06}.Debug|Any CPU.Build.0 = Debug|Any CPU
{44CF90C8-76E4-4BD6-A957-E8F7AE019B06}.Product|Any CPU.ActiveCfg = Product|Any CPU
{44CF90C8-76E4-4BD6-A957-E8F7AE019B06}.Product|Any CPU.Build.0 = Product|Any CPU
{44CF90C8-76E4-4BD6-A957-E8F7AE019B06}.Release|Any CPU.ActiveCfg = Release|Any CPU
{44CF90C8-76E4-4BD6-A957-E8F7AE019B06}.Release|Any CPU.Build.0 = Release|Any CPU
{3C74C94F-2FEB-47F7-ABB3-B0C9CBCCC876}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{3C74C94F-2FEB-47F7-ABB3-B0C9CBCCC876}.Debug|Any CPU.Build.0 = Debug|Any CPU
{3C74C94F-2FEB-47F7-ABB3-B0C9CBCCC876}.Product|Any CPU.ActiveCfg = Product|Any CPU
{3C74C94F-2FEB-47F7-ABB3-B0C9CBCCC876}.Product|Any CPU.Build.0 = Product|Any CPU
{3C74C94F-2FEB-47F7-ABB3-B0C9CBCCC876}.Release|Any CPU.ActiveCfg = Release|Any CPU
{3C74C94F-2FEB-47F7-ABB3-B0C9CBCCC876}.Release|Any CPU.Build.0 = Release|Any CPU
{9AC9AF60-280A-4871-A7FA-69AB4D0C858A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{9AC9AF60-280A-4871-A7FA-69AB4D0C858A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{9AC9AF60-280A-4871-A7FA-69AB4D0C858A}.Product|Any CPU.ActiveCfg = Product|Any CPU
{9AC9AF60-280A-4871-A7FA-69AB4D0C858A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{DE2DD6A4-A906-4BA6-8AAA-2A0433DF523F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{DE2DD6A4-A906-4BA6-8AAA-2A0433DF523F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{DE2DD6A4-A906-4BA6-8AAA-2A0433DF523F}.Product|Any CPU.ActiveCfg = Product|Any CPU
{DE2DD6A4-A906-4BA6-8AAA-2A0433DF523F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{73261A8C-FB41-4C4C-90D4-ED5EEC991413}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{73261A8C-FB41-4C4C-90D4-ED5EEC991413}.Debug|Any CPU.Build.0 = Debug|Any CPU
{73261A8C-FB41-4C4C-90D4-ED5EEC991413}.Product|Any CPU.ActiveCfg = Product|Any CPU
{73261A8C-FB41-4C4C-90D4-ED5EEC991413}.Release|Any CPU.ActiveCfg = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

View File

@ -1,12 +0,0 @@
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Name>AyCode.Core.targets</Name>
<TargetFramework>net9.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<Configurations>Debug;Release;Product</Configurations>
<BaseOutputPath>bin\Master</BaseOutputPath>
</PropertyGroup>
</Project>

View File

@ -1,79 +0,0 @@
namespace AyCode.Core
{
/// <summary>
/// Singleton!
/// </summary>
public sealed class AcDomain
{
private readonly object _forLock = new();
private static readonly AcDomain Instance = new();
private int _uniqueInt32;
private long _uniqueInt64;
private string _processName;
public string ProcessName => Instance._processName;
static AcDomain()
{ }
private AcDomain()
{
//AppDomain.CurrentDomain.UnhandledException += (sender, args) =>
//{
// var ex = (Exception) args?.ExceptionObject;
// if (ex == null) Instance._logger.Error($"GLOBAL EXCEPTION");
// else Instance._logger.Error($"GLOBAL EXCEPTION{Env.NL}{ex.Message}{Env.NL}{sender}", ex);
//};
//_processName = System.Diagnostics.Process.GetCurrentProcess()?.ProcessName ?? "Unknown ProcessName";
}
public static bool IsDeveloperVersion
{
get
{
#if PRODUCT
{
return false;
}
#endif
return true;
}
}
public static bool IsProductVersion
{
get
{
#if PRODUCT
{
return true;
}
#endif
return false;
}
}
//public static string CdnBaseUrl => IsProductVersion ? "https://cdn2.anataworld.com/" : "https://cdn2.anataworld.com/";
/// <summary>
///
/// </summary>
/// <param name="multiplier"></param>
/// <returns>(int)(multiplier * Environment.ProcessorCount), but minimum: 1</returns>
public static int ProcessorCount(double multiplier = 1)
{
var pCount = (int)(multiplier * Environment.ProcessorCount);
return pCount > 0 ? pCount : ++pCount;
}
public static int NextUniqueInt32 => Interlocked.Increment(ref Instance._uniqueInt32);
public static long NextUniqueInt64 => Interlocked.Increment(ref Instance._uniqueInt64);
}
}

View File

@ -1,20 +1,13 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
</PropertyGroup>
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<Import Project="..//AyCode.Core.targets" />
<ItemGroup>
<ProjectReference Include="..\AyCode.Utils\AyCode.Utils.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="AutoMapper" Version="15.0.1" />
<PackageReference Include="MessagePack" Version="3.1.4" />
<PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="9.0.8" />
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="9.0.8" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\AyCode.Utils\AyCode.Utils.csproj" />
</ItemGroup>
</Project>

View File

@ -1,16 +1,7 @@
using System.Runtime.InteropServices;
using System.Security;
using System.Text;
using AyCode.Core.Extensions;
using AyCode.Utils.Extensions;
namespace AyCode.Core.Consts
namespace AyCode.Core.Consts
{
public abstract class AcConst
public static class AcConst
{
public static Guid ProjectId;
public static string ProjectSalt;
public const int ImageUploadLimit = 4096 * 1024;
public static int ConsentCount = 1;
@ -56,7 +47,6 @@ namespace AyCode.Core.Consts
/// MainScene, Lobby
/// </summary>
public static readonly Guid AnataCity;
public static readonly Guid PlayerGarage;
public static readonly Guid PlayerWardrobe;
public static readonly Guid LoadingId;
@ -66,7 +56,6 @@ namespace AyCode.Core.Consts
/// RegionAdmin
/// </summary>
public static readonly Guid RegionAdminUserId;
public static readonly Guid RegionAdminPlayerId;
public static readonly Guid GamePlayer;
@ -78,13 +67,8 @@ namespace AyCode.Core.Consts
public static string[] AvailableDomainSuffixes = new string[] { "3d", "anata", "app", "art", "club", "game", "blog", "shop", "biz", "chat", "conf", "city", "com", "net", "cool", "dance", "date", "fun", "design", "digital", "estate", "metaverse", "mv", "events", "fans", "fashion", "makeup", "fin", "fm", "sport", "gallery", "io", "info", "job", "mev", "land", "world", "life", "live", "lol", "love", "market", "media", "museum", "news", "ngo", "ninja", "kiwi", "one", "org", "party", "pink", "press", "slide", "property", "pub", "race", "sale", "school", "science", "social", "study", "style", "support", "tattoo", "team", "tech", "theatre", "town", "trade", "travel", "tv", "university", "education", "video", "vip", "vision", "wiki", "work", "xxx", "yeti", "ac", "ad", "ae", "af", "ag", "ai", "al", "am", "ao", "aq", "ar", "as", "at", "au", "aw", "ax", "az", "ba", "bb", "bd", "be", "bf", "bg", "bh", "bi", "bj", "bm", "bn", "bo", "bq", "br", "bs", "bt", "bw", "by", "bz", "ca", "cc", "cd", "cf", "cg", "ch", "ci", "ck", "cl", "cm", "cn", "co", "cr", "cu", "cv", "cw", "cx", "cy", "cz", "de", "dj", "dk", "dm", "do", "dz", "ec", "ee", "eg", "eh", "er", "es", "et", "eu", "fi", "fj", "fk", "fm", "fo", "fr", "ga", "gd", "ge", "gf", "gg", "gh", "gi", "gl", "gm", "gn", "gp", "gq", "gr", "gs", "gt", "gu", "gw", "gy", "hk", "hm", "hn", "hr", "ht", "hu", "id", "ie", "il", "im", "in", "io", "iq", "ir", "is", "it", "je", "jm", "jo", "jp", "ke", "kg", "kh", "ki", "km", "kn", "kp", "kr", "kw", "ky", "kz", "la", "lb", "lc", "li", "lk", "lr", "ls", "lt", "lu", "lv", "ly", "ma", "mc", "md", "me", "mg", "mh", "mk", "ml", "mm", "mn", "mo", "mp", "mq", "mr", "ms", "mt", "mu", "mv", "mw", "mx", "my", "mz", "na", "nc", "ne", "nf", "ng", "ni", "nl", "no", "np", "nr", "nu", "nz", "om", "pa", "pe", "pf", "pg", "ph", "pk", "pl", "pm", "pn", "pr", "ps", "pt", "pw", "py", "qa", "re", "ro", "rs", "ru", "rw", "sa", "sb", "sc", "sd", "se", "sg", "sh", "si", "sk", "sl", "sm", "sn", "so", "sr", "ss", "st", "su", "sv", "sx", "sy", "sz", "tc", "td", "tf", "tg", "th", "tj", "tk", "tl", "tm", "tn", "to", "tr", "tt", "tv", "tw", "tz", "ua", "ug", "uk", "us", "uy", "uz", "va", "vc", "ve", "vg", "vi", "vn", "vu", "wf", "ws", "ye", "yt", "za", "zm", "zw" };
//TODO: kitörölni és DB-ből kiszedni! - J.
//private static string _tiamProjectIdString = "684f34d1-163a-4077-918f-a9d9df5ce789";
static AcConst()
{
ProjectId = Guid.Parse(AcEnv.AppConfiguration["AyCode:ProjectId"].ToLower());
ProjectSalt = GenerateProjectSalt(ProjectId.ToString("N").ToLower());
//var anataFolder = AcDomain.IsProductVersion ? "Anata" : "AnataDev";
//AnataRootCacheFolder = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "AyCode", anataFolder);
@ -116,30 +100,5 @@ namespace AyCode.Core.Consts
//AnataWorldDomainId = Guid.Parse("8EFA53B3-7114-41E2-98F1-D690ECF509D2");
//AnataWorldBrandId = Guid.Parse("99265775-4B19-4975-B338-EB0F2F890806");
}
//SEMMILYEN KÖRÜLMÉNYEK KÖZÖTT SE VÁLTOZTASD MEG METÓDUS LOGIKÁJÁT!!! Különben senki sem fog tudni Login-olni! - J.
public static string GenerateProjectSalt(string projectIdString)
{
if (projectIdString.IsNullOrWhiteSpace()) return string.Empty;
var projectSalt = new StringBuilder();
var projectIdChars = projectIdString.ToCharArray();
var mid = (projectIdChars.Length + 1) / 2;
var firstHalf = projectIdChars.Take(mid).Reverse();
var secondHalf = projectIdChars.Skip(mid).Reverse();
var mixedChars = firstHalf.MixCharacters(secondHalf).ToArray();
for (var i = mixedChars.Length - 1; i >= 0; i--)
{
projectSalt.Append(mixedChars[i]);
mixedChars[i] = ' ';
projectIdChars[i] = ' ';
}
return projectSalt.ToString();
}
}
}

View File

@ -1,8 +1,5 @@
//using Anata.Logger;
using AyCode.Core.Enums;
using Microsoft.Extensions.Configuration;
namespace AyCode.Core.Consts
{
//TODO: Adatbázisból kéne a környezeti beállításokat - J.
@ -21,25 +18,5 @@ namespace AyCode.Core.Consts
//public static LogLevel LogLevel = LogLevel.Detail;
public static ulong MaxLogItemsPerSession = 250;
private static IConfiguration? _appConfiguration = null;
public static IConfiguration AppConfiguration => _appConfiguration ??= GetAppSettingsConfiguration();
public static TEnum GetEnum<TEnum>(this IConfiguration configuration, string configPath) where TEnum : struct
=> (TEnum)Enum.Parse(typeof(TEnum), configuration[configPath]);
public static TEnum GetEnum<TEnum>(this IConfigurationSection section, string configPath) where TEnum : struct
=> (TEnum)Enum.Parse(typeof(TEnum), section[configPath]);
private static IConfiguration GetAppSettingsConfiguration(string appSettingsFileName = "appsettings.json")
{
var config = new ConfigurationBuilder()
.AddJsonFile(appSettingsFileName)
.AddEnvironmentVariables()
.Build();
return config;
}
}
}

View File

@ -2,6 +2,8 @@
{
public enum AcErrorCode : byte
{
Unset = 255,
//[DisplayName("Unknown error")]
UnknownError = 0,
InvalidMessage = 1,
@ -51,11 +53,5 @@
DomainIdNotFound = 43,
DisableAddUser = 44,
PhoneNumberFormatIsNotValid = 45,
RefreshTokenUpdateError = 50,
EmailIsNullOrEmpty = 55,
Unset = 255,
}
}

View File

@ -1,20 +0,0 @@
using System.Text.RegularExpressions;
namespace AyCode.Core.Consts;
public static partial class AcRegExpression
{
//public const string EmailMask = @"^[\w\.-]+@[\w-]+\.[a-zA-Z]{2,}(?:\.[a-zA-Z]{2,})?$";
//public const string EmailMask = @"([\w\.-])+@([\w-])+\.(\w|-){2,4}(?:\.[a-zA-Z]{2,4})?";
public const string EmailMask = @"((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?";
//public const string EmailMask = @"[\w\.-]+@[a-zA-Z\d-]+.[a-zA-Z]{2,}(.[a-zA-Z]{2,})?";
//public const string EmailMask = @"(\w|[.-])+@(\w|-)+\.(\w|-){2,4}"; //original
//public const string PhoneNumberMask = @"\+(9[976]\d|8[987530]\d|6[987]\d|5[90]\d|42\d|3[875]\d|2[98654321]\d|9[8543210]|8[6421]|6[6543210]|5[87654321]|4[987654310]|3[9643210]|2[70]|7|1)\W*\d\W*\d\W*\d\W*\d\W*\d\W*\d\W*\d\W*\d\W*(\d{1,2})";
public const string PhoneNumberMask = @"\+(9[976]\d|8[987530]\d|6[987]\d|5[90]\d|42\d|3[875]\d|2[98654321]\d|9[8543210]|8[6421]|6[6543210]|5[87654321]|4[987654310]|3[9643210]|2[70]|7|1)\W*\d(\W*\d){1,14}";
[GeneratedRegex(AcRegExpression.EmailMask)]
public static partial Regex EmailRegex();
[GeneratedRegex(AcRegExpression.PhoneNumberMask)]
public static partial Regex PhoneNumberRegex();
}

View File

@ -1,16 +1,10 @@
using AyCode.Utils.Extensions;
using System.Text.RegularExpressions;
using AyCode.Core.Extensions;
namespace AyCode.Core.Consts
{
public static class AcValidate
{
public static bool IsValidEmailAndPasswordFormat(string? email, string? password, out AcErrorCode acErrorCode)
{
return IsValidEmailFormat(email, out acErrorCode) && IsValidPasswordFormat(password, out acErrorCode);
}
public static bool IsValidUserNameAndPasswordFormat(string username, string password, out AcErrorCode acErrorCode)
{
return IsValidUserNameFormat(username, out acErrorCode) && IsValidPasswordFormat(password, out acErrorCode);
@ -36,38 +30,27 @@ namespace AyCode.Core.Consts
return isValid;
}
public static bool IsValidPasswordFormat(string? password, out AcErrorCode acErrorCode)
public static bool IsValidPasswordFormat(string password, out AcErrorCode acErrorCode)
{
acErrorCode = AcErrorCode.Unset;
var isValid = !string.IsNullOrWhiteSpace(password) && password.Length is >= AcConst.MinPasswordLength and <= AcConst.MaxPasswordLength;
var isValid = !password.IsNullOrWhiteSpace() && password.Length is >= AcConst.MinPasswordLength and <= AcConst.MaxPasswordLength;
if (!isValid) acErrorCode = AcErrorCode.PasswordIsTooShort;
return isValid;
}
public static bool IsValidEmailFormat(string? email, out AcErrorCode acErrorCode)
public static bool IsValidEmailFormat(string email, out AcErrorCode acErrorCode)
{
acErrorCode = AcErrorCode.Unset;
//a@a.a -> length == 5
//var isValid = !email.IsNullOrWhiteSpace() && email.Length >= 5 && email.Contains('@') && email.Contains('.') && !email.Contains(' ');
var isValid = !string.IsNullOrWhiteSpace(email) && AcRegExpression.EmailRegex().IsMatch(email);
var isValid = !email.IsNullOrWhiteSpace() && email.Length >= 5 && email.Contains('@') && email.Contains('.') && !email.Contains(' ');
if (!isValid) acErrorCode = AcErrorCode.EmailFormatIsNotValid;
return isValid;
}
public static bool IsValidPhoneNumberFormat(string phoneNumber, out AcErrorCode acErrorCode)
{
acErrorCode = AcErrorCode.Unset;
var isValid = AcRegExpression.PhoneNumberRegex().IsMatch(phoneNumber);
if (!isValid) acErrorCode = AcErrorCode.PhoneNumberFormatIsNotValid;
return isValid;
}
public static bool IsValidUserTokenFormat(string verificationToken, out AcErrorCode acErrorCode)
{
acErrorCode = AcErrorCode.Unset;

View File

@ -9,6 +9,6 @@
Web = 15,
Mobile = 20,
Dissonance = 25,
TestUnit = 255,
UnitTest = 255,
}
}

View File

@ -1,12 +0,0 @@
namespace AyCode.Core.Enums;
public enum MessageContextType : byte
{
Unset = 0,
System = 5,
Private = 10,
Group = 15,
Transfer = 20,
Product = 25,
Company = 30,
}

View File

@ -1,18 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace AyCode.Core.Enums
{
public enum TrackingState : byte
{
None = 0,
Get = 1,
GetAll = 2,
Add = 3,
Update = 4,
Remove = 5,
}
}

View File

@ -1,106 +0,0 @@
using AyCode.Core.Enums;
using AyCode.Core.Interfaces;
using AyCode.Utils.Extensions;
namespace AyCode.Core.Extensions
{
public static class CollectionExtensions
{
public static void UpdateCollection<TDataItem>(this IList<TDataItem> source, IList<TDataItem> dataItems, bool isRemove) where TDataItem : IId<Guid>
{
if (source == null) throw new ArgumentNullException(nameof(source), $"source == null");
if (dataItems == null) throw new ArgumentNullException(nameof(dataItems), $"dataItems == null");
foreach (var dataItem in dataItems)
{
source.UpdateCollection(dataItem, isRemove);
}
}
public static TrackingState UpdateCollection<TDataItem>(this IList<TDataItem> source, TDataItem dataItem, bool isRemove) where TDataItem : IId<Guid>
{
if (source == null) throw new ArgumentNullException(nameof(source), $"source == null");
if (dataItem.Id.IsNullOrEmpty()) throw new ArgumentNullException(nameof(dataItem), "UpdateCollection->dataItem.Id.IsNullOrEmpty()");
var transferIndex = source.FindIndex(x => x.Id == dataItem.Id);
if (isRemove)
{
if (transferIndex > -1) source.RemoveAt(transferIndex);
return TrackingState.Remove;
}
if (transferIndex > -1)
{
source[transferIndex] = dataItem;
return TrackingState.Update;
}
source.Add(dataItem);
return TrackingState.Add;
}
public static int FindIndex<T>(this IList<T> list, Predicate<T> predicate)
{
for (var index = 0; index < list.Count; ++index)
{
if (predicate(list[index]))
return index;
}
return -1;
}
public static bool IsValidIndex<T>(this IList<T>? array, int index)
{
return array != null && index >= 0 && index < array.Count;
}
public static bool TryGetValue<T>(this IList<T> array, int index, out T? value)
{
if (array.IsValidIndex<T>(index))
{
value = array[index];
return true;
}
value = default(T);
return false;
}
public static int BinarySearch<TValue, TKey>(this IList<TValue> list, TKey key, Func<TValue, TKey> getKey) where TKey : IComparable
{
var index1 = 0;
var index2 = list.Count - 1;
while (index2 >= index1)
{
var obj1 = list[index1];
if (getKey(obj1).CompareTo((object)key) == 0) return index1;
var obj2 = list[index2];
if (getKey(obj2).CompareTo((object)key) == 0) return index2;
var index3 = (index1 + index2) / 2;
var obj3 = list[index3];
var num = getKey(obj3).CompareTo((object)key);
if (num == 0) return index3;
if (num < 0)
{
index1 = index3 + 1;
--index2;
}
else
{
index2 = index3 - 1;
++index1;
}
}
return -1;
}
}
}

View File

@ -1,56 +0,0 @@
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
namespace AyCode.Core.Extensions
{
public static class EnumExtensions
{
private static readonly ConcurrentDictionary<Type, Dictionary<string, DisplayAttribute>> DisplayNameCache = new();
private static T? GetAttributeOfType<T>(this Enum enumValue) where T : Attribute
{
var type = enumValue.GetType();
var memInfo = type.GetField(enumValue.ToString(), BindingFlags.Public | BindingFlags.Static);
if (memInfo == null) return null;
var attributes = memInfo.GetCustomAttributes<T>(false);
return attributes.FirstOrDefault();
}
//public static string GetDisplayValuesName(this Enum enumValue)
//=> DisplayNameCache[enumValue]
public static string GetDisplayName2<T>(this T enumValue) where T : class
{
return string.Empty;
//return GetDisplayAttribute(enumValue).Name!;
}
public static string GetDisplayName(this Enum enumValue)
{
return GetDisplayAttribute(enumValue).Name!;
}
public static DisplayAttribute GetDisplayAttribute(this Enum enumValue)
{
return new DisplayAttribute();
//return DisplayNameCache.GetOrAdd(enumValue, e =>
//{
// var displayAttribute = e.GetAttributeOfType<DisplayAttribute>();
// if (displayAttribute != null) return displayAttribute;
// var name = e.ToString();
// return new DisplayAttribute { Name = name, ShortName = name, Prompt = name, Description = name };
//});
}
}
}

View File

@ -1,26 +0,0 @@
using AyCode.Utils.Extensions;
namespace AyCode.Core.Extensions;
public static class ExceptionExtensions
{
public static void GetCategoryAndMemberNameFromStackTraceString(this Exception? exception, out string? memberName, out string? categoryName)
{
categoryName = null;
memberName = null;
if (exception == null) return;
var stackTraceString = exception.StackTrace ?? exception.InnerException?.StackTrace;
if (stackTraceString.IsNullOrWhiteSpace()) return;
var stackSplit = stackTraceString.Split(" in ");
if (stackSplit.Length <= 0) return;
stackSplit = stackSplit[0].Split('.');
if (stackSplit.Length <= 1) return;
memberName = stackSplit[^1]; //new StackTrace(exception).GetFrame(0)?.GetMethod()?.Name;
categoryName = stackSplit[^2]; //exception.Source
}
}

View File

@ -1,15 +0,0 @@
using System.Diagnostics.CodeAnalysis;
namespace AyCode.Core.Extensions
{
public static class GuidExtensions
{
//[ContractAnnotation("=> true, result: notnull; => false, result: null")]
//[ContractAnnotation("true => null; false => notnull")]
public static bool IsNullOrEmpty([NotNullWhen(false)] this Guid guid) => guid == Guid.Empty;
//[ContractAnnotation("=> true, result: notnull; => false, result: null")]
//[ContractAnnotation("guid:null => true; guid:notnull <= false")]
public static bool IsNullOrEmpty([NotNullWhen(false)] this Guid? guid) => guid == null || guid == Guid.Empty;
}
}

View File

@ -1,51 +0,0 @@
using System.Linq.Expressions;
using AyCode.Core.Interfaces;
using MessagePack.Resolvers;
using MessagePack;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System.Text.RegularExpressions;
namespace AyCode.Core.Extensions;
public static class SerializeObjectExtensions
{
public static readonly JsonSerializerSettings Options = new()
{
//TypeNameHandling = TypeNameHandling.All,
PreserveReferencesHandling = PreserveReferencesHandling.Objects,
ReferenceLoopHandling = ReferenceLoopHandling.Ignore,
NullValueHandling = NullValueHandling.Ignore
////System.Text.Json
//ReferenceHandler.Preserve
//ReferenceHandler.IgnoreCycles
};
public static string ToJson<T>(this T source) => JsonConvert.SerializeObject(source, Options);
public static string ToJson<T>(this IQueryable<T> source) where T : class, IAcSerializableToJson => JsonConvert.SerializeObject(source, Options);
public static string ToJson<T>(this IEnumerable<T> source) where T : class, IAcSerializableToJson => JsonConvert.SerializeObject(source, Options);
public static T? JsonTo<T>(this string json)
{
if (json.StartsWith("\"") && json.EndsWith("\"")) json = Regex.Unescape(json).TrimStart('"').TrimEnd('"');
return JsonConvert.DeserializeObject<T>(json, Options);
}
public static object? JsonTo(this string json, Type toType)
{
if (json.StartsWith("\"") && json.EndsWith("\"")) json = Regex.Unescape(json).TrimStart('"').TrimEnd('"');
return JsonConvert.DeserializeObject(json, toType, Options);
}
//public static string ToJson(this Expression source) => JsonConvert.SerializeObject(source, Options);
public static byte[] ToMessagePack(this object message) => MessagePackSerializer.Serialize(message);
public static byte[] ToMessagePack(this object message, MessagePackSerializerOptions options) => MessagePackSerializer.Serialize(message, options);
public static T MessagePackTo<T>(this byte[] message) => MessagePackSerializer.Deserialize<T>(message);
public static T MessagePackTo<T>(this byte[] message, MessagePackSerializerOptions options) => MessagePackSerializer.Deserialize<T>(message, options);
}

View File

@ -1,41 +0,0 @@
using AyCode.Core.Consts;
namespace AyCode.Core.Helpers
{
public static class AcCharsGenerator
{
public static readonly char[] Letters;
public static readonly char[] Numbers;
public static readonly char[] LettersAndNumbers;
static AcCharsGenerator()
{
//"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
Numbers = "0123456789".ToCharArray();
Letters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ".ToCharArray();
LettersAndNumbers = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789".ToCharArray();
}
private static char[] GetRandomChars() => GetRandomChars(LettersAndNumbers, 8, 12);
private static char[] GetRandomChars(int length) => GetRandomChars(LettersAndNumbers, length, length);
private static char[] GetRandomChars(int minLength, int maxLength) => GetRandomChars(LettersAndNumbers, minLength, maxLength);
private static char[] GetRandomChars(char[] sourceChars, int minLength, int maxLength)
{
if (minLength < 1) throw new ArgumentOutOfRangeException(nameof(minLength), "must have length greater than or equal to 1");
var random = new Random();
return Enumerable.Repeat(sourceChars, random.Next(minLength, maxLength)).Select(s => s[random.Next(s.Length)]).ToArray();
}
public static string NewToken()
{
return new string(GetRandomChars(AcConst.MinUserTokenLength, AcConst.MaxUserTokenLength));
}
public static string NewPassword(int minLength = AcConst.MinPasswordLength, int maxLength = AcConst.MaxPasswordLength)
{
return new string(GetRandomChars(AcConst.MinPasswordLength, AcConst.MaxPasswordLength));
}
}
}

View File

@ -1,47 +0,0 @@
using System.Reflection;
namespace AyCode.Core.Helpers;
public sealed class ConstHelper
{
private static readonly Dictionary<string, Dictionary<int, string>?> ObjectsByNamesByValue = new();
public static string NameByValue<T>(int value) where T : class
=> GetNameByValue(GetNamesByType(typeof(T).Name) ?? FillNames<T>(), value);
public static string NameByValue(string typeName, int value)
=> GetNameByValue(GetNamesByType(typeName), value);
private static string GetNameByValue(IReadOnlyDictionary<int, string>? namesByValue, int value)
=> namesByValue != null && namesByValue.TryGetValue(value, out var fieldName) ? $"tag: {fieldName}_{value}" : $"..._{value}";
private static Dictionary<int, string>? GetNamesByType(string typeName)
{
lock (ObjectsByNamesByValue)
{
if (ObjectsByNamesByValue.TryGetValue(typeName, out var namesByValue) && namesByValue!.Count > 0)
return namesByValue;
}
return null;
}
private static Dictionary<int, string> FillNames<T>() where T : class
{
var objectType = typeof(T);
var namesByValue = new Dictionary<int, string>();
lock (ObjectsByNamesByValue)
{
foreach (var fieldInfo in objectType.GetFields().Where(x => (x.Attributes & FieldAttributes.Literal) != 0 && x.FieldType == typeof(int)))
{
namesByValue[(int)fieldInfo.GetValue(null)!] = fieldInfo.Name;
}
ObjectsByNamesByValue[objectType.Name] = namesByValue;
}
return namesByValue;
}
}

View File

@ -1,63 +0,0 @@
using System.Security.Cryptography;
using System.Text;
using AyCode.Core.Consts;
using AyCode.Core.Extensions;
using AyCode.Utils.Extensions;
using Microsoft.AspNetCore.Cryptography.KeyDerivation;
namespace AyCode.Core.Helpers
{
public class PasswordHasher
{
public static string HashPassword(string? password, string? dynamicSalt = null)
{
if (string.IsNullOrWhiteSpace(password)) throw new ArgumentNullException(nameof(password));
// Generate a random salt
var salt = new byte[16];
using (var rng = RandomNumberGenerator.Create()) rng.GetBytes(salt);
// Hash the password with the salt
var hashedPassword = GenerateHashedPassword(password, salt, dynamicSalt);
// Combine the salt and hashed password
var combinedHash = $"$bcrypt$v=1$salt={Convert.ToBase64String(salt)}$hash={hashedPassword}";
return combinedHash;
}
public static bool VerifyPassword(string? password, string hashedPassword, string? dynamicSalt = null)
{
if (string.IsNullOrWhiteSpace(password)) return false;
// Extract the salt and hashed password from the combined hash
var parts = hashedPassword.Split('$');
if (parts.Length != 5) return false;
var salt = Convert.FromBase64String(parts[3].Replace("salt=", string.Empty));
var storedHash = parts[4].Replace("hash=", string.Empty);
return storedHash == GenerateHashedPassword(password, salt, dynamicSalt);
}
private static string GenerateHashedPassword(string password, byte[] salt, string? dynamicSalt)
=> Convert.ToBase64String(KeyDerivation.Pbkdf2(
password: password,
salt: GenerateFinallySalt(salt, dynamicSalt),
prf: KeyDerivationPrf.HMACSHA512,
iterationCount: 10000,
numBytesRequested: 32));
//SEMMILYEN KÖRÜLMÉNYEK KÖZÖTT SE VÁLTOZTASD MEG METÓDUS LOGIKÁJÁT!!! Különben senki sem fog tudni Login-olni! - J.
public static string GenerateDynamicSalt(Guid userId)
=> userId.ToString("N").ToLower().Reverse().MixCharacters(AcConst.ProjectSalt);
//SEMMILYEN KÖRÜLMÉNYEK KÖZÖTT SE VÁLTOZTASD MEG METÓDUS LOGIKÁJÁT!!! Különben senki sem fog tudni Login-olni! - J.
private static byte[] GenerateFinallySalt(byte[] salt, string? dynamicSalt)
=> SHA256.HashData(string.IsNullOrWhiteSpace(dynamicSalt) ? salt : Encoding.ASCII.GetBytes(Convert.ToBase64String(salt).Reverse().MixCharacters(dynamicSalt))).Take(16).ToArray();
}
}

View File

@ -2,18 +2,16 @@
{
public static class TaskHelper
{
public static bool WaitTo(Func<bool> predicate, int msTimeout = 10000, int msDelay = 5, int msFirstDelay = 0)
=> WaitToAsync(predicate, msTimeout, msDelay, msFirstDelay).GetAwaiter().GetResult();
public static bool WaitTo(Func<bool> predicate, int msTimeout = 10000, int msDelay = 5)
=> WaitToAsync(predicate, msTimeout, msDelay).GetAwaiter().GetResult();
public static Task<bool> WaitToAsync(Func<bool> predicate, int msTimeout = 10000, int msDelay = 5, int msFirstDelay = 0)
public static Task<bool> WaitToAsync(Func<bool> predicate, int msTimeout = 10000, int msDelay = 5)
{
return ToThreadPoolTask(async () =>
{
var result = false;
var dtTimeout = DateTime.UtcNow.AddMilliseconds(msTimeout).Ticks;
if (msFirstDelay > 0) await Task.Delay(msFirstDelay).ConfigureAwait(false);
while (dtTimeout > DateTime.UtcNow.Ticks && !(result = predicate()))
await Task.Delay(msDelay).ConfigureAwait(false); //Thread.Sleep(msDelay);
@ -62,9 +60,7 @@
//public static void RunOnThreadPool(this Task task) => Task.Run(() => _ = task).Forget(); //TODO: Letesztelni, a ThreadId-kat! - J.
public static void RunOnThreadPool(this Action action) => ToThreadPoolTask(action).Forget();
public static void RunOnThreadPool<T>(this Func<T> func) => ToThreadPoolTask(func).Forget();
public static Task ToThreadPoolTask(this Action action) => Task.Run(action);
//public static Task ToThreadPoolTask(this Task task) => Task.Run(() => _ = task);
//public static void ToParallelTaskStart(this Task task) => task.Start();
//public static Task<T> ToThreadPoolTask<T>(this Task<T> task) => Task.Run(() => task);

View File

@ -1,13 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace AyCode.Core.Interfaces
{
public interface IId<T>
{
T Id { get; set; }
}
}

View File

@ -1,4 +1,4 @@
namespace AyCode.Core.Loggers
namespace AyCode.Core.Logger
{
/// <summary>
/// Az adatbásisban van egy LogLevel tábla, ha változtatunk az enum-ok értékén, akkor ott is igazítsuk hozzá!

View File

@ -0,0 +1,85 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
using AyCode.Core.Consts;
using AyCode.Core.Enums;
namespace AyCode.Core.Logger
{
public static class Logger
{
public static LogLevel LogLevel { get; set; } = LogLevel.Detail;
public static AppType AppType { get; set; } = AppType.Server;
public static void Detail(string text, [CallerMemberName] string? memberName = null)
=> WriteToConsole(LogLevel.Detail, GetDiagnosticText(LogLevel.Detail, text, memberName, null));
public static void Debug(string text, [CallerMemberName] string? memberName = null)
=> WriteToConsole(LogLevel.Debug, GetDiagnosticText(LogLevel.Debug, text, memberName, null));
public static void Info(string text, [CallerMemberName] string? memberName = null)
=> WriteToConsole(LogLevel.Info, GetDiagnosticText(LogLevel.Info, text, memberName, null));
public static void Warning(string text, [CallerMemberName] string? memberName = null)
=> WriteToConsole(LogLevel.Warning, GetDiagnosticText(LogLevel.Warning, text, memberName, null));
public static void Suggest(string text, [CallerMemberName] string? memberName = null)
=> WriteToConsole(LogLevel.Suggest, GetDiagnosticText(LogLevel.Suggest, text, memberName, null));
public static void Error(string text, [CallerMemberName] string? memberName = null)
=> WriteToConsole(LogLevel.Error, GetDiagnosticText(LogLevel.Error, text, memberName, null));
public static void Error(string text, Exception ex, [CallerMemberName] string? memberName = null)
=> WriteToConsole(LogLevel.Error, GetDiagnosticText(LogLevel.Error, text, memberName, ex));
private static void WriteToConsole(LogLevel logLevel, string text)
{
if (logLevel < LogLevel) return;
//lock (ForWriterLock)
{
//if (logLevel > LogLevel.Trace && logLevel < LogLevel.Suggest)
{
Console.WriteLine(text);
return;
}
if (logLevel <= LogLevel.Trace)
{
Console.ForegroundColor = ConsoleColor.Gray;
Console.WriteLine(text);
}
else if (logLevel == LogLevel.Suggest)
{
Console.ForegroundColor = ConsoleColor.Cyan;
Console.WriteLine(text);
}
else
{
Console.ForegroundColor = logLevel == LogLevel.Warning ? ConsoleColor.Yellow : ConsoleColor.Red;
Console.WriteLine($"{AcEnv.NL}{text}{AcEnv.NL}");
}
Console.ForegroundColor = ConsoleColor.White;
}
}
private static string GetDiagnosticText(LogLevel logLevel, string logText, string? callerName, Exception? ex)
{
var threadId = Environment.CurrentManagedThreadId;
return $"[{DateTime.Now:HH:mm:ss.fff}] [{AppType.ToString()[0]}] {"[" + logLevel + "]",-9} {"[...->" + callerName + "]",-54} {"[" + threadId + "]",5} {logText}{ErrorText(ex)}";
}
private static string ErrorText(Exception? ex)
{
if (ex == null) return string.Empty;
var errorType = ex.GetType().Name;
return string.IsNullOrWhiteSpace(errorType) ? string.Empty : $"{Environment.NewLine}[{errorType.ToUpper()}]: {ex}";
}
}
}

View File

@ -1,62 +0,0 @@
using AyCode.Core.Consts;
using AyCode.Core.Enums;
using AyCode.Utils.Extensions;
namespace AyCode.Core.Loggers;
public interface IAcConsoleLogWriter : IAcTextLogWriterBase
{}
public class AcConsoleLogWriter : AcTextLogWriterBase, IAcConsoleLogWriter
{
private static readonly object ForWriterLock = new();
protected AcConsoleLogWriter() : this(null)
{
Initialize();
}
protected AcConsoleLogWriter(string? categoryName = null) : base(categoryName)
{
Initialize();
}
public AcConsoleLogWriter(AppType appType, LogLevel logLevel, string? categoryName = null) : base(appType, logLevel, categoryName)
{
Initialize();
}
private static void Initialize()
{
Console.ForegroundColor = ConsoleColor.White;
}
protected override void WriteText(string? logText, LogLevel loglevel)
{
if (logText.IsNullOrWhiteSpace()) return;
lock (ForWriterLock)
{
switch (loglevel)
{
case > LogLevel.Trace and < LogLevel.Suggest:
Console.WriteLine(logText);
return;
case <= LogLevel.Trace:
Console.ForegroundColor = ConsoleColor.Gray;
Console.WriteLine(logText);
break;
case LogLevel.Suggest:
Console.ForegroundColor = ConsoleColor.Cyan;
Console.WriteLine(logText);
break;
default:
Console.ForegroundColor = loglevel == LogLevel.Warning ? ConsoleColor.Yellow : ConsoleColor.Red;
Console.WriteLine($"{AcEnv.NL}{logText}{AcEnv.NL}");
break;
}
Console.ForegroundColor = ConsoleColor.White;
}
}
}

View File

@ -1,114 +0,0 @@
using System.Diagnostics;
using System.Runtime.CompilerServices;
using AyCode.Core.Consts;
using AyCode.Core.Enums;
namespace AyCode.Core.Loggers;
public abstract class AcLogWriterBase : IAcLogWriterBase
{
public string? CategoryName { get; }
protected AppType AppType { get; set; } = AppType.Server;
protected LogLevel LogLevel { get; set; } = LogLevel.Error;
protected AcLogWriterBase() : this(null)
{}
protected AcLogWriterBase(string? categoryName = null)
{
CategoryName = categoryName ?? "...";
AppType = AcEnv.AppConfiguration.GetEnum<AppType>("AyCode:Logger:AppType");
//AppType = (AppType)Enum.Parse(typeof(AppType), AcEnv.AppConfiguration["AyCode:Logger:AppType"], true);
var writerSettings = AcEnv.AppConfiguration.GetSection("AyCode:Logger:LogWriters")
.GetChildren()
.FirstOrDefault(logWriter=> (logWriter["LogWriterType"].ToLower()).Equals(this.GetType().AssemblyQualifiedName, StringComparison.CurrentCultureIgnoreCase));
LogLevel = writerSettings.GetEnum<LogLevel>("LogLevel");
}
protected AcLogWriterBase(AppType appType, LogLevel logLevel, string? categoryName = null)
{
AppType = appType;
LogLevel = logLevel;
CategoryName = categoryName ?? "...";
}
public void Detail(string? text, string? categoryName = null, [CallerMemberName] string? memberName = null)
=> Write(AppType, LogLevel.Detail, text, memberName, categoryName ?? CategoryName);
[Conditional("DEBUG")]
public void DetailConditional(string? text, string? categoryName = null, [CallerMemberName] string? memberName = null)
=> Detail(text, categoryName, memberName);
public void Debug(string? text, string? categoryName = null, [CallerMemberName] string? memberName = null)
=> Write(AppType, LogLevel.Debug, text, memberName, categoryName ?? CategoryName);
[Conditional("DEBUG")]
public void DebugConditional(string? text, string? categoryName = null, [CallerMemberName] string? memberName = null)
=> Debug(text, categoryName, memberName);
public void Info(string? text, string? categoryName = null, [CallerMemberName] string? memberName = null)
=> Write(AppType, LogLevel.Info, text, memberName, categoryName ?? CategoryName);
[Conditional("DEBUG")]
public void InfoConditional(string? text, string? categoryName = null, [CallerMemberName] string? memberName = null)
=> Info(text, categoryName, memberName);
public void Warning(string? text, string? categoryName = null, [CallerMemberName] string? memberName = null)
=> Write(AppType, LogLevel.Warning, text, memberName, categoryName ?? CategoryName);
[Conditional("DEBUG")]
public void WarningConditional(string? text, string? categoryName = null, [CallerMemberName] string? memberName = null)
=> Warning(text, categoryName, memberName);
public void Suggest(string? text, string? categoryName = null, [CallerMemberName] string? memberName = null)
=> Write(AppType, LogLevel.Suggest, text, memberName, categoryName ?? CategoryName);
[Conditional("DEBUG")]
public void SuggestConditional(string? text, string? categoryName = null, [CallerMemberName] string? memberName = null)
=> Suggest(text, categoryName, memberName);
public void Error(string? text, Exception? ex = null, string? categoryName = null, [CallerMemberName] string? memberName = null)
=> Write(AppType, LogLevel.Error, text, memberName, categoryName ?? CategoryName, ex);
[Conditional("DEBUG")]
public void ErrorConditional(string? text, Exception? ex = null, string? categoryName = null, [CallerMemberName] string? memberName = null)
=> Error(text, ex, categoryName, memberName);
public void Write(AppType appType, LogLevel logLevel, string? logText, string? callerMemberName, string? categoryName)
=> Write(appType, logLevel, logText, callerMemberName, categoryName, null, null);
[Conditional("DEBUG")]
public void WriteConditional(AppType appType, LogLevel logLevel, string? logText, string? callerMemberName, string? categoryName)
=> Write(appType, logLevel, logText, callerMemberName, categoryName, null, null);
public void Write(AppType appType, LogLevel logLevel, string? logText, string? callerMemberName, string? categoryName, Exception? ex)
=> Write(appType, logLevel, logText, callerMemberName, categoryName, ex?.GetType().Name, ex?.ToString());
[Conditional("DEBUG")]
public void WriteConditional(AppType appType, LogLevel logLevel, string? logText, string? callerMemberName, string? categoryName, Exception? ex)
=> Write(appType, logLevel, logText, callerMemberName, categoryName, ex);
public virtual void Write(AppType appType, LogLevel logLevel, string? logText, string? callerMemberName, string? categoryName, string? errorType, string? exMessage)
{
throw new NotImplementedException();
}
[Conditional("DEBUG")]
public void WriteConditional(AppType appType, LogLevel logLevel, string? logText, string? callerMemberName, string? categoryName, string? errorType, string? exMessage)
=> Write(appType, logLevel, logText, callerMemberName, categoryName, errorType, exMessage);
public virtual void Write(IAcLogItemClient logItem)
{
throw new NotImplementedException();
}
[Conditional("DEBUG")]
public void WriteConditional(IAcLogItemClient logItem) => Write(logItem);
}

View File

@ -1,143 +0,0 @@
using System.Diagnostics;
using System.Runtime.CompilerServices;
using System.Security.AccessControl;
using AyCode.Core.Consts;
using AyCode.Core.Enums;
using static System.Net.Mime.MediaTypeNames;
namespace AyCode.Core.Loggers;
public abstract class AcLoggerBase : IAcLoggerBase
{
protected readonly List<IAcLogWriterBase> LogWriters = [];
public LogLevel LogLevel { get; set; } = LogLevel.Error;
public AppType AppType { get; set; } = AppType.Server;
public string? CategoryName { get; set; }
protected AcLoggerBase() : this(null)
{
}
protected AcLoggerBase(string? categoryName)
{
CategoryName = categoryName ?? "...";
AppType = AcEnv.AppConfiguration.GetEnum<AppType>("AyCode:Logger:AppType");
LogLevel = AcEnv.AppConfiguration.GetEnum<LogLevel>("AyCode:Logger:LogLevel");
foreach (var logWriter in AcEnv.AppConfiguration.GetSection("AyCode:Logger:LogWriters").GetChildren())
{
var logWriterType = Type.GetType(logWriter["LogWriterType"]);
var logWriterLogLevel = logWriter.GetEnum<LogLevel>("LogLevel");
LogWriters.Add(Activator.CreateInstance(logWriterType, AppType, logWriterLogLevel, CategoryName) as IAcLogWriterBase);
}
}
protected AcLoggerBase(string? categoryName, params IAcLogWriterBase[] logWriters) :
this(AcEnv.AppConfiguration.GetEnum<AppType>("AyCode:Logger:AppType"), AcEnv.AppConfiguration.GetEnum<LogLevel>("AyCode:Logger:LogLevel"), categoryName, logWriters)
{
}
protected AcLoggerBase(AppType appType, LogLevel logLevel, string? categoryName, params IAcLogWriterBase[] logWriters)
{
AppType = appType;
LogLevel = logLevel;
CategoryName = categoryName ?? "...";
foreach (var acLogWriterBase in logWriters)
LogWriters.Add(acLogWriterBase);
}
public List<IAcLogWriterBase> GetWriters => [.. LogWriters];
public TLogWriter? Writer<TLogWriter>() where TLogWriter : IAcLogWriterBase => LogWriters.OfType<TLogWriter>().FirstOrDefault();
public virtual void Detail(string? text, string? categoryName = null, [CallerMemberName] string? memberName = null)
{
if (LogLevel <= LogLevel.Detail) LogWriters.ForEach(x => x.Detail(text, categoryName ?? CategoryName, memberName));
}
[Conditional("DEBUG")]
public void DetailConditional(string? text, string? categoryName = null, [CallerMemberName] string? memberName = null)
=> Detail(text, categoryName, memberName);
public virtual void Debug(string? text, string? categoryName = null, [CallerMemberName] string? memberName = null)
{
if (LogLevel <= LogLevel.Debug) LogWriters.ForEach(x => x.Debug(text, categoryName ?? CategoryName, memberName));
}
[Conditional("DEBUG")]
public void DebugConditional(string? text, string? categoryName = null, [CallerMemberName] string? memberName = null)
=> Debug(text, categoryName, memberName);
public virtual void Info(string? text, string? categoryName = null, [CallerMemberName] string? memberName = null)
{
if (LogLevel <= LogLevel.Info) LogWriters.ForEach(x => x.Info(text, categoryName ?? CategoryName, memberName));
}
[Conditional("DEBUG")]
public void InfoConditional(string? text, string? categoryName = null, [CallerMemberName] string? memberName = null)
=> Info(text, categoryName, memberName);
public virtual void Warning(string? text, string? categoryName = null, [CallerMemberName] string? memberName = null)
{
if (LogLevel <= LogLevel.Warning) LogWriters.ForEach(x => x.Warning(text, categoryName ?? CategoryName, memberName));
}
[Conditional("DEBUG")]
public void WarningConditional(string? text, string? categoryName = null, [CallerMemberName] string? memberName = null)
=> Warning(text, categoryName, memberName);
public virtual void Suggest(string? text, string? categoryName = null, [CallerMemberName] string? memberName = null)
{
if (LogLevel <= LogLevel.Suggest) LogWriters.ForEach(x => x.Suggest(text, categoryName ?? CategoryName, memberName));
}
[Conditional("DEBUG")]
public void SuggestConditional(string? text, string? categoryName = null, [CallerMemberName] string? memberName = null)
=> Suggest(text, categoryName, memberName);
public virtual void Error(string? text, Exception? ex = null, string? categoryName = null, [CallerMemberName] string? memberName = null)
{
if (LogLevel <= LogLevel.Error) LogWriters.ForEach(x => x.Error(text, ex, categoryName ?? CategoryName, memberName));
}
[Conditional("DEBUG")]
public void ErrorConditional(string? text, Exception? ex = null, string? categoryName = null, [CallerMemberName] string? memberName = null)
=> Error(text, ex, categoryName, memberName);
public void Write(AppType appType, LogLevel logLevel, string? logText, string? callerMemberName, string? categoryName)
=> Write(appType, logLevel, logText, callerMemberName, categoryName, null, null);
[Conditional("DEBUG")]
public void WriteConditional(AppType appType, LogLevel logLevel, string? logText, string? callerMemberName, string? categoryName)
=> Write(appType, logLevel, logText, callerMemberName, categoryName, null, null);
public void Write(AppType appType, LogLevel logLevel, string? logText, string? callerMemberName, string? categoryName, Exception? ex)
=> Write(appType, logLevel, logText, callerMemberName, categoryName, ex?.GetType().Name, ex?.ToString());
[Conditional("DEBUG")]
public void WriteConditional(AppType appType, LogLevel logLevel, string? logText, string? callerMemberName, string? categoryName, Exception? ex)
=> Write(appType, logLevel, logText, callerMemberName, categoryName, ex);
public virtual void Write(AppType appType, LogLevel logLevel, string? logText, string? callerMemberName, string? categoryName, string? errorType, string? exMessage)
{
if (LogLevel <= logLevel) LogWriters.ForEach(x => x.Write(appType, logLevel, logText, callerMemberName, categoryName ?? CategoryName, errorType, exMessage));
}
[Conditional("DEBUG")]
public void WriteConditional(AppType appType, LogLevel logLevel, string? logText, string? callerMemberName, string? categoryName, string? errorType, string? exMessage)
=> Write(appType, logLevel, logText, callerMemberName, categoryName, errorType, exMessage);
public void Write(IAcLogItemClient logItem)
{
if (LogLevel <= logItem.LogLevel) LogWriters.ForEach(x => x.Write(logItem));
}
[Conditional("DEBUG")]
public void WriteConditional(IAcLogItemClient logItem) => Write(logItem);
}

View File

@ -1,70 +0,0 @@
using AyCode.Core.Consts;
using AyCode.Core.Enums;
using AyCode.Utils.Extensions;
namespace AyCode.Core.Loggers;
public interface IAcTextLogWriterBase : IAcLogWriterBase
{}
public abstract class AcTextLogWriterBase : AcLogWriterBase, IAcTextLogWriterBase
{
protected AcTextLogWriterBase() : this(null)
{ }
protected AcTextLogWriterBase(string? categoryName = null) : base(categoryName)
{ }
protected AcTextLogWriterBase(AppType appType, LogLevel logLevel, string? categoryName = null) : base(appType, logLevel, categoryName)
{ }
public override void Write(AppType appType, LogLevel logLevel, string? logText, string? callerMemberName, string? categoryName, string? errorType, string? ex)
{
if (logLevel < LogLevel) return;
WriteText(GetDiagnosticText(appType, logLevel, logText, callerMemberName, categoryName, errorType, ex), logLevel);
}
public override void Write(IAcLogItemClient logItem)
{
if (logItem.LogLevel < LogLevel) return;
WriteText(GetDiagnosticText(logItem), logItem.LogLevel);
}
protected virtual void WriteText(string? logText, LogLevel loglevel)
{
throw new NotImplementedException();
}
protected string GetDiagnosticText(IAcLogItemClient logItem)
=> GetDiagnosticText(logItem.TimeStampUtc, logItem.AppType, logItem.LogLevel, logItem.ThreadId, logItem.Text, logItem.CallerName, logItem.CategoryName, logItem.ErrorType, logItem.Exception);
protected string GetDiagnosticText(LogLevel logLevel, string? logText, string? callerMemberName, string? categoryName = null, Exception? ex = null)
=> GetDiagnosticText(AppType, logLevel, logText, callerMemberName, categoryName, ex?.GetType().Name, ex?.ToString());
protected string GetDiagnosticText(AppType appType, LogLevel logLevel, string? logText, string? callerMemberName, string? categoryName, string? errorType, string? exMessage)
=> GetDiagnosticText(DateTime.UtcNow, appType, logLevel, Environment.CurrentManagedThreadId, logText, callerMemberName, categoryName, errorType, exMessage);
protected string GetDiagnosticText(DateTime utcNow, AppType appType, LogLevel logLevel, int threadId, string? logText, string? callerMemberName, string? categoryName, string? errorType, string? exMessage)
{
if (LogLevel > logLevel) return string.Empty;
if(categoryName.IsNullOrWhiteSpace()) categoryName = CategoryName;
return $"[{utcNow.ToLocalTime():HH:mm:ss.fff}] [{appType.ToString()[0]}] {"[" + logLevel + "]",-9} {"[" + categoryName + "->" + callerMemberName + "]",-54} {"[" + threadId + "]",5} {logText}{ErrorText(errorType, exMessage)}";
}
protected string ErrorText(Exception? ex)
{
return ex == null ? string.Empty : ErrorText(ex.GetType().Name, ex.ToString());
}
protected virtual string ErrorText(string? errorType, string? exMessage)
{
if (errorType.IsNullOrWhiteSpace() && exMessage.IsNullOrWhiteSpace()) return string.Empty;
return string.IsNullOrWhiteSpace(errorType) ? string.Empty : $"{AcEnv.NL}[{errorType.ToUpper()}]: {exMessage}";
}
}

View File

@ -1,17 +0,0 @@
using AyCode.Core.Enums;
namespace AyCode.Core.Loggers;
public interface IAcLogItemClient
{
public DateTime TimeStampUtc { get; set; }
public AppType AppType { get; set; }
public LogLevel LogLevel { get; set; }
public int ThreadId { get; set; }
public string? CategoryName { get; set; }
public string? CallerName { get; set; }
public string? Text { get; set; }
public string? Exception { get; set; }
public string? ErrorType { get; set; }
}

View File

@ -1,38 +0,0 @@
using System.Diagnostics;
using AyCode.Core.Enums;
using System.Runtime.CompilerServices;
namespace AyCode.Core.Loggers;
public interface IAcLogWriterBase
{
public string? CategoryName { get; }
public void Detail(string? text, string? categoryName = null, [CallerMemberName] string? memberName = null);
//public void DetailConditional(string? text, string? categoryName = null, [CallerMemberName] string? memberName = null);
public void Debug(string? text, string? categoryName = null, [CallerMemberName] string? memberName = null);
//public void DebugConditional(string? text, string? categoryName = null, [CallerMemberName] string? memberName = null);
public void Info(string? text, string? categoryName = null, [CallerMemberName] string? memberName = null);
//public void InfoConditional(string? text, string? categoryName = null, [CallerMemberName] string? memberName = null);
public void Warning(string? text, string? categoryName = null, [CallerMemberName] string? memberName = null);
//public void WarningConditional(string? text, string? categoryName = null, [CallerMemberName] string? memberName = null);
public void Suggest(string? text, string? categoryName = null, [CallerMemberName] string? memberName = null);
//public void SuggestConditional(string? text, string? categoryName = null, [CallerMemberName] string? memberName = null);
public void Error(string? text, Exception? ex = null, string? categoryName = null, [CallerMemberName] string? memberName = null);
//public void ErrorConditional(string? text, Exception? ex = null, string? categoryName = null, [CallerMemberName] string? memberName = null);
public void Write(AppType appType, LogLevel logLevel, string? logText, string? callerMemberName, string? categoryName);
//public void WriteConditional(AppType appType, LogLevel logLevel, string? logText, string? callerMemberName, string? categoryName);
public void Write(AppType appType, LogLevel logLevel, string? logText, string? callerMemberName, string? categoryName, Exception? ex);
//public void WriteConditional(AppType appType, LogLevel logLevel, string? logText, string? callerMemberName, string? categoryName, Exception? ex);
public void Write(AppType appType, LogLevel logLevel, string? logText, string? callerMemberName, string? categoryName, string? errorType, string? exMessage);
//public void WriteConditional(AppType appType, LogLevel logLevel, string? logText, string? callerMemberName, string? categoryName, string? errorType, string? exMessage);
public void Write(IAcLogItemClient logItem);
//public void WriteConditional(IAcLogItemClient logItem);
}

View File

@ -1,7 +0,0 @@
namespace AyCode.Core.Loggers;
public interface IAcLoggerBase : IAcLogWriterBase
{
public List<IAcLogWriterBase> GetWriters { get; }
public TLogWriter? Writer<TLogWriter>() where TLogWriter : IAcLogWriterBase;
}

View File

@ -1,51 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<IsPackable>false</IsPackable>
<IsTestProject>true</IsTestProject>
</PropertyGroup>
<Import Project="..//AyCode.Core.targets" />
<ItemGroup>
<None Remove="appsettings.json" />
</ItemGroup>
<ItemGroup>
<Content Include="appsettings.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup>
<ItemGroup>
<PackageReference Include="coverlet.collector" Version="6.0.4">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="9.0.8" />
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="9.0.8" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.14.1" />
<PackageReference Include="MSTest.TestAdapter" Version="3.10.3" />
<PackageReference Include="MSTest.TestFramework" Version="3.10.3" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\AyCode.Core.Server\AyCode.Core.Server.csproj" />
<ProjectReference Include="..\AyCode.Core.Tests.Internal\AyCode.Core.Tests.Internal.csproj" />
<ProjectReference Include="..\AyCode.Core.Tests\AyCode.Core.Tests.csproj" />
<ProjectReference Include="..\AyCode.Core\AyCode.Core.csproj" />
<ProjectReference Include="..\AyCode.Database.Tests\AyCode.Database.Tests.csproj" />
<ProjectReference Include="..\AyCode.Database\AyCode.Database.csproj" />
<ProjectReference Include="..\AyCode.Entities.Server\AyCode.Entities.Server.csproj" />
<ProjectReference Include="..\AyCode.Entities\AyCode.Entities.csproj" />
<ProjectReference Include="..\AyCode.Interfaces.Server\AyCode.Interfaces.Server.csproj" />
<ProjectReference Include="..\AyCode.Interfaces\AyCode.Interfaces.csproj" />
<ProjectReference Include="..\AyCode.Models.Server\AyCode.Models.Server.csproj" />
<ProjectReference Include="..\AyCode.Models\AyCode.Models.csproj" />
</ItemGroup>
<ItemGroup>
<Using Include="Microsoft.VisualStudio.TestTools.UnitTesting" />
</ItemGroup>
</Project>

View File

@ -1,23 +0,0 @@
using AyCode.Database.DbContexts;
using AyCode.Database.Tests.Internal.Users;
namespace AyCode.Database.Tests.Internal
{
[TestClass]
public class DatabaseTestBase : AcDatabaseTestBase<UserDbContext>
{
[TestInitialize]
public void Setup()
{
}
[TestCleanup]
public void TearDown()
{
}
[TestMethod]
public override void DatabaseExistsTest() => base.DatabaseExistsTest();
}
}

View File

@ -1,9 +0,0 @@
using AyCode.Core.Tests.Internal.Entities;
using AyCode.Database.DataLayers.Users;
namespace AyCode.Database.Tests.Internal.Users;
public sealed class UserDal : AcUserDalBase<UserDbContext, User, Profile, UserToken, Company, UserToCompany, Address, EmailMessage>
{
}

View File

@ -1,24 +0,0 @@
using AyCode.Core.Tests.Internal.Entities;
using AyCode.Database.Tests.Users;
namespace AyCode.Database.Tests.Internal.Users;
[TestClass]
public sealed class UserDalTests : AcUserDalTestBase<UserDal, UserDbContext, User, Profile, UserToken, Company, UserToCompany, Address, EmailMessage>
{
[DataTestMethod]
[DataRow("test@tiam.hu")]
public override void AcBase_GetUserByEmail_ReturnsUser_WhenUserExists(string email)
=> base.AcBase_GetUserByEmail_ReturnsUser_WhenUserExists(email);
[DataTestMethod]
[DataRow("540271F6-C604-4C16-8160-D5A7CAFEDF00")]
public override void AcBase_GetUserById_ReturnsUser_WhenUserExists(string userIdString)
=> base.AcBase_GetUserById_ReturnsUser_WhenUserExists(userIdString);
[DataTestMethod]
[DataRow(["e31044d7-1771-4a32-8dd9-6f9853ed53c6", "0a831191-70a3-4504-9ec4-c5902affaba7", "8eed080c-d2ce-4cc3-bcfe-2268c220bba7", "addUser_test9432@tiam.hu"])]
public override async Task AcBase_AddUserTest(string[] userIdProfileIdAddressIdEmailStrings)
=> await base.AcBase_AddUserTest(userIdProfileIdAddressIdEmailStrings);
}

View File

@ -1,44 +0,0 @@
using AyCode.Core.Tests.Internal.Entities;
using AyCode.Database.DbContexts.Users;
using Microsoft.EntityFrameworkCore;
namespace AyCode.Database.Tests.Internal.Users;
public sealed class UserDbContext : AcUserDbContextBase<User, Profile, UserToken, Company, UserToCompany, Address, EmailMessage>
{
public UserDbContext() //: this(string.Empty)
{
}
public UserDbContext(DbContextOptions<UserDbContext> options) //: this(string.Empty)
{
}
public UserDbContext(string name) : base(name)
{
}
public UserDbContext(DbContextOptions<DbContext> options, string name) : base(options, name)
{
}
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
base.OnConfiguring(optionsBuilder);
optionsBuilder.UseLazyLoadingProxies(true);
optionsBuilder.EnableDetailedErrors(true);
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
//new UserEntityTypeDefaultConfiguration().Configure(modelBuilder.Entity<User>());
//new ProfileEntityTypeConfigurations().Configure(modelBuilder.Entity<Profile>());
//new EmailMessageEntityTypeDefaultConfigurations().Configure(modelBuilder.Entity<EmailMessage>());
}
}

View File

@ -1,22 +0,0 @@
{
"ConnectionStrings": {
"DeveloperDbConnection": "Data Source=185.51.190.197;Initial Catalog=TIAM_DEV;Trusted_Connection=false;Encrypt=false;TrustServerCertificate=True;Connect Timeout=200;User ID=Anata_Development_Team;Password=v6f_?xNfg9N1;MultipleActiveResultSets=true"
},
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*",
"JWT": {
"Key": "Cee4400-rDMFkVvHPufyLDSzbfu2grgRhpepos299IhTLOXsljkcpt3yUR4RRjPQ",
"Issuer": "http://localhost:5000",
"Audience": "http://localhost:5000"
},
"SendGrid": {
//"Key": "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"
"Key": "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"
}
}

View File

@ -5,7 +5,7 @@ namespace AyCode.Database.Tests
public abstract class AcDatabaseTestBase<TDbContext> : AcDatabaseTestModelBase<TDbContext> where TDbContext : AcDbContextBase
{
[TestMethod]
public virtual void DatabaseExistsTest()
public void DatabaseExistsTest()
{
var isConnected = Context.Database.CanConnect();
Assert.IsTrue(isConnected);

View File

@ -6,10 +6,18 @@ namespace AyCode.Database.Tests;
public abstract class AcDatabaseTestModelBase<TDal, TDbContext> : TestModelBase where TDal : IAcDalBase<TDbContext> where TDbContext : AcDbContextBase
{
protected readonly TDal Dal = PooledDal.CreateDal<TDal>();
protected TDal Dal;
protected AcDatabaseTestModelBase()
{
Dal = PooledDal.CreateDal<TDal>();
}
}
public abstract class AcDatabaseTestModelBase<TDbContext> : TestModelBase where TDbContext : AcDbContextBase
{
protected readonly TDbContext Context = Activator.CreateInstance<TDbContext>();
protected TDbContext Context;
protected AcDatabaseTestModelBase()
{
Context = Activator.CreateInstance<TDbContext>();
}
}

View File

@ -1,40 +1,37 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<IsPackable>false</IsPackable>
<IsTestProject>true</IsTestProject>
</PropertyGroup>
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<Import Project="..//AyCode.Core.targets" />
<IsPackable>false</IsPackable>
<IsTestProject>true</IsTestProject>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="9.0.8" />
<PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="9.0.8" />
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="9.0.8" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.14.1" />
<PackageReference Include="MSTest.TestAdapter" Version="3.10.3" />
<PackageReference Include="MSTest.TestFramework" Version="3.10.3" />
<PackageReference Include="coverlet.collector" Version="6.0.4">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.8.0" />
<PackageReference Include="MSTest.TestAdapter" Version="3.1.1" />
<PackageReference Include="MSTest.TestFramework" Version="3.1.1" />
<PackageReference Include="coverlet.collector" Version="6.0.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\AyCode.Core.Server\AyCode.Core.Server.csproj" />
<ProjectReference Include="..\AyCode.Core.Tests\AyCode.Core.Tests.csproj" />
<ProjectReference Include="..\AyCode.Core\AyCode.Core.csproj" />
<ProjectReference Include="..\AyCode.Database\AyCode.Database.csproj" />
<ProjectReference Include="..\AyCode.Entities.Server\AyCode.Entities.Server.csproj" />
<ProjectReference Include="..\AyCode.Entities\AyCode.Entities.csproj" />
<ProjectReference Include="..\AyCode.Interfaces.Server\AyCode.Interfaces.Server.csproj" />
<ProjectReference Include="..\AyCode.Interfaces\AyCode.Interfaces.csproj" />
<ProjectReference Include="..\AyCode.Models.Server\AyCode.Models.Server.csproj" />
<ProjectReference Include="..\AyCode.Models\AyCode.Models.csproj" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\AyCode.Core.Server\AyCode.Core.Server.csproj" />
<ProjectReference Include="..\AyCode.Core.Tests\AyCode.Core.Tests.csproj" />
<ProjectReference Include="..\AyCode.Core\AyCode.Core.csproj" />
<ProjectReference Include="..\AyCode.Database\AyCode.Database.csproj" />
<ProjectReference Include="..\AyCode.Entities.Server\AyCode.Entities.Server.csproj" />
<ProjectReference Include="..\AyCode.Entities\AyCode.Entities.csproj" />
<ProjectReference Include="..\AyCode.Interfaces.Server\AyCode.Interfaces.Server.csproj" />
<ProjectReference Include="..\AyCode.Interfaces\AyCode.Interfaces.csproj" />
</ItemGroup>
<ItemGroup>
<Folder Include="UserTokens\" />
</ItemGroup>
<ItemGroup>
<Folder Include="UserTokens\" />
</ItemGroup>
</Project>

View File

@ -1,52 +1,27 @@
using AyCode.Database.DataLayers.Users;
using AyCode.Database.DbContexts;
using AyCode.Database.DbContexts.Users;
using AyCode.Database.Tests;
using AyCode.Entities.Addresses;
using AyCode.Entities.Profiles;
using AyCode.Entities.Users;
using AyCode.Interfaces.Addresses;
using AyCode.Interfaces.Addresses.Dtos;
using AyCode.Interfaces.Messages;
using AyCode.Interfaces.Profiles;
using AyCode.Interfaces.Profiles.Dtos;
using AyCode.Interfaces.ServiceProviders;
using AyCode.Interfaces.Users;
using AyCode.Interfaces.Users.Dtos;
using AyCode.Models.Users;
namespace AyCode.Database.Tests.Users
{
public abstract class AcUserDalTestBase<TDal, TDbContext, TUser, TProfile, TUserToken, TCompany, TUserToCompany, TAddress, TEmailMessage> : AcDatabaseTestModelBase<TDal, TDbContext>
where TDal : AcUserDalBase<TDbContext, TUser, TProfile, TUserToken, TCompany, TUserToCompany, TAddress, TEmailMessage>
where TDbContext : AcDbContextBase, IAcUserDbContextBase<TUser, TProfile, TUserToken, TCompany, TUserToCompany, TAddress, TEmailMessage>
where TUser : class, IAcUser<TProfile, TCompany, TUserToCompany, TAddress>
where TProfile : class, IAcProfile<TAddress>
where TAddress : class, IAcAddressDtoBase
public abstract class AcUserDalTestBase<TDal, TDbContext, TUser, TProfile, TUserToken, TServiceProvider, TUserToServiceProvider, TProfileAddress> : AcDatabaseTestModelBase<TDal, TDbContext>
where TDal : AcUserDalBase<TDbContext, TUser, TProfile, TUserToken, TServiceProvider, TUserToServiceProvider, TProfileAddress>
where TDbContext : AcDbContextBase, IAcUserDbContextBase<TUser, TProfile, TUserToken,TServiceProvider, TUserToServiceProvider, TProfileAddress>
where TUser : class, IAcUser<TProfile, TServiceProvider, TUserToServiceProvider, TProfileAddress>
where TProfile : class, IAcProfile<TProfileAddress>
where TProfileAddress : class, IAcAddress
where TUserToken : class, IAcUserTokenBase
where TCompany : class, IAcCompanyBase
where TUserToCompany : class, IAcUserToCompanyBase
where TEmailMessage : class, IAcEmailMessageBase
where TServiceProvider : class, IAcServiceProviderBase
where TUserToServiceProvider : class, IAcUserToServiceProviderBase
{
public class UserModelDtoDetailTest : AcUserModelDtoDetailBase<TUser, TProfile, TCompany, TUserToCompany, TAddress>
{
public UserModelDtoDetailTest() : base()
{
}
public UserModelDtoDetailTest(IAcUserDtoDetailBase<TProfile, TCompany, TUserToCompany, TAddress> user) : base(user)
{
}
}
[DataTestMethod]
public virtual void AcBase_GetUserById_ReturnsUser_WhenUserExists(string userIdString) => AcBase_GetUserById(userIdString);
// ReSharper disable once MemberCanBePrivate.Global
protected TUser AcBase_GetUserById(string userIdString)
protected TUser AcBase_GetUserById_ReturnsUser_WhenUserExists(string userIdString)
{
var userId = Guid.Parse(userIdString);
var user = Dal.GetUserById(userId, false);
var user = Dal.GetUserById(userId);
Assert.IsNotNull(user, "User is null");
Assert.IsNotNull(user.Profile, "Profile is null");
@ -57,13 +32,9 @@ namespace AyCode.Database.Tests.Users
return user;
}
[DataTestMethod]
public virtual void AcBase_GetUserByEmail_ReturnsUser_WhenUserExists(string email) => AcBase_GetUserByEmail(email);
// ReSharper disable once MemberCanBePrivate.Global
protected TUser AcBase_GetUserByEmail(string email)
protected TUser AcBase_GetUserByEmail_ReturnsUser_WhenUserExists(string email)
{
var user = Dal.GetUserByEmail(email, false);
var user = Dal.GetUserByEmail(email);
Assert.IsNotNull(user, "User is null");
Assert.IsNotNull(user.Profile, "Profile is null");
@ -74,24 +45,11 @@ namespace AyCode.Database.Tests.Users
return user;
}
[DataTestMethod]
public virtual void AcBase_GetUserModelDtoDetailById_ReturnsUser_WhenUserExists(string userIdString)
{
var userId = Guid.Parse(userIdString);
var userModelDtoDetail = Dal.GetUserModelDtoById<UserModelDtoDetailTest>(userId, false);
Assert.IsNotNull(userModelDtoDetail, "User is null");
Assert.IsNotNull(userModelDtoDetail.ProfileDto, "Profile is null");
Assert.IsNotNull(userModelDtoDetail.ProfileDto.Address, "Profile.Address is null");
Assert.AreEqual(userId, userModelDtoDetail.Id);
}
protected async Task<TUser> AcBase_GetUserByEmailAsync_ReturnsUser_WhenUserExists(string email)
{
TUser? user = null;
user = await Dal.GetUserByEmailAsync(email, false).ConfigureAwait(false);
user = await Dal.GetUserByEmailAsync(email).ConfigureAwait(false);
//user = await Dal.SessionAsync(ctx => ctx.Users.FirstOrDefault(x => x.EmailAddress == email)).ConfigureAwait(false);
@ -108,51 +66,5 @@ namespace AyCode.Database.Tests.Users
return user;
}
[DataTestMethod]
public virtual async Task AcBase_AddUserTest(string[] userIdProfileIdAddressIdEmailStrings)
{
var userId = Guid.Parse(userIdProfileIdAddressIdEmailStrings[0]);
var profileId = Guid.Parse(userIdProfileIdAddressIdEmailStrings[1]);
var addressId = Guid.Parse(userIdProfileIdAddressIdEmailStrings[2]);
var email = userIdProfileIdAddressIdEmailStrings[3];
var fromAddress = "Budapest, Liszt Ferenc tér";
var toAddress = "1211 Budapest, Kossuth Lajos utca 145";
//var userProductToCarId = Guid.Parse("97179a87-d99f-4f12-b7b2-75e21aaec6ab");
await Dal.RemoveUserAsync(userId); //kitöröljük a szemetet, ha korábbról bentmaradt - J.
var user = Activator.CreateInstance(typeof(TUser), userId, email, "235664", "dsfglfjg45r34903t3kggvq") as TUser;
Assert.IsNotNull(user);
user.ProfileId = profileId;
var profile = Activator.CreateInstance<TProfile>();
profile.Id = profileId;;
profile.Name = "Add user test name";
var address = Activator.CreateInstance<TAddress>();
address.Id = addressId;
address.Latitude = 5362.2341652256;
address.Longitude = 5362.2341333317;
address.AddressText = "1214 Kossuth Lajos utca 124.";
user.Profile = profile;
user.Profile.AddressId = addressId;
user.Profile.Address = address;
Assert.IsTrue(await Dal.AddUserAsync(user));
user = Dal.GetUserById(userId, false);
Assert.IsNotNull(user);
Assert.IsNotNull(user.Profile);
Assert.IsNotNull(user.Profile.Address);
Assert.IsTrue(await Dal.RemoveUserAsync(userId)); //mielőbb kitöröljük, h ne maradjon szemét a db-ben - J.
user = Dal.GetUserById(userId, false);
Assert.IsNull(user); //a korábbi törlés miatt NULL kell legyen - J.
}
}
}

View File

@ -1,50 +0,0 @@
using AyCode.Core.Consts;
using AyCode.Core.Enums;
using AyCode.Core.Helpers;
using AyCode.Core.Loggers;
using AyCode.Database.DbContexts.Loggers;
using AyCode.Entities;
using AyCode.Entities.Server.LogItems;
using AyCode.Interfaces.Entities;
using Microsoft.EntityFrameworkCore;
namespace AyCode.Database;
public class AcDbLogItemWriter<TLoggerDbContext, TLogItem> : AcLogItemWriterBase<TLogItem> where TLoggerDbContext : AcLoggerDbContextBase<TLogItem>
where TLogItem : class, IAcLogItem
{
private TLoggerDbContext _ctx = Activator.CreateInstance<TLoggerDbContext>();
protected AcDbLogItemWriter() : this(null)
{ }
protected AcDbLogItemWriter(string? categoryName = null) : base(categoryName)
{ }
public AcDbLogItemWriter(AppType appType, LogLevel logLevel, string? categoryName = null) : base(appType, logLevel, categoryName)
{ }
protected override void WriteLogItemCallback(TLogItem logItem)
{
//using var ctx = Activator.CreateInstance<TLoggerDbContext>();
_ctx.LogItems.Add(logItem);
_ctx.SaveChanges();
}
//protected override void WriteLogItem(TLogItem logItem, Action<IEnumerable<TLogItem>>? callback = null)
//{
// try
// {
// base.WriteLogItem(logItem, logItems =>
// {
// _ctx.LogItems.AddRange(logItems);
// _ctx.SaveChanges();
// });
// }
// catch (Exception ex)
// {
// Console.WriteLine("ERRORORRORO");
// }
//}
}

View File

@ -1,34 +1,29 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
</PropertyGroup>
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<Import Project="..//AyCode.Core.targets" />
<ItemGroup>
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="8.0.1" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Proxies" Version="8.0.1" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="MessagePack.Annotations" Version="3.1.4" />
<PackageReference Include="Microsoft.AspNetCore.Cryptography.KeyDerivation" Version="9.0.8" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="9.0.8" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Proxies" Version="9.0.8" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="9.0.8" />
<PackageReference Include="Microsoft.Extensions.Configuration" Version="9.0.8" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\AyCode.Core.Server\AyCode.Core.Server.csproj" />
<ProjectReference Include="..\AyCode.Core\AyCode.Core.csproj" />
<ProjectReference Include="..\AyCode.Entities.Server\AyCode.Entities.Server.csproj" />
<ProjectReference Include="..\AyCode.Entities\AyCode.Entities.csproj" />
<ProjectReference Include="..\AyCode.Interfaces.Server\AyCode.Interfaces.Server.csproj" />
<ProjectReference Include="..\AyCode.Interfaces\AyCode.Interfaces.csproj" />
<ProjectReference Include="..\AyCode.Models.Server\AyCode.Models.Server.csproj" />
<ProjectReference Include="..\AyCode.Models\AyCode.Models.csproj" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\AyCode.Core.Server\AyCode.Core.Server.csproj" />
<ProjectReference Include="..\AyCode.Core\AyCode.Core.csproj" />
<ProjectReference Include="..\AyCode.Entities.Server\AyCode.Entities.Server.csproj" />
<ProjectReference Include="..\AyCode.Entities\AyCode.Entities.csproj" />
<ProjectReference Include="..\AyCode.Interfaces.Server\AyCode.Interfaces.Server.csproj" />
<ProjectReference Include="..\AyCode.Interfaces\AyCode.Interfaces.csproj" />
<ProjectReference Include="..\AyCode.Models.Server\AyCode.Models.Server.csproj" />
<ProjectReference Include="..\AyCode.Models\AyCode.Models.csproj" />
</ItemGroup>
<ItemGroup>
<Folder Include="DbSets\Loggers\" />
<Folder Include="SqlScripts\" />
</ItemGroup>
<ItemGroup>
<Folder Include="SqlScripts\" />
</ItemGroup>
</Project>

View File

@ -3,12 +3,9 @@ using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
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;
@ -21,12 +18,8 @@ public abstract class AcDalBase<TDbContext> : IAcDalBase<TDbContext> where TDbCo
public bool AutoCloseSession { get; set; }
/// <summary>
/// Do not use it! Use Session or Transaction... - J.
/// </summary>
public TDbContext Context { get; private set; }
public Mutex MutextLock { get; } = new();
//protected AcDalBase()
//{
// Name = $"{GetType().Name}";
@ -56,18 +49,6 @@ public abstract class AcDalBase<TDbContext> : IAcDalBase<TDbContext> where TDbCo
ctx = null;
}
public TModelDto? GetModelDtoById<TModelDto, TEntity>(Guid id) where TModelDto : class, IAcModelDtoBase where TEntity : class, IEntity
=> Session(ctx => ctx.GetModelDtoById<TModelDto, TEntity>(id));
public Task<TModelDto?> GetModelDtoByIdAsync<TModelDto, TEntity>(Guid id) where TModelDto : class, IAcModelDtoBase where TEntity : class, IEntity
=> SessionAsync(ctx => ctx.GetModelDtoById<TModelDto, TEntity>(id));
public List<TModelDto> GetAllModelDto<TModelDto, TEntity>() where TModelDto : class, IAcModelDtoBase where TEntity : class, IEntity
=> Session(ctx => ctx.GetAllModelDto<TModelDto, TEntity>().ToList());
public Task<List<TModelDto>> GetAllModelDtoAsync<TModelDto, TEntity>() where TModelDto : class, IAcModelDtoBase where TEntity : class, IEntity
=> SessionAsync(ctx => ctx.GetAllModelDto<TModelDto, TEntity>().ToList());
public Task<TResultType> SessionAsync<TResultType>(Func<TDbContext, TResultType> callback)
=> this.SessionAsync<TDbContext, TResultType>(callback);
@ -86,12 +67,6 @@ public abstract class AcDalBase<TDbContext> : IAcDalBase<TDbContext> where TDbCo
public bool Transaction(Func<TDbContext, bool> callbackTransactionBody, bool throwException = false)
=> this.Transaction<TDbContext>(callbackTransactionBody, throwException);
public Task<TEntity?> UpdateSafeAsync<TEntity>(TEntity entity, Func<TDbContext, TEntity, bool>? callbackTransactionBody = null, bool throwException = false) where TEntity : class, IEntityGuid
=> this.UpdateSafeAsync<TDbContext, TEntity>(entity, callbackTransactionBody, throwException);
public TEntity? UpdateSafe<TEntity>(TEntity entity, Func<TDbContext, TEntity, bool>? callbackTransactionBody = null, bool throwException = false) where TEntity : class, IEntityGuid
=> this.UpdateSafe<TDbContext, TEntity>(entity, callbackTransactionBody, throwException);
public override string ToString()
{
return Name;

View File

@ -10,12 +10,7 @@ public interface IAcDalBase //: IDisposable
public interface IAcDalBase<TDbContext> : IAcDalBase where TDbContext : AcDbContextBase
{
public bool AutoCloseSession { get; set; }
/// <summary>
/// Do not use it! Use Session or Transaction... - J.
/// </summary>
public TDbContext Context { get; }
public Mutex MutextLock { get; }
public TDbContext CreateDbContext();
public void CloseDbContext(ref TDbContext? ctx);

View File

@ -1,5 +1,4 @@
using System.Collections.Concurrent;
using AyCode.Core.Extensions;
using AyCode.Utils.Extensions;
namespace AyCode.Database.DataLayers

View File

@ -10,151 +10,27 @@ using AyCode.Interfaces.Users;
using Microsoft.EntityFrameworkCore;
using AyCode.Database.Extensions;
using AyCode.Core.Consts;
using AyCode.Core.Helpers;
using AyCode.Core.Loggers;
using AyCode.Core.Server.Loggers;
using AyCode.Database.DbSets.Users;
using AyCode.Interfaces.Addresses;
using AyCode.Interfaces.Messages;
using AyCode.Interfaces.Profiles;
using AyCode.Interfaces.ServiceProviders;
using AyCode.Interfaces.Addresses.Dtos;
using AyCode.Interfaces.Profiles.Dtos;
namespace AyCode.Database.DataLayers.Users
{
public abstract class AcUserDalBase<TDbContext, TUser, TProfile, TUserToken, TCompany, TUserToCompany, TAddress, TEmailMessage> : AcDalBase<TDbContext>
where TDbContext : AcDbContextBase, IAcUserDbContextBase<TUser, TProfile, TUserToken, TCompany, TUserToCompany, TAddress, TEmailMessage>
where TUser : class, IAcUser<TProfile, TCompany, TUserToCompany, TAddress>
where TProfile : class, IAcProfile<TAddress>
public abstract class AcUserDalBase<TDbContext, TUser, TProfile, TUserToken, TServiceProvider, TUserToServiceProvider, TProfileAddress> : AcDalBase<TDbContext>
where TDbContext : AcDbContextBase, IAcUserDbContextBase<TUser, TProfile, TUserToken, TServiceProvider, TUserToServiceProvider, TProfileAddress>
where TUser : class, IAcUser<TProfile, TServiceProvider, TUserToServiceProvider, TProfileAddress>
where TProfile : class, IAcProfile<TProfileAddress>
where TUserToken : class, IAcUserTokenBase
where TCompany : class, IAcCompanyBase
where TUserToCompany : class, IAcUserToCompanyBase
where TAddress : class, IAcAddressDtoBase
where TEmailMessage : class, IAcEmailMessageBase
where TServiceProvider : class, IAcServiceProviderBase
where TUserToServiceProvider : class, IAcUserToServiceProviderBase
where TProfileAddress : class, IAcAddress
{
public TUser? GetUserById(Guid userId, bool onlyConfirmed) => Session(x => x.GetUserById(userId, onlyConfirmed));
public Task<TUser?> GetUserByIdAsync(Guid userId, bool onlyConfirmed) => SessionAsync(x => x.GetUserById(userId, onlyConfirmed));
public TUser? GetUserById(Guid userId) => Session(x => x.GetUserById(userId));
public Task<TUser?> GetUserByIdAsync(Guid userId) => SessionAsync(x => x.GetUserById(userId));
public TUser? GetUserByEmail(string? email, bool onlyConfirmed) => Session(x => x.GetUserByEmail(email, onlyConfirmed));
public Task<TUser?> GetUserByEmailAsync(string? email, bool onlyConfirmed) => SessionAsync(x => x.GetUserByEmail(email, onlyConfirmed));
public TUserModelDto? GetUserModelDtoById<TUserModelDto>(Guid userId, bool onlyConfirmed) where TUserModelDto : class, IAcUserModelDtoMinBase
=> Session(ctx => ctx.GetUserModelDtoById<TUserModelDto, TUser>(userId, onlyConfirmed));
public Task<TUserModelDto?> GetUserModelDtoByIdAsync<TUserModelDto>(Guid userId, bool onlyConfirmed) where TUserModelDto : class, IAcUserModelDtoMinBase
=> SessionAsync(ctx => ctx.GetUserModelDtoById<TUserModelDto, TUser>(userId, onlyConfirmed));
public TUserModelDto? GetUserModelDtoByEmail<TUserModelDto>(string email, bool onlyConfirmed) where TUserModelDto : class, IAcUserModelDtoMinBase
=> Session(ctx => ctx.GetUserModelDtoByEmail<TUserModelDto, TUser>(email, onlyConfirmed));
public Task<TUserModelDto?> GetUserModelDtoByEmailAsync<TUserModelDto>(string email, bool onlyConfirmed) where TUserModelDto : class, IAcUserModelDtoMinBase
=> SessionAsync(ctx => ctx.GetUserModelDtoByEmail<TUserModelDto, TUser>(email, onlyConfirmed));
public List<TUserModelDto> GetAllUserModelDto<TUserModelDto>() where TUserModelDto : class, IAcUserModelDtoMinBase
=> GetAllModelDto<TUserModelDto, TUser>();
public Task<List<TUserModelDto>> GetAllUserModelDtoAsync<TUserModelDto>() where TUserModelDto : class, IAcUserModelDtoMinBase
=> GetAllModelDtoAsync<TUserModelDto, TUser>();
public Task<List<TUser>> GetUsersAsync() => SessionAsync(ctx => ctx.Users.ToList());
//public Task<List<TUserModelDto>> GetUserEmails() => SessionAsync(ctx => ctx.Users.Select(x => new UserModelDtoEmail(x)).ToList());
public virtual Task<TUser?> UpdateUserAsync(TUser user) => UpdateSafeAsync(user);
public virtual TUser? UpdateUser(TUser user) => UpdateSafe(user);
public Task<bool> AddUserAsync(TUser user)
{
return TransactionAsync(ctx => ctx.AddUser(user));
}
public Task<bool> AddUserAsync(TUser user, string profileName, TAddress address, string? firstName = null, string? lastName = null)
{
return TransactionAsync(ctx =>
{
var profile = CreateProfile(profileName, address, firstName, lastName);
user.Profile= profile;
return ctx.AddUser(user);
});
}
public bool AddUser(TUser user, string profileName, TAddress address, string? firstName = null, string? lastName = null)
{
return Transaction(ctx =>
{
var profile = CreateProfile(profileName, address, firstName, lastName);
user.Profile = profile;
return ctx.AddUser(user);
});
}
private static TProfile CreateProfile(string profileName, TAddress address, string? firstName, string? lastName)
{
var profile = Activator.CreateInstance<TProfile>();
profile.Id = Guid.NewGuid();
profile.Name = profileName;
profile.FirstName = firstName;
profile.LastName = lastName;
profile.Address = address;
profile.AddressId = address.Id;
return profile;
}
public Task<bool> RemoveUserAsync(TUser user) => TransactionAsync(ctx => ctx.RemoveUser(user));
public Task<bool> RemoveUserAsync(Guid userId) => TransactionAsync(ctx => ctx.RemoveUser(userId));
public TUser? AuthenticateUser(string? email, string? password, string refreshToken, out AcErrorCode errorCode)
{
TUser? user = null;
var errorCodeInner = AcErrorCode.Unset;
var result = Transaction(ctx =>
{
try
{
//var passwordHash = PasswordHasher.HashPassword(password, PasswordHasher.GenerateDynamicSalt(userId));
user = ctx.GetUserByEmail(email, true);
if (user is { EmailConfirmed: true } && string.Equals(user.EmailAddress, email, StringComparison.CurrentCultureIgnoreCase)
&& PasswordHasher.VerifyPassword(password, user.Password, PasswordHasher.GenerateDynamicSalt(user.Id)))
{
if (ctx.UpdateJwtRefreshToken(user, refreshToken)) return true;
errorCodeInner = AcErrorCode.RefreshTokenUpdateError;
}
else errorCodeInner = AcErrorCode.WrongLoginData;
}
catch (Exception ex)
{
GlobalLogger.Error(ex.Message, ex);
errorCodeInner = AcErrorCode.UnknownError;
}
return false;
});
errorCode = errorCodeInner;
return result ? user : null;
}
public async Task<TUser?> UpdateJwtRefreshTokenAsync(string email, string refreshToken)
{
TUser? user = null;
return await TransactionAsync(ctx => (user = ctx.UpdateJwtRefreshToken(email, refreshToken)) != null) ? user : null;
}
public TUser? UpdateJwtRefreshToken(string email, string refreshToken)
{
TUser? user = null;
return Transaction(ctx => (user = ctx.UpdateJwtRefreshToken(email, refreshToken)) != null) ? user : null;
}
public TUser? GetUserByEmail(string email) => Session(x => x.GetUserByEmail(email));
public Task<TUser?> GetUserByEmailAsync(string email) => SessionAsync(x => x.GetUserByEmail(email));
//public UserToken CreateUserToken(Guid userId, string verificationToken)
//{

View File

@ -1,21 +1,17 @@
using AyCode.Core.Consts;
using System.Runtime.CompilerServices;
using Microsoft.EntityFrameworkCore;
using AyCode.Interfaces.TimeStampInfo;
using Microsoft.Extensions.Configuration;
namespace AyCode.Database.DbContexts;
public abstract class AcDbContextBase : DbContext, IAcDbContextBase
public abstract class AcDbContextBase : DbContext
{
private readonly string? _connString;
public string Name { get; set; }
public Guid SessionId { get; protected set; } = Guid.NewGuid();
protected AcDbContextBase()
{
_connString = AcEnv.AppConfiguration.GetConnectionString("DeveloperDbConnection");
//DbInterception.Add(new UtcDateTimeDbCommandInterceptor());
}
@ -27,15 +23,11 @@ public abstract class AcDbContextBase : DbContext, IAcDbContextBase
protected AcDbContextBase(DbContextOptions<DbContext> options, string name) : base(options)
{
Name = name;
_connString = AcEnv.AppConfiguration.GetConnectionString("DeveloperDbConnection");
}
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseLazyLoadingProxies(true);
optionsBuilder.UseSqlServer(_connString);
}
public override int SaveChanges()
@ -67,6 +59,7 @@ public abstract class AcDbContextBase : DbContext, IAcDbContextBase
var utcNow = DateTime.UtcNow;
foreach (var entityEntry in entries)
{
//entityEntry.DebugView.LongView
if (entityEntry.Entity is ITimeStampModified timeStampModified)
timeStampModified.Modified = utcNow;
@ -79,7 +72,6 @@ public abstract class AcDbContextBase : DbContext, IAcDbContextBase
continue;
}
//entityEntry.State = EntityState.Unchanged;
entityEntry.Property(nameof(timeStampCreated.Created)).IsModified = false;
}
}

View File

@ -1,7 +0,0 @@
namespace AyCode.Database.DbContexts;
public interface IAcDbContextBase
{
public string Name { get; set; }
public Guid SessionId { get; }
}

View File

@ -1,19 +0,0 @@
using AyCode.Database.DbSets.Loggers;
using AyCode.Entities.Server.LogItems;
using AyCode.Interfaces.Entities;
using Microsoft.EntityFrameworkCore;
using Microsoft.Identity.Client;
namespace AyCode.Database.DbContexts.Loggers;
public class AcLoggerDbContextBase<TLogItem> : AcDbContextBase, IAcLoggerDbContextBase<TLogItem> where TLogItem : class, IAcLogItem
{
public DbSet<TLogItem> LogItems { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
base.OnConfiguring(optionsBuilder);
optionsBuilder.UseQueryTrackingBehavior(QueryTrackingBehavior.NoTracking);
}
}

View File

@ -1,10 +0,0 @@
using AyCode.Database.DbSets.Loggers;
using AyCode.Entities.Server.LogItems;
using AyCode.Interfaces.Entities;
namespace AyCode.Database.DbContexts.Loggers;
public interface IAcLoggerDbContextBase<TLogItem> : IAcLogItemDbSetBase<TLogItem> where TLogItem : class, IAcLogItem
{
}

View File

@ -1,7 +1,9 @@
using AyCode.Database.ModelBuilders.Profiles;
using AyCode.Database.ModelBuilders.Users;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using AyCode.Interfaces.Addresses;
using AyCode.Interfaces.Messages;
using AyCode.Interfaces.Profiles;
using AyCode.Interfaces.ServiceProviders;
using AyCode.Interfaces.Users;
@ -9,21 +11,16 @@ using Microsoft.EntityFrameworkCore;
namespace AyCode.Database.DbContexts.Users
{
public abstract class AcUserDbContextBase<TUser, TProfile, TUserToken, TCompany, TUserToCompany, TAddress, TEmailMessage> : AcDbContextBase, IAcUserDbContextBase<TUser, TProfile, TUserToken, TCompany, TUserToCompany, TAddress, TEmailMessage>
where TUser : class, IAcUser<TProfile, TCompany, TUserToCompany, TAddress>
where TProfile : class, IAcProfile<TAddress>
public abstract class AcUserDbContextBase<TUser, TProfile, TUserToken, TServiceProvider, TUserToServiceProvider, TProfileAddress> : AcDbContextBase, IAcUserDbContextBase<TUser, TProfile, TUserToken, TServiceProvider, TUserToServiceProvider, TProfileAddress>
where TUser : class, IAcUser<TProfile, TServiceProvider, TUserToServiceProvider, TProfileAddress>
where TProfile : class, IAcProfile<TProfileAddress>
where TUserToken : class, IAcUserTokenBase
where TCompany : class, IAcCompany<TUser, TUserToCompany, TProfile>//IAcServiceProviderBase
where TUserToCompany : class, IAcUserToCompanyBase
where TAddress : class, IAcAddress
where TEmailMessage : class, IAcEmailMessageBase
where TServiceProvider : class, IAcServiceProviderBase
where TUserToServiceProvider : class, IAcUserToServiceProviderBase
where TProfileAddress : class, IAcAddress
{
public required DbSet<TUser> Users { get; set; }
public required DbSet<TUserToken> UserTokens { get; set; }
public DbSet<TAddress> Addresses { get; set; }
public DbSet<TProfile> Profiles { get; set; }
public DbSet<TEmailMessage> EmailMessages { get; set; }
public DbSet<TCompany> Companies { get; set; }
protected AcUserDbContextBase() : this(string.Empty)
{ }
@ -34,22 +31,5 @@ namespace AyCode.Database.DbContexts.Users
protected AcUserDbContextBase(DbContextOptions<DbContext> options, string name) : base(options, name)
{
}
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
base.OnConfiguring(optionsBuilder);
optionsBuilder.UseLazyLoadingProxies(true);
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
new AcUserEntityTypeDefaultConfiguration<TUser, TProfile, TCompany, TUserToCompany, TAddress>().Configure(modelBuilder.Entity<TUser>());
new AcProfileEntityTypeDefaultConfiguration<TProfile, TAddress>().Configure(modelBuilder.Entity<TProfile>());
//new EmailMessageEntityTypeDefaultConfigurations().Configure(modelBuilder.Entity<EmailMessage>());
}
}
}

View File

@ -1,25 +1,18 @@
using AyCode.Database.DbSets.Addresses;
using AyCode.Database.DbSets.Messages;
using AyCode.Database.DbSets.Profiles;
using AyCode.Database.DbSets.Users;
using AyCode.Database.DbSets.Users;
using AyCode.Interfaces.Addresses;
using AyCode.Interfaces.Addresses.Dtos;
using AyCode.Interfaces.Messages;
using AyCode.Interfaces.Profiles;
using AyCode.Interfaces.ServiceProviders;
using AyCode.Interfaces.Users;
using Microsoft.EntityFrameworkCore;
namespace AyCode.Database.DbContexts.Users;
public interface IAcUserDbContextBase<TUser, TProfile, TUserToken, TCompany, TUserToServiceProvider, TProfileAddress, TEmailMessage>
: IAcUserDbSetBase<TUser, TProfile, TCompany, TUserToServiceProvider, TProfileAddress>, IAcUserTokenDbSet<TUserToken>, IAcEmailMessageDbSet<TEmailMessage>
where TUser : class, IAcUser<TProfile, TCompany, TUserToServiceProvider, TProfileAddress>
public interface IAcUserDbContextBase<TUser, TProfile, TUserToken, TServiceProvider, TUserToServiceProvider, TProfileAddress> : IAcUserDbSet<TUser, TProfile, TServiceProvider, TUserToServiceProvider, TProfileAddress>, IAcUserTokenDbSet<TUserToken>
where TUser : class, IAcUser<TProfile, TServiceProvider, TUserToServiceProvider, TProfileAddress>
where TProfile : class, IAcProfile<TProfileAddress>
where TUserToken : class, IAcUserTokenBase
where TCompany : class, IAcCompanyBase
where TUserToServiceProvider : class, IAcUserToCompanyBase
where TProfileAddress : class, IAcAddressDtoBase
where TEmailMessage : class, IAcEmailMessageBase
where TServiceProvider : class, IAcServiceProviderBase
where TUserToServiceProvider : class, IAcUserToServiceProviderBase
where TProfileAddress : class, IAcAddress
{
}

View File

@ -1,36 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
using AyCode.Interfaces.Addresses;
using AyCode.Interfaces.Addresses.Dtos;
using AyCode.Interfaces.Profiles;
using Microsoft.EntityFrameworkCore;
namespace AyCode.Database.DbSets.Addresses
{
public static class AcAddressDbSetExtensions
{
public static IQueryable<TAddress> GetAddresses<TAddress>(this IAcAddressDbSetBase<TAddress> ctx) where TAddress : class, IAcAddressDtoBase
=> ctx.Addresses;
public static TAddress? GetAddressById<TAddress>(this IAcAddressDbSetBase<TAddress> ctx, Guid addressId) where TAddress : class, IAcAddressDtoBase
=> ctx.GetAddresses().FirstOrDefault(x => x.Id == addressId);
public static bool UpdateAddress<TAddress>(this IAcAddressDbSetBase<TAddress> ctx, TAddress address) where TAddress : class, IAcAddressDtoBase
=> ctx.Addresses.Update(address).State == EntityState.Modified;
public static bool RemoveAddress<TAddress>(this IAcAddressDbSetBase<TAddress> ctx, TAddress address) where TAddress : class, IAcAddressDtoBase
=> ctx.Addresses.Remove(address).State == EntityState.Deleted;
public static bool RemoveAddress<TAddress>(this IAcAddressDbSetBase<TAddress> ctx, Guid addressId) where TAddress : class, IAcAddressDtoBase
{
var address = ctx.GetAddressById(addressId);
return address != null && ctx.RemoveAddress(address);
}
}
}

View File

@ -1,11 +1,10 @@
using AyCode.Interfaces.Addresses;
using AyCode.Interfaces.Addresses.Dtos;
using AyCode.Interfaces.Users;
using Microsoft.EntityFrameworkCore;
namespace AyCode.Database.DbSets.Addresses;
public interface IAcAddressDbSetBase<TAddress> where TAddress : class, IAcAddressDtoBase
public interface IAcAddressDbSetBase<TAddress> where TAddress : class, IAcAddress
{
DbSet<TAddress> Addresses { get; set; }
}

View File

@ -0,0 +1,18 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using AyCode.Interfaces.Addresses;
namespace AyCode.Database.DbSets.Addresses
{
public static class AcAddressDbSetExtensions
{
public static IQueryable<TAddress> GetAddresses<TAddress>(this IAcAddressDbSetBase<TAddress> ctx) where TAddress : class, IAcAddress
=> ctx.Addresses;
public static TAddress? GetAddressById<TAddress>(this IAcAddressDbSetBase<TAddress> ctx, Guid addressId) where TAddress : class, IAcAddress
=> ctx.GetAddresses().FirstOrDefault(x => x.Id == addressId);
}
}

View File

@ -1,99 +0,0 @@
using AyCode.Core.Extensions;
using AyCode.Database.DbSets.Profiles;
using AyCode.Interfaces.Addresses;
using AyCode.Interfaces.Profiles;
using AyCode.Interfaces.Profiles.Dtos;
using AyCode.Interfaces.ServiceProviders;
using AyCode.Interfaces.Users;
using AyCode.Utils.Extensions;
using Microsoft.EntityFrameworkCore;
namespace AyCode.Database.DbSets.Companies;
public static class AcCompanyDbSetExtensions
{
#region Add, Update, Remove
public static bool AddCompany<TCompany, TProfile, TAddress>(this IAcCompanyDbSetBase<TCompany> ctx, TCompany company)
where TCompany : class, IAcCompany<TProfile, TAddress>
where TProfile : class, IAcProfile<TAddress>
where TAddress : class, IAcAddress
{
if (company.Profile == null!)
company.SetProfile((Activator.CreateInstance(typeof(TProfile), company.ProfileId, company.Name) as TProfile)!);
if (company.Profile!.Address == null!)
company.Profile.SetAddress((Activator.CreateInstance(typeof(TAddress), company.Profile.AddressId, company.Name) as TAddress)!);
if (!company.OwnerId.IsNullOrEmpty())
company.AddUser(company.OwnerId.Value, 1);
return ctx.Companies.Add(company).State == EntityState.Added;
}
public static bool UpdateCompany<TCompany, TProfile, TAddress, TUserToCompany>(this IAcCompanyDbSetBase<TCompany, TProfile, TAddress, TUserToCompany> ctx, TCompany company)
where TCompany : class, IAcCompany<TProfile, TAddress>
where TProfile : class, IAcProfile<TAddress>
where TAddress : class, IAcAddress
where TUserToCompany : class, IAcUserToCompanyBase
{
var companyProfile = company.Profile;
if (company.ProfileId.IsNullOrEmpty() || companyProfile.Id != company.ProfileId || companyProfile.AddressId.IsNullOrEmpty() || companyProfile.Address.Id != companyProfile.AddressId)
{
return false;
}
var ownerId = company.OwnerId;
if (!ownerId.IsNullOrEmpty() && !company.HasUser(ownerId.Value))
{
if (!ctx.UserToCompanies.Any(x => x.UserId == company.OwnerId && x.ServiceProviderId == company.Id))
{
var userToCompany = (Activator.CreateInstance(typeof(TUserToCompany)) as TUserToCompany)!;
userToCompany.Id = Guid.NewGuid();
userToCompany.ServiceProviderId = company.Id;
userToCompany.UserId = ownerId.Value;
userToCompany.Permissions = 1;
ctx.UserToCompanies.Add(userToCompany);
//company.AddUser(ownerId.Value, 1);
}
}
return ctx.Companies.Update(company).State == EntityState.Modified;
}
private static bool RemoveCompany<TCompany, TProfile, TAddress, TUserToCompany>(this IAcCompanyDbSetBase<TCompany, TProfile, TAddress, TUserToCompany> ctx, TCompany company)
where TCompany : class, IAcCompany<TProfile, TAddress>
where TProfile : class, IAcProfile<TAddress>
where TAddress : class, IAcAddress
where TUserToCompany : class, IAcUserToCompanyBase
{
ctx.RemoveProfile(company.ProfileId);
ctx.UserToCompanies.RemoveRange(ctx.UserToCompanies.Where(x => x.ServiceProviderId == company.Id));
//TODO: RemoveProduct, UserToProduct, etc... - J.
return ctx.Companies.Remove(company).State == EntityState.Deleted;
}
public static bool RemoveCompany<TCompany, TProfile, TAddress, TUserToCompany>(this IAcCompanyDbSetBase<TCompany, TProfile, TAddress, TUserToCompany> ctx, Guid companyId)
where TCompany : class, IAcCompany<TProfile, TAddress>
where TProfile : class, IAcProfile<TAddress>
where TAddress : class, IAcAddress
where TUserToCompany : class, IAcUserToCompanyBase
{
var company = ctx.GetCompanyById(companyId);
return company == null || ctx.RemoveCompany(company);
}
#endregion Add, Update, Remove
public static TCompany? GetCompanyById<TCompany>(this IAcCompanyDbSetBase<TCompany> ctx, Guid companyId) where TCompany : class, IAcCompanyBase
=> ctx.Companies.FirstOrDefault(x => x.Id == companyId);
public static IQueryable<TCompany> GetCompanies<TCompany>(this IAcCompanyDbSetBase<TCompany> ctx) where TCompany : class, IAcCompanyBase
=> ctx.Companies;
public static List<TCompany> GetCompaniesByOwnerId<TCompany>(this IAcCompanyDbSetBase<TCompany> ctx, Guid ownerId) where TCompany : class, IAcCompanyBase
=> ctx.Companies.Where(x => x.OwnerId == ownerId).ToList();
}

View File

@ -1,33 +0,0 @@
using AyCode.Database.DbSets.Profiles;
using AyCode.Database.DbSets.Users;
using AyCode.Interfaces.Addresses;
using AyCode.Interfaces.Profiles;
using AyCode.Interfaces.Profiles.Dtos;
using AyCode.Interfaces.ServiceProviders;
using AyCode.Interfaces.Users;
using Microsoft.EntityFrameworkCore;
namespace AyCode.Database.DbSets.Companies;
public interface IAcCompanyDbSetBase<TCompany> where TCompany : class, IAcCompanyBase
{
DbSet<TCompany> Companies { get; set; }
}
public interface IAcCompanyDbSetBase<TCompany, TProfile> : IAcCompanyDbSetBase<TCompany>, IAcProfileDbSetBase<TProfile>
where TCompany : class, IAcCompany<TProfile>
where TProfile : class, IAcProfileDtoBase
{ }
public interface IAcCompanyDbSetBase<TCompany, TProfile, TAddress> : IAcCompanyDbSetBase<TCompany, TProfile>, IAcProfileDbSetBase<TProfile, TAddress>
where TCompany : class, IAcCompany<TProfile, TAddress>
where TProfile : class, IAcProfile<TAddress>
where TAddress : class, IAcAddress
{ }
public interface IAcCompanyDbSetBase<TCompany, TProfile, TAddress, TUserToCompany> : IAcCompanyDbSetBase<TCompany, TProfile, TAddress>, IAcUserToCompanyDbSetBase<TUserToCompany>
where TCompany : class, IAcCompany<TProfile, TAddress>
where TProfile : class, IAcProfile<TAddress>
where TAddress : class, IAcAddress
where TUserToCompany : class, IAcUserToCompanyBase
{ }

View File

@ -1,15 +0,0 @@
using AyCode.Interfaces.Entities;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata;
namespace AyCode.Database.DbSets;
public class AcDbTableBase<TEntity> : DbSet<TEntity>, IAcDbTableBase where TEntity : class, IEntity
{
public override IEntityType EntityType { get; } = null!;
}
public interface IAcDbTableBase
{
}

View File

@ -1,11 +0,0 @@
using AyCode.Entities.Server.LogItems;
using AyCode.Interfaces.Entities;
using AyCode.Interfaces.Users;
using Microsoft.EntityFrameworkCore;
namespace AyCode.Database.DbSets.Loggers;
public interface IAcLogItemDbSetBase<TLogItem> where TLogItem : class, IAcLogItem
{
DbSet<TLogItem> LogItems { get; set; }
}

View File

@ -1,118 +0,0 @@
using AyCode.Interfaces.Messages;
using Microsoft.EntityFrameworkCore;
namespace AyCode.Database.DbSets.Messages;
public static class AcEmailMessageDbSetExtension
{
public static TEmailMessage? GetEmailMessageById<TEmailMessage>(this IAcEmailMessageDbSet<TEmailMessage> ctx, Guid emailMessageId) where TEmailMessage : class, IAcEmailMessageBase
=> ctx.EmailMessages.FirstOrDefault(x => x.Id == emailMessageId);
public static IQueryable<TEmailMessage> GetEmailMessagesByContextId<TEmailMessage>(this IAcEmailMessageDbSet<TEmailMessage> ctx, Guid contextId) where TEmailMessage : class, IAcEmailMessageBase
=> ctx.EmailMessages.Where(x => x.ContextId == contextId);
public static IQueryable<TEmailMessage> GetEmailMessagesBySenderEmailAddress<TEmailMessage>(this IAcEmailMessageDbSet<TEmailMessage> ctx, string senderEmailAddress) where TEmailMessage : class, IAcEmailMessageBase
=> ctx.EmailMessages.Where(x => x.EmailAddress == senderEmailAddress);
public static IQueryable<TEmailMessage> GetEmailMessagesBySenderId<TEmailMessage>(this IAcEmailMessageDbSet<TEmailMessage> ctx, Guid senderId) where TEmailMessage : class, IAcEmailMessageBase
=> ctx.EmailMessages.Where(x => x.SenderId == senderId);
public static IQueryable<TEmailMessage> GetEmailMessagesByRecipientId<TEmailMessage, TEmailRecipient>(this IAcEmailMessageDbSet<TEmailMessage> ctx, Guid recipientId)
where TEmailMessage : class, IAcEmailMessageBase, IAcEmailRecipientsRelation<TEmailRecipient>
where TEmailRecipient : IAcEmailRecipientBase
{
return ctx.EmailMessages.Where(x => x.Recipients.Any(recipient => recipient.RecipientId == recipientId));
}
private static IQueryable<TEmailMessage> GetEmailMessagesBySenderIdOrRecipientId<TEmailMessage, TEmailRecipient>(this IQueryable<TEmailMessage> queryableEmails, Guid senderIdOrRecipientId)
where TEmailMessage : class, IAcEmailMessageBase, IAcEmailRecipientsRelation<TEmailRecipient>
where TEmailRecipient : IAcEmailRecipientBase
{
return queryableEmails.Where(x => x.SenderId == senderIdOrRecipientId || x.Recipients.Any(recipient => recipient.RecipientId == senderIdOrRecipientId));
}
public static IQueryable<TEmailMessage> GetEmailMessages<TEmailMessage, TEmailRecipient>(this IAcEmailMessageDbSet<TEmailMessage> ctx, Guid senderIdOrRecipientId)
where TEmailMessage : class, IAcEmailMessageBase, IAcEmailRecipientsRelation<TEmailRecipient>
where TEmailRecipient : IAcEmailRecipientBase
{
return ctx.EmailMessages.GetEmailMessagesBySenderIdOrRecipientId<TEmailMessage, TEmailRecipient>(senderIdOrRecipientId);
}
public static IQueryable<TEmailMessage> GetEmailMessages<TEmailMessage, TEmailRecipient>(this IAcEmailMessageDbSet<TEmailMessage> ctx, Guid contextId, Guid senderIdOrRecipientId)
where TEmailMessage : class, IAcEmailMessageBase, IAcEmailRecipientsRelation<TEmailRecipient>
where TEmailRecipient : IAcEmailRecipientBase
{
return ctx.EmailMessages.Where(x => x.ContextId == contextId).GetEmailMessagesBySenderIdOrRecipientId<TEmailMessage, TEmailRecipient>(senderIdOrRecipientId);
}
private static IQueryable<TEmailMessage> GetEmailMessagesByUserIdOrUpmId<TEmailMessage, TEmailRecipient>(this IQueryable<TEmailMessage> queryableEmails, Guid userId, Guid userProductMappingId)
where TEmailMessage : class, IAcEmailMessageBase, IAcEmailRecipientsRelation<TEmailRecipient>
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<TEmailMessage> GetEmailMessagesByUserIdOrUpmId<TEmailMessage, TEmailRecipient>(this IAcEmailMessageDbSet<TEmailMessage> ctx, Guid userId, Guid userProductMappingId)
where TEmailMessage : class, IAcEmailMessageBase, IAcEmailRecipientsRelation<TEmailRecipient>
where TEmailRecipient : IAcEmailRecipientBase
{
return ctx.EmailMessages.GetEmailMessagesByUserIdOrUpmId<TEmailMessage, TEmailRecipient>(userId, userProductMappingId);
}
public static IQueryable<TEmailMessage> GetAllEmailMessages<TEmailMessage, TEmailRecipient>(this IAcEmailMessageDbSet<TEmailMessage> ctx)
where TEmailMessage : class, IAcEmailMessageBase, IAcEmailRecipientsRelation<TEmailRecipient>
where TEmailRecipient : IAcEmailRecipientBase
{
return ctx.EmailMessages;
}
public static IQueryable<TEmailMessage> GetEmailMessages<TEmailMessage, TEmailRecipient>(this IAcEmailMessageDbSet<TEmailMessage> ctx, Guid contextId, Guid userId, Guid userProductMappingId)
where TEmailMessage : class, IAcEmailMessageBase, IAcEmailRecipientsRelation<TEmailRecipient>
where TEmailRecipient : IAcEmailRecipientBase
{
return ctx.GetEmailMessagesByContextId(contextId).GetEmailMessagesByUserIdOrUpmId<TEmailMessage, TEmailRecipient>(userId, userProductMappingId);
}
private static IQueryable<TEmailMessage> GetEmailMessagesByIds<TEmailMessage, TEmailRecipient>(this IQueryable<TEmailMessage> queryableEmails, IQueryable<Guid> ids)
where TEmailMessage : class, IAcEmailMessageBase, IAcEmailRecipientsRelation<TEmailRecipient>
where TEmailRecipient : IAcEmailRecipientBase
{
return queryableEmails.Where(x => ids.Any(id => id == x.SenderId) || x.Recipients.Any(recipient => ids.Any(id => id == recipient.RecipientId)));
}
public static IQueryable<TEmailMessage> GetEmailMessagesByIds<TEmailMessage, TEmailRecipient>(this IAcEmailMessageDbSet<TEmailMessage> ctx, IQueryable<Guid> ids)
where TEmailMessage : class, IAcEmailMessageBase, IAcEmailRecipientsRelation<TEmailRecipient>
where TEmailRecipient : IAcEmailRecipientBase
{
return ctx.EmailMessages.GetEmailMessagesByIds<TEmailMessage, TEmailRecipient>(ids);
}
public static IQueryable<TEmailMessage> GetEmailMessagesByIds<TEmailMessage, TEmailRecipient>(this IAcEmailMessageDbSet<TEmailMessage> ctx, Guid contextId, IQueryable<Guid> ids)
where TEmailMessage : class, IAcEmailMessageBase, IAcEmailRecipientsRelation<TEmailRecipient>
where TEmailRecipient : IAcEmailRecipientBase
{
return ctx.GetEmailMessagesByContextId(contextId).GetEmailMessagesByIds<TEmailMessage, TEmailRecipient>(ids);
}
#region Add, Update, Remove
public static bool AddEmailMessage<TEmailMessage>(this IAcEmailMessageDbSet<TEmailMessage> ctx, TEmailMessage emailMessage) where TEmailMessage : class, IAcEmailMessageBase
=> ctx.EmailMessages.Add(emailMessage).State == EntityState.Added;
public static bool UpdateEmailMessage<TEmailMessage>(this IAcEmailMessageDbSet<TEmailMessage> ctx, TEmailMessage emailMessage) where TEmailMessage : class, IAcEmailMessageBase
=> ctx.EmailMessages.Update(emailMessage).State == EntityState.Modified;
public static bool RemoveEmailMessage<TEmailMessage>(this IAcEmailMessageDbSet<TEmailMessage> ctx, Guid emailMessageId) where TEmailMessage : class, IAcEmailMessageBase
{
var emailMessage = ctx.GetEmailMessageById(emailMessageId);
return emailMessage == null || ctx.RemoveEmailMessage(emailMessage);
}
public static bool RemoveEmailMessage<TEmailMessage>(this IAcEmailMessageDbSet<TEmailMessage> ctx, TEmailMessage emailMessage) where TEmailMessage : class, IAcEmailMessageBase
=> ctx.EmailMessages.Remove(emailMessage).State == EntityState.Deleted;
#endregion Add, Update, Remove
}

View File

@ -1,9 +0,0 @@
using AyCode.Interfaces.Messages;
using Microsoft.EntityFrameworkCore;
namespace AyCode.Database.DbSets.Messages;
public interface IAcEmailMessageDbSet<TEmailMessage> where TEmailMessage : class, IAcEmailMessageBase
{
public DbSet<TEmailMessage> EmailMessages { get; set; }
}

View File

@ -1,44 +0,0 @@
using AyCode.Core.Server.Loggers;
using AyCode.Database.DbSets.Addresses;
using AyCode.Database.DbSets.Profiles;
using AyCode.Entities;
using AyCode.Interfaces.Addresses;
using AyCode.Interfaces.Profiles.Dtos;
using AyCode.Interfaces.Profiles;
using Microsoft.EntityFrameworkCore;
using AyCode.Interfaces.Addresses.Dtos;
using AyCode.Database.DbSets.Users;
using AyCode.Interfaces.Users;
namespace AyCode.Database.DbSets.Profiles;
public static class AcProfileDbSetExtensions
{
public static TProfile? GetProfileById<TProfile>(this IAcProfileDbSetBase<TProfile> ctx, Guid profileId) where TProfile : class, IAcProfileDtoBase
=> ctx.Profiles.FirstOrDefault(u => u.Id == profileId);
public static bool AddProfile<TProfile>(this IAcProfileDbSetBase<TProfile> ctx, TProfile profile) where TProfile : class, IAcProfileDtoBase
=> ctx.Profiles.Add(profile).State == EntityState.Added;
public static bool UpdateProfile<TProfile>(this IAcProfileDbSetBase<TProfile> ctx, TProfile profile) where TProfile : class, IAcProfileDtoBase
=> ctx.Profiles.Update(profile).State == EntityState.Modified;
private static bool RemoveProfile<TProfile, TAddress>(this IAcProfileDbSetBase<TProfile, TAddress> ctx, TProfile profile)
where TProfile : class, IAcProfile<TAddress>
where TAddress : class, IAcAddressDtoBase
{
var address = ctx.GetAddressById(profile.AddressId);
if (address != null) ctx.Addresses.Remove(address);
return ctx.Profiles.Remove(profile).State == EntityState.Deleted;
}
public static bool RemoveProfile<TProfile, TAddress>(this IAcProfileDbSetBase<TProfile, TAddress> ctx, Guid profileId)
where TProfile : class, IAcProfile<TAddress>
where TAddress : class, IAcAddressDtoBase
{
var profile = ctx.GetProfileById(profileId);
return profile != null && ctx.RemoveProfile(profile);
}
}

View File

@ -1,20 +0,0 @@
using AyCode.Database.DbSets.Addresses;
using AyCode.Interfaces.Addresses;
using AyCode.Interfaces.Addresses.Dtos;
using AyCode.Interfaces.Profiles;
using AyCode.Interfaces.Profiles.Dtos;
using AyCode.Interfaces.Users;
using Microsoft.EntityFrameworkCore;
namespace AyCode.Database.DbSets.Profiles;
public interface IAcProfileDbSetBase<TProfile> where TProfile : class, IAcProfileDtoBase
{
DbSet<TProfile> Profiles { get; set; }
}
public interface IAcProfileDbSetBase<TProfile, TAddress> : IAcProfileDbSetBase<TProfile>, IAcAddressDbSetBase<TAddress>
where TProfile : class, IAcProfile<TAddress>
where TAddress : class, IAcAddressDtoBase
{
}

View File

@ -1,119 +1,26 @@
using AyCode.Core.Extensions;
using AyCode.Core.Loggers;
using AyCode.Core.Server.Loggers;
using AyCode.Database.DbSets.Profiles;
using AyCode.Database.Extensions;
using AyCode.Entities;
using AyCode.Core.Logger;
using AyCode.Entities.Users;
using AyCode.Interfaces.Addresses;
using AyCode.Interfaces.Addresses.Dtos;
using AyCode.Interfaces.Entities;
using AyCode.Interfaces.Profiles;
using AyCode.Interfaces.Profiles.Dtos;
using AyCode.Interfaces.ServiceProviders;
using AyCode.Interfaces.Users;
using AyCode.Models.Users;
using Microsoft.EntityFrameworkCore;
namespace AyCode.Database.DbSets.Users;
public static class AcUserDbSetExtensions
{
public static TUser? AuthenticateUser<TUser>(this IAcUserDbSetBase<TUser> ctx, string? email, string? passwordHash, bool onlyConfirmed) where TUser : class, IAcUserBase
public static TUser? GetUserById<TUser>(this IAcUserDbSetBase<TUser> ctx, Guid userId) where TUser : class, IAcUserBase
=> ctx.GetUsersById(userId).FirstOrDefault();
public static TUser? GetUserByEmail<TUser>(this IAcUserDbSetBase<TUser> ctx, string email) where TUser : class, IAcUserBase
=> ctx.GetUsersByEmail(email).FirstOrDefault();
public static IQueryable<TUser> GetUsersById<TUser>(this IAcUserDbSetBase<TUser> ctx, Guid userId) where TUser : class, IAcUserBase
=> ctx.Users.Where(u => u.Id == userId);
public static IQueryable<TUser> GetUsersByEmail<TUser>(this IAcUserDbSetBase<TUser> ctx, string email) where TUser : class, IAcUserBase
{
if (string.IsNullOrWhiteSpace(email) || string.IsNullOrWhiteSpace(passwordHash))
return null;
return ctx.GetQueryableUserByEmail(email, onlyConfirmed)?.SingleOrDefault(u => u.Password == passwordHash);
}
public static TUser? GetUserById<TUser>(this IAcUserDbSetBase<TUser> ctx, Guid userId, bool onlyConfirmed) where TUser : class, IAcUserBase
=> ctx.Users.FirstOrDefault(u => u.Id == userId && (!onlyConfirmed || u.EmailConfirmed));
public static TUserModelDto? GetUserModelDtoById<TUserModelDto, TUser>(this IAcUserDbSetBase<TUser> ctx, Guid userId, bool onlyConfirmed)
where TUserModelDto : class, IAcUserModelDtoMinBase
where TUser : class, IAcUserBase
{
return ctx.GetUserById(userId, onlyConfirmed)?.ToModelDto<TUserModelDto, TUser>();
}
public static TUser? GetUserByEmail<TUser>(this IAcUserDbSetBase<TUser> ctx, string? email, bool onlyConfirmed) where TUser : class, IAcUserBase
=> ctx.GetQueryableUserByEmail(email, onlyConfirmed)?.FirstOrDefault();
public static TUserModelDto? GetUserModelDtoByEmail<TUserModelDto, TUser>(this IAcUserDbSetBase<TUser> ctx, string? email, bool onlyConfirmed)
where TUserModelDto : class, IAcUserModelDtoMinBase
where TUser : class, IAcUserBase
{
return ctx.GetUserByEmail(email, onlyConfirmed)?.ToModelDto<TUserModelDto, TUser>();
}
public static IQueryable<TUser> GetQueryableUsersById<TUser>(this IAcUserDbSetBase<TUser> ctx, Guid userId, bool onlyConfirmed) where TUser : class, IAcUserBase
=> ctx.Users.Where(u => u.Id == userId && (!onlyConfirmed || u.EmailConfirmed));
public static IQueryable<TUser>? GetQueryableUserByEmail<TUser>(this IAcUserDbSetBase<TUser> ctx, string? email, bool onlyConfirmed) where TUser : class, IAcUserBase
{
GlobalLogger.Info($"GetUserByEmail: {email}");
if (string.IsNullOrWhiteSpace(email)) return null;
Logger.Info($"GetUserByEmail: {email}");
var emailLower = email.ToLower();
return ctx.Users.Where(u => u.EmailAddress == emailLower && (!onlyConfirmed || u.EmailConfirmed));
}
public static bool AddUser<TUser>(this IAcUserDbSetBase<TUser> ctx, TUser user) where TUser : class, IAcUserBase
{
var emailLower = user.EmailAddress.ToLower();
GlobalLogger.Info($"AddUser: {emailLower}");
return ctx.Users.Add(user).State == EntityState.Added;
}
public static bool UpdateUser<TUser>(this IAcUserDbSetBase<TUser> ctx, TUser user) where TUser : class, IAcUserBase
=> ctx.Users.Update(user).State == EntityState.Modified;
public static bool RemoveUser<TUser, TProfile, TAddress>(this IAcUserDbSetBase<TUser, TProfile, TAddress> ctx, TUser user)
where TUser : class, IAcUser<TProfile, TAddress>
where TProfile : class, IAcProfile<TAddress>
where TAddress : class, IAcAddressDtoBase
{
ctx.RemoveProfile(user.ProfileId);
return ctx.Users.Remove(user).State == EntityState.Deleted;
}
public static bool RemoveUser<TUser, TProfile, TAddress>(this IAcUserDbSetBase<TUser, TProfile, TAddress> ctx, Guid userId)
where TUser : class, IAcUser<TProfile, TAddress>
where TProfile : class, IAcProfile<TAddress>
where TAddress : class, IAcAddressDtoBase
{
var user = ctx.GetUserById(userId, false);
return user != null && ctx.RemoveUser(user);
}
public static bool UpdateJwtRefreshToken<TUser>(this IAcUserDbSetBase<TUser> ctx, TUser user, string refreshToken) where TUser : class, IAcUserBase
{
if (string.IsNullOrWhiteSpace(refreshToken)) return false;
user.RefreshToken = refreshToken;
ctx.Users.Update(user);
return true;
}
public static TUser? UpdateJwtRefreshToken<TUser>(this IAcUserDbSetBase<TUser> ctx, string email, string refreshToken) where TUser : class, IAcUserBase
{
GlobalLogger.Info(@"UserDal Update refresh token");
if (string.IsNullOrWhiteSpace(refreshToken)) return null;
var existingUser = ctx.GetUserByEmail(email, true);
if (existingUser == null) return null;
existingUser.RefreshToken = refreshToken;
ctx.Users.Update(existingUser);
return existingUser;
return ctx.Users.Where(u => u.EmailAddress == emailLower);
}
}

View File

@ -0,0 +1,15 @@
using AyCode.Database.DbContexts;
using AyCode.Interfaces.Addresses;
using AyCode.Interfaces.Profiles;
using AyCode.Interfaces.ServiceProviders;
using AyCode.Interfaces.Users;
namespace AyCode.Database.DbSets.Users;
public interface IAcUserDbSet<TUser, TProfile, TServiceProvider, TUserToServiceProvider, TProfileAddress> : IAcUserDbSetBase<TUser>
where TUser : class, IAcUser<TProfile, TServiceProvider, TUserToServiceProvider, TProfileAddress>
where TProfile : class, IAcProfile<TProfileAddress>
where TServiceProvider : class, IAcServiceProviderBase
where TUserToServiceProvider : class, IAcUserToServiceProviderBase
where TProfileAddress : class, IAcAddress
{ }

View File

@ -1,11 +1,4 @@
using AyCode.Database.DbSets.Addresses;
using AyCode.Database.DbSets.Companies;
using AyCode.Database.DbSets.Profiles;
using AyCode.Interfaces.Addresses;
using AyCode.Interfaces.Addresses.Dtos;
using AyCode.Interfaces.Profiles;
using AyCode.Interfaces.ServiceProviders;
using AyCode.Interfaces.Users;
using AyCode.Interfaces.Users;
using Microsoft.EntityFrameworkCore;
namespace AyCode.Database.DbSets.Users;
@ -13,25 +6,4 @@ namespace AyCode.Database.DbSets.Users;
public interface IAcUserDbSetBase<TUser> where TUser : class, IAcUserBase
{
DbSet<TUser> Users { get; set; }
}
public interface IAcUserDbSetBase<TUser, TProfile, TAddress> : IAcUserDbSetBase<TUser>, IAcProfileDbSetBase<TProfile, TAddress>
where TUser : class, IAcUserBase
where TProfile : class, IAcProfile<TAddress>
where TAddress : class, IAcAddressDtoBase
{ }
public interface IAcUserDbSetBase<TUser, TProfile, TCompany, TAddress> : IAcUserDbSetBase<TUser, TProfile, TAddress>, IAcCompanyDbSetBase<TCompany>
where TUser : class, IAcUserBase
where TProfile : class, IAcProfile<TAddress>
where TCompany : class, IAcCompanyBase
where TAddress : class, IAcAddressDtoBase
{ }
public interface IAcUserDbSetBase<TUser, TProfile, TCompany, TUserToCompany, TAddress> : IAcUserDbSetBase<TUser, TProfile, TCompany, TAddress>
where TUser : class, IAcUserBase, IAcUser<TProfile, TCompany, TUserToCompany, TAddress>
where TProfile : class, IAcProfile<TAddress>
where TCompany : class, IAcCompanyBase
where TUserToCompany : class, IAcUserToCompanyBase
where TAddress : class, IAcAddressDtoBase
{ }
}

View File

@ -1,9 +0,0 @@
using AyCode.Interfaces.Users;
using Microsoft.EntityFrameworkCore;
namespace AyCode.Database.DbSets.Users;
public interface IAcUserToCompanyDbSetBase<TUserToCompany> where TUserToCompany : class, IAcUserToCompanyBase
{
DbSet<TUserToCompany> UserToCompanies { get; set; }
}

View File

@ -2,8 +2,6 @@
using AyCode.Database.DataLayers;
using AyCode.Database.DbContexts;
using AyCode.Interfaces.Entities;
using AyCode.Utils.Extensions;
using Microsoft.EntityFrameworkCore;
namespace AyCode.Database.Extensions;
@ -17,22 +15,16 @@ public static class AcDalExtension
public static TResultType Session<TDbContext, TResultType>(this IAcDalBase<TDbContext> acDal, Func<TDbContext, TResultType> callback) where TDbContext : AcDbContextBase
{
//using var ctx = acDal.CreateDbContext();
using (acDal.MutextLock.UseWaitOne())
{
return acDal.Context.Session(callback);
}
using var ctx = acDal.CreateDbContext();
return ctx.Session(callback);
}
public static IEnumerable<TEntity> Session<TDbContext, TEntity>(this IAcDalBase<TDbContext> acDal, Func<TDbContext, IQueryable<TEntity>> callback) where TEntity : IEntity where TDbContext : AcDbContextBase
{
//using var ctx = acDal.CreateDbContext();
using (acDal.MutextLock.UseWaitOne())
{
return acDal.Context.Session(callback);
}
using var ctx = acDal.CreateDbContext();
return ctx.Session(callback);
}
public static Task<bool> TransactionAsync<TDbContext>(this IAcDalBase<TDbContext> acDal, Func<TDbContext, bool> callbackTransactionBody, bool throwException = false) where TDbContext : AcDbContextBase
@ -40,35 +32,8 @@ public static class AcDalExtension
public static bool Transaction<TDbContext>(this IAcDalBase<TDbContext> acDal, Func<TDbContext, bool> callbackTransactionBody, bool throwException = false) where TDbContext : AcDbContextBase
{
//using var ctx = acDal.CreateDbContext();
using (acDal.MutextLock.UseWaitOne())
{
return acDal.Context.Transaction(callbackTransactionBody, throwException);
}
}
public static Task<TEntity?> UpdateSafeAsync<TDbContext, TEntity>(this IAcDalBase<TDbContext> acDal, TEntity entity, Func<TDbContext, TEntity, bool>? callbackTransactionBody = null, bool throwException = false) where TDbContext : AcDbContextBase where TEntity : class, IEntityGuid
=> TaskHelper.ToThreadPoolTask(() => acDal.UpdateSafe(entity, callbackTransactionBody, throwException));
public static TEntity? UpdateSafe<TDbContext, TEntity>(this IAcDalBase<TDbContext> acDal, TEntity entity, Func<TDbContext, TEntity, bool>? callbackTransactionBody = null, bool throwException = false) where TDbContext : AcDbContextBase where TEntity : class, IEntityGuid
{
TEntity? updateEntity = null;
var isSuccess = acDal.Context.Transaction(ctx =>
{
updateEntity = ctx.Set<TEntity>().FirstOrDefault(x => x.Id == entity.Id);
if (updateEntity == null) return false;
//ctx.Entry(updateEntity).State = EntityState.Detached;
ctx.Entry(updateEntity).CurrentValues.SetValues(entity);
if (callbackTransactionBody == null)
return ctx.Update(updateEntity).State == EntityState.Modified;
return callbackTransactionBody.Invoke(ctx, updateEntity);
}, throwException);
return isSuccess ? updateEntity : null;
using var ctx = acDal.CreateDbContext();
return ctx.Transaction(callbackTransactionBody, throwException);
}
}

View File

@ -1,18 +0,0 @@
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<TModelDto, TEntity>(this AcDbContextBase ctx, Guid id) where TModelDto : class, IAcModelDtoBase where TEntity : class, IEntity
=> ctx.Set<TEntity>().Find(id)?.ToModelDto<TModelDto, TEntity>();
public static IEnumerable<TModelDto> GetAllModelDto<TModelDto, TEntity>(this AcDbContextBase ctx) where TModelDto : class, IAcModelDtoBase where TEntity : class, IEntity
=> ctx.Set<TEntity>().ToModelDto<TModelDto, TEntity>();
}

View File

@ -1,7 +1,6 @@
using AyCode.Core.Consts;
using AyCode.Core.Helpers;
using AyCode.Core.Loggers;
using AyCode.Core.Server.Loggers;
using AyCode.Core.Logger;
using AyCode.Database.DbContexts;
using AyCode.Interfaces.Entities;
@ -23,7 +22,7 @@ public static class AcDbSessionExtension
catch (Exception ex)
{
var errorText = $"Session({ctx}) callback error...{AcEnv.NL}";
GlobalLogger.Error($"{errorText}", ex);
Logger.Error($"{errorText}", ex);
throw new Exception($"{errorText}{ex}");
}

View File

@ -1,10 +1,10 @@
using AyCode.Core.Helpers;
using Microsoft.EntityFrameworkCore.Storage;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using AyCode.Database.DbContexts;
using AyCode.Core.Logger;
using AyCode.Core.Consts;
using AyCode.Core.Loggers;
using AyCode.Core.Server.Loggers;
namespace AyCode.Database.Extensions;
@ -46,7 +46,7 @@ public static class AcDbTransactionExtension
transaction.Rollback();
if (throwException) throw new Exception(errorText, ex);
GlobalLogger.Error($"{errorText}", ex);
Logger.Error($"{errorText}", ex);
}
return result;
}
@ -66,7 +66,7 @@ public static class AcDbTransactionExtension
else
{
transaction.Rollback();
GlobalLogger.Warning($"Transaction({ctx}) transaction ROLLBACK!");
Logger.Warning($"Transaction({ctx}) transaction ROLLBACK!");
}
}
catch (Exception ex)
@ -74,7 +74,7 @@ public static class AcDbTransactionExtension
if (throwException) throw;
result = false;
GlobalLogger.Error($"Transaction({ctx}) transaction error...{AcEnv.NL}", ex);
Logger.Error($"Transaction({ctx}) transaction error...{AcEnv.NL}", ex);
}
finally
{

View File

@ -1,5 +1,6 @@
using AyCode.Interfaces.Addresses;
using Microsoft.EntityFrameworkCore;
using AyCode.Interfaces.Profiles;
using AyCode.Interfaces.Profiles.Dtos;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
namespace AyCode.Database.ModelBuilders.Profiles;
@ -11,8 +12,6 @@ public static class AcProfileEntityTypeBuilderExtensions
where TAddress : class, IAcAddress
{
//modelBuilder.HasOne(e => e.Address).WithOne().HasForeignKey<TAddressRelation>(e => e.AddressId);
modelBuilder.HasOne(x => x.Address).WithOne().OnDelete(DeleteBehavior.Cascade);
modelBuilder.Navigation(e => e.Address).AutoInclude(autoInclude).IsRequired();
modelBuilder.Navigation(e => e.Address).AutoInclude(autoInclude);
}
}

View File

@ -7,12 +7,16 @@ using Microsoft.EntityFrameworkCore.Metadata.Builders;
namespace AyCode.Database.ModelBuilders.Profiles;
public class AcProfileEntityTypeDefaultConfiguration<TProfile, TProfileAddress> : IAcEntityTypeConfiguration<TProfile>
where TProfile : class, IAcProfile<TProfileAddress>
where TProfileAddress : class, IAcAddress
public abstract class AcProfileEntityTypeConfigurations
{
public virtual void Configure(EntityTypeBuilder<TProfile> modelBuilder)
public abstract class AcProfileEntityTypeDefaultConfiguration<TProfile, TProfileAddress> : IAcEntityTypeConfiguration<TProfile>
where TProfile : class, IAcProfile<TProfileAddress>
where TProfileAddress : class, IAcAddress
{
modelBuilder.BuildEntityToAddressRelation<TProfile, TProfileAddress>();
public virtual void Configure(EntityTypeBuilder<TProfile> modelBuilder)
{
modelBuilder.BuildEntityToAddressRelation<TProfile, TProfileAddress>();
}
}
}
}

View File

@ -15,15 +15,13 @@ public static class AcUserEntityTypeBuilderExtensions
where TProfileRelation : class, IAcProfileRelation<TProfile>
where TProfile : class, IAcProfileDtoBase
{
modelBuilder.HasOne(x => x.Profile).WithOne().OnDelete(DeleteBehavior.Cascade);
modelBuilder.Navigation(e => e.Profile).AutoInclude(autoInclude).IsRequired();
modelBuilder.Navigation(e => e.Profile).AutoInclude(autoInclude);
}
public static void BuildEntityToServiceProviderRelation<TCompanyRelation, TCompany, TUserToServiceProvider, TProfile>(this EntityTypeBuilder<TCompanyRelation> modelBuilder, bool autoInclude = true)
where TCompanyRelation : class, IAcUserBase, IAcCompanyRelation<TCompany, TUserToServiceProvider>
where TCompany : class, IAcCompany<TCompanyRelation, TUserToServiceProvider, TProfile>
where TUserToServiceProvider : class, IAcUserToCompanyBase
where TProfile : class, IAcProfileDtoBase
public static void BuildEntityToServiceProviderRelation<TServiceProviderRelation, TServiceProvider, TUserToServiceProvider>(this EntityTypeBuilder<TServiceProviderRelation> modelBuilder, bool autoInclude = true)
where TServiceProviderRelation : class, IAcUserBase, IAcServiceProviderRelation<TServiceProvider, TUserToServiceProvider>
where TServiceProvider : class, IAcServiceProvider<TServiceProviderRelation, TUserToServiceProvider>
where TUserToServiceProvider : class, IAcUserToServiceProviderBase
{
modelBuilder
.HasMany(e => e.ServiceProviders)

View File

@ -7,38 +7,17 @@ using Microsoft.EntityFrameworkCore.Metadata.Builders;
namespace AyCode.Database.ModelBuilders.Users;
public class AcUserEntityTypeDefaultConfiguration<TUser, TProfile, TCompany, TUserToCompany, TProfileAddress> : IAcEntityTypeConfiguration<TUser>
where TUser : class, IAcUser<TProfile, TCompany, TUserToCompany, TProfileAddress>
public abstract class AcUserEntityTypeDefaultConfiguration<TUser, TProfile, TServiceProvider, TUserToServiceProvider, TProfileAddress> : IAcEntityTypeConfiguration<TUser>
where TUser : class, IAcUser<TProfile, TServiceProvider, TUserToServiceProvider, TProfileAddress>
where TProfile : class, IAcProfile<TProfileAddress>
where TCompany : class, IAcCompany<TUser, TUserToCompany, TProfile>
where TUserToCompany : class, IAcUserToCompanyBase
where TServiceProvider : class, IAcServiceProvider<TUser, TUserToServiceProvider>
where TUserToServiceProvider : class, IAcUserToServiceProviderBase
where TProfileAddress : class, IAcAddress
{
public virtual void Configure(EntityTypeBuilder<TUser> modelBuilder)
{
modelBuilder.BuildEntityToProfileRelation<TUser, TProfile>();
//modelBuilder.BuildEntityToAddressRelation<TProfileAddress, TProfile, TProfileAddress>();
modelBuilder.BuildEntityToServiceProviderRelation<TUser, TCompany, TUserToCompany, TProfile>();
}
}
public class AcCompanyEntityTypeDefaultConfiguration<TCompany, TProfile, TProfileAddress, TUserToCompany, TUser> : IAcEntityTypeConfiguration<TCompany>
where TUser : class, IAcUser<TProfile, TCompany, TUserToCompany, TProfileAddress>
where TProfile : class, IAcProfile<TProfileAddress>
where TCompany : class, IAcCompany<TUser, TUserToCompany, TProfile>
where TUserToCompany : class, IAcUserToCompanyBase
where TProfileAddress : class, IAcAddress
{
public virtual void Configure(EntityTypeBuilder<TCompany> modelBuilder)
{
modelBuilder.BuildEntityToProfileRelation<TCompany, TProfile>();
//modelBuilder
// .HasMany(e => e.Users)
// .WithMany(e => e.ServiceProviders)
// .UsingEntity<TUserToCompany>();
//modelBuilder.Navigation(e => e.Users).AutoInclude();
modelBuilder.Navigation(e => e.UserToServiceProviders).AutoInclude();
modelBuilder.BuildEntityToServiceProviderRelation<TUser, TServiceProvider, TUserToServiceProvider>();
}
}

View File

@ -1,18 +1,13 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
</PropertyGroup>
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<Import Project="..//AyCode.Core.targets" />
<ItemGroup>
<PackageReference Include="MessagePack.Annotations" Version="3.1.4" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\AyCode.Core\AyCode.Core.csproj" />
<ProjectReference Include="..\AyCode.Entities\AyCode.Entities.csproj" />
<ProjectReference Include="..\AyCode.Utils\AyCode.Utils.csproj" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\AyCode.Utils\AyCode.Utils.csproj" />
</ItemGroup>
</Project>

View File

@ -1,23 +0,0 @@
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using AyCode.Core.Enums;
using AyCode.Core.Loggers;
using AyCode.Entities.LogItems;
using MessagePack;
using KeyAttribute = MessagePack.KeyAttribute;
namespace AyCode.Entities.Server.LogItems;
[MessagePackObject]
[Table("LogItem")]
public class AcLogItem : AcLogItemClient, IAcLogItem
{
[Key(55)]
[System.ComponentModel.DataAnnotations.Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
[Key(60)] public int LogHeaderId { get; set; }
public AcLogItem() : base()
{ }
}

View File

@ -1,10 +0,0 @@
using AyCode.Core.Enums;
using AyCode.Core.Loggers;
using AyCode.Interfaces.Entities;
namespace AyCode.Entities.Server.LogItems;
public interface IAcLogItem : IAcLogItemClient, IEntityInt
{
public int LogHeaderId { get; set; }
}

View File

@ -1,120 +0,0 @@
using AyCode.Core.Enums;
using AyCode.Core.Helpers;
using AyCode.Core.Loggers;
using AyCode.Interfaces.Entities;
using AyCode.Utils.Extensions;
using System.Collections.Concurrent;
using AyCode.Core.Consts;
namespace AyCode.Entities;
public abstract class AcLogItemWriterBase<TLogItem> : AcLogWriterBase where TLogItem : class, IAcLogItemClient
{
protected readonly Mutex MutexLock = new();//new(false, "GLOBAL");
protected AcLogItemWriterBase() : this(null)
{ }
protected AcLogItemWriterBase(string? categoryName = null) : base(categoryName)
{ }
protected AcLogItemWriterBase(AppType appType, LogLevel logLevel, string? categoryName = null) : base(appType, logLevel, categoryName)
{
}
protected virtual TLogItem CreateLogItem(DateTime utcNow, AppType appType, int threadId, LogLevel logLevel, string? logText, string? callerMemberName, string? categoryName = null, string? errorType = null, string? exMessage = null)
{
var logItem = Activator.CreateInstance<TLogItem>();
logItem.TimeStampUtc = utcNow;
logItem.AppType = appType;
logItem.LogLevel = logLevel;
logItem.CategoryName = categoryName ?? CategoryName;
logItem.CallerName = callerMemberName;
logItem.Text = logText;
logItem.ThreadId = threadId;
logItem.ErrorType = errorType;
logItem.Exception = exMessage;
return logItem;
}
public override void Write(IAcLogItemClient logItem)
=> WriteLogItemAsync(logItem as TLogItem);
public override void Write(AppType appType, LogLevel logLevel, string? logText, string? callerMemberName, string? categoryName, string? errorType, string? exMessage)
=> WriteAsync(appType, logLevel, logText, callerMemberName, categoryName, errorType, exMessage);
protected virtual void WriteAsync(AppType appType, LogLevel logLevel, string? logText, string? callerMemberName, string? categoryName, string? errorType, string? exMessage)
{
if (logLevel < LogLevel) return;
var utcNow = DateTime.UtcNow;
var threadId = Environment.CurrentManagedThreadId;
TaskHelper.RunOnThreadPool(() => WriteLogItem(CreateLogItem(utcNow, appType, threadId, logLevel, logText, callerMemberName, categoryName, errorType, exMessage)));
}
public void WriteLogItemAsync(TLogItem? logItem)
{
if (logItem == null || logItem.LogLevel < LogLevel) return;
TaskHelper.RunOnThreadPool(() => WriteLogItem(logItem));
}
public void WriteLogItem(TLogItem logItem)
{
try
{
if (logItem.LogLevel < LogLevel) return;
using (MutexLock.UseWaitOne())
{
WriteLogItemCallback(logItem);
}
}
catch (Exception ex)
{
Console.WriteLine($@"ERROR!!! {nameof(AcLogItemWriterBase<TLogItem>)}->WriteLogItem; ex: {ex.Message}{AcEnv.NL}{AcEnv.NL}{ex}");
//Console.WriteLine("ERRORORROROR! " + AcEnv.NL + ex);
//throw;
}
}
protected virtual void WriteLogItemCallback(TLogItem logItem)
{
throw new NotImplementedException();
}
//private volatile bool _isLocked = false;
//private readonly object _forLock = new();
//private readonly List<TLogItem> _logItemsCahce = new();
//private readonly List<TLogItem> _logItemsCahce2 = new();
//protected virtual void WriteLogItem(TLogItem logItem, Action<IEnumerable<TLogItem>>? callback = null)
//{
// lock (_forLock) _logItemsCahce.Add(logItem);
// if (_isLocked) return;
// using (MutexLock.UseWaitOne())
// {
// _isLocked = true;
// _logItemsCahce2.Clear();
// lock (_forLock)
// {
// _logItemsCahce2.AddRange(_logItemsCahce);
// _logItemsCahce.Clear();
// }
// callback?.Invoke(_logItemsCahce2);
// }
// _isLocked = false;
//}
}

View File

@ -1,13 +0,0 @@
using AyCode.Interfaces;
using AyCode.Interfaces.Entities;
namespace AyCode.Entities;
public static class AcModelDtoExtension
{
public static TModelDto? ToModelDto<TModelDto, TEntity>(this TEntity entity) where TModelDto : class, IAcModelDtoBase where TEntity : class, IEntity
=> Activator.CreateInstance(typeof(TModelDto), entity) as TModelDto;
public static IEnumerable<TModelDto> ToModelDto<TModelDto, TEntity>(this IEnumerable<TEntity> entities) where TModelDto : class, IAcModelDtoBase where TEntity : class, IEntity
=> entities.Select(entity => entity.ToModelDto<TModelDto, TEntity>())!;
}

View File

@ -10,32 +10,11 @@ public abstract class AcAddress : IAcAddress
[Key, DatabaseGenerated(DatabaseGeneratedOption.None)]
public Guid Id { get; set; }
public bool IsValid { get; set; }
public bool IsHelper { get; set; }
public double Latitude { get; set; }
public double Longitude { get; set; }
public double? Latitude { get; set; }
public double? Longitude { get; set; }
public string? AddressText { get; set; }
public string AddressText { get; set; }
public DateTime Created { get; set; }
public DateTime Modified { get; set; }
protected AcAddress()
{ }
protected AcAddress(Guid id)
{
Id = id;
}
protected AcAddress(Guid id, string? addressText) : this(id, null, null, addressText)
{ }
protected AcAddress(Guid id, double? latitude, double? longitude, string? addressText) : this(id)
{
Latitude = latitude;
Longitude = longitude;
AddressText = addressText;
}
}

View File

@ -1,20 +1,13 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
</PropertyGroup>
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<Import Project="..//AyCode.Core.targets" />
<ItemGroup>
<ProjectReference Include="..\AyCode.Interfaces\AyCode.Interfaces.csproj" />
</ItemGroup>
<ItemGroup>
<Folder Include="Messages\" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="MessagePack.Annotations" Version="3.1.4" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\AyCode.Interfaces\AyCode.Interfaces.csproj" />
</ItemGroup>
</Project>

View File

@ -1,35 +0,0 @@
using AyCode.Core.Enums;
using AyCode.Core.Loggers;
using MessagePack;
namespace AyCode.Entities.LogItems;
[MessagePackObject]
public class AcLogItemClient : IAcLogItemClient
{
[Key(5)] public DateTime TimeStampUtc { get; set; }
[Key(15)] public AppType AppType { get; set; }
[Key(20)] public LogLevel LogLevel { get; set; }
[Key(25)] public int ThreadId { get; set; } = Environment.CurrentManagedThreadId;
[Key(30)] public string? CategoryName { get; set; }
[Key(35)] public string? CallerName { get; set; }
[Key(40)] public string? Text { get; set; }
[Key(45)] public string? ErrorType { get; set; }
[Key(50)] public string? Exception { get; set; }
public override string? ToString() => Text ?? base.ToString();
//public string ErrorText() => string.IsNullOrWhiteSpace(ErrorType) ? string.Empty : $"{AcEnv.NL}[{ErrorType.ToUpper()}]: {Exception}";
//public string ToMinimalText() => $"{"[" + CategoryName + "->" + CallerName + "]"} - {"[" + ThreadId + "]", 5} {Text}{ErrorText()}";
//public string ToNormalText()
// => $"{"[" + LogLevel + "]",-9} {"[" + CategoryName + "->" + CallerName + "]"} - {"[" + ThreadId + "]", 5} {Text}{ErrorText()}";
//public string ToDetailText()
// => $"[{TimeStampUtc.ToLocalTime():HH:mm:ss.fff}] {"[" + LogLevel + "]",-9} {"[" + CategoryName + "->" + CallerName + "]", -55} {"[" + ThreadId + "]", 5} {Text}{ErrorText()}";
//public string ToDiagnosticText()
// => $"[{TimeStampUtc.ToLocalTime():HH:mm:ss.fff}] [{AppType.ToString()[0]}] {"[" + LogLevel + "]",-9} {"[" + CategoryName + "->" + CallerName + "]", -54} {"[" + ThreadId + "]", 5} {Text}{ErrorText()}";
}

View File

@ -1,45 +0,0 @@
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Net.Mail;
using AyCode.Core.Enums;
using AyCode.Interfaces.Messages;
namespace AyCode.Entities.Messages;
[Table("EmailMessage")]
public abstract class AcEmailMessage<TEmailRecipient> : IAcEmailMessage<TEmailRecipient> where TEmailRecipient : IAcEmailRecipientBase
{
protected AcEmailMessage()
{
}
protected AcEmailMessage(Guid id, Guid? senderId, Guid contextId, string subject, string? text, string emailAddress) : this()
{
Id = id;
SenderId = senderId;
ContextId = contextId;
Subject = subject;
Text = text;
EmailAddress = emailAddress;
}
[Key, DatabaseGenerated(DatabaseGeneratedOption.None)]
public Guid Id { get; set; }
public Guid ContextId { get; set; }
public Guid? SenderId { get; set; }
public MessageContextType ContextType { get; set; }
public virtual List<TEmailRecipient> Recipients { get; set; } = [];
[MaxLength(150)]
public string EmailAddress { get; set; }
[MaxLength(100)]
public string Subject { get; set; }
public string? Text { get; set; }
public bool IsReaded { get; set; }
public DateTime Created { get; set; }
public DateTime Modified { get; set; }
}

View File

@ -1,35 +0,0 @@
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Net.Mail;
using AyCode.Interfaces.Messages;
namespace AyCode.Entities.Messages;
[Table("EmailRecipient")]
public abstract class AcEmailRecipient<TEmailMessage> : IAcEmailRecipient<TEmailMessage> where TEmailMessage : IAcEmailMessageBase
{
protected AcEmailRecipient()
{
}
protected AcEmailRecipient(Guid id, Guid recipientId, Guid emailMessageId, string emailAddress) : this()
{
Id = id;
RecipientId = recipientId;
EmailMessageId = emailMessageId;
EmailAddress = emailAddress;
}
[Key, DatabaseGenerated(DatabaseGeneratedOption.None)]
public Guid Id { get; set; }
public Guid RecipientId { get; set; }
public Guid EmailMessageId { get; set; }
public string EmailAddress { get; set; }
public bool IsReaded { get; set; }
public virtual TEmailMessage EmailMessage { get; set; }
public DateTime Created { get; set; }
public DateTime Modified { get; set; }
}

View File

@ -0,0 +1,37 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations.Schema;
using System.ComponentModel.DataAnnotations;
using AyCode.Interfaces.Messages;
namespace AyCode.Entities.Messages
{
[Table("Notices")]
public class NoticeBase : INoticeBase
{
public NoticeBase() { }
public NoticeBase(Guid senderId, Guid receiverId, string message) : this(Guid.NewGuid(), senderId, receiverId, message) { }
public NoticeBase(Guid id, Guid senderId, Guid receiverId, string message) : this()
{
Id = id;
SenderId = senderId;
ReceiverId = receiverId;
Message = message;
}
[Key, DatabaseGenerated(DatabaseGeneratedOption.None)]
public Guid Id { get; set; }
public Guid SenderId { get; set; }
public Guid ReceiverId { get; set; }
public string Message { get; set; }
public DateTime Created { get; set; }
public DateTime Modified { get; set; }
}
}

View File

@ -1,17 +1,25 @@
using AyCode.Interfaces.Profiles;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using AyCode.Core.Extensions;
using AyCode.Entities.Addresses;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using AyCode.Interfaces.Addresses;
using AyCode.Utils.Extensions;
using static System.Runtime.InteropServices.JavaScript.JSType;
namespace AyCode.Entities.Profiles
{
[Table("Profile")]
public abstract class AcProfile<TAddress> : IAcProfile<TAddress> where TAddress : class, IAcAddress
{
protected AcProfile() { }
protected AcProfile(Guid id) : this()
{
Id = id;
}
[Key, DatabaseGenerated(DatabaseGeneratedOption.None)]
public Guid Id { get; set; }
public Guid? UserMediaId { get; set; }
@ -23,52 +31,11 @@ namespace AyCode.Entities.Profiles
[Required]
public string Name { get; set; }
public string? FullName => GetFullName("ENG");
public string? FirstName { get; set; }
public string? LastName { get; set; }
//public string NickName { get; set; }
public string? EmailAddress { get; set; }
public string? Description { get; set; }
public string? ThumbnailUrl { get ; set; }
public DateTime Created { get; set; }
public DateTime Modified { get; set; }
protected AcProfile() { }
protected AcProfile(Guid id) : this()
{
Id = id;
}
protected AcProfile(Guid id, string name) : this(id)
{
Name = name;
}
public void SetAddress(TAddress address)
{
if (address.Id.IsNullOrEmpty()) address.Id = Guid.NewGuid();
Address = address;
AddressId = address.Id;
}
public string? GetFullName(string lang = "ENG") => GetFullName(FirstName, LastName, lang);
public static string? GetFullName(string? firstName, string? lastName, string? lang = "ENG")
{
if (firstName.IsNullOrWhiteSpace()) return lastName;
if(lastName.IsNullOrWhiteSpace()) return firstName;
if (lang == "ENG") return firstName + " " + lastName;
return lastName + " " + firstName;
}
}
}

View File

@ -1,96 +0,0 @@

using System.ComponentModel.DataAnnotations.Schema;
using System.ComponentModel.DataAnnotations;
using System.Reflection.Metadata.Ecma335;
using AyCode.Core.Extensions;
using AyCode.Interfaces.Addresses;
using AyCode.Interfaces.Profiles;
using AyCode.Interfaces.Profiles.Dtos;
using AyCode.Interfaces.ServiceProviders;
using AyCode.Interfaces.Users;
using AyCode.Utils.Extensions;
namespace AyCode.Entities.ServiceProviders
{
[Table("ServiceProviders")]
public abstract class AcCompany<TUser, TUserToCompany, TProfile, TAddress> : IAcCompany<TUser, TUserToCompany, TProfile, TAddress>
where TUser : class, IAcUserBase
where TUserToCompany : class, IAcUserToCompanyBase
where TProfile : class, IAcProfile<TAddress>
where TAddress : class, IAcAddress
{
[Key, DatabaseGenerated(DatabaseGeneratedOption.None)]
public Guid Id { get; set; }
//[Required]
public Guid? OwnerId { get; set; }
[Required]
public Guid ProfileId { get; set; }
public virtual TProfile Profile { get; set; }
[Required]
public string Name { get; set; }
public double CommissionPercent { get; set; }
[Required]
public Guid AffiliateId { get; set; }
public Guid? ReferralId { get; set; }
public virtual List<TUser> Users { get; set; } = [];
public virtual List<TUserToCompany> UserToServiceProviders { get; set; } = [];
public DateTime Created { get; set; }
public DateTime Modified { get; set; }
protected AcCompany()
{
}
protected AcCompany(string name, Guid? ownerId) : this(Guid.NewGuid(), name, ownerId)
{
}
protected AcCompany(Guid id, string name, Guid? ownerId) : this(id, name, ownerId, Guid.NewGuid())
{
}
protected AcCompany(Guid id, string name, Guid? ownerId, Guid affiliateId, double commissionPercent = 0) : this()
{
Id = id;
Name = name;
OwnerId = ownerId == Guid.Empty ? null : ownerId;
AffiliateId = affiliateId;
CommissionPercent = commissionPercent;
}
public void SetProfile(TProfile profile)
{
if (profile.Id.IsNullOrEmpty()) profile.Id = Guid.NewGuid();
Profile = profile;
ProfileId = profile.Id;
}
public bool HasUser(Guid userId)
=> UserToServiceProviders.Any(x => x.UserId == userId);
public void AddUser(Guid userId, int permissions)
{
if (UserToServiceProviders.Any(x => x.UserId == userId))
return;
var userToCompany = Activator.CreateInstance<TUserToCompany>();
userToCompany.Id = Guid.NewGuid();
userToCompany.UserId = userId;
userToCompany.ServiceProviderId = Id;
userToCompany.Permissions = permissions;
UserToServiceProviders.Add(userToCompany);
}
}
}

View File

@ -0,0 +1,58 @@

using System.ComponentModel.DataAnnotations.Schema;
using System.ComponentModel.DataAnnotations;
using AyCode.Interfaces.ServiceProviders;
using AyCode.Interfaces.Users;
namespace AyCode.Entities.ServiceProviders
{
[Table("ServiceProviders")]
public abstract class AcServiceProvider<TUser, TUserToServiceProvider> : IAcServiceProvider<TUser, TUserToServiceProvider>
where TUser : class, IAcUserBase
where TUserToServiceProvider : class, IAcUserToServiceProviderBase
{
[Key, DatabaseGenerated(DatabaseGeneratedOption.None)]
public Guid Id { get; set; }
[Required]
public Guid OwnerId { get; set; }
[Required]
public string Name { get; set; }
public double? CommissionPercent { get; set; }
[Required]
public Guid AffiliateId { get; set; }
public Guid? ReferralId { get; set; }
public virtual List<TUser> Users { get; set; }
public virtual List<TUserToServiceProvider> UserToServiceProviders { get; set; }
public DateTime Created { get; set; }
public DateTime Modified { get; set; }
protected AcServiceProvider()
{
}
protected AcServiceProvider(string name, Guid ownerId) : this(Guid.NewGuid(), name, ownerId)
{
}
protected AcServiceProvider(Guid id, string name, Guid ownerId) : this(id, name, ownerId, Guid.NewGuid())
{
}
protected AcServiceProvider(Guid id, string name, Guid ownerId, Guid affiliateId, double? commissionPercent = null) : this()
{
Id = id;
Name = name;
OwnerId = ownerId;
AffiliateId = affiliateId;
CommissionPercent = commissionPercent;
}
}
}

View File

@ -1,8 +1,13 @@
using System.ComponentModel.DataAnnotations.Schema;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations.Schema;
using System.ComponentModel.DataAnnotations;
using System.Text.Json.Serialization;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using AyCode.Interfaces.Profiles;
using AyCode.Interfaces.Users;
using AyCode.Entities.ServiceProviders;
using AyCode.Interfaces.Addresses;
using AyCode.Interfaces.ServiceProviders;
@ -12,24 +17,19 @@ using AyCode.Interfaces.ServiceProviders;
namespace AyCode.Entities.Users
{
[Table("Users")]
public abstract class AcUser<TProfile, TCompany, TUserToServiceProvider, TProfileAddress>() : IAcUser<TProfile, TCompany, TUserToServiceProvider, TProfileAddress>
public abstract class AcUser<TProfile, TServiceProvider, TUserToServiceProvider, TProfileAddress>() : IAcUser<TProfile, TServiceProvider, TUserToServiceProvider, TProfileAddress>
where TProfile : class, IAcProfile<TProfileAddress>
where TCompany : class, IAcCompanyBase
where TUserToServiceProvider : class, IAcUserToCompanyBase
where TServiceProvider : class, IAcServiceProviderBase
where TUserToServiceProvider : class, IAcUserToServiceProviderBase
where TProfileAddress : class, IAcAddress
{
[Key, DatabaseGenerated(DatabaseGeneratedOption.None)]
public Guid Id { get; set; }
[NotMapped]
[JsonIgnore]
[Newtonsoft.Json.JsonIgnore]
public string? FullName => Profile.FullName;
[Required, Column("Email")]
public string EmailAddress { get; set; }
//public string NormalizedEmail { get; set; }
public string? PhoneNumber { get; set; }
public string PhoneNumber { get; set; }
public string Password { get; set; }
public string? RefreshToken { get; set; }
@ -45,7 +45,7 @@ namespace AyCode.Entities.Users
public virtual TProfile Profile { get; set; }
//[NotMapped]
public virtual List<TCompany> ServiceProviders { get; set; }
public virtual List<TServiceProvider> ServiceProviders { get; set; }
public virtual List<TUserToServiceProvider> UserToServiceProviders { get; set; }
public DateTime Created { get; set; }

View File

@ -6,9 +6,9 @@ using AyCode.Interfaces.Users;
namespace AyCode.Entities.Users;
[Table("UserToServiceProvider")]
public abstract class AcUserToCompany<TUser, TCompany> : IAcUserToCompany<TUser, TCompany>
public abstract class AcUserToServiceProvider<TUser, TServiceProvider> : IAcUserToAcServiceProvider<TUser, TServiceProvider>
where TUser : class, IAcUserBase
where TCompany : class, IAcCompanyBase
where TServiceProvider : class, IAcServiceProviderBase
{
[Key, DatabaseGenerated(DatabaseGeneratedOption.None)]
public Guid Id { get; set; }
@ -16,11 +16,8 @@ public abstract class AcUserToCompany<TUser, TCompany> : IAcUserToCompany<TUser,
public Guid UserId { get; set; }
public Guid ServiceProviderId { get; set; }
public int Permissions { get; set; }
public virtual TUser User { get; set; }
[ForeignKey("ServiceProviderId")] //COMPANY_RENAME - J.
public virtual TCompany Company { get; set; }
public virtual TServiceProvider ServiceProvider { get; set; }
public DateTime Created { get; set; }
public DateTime Modified { get; set; }

View File

@ -1,16 +1,9 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
</PropertyGroup>
<Import Project="..//AyCode.Core.targets" />
<ItemGroup>
<ProjectReference Include="..\AyCode.Core.Server\AyCode.Core.Server.csproj" />
<ProjectReference Include="..\AyCode.Core\AyCode.Core.csproj" />
<ProjectReference Include="..\AyCode.Entities.Server\AyCode.Entities.Server.csproj" />
<ProjectReference Include="..\AyCode.Entities\AyCode.Entities.csproj" />
<ProjectReference Include="..\AyCode.Interfaces\AyCode.Interfaces.csproj" />
</ItemGroup>
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
</Project>

View File

@ -1,25 +0,0 @@
using AyCode.Core.Consts;
using AyCode.Interfaces.Addresses;
using AyCode.Interfaces.Profiles;
using AyCode.Interfaces.ServiceProviders;
using AyCode.Interfaces.Users;
namespace AyCode.Interfaces.Server.Logins;
public interface IAcLoggedInModelBase<TUser, TUserToken, TProfile, TCompany, TUserToServiceProvider, TProfileAddress> : IAcLoginDtoBase
where TUser : class, IAcUser<TProfile, TCompany, TUserToServiceProvider, TProfileAddress>
where TUserToken : class, IAcUserTokenBase
where TProfile : class, IAcProfile<TProfileAddress>
where TCompany : class, IAcCompanyBase
where TUserToServiceProvider : class, IAcUserToCompanyBase
where TProfileAddress : class, IAcAddress
{
bool IsLoggedIn { get; }
TUser LoggedInUser { get; }
string AccessToken { get; }
AcErrorCode LoginErrorCode { get; set; }
void AddLoggedInUser(TUser user, string accessToken);
void Logout();
}

View File

@ -1,6 +0,0 @@
namespace AyCode.Interfaces.Server.Logins;
public interface IAcLoginDtoBase
{
}

View File

@ -1,27 +0,0 @@
using System.Net;
using AyCode.Core.Consts;
using AyCode.Interfaces.Addresses;
using AyCode.Interfaces.Logins;
using AyCode.Interfaces.Profiles;
using AyCode.Interfaces.ServiceProviders;
using AyCode.Interfaces.Users;
namespace AyCode.Interfaces.Server.Logins;
public interface IAcLoginServiceServer<TResultLoggedInModel, TUser, TUserToken, TProfile, TCompany, TUserToServiceProvider, TProfileAddress> : IAcLoginServiceCommon<TUser, TProfile, TCompany, TUserToServiceProvider, TProfileAddress>
where TResultLoggedInModel: class, IAcLoggedInModelBase<TUser, TUserToken, TProfile, TCompany, TUserToServiceProvider, TProfileAddress>
where TUser : class, IAcUser<TProfile, TCompany, TUserToServiceProvider, TProfileAddress>
where TUserToken : class, IAcUserTokenBase
where TProfile : class, IAcProfile<TProfileAddress>
where TCompany : class, IAcCompanyBase
where TUserToServiceProvider : class, IAcUserToCompanyBase
where TProfileAddress : class, IAcAddress
{
public TResultLoggedInModel? LoggedInModel { get; }
public TResultLoggedInModel Login(string? email, string password);
public Task<TResultLoggedInModel> LoginAsync(string? email, string password);
public AcErrorCode UpdatePassword(TUser user, string password);
}

View File

@ -5,10 +5,7 @@ namespace AyCode.Interfaces.Addresses.Dtos;
public interface IAcAddressDtoBase : IEntityGuid
{
public bool IsValid { get; set; }
public bool IsHelper { get; set; }
public double? Latitude { get; set; }
public double? Longitude { get; set; }
public string? AddressText { get; set; }
public double Latitude { get; set; }
public double Longitude { get; set; }
public string AddressText { get; set; }
}

View File

@ -1,8 +1,6 @@
using AyCode.Interfaces.Entities;
namespace AyCode.Interfaces.Addresses;
namespace AyCode.Interfaces.Addresses;
public interface IAcAddressForeignKey : IEntityGuid
public interface IAcAddressForeignKey
{
public Guid AddressId { get; set; }
}

View File

@ -1,11 +1,10 @@
using AyCode.Interfaces.Addresses.Dtos;
using AyCode.Interfaces.Profiles;
using AyCode.Interfaces.Profiles;
using System.Formats.Tar;
using System.Net;
namespace AyCode.Interfaces.Addresses;
public interface IAcAddressRelation<TAddress> : IAcAddressForeignKey where TAddress : IAcAddressDtoBase
public interface IAcAddressRelation<TAddress> : IAcAddressForeignKey where TAddress : class, IAcAddress
{
public TAddress Address { get; set; }
}

View File

@ -1,17 +1,18 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
</PropertyGroup>
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<Import Project="..//AyCode.Core.targets" />
<ItemGroup>
<Folder Include="Addresses\Dtos\" />
<Folder Include="Sessions\" />
</ItemGroup>
<ItemGroup>
<Folder Include="Addresses\Dtos\" />
<Folder Include="Sessions\" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\AyCode.Core\AyCode.Core.csproj" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\AyCode.Core\AyCode.Core.csproj" />
</ItemGroup>
</Project>

View File

@ -1,9 +0,0 @@
namespace AyCode.Interfaces.Entities;
public interface IAcSoftRemoveEntity : IEntity
{
/// <summary>
/// Gets or sets a value indicating whether the entity has been deleted
/// </summary>
bool Deleted { get; set; }
}

View File

@ -1,4 +0,0 @@
namespace AyCode.Interfaces.Entities;
public interface IAcSoftRemoveEntityGuid : IAcSoftRemoveEntity, IEntityGuid
{}

View File

@ -1,4 +0,0 @@
namespace AyCode.Interfaces.Entities;
public interface IAcSoftRemoveEntityInt : IAcSoftRemoveEntity, IEntityInt
{}

View File

@ -9,9 +9,9 @@ namespace AyCode.Interfaces.Entities
{
}
public interface IEntity<TPKey> : IEntity, IId<TPKey>
public interface IEntity<TPKey> : IEntity
{
//[Key] TPKey Id { get; set; }
[Key] TPKey Id { get; set; }
//T SetId(T id);
}
}

View File

@ -1,16 +0,0 @@
using AyCode.Interfaces.Entities;
namespace AyCode.Interfaces;
public interface IAcModelDtoBaseEmpty
{
}
public interface IAcModelDtoBase : IEntityGuid, IAcModelDtoBaseEmpty
{
}
public interface IAcModelDtoBase<out TMainEntity> : IAcModelDtoBase where TMainEntity : IEntityGuid
{
TMainEntity CreateMainEntity();
}

View File

@ -1,16 +0,0 @@
using AyCode.Interfaces.Addresses;
using AyCode.Interfaces.Profiles;
using AyCode.Interfaces.ServiceProviders;
using AyCode.Interfaces.Users;
namespace AyCode.Interfaces.Logins;
public interface IAcLoginServiceBase<TUser, TProfile, TCompany, TUserToServiceProvider, TProfileAddress> where TUser : class, IAcUser<TProfile, TCompany, TUserToServiceProvider, TProfileAddress>
where TProfile : class, IAcProfile<TProfileAddress>
where TCompany : class, IAcCompanyBase
where TUserToServiceProvider : class, IAcUserToCompanyBase
where TProfileAddress : class, IAcAddress
{
public bool IsLoggedIn { get; }
public TUser? LoggedInUser { get; }
}

View File

@ -1,15 +0,0 @@
using AyCode.Interfaces.Addresses;
using AyCode.Interfaces.Profiles;
using AyCode.Interfaces.ServiceProviders;
using AyCode.Interfaces.Users;
namespace AyCode.Interfaces.Logins;
public interface IAcLoginServiceClient<TUser, TProfile, TCompany, TUserToServiceProvider, TProfileAddress> : IAcLoginServiceCommon<TUser, TProfile, TCompany, TUserToServiceProvider, TProfileAddress>
where TUser : class, IAcUser<TProfile, TCompany, TUserToServiceProvider, TProfileAddress>
where TProfile : class, IAcProfile<TProfileAddress>
where TCompany : class, IAcCompanyBase
where TUserToServiceProvider : class, IAcUserToCompanyBase
where TProfileAddress : class, IAcAddress
{
}

View File

@ -1,29 +0,0 @@
using AyCode.Core.Consts;
using AyCode.Interfaces.Addresses;
using AyCode.Interfaces.Profiles;
using AyCode.Interfaces.ServiceProviders;
using AyCode.Interfaces.Users;
namespace AyCode.Interfaces.Logins;
public interface IAcLoginServiceCommon<TUser, TProfile, TCompany, TUserToServiceProvider, TProfileAddress> : IAcLoginServiceBase<TUser, TProfile, TCompany, TUserToServiceProvider, TProfileAddress>
where TUser : class, IAcUser<TProfile, TCompany, TUserToServiceProvider, TProfileAddress>
where TProfile : class, IAcProfile<TProfileAddress>
where TCompany : class, IAcCompanyBase
where TUserToServiceProvider : class, IAcUserToCompanyBase
where TProfileAddress : class, IAcAddress
{
public bool Logout();
public Task<bool> LogoutAsync();
public AcErrorCode Registration(string email, string password, string? phoneNumber = null, Guid? referralId = null);
public AcErrorCode Registration(Guid userId, string email, string password, string? phoneNumber = null, Guid? referralId = null);
public Task<AcErrorCode> RegistrationAsync(string email, string password, string? phoneNumber = null, Guid? referralId = null);
public Task<AcErrorCode> RegistrationAsync(Guid userId, string email, string password, string? phoneNumber = null, Guid? referralId = null);
public AcErrorCode ChangePassword(Guid userId, string oldPassword, string newPassword);
public Task<AcErrorCode> ChangePasswordAsync(Guid userId, string oldPassword, string newPassword);
public AcErrorCode ForgotPassword(string email, string newPassword);
public Task<AcErrorCode> ForgotPasswordAsync(string email, string newPassword);
}

View File

@ -1,7 +0,0 @@
namespace AyCode.Interfaces.Messages;
public interface IAcEmailMessage<TEmailRecipient> : IAcEmailMessageBase, IAcEmailRecipientsRelation<TEmailRecipient>
where TEmailRecipient : IAcEmailRecipientBase
{
}

View File

@ -1,19 +0,0 @@
using AyCode.Core.Enums;
using AyCode.Interfaces.Entities;
using AyCode.Interfaces.TimeStampInfo;
using AyCode.Interfaces.Users;
namespace AyCode.Interfaces.Messages;
public interface IAcEmailMessageBase : IEntityGuid, ITimeStampInfo, IAcEmailAddress
{
public Guid ContextId { get; set; }
public Guid? SenderId { get; set; }
public MessageContextType ContextType { get; set; }
public string Subject { get; set; }
public string? Text { get; set; }
public bool IsReaded { get; set; }
}

View File

@ -1,9 +0,0 @@
namespace AyCode.Interfaces.Messages;
public interface IAcEmailMessageForeignKey<T>
{
public T EmailMessageId { get; set; }
}
public interface IAcEmailMessageForeignKey : IAcEmailMessageForeignKey<Guid>
{ }

View File

@ -1,6 +0,0 @@
namespace AyCode.Interfaces.Messages;
public interface IAcEmailMessageRelation<TEmailMessage> where TEmailMessage : IAcEmailMessageBase
{
TEmailMessage EmailMessage { get; }
}

View File

@ -1,9 +0,0 @@
using System.Net.Mail;
namespace AyCode.Interfaces.Messages;
public interface IAcEmailRecipient<TEmailMessage> : IAcEmailRecipientBase, IAcEmailMessageRelation<TEmailMessage>
where TEmailMessage : IAcEmailMessageBase
{
}

View File

@ -1,12 +0,0 @@
using AyCode.Interfaces.Entities;
using AyCode.Interfaces.TimeStampInfo;
using AyCode.Interfaces.Users;
namespace AyCode.Interfaces.Messages;
public interface IAcEmailRecipientBase : IEntityGuid, ITimeStampInfo, IAcEmailAddress
{
public Guid RecipientId { get; set; }
public Guid EmailMessageId { get; set; }
public bool IsReaded { get; set; }
}

View File

@ -1,6 +0,0 @@
namespace AyCode.Interfaces.Messages;
public interface IAcEmailRecipientsRelation<TEmailRecipient> where TEmailRecipient : IAcEmailRecipientBase
{
public List<TEmailRecipient> Recipients { get; set; }
}

View File

@ -1,8 +0,0 @@
namespace AyCode.Interfaces.Messages;
public interface IAcMessageSenderService<TEmailMessage, TEmailRecipient>
where TEmailMessage : IAcEmailMessage<TEmailRecipient>
where TEmailRecipient : IAcEmailRecipientBase
{
public Task<string> SendMessageAsync(TEmailMessage message, int messageType);
}

View File

@ -0,0 +1,8 @@

namespace AyCode.Interfaces.Messages
{
public interface IMessageParticipants : IMessageSender, IMessageReceiver
{
}
}

View File

@ -0,0 +1,9 @@
using AyCode.Interfaces.Entities;
namespace AyCode.Interfaces.Messages
{
public interface IMessageReceiver : IEntityGuid
{
}
}

View File

@ -0,0 +1,10 @@

using AyCode.Interfaces.Entities;
namespace AyCode.Interfaces.Messages
{
public interface IMessageSender : IEntityGuid
{
}
}

View File

@ -0,0 +1,9 @@
using AyCode.Interfaces.Enums;
namespace AyCode.Interfaces.Messages
{
public interface IMessageSenderService
{
public Task<string> SendMessageAsync<TNotice>(TNotice message, int messageType) where TNotice : class, INoticeBase;
}
}

View File

@ -0,0 +1,12 @@

using AyCode.Interfaces.Entities;
using AyCode.Interfaces.Enums;
using AyCode.Interfaces.TimeStampInfo;
namespace AyCode.Interfaces.Messages
{
public interface INoticeBase : IEntityGuid, ITimeStampInfo, IMessageParticipants
{
string Message { get; }
}
}

View File

@ -1,8 +0,0 @@
namespace AyCode.Interfaces.Profiles.Dtos;
public interface IAcFullName
{
string? FullName { get; }
string? FirstName { get; set; }
string? LastName { get; set; }
}

View File

@ -1,20 +1,11 @@
using AyCode.Interfaces.Addresses;
using AyCode.Interfaces.Entities;
using AyCode.Interfaces.MediaInfo;
using AyCode.Interfaces.Users;
using System.ComponentModel.DataAnnotations;
using AyCode.Interfaces.Addresses.Dtos;
namespace AyCode.Interfaces.Profiles.Dtos;
public interface IAcProfileDtoBase<TAddress> : IAcProfileDtoBase, IAcAddressRelation<TAddress> where TAddress : IAcAddressDtoBase
public interface IAcProfileDtoBase : IEntityGuid, IMediaInfo, IAcAddressForeignKey
{
}
public interface IAcProfileDtoBase : IEntityGuid, IAcProfileName, IMediaInfo, IAcAddressForeignKey//, IAcEmailAddress
{
[MaxLength(150)]
string? EmailAddress { get; set; }
string Name { get; set; }
string? Description { get; set; }
}

View File

@ -1,7 +0,0 @@
namespace AyCode.Interfaces.Profiles.Dtos;
public interface IAcProfileName : IAcFullName
{
string Name { get; set; }
//string NickName { get; set; }
}

View File

@ -1,12 +1,12 @@
using AyCode.Interfaces.Addresses;
using AyCode.Interfaces;
using AyCode.Interfaces.Addresses;
using AyCode.Interfaces.TimeStampInfo;
using AyCode.Interfaces.MediaInfo;
using AyCode.Interfaces.Entities;
using AyCode.Interfaces.Profiles.Dtos;
using AyCode.Interfaces.Addresses.Dtos;
namespace AyCode.Interfaces.Profiles;
public interface IAcProfile<TAddress> : IAcProfileDtoBase<TAddress>, ITimeStampInfo where TAddress : IAcAddressDtoBase
public interface IAcProfile<TAddress> : IAcProfileDtoBase, ITimeStampInfo, IAcAddressRelation<TAddress> where TAddress : class, IAcAddress
{
public string? GetFullName(string lang = "ENG");
public void SetAddress(TAddress address);
}

View File

@ -1,8 +1,11 @@
using AyCode.Interfaces.Profiles.Dtos;
using AyCode.Interfaces.TimeStampInfo;
using AyCode.Interfaces.Users.Dtos;
using AyCode.Interfaces.Users;
using AyCode.Interfaces.Profiles.Dtos;
namespace AyCode.Interfaces.Profiles;
public interface IAcProfileRelation<TProfile> : IAcProfileForeignKey where TProfile : IAcProfileDtoBase
public interface IAcProfileRelation<TProfile> : IAcProfileForeignKey where TProfile : class, IAcProfileDtoBase
{
public TProfile Profile { get; set; }
}

View File

@ -1,31 +0,0 @@
using AyCode.Interfaces.Addresses;
using AyCode.Interfaces.Profiles.Dtos;
using AyCode.Interfaces.Profiles;
using AyCode.Interfaces.Users;
namespace AyCode.Interfaces.ServiceProviders;
public interface IAcCompany<TProfile> : IAcCompanyBase, IAcProfileRelation<TProfile>
where TProfile : IAcProfileDtoBase
{
public void SetProfile(TProfile profile);
}
public interface IAcCompany<TProfile, TAddress> : IAcCompany<TProfile>
where TProfile : IAcProfile<TAddress>
where TAddress : class, IAcAddress
{}
public interface IAcCompany<TUser, TUserToCompany, TProfile> : IAcCompany<TProfile>, IAcUsersRelation<TUser, TUserToCompany>
where TUser : IAcUserBase
where TUserToCompany : IAcUserToCompanyBase
where TProfile : IAcProfileDtoBase
{}
public interface IAcCompany<TUser, TUserToCompany, TProfile, TAddress> : IAcCompany<TUser, TUserToCompany, TProfile>, IAcCompany<TProfile, TAddress>
where TUser : IAcUserBase
where TUserToCompany : IAcUserToCompanyBase
where TProfile : IAcProfile<TAddress>
where TAddress : class, IAcAddress
{}

View File

@ -1,21 +0,0 @@

using AyCode.Interfaces.Entities;
using AyCode.Interfaces.Profiles;
using AyCode.Interfaces.TimeStampInfo;
namespace AyCode.Interfaces.ServiceProviders;
public interface IAcCompanyBase : IEntityGuid, IAcProfileForeignKey, ITimeStampInfo//, IOwnerId
{
Guid? OwnerId { get; set; }
string Name { get; set; }
double CommissionPercent { get; set; }
Guid AffiliateId { get; set; }
Guid? ReferralId { get; set; }
public bool HasUser(Guid userId);
public void AddUser(Guid userId, int permissions);
}

View File

@ -1,11 +0,0 @@
using AyCode.Interfaces.Users;
namespace AyCode.Interfaces.ServiceProviders;
public interface IAcCompanyRelation<TCompany, TUserToServiceProvider>
where TCompany : IAcCompanyBase
where TUserToServiceProvider : IAcUserToCompanyBase
{
public List<TCompany> ServiceProviders { get; set; }
public List<TUserToServiceProvider> UserToServiceProviders { get; set; }
}

View File

@ -0,0 +1,8 @@
using AyCode.Interfaces.Users;
namespace AyCode.Interfaces.ServiceProviders;
public interface IAcServiceProvider<TUser, TUserToServiceProvider> : IAcServiceProviderBase, IAcUsersRelation<TUser, TUserToServiceProvider>
where TUser : class, IAcUserBase
where TUserToServiceProvider : class, IAcUserToServiceProviderBase
{}

View File

@ -0,0 +1,18 @@

using AyCode.Interfaces.Entities;
using AyCode.Interfaces.Profiles;
using AyCode.Interfaces.TimeStampInfo;
using System;
using System.Dynamic;
namespace AyCode.Interfaces.ServiceProviders;
public interface IAcServiceProviderBase : IEntityGuid, ITimeStampInfo, IOwnerId
{
string Name { get; set; }
double? CommissionPercent { get; set; }
Guid AffiliateId { get; set; }
Guid? ReferralId { get; set; }
}

View File

@ -0,0 +1,11 @@
using AyCode.Interfaces.Users;
namespace AyCode.Interfaces.ServiceProviders;
public interface IAcServiceProviderRelation<TServiceProvider, TUserToServiceProvider>
where TServiceProvider : class, IAcServiceProviderBase
where TUserToServiceProvider : class, IAcUserToServiceProviderBase
{
public List<TServiceProvider> ServiceProviders { get; set; }
public List<TUserToServiceProvider> UserToServiceProviders { get; set; }
}

View File

@ -1,6 +1,6 @@
namespace AyCode.Interfaces.ServiceProviders;
public interface IAcCompanyForeignKey
public interface IAcServiceProviderForeignKey
{
public Guid ServiceProviderId { get; set; }
}

View File

@ -1,34 +1,16 @@
using System.Diagnostics.Contracts;
using AyCode.Interfaces.Entities;
using AyCode.Interfaces.Profiles;
using AyCode.Interfaces.ServiceProviders;
using AyCode.Interfaces.Addresses;
using AyCode.Interfaces.Profiles.Dtos;
using AyCode.Interfaces.Addresses.Dtos;
using AyCode.Interfaces.ServiceProviders;
using System.Net;
using AyCode.Interfaces.Addresses;
namespace AyCode.Interfaces.Users.Dtos;
public interface IAcUserDtoBase : IAcUserDtoMinBase
{}
public interface IAcUserDtoBase<TProfile> : IAcUserDtoMinBase<TProfile>, IAcUserDtoBase
where TProfile : IAcProfileDtoBase
{ }
//public interface IAcUserDtoBase<TProfile, TAddress> : IAcUserDtoBase<TProfile>
// where TProfile : IAcProfileDtoBase<TAddress>
// where TAddress : IAcAddressDtoBase
//{ }
public interface IAcUserDtoBase<TProfile, TCompany, TUserToCompany> : IAcUserDtoBase<TProfile>, IAcCompanyRelation<TCompany, TUserToCompany>
where TProfile : IAcProfileDtoBase
where TCompany : IAcCompanyBase
where TUserToCompany : IAcUserToCompanyBase
{ }
//public interface IAcUserDtoBase<TProfile, TCompany, TUserToCompany, TAddress> : IAcUserDtoBase<TProfile, TCompany, TUserToCompany>, IAcUserDtoBase<TProfile, TAddress>
// where TProfile : IAcProfileDtoBase<TAddress>
// where TCompany : IAcCompanyBase
// where TUserToCompany : IAcUserToCompanyBase
// where TAddress : IAcAddressDtoBase
//{ }
public interface IAcUserDtoBase<TProfile, TServiceProvider, TUserToServiceProvider, TProfileAddress> : IAcUserDtoMinBase<TProfile>, IAcServiceProviderRelation<TServiceProvider, TUserToServiceProvider>
where TProfile : class, IAcProfile<TProfileAddress>
where TServiceProvider : class, IAcServiceProviderBase
where TUserToServiceProvider : class, IAcUserToServiceProviderBase
where TProfileAddress : class, IAcAddress
{
}

View File

@ -1,32 +1,14 @@
using AyCode.Interfaces.Addresses;
using AyCode.Interfaces.Addresses.Dtos;
using AyCode.Interfaces.Entities;
using AyCode.Interfaces.Profiles;
using AyCode.Interfaces.Profiles.Dtos;
using AyCode.Interfaces.ServiceProviders;
namespace AyCode.Interfaces.Users.Dtos;
public interface IAcUserDtoDetailBase : IAcUserBase, IAcUserDtoBase
{ }
public interface IAcUserDtoDetailBase<TProfile> : IAcUserDtoDetailBase, IAcUserDtoBase<TProfile>
where TProfile : IAcProfileDtoBase
{ }
public interface IAcUserDtoDetailBase<TProfile, TAddress> : IAcUserDtoDetailBase<TProfile>//, IAcUserDtoBase<TProfile, TAddress>
where TProfile : IAcProfileDtoBase<TAddress>
where TAddress : IAcAddressDtoBase
{ }
public interface IAcUserDtoDetailBase<TProfile, TCompany, TUserToCompany> : IAcUserDtoDetailBase<TProfile>, IAcUserDtoBase<TProfile, TCompany, TUserToCompany>
where TProfile : IAcProfileDtoBase
where TCompany : IAcCompanyBase
where TUserToCompany : IAcUserToCompanyBase
{ }
public interface IAcUserDtoDetailBase<TProfile, TCompany, TUserToCompany, TAddress> : IAcUserDtoDetailBase<TProfile, TAddress>, IAcUserDtoBase<TProfile, TCompany, TUserToCompany>
where TProfile : IAcProfileDtoBase<TAddress>
where TCompany : IAcCompanyBase
where TUserToCompany : IAcUserToCompanyBase
where TAddress : IAcAddressDtoBase
{ }
public interface IAcUserDtoDetailBase<TProfile, TServiceProvider, TUserToServiceProvider, TProfileAddress> : IAcUserBase, IAcUserDtoBase<TProfile, TServiceProvider, TUserToServiceProvider, TProfileAddress>
where TProfile : class, IAcProfile<TProfileAddress>
where TServiceProvider : class, IAcServiceProviderBase
where TUserToServiceProvider : class, IAcUserToServiceProviderBase
where TProfileAddress : class, IAcAddress
{
}

View File

@ -5,12 +5,7 @@ using AyCode.Interfaces.Profiles.Dtos;
namespace AyCode.Interfaces.Users.Dtos;
public interface IAcUserDtoMinBase : IAcModelDtoBase
public interface IAcUserDtoMinBase<TProfile> : IEntityGuid, IAcProfileRelation<TProfile> where TProfile : class, IAcProfileDtoBase
{
public Guid AffiliateId { get; set; }
}
public interface IAcUserDtoMinBase<TProfile> : IAcUserDtoMinBase, IAcProfileRelation<TProfile> where TProfile : IAcProfileDtoBase
{
}

View File

@ -1,16 +0,0 @@
using AyCode.Interfaces.Entities;
using AyCode.Interfaces.TimeStampInfo;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.IO;
namespace AyCode.Interfaces.Users;
public interface IAcEmailAddress
{
[MaxLength(150)]
string EmailAddress { get; set; }
//[MaxLength(150)]
//string NormalizedEmail { get; set; }
}

View File

@ -1,20 +1,16 @@

using AyCode.Interfaces.Addresses;
using AyCode.Interfaces.Addresses.Dtos;
using AyCode.Interfaces.Entities;
using AyCode.Interfaces.Profiles;
using AyCode.Interfaces.Profiles.Dtos;
using AyCode.Interfaces.ServiceProviders;
using AyCode.Interfaces.Users.Dtos;
namespace AyCode.Interfaces.Users;
public interface IAcUser<TProfile, TAddress> : IAcUserDtoDetailBase<TProfile, TAddress>
where TProfile : IAcProfile<TAddress>
where TAddress : IAcAddressDtoBase
{ }
public interface IAcUser<TProfile, TCompany, TUserToCompany, TAddress> : IAcUser<TProfile, TAddress>, IAcUserDtoDetailBase<TProfile, TCompany, TUserToCompany, TAddress>
where TProfile : IAcProfile<TAddress>
where TCompany : IAcCompanyBase
where TUserToCompany : IAcUserToCompanyBase
where TAddress : IAcAddressDtoBase
public interface IAcUser<TProfile, TServiceProvider, TUserToServiceProvider, TProfileAddress> : IAcUserDtoDetailBase<TProfile, TServiceProvider, TUserToServiceProvider, TProfileAddress>
where TProfile : class, IAcProfile<TProfileAddress>
where TServiceProvider : class, IAcServiceProviderBase
where TUserToServiceProvider : class, IAcUserToServiceProviderBase
where TProfileAddress : class, IAcAddress
{ }

View File

@ -1,14 +1,13 @@
using AyCode.Interfaces.Entities;
using AyCode.Interfaces.Profiles;
using AyCode.Interfaces.TimeStampInfo;
using AyCode.Interfaces.Users.Dtos;
namespace AyCode.Interfaces.Users;
public interface IAcUserBase : IEntityGuid, IAcProfileForeignKey, IAcEmailAddress, IEmailConfirmed, IPassword, ITimeStampInfo
public interface IAcUserBase : IEntityGuid, IAcProfileForeignKey, IEmailAddress, IPassword, ITimeStampInfo
{
public string? FullName { get; }
public string? PhoneNumber { get; set; }
public string PhoneNumber { get; set; }
public string? RefreshToken { get; set; }
public Guid? RefferalId { get; set; }

View File

@ -1,6 +0,0 @@
namespace AyCode.Interfaces.Users;
public interface IAcUserModelDtoMinBase : IAcModelDtoBase
{
}

View File

@ -4,10 +4,10 @@ using AyCode.Interfaces.TimeStampInfo;
namespace AyCode.Interfaces.Users;
public interface IAcUserToCompany<TUser, TCompany> : IAcUserToCompanyBase
public interface IAcUserToAcServiceProvider<TUser, TServiceProvider> : IAcUserToServiceProviderBase
where TUser : class, IAcUserBase
where TCompany : class, IAcCompanyBase
where TServiceProvider : class, IAcServiceProviderBase
{
public TUser User { get; set; }
public TCompany Company { get; set; }
public TServiceProvider ServiceProvider { get; set; }
}

View File

@ -4,7 +4,6 @@ using AyCode.Interfaces.TimeStampInfo;
namespace AyCode.Interfaces.Users;
public interface IAcUserToCompanyBase : IEntityGuid, IAcUserForeignKey, IAcCompanyForeignKey, ITimeStampInfo
public interface IAcUserToServiceProviderBase : IEntityGuid, IAcUserForeignKey, IAcServiceProviderForeignKey, ITimeStampInfo
{
public int Permissions { get; set; }
}

View File

@ -2,11 +2,11 @@
namespace AyCode.Interfaces.Users;
public interface IAcUserToServiceProviderRelation<TUser, TCompany, TUserToServiceProvider>
where TUser : class, IAcUserBase, IAcCompanyRelation<TCompany, TUserToServiceProvider>
where TCompany : class, IAcCompanyBase
where TUserToServiceProvider : class, IAcUserToCompanyBase
public interface IAcUserToServiceProviderRelation<TUser, TServiceProvider, TUserToServiceProvider>
where TUser : class, IAcUserBase, IAcServiceProviderRelation<TServiceProvider, TUserToServiceProvider>
where TServiceProvider : class, IAcServiceProviderBase
where TUserToServiceProvider : class, IAcUserToServiceProviderBase
{
public TUser User { get; set; }
public TCompany ServiceProvider { get; set; }
public TServiceProvider ServiceProvider { get; set; }
}

View File

@ -1,6 +1,8 @@
namespace AyCode.Interfaces.Users;
public interface IAcUsersRelation<TUser, TUserToServiceProvider> where TUser : IAcUserBase where TUserToServiceProvider : IAcUserToCompanyBase
public interface IAcUsersRelation<TUser, TUserToServiceProvider>
where TUser : class, IAcUserBase
where TUserToServiceProvider : class, IAcUserToServiceProviderBase
{
public List<TUser> Users { get; set; }
public List<TUserToServiceProvider> UserToServiceProviders { get; set; }

View File

@ -0,0 +1,13 @@
using System.ComponentModel.DataAnnotations;
namespace AyCode.Interfaces.Users;
public interface IEmailAddress
{
[MaxLength(150)]
string EmailAddress { get; set; }
bool EmailConfirmed { get; set; }
//[MaxLength(150)]
//string NormalizedEmail { get; set; }
}

View File

@ -1,6 +0,0 @@
namespace AyCode.Interfaces.Users;
public interface IEmailConfirmed
{
bool EmailConfirmed { get; set; }
}

View File

@ -1,23 +1,23 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
</PropertyGroup>
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<Import Project="..//AyCode.Core.targets" />
<ItemGroup>
<Folder Include="Dtos\" />
</ItemGroup>
<ItemGroup>
<Folder Include="Dtos\" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\AyCode.Core.Server\AyCode.Core.Server.csproj" />
<ProjectReference Include="..\AyCode.Core\AyCode.Core.csproj" />
<ProjectReference Include="..\AyCode.Entities.Server\AyCode.Entities.Server.csproj" />
<ProjectReference Include="..\AyCode.Entities\AyCode.Entities.csproj" />
<ProjectReference Include="..\AyCode.Interfaces.Server\AyCode.Interfaces.Server.csproj" />
<ProjectReference Include="..\AyCode.Interfaces\AyCode.Interfaces.csproj" />
<ProjectReference Include="..\AyCode.Models\AyCode.Models.csproj" />
<ProjectReference Include="..\AyCode.Services\AyCode.Services.csproj" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\AyCode.Core.Server\AyCode.Core.Server.csproj" />
<ProjectReference Include="..\AyCode.Core\AyCode.Core.csproj" />
<ProjectReference Include="..\AyCode.Entities.Server\AyCode.Entities.Server.csproj" />
<ProjectReference Include="..\AyCode.Entities\AyCode.Entities.csproj" />
<ProjectReference Include="..\AyCode.Interfaces.Server\AyCode.Interfaces.Server.csproj" />
<ProjectReference Include="..\AyCode.Interfaces\AyCode.Interfaces.csproj" />
<ProjectReference Include="..\AyCode.Models\AyCode.Models.csproj" />
</ItemGroup>
</Project>

View File

@ -1,35 +0,0 @@
using System.Collections.Concurrent;
using System.Reflection;
using AyCode.Services.SignalRs;
namespace AyCode.Models.Server.DynamicMethods;
public class AcDynamicMethodCallModel<TAttribute> where TAttribute : TagAttribute
{
public object InstanceObject { get; init; }
public ConcurrentDictionary<int, AcMethodInfoModel<TAttribute>> MethodsByMessageTag { get; init; } = new();
public AcDynamicMethodCallModel(Type instanceObjectType) : this(instanceObjectType, null!)
{
}
public AcDynamicMethodCallModel(Type instanceObjectType, params object[] constructorParams) : this(Activator.CreateInstance(instanceObjectType, constructorParams)!)
{
}
public AcDynamicMethodCallModel(object instanceObject)
{
InstanceObject = instanceObject;
foreach (var methodInfo in instanceObject.GetType().GetMethods())
{
if (methodInfo.GetCustomAttribute(typeof(TAttribute)) is not TAttribute attribute) continue;
if (MethodsByMessageTag.ContainsKey(attribute.MessageTag))
throw new Exception($"Multiple SignaRMessageTag! messageTag: {attribute.MessageTag}; methodName: {methodInfo.Name}");
MethodsByMessageTag[attribute.MessageTag] = new AcMethodInfoModel<TAttribute>(attribute, methodInfo!);
}
}
}

View File

@ -1,24 +0,0 @@
using System.Reflection;
using AyCode.Services.SignalRs;
namespace AyCode.Models.Server.DynamicMethods;
public class AcMethodInfoModel<TAttribute> where TAttribute : TagAttribute
{
public ParameterInfo[]? ParamInfos { get; init; } = null;
public TAttribute Attribute { get; init; }
public MethodInfo MethodInfo { get; init; }
public AcMethodInfoModel(TAttribute attribute, MethodInfo methodInfo)
{
Attribute = attribute;
MethodInfo = methodInfo;
var parameters = methodInfo.GetParameters();
//if (parameters.Length > 1)
// throw new Exception("MethodInfoModel; parameters.Length > 1");
ParamInfos = parameters;
}
}

View File

@ -1,38 +0,0 @@
using AyCode.Core.Consts;
using AyCode.Interfaces.Addresses;
using AyCode.Interfaces.Profiles;
using AyCode.Interfaces.ServiceProviders;
using AyCode.Interfaces.Users;
using AyCode.Interfaces.Server.Logins;
namespace AyCode.Models.Server.Logins;
public class AcLoggedInModelServer<TUser, TUserToken, TProfile, TCompany, TUserToServiceProvider, TProfileAddress> : IAcLoggedInModelBase<TUser, TUserToken, TProfile, TCompany, TUserToServiceProvider, TProfileAddress>
where TUser : class, IAcUser<TProfile, TCompany, TUserToServiceProvider, TProfileAddress>
where TUserToken : class, IAcUserTokenBase
where TProfile : class, IAcProfile<TProfileAddress>
where TCompany : class, IAcCompanyBase
where TUserToServiceProvider : class, IAcUserToCompanyBase
where TProfileAddress : class, IAcAddress
{
public bool IsLoggedIn => LoggedInUser != null;
public TUser LoggedInUser { get; private set; }
public string AccessToken { get; private set; }
public AcErrorCode LoginErrorCode { get; set; }
public void AddLoggedInUser(TUser user, string accessToken)
{
LoggedInUser = user;
AccessToken = accessToken;
}
public void Logout()
{
AccessToken = string.Empty;
LoggedInUser = null;
LoginErrorCode = AcErrorCode.Unset;
}
}

View File

@ -1,5 +1,4 @@
using AyCode.Interfaces;
using AyCode.Interfaces.Entities;
using AyCode.Interfaces.Entities;
namespace AyCode.Models;
@ -9,19 +8,4 @@ public abstract class AcModelDtoBase : IAcModelDtoBase
protected AcModelDtoBase(){}
protected AcModelDtoBase(Guid id) => Id = id;
}
public abstract class AcModelDtoBase<TMainEntity> : AcModelDtoBase, IAcModelDtoBase<TMainEntity> where TMainEntity : IEntityGuid
{
protected AcModelDtoBase() : base() { }
protected AcModelDtoBase(Guid id) : base(id) { }
protected AcModelDtoBase(TMainEntity mainEntity) : this(mainEntity.Id) { }
public virtual TMainEntity CreateMainEntity()
{
var mainEntity = Activator.CreateInstance<TMainEntity>();
mainEntity.Id = Id;
return mainEntity;
}
}

View File

@ -1,18 +1,19 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
</PropertyGroup>
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<Import Project="..//AyCode.Core.targets" />
<ItemGroup>
<Folder Include="Logins\" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\AyCode.Core\AyCode.Core.csproj" />
<ProjectReference Include="..\AyCode.Entities\AyCode.Entities.csproj" />
<ProjectReference Include="..\AyCode.Interfaces\AyCode.Interfaces.csproj" />
</ItemGroup>
<ItemGroup>
<Folder Include="Logins\" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\AyCode.Core\AyCode.Core.csproj" />
<ProjectReference Include="..\AyCode.Entities\AyCode.Entities.csproj" />
<ProjectReference Include="..\AyCode.Interfaces\AyCode.Interfaces.csproj" />
</ItemGroup>
</Project>

View File

@ -0,0 +1,7 @@
using AyCode.Interfaces.Entities;
namespace AyCode.Models;
public interface IAcModelDtoBase : IEntityGuid
{
}

View File

@ -0,0 +1,8 @@
using AyCode.Interfaces.Entities;
namespace AyCode.Models.Logins;
public interface IAcLoginDtoBase : IEntityGuid
{
}

View File

@ -1,4 +1,4 @@
//using AyCode.Entities.Messages;
using AyCode.Entities.Messages;
using System;
using System.Collections.Generic;
using System.Linq;
@ -7,15 +7,15 @@ using System.Threading.Tasks;
namespace AyCode.Models.Messages
{
//public class EmailMessage : NoticeBase
//{
// public EmailMessage() { }
// public string Subject { get; set; }
// public string HtmlContent { get; set; }
// public EmailMessage(Guid senderId, Guid receiverId, string message, string subject, string htmlContent) : base(senderId, receiverId, message)
// {
// Subject = subject;
// HtmlContent = htmlContent;
// }
//}
public class EmailMessage : NoticeBase
{
public EmailMessage() { }
public string Subject { get; set; }
public string HtmlContent { get; set; }
public EmailMessage(Guid senderId, Guid receiverId, string message, string subject, string htmlContent) : base(senderId, receiverId, message)
{
Subject = subject;
HtmlContent = htmlContent;
}
}
}

View File

@ -1,23 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace AyCode.Models.Users
{
public abstract class AcChangePasswordDto : AcPasswordDtoBase
{
public Guid UserId { get; set; }
public string OldPassword { get; set; }
protected AcChangePasswordDto() : base()
{ }
protected AcChangePasswordDto(Guid userId, string oldPassword, string newPassword) : base(newPassword)
{
UserId = userId;
OldPassword = oldPassword;
}
}
}

View File

@ -1,14 +0,0 @@
namespace AyCode.Models.Users;
public abstract class AcForgotPasswordDto : AcPasswordDtoBase
{
public string Email { get; set; }
protected AcForgotPasswordDto() : base()
{ }
protected AcForgotPasswordDto(string email, string newPassword) : base(newPassword)
{
Email = email;
}
}

View File

@ -1,13 +0,0 @@
namespace AyCode.Models.Users;
public abstract class AcPasswordDtoBase
{
public string NewPassword { get; set; }
protected AcPasswordDtoBase() { }
protected AcPasswordDtoBase(string newPassword) : this()
{
NewPassword = newPassword;
}
}

View File

@ -1,7 +1,4 @@
using System.ComponentModel.DataAnnotations.Schema;
using System.Text.Json.Serialization;
using AyCode.Interfaces.Addresses;
using AyCode.Interfaces.Addresses.Dtos;
using AyCode.Interfaces.Addresses;
using AyCode.Interfaces.Profiles;
using AyCode.Interfaces.Profiles.Dtos;
using AyCode.Interfaces.ServiceProviders;
@ -10,37 +7,35 @@ using AyCode.Interfaces.Users.Dtos;
namespace AyCode.Models.Users;
public abstract class AcUserModelDtoBase<TUserDto, TProfileDto, TCompany, TUserToCompany> : AcUserModelDtoMinBase<TUserDto, TProfileDto>, IAcCompanyRelation<TCompany, TUserToCompany>
where TUserDto : class, IAcUserDtoBase
public abstract class AcUserModelDtoBase<TUserDto, TProfile, TProfileDto, TServiceProvider, TUserToServiceProvider, TProfileAddress> : AcUserModelDtoMinBase<TUserDto, TProfile, TProfileDto, TProfileAddress>, IAcServiceProviderRelation<TServiceProvider, TUserToServiceProvider>
where TUserDto : class, IAcUserDtoBase<TProfile, TServiceProvider, TUserToServiceProvider, TProfileAddress>
where TProfile : class, IAcProfile<TProfileAddress>
where TProfileDto : class, IAcProfileDtoBase
where TCompany : class, IAcCompanyBase
where TUserToCompany : class, IAcUserToCompanyBase
//where TAddressDto : class, IAcAddressDtoBase
where TServiceProvider : class, IAcServiceProviderBase
where TUserToServiceProvider : class, IAcUserToServiceProviderBase
where TProfileAddress : class, IAcAddress
{
public List<TCompany> ServiceProviders { get; set; } = [];
public List<TUserToCompany> UserToServiceProviders { get; set; } = [];
public List<TServiceProvider> ServiceProviders { get; set; }
public List<TUserToServiceProvider> UserToServiceProviders { get; set; }
protected AcUserModelDtoBase()
protected AcUserModelDtoBase() {}
protected AcUserModelDtoBase(IAcUserDtoBase<TProfile, TServiceProvider, TUserToServiceProvider, TProfileAddress> user) : base(user)
{
}
protected AcUserModelDtoBase(IAcUserDtoBase<TProfileDto, TCompany, TUserToCompany> user) : base(user)
{
ProfileDto.AddressId = user.Profile.AddressId;
if (user.ServiceProviders.Count == 0) return;
//így proxy error lesz... - J.
//ServiceProviders = new List<TCompany>(user.ServiceProviders);
//UserToServiceProviders = new List<TUserToServiceProvider>(user.UserToServiceProviders);
UserDto.AffiliateId = user.AffiliateId;
ServiceProviders = new List<TCompany>(user.ServiceProviders.Count);
UserToServiceProviders = new List<TUserToCompany>(user.UserToServiceProviders.Count);
//így proxy error lesz... - J.
//ServiceProviders = new List<TServiceProvider>(user.ServiceProviders);
//UserToServiceProviders = new List<TUserToServiceProvider>(user.UserToServiceProviders);
ServiceProviders = new List<TServiceProvider>(user.ServiceProviders.Count);
UserToServiceProviders = new List<TUserToServiceProvider>(user.UserToServiceProviders.Count);
foreach (var serviceProvider in user.ServiceProviders)
{
var newProvider = Activator.CreateInstance<TCompany>();
var newProvider = Activator.CreateInstance<TServiceProvider>();
newProvider.Id = serviceProvider.Id;
newProvider.Name = serviceProvider.Name;
@ -51,7 +46,7 @@ public abstract class AcUserModelDtoBase<TUserDto, TProfileDto, TCompany, TUserT
foreach (var userToServiceProvider in user.UserToServiceProviders)
{
var newUserToProvider = Activator.CreateInstance<TUserToCompany>();
var newUserToProvider = Activator.CreateInstance<TUserToServiceProvider>();
newUserToProvider.Id = userToServiceProvider.Id;
newUserToProvider.UserId = userToServiceProvider.UserId;

View File

@ -1,76 +1,22 @@
using System.ComponentModel.DataAnnotations.Schema;
using System.Text.Json.Serialization;
using AyCode.Interfaces.Addresses;
using AyCode.Interfaces.Addresses.Dtos;
using AyCode.Interfaces.Addresses;
using AyCode.Interfaces.Profiles;
using AyCode.Interfaces.Profiles.Dtos;
using AyCode.Interfaces.ServiceProviders;
using AyCode.Interfaces.TimeStampInfo;
using AyCode.Interfaces.Users;
using AyCode.Interfaces.Users.Dtos;
namespace AyCode.Models.Users;
//public abstract class AcUserModelDtoDetailBase<TUserDtoDetail, TProfile, TCompany, TUserToCompany, TAddressDto> : AcUserModelDtoDetailBase<TUserDtoDetail, TProfile, TProfile, TCompany, TUserToCompany, TAddressDto>
// where TUserDtoDetail : class, IAcUserDtoDetailBase
// where TProfile: class, IAcProfile<TAddressDto>
// where TCompany : class, IAcCompanyBase
// where TUserToCompany : class, IAcUserToCompanyBase
// where TAddressDto : class, IAcAddressDtoBase
//{
// protected AcUserModelDtoDetailBase() : base()
// {}
// protected AcUserModelDtoDetailBase(IAcUserDtoDetailBase<TProfile, TCompany, TUserToCompany, TAddressDto> user) : base(user)
// {
// }
//}
public abstract class AcUserModelDtoDetailBase<TUserDtoDetail, TProfileDto, TCompany, TUserToCompany, TAddressDto> : AcUserModelDtoBase<TUserDtoDetail, TProfileDto, TCompany, TUserToCompany>
where TUserDtoDetail : class, IAcUserDtoDetailBase
where TProfileDto : class, IAcProfileDtoBase<TAddressDto>
where TCompany : class, IAcCompanyBase
where TUserToCompany : class, IAcUserToCompanyBase
where TAddressDto : class, IAcAddressDtoBase
public abstract class AcUserModelDtoDetailBase<TUserDtoDetail, TProfile, TProfileDto, TServiceProvider, TUserToServiceProvider, TProfileAddress> : AcUserModelDtoBase<TUserDtoDetail, TProfile, TProfileDto, TServiceProvider, TUserToServiceProvider, TProfileAddress>
where TUserDtoDetail : class, IAcUserDtoDetailBase<TProfile, TServiceProvider, TUserToServiceProvider, TProfileAddress>
where TProfile : class, IAcProfile<TProfileAddress>
where TProfileDto : class, IAcProfileDtoBase
where TServiceProvider : class, IAcServiceProviderBase
where TUserToServiceProvider : class, IAcUserToServiceProviderBase
where TProfileAddress : class, IAcAddress
{
//public TAddressDto AddressDto { get; set; }
protected AcUserModelDtoDetailBase() : base() {}
protected AcUserModelDtoDetailBase(IAcUserDtoDetailBase<TProfileDto, TCompany, TUserToCompany, TAddressDto> user) : base(user)
protected AcUserModelDtoDetailBase() {}
protected AcUserModelDtoDetailBase(IAcUserDtoDetailBase<TProfile, TServiceProvider, TUserToServiceProvider, TProfileAddress> user) : base(user)
{
UserDto.Id = user.Id;
UserDto.ProfileId = user.ProfileId;
UserDto.EmailAddress = user.EmailAddress;
UserDto.EmailConfirmed = user.EmailConfirmed;
UserDto.PhoneNumber = user.PhoneNumber;
UserDto.RefferalId = user.RefferalId;
UserDto.AffiliateId = user.AffiliateId;
UserDto.RefreshToken = user.RefreshToken;
UserDto.Created = user.Created;
UserDto.Modified = user.Modified;
var address = Activator.CreateInstance<TAddressDto>();
address.Id = user.Profile.AddressId;
address.AddressText = user.Profile.Address.AddressText;
address.Latitude = user.Profile.Address.Latitude;
address.Longitude = user.Profile.Address.Longitude;
ProfileDto.Address = address;
}
public void CopyUserDtoValuesToUser(IAcUserDtoDetailBase<TProfileDto, TCompany, TUserToCompany, TAddressDto> user)
{
base.CopyUserDtoValuesToUser(user);
user.ProfileId = UserDto.ProfileId;
user.EmailAddress = UserDto.EmailAddress;
user.EmailConfirmed = UserDto.EmailConfirmed;
user.PhoneNumber = UserDto.PhoneNumber;
user.RefferalId = UserDto.RefferalId;
//user.RefreshToken = UserDto.RefreshToken; //Ezzel mi legyen?! - J.
user.Created = UserDto.Created;
user.Modified = UserDto.Modified;
}
}

View File

@ -1,6 +1,4 @@
using System.ComponentModel.DataAnnotations.Schema;
using System.Text.Json.Serialization;
using AyCode.Interfaces.Addresses;
using AyCode.Interfaces.Addresses;
using AyCode.Interfaces.Profiles;
using AyCode.Interfaces.Profiles.Dtos;
using AyCode.Interfaces.Users;
@ -8,17 +6,17 @@ using AyCode.Interfaces.Users.Dtos;
namespace AyCode.Models.Users;
public abstract class AcUserModelDtoMinBase<TUserDtoMin, TProfileDto> : AcModelDtoBase, /*AcModelDtoBase<IAcUserDtoMinBase<TProfileDto>>,*/ IAcUserModelDtoMinBase
where TUserDtoMin : class, IAcUserDtoMinBase
//where TProfile : class, IAcProfileDtoBase
public abstract class AcUserModelDtoMinBase<TUserDtoMin, TProfile, TProfileDto, TProfileAddress> : AcModelDtoBase
where TUserDtoMin : class, IAcUserDtoMinBase<TProfile>
where TProfile : class, IAcProfile<TProfileAddress>
where TProfileDto : class, IAcProfileDtoBase
//where TAddress : class, IAcAddress
where TProfileAddress : class, IAcAddress
{
public TUserDtoMin UserDto { get; set;}
public TProfileDto ProfileDto { get; set; }
public TProfileDto? Profile { get; set; }
protected AcUserModelDtoMinBase() {}
protected AcUserModelDtoMinBase(IAcUserDtoMinBase<TProfileDto> user) : base(user.Id)
protected AcUserModelDtoMinBase(IAcUserDtoMinBase<TProfile> user) : base(user.Id)
{
Id = user.Id;
@ -26,28 +24,8 @@ public abstract class AcUserModelDtoMinBase<TUserDtoMin, TProfileDto> : AcModelD
UserDto.Id = user.Id;
UserDto.AffiliateId = user.AffiliateId;
ProfileDto = Activator.CreateInstance<TProfileDto>();
ProfileDto.Id = user.Profile.Id;
ProfileDto.Name = user.Profile.Name;
ProfileDto.FirstName = user.Profile.FirstName;
ProfileDto.LastName = user.Profile.LastName;
//Profile.NickName = user.Profile.NickName;
Profile = Activator.CreateInstance<TProfileDto>();
Profile.Id = user.Profile.Id;
Profile.Name = user.Profile.Name;
}
public void CopyUserDtoValuesToUser(IAcUserDtoMinBase<TProfileDto> user)
{
user.Id = UserDto.Id;
user.AffiliateId = UserDto.AffiliateId;
}
//public virtual TUserDtoMin CreateMainEntity()
//{
// var user = base.CreateMainEntity();
// user.AffiliateId = UserDto.AffiliateId;
// user.ProfileId = ProfileDto.Id;
// user.Profile = Activator.CreateInstance<>()
//}
}

View File

@ -1,45 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<IsPackable>false</IsPackable>
<IsTestProject>true</IsTestProject>
</PropertyGroup>
<Import Project="..//AyCode.Core.targets" />
<ItemGroup>
<PackageReference Include="coverlet.collector" Version="6.0.4">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.AspNetCore.Cryptography.KeyDerivation" Version="9.0.8" />
<PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="9.0.8" />
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="9.0.8" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.14.1" />
<PackageReference Include="MSTest.TestAdapter" Version="3.10.3" />
<PackageReference Include="MSTest.TestFramework" Version="3.10.3" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\AyCode.Core.Server\AyCode.Core.Server.csproj" />
<ProjectReference Include="..\AyCode.Core.Tests\AyCode.Core.Tests.csproj" />
<ProjectReference Include="..\AyCode.Core\AyCode.Core.csproj" />
<ProjectReference Include="..\AyCode.Database.Tests\AyCode.Database.Tests.csproj" />
<ProjectReference Include="..\AyCode.Database\AyCode.Database.csproj" />
<ProjectReference Include="..\AyCode.Entities.Server\AyCode.Entities.Server.csproj" />
<ProjectReference Include="..\AyCode.Entities\AyCode.Entities.csproj" />
<ProjectReference Include="..\AyCode.Interfaces.Server\AyCode.Interfaces.Server.csproj" />
<ProjectReference Include="..\AyCode.Interfaces\AyCode.Interfaces.csproj" />
<ProjectReference Include="..\AyCode.Models.Server\AyCode.Models.Server.csproj" />
<ProjectReference Include="..\AyCode.Models\AyCode.Models.csproj" />
<ProjectReference Include="..\AyCode.Services.Server\AyCode.Services.Server.csproj" />
<ProjectReference Include="..\AyCode.Services\AyCode.Services.csproj" />
<ProjectReference Include="..\AyCode.Utils.Server\AyCode.Utils.Server.csproj" />
<ProjectReference Include="..\AyCode.Utils\AyCode.Utils.csproj" />
</ItemGroup>
<ItemGroup>
<Using Include="Microsoft.VisualStudio.TestTools.UnitTesting" />
</ItemGroup>
</Project>

View File

@ -1,138 +0,0 @@
using AyCode.Database.DataLayers.Users;
using AyCode.Database.DbContexts.Users;
using AyCode.Database.DbContexts;
using AyCode.Database.Tests;
using AyCode.Interfaces.Addresses;
using AyCode.Interfaces.Messages;
using AyCode.Interfaces.Profiles;
using AyCode.Interfaces.Server.Logins;
using AyCode.Interfaces.ServiceProviders;
using AyCode.Interfaces.Users;
using AyCode.Core.Consts;
using AyCode.Core.Extensions;
using AyCode.Services.Server.Logins;
using AyCode.Utils.Extensions;
using AyCode.Core.Helpers;
namespace AyCode.Services.Server.Tests.LoginServices
{
public abstract class AcLoginServiceServerTestBase<TDal, TDbContext, TLoginServiceServer, TResultLoggedInModel, TUser, TProfile, TUserToken, TCompany, TUserToServiceProvider, TProfileAddress, TEmailMessage> : AcDatabaseTestModelBase<TDal, TDbContext>
where TDal : AcUserDalBase<TDbContext, TUser, TProfile, TUserToken, TCompany, TUserToServiceProvider, TProfileAddress, TEmailMessage>
where TDbContext : AcDbContextBase, IAcUserDbContextBase<TUser, TProfile, TUserToken, TCompany, TUserToServiceProvider, TProfileAddress, TEmailMessage>
where TLoginServiceServer : class, IAcLoginServiceServer<TResultLoggedInModel, TUser, TUserToken, TProfile, TCompany, TUserToServiceProvider, TProfileAddress>
where TResultLoggedInModel : class, IAcLoggedInModelBase<TUser, TUserToken, TProfile, TCompany, TUserToServiceProvider, TProfileAddress>
where TUser : class, IAcUser<TProfile, TCompany, TUserToServiceProvider, TProfileAddress>
where TProfile : class, IAcProfile<TProfileAddress>
where TProfileAddress : class, IAcAddress
where TUserToken : class, IAcUserTokenBase
where TCompany : class, IAcCompanyBase
where TUserToServiceProvider : class, IAcUserToCompanyBase
where TEmailMessage : class, IAcEmailMessageBase
{
[DataTestMethod]
[DataRow(["", "", ""])]
public virtual async Task AcBase_RegisterUser_ReturnsUser_WhenUserExist(string[] userIdEmailPasswordStrings)
{
var registerUserId = Guid.Parse(userIdEmailPasswordStrings[0]);
var registerEmail = userIdEmailPasswordStrings[1];
var registerPassword = userIdEmailPasswordStrings[2];
await Dal.RemoveUserAsync(registerUserId); //kitöröljük a szemetet, ha korábbról bentmaradt - J.
var loginService = Activator.CreateInstance(typeof(TLoginServiceServer), Dal, AcEnv.AppConfiguration) as TLoginServiceServer;
Assert.IsNotNull(loginService);
var errorCode = await loginService.RegistrationAsync(registerUserId, registerEmail, registerPassword, null);
Assert.IsTrue(errorCode == AcErrorCode.Unset);
var user = Dal.GetUserByEmail(registerEmail, false);
Assert.IsNotNull(user);
Assert.IsNotNull(user.Profile);
Assert.IsNotNull(user.Profile.Address);
await Dal.RemoveUserAsync(user); //kitöröljük a szemetet - J.
}
[DataTestMethod]
[DataRow(["", ""])]
public virtual void AcBase_LoginUser_ReturnsUser_WhenUserExist(string[] emailPasswordStrings)
{
var loginEmail = emailPasswordStrings[0];
var loginPassword = emailPasswordStrings[1];
var loginService = Activator.CreateInstance(typeof(TLoginServiceServer), Dal, AcEnv.AppConfiguration) as TLoginServiceServer;
Assert.IsNotNull(loginService);
#region Valid email+password test
var loggedInModel = loginService.Login(loginEmail, loginPassword);
Assert.IsNotNull(loggedInModel);
Assert.IsNotNull(loggedInModel.LoggedInUser);
Assert.IsNotNull(loginService.LoggedInModel?.LoggedInUser);
Assert.IsTrue(loggedInModel.LoginErrorCode == AcErrorCode.Unset, $"errorCode: {loggedInModel.LoginErrorCode}");
Assert.IsTrue(loggedInModel.IsLoggedIn, $"loggedInModel.IsLoggedIn == false; errorCode: {loggedInModel.LoginErrorCode}");
Assert.IsTrue(string.Equals(loggedInModel.LoggedInUser.EmailAddress, loginEmail, StringComparison.CurrentCultureIgnoreCase));
#endregion Valid email+password test
#region Wrong email test
loggedInModel = loginService.Login("gffsdgdfg@gu.hu", loginPassword);
Assert.IsNotNull(loggedInModel);
Assert.IsFalse(loggedInModel.IsLoggedIn);
Assert.IsTrue(loggedInModel.LoginErrorCode == AcErrorCode.WrongLoginData);
#endregion Wrong email test
#region Wrong password test
loggedInModel = loginService.Login(loginEmail, "fsdgfsdg");
Assert.IsNotNull(loggedInModel);
Assert.IsFalse(loggedInModel.IsLoggedIn);
Assert.IsTrue(loggedInModel.LoginErrorCode == AcErrorCode.WrongLoginData);
#endregion Wrong password test
}
[DataTestMethod]
[DataRow(["", "", ""])]
public virtual void AcBase_ChangePassword_ReturnUser_WhenUserLoggedInWithNewPassword(string[] userIdOriginalPasswordNewPasswordStrings)
{
var userId = Guid.Parse(userIdOriginalPasswordNewPasswordStrings[0]);
var originalPassword = userIdOriginalPasswordNewPasswordStrings[1];
var newPassword = userIdOriginalPasswordNewPasswordStrings[2];
var loginService = Activator.CreateInstance(typeof(TLoginServiceServer), Dal, AcEnv.AppConfiguration) as TLoginServiceServer;
Assert.IsNotNull(loginService);
var user = Dal.GetUserById(userId, false)!;
RestoreOriginalPassword(loginService, user, originalPassword);
var errorCode = loginService.ChangePassword(userId, originalPassword, newPassword);
Assert.IsTrue(errorCode == AcErrorCode.Unset, $"{errorCode}");
var loggedInModel = loginService.Login(user.EmailAddress, newPassword);
Assert.IsNotNull(loggedInModel);
Assert.IsTrue(loggedInModel.IsLoggedIn);
Assert.IsTrue(loggedInModel.LoggedInUser.Id == userId);
Assert.IsTrue(PasswordHasher.VerifyPassword(newPassword, loggedInModel.LoggedInUser.Password, PasswordHasher.GenerateDynamicSalt(userId)));
RestoreOriginalPassword(loginService, loggedInModel.LoggedInUser, originalPassword);
}
protected void RestoreOriginalPassword(TLoginServiceServer loginService, TUser user, string originalPassword)
{
if (PasswordHasher.VerifyPassword(originalPassword, user.Password, PasswordHasher.GenerateDynamicSalt(user.Id))) return;
loginService.UpdatePassword(user, originalPassword);
}
}
}

View File

@ -1,35 +1,31 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
</PropertyGroup>
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<Import Project="..//AyCode.Core.targets" />
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Configuration" Version="8.0.0" />
<PackageReference Include="SendGrid" Version="9.29.1" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Cryptography.KeyDerivation" Version="9.0.8" />
<PackageReference Include="Microsoft.AspNetCore.SignalR.Client" Version="9.0.8" />
<PackageReference Include="Microsoft.AspNetCore.SignalR.Common" Version="9.0.8" />
<PackageReference Include="Microsoft.AspNetCore.SignalR.Protocols.NewtonsoftJson" Version="9.0.8" />
<PackageReference Include="Microsoft.Extensions.Configuration" Version="9.0.8" />
<PackageReference Include="SendGrid" Version="9.29.3" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\AyCode.Core.Server\AyCode.Core.Server.csproj" />
<ProjectReference Include="..\AyCode.Core\AyCode.Core.csproj" />
<ProjectReference Include="..\AyCode.Database\AyCode.Database.csproj" />
<ProjectReference Include="..\AyCode.Entities.Server\AyCode.Entities.Server.csproj" />
<ProjectReference Include="..\AyCode.Entities\AyCode.Entities.csproj" />
<ProjectReference Include="..\AyCode.Interfaces.Server\AyCode.Interfaces.Server.csproj" />
<ProjectReference Include="..\AyCode.Interfaces\AyCode.Interfaces.csproj" />
<ProjectReference Include="..\AyCode.Models.Server\AyCode.Models.Server.csproj" />
<ProjectReference Include="..\AyCode.Models\AyCode.Models.csproj" />
<ProjectReference Include="..\AyCode.Services\AyCode.Services.csproj" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\AyCode.Core.Server\AyCode.Core.Server.csproj" />
<ProjectReference Include="..\AyCode.Core\AyCode.Core.csproj" />
<ProjectReference Include="..\AyCode.Database\AyCode.Database.csproj" />
<ProjectReference Include="..\AyCode.Entities.Server\AyCode.Entities.Server.csproj" />
<ProjectReference Include="..\AyCode.Entities\AyCode.Entities.csproj" />
<ProjectReference Include="..\AyCode.Interfaces.Server\AyCode.Interfaces.Server.csproj" />
<ProjectReference Include="..\AyCode.Interfaces\AyCode.Interfaces.csproj" />
<ProjectReference Include="..\AyCode.Models.Server\AyCode.Models.Server.csproj" />
<ProjectReference Include="..\AyCode.Models\AyCode.Models.csproj" />
<ProjectReference Include="..\AyCode.Services\AyCode.Services.csproj" />
</ItemGroup>
<ItemGroup>
<Folder Include="Messages\" />
<Folder Include="Emails\" />
</ItemGroup>
<ItemGroup>
<Folder Include="Messages\" />
</ItemGroup>
</Project>

View File

@ -1,48 +0,0 @@
using AyCode.Core.Consts;
using Microsoft.Extensions.Configuration;
using SendGrid.Helpers.Mail;
using SendGrid;
namespace AyCode.Services.Server.Emails;
public interface IAcEmailServiceServer
{
}
public class AcEmailServiceServer() : IAcEmailServiceServer
{
private readonly SendGridClient _sendGridClient;
private readonly EmailAddress _fromEmailAddress;
public AcEmailServiceServer(IConfiguration configuration) : this()
{
_sendGridClient = new SendGridClient(configuration["SendGrid:Key"]);
_fromEmailAddress = new EmailAddress(configuration["SendGrid:FromEmail"], configuration["SendGrid:FromName"]);
//Logger.Info($"{config.ServerUserName}; {config.FromEmail}; {config.FromName}");
}
public async Task<Response> SendLostPasswordEmailAsync(string addressEmail, string verificationToken)
{
const string subject = "Lost password";
var toEmailAddress = new EmailAddress(addressEmail);
var plainTextContent = $"{verificationToken}";
var htmlContent = $"<strong>{verificationToken}</strong>";
var msg = MailHelper.CreateSingleEmail(_fromEmailAddress, toEmailAddress, subject, plainTextContent, htmlContent);
return await _sendGridClient.SendEmailAsync(msg).ConfigureAwait(false);
}
public async Task<Response> SendRegistrationEmailAsync(string addressEmail, string verificationToken, string userName)
{
const string subject = "Registration";
var toEmailAddress = new EmailAddress(addressEmail);
var plainTextContent = $"User name: {userName}{AcEnv.NL}Confirmation token: {verificationToken}";
var htmlContent = $"User name: <strong>{userName}</strong></br>Confirmation token: <strong>{verificationToken}</strong>";
var msg = MailHelper.CreateSingleEmail(_fromEmailAddress, toEmailAddress, subject, plainTextContent, htmlContent);
return await _sendGridClient.SendEmailAsync(msg).ConfigureAwait(false);
}
}

View File

@ -1,256 +0,0 @@
using System.IdentityModel.Tokens.Jwt;
using AyCode.Core.Helpers;
using AyCode.Interfaces.Addresses;
using AyCode.Interfaces.Logins;
using AyCode.Interfaces.Profiles;
using AyCode.Interfaces.Server.Logins;
using AyCode.Interfaces.ServiceProviders;
using AyCode.Interfaces.Users;
using AyCode.Services.Logins;
using System.Runtime.InteropServices;
using System.Security;
using System.Security.Claims;
using System.Security.Cryptography;
using System.Text;
using Microsoft.IdentityModel.Tokens;
using AyCode.Database.DataLayers;
using Microsoft.EntityFrameworkCore;
using AyCode.Database.DbContexts;
using AyCode.Core.Consts;
using AyCode.Core.Extensions;
using AyCode.Core.Loggers;
using AyCode.Core.Server.Loggers;
using AyCode.Database.DataLayers.Users;
using AyCode.Database.DbContexts.Users;
using AyCode.Interfaces.Messages;
using AyCode.Models.Server.Logins;
using AyCode.Utils.Extensions;
using Microsoft.Extensions.Configuration;
namespace AyCode.Services.Server.Logins;
public class AcLoginServiceServer<TResultLoggedInModel, TDal, TDbContext, TUser, TUserToken, TProfile, TCompany, TUserToCompany, TProfileAddress, TEmailMessage>(TDal userDal, IConfiguration configuration)
: AcLoginServiceBase<TUser, TProfile, TCompany, TUserToCompany, TProfileAddress>, IAcLoginServiceServer<TResultLoggedInModel, TUser, TUserToken, TProfile, TCompany, TUserToCompany, TProfileAddress>
where TResultLoggedInModel : class, IAcLoggedInModelBase<TUser, TUserToken, TProfile, TCompany, TUserToCompany, TProfileAddress>
where TDal : AcUserDalBase<TDbContext, TUser, TProfile, TUserToken, TCompany, TUserToCompany, TProfileAddress, TEmailMessage>
where TDbContext : AcDbContextBase, IAcUserDbContextBase<TUser, TProfile, TUserToken, TCompany, TUserToCompany, TProfileAddress, TEmailMessage>
where TUser : class, IAcUser<TProfile, TCompany, TUserToCompany, TProfileAddress>
where TUserToken : class, IAcUserTokenBase
where TProfile : class, IAcProfile<TProfileAddress>
where TCompany : class, IAcCompanyBase
where TUserToCompany : class, IAcUserToCompanyBase
where TProfileAddress : class, IAcAddress
where TEmailMessage : class, IAcEmailMessageBase
{
public TResultLoggedInModel? LoggedInModel { get; private set; }
public override TUser? LoggedInUser => LoggedInModel?.LoggedInUser;
public override bool IsLoggedIn => LoggedInModel?.IsLoggedIn ?? false;
public virtual TResultLoggedInModel Login(string? email, string? password)
{
if (LoggedInModel != null) Logout();
LoggedInModel = Activator.CreateInstance<TResultLoggedInModel>();
if (AcValidate.IsValidEmailAndPasswordFormat(email, password, out var errorCode))
{
var user = userDal.AuthenticateUser(email, password, GenerateRefreshToken(), out errorCode);
if (user != null) LoggedInModel.AddLoggedInUser(user, GenerateAccessToken(user));
}
LoggedInModel.LoginErrorCode = errorCode;
return LoggedInModel;
}
public virtual Task<TResultLoggedInModel> LoginAsync(string? email, string? password)
{
return TaskHelper.ToThreadPoolTask(() => Login(email, password));
}
public virtual bool Logout()
{
LoggedInModel?.Logout();
LoggedInModel = null;
return true;
}
public virtual Task<bool> LogoutAsync()
{
return TaskHelper.ToThreadPoolTask(Logout);
}
public virtual AcErrorCode Registration(string email, string password, string? phoneNumber = null, Guid? referralId = null)
=> Registration(Guid.NewGuid(), email, password, phoneNumber, referralId);
public virtual AcErrorCode Registration(Guid userId, string email, string password, string? phoneNumber = null, Guid? referralId = null)
{
email = email.ToLower();
if ((phoneNumber != null && !AcValidate.IsValidPhoneNumberFormat(phoneNumber, out var errorCode)) ||
!AcValidate.IsValidEmailAndPasswordFormat(email, password, out errorCode)) return errorCode;
var user = Activator.CreateInstance<TUser>();
user.Id = userId;
user.EmailAddress = email;
user.EmailConfirmed = true;
user.Password = PasswordHasher.HashPassword(password, PasswordHasher.GenerateDynamicSalt(userId));
user.RefferalId = referralId;
var address = Activator.CreateInstance<TProfileAddress>();
address.Id = Guid.NewGuid();
var userName = email.Split('@')[0]; //TODO: generálni egy nevet... - J.
if (!userDal.AddUser(user, userName, address)) errorCode = AcErrorCode.DatabaseError;
return errorCode;
}
public virtual Task<AcErrorCode> RegistrationAsync(string email, string password, string? phoneNumber = null, Guid? referralId = null)
=> RegistrationAsync(Guid.NewGuid(), email, password, phoneNumber, referralId);
public virtual Task<AcErrorCode> RegistrationAsync(Guid userId, string email, string password, string? phoneNumber = null, Guid? referralId = null)
=> TaskHelper.ToThreadPoolTask(() => Registration(userId, email, password, phoneNumber, referralId));
public virtual Task<AcErrorCode> ChangePasswordAsync(Guid userId, string oldPassword, string newPassword)
=> TaskHelper.ToThreadPoolTask(() => ChangePassword(userId, oldPassword, newPassword));
public virtual AcErrorCode ChangePassword(Guid userId, string oldPassword, string newPassword)
{
try
{
if (userId.IsNullOrEmpty()) return AcErrorCode.IdIsNullOrEmpty;
if (!AcValidate.IsValidPasswordFormat(newPassword, out var errorCode)) return errorCode;
var user = userDal.GetUserById(userId, false); //TODO: csak az EmailConfirmed user password-öket lehessen change-elni! - J.
if (user == null) return AcErrorCode.EntityIsNull;
return PasswordHasher.VerifyPassword(oldPassword, user.Password, PasswordHasher.GenerateDynamicSalt(user.Id)) ? UpdatePassword(user, newPassword) : AcErrorCode.WrongLoginData;
}
catch (Exception)
{
// ignored
}
return AcErrorCode.UnknownError;
}
public Task<AcErrorCode> ForgotPasswordAsync(string email, string newPassword)
=> TaskHelper.ToThreadPoolTask(() => ForgotPassword(email, newPassword));
public AcErrorCode ForgotPassword(string email, string newPassword)
{
try
{
if (email.IsNullOrEmpty()) return AcErrorCode.EmailIsNullOrEmpty;
if (!AcValidate.IsValidPasswordFormat(newPassword, out var errorCode)) return errorCode;
var user = userDal.GetUserByEmail(email, false);
return user == null ? AcErrorCode.EntityIsNull : UpdatePassword(user, newPassword);
}
catch (Exception)
{
// ignored
}
return AcErrorCode.UnknownError;
}
public AcErrorCode UpdatePassword(TUser user, string password)
{
user.Password = PasswordHasher.HashPassword(password, PasswordHasher.GenerateDynamicSalt(user.Id));
return userDal.UpdateUser(user) == null ? AcErrorCode.DatabaseError : AcErrorCode.Unset;
}
public virtual bool SendConfirmationToken(string? email, string confirmationToken)
{
//var sendGrid = SendGrid.SendGridClient();
return true;
}
public virtual Task<bool> SendConfirmationTokenAsync(string email, string confirmationToken)
=> TaskHelper.ToThreadPoolTask(() => SendConfirmationToken(email, confirmationToken));
public string GenerateAccessToken(TUser user)
{
var tokenHandler = new JwtSecurityTokenHandler();
//GlobalLogger.Detail("----------------------------------------------------------");
if (configuration["JWT:Key"] == null)
throw new SecurityTokenException("Token is null");
var keyDetail = Encoding.UTF8.GetBytes(configuration["JWT:Key"] ?? string.Empty);
GlobalLogger.Detail($"Key: {configuration["JWT:Key"]}");
var claims = new List<Claim>
{
new(ClaimTypes.NameIdentifier, user.Id.ToString()),
new(ClaimTypes.Email, user.EmailAddress)
};
var tokenDescriptor = new SecurityTokenDescriptor
{
Audience = configuration["JWT:Audience"],
Issuer = configuration["JWT:Issuer"],
Expires = DateTime.UtcNow.AddHours(6),
//Expires = DateTime.UtcNow.AddSeconds(30),
Subject = new ClaimsIdentity(claims),
SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(keyDetail), SecurityAlgorithms.HmacSha256Signature)
};
var token = tokenHandler.CreateToken(tokenDescriptor) as JwtSecurityToken;
var writtenToken = tokenHandler.WriteToken(token);
GlobalLogger.Detail($"AccesToken: {writtenToken}");
return writtenToken;
}
public ClaimsPrincipal? GetPrincipalFromExpiredToken(string? token)
{
if (token.IsNullOrWhiteSpace()) return null;
var tokenHandler = new JwtSecurityTokenHandler();
if (configuration["JWT:Key"] == null)
throw new SecurityTokenException("Token is null");
var keyDetail = Encoding.UTF8.GetBytes(configuration["JWT:Key"] ?? string.Empty);
var tokenValidationParameter = new TokenValidationParameters
{
ValidateIssuer = false,
ValidateAudience = false,
ValidateLifetime = false,
ValidateIssuerSigningKey = true,
ValidIssuer = configuration["JWT:Issuer"],
ValidAudience = configuration["JWT:Audience"],
IssuerSigningKey = new SymmetricSecurityKey(keyDetail),
};
var principal = tokenHandler.ValidateToken(token, tokenValidationParameter, out var securityToken);
if (securityToken is not JwtSecurityToken jwtSecurityToken || !jwtSecurityToken.Header.Alg.Equals(SecurityAlgorithms.HmacSha256, StringComparison.InvariantCultureIgnoreCase))
throw new SecurityTokenException("Invalid token");
return principal;
}
public string GenerateRefreshToken()
{
var randomNumber = new byte[32];
using var rng = RandomNumberGenerator.Create();
rng.GetBytes(randomNumber);
return Convert.ToBase64String(randomNumber);
}
}

View File

@ -1,12 +0,0 @@
using System.Collections.Concurrent;
namespace AyCode.Services.Server.SignalRs;
public class AcSessionService<TSessionItem, TSessionItemId> where TSessionItem : IAcSessionItem<TSessionItemId> where TSessionItemId : notnull
{
public ConcurrentDictionary<TSessionItemId, TSessionItem> Sessions { get; private set; } = [];
public AcSessionService()
{
}
}

View File

@ -1,283 +0,0 @@
using System.Collections.Concurrent;
using AyCode.Core;
using AyCode.Core.Extensions;
using AyCode.Core.Helpers;
using AyCode.Core.Loggers;
using AyCode.Interfaces.Entities;
using AyCode.Services.SignalRs;
using MessagePack.Resolvers;
using Microsoft.AspNetCore.SignalR.Client;
namespace AyCode.Services.Server.SignalRs
{
public abstract class AcSignalRClientBase : IAcSignalRHubClient
{
private readonly ConcurrentDictionary<int, SignalRRequestModel> _responseByRequestId = new();
protected readonly HubConnection HubConnection;
protected readonly AcLoggerBase Logger;
public event Action<int, byte[], int?> OnMessageReceived = null!;
//public event Action<int, int> OnMessageRequested;
public int Timeout = 10000;
private const string TagsName = "SignalRTags";
protected AcSignalRClientBase(string fullHubName, AcLoggerBase logger)
{
Logger = logger;
HubConnection = new HubConnectionBuilder()
.WithUrl(fullHubName)
//.AddMessagePackProtocol(options => {
// options.SerializerOptions = MessagePackSerializerOptions.Standard
// .WithResolver(MessagePack.Resolvers.StandardResolver.Instance)
// .WithSecurity(MessagePackSecurity.UntrustedData)
// .WithCompression(MessagePackCompression.Lz4Block)
// .WithCompressionMinLength(256);})
.Build();
HubConnection.Closed += HubConnection_Closed;
_ = HubConnection.On<int, byte[], int?>(nameof(IAcSignalRHubClient.OnReceiveMessage), OnReceiveMessage);
//_ = HubConnection.On<int, int>(nameof(IAcSignalRHubClient.OnRequestMessage), OnRequestMessage);
HubConnection.StartAsync().Forget();
}
private Task HubConnection_Closed(Exception? arg)
{
if (_responseByRequestId.IsEmpty) Logger.DebugConditional($"Client HubConnection_Closed");
else Logger.Warning($"Client HubConnection_Closed; {nameof(_responseByRequestId)} count: {_responseByRequestId.Count}");
_responseByRequestId.Clear();
return Task.CompletedTask;
}
public async Task StartConnection()
{
if (HubConnection.State == HubConnectionState.Disconnected)
await HubConnection.StartAsync();
if (HubConnection.State != HubConnectionState.Connected)
await TaskHelper.WaitToAsync(() => HubConnection.State == HubConnectionState.Connected, Timeout, 10, 25);
}
public async Task StopConnection()
{
await HubConnection.StopAsync();
await HubConnection.DisposeAsync();
}
public virtual Task SendMessageToServerAsync(int messageTag)
=> SendMessageToServerAsync(messageTag, null, AcDomain.NextUniqueInt32);
public virtual Task SendMessageToServerAsync(int messageTag, ISignalRMessage? message, int? requestId)
{
Logger.DebugConditional($"Client SendMessageToServerAsync; {nameof(requestId)}: {requestId}; {ConstHelper.NameByValue(TagsName, messageTag)}");
return StartConnection().ContinueWith(_ =>
{
var msgp = message?.ToMessagePack(ContractlessStandardResolver.Options);
return HubConnection.SendAsync(nameof(IAcSignalRHubClient.OnReceiveMessage), messageTag, msgp, requestId);
});
}
#region CRUD
public virtual Task<TResponseData?> GetByIdAsync<TResponseData>(int messageTag, object id) //where TResponseData : class
=> SendMessageToServerAsync<TResponseData>(messageTag, new SignalPostJsonDataMessage<IdMessage>(new IdMessage(id)), AcDomain.NextUniqueInt32);
public virtual Task GetByIdAsync<TResponseData>(int messageTag, Func<ISignalResponseMessage<TResponseData?>, Task> responseCallback, object id)
=> SendMessageToServerAsync(messageTag, new SignalPostJsonDataMessage<IdMessage>(new IdMessage(id)), responseCallback);
public virtual Task<TResponseData?> GetByIdAsync<TResponseData>(int messageTag, object[] ids) //where TResponseData : class
=> SendMessageToServerAsync<TResponseData>(messageTag, new SignalPostJsonDataMessage<IdMessage>(new IdMessage(ids)), AcDomain.NextUniqueInt32);
public virtual Task GetByIdAsync<TResponseData>(int messageTag, Func<ISignalResponseMessage<TResponseData?>, Task> responseCallback, object[] ids)
=> SendMessageToServerAsync(messageTag, new SignalPostJsonDataMessage<IdMessage>(new IdMessage(ids)), responseCallback);
public virtual Task<TResponseData?> GetAllAsync<TResponseData>(int messageTag) //where TResponseData : class
=> SendMessageToServerAsync<TResponseData>(messageTag);
public virtual Task GetAllAsync<TResponseData>(int messageTag, Func<ISignalResponseMessage<TResponseData?>, Task> responseCallback)
=> SendMessageToServerAsync(messageTag, null, responseCallback);
public virtual Task GetAllAsync<TResponseData>(int messageTag, Func<ISignalResponseMessage<TResponseData?>, Task> responseCallback, object[]? contextParams)
=> SendMessageToServerAsync(messageTag, (contextParams == null || contextParams.Length == 0 ? null : new SignalPostJsonDataMessage<IdMessage>(new IdMessage(contextParams))), responseCallback);
public virtual Task<TResponseData?> GetAllAsync<TResponseData>(int messageTag, object[]? contextParams) //where TResponseData : class
=> SendMessageToServerAsync<TResponseData>(messageTag, contextParams == null || contextParams.Length == 0 ? null : new SignalPostJsonDataMessage<IdMessage>(new IdMessage(contextParams)), AcDomain.NextUniqueInt32);
public virtual Task<TPostData?> PostDataAsync<TPostData>(int messageTag, TPostData postData) where TPostData : class
=> SendMessageToServerAsync<TPostData>(messageTag, new SignalPostJsonDataMessage<TPostData>(postData), AcDomain.NextUniqueInt32);
public virtual Task<TResponseData?> PostDataAsync<TPostData, TResponseData>(int messageTag, TPostData postData) //where TPostData : class where TResponseData : class
=> SendMessageToServerAsync<TResponseData>(messageTag, new SignalPostJsonDataMessage<TPostData>(postData), AcDomain.NextUniqueInt32);
public virtual Task PostDataAsync<TPostData>(int messageTag, TPostData postData, Func<ISignalResponseMessage<TPostData?>, Task> responseCallback) //where TPostData : class
=> SendMessageToServerAsync(messageTag, new SignalPostJsonDataMessage<TPostData>(postData), responseCallback);
public virtual Task PostDataAsync<TPostData, TResponseData>(int messageTag, TPostData postData, Func<ISignalResponseMessage<TResponseData?>, Task> responseCallback) //where TPostData : class where TResponseData : class
=> SendMessageToServerAsync(messageTag, new SignalPostJsonDataMessage<TPostData>(postData), responseCallback);
public Task GetAllIntoAsync<TResponseItem>(List<TResponseItem> intoList, int messageTag, object[]? contextParams = null, Action? callback = null) where TResponseItem : IEntityGuid
{
return GetAllAsync<List<TResponseItem>>(messageTag, response =>
{
var logText = $"GetAllIntoAsync<{typeof(TResponseItem).Name}>(); status: {response.Status}; dataCount: {response.ResponseData?.Count}; {ConstHelper.NameByValue(TagsName, messageTag)};";
intoList.Clear();
if (response.Status == SignalResponseStatus.Success && response.ResponseData != null)
{
Logger.Debug(logText);
intoList.AddRange(response.ResponseData);
}
else Logger.Error(logText);
callback?.Invoke();
return Task.CompletedTask;
}, contextParams);
}
#endregion CRUD
public virtual Task<TResponse?> SendMessageToServerAsync<TResponse>(int messageTag) //where TResponse : class
=> SendMessageToServerAsync<TResponse>(messageTag, null, AcDomain.NextUniqueInt32);
public virtual Task<TResponse?> SendMessageToServerAsync<TResponse>(int messageTag, ISignalRMessage? message) //where TResponse : class
=> SendMessageToServerAsync<TResponse>(messageTag, message, AcDomain.NextUniqueInt32);
protected virtual async Task<TResponse?> SendMessageToServerAsync<TResponse>(int messageTag, ISignalRMessage? message, int requestId) //where TResponse : class
{
Logger.DebugConditional($"Client SendMessageToServerAsync<TResult>; {nameof(requestId)}: {requestId}; {ConstHelper.NameByValue(TagsName, messageTag)}");
_responseByRequestId[requestId] = new SignalRRequestModel();
await SendMessageToServerAsync(messageTag, message, requestId);
try
{
if (await TaskHelper.WaitToAsync(() => _responseByRequestId[requestId].ResponseByRequestId != null, Timeout, 25, 50) &&
_responseByRequestId.TryRemove(requestId, out var obj) && obj.ResponseByRequestId is ISignalResponseMessage<string> responseMessage)
{
if (responseMessage.Status == SignalResponseStatus.Error || responseMessage.ResponseData == null)
{
var errorText = $"Client SendMessageToServerAsync<TResponseData> response error; await; tag: {messageTag}; Status: {responseMessage.Status}; requestId: {requestId};";
Logger.Error(errorText);
//TODO: Ideiglenes, majd a ResponseMessage-et kell visszaadni a Status miatt! - J.
return await Task.FromException<TResponse>(new Exception(errorText));
//throw new Exception(errorText);
//return default;
}
return responseMessage.ResponseData.JsonTo<TResponse>();
}
}
catch (Exception ex)
{
Logger.Error($"SendMessageToServerAsync; requestId: {requestId}; {ex.Message}; {ConstHelper.NameByValue(TagsName, messageTag)}", ex);
}
_responseByRequestId.TryRemove(requestId, out _);
return default;
}
public virtual Task SendMessageToServerAsync<TResponseData>(int messageTag, Func<ISignalResponseMessage<TResponseData?>, Task> responseCallback)
=> SendMessageToServerAsync(messageTag, null, responseCallback);
public virtual Task SendMessageToServerAsync<TResponseData>(int messageTag, ISignalRMessage? message, Func<ISignalResponseMessage<TResponseData?>, Task> responseCallback)
{
if (messageTag == 0)
Logger.Error($"SendMessageToServerAsync; messageTag == 0");
var requestId = AcDomain.NextUniqueInt32;
_responseByRequestId[requestId] = new SignalRRequestModel(new Action<ISignalResponseMessage<string>>(responseMessage =>
{
TResponseData? responseData = default;
if (responseMessage.Status == SignalResponseStatus.Success)
{
responseData = string.IsNullOrEmpty(responseMessage.ResponseData) ? default : responseMessage.ResponseData.JsonTo<TResponseData?>();
}
else Logger.Error($"Client SendMessageToServerAsync<TResponseData> response error; callback; Status: {responseMessage.Status}; requestId: {requestId}; {ConstHelper.NameByValue(TagsName, messageTag)}");
responseCallback(new SignalResponseMessage<TResponseData?>(messageTag, responseMessage.Status, responseData));
}));
return SendMessageToServerAsync(messageTag, message, requestId);
}
public virtual Task OnReceiveMessage(int messageTag, byte[] message, int? requestId)
{
var logText = $"Client OnReceiveMessage; {nameof(requestId)}: {requestId}; {ConstHelper.NameByValue(TagsName, messageTag)}";
if (message.Length == 0) Logger.Warning($"message.Length == 0! {logText}");
try
{
if (requestId.HasValue && _responseByRequestId.ContainsKey(requestId.Value))
{
var reqId = requestId.Value;
_responseByRequestId[reqId].ResponseDateTime = DateTime.UtcNow;
Logger.Info($"[{_responseByRequestId[reqId].ResponseDateTime.Subtract(_responseByRequestId[reqId].RequestDateTime).TotalMilliseconds:N0}ms][{(message.Length/1024)}kb]{logText}");
var responseMessage = message.MessagePackTo<SignalResponseJsonMessage>(ContractlessStandardResolver.Options);
switch (_responseByRequestId[reqId].ResponseByRequestId)
{
case null:
_responseByRequestId[reqId].ResponseByRequestId = responseMessage;
return Task.CompletedTask;
case Action<ISignalResponseMessage<string>> messagePackCallback:
_responseByRequestId.TryRemove(reqId, out _);
messagePackCallback.Invoke(responseMessage);
return Task.CompletedTask;
//case Action<string> jsonCallback:
// _responseByRequestId.TryRemove(reqId, out _);
// jsonCallback.Invoke(responseMessage);
// return Task.CompletedTask;
default:
Logger.Error($"Client OnReceiveMessage switch; unknown message type: {_responseByRequestId[reqId].ResponseByRequestId?.GetType().Name}; {ConstHelper.NameByValue(TagsName, messageTag)}");
break;
}
_responseByRequestId.TryRemove(reqId, out _);
}
else Logger.Info(logText);
OnMessageReceived(messageTag, message, requestId);
}
catch (Exception ex)
{
if (requestId.HasValue)
_responseByRequestId.TryRemove(requestId.Value, out _);
Logger.Error($"Client OnReceiveMessage; requestId: {requestId}; {ex.Message}; {ConstHelper.NameByValue(TagsName, messageTag)}", ex);
throw;
}
return Task.CompletedTask;
}
//public virtual Task OnRequestMessage(int messageTag, int requestId)
//{
// Logger.DebugConditional($"Client OnRequestMessage; {nameof(messageTag)}: {messageTag}; {nameof(requestId)}: {requestId};");
// try
// {
// OnMessageRequested(messageTag, requestId);
// }
// catch(Exception ex)
// {
// Logger.Error($"Client OnReceiveMessage; {nameof(messageTag)}: {messageTag}; {nameof(requestId)}: {requestId}; {ex.Message}", ex);
// throw;
// }
// return Task.CompletedTask;
//}
}
}

View File

@ -1,1075 +0,0 @@
using System.Collections;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using AyCode.Core.Enums;
using AyCode.Core.Extensions;
using AyCode.Core.Helpers;
using AyCode.Core.Interfaces;
using AyCode.Services.SignalRs;
namespace AyCode.Services.Server.SignalRs
{
public class TrackingItem<T>(TrackingState trackingState, T currentValue, T? originalValue = null) where T : class, IId<Guid>
{
public TrackingState TrackingState { get; internal set; } = trackingState;
public T CurrentValue { get; internal set; } = currentValue;
public T? OriginalValue { get; init; } = originalValue;
internal TrackingItem<T> UpdateItem(TrackingState trackingState, T newValue)
{
CurrentValue = newValue;
if (TrackingState != TrackingState.Add)
TrackingState = trackingState;
return this;
}
}
public class ChangeTracking<T> /*: IEnumerable<TrackingItem<T>>*/ where T : class, IId<Guid>
{
private readonly List<TrackingItem<T>> _trackingItems = []; //TODO: Dictionary... - J.
internal TrackingItem<T>? AddTrackingItem(TrackingState trackingState, T newValue, T? originalValue = null)
{
if (newValue.Id.IsNullOrEmpty()) throw new ArgumentNullException(nameof(newValue), $@"currentValue.Id.IsNullOrEmpty()");
var itemIndex = _trackingItems.FindIndex(x => x.CurrentValue.Id == newValue.Id);
TrackingItem<T>? trackingItem = null;
if (itemIndex > -1)
{
trackingItem = _trackingItems[itemIndex];
if (trackingState == TrackingState.Remove && trackingItem.TrackingState == TrackingState.Add)
{
_trackingItems.RemoveAt(itemIndex);
return null;
}
return trackingItem.UpdateItem(trackingState, newValue);
}
if (originalValue != null && Equals(newValue, originalValue))
originalValue = TrackingItemHelpers.JsonClone(originalValue);
trackingItem = new TrackingItem<T>(trackingState, newValue, originalValue);
_trackingItems.Add(trackingItem);
return trackingItem;
}
public int Count => _trackingItems.Count;
internal void Clear() => _trackingItems.Clear();
public List<TrackingItem<T>> ToList() => _trackingItems.ToList();
public bool TryGetTrackingItem(Guid id, [NotNullWhen(true)] out TrackingItem<T>? trackingItem)
{
trackingItem = _trackingItems.FirstOrDefault(x => x.CurrentValue.Id == id);
return trackingItem != null;
}
internal void Remove(TrackingItem<T> trackingItem) => _trackingItems.Remove(trackingItem);
//public IEnumerator<TrackingItem<T>> GetEnumerator()
//{
// return _trackingItems.GetEnumerator();
//}
//IEnumerator IEnumerable.GetEnumerator()
//{
// return GetEnumerator();
//}
}
[Serializable]
[DebuggerDisplay("Count = {Count}")]
public class AcSignalRDataSource<T> : IList<T>, IList, IReadOnlyList<T> where T : class, IId<Guid>
{
private readonly object _syncRoot = new();
protected List<T> InnerList = []; //TODO: Dictionary??? - J.
protected readonly ChangeTracking<T> TrackingItems = new();
public object[]? ContextIds;
public string? FilterText { get; set; }
public AcSignalRClientBase SignalRClient;
protected readonly SignalRCrudTags SignalRCrudTags;
public Func<ItemChangedEventArgs<T>, Task>? OnDataSourceItemChanged;
public Func<Task>? OnDataSourceLoaded;
public AcSignalRDataSource(AcSignalRClientBase signalRClient, SignalRCrudTags signalRCrudTags, object[]? contextIds = null)
{
//if (contextIds != null) (ContextIds = new List<object>()).AddRange(contextIds);
ContextIds = contextIds;
SignalRCrudTags = signalRCrudTags;
SignalRClient = signalRClient;
}
public bool IsSynchronized => true;
public object SyncRoot => _syncRoot;
public bool IsFixedSize => false;
public bool HasWorkingReferenceList { get; private set; }
public void SetWorkingReferenceList(List<T> workingList)
{
if (workingList == null!) return; //throw new ArgumentNullException(nameof(workingList));
Monitor.Enter(_syncRoot);
try
{
HasWorkingReferenceList = true;
if (ReferenceEquals(InnerList, workingList)) return;
if (workingList.Count == 0) workingList.AddRange(InnerList);
Clear(true);
InnerList = workingList;
}
finally
{
Monitor.Exit(_syncRoot);
}
}
private object[]? GetContextParams()
{
var parameters = new List<object>();
if (ContextIds != null) parameters.AddRange(ContextIds);
if (FilterText != null) parameters.Add(FilterText); //Az empty string-et beletesszük, h legyen paraméter! - J.
if (parameters.Count == 0) parameters = null;
return parameters?.ToArray();
}
/// <summary>
/// GetAllMessageTag
/// </summary>
/// <exception cref="ArgumentException"></exception>
/// <exception cref="NullReferenceException"></exception>
public async Task LoadDataSource(bool clearChangeTracking = true)
{
if (SignalRCrudTags.GetAllMessageTag == AcSignalRTags.None) throw new ArgumentException($"SignalRCrudTags.GetAllMessageTag == SignalRTags.None");
var responseData = (await SignalRClient.GetAllAsync<List<T>>(SignalRCrudTags.GetAllMessageTag, GetContextParams())) ?? throw new NullReferenceException();
await LoadDataSource(responseData, false, false, clearChangeTracking);
}
public Task LoadDataSourceAsync(bool clearChangeTracking = true)
{
if (SignalRCrudTags.GetAllMessageTag == AcSignalRTags.None) throw new ArgumentException($"SignalRCrudTags.GetAllMessageTag == SignalRTags.None");
return SignalRClient.GetAllAsync<List<T>>(SignalRCrudTags.GetAllMessageTag, result=>
{
if (result.Status != SignalResponseStatus.Success || result.ResponseData == null)
throw new NullReferenceException($"LoadDataSourceAsync; result.Status != SignalResponseStatus.Success || result.ResponseData == null; Status: {SignalResponseStatus.Success}");
return LoadDataSource(result.ResponseData, false, false, clearChangeTracking);
}, GetContextParams());
}
public async Task LoadDataSource(IList<T> fromSource, bool refreshDataFromDbAsync = false, bool setSourceToWorkingReferenceList = false, bool clearChangeTracking = true)
{
Monitor.Enter(_syncRoot);
try
{
if (!ReferenceEquals(InnerList, fromSource))
{
Clear(clearChangeTracking);
if (setSourceToWorkingReferenceList && fromSource is List<T> fromSourceList) SetWorkingReferenceList(fromSourceList);
else InnerList.AddRange(fromSource);
}
else if (clearChangeTracking) TrackingItems.Clear();
if (refreshDataFromDbAsync) LoadDataSourceAsync(false).Forget();
}
finally
{
Monitor.Exit(_syncRoot);
}
if (OnDataSourceLoaded != null) await OnDataSourceLoaded.Invoke();
}
public async Task<T?> LoadItem(Guid id)
{
if (SignalRCrudTags.GetItemMessageTag == AcSignalRTags.None) throw new ArgumentException($"SignalRCrudTags.GetItemMessageTag == SignalRTags.None");
T? resultitem = null;
Monitor.Enter(_syncRoot);
try
{
resultitem = await SignalRClient.GetByIdAsync<T>(SignalRCrudTags.GetItemMessageTag, id);
if (resultitem == null) return null;
if (TryGetIndex(id, out var index)) InnerList[index] = resultitem;
else InnerList.Add(resultitem);
var eventArgs = new ItemChangedEventArgs<T>(resultitem, TrackingState.Get);
if (OnDataSourceItemChanged != null) await OnDataSourceItemChanged.Invoke(eventArgs);
}
finally
{
Monitor.Exit(_syncRoot);
}
return resultitem;
}
/// <summary>
/// set: UpdateMessageTag
/// </summary>
/// <param name="index"></param>
/// <returns></returns>
/// <exception cref="ArgumentOutOfRangeException"></exception>
public T this[int index]
{
get
{
if ((uint)index >= (uint)Count) throw new ArgumentOutOfRangeException(nameof(index));
Monitor.Enter(_syncRoot);
try
{
return InnerList[index];
}
finally
{
Monitor.Exit(_syncRoot);
}
}
set
{
Monitor.Enter(_syncRoot);
try
{
UpdateUnsafe(index, value);
}
finally
{
Monitor.Exit(_syncRoot);
}
}
}
public void Add(T newValue)
{
if (newValue.Id.IsNullOrEmpty()) throw new ArgumentNullException(nameof(newValue), @"Add->newValue.Id.IsNullOrEmpty()");
Monitor.Enter(_syncRoot);
try
{
if (Contains(newValue))
throw new ArgumentException($@"It already contains this Id! Id: {newValue.Id}", nameof(newValue));
UnsafeAdd(newValue);
}
finally
{
Monitor.Exit(_syncRoot);
}
}
/// <summary>
/// AddMessageTag
/// </summary>
/// <param name="newValue"></param>
/// <param name="autoSave"></param>
/// <exception cref="ArgumentException"></exception>
public async Task<T> Add(T newValue, bool autoSave)
{
Monitor.Enter(_syncRoot);
try
{
Add(newValue);
return autoSave ? await SaveItem(newValue, TrackingState.Add) : newValue;
}
finally
{
Monitor.Exit(_syncRoot);
}
}
/// <summary>
/// AddMessageTag or UpdateMessageTag
/// </summary>
/// <param name="newValue"></param>
/// <param name="autoSave"></param>
/// <returns></returns>
public async Task<T> AddOrUpdate(T newValue, bool autoSave)
{
if (newValue.Id.IsNullOrEmpty()) throw new ArgumentNullException(nameof(newValue), @"AddOrUpdate->newValue.Id.IsNullOrEmpty()");
Monitor.Enter(_syncRoot);
try
{
var index = IndexOf(newValue);
return index > -1 ? await Update(index, newValue, autoSave) : await Add(newValue, autoSave);
}
finally
{
Monitor.Exit(_syncRoot);
}
}
//public void AddRange(IEnumerable<T> collection)
//{
// lock (_syncRoot)
// {
// }
//}
protected void UnsafeAdd(T newValue)
{
TrackingItems.AddTrackingItem(TrackingState.Add, newValue);
InnerList.Add(newValue);
}
/// <summary>
/// AddMessageTag
/// </summary>
/// <param name="index"></param>
/// <param name="newValue"></param>
/// <param name="autoSave"></param>
/// <exception cref="ArgumentException"></exception>
/// <exception cref="NullReferenceException"></exception>
public void Insert(int index, T newValue)
{
if (newValue.Id.IsNullOrEmpty()) throw new ArgumentNullException(nameof(newValue), @"Insert->newValue.Id.IsNullOrEmpty()");
Monitor.Enter(_syncRoot);
try
{
if (Contains(newValue))
throw new ArgumentException($@"Insert; It already contains this Id! Id: {newValue.Id}", nameof(newValue));
TrackingItems.AddTrackingItem(TrackingState.Add, newValue);
InnerList.Insert(index, newValue);
}
finally
{
Monitor.Exit(_syncRoot);
}
}
public async Task<T> Insert(int index, T newValue, bool autoSave)
{
Monitor.Enter(_syncRoot);
try
{
Insert(index, newValue);
return autoSave ? await SaveItem(newValue, TrackingState.Add) : newValue;
}
finally
{
Monitor.Exit(_syncRoot);
}
}
/// <summary>
/// UpdateMessageTag
/// </summary>
/// <param name="newItem"></param>
/// <param name="autoSave"></param>
public Task<T> Update(T newItem, bool autoSave) => Update(IndexOf(newItem), newItem, autoSave);
/// <summary>
/// UpdateMessageTag
/// </summary>
/// <param name="index"></param>
/// <param name="newValue"></param>
/// <param name="autoSave"></param>
/// /// <exception cref="ArgumentException"></exception>
/// /// <exception cref="NullReferenceException"></exception>
/// <exception cref="ArgumentNullException"></exception>
/// <exception cref="ArgumentOutOfRangeException"></exception>
public async Task<T> Update(int index, T newValue, bool autoSave)
{
Monitor.Enter(_syncRoot);
try
{
UpdateUnsafe(index, newValue);
return autoSave ? await SaveItem(newValue, TrackingState.Update) : newValue;
}
finally
{
Monitor.Exit(_syncRoot);
}
}
private void UpdateUnsafe(int index, T newValue)
{
if (default(T) != null && newValue == null) throw new NullReferenceException(nameof(newValue));
if (newValue.Id.IsNullOrEmpty()) throw new ArgumentNullException(nameof(newValue), @"UpdateUnsafe->newValue.Id.IsNullOrEmpty()");
if ((uint)index >= (uint)Count) throw new ArgumentOutOfRangeException(nameof(index));
Monitor.Enter(_syncRoot);
try
{
var currentItem = InnerList[index];
if (currentItem.Id != newValue.Id)
throw new ArgumentException($@"UpdateUnsafe; currentItem.Id != item.Id! Id: {newValue.Id}", nameof(newValue));
TrackingItems.AddTrackingItem(TrackingState.Update, newValue, currentItem);
InnerList[index] = newValue;
}
finally
{
Monitor.Exit(_syncRoot);
}
}
/// <summary>
/// RemoveMessageTag
/// </summary>
/// <param name="item"></param>
/// <returns></returns>
public bool Remove(T item)
{
Monitor.Enter(_syncRoot);
try
{
var index = IndexOf(item);
if (index < 0) return false;
RemoveAt(index);
return true;
}
finally
{
Monitor.Exit(_syncRoot);
}
}
public async Task<bool> Remove(T item, bool autoSave)
{
Monitor.Enter(_syncRoot);
try
{
var result = Remove(item);
if (!autoSave || !result) return result;
await SaveItem(item, TrackingState.Remove);
return true;
}
finally
{
Monitor.Exit(_syncRoot);
}
}
/// <summary>
///
/// </summary>
/// <param name="id"></param>
/// <param name="item"></param>
/// <returns></returns>
public bool TryRemove(Guid id, out T? item)
{
Monitor.Enter(_syncRoot);
try
{
return TryGetValue(id, out item) && Remove(item);
}
finally
{
Monitor.Exit(_syncRoot);
}
}
/// <summary>
/// RemoveMessageTag
/// </summary>
/// <param name="index"></param>
/// <exception cref="ArgumentException"></exception>
/// /// <exception cref="ArgumentNullException"></exception>
/// <exception cref="NullReferenceException"></exception>
public void RemoveAt(int index)
{
Monitor.Enter(_syncRoot);
try
{
var currentItem = InnerList[index];
if (currentItem.Id.IsNullOrEmpty()) throw new ArgumentNullException(nameof(currentItem), $@"RemoveAt->item.Id.IsNullOrEmpty(); index: {index}");
TrackingItems.AddTrackingItem(TrackingState.Remove, currentItem, currentItem);
InnerList.RemoveAt(index);
}
finally
{
Monitor.Exit(_syncRoot);
}
}
public async Task RemoveAt(int index, bool autoSave)
{
Monitor.Enter(_syncRoot);
try
{
var currentItem = InnerList[index];
RemoveAt(index);
if (autoSave)
{
await SaveItem(currentItem, TrackingState.Remove);
}
}
finally
{
Monitor.Exit(_syncRoot);
}
}
/// <summary>
///
/// </summary>
/// <returns></returns>
public List<TrackingItem<T>> GetTrackingItems()
{
Monitor.Enter(_syncRoot);
try
{
return TrackingItems.ToList();
}
finally
{
Monitor.Exit(_syncRoot);
}
}
public void SetTrackingStateToUpdate(T item)
{
Monitor.Enter(_syncRoot);
try
{
if (TrackingItems.TryGetTrackingItem(item.Id, out var trackingItem))
{
if (trackingItem.TrackingState != TrackingState.Add)
trackingItem.TrackingState = TrackingState.Update;
return;
}
if (!TryGetValue(item.Id, out var originalItem)) return;
TrackingItems.AddTrackingItem(TrackingState.Update, item, originalItem);
}
finally
{
Monitor.Exit(_syncRoot);
}
}
/// <summary>
///
/// </summary>
/// <param name="id"></param>
/// <param name="trackingItem"></param>
/// <returns></returns>
public bool TryGetTrackingItem(Guid id, [NotNullWhen(true)] out TrackingItem<T>? trackingItem)
{
Monitor.Enter(_syncRoot);
try
{
return TrackingItems.TryGetTrackingItem(id, out trackingItem);
}
finally
{
Monitor.Exit(_syncRoot);
}
}
/// <summary>
///
/// </summary>
/// <returns>Unsaved items</returns>
public async Task<List<TrackingItem<T>>> SaveChanges()
{
Monitor.Enter(_syncRoot);
try
{
foreach (var trackingItem in TrackingItems.ToList())
{
try
{
await SaveTrackingItemUnsafe(trackingItem);
}
catch(Exception ex)
{
TryRollbackItem(trackingItem.CurrentValue.Id, out _);
}
}
return TrackingItems.ToList();
}
finally
{
Monitor.Exit(_syncRoot);
}
}
public async Task SaveChangesAsync()
{
Monitor.Enter(_syncRoot);
try
{
foreach (var trackingItem in TrackingItems.ToList())
{
try
{
await SaveTrackingItemUnsafeAsync(trackingItem);
}
catch(Exception ex)
{
TryRollbackItem(trackingItem.CurrentValue.Id, out _);
}
}
}
finally
{
Monitor.Exit(_syncRoot);
}
}
/// <summary>
///
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
public async Task<T> SaveItem(Guid id)
{
Monitor.Enter(_syncRoot);
try
{
T resultItem = null!;
if (TryGetTrackingItem(id, out var trackingItem))
resultItem = await SaveTrackingItemUnsafe(trackingItem);
if (resultItem == null) throw new NullReferenceException($"SaveItem; resultItem == null");
return resultItem;
}
finally
{
Monitor.Exit(_syncRoot);
}
}
public async Task<T> SaveItem(Guid id, TrackingState trackingState)
{
//Monitor.Enter(_syncRoot);
try
{
T resultItem = null!;
if (TryGetValue(id, out var item))
resultItem = await SaveItem(item, trackingState);
if (resultItem == null) throw new NullReferenceException($"SaveItem; resultItem == null");
return resultItem;
}
finally
{
//Monitor.Exit(_syncRoot);
}
}
public Task<T> SaveItem(T item, TrackingState trackingState) => SaveItemUnsafe(item, trackingState);
protected Task<T> SaveTrackingItemUnsafe(TrackingItem<T> trackingItem)
=> SaveItemUnsafe(trackingItem.CurrentValue, trackingItem.TrackingState);
protected Task SaveTrackingItemUnsafeAsync(TrackingItem<T> trackingItem)
=> SaveItemUnsafeAsync(trackingItem.CurrentValue, trackingItem.TrackingState);
protected Task<T> SaveItemUnsafe(T item, TrackingState trackingState)
{
var messageTag = SignalRCrudTags.GetMessageTagByTrackingState(trackingState);
if (messageTag == AcSignalRTags.None) throw new ArgumentException($"SaveItemUnsafe; messageTag == SignalRTags.None");
return SignalRClient.PostDataAsync(messageTag, item).ContinueWith(x =>
{
if (x.Result == null)
{
if (TryRollbackItem(item.Id, out _)) return item;
throw new NullReferenceException($"SaveItemUnsafe; result == null");
}
ProcessSavedResponseItem(x.Result, trackingState);
return x.Result;
});
}
protected Task SaveItemUnsafeAsync(T item, TrackingState trackingState)
{
var messageTag = SignalRCrudTags.GetMessageTagByTrackingState(trackingState);
if (messageTag == AcSignalRTags.None) return Task.CompletedTask;
return SignalRClient.PostDataAsync(messageTag, item, response =>
{
Monitor.Enter(_syncRoot);
try
{
if (response.Status != SignalResponseStatus.Success || response.ResponseData == null)
{
if (TryRollbackItem(item.Id, out _)) return Task.CompletedTask;
throw new NullReferenceException($"SaveItemUnsafeAsync; result.Status != SignalResponseStatus.Success || result.ResponseData == null; Status: {SignalResponseStatus.Success}");
}
return ProcessSavedResponseItem(response.ResponseData, trackingState);
}
finally
{
Monitor.Exit(_syncRoot);
}
});
}
private Task ProcessSavedResponseItem(T? resultItem, TrackingState trackingState)
{
if (resultItem == null) return Task.CompletedTask;
if (TryGetTrackingItem(resultItem.Id, out var trackingItem))
TrackingItems.Remove(trackingItem);
if (TryGetIndex(resultItem.Id, out var index))
InnerList[index] = resultItem;
var eventArgs = new ItemChangedEventArgs<T>(resultItem, trackingState);
if (OnDataSourceItemChanged != null) return OnDataSourceItemChanged.Invoke(eventArgs);
return Task.CompletedTask;
}
protected void RollbackItemUnsafe(TrackingItem<T> trackingItem)
{
if (TryGetIndex(trackingItem.CurrentValue.Id, out var index))
{
if (trackingItem.TrackingState == TrackingState.Add) InnerList.RemoveAt(index);
else InnerList[index] = trackingItem.OriginalValue!;
}
else if (trackingItem.TrackingState != TrackingState.Add)
InnerList.Add(trackingItem.OriginalValue!);
TrackingItems.Remove(trackingItem);
}
public bool TryRollbackItem(Guid id, out T? originalValue)
{
Monitor.Enter(_syncRoot);
try
{
if (TryGetTrackingItem(id, out var trackingItem))
{
originalValue = trackingItem.OriginalValue;
RollbackItemUnsafe(trackingItem);
return true;
}
originalValue = null;
return false;
}
finally
{
Monitor.Exit(_syncRoot);
}
}
public void Rollback()
{
Monitor.Enter(_syncRoot);
try
{
foreach (var trackingItem in TrackingItems.ToList())
RollbackItemUnsafe(trackingItem);
}
finally
{
Monitor.Exit(_syncRoot);
}
}
public int Count
{
get
{
Monitor.Enter(_syncRoot);
try
{
return InnerList.Count;
}
finally
{
Monitor.Exit(_syncRoot);
}
}
}
public void Clear() => Clear(true);
public void Clear(bool clearChangeTracking)
{
Monitor.Enter(_syncRoot);
try
{
if (clearChangeTracking) TrackingItems.Clear();
InnerList.Clear();
}
finally
{
Monitor.Exit(_syncRoot);
}
}
public int IndexOf(Guid id)
{
Monitor.Enter(_syncRoot);
try
{
return InnerList.FindIndex(x => x.Id == id);
}
finally
{
Monitor.Exit(_syncRoot);
}
}
public int IndexOf(T item) => IndexOf(item.Id);
public bool TryGetIndex(Guid id, out int index) => (index = IndexOf(id)) > -1;
public bool Contains(T item) => IndexOf(item) > -1;
public bool TryGetValue(Guid id, [NotNullWhen(true)] out T? item)
{
Monitor.Enter(_syncRoot);
try
{
item = InnerList.FirstOrDefault(x => x.Id == id);
return item != null;
}
finally
{
Monitor.Exit(_syncRoot);
}
}
public void CopyTo(T[] array) => CopyTo(array, 0);
public void CopyTo(T[] array, int arrayIndex)
{
Monitor.Enter(_syncRoot);
try
{
InnerList.CopyTo(array, arrayIndex);
}
finally
{
Monitor.Exit(_syncRoot);
}
}
public int BinarySearch(int index, int count, T item, IComparer<T>? comparer)
{
throw new NotImplementedException($"BinarySearch");
if (index < 0)
throw new ArgumentOutOfRangeException(nameof(index));
if (count < 0)
throw new ArgumentOutOfRangeException(nameof(count));
if (Count - index < count)
throw new ArgumentException("Invalid length");
//Monitor.Enter(_syncRoot);
//try
//{
// return InnerList.BinarySearch(index, count, item, comparer);
//}
//finally
//{
// Monitor.Exit(_syncRoot);
//}
}
public int BinarySearch(T item) => BinarySearch(0, Count, item, null);
public int BinarySearch(T item, IComparer<T>? comparer) => BinarySearch(0, Count, item, comparer);
public IEnumerator<T> GetEnumerator()
{
Monitor.Enter(_syncRoot);
try
{
//return InnerList.ToList().GetEnumerator();
return InnerList.GetEnumerator();
}
finally
{
Monitor.Exit(_syncRoot);
}
}
public ReadOnlyCollection<T> AsReadOnly() => new(this);
private static bool IsCompatibleObject(object? value) => (value is T) || (value == null && default(T) == null);
#region IList, ICollection
bool IList.IsReadOnly => false;
object? IList.this[int index]
{
get => this[index];
set
{
if (default(T) != null && value == null) throw new NullReferenceException(nameof(value));
try
{
this[index] = (T)value!;
}
catch (InvalidCastException)
{
throw new InvalidCastException(nameof(value));
}
}
}
int IList.Add(object? item)
{
if (default(T) != null && item == null) throw new NullReferenceException(nameof(item));
try
{
Add((T)item!);
}
catch (InvalidCastException)
{
throw new InvalidCastException(nameof(item));
}
return Count - 1;
}
void IList.Clear() => Clear(true);
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
bool IList.Contains(object? item) => IsCompatibleObject(item) && Contains((T)item!);
int IList.IndexOf(object? item) => (IsCompatibleObject(item)) ? IndexOf((T)item!) : -1;
void IList.Insert(int index, object? item)
{
if (default(T) != null && item == null) throw new NullReferenceException(nameof(item));
try
{
Insert(index, (T)item!);
}
catch (InvalidCastException)
{
throw new InvalidCastException(nameof(item));
}
}
void IList.Remove(object? item)
{
if (IsCompatibleObject(item)) Remove((T)item!);
}
void ICollection<T>.Clear() => Clear(true);
void ICollection.CopyTo(Array array, int arrayIndex)
{
if ((array != null) && (array.Rank != 1))
{
throw new ArgumentException();
}
try
{
Monitor.Enter(_syncRoot);
try
{
//TODO: _list.ToArray() - ez nem az igazi... - J.
Array.Copy(InnerList.ToArray(), 0, array!, arrayIndex, InnerList.Count);
}
finally
{
Monitor.Exit(_syncRoot);
}
}
catch (ArrayTypeMismatchException)
{
throw new ArrayTypeMismatchException();
}
}
int ICollection.Count => Count;
int ICollection<T>.Count => Count;
bool ICollection<T>.IsReadOnly => false;
void IList<T>.RemoveAt(int index) => RemoveAt(index);
int IReadOnlyCollection<T>.Count => Count;
#endregion IList, ICollection
}
public class ItemChangedEventArgs<T> where T : IId<Guid>
{
internal ItemChangedEventArgs(T item, TrackingState trackingState)
{
Item = item;
TrackingState = trackingState;
}
public T Item { get; }
public TrackingState TrackingState { get; }
}
}

View File

@ -1,195 +0,0 @@
using System.Linq.Expressions;
using System.Security.Claims;
using AyCode.Core;
using AyCode.Core.Extensions;
using AyCode.Core.Helpers;
using AyCode.Core.Loggers;
using AyCode.Models.Server.DynamicMethods;
using AyCode.Services.SignalRs;
using MessagePack;
using MessagePack.Resolvers;
using Microsoft.AspNetCore.SignalR;
using Microsoft.Extensions.Configuration;
namespace AyCode.Services.Server.SignalRs;
public abstract class AcWebSignalRHubBase<TSignalRTags, TLogger>(IConfiguration configuration, TLogger logger)
: Hub<IAcSignalRHubItemServer>, IAcSignalRHubServer where TSignalRTags : AcSignalRTags where TLogger : AcLoggerBase
{
protected readonly List<AcDynamicMethodCallModel<SignalRAttribute>> DynamicMethodCallModels = [];
//protected readonly TIAM.Core.Loggers.Logger<AcWebSignalRHubBase<TSignalRTags>> Logger = new(logWriters.ToArray());
protected TLogger Logger = logger;
protected IConfiguration Configuration = configuration;
//private readonly ServiceProviderAPIController _serviceProviderApiController;
//private readonly TransferDataAPIController _transferDataApiController;
//_serviceProviderApiController = serviceProviderApiController;
//_transferDataApiController = transferDataApiController;
// https://docs.microsoft.com/en-us/aspnet/core/signalr/hubs?view=aspnetcore-3.1#strongly-typed-hubs
public override async Task OnConnectedAsync()
{
Logger.Debug($"Server OnConnectedAsync; ConnectionId: {Context.ConnectionId}; UserIdentifier: {Context.UserIdentifier}");
LogContextUserNameAndId();
await base.OnConnectedAsync();
//Clients.Caller.ConnectionId = Context.ConnectionId;
//Clients.Caller.UserIdentifier = Context.UserIdentifier;
}
public override async Task OnDisconnectedAsync(Exception? exception)
{
var logText = $"Server OnDisconnectedAsync; ConnectionId: {Context.ConnectionId}; UserIdentifier: {Context.UserIdentifier};";
if (exception == null) Logger.Debug(logText);
else Logger.Error(logText, exception);
LogContextUserNameAndId();
await base.OnDisconnectedAsync(exception);
}
public virtual Task OnReceiveMessage(int messageTag, byte[]? message, int? requestId)
{
return ProcessOnReceiveMessage(messageTag, message, requestId, null);
}
protected async Task ProcessOnReceiveMessage(int messageTag, byte[]? message, int? requestId, Func<string, Task>? notFoundCallback)
{
var tagName = ConstHelper.NameByValue<TSignalRTags>(messageTag);
var logText = $"Server OnReceiveMessage; {nameof(requestId)}: {requestId}; ConnectionId: {Context.ConnectionId}; {tagName}";
if (message is { Length: 0 }) Logger.Warning($"message.Length == 0! {logText}");
else Logger.Info($"[{message?.Length:N0}b] {logText}");
try
{
if (AcDomain.IsDeveloperVersion) LogContextUserNameAndId();
foreach (var methodsByDeclaringObject in DynamicMethodCallModels)
{
if (!methodsByDeclaringObject.MethodsByMessageTag.TryGetValue(messageTag, out var methodInfoModel)) continue;
object[]? paramValues = null;
logText = $"Found dynamic method for the tag! method: {methodsByDeclaringObject.InstanceObject.GetType().Name}.{methodInfoModel.MethodInfo.Name}";
if (methodInfoModel.ParamInfos is { Length: > 0 })
{
Logger.Debug($"{logText}({string.Join(", ", methodInfoModel.ParamInfos.Select(x => x.Name))}); {tagName}");
paramValues = new object[methodInfoModel.ParamInfos.Length];
var firstParamType = methodInfoModel.ParamInfos[0].ParameterType;
if (methodInfoModel.ParamInfos.Length > 1 || firstParamType == typeof(string) || firstParamType.IsEnum || firstParamType.IsValueType || firstParamType == typeof(DateTime))
{
var msg = message!.MessagePackTo<SignalPostJsonDataMessage<IdMessage>>();
for (var i = 0; i < msg.PostData.Ids.Count; i++)
{
//var obj = (string)msg.PostData.Ids[i];
//if (msg.PostData.Ids[i] is Guid id)
//{
// if (id.IsNullOrEmpty()) throw new NullReferenceException($"PostData.Id.IsNullOrEmpty(); Ids: {msg.PostData.Ids}");
// paramValues[i] = id;
//}
//else if (Guid.TryParse(obj, out id))
//{
// if (id.IsNullOrEmpty()) throw new NullReferenceException($"PostData.Id.IsNullOrEmpty(); Ids: {msg.PostData.Ids}");
// paramValues[i] = id;
//}
//else if (Enum.TryParse(methodInfoModel.ParameterType, obj, out var enumObj))
//{
// paramValues[i] = enumObj;
//}
//else paramValues[i] = Convert.ChangeType(obj, methodInfoModel.ParameterType);
var obj = msg.PostData.Ids[i];
//var config = new MapperConfiguration(cfg =>
//{
// cfg.CreateMap(obj.GetType(), methodInfoModel.ParameterType);
//});
//var mapper = new Mapper(config);
//paramValues[i] = mapper.Map(obj, methodInfoModel.ParameterType);
//paramValues[i] = obj;
var a = Array.CreateInstance(methodInfoModel.ParamInfos[i].ParameterType, 1);
if (methodInfoModel.ParamInfos[i].ParameterType == typeof(Expression))
{
//var serializer = new ExpressionSerializer(new JsonSerializer());
//paramValues[i] = serializer.DeserializeText((string)(obj.JsonTo(a.GetType()) as Array)?.GetValue(0)!);
}
else paramValues[i] = (obj.JsonTo(a.GetType()) as Array)?.GetValue(0)!;
}
}
else paramValues[0] = message!.MessagePackTo<SignalPostJsonDataMessage<object>>(MessagePackSerializerOptions.Standard).PostDataJson.JsonTo(firstParamType)!;
}
else Logger.Debug($"{logText}(); {tagName}");
var responseDataJson = new SignalResponseJsonMessage(messageTag, SignalResponseStatus.Success, methodInfoModel.MethodInfo.InvokeMethod(methodsByDeclaringObject.InstanceObject, paramValues));
var responseDataJsonKiloBytes = System.Text.Encoding.Unicode.GetByteCount(responseDataJson.ResponseData!) / 1024;
//File.WriteAllText(Path.Combine("h:", $"{requestId}.json"), responseDataJson.ResponseData);
Logger.Info($"[{responseDataJsonKiloBytes}kb] responseData serialized to json");
await ResponseToCaller(messageTag, responseDataJson, requestId);
return;
}
Logger.Debug($"Not found dynamic method for the tag! {tagName}");
notFoundCallback?.Invoke(tagName);
}
catch (Exception ex)
{
Logger.Error($"Server OnReceiveMessage; {ex.Message}; {tagName}", ex);
}
await ResponseToCaller(messageTag, new SignalResponseJsonMessage(messageTag, SignalResponseStatus.Error), requestId);
}
protected async Task ResponseToCaller(int messageTag, ISignalRMessage message, int? requestId)
=> await SendMessageToClient(Clients.Caller, messageTag, message, requestId);
public async Task SendMessageToUserId(string userId, int messageTag, ISignalRMessage message, int? requestId)
=> await SendMessageToClient(Clients.User(userId), messageTag, message, requestId);
public async Task SendMessageToConnectionId(string connectionId, int messageTag, ISignalRMessage message, int? requestId)
=> await SendMessageToClient(Clients.Client(Context.ConnectionId), messageTag, message, requestId);
protected async Task SendMessageToClient(IAcSignalRHubItemServer sendTo, int messageTag, ISignalRMessage message, int? requestId = null)
{
var responseDataMessagePack = message.ToMessagePack(ContractlessStandardResolver.Options);
Logger.Info($"[{(responseDataMessagePack.Length/1024)}kb] Server sending responseDataMessagePack to client; {nameof(requestId)}: {requestId}; ConnectionId: {Context.ConnectionId}; {ConstHelper.NameByValue<TSignalRTags>(messageTag)}");
await sendTo.OnReceiveMessage(messageTag, responseDataMessagePack, requestId);
}
public async Task SendMessageToGroup(string groupId, int messageTag, string message)
{
//await Clients.Group(groupId).Post("", messageTag, message);
}
//[Conditional("DEBUG")]
private void LogContextUserNameAndId()
{
string? userName = null;
var userId = Guid.Empty;
if (Context.User != null)
{
userName = Context.User.Identity?.Name;
Guid.TryParse((string?)Context.User.FindFirstValue(ClaimTypes.NameIdentifier), out userId);
}
if (AcDomain.IsDeveloperVersion) Logger.WarningConditional($"SignalR.Context; userName: {userName}; userId: {userId}");
else Logger.Debug($"SignalR.Context; userName: {userName}; userId: {userId}");
}
}

View File

@ -1,18 +0,0 @@
using System.Reflection;
using System.Runtime.CompilerServices;
namespace AyCode.Services.Server.SignalRs;
public static class ExtensionMethods
{
public static object? InvokeMethod(this MethodInfo methodInfo, object obj, params object[]? parameters)
{
if (methodInfo.GetCustomAttribute(typeof(AsyncStateMachineAttribute)) is AsyncStateMachineAttribute isAsyncTask)
{
dynamic awaitable = methodInfo.Invoke(obj, parameters)!;
return awaitable.GetAwaiter().GetResult();
}
return methodInfo.Invoke(obj, parameters);
}
}

View File

@ -1,6 +0,0 @@
namespace AyCode.Services.Server.SignalRs;
public interface IAcSessionItem<TSessionItemId> where TSessionItemId : notnull
{
public TSessionItemId SessionId { get; set; }
}

View File

@ -1,13 +0,0 @@
using AyCode.Services.SignalRs;
namespace AyCode.Services.Server.SignalRs;
public interface IAcSignalRHubItemServer : IAcSignalRHubBase
{
//string ConnectionId { get; set; }
//string? UserIdentifier { get; set; }
}
public interface IAcSignalRHubServer : IAcSignalRHubBase //: IAcSignalRHubBase
{
}

View File

@ -1,19 +0,0 @@
namespace AyCode.Services.Server.SignalRs;
public class SignalRRequestModel
{
public DateTime RequestDateTime;
public DateTime ResponseDateTime;
public object? ResponseByRequestId = null;
public SignalRRequestModel()
{
RequestDateTime = DateTime.UtcNow;
}
public SignalRRequestModel(object responseByRequestId) : this()
{
ResponseByRequestId = responseByRequestId;
}
}

View File

@ -1,46 +0,0 @@
using System.Reflection;
using AyCode.Core.Extensions;
namespace AyCode.Services.Server.SignalRs;
public static class TrackingItemHelpers
{
public static T JsonClone<T>(T source) => source.ToJson().JsonTo<T>()!;
public static T ReflectionClone<T>(T source)
{
var type = source!.GetType();
if (type.IsPrimitive || typeof(string) == type)
return source;
if (type.IsArray)
{
var elementType = Type.GetType(type.FullName!.Replace("[]", string.Empty))!;
var array = (source as Array)!;
var cloned = Array.CreateInstance(elementType, array.Length);
for (var i = 0; i < array.Length; i++)
cloned.SetValue(ReflectionClone(array.GetValue(i)), i);
return (T)Convert.ChangeType(cloned, type);
}
var clone = Activator.CreateInstance(type);
while (type != null && type != typeof(object))
{
foreach (var field in type.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance))
{
var fieldValue = field.GetValue(source);
if (fieldValue == null) continue;
field.SetValue(clone, ReflectionClone(fieldValue));
}
type = type.BaseType;
}
return (T)clone!;
}
}

View File

@ -1,20 +1,16 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
</PropertyGroup>
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<Import Project="..//AyCode.Core.targets" />
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="9.0.8" />
<PackageReference Include="Microsoft.AspNetCore.SignalR.Common" Version="9.0.8" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\AyCode.Core\AyCode.Core.csproj" />
<ProjectReference Include="..\AyCode.Entities\AyCode.Entities.csproj" />
<ProjectReference Include="..\AyCode.Interfaces\AyCode.Interfaces.csproj" />
<ProjectReference Include="..\AyCode.Models\AyCode.Models.csproj" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\AyCode.Core\AyCode.Core.csproj" />
<ProjectReference Include="..\AyCode.Entities\AyCode.Entities.csproj" />
<ProjectReference Include="..\AyCode.Interfaces\AyCode.Interfaces.csproj" />
<ProjectReference Include="..\AyCode.Models\AyCode.Models.csproj" />
</ItemGroup>
</Project>

View File

@ -1,74 +0,0 @@
using AyCode.Core.Enums;
using AyCode.Core.Loggers;
using AyCode.Entities;
using System.Net;
using System.Net.Http.Json;
using AyCode.Core.Helpers;
namespace AyCode.Services.Loggers;
public abstract class AcHttpClientLogItemWriter<TLogItem> : AcLogItemWriterBase<TLogItem>, IAcLogWriterClientBase where TLogItem : class, IAcLogItemClient
{
protected string _url;
protected HttpClient _httpClient;
protected HttpClientHandler _httpClientHandler;
protected AcHttpClientLogItemWriter(HttpClient httpClient, string url) : base(AppType.Web, LogLevel.Detail)
{
//_httpClient = httpClient;
_url = url;
Initialize(httpClient.BaseAddress, httpClient.DefaultRequestVersion, httpClient.DefaultVersionPolicy);
}
protected AcHttpClientLogItemWriter(string url, string? categoryName = null) : base(categoryName)
{
_url = url;
Initialize(null, HttpVersion.Version20, HttpVersionPolicy.RequestVersionOrHigher);
}
protected AcHttpClientLogItemWriter(string url, AppType appType, LogLevel logLevel, string? categoryName = null) : base(appType, logLevel, categoryName)
{
_url = url;
Initialize(null, HttpVersion.Version20, HttpVersionPolicy.RequestVersionOrHigher);
}
private void Initialize(Uri? baseAddress, Version defaultRequestVersion, HttpVersionPolicy defaultVersionPolicy)
{
_httpClientHandler = new HttpClientHandler();
_httpClient = new HttpClient(_httpClientHandler, false);
_httpClient.BaseAddress = baseAddress;
_httpClient.DefaultRequestVersion = defaultRequestVersion;
_httpClient.DefaultVersionPolicy = defaultVersionPolicy;
}
public override void Write(AppType appType, LogLevel logLevel, string? logText, string? callerMemberName, string? categoryName, string? errorType, string? exMessage)
=> WriteLogItem(CreateLogItem(DateTime.UtcNow, appType, Environment.CurrentManagedThreadId, logLevel, logText, callerMemberName, categoryName, errorType, exMessage));
protected override void WriteLogItemCallback(TLogItem logItem)
{
//logItem.ThreadId = Environment.CurrentManagedThreadId;
_httpClient.PostAsJsonAsync(_url, logItem).Forget();
}
//protected override void WriteLogItem(TLogItem logItem, Action? callback = null)
//{
// //throw new NotImplementedException();
// base.WriteLogItem(logItem, () =>
// {
// //http.PostAsJson(url, Param);
// //_httpClient.Send()
// });
//}
//protected override void WriteLogItem(TLogItem logItem, Action<IEnumerable<TLogItem>>? callback = null)
//{
// throw new NotImplementedException();
// base.WriteLogItem(logItem, logItems =>
// {
// //_httpClient.Send()
// });
//}
}

View File

@ -1,6 +0,0 @@
using AyCode.Core.Loggers;
namespace AyCode.Services.Loggers;
public interface IAcLogWriterClientBase : IAcLogWriterBase
{}

View File

@ -1,18 +0,0 @@
using AyCode.Interfaces.Addresses;
using AyCode.Interfaces.Logins;
using AyCode.Interfaces.Profiles;
using AyCode.Interfaces.ServiceProviders;
using AyCode.Interfaces.Users;
namespace AyCode.Services.Logins;
public abstract class AcLoginServiceBase<TUser, TProfile, TCompany, TUserToServiceProvider, TProfileAddress> : IAcLoginServiceBase<TUser, TProfile, TCompany, TUserToServiceProvider, TProfileAddress>
where TUser : class, IAcUser<TProfile, TCompany, TUserToServiceProvider, TProfileAddress>
where TProfile : class, IAcProfile<TProfileAddress>
where TCompany : class, IAcCompanyBase
where TUserToServiceProvider : class, IAcUserToCompanyBase
where TProfileAddress : class, IAcAddress
{
public virtual bool IsLoggedIn => LoggedInUser != null;
public virtual TUser? LoggedInUser { get; protected set; }
}

View File

@ -1,79 +0,0 @@
using AyCode.Core.Consts;
using AyCode.Core.Helpers;
using AyCode.Interfaces.Addresses;
using AyCode.Interfaces.Logins;
using AyCode.Interfaces.Profiles;
using AyCode.Interfaces.ServiceProviders;
using AyCode.Interfaces.Users;
namespace AyCode.Services.Logins;
public class AcLoginServiceClient<TUser, TProfile, TCompany, TUserToServiceProvider, TProfileAddress>
: AcLoginServiceBase<TUser, TProfile, TCompany, TUserToServiceProvider, TProfileAddress>, IAcLoginServiceClient<TUser, TProfile, TCompany, TUserToServiceProvider, TProfileAddress>
where TUser : class, IAcUser<TProfile, TCompany, TUserToServiceProvider, TProfileAddress>
where TProfile : class, IAcProfile<TProfileAddress>
where TCompany : class, IAcCompanyBase
where TUserToServiceProvider : class, IAcUserToCompanyBase
where TProfileAddress : class, IAcAddress
{
public virtual TUser? Login(string email, string password, out string accessToken)
{
throw new NotImplementedException();
}
public virtual Task<TUser?> LoginAsync(string email, string password)
{
return TaskHelper.ToThreadPoolTask(() => Login(email, password, out _));
}
public virtual bool Logout()
{
throw new NotImplementedException();
}
public virtual Task<bool> LogoutAsync()
{
return TaskHelper.ToThreadPoolTask(Logout);
}
public virtual AcErrorCode Registration(string email, string password, string? phoneNumber = null, Guid? referralId = null)
{
throw new NotImplementedException();
}
public virtual AcErrorCode Registration(Guid userId, string email, string password, string? phoneNumber = null, Guid? referralId = null)
{
throw new NotImplementedException();
}
public virtual Task<AcErrorCode> RegistrationAsync(string email, string password, string? phoneNumber = null, Guid? referralId = null)
{
return TaskHelper.ToThreadPoolTask(() => Registration(email, password, phoneNumber));
}
public virtual Task<AcErrorCode> RegistrationAsync(Guid userId, string email, string password, string? phoneNumber = null, Guid? referralId = null)
{
throw new NotImplementedException();
}
public virtual AcErrorCode ChangePassword(Guid userId, string oldPassword, string newPassword)
{
throw new NotImplementedException();
}
public virtual Task<AcErrorCode> ChangePasswordAsync(Guid userId, string oldPassword, string newPassword)
{
throw new NotImplementedException();
}
public AcErrorCode ForgotPassword(string email, string newPassword)
{
throw new NotImplementedException();
}
public async Task<AcErrorCode> ForgotPasswordAsync(string email, string newPassword)
{
throw new NotImplementedException();
}
}

View File

@ -1,6 +0,0 @@
namespace AyCode.Services.SignalRs;
public class AcSignalRTags
{
public const int None = 0;
}

View File

@ -1,7 +0,0 @@
namespace AyCode.Services.SignalRs;
public interface IAcSignalRHubBase
{
//Task OnRequestMessage(int messageTag, int requestId);
Task OnReceiveMessage(int messageTag, byte[] message, int? requestId);
}

View File

@ -1,198 +0,0 @@
using AyCode.Core.Extensions;
using MessagePack;
using Newtonsoft.Json.Linq;
using System.Text.RegularExpressions;
using AyCode.Core.Interfaces;
using System.Collections.Generic;
using System.Linq.Expressions;
namespace AyCode.Services.SignalRs;
public class IdMessage
{
public List<string> Ids { get; private set; } = [];
public IdMessage()
{
}
public IdMessage(IEnumerable<object> ids) : this()
{
//Ids.AddRange(ids);
Ids.AddRange(ids.Select(x =>
{
string item;
//if (x is Expression expr)
//{
// string aa = string.Empty;
// var serializer = new ExpressionSerializer(new JsonSerializer());
// try
// {
// aa = serializer.SerializeText(expr);
// }
// catch(Exception ex)
// {
// Console.WriteLine(ex);
// }
// item = (new[] { aa }).ToJson();
//}
//else
item = (new[] { x }).ToJson();
return item;
}));
}
public IdMessage(object id) : this(new object[] { id })
{
}
public IdMessage(IEnumerable<Guid> ids) : this(ids.Cast<object>().ToArray())
{
}
public override string ToString()
{
return string.Join("; ", Ids);
}
}
public class SignalPostJsonMessage
{
[Key(0)]
public string PostDataJson { get; set; }
public SignalPostJsonMessage()
{}
protected SignalPostJsonMessage(string postDataJson) => PostDataJson = postDataJson;
}
[MessagePackObject]
public class SignalPostJsonDataMessage<TPostDataType> : SignalPostJsonMessage, ISignalPostMessage<TPostDataType> //where TPostDataType : class
{
[IgnoreMember]
private TPostDataType? _postData;
[IgnoreMember]
public TPostDataType PostData
{
get
{
return _postData ??= PostDataJson.JsonTo<TPostDataType>()!;
}
private init
{
_postData = value;
PostDataJson = _postData.ToJson();
}
}
public SignalPostJsonDataMessage() : base()
{}
public SignalPostJsonDataMessage(TPostDataType postData) => PostData = postData;
public SignalPostJsonDataMessage(string postDataJson) : base(postDataJson)
{}
}
[MessagePackObject]
public class SignalPostMessage<TPostData>(TPostData postData) : ISignalPostMessage<TPostData>
{
[Key(0)]
public TPostData? PostData { get; set; } = postData;
}
public interface ISignalPostMessage<TPostData> : ISignalRMessage
{
TPostData? PostData { get; }
}
[MessagePackObject]
public class SignalRequestByIdMessage(Guid id) : ISignalRequestMessage<Guid>, IId<Guid>
{
[Key(0)]
public Guid Id { get; set; } = id;
}
public interface ISignalRequestMessage<TRequestId> : ISignalRMessage
{
TRequestId Id { get; set; }
}
public interface ISignalRMessage
{ }
[MessagePackObject]
public sealed class SignalResponseJsonMessage : ISignalResponseMessage<string>
{
[Key(0)] public int MessageTag { get; set; }
[Key(1)] public SignalResponseStatus Status { get; set; }
[Key(2)] public string? ResponseData { get; set; } = null;
public SignalResponseJsonMessage(){}
public SignalResponseJsonMessage(int messageTag, SignalResponseStatus status)
{
Status = status;
MessageTag = messageTag;
}
public SignalResponseJsonMessage(int messageTag, SignalResponseStatus status, object? responseData) : this(messageTag, status)
{
if (responseData is string stringdata)
ResponseData = stringdata;
else ResponseData = responseData.ToJson();
}
public SignalResponseJsonMessage(int messageTag, SignalResponseStatus status, string? responseDataJson) : this(messageTag, status)
{
ResponseData = responseDataJson;
}
}
[MessagePackObject]
public sealed class SignalResponseMessage<TResponseData>(int messageTag, SignalResponseStatus status, TResponseData? responseData) : ISignalResponseMessage<TResponseData>
{
[Key(0)] public int MessageTag { get; set; }
[Key(1)] public SignalResponseStatus Status { get; set; } = status;
[Key(2)] public TResponseData? ResponseData { get; set; } = responseData;
}
public sealed class SignalResponseStatusMessage(SignalResponseStatus status) : ISignalRMessage
{
public SignalResponseStatus Status { get; set; } = status;
}
//[MessagePackObject]
//public sealed class SignalResponseMessage(SignalResponseStatus status) : ISignalResponseMessage
//{
// [Key(0)]
// public SignalResponseStatus Status { get; set; } = status;
//}
public interface ISignalResponseMessage<TResponseData> : ISignalResponseMessage
{
TResponseData? ResponseData { get; set; }
}
public interface ISignalResponseMessage : ISignalRMessage
{
int MessageTag { get; set; }
SignalResponseStatus Status { get; set; }
}
public enum SignalResponseStatus : byte
{
Error = 0,
Success = 5
}
public interface IAcSignalRHubClient : IAcSignalRHubBase
{
Task SendMessageToServerAsync(int messageTag, ISignalRMessage? message, int? requestId );
//Task SendRequestToServerAsync(int messageTag, int requestId);
}

View File

@ -1,12 +0,0 @@
namespace AyCode.Services.SignalRs;
[AttributeUsage(AttributeTargets.Method)]
public class TagAttribute(int messageTag) : Attribute
{
public int MessageTag { get; init; } = messageTag;
}
[AttributeUsage(AttributeTargets.Method)]
public class SignalRAttribute(int messageTag) : TagAttribute(messageTag)
{
}

View File

@ -1,26 +0,0 @@
using AyCode.Core.Enums;
namespace AyCode.Services.SignalRs;
public sealed class SignalRCrudTags(int getAllTag, int getItemTag, int addTag, int updateTag, int removeTag)
{
public int GetAllMessageTag { get; } = getAllTag;
public int GetItemMessageTag { get; } = getItemTag;
public int AddMessageTag { get; } = addTag;
public int UpdateMessageTag { get; } = updateTag;
public int RemoveMessageTag { get; } = removeTag;
public int GetMessageTagByTrackingState(TrackingState trackingState)
{
return trackingState switch
{
TrackingState.None => 0,
TrackingState.Get => GetItemMessageTag,
TrackingState.GetAll => GetAllMessageTag,
TrackingState.Add => AddMessageTag,
TrackingState.Update => UpdateMessageTag,
TrackingState.Remove => RemoveMessageTag,
_ => throw new ArgumentOutOfRangeException()
};
}
}

View File

@ -1,7 +1,9 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
</PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<Import Project="..//AyCode.Core.targets" />
</Project>

View File

@ -1,17 +1,14 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
</PropertyGroup>
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<Import Project="..//AyCode.Core.targets" />
<ItemGroup>
<PackageReference Include="JetBrains.Annotations" Version="2025.2.1" />
<PackageReference Include="Microsoft.AspNetCore.Cryptography.KeyDerivation" Version="9.0.8" />
</ItemGroup>
<ItemGroup>
<Folder Include="Helpers\" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="JetBrains.Annotations" Version="2023.3.0" />
<PackageReference Include="Microsoft.AspNetCore.Cryptography.KeyDerivation" Version="8.0.1" />
</ItemGroup>
</Project>

View File

@ -0,0 +1,15 @@
using JetBrains.Annotations;
namespace AyCode.Utils.Extensions
{
public static class GuidExtensions
{
//[ContractAnnotation("=> true, result: notnull; => false, result: null")]
//[ContractAnnotation("true => null; false => notnull")]
public static bool IsNullOrEmpty(this Guid guid) => guid == Guid.Empty;
//[ContractAnnotation("=> true, result: notnull; => false, result: null")]
[ContractAnnotation("guid:null => true; guid:notnull <= false")]
public static bool IsNullOrEmpty(this Guid? guid) => guid == null || guid == Guid.Empty;
}
}

View File

@ -1,5 +1,4 @@
using System.Diagnostics.CodeAnalysis;
using System.Text;
using JetBrains.Annotations;
namespace AyCode.Utils.Extensions
@ -7,12 +6,11 @@ namespace AyCode.Utils.Extensions
public static class StringExtensions
{
//[ContractAnnotation("str:null => true; str:notnull <= false")]
//[return: NotNullIfNotNull(nameof(str))]
public static bool IsNullOrEmpty([NotNullWhen(false)] this string? str) => str == null || str.Length == 0;
[ContractAnnotation("str:null => true; str:notnull <= false")]
public static bool IsNullOrEmpty([NotNullWhen(returnValue: false)] this string str) => str == null || str.Length == 0;
//[ContractAnnotation("str:null => true;; str:notnull <= false")]
//[return: NotNullIfNotNull(nameof(str))]
public static bool IsNullOrWhiteSpace([NotNullWhen(false)] this string? str)
[ContractAnnotation("str:null => true;")]
public static bool IsNullOrWhiteSpace([NotNullWhen(returnValue: false)] this string str)
{
if (str == null || str.Length == 0) return true;
if (!char.IsWhiteSpace(str[0])) return false;
@ -38,41 +36,5 @@ namespace AyCode.Utils.Extensions
return char.ToUpper(str[0]) + str[1..];
}
//public static string MixCharacters(this string str1, string str2)
// => MixCharacters(str1?.ToCharArray(), str2?.ToCharArray());
//public static string MixCharacters(this char[] chars1, string str2)
// => MixCharacters(chars1, str2?.ToCharArray());
//public static string MixCharacters(this string str1, char[] chars2)
// => MixCharacters(str1?.ToCharArray(), chars2);
/// <summary>
/// Example : chars1=ABC, chars2=DEF ==> ADBECF
/// </summary>
/// <param name="firstChars"></param>
/// <param name="secondChars"></param>
/// <returns></returns>
public static string MixCharacters(this IEnumerable<char> firstChars, IEnumerable<char> secondChars)
{
var chars1 = firstChars as char[] ?? firstChars.ToArray();
var chars2 = secondChars as char[] ?? secondChars.ToArray();
if (chars1 is not { Length: > 0 }) return chars2.ToString() ?? string.Empty;
if (chars2 is not { Length: > 0 }) return chars1.ToString() ?? string.Empty;
var length = chars1.Length < chars2.Length ? chars1.Length : chars2.Length;
var builder = new StringBuilder(length * 2);
for (var i = 0; i < length; i++)
{
builder.Append(chars1[i]);
builder.Append(chars2[i]);
}
return builder.ToString();
}
}
}

View File

@ -0,0 +1,52 @@
using Microsoft.AspNetCore.Cryptography.KeyDerivation;
using System.Security.Cryptography;
namespace AyCode.Utils.Helpers
{
public class PasswordHasher
{
public string HashPassword(string password)
{
// Generate a random salt
byte[] salt = new byte[16];
using (var rng = RandomNumberGenerator.Create())
{
rng.GetBytes(salt);
}
// Hash the password with the salt
string hashedPassword = Convert.ToBase64String(KeyDerivation.Pbkdf2(
password: password,
salt: salt,
prf: KeyDerivationPrf.HMACSHA512,
iterationCount: 10000,
numBytesRequested: 32));
// Combine the salt and hashed password
string combinedHash = $"$bcrypt$v=1$salt={Convert.ToBase64String(salt)}$hash={hashedPassword}";
return combinedHash;
}
public bool VerifyPassword(string password, string hashedPassword)
{
// Extract the salt and hashed password from the combined hash
string[] parts = hashedPassword.Split('$');
byte[] salt = Convert.FromBase64String(parts[3]);
string storedHash = parts[5];
// Hash the provided password with the extracted salt
string hashedProvidedPassword = Convert.ToBase64String(KeyDerivation.Pbkdf2(
password: password,
salt: salt,
prf: KeyDerivationPrf.HMACSHA512,
iterationCount: 10000,
numBytesRequested: 32));
// Compare the hashed passwords
return storedHash == hashedProvidedPassword;
}
}
}