Login, Register, ProjectSalt, PasswordHash, meg a faszom sem tudja már...
This commit is contained in:
parent
a11c4e7644
commit
daf35ebf04
|
|
@ -11,8 +11,8 @@
|
|||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.9.0" />
|
||||
<PackageReference Include="MSTest.TestAdapter" Version="3.2.2" />
|
||||
<PackageReference Include="MSTest.TestFramework" Version="3.2.2" />
|
||||
<PackageReference Include="MSTest.TestAdapter" Version="3.3.1" />
|
||||
<PackageReference Include="MSTest.TestFramework" Version="3.3.1" />
|
||||
<PackageReference Include="coverlet.collector" Version="6.0.2">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
|
|
|
|||
|
|
@ -25,13 +25,15 @@ 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("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AyCode.Models", "AyCode.Models\AyCode.Models.csproj", "{21392620-7D0E-44B6-9485-93C57F944C20}"
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AyCode.Models", "AyCode.Models\AyCode.Models.csproj", "{21392620-7D0E-44B6-9485-93C57F944C20}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AyCode.Services", "AyCode.Services\AyCode.Services.csproj", "{58C8A6A7-D624-4E32-93B9-16B879405CAA}"
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AyCode.Services", "AyCode.Services\AyCode.Services.csproj", "{58C8A6A7-D624-4E32-93B9-16B879405CAA}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AyCode.Models.Server", "AyCode.Models.Server\AyCode.Models.Server.csproj", "{44CF90C8-76E4-4BD6-A957-E8F7AE019B06}"
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AyCode.Models.Server", "AyCode.Models.Server\AyCode.Models.Server.csproj", "{44CF90C8-76E4-4BD6-A957-E8F7AE019B06}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AyCode.Services.Server", "AyCode.Services.Server\AyCode.Services.Server.csproj", "{3C74C94F-2FEB-47F7-ABB3-B0C9CBCCC876}"
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AyCode.Services.Server", "AyCode.Services.Server\AyCode.Services.Server.csproj", "{3C74C94F-2FEB-47F7-ABB3-B0C9CBCCC876}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AyCode.Services.Server.Tests", "AyCode.Services.Server.Tests\AyCode.Services.Server.Tests.csproj", "{9AC9AF60-280A-4871-A7FA-69AB4D0C858A}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
|
|
@ -99,6 +101,10 @@ Global
|
|||
{3C74C94F-2FEB-47F7-ABB3-B0C9CBCCC876}.Debug|Any CPU.Build.0 = Debug|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}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{9AC9AF60-280A-4871-A7FA-69AB4D0C858A}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
|
|
|||
|
|
@ -10,4 +10,8 @@
|
|||
<ProjectReference Include="..\AyCode.Utils\AyCode.Utils.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Folder Include="Extensions\" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
|
|||
|
|
@ -1,7 +1,15 @@
|
|||
namespace AyCode.Core.Consts
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Security;
|
||||
using System.Text;
|
||||
using AyCode.Core.Extensions;
|
||||
|
||||
namespace AyCode.Core.Consts
|
||||
{
|
||||
public static class AcConst
|
||||
public abstract class AcConst
|
||||
{
|
||||
public static Guid ProjectId;
|
||||
public static string ProjectSalt;
|
||||
|
||||
public const int ImageUploadLimit = 4096 * 1024;
|
||||
|
||||
public static int ConsentCount = 1;
|
||||
|
|
@ -47,6 +55,7 @@
|
|||
/// MainScene, Lobby
|
||||
/// </summary>
|
||||
public static readonly Guid AnataCity;
|
||||
|
||||
public static readonly Guid PlayerGarage;
|
||||
public static readonly Guid PlayerWardrobe;
|
||||
public static readonly Guid LoadingId;
|
||||
|
|
@ -56,6 +65,7 @@
|
|||
/// RegionAdmin
|
||||
/// </summary>
|
||||
public static readonly Guid RegionAdminUserId;
|
||||
|
||||
public static readonly Guid RegionAdminPlayerId;
|
||||
|
||||
public static readonly Guid GamePlayer;
|
||||
|
|
@ -67,8 +77,13 @@
|
|||
|
||||
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(_tiamProjectIdString);
|
||||
ProjectSalt = GenerateProjectSalt(ProjectId.ToString("N"));
|
||||
|
||||
//var anataFolder = AcDomain.IsProductVersion ? "Anata" : "AnataDev";
|
||||
|
||||
//AnataRootCacheFolder = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "AyCode", anataFolder);
|
||||
|
|
@ -100,5 +115,30 @@
|
|||
//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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -53,5 +53,6 @@
|
|||
DomainIdNotFound = 43,
|
||||
|
||||
DisableAddUser = 44,
|
||||
PhoneNumberFormatIsNotValid = 45,
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,15 @@
|
|||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace AyCode.Core.Consts;
|
||||
|
||||
public static partial class AcRegExpression
|
||||
{
|
||||
public const string EmailMask = @"(\w|[.-])+@(\w|-)+\.(\w|-){2,4}";
|
||||
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})";
|
||||
|
||||
[GeneratedRegex(AcRegExpression.EmailMask)]
|
||||
public static partial Regex EmailRegex();
|
||||
|
||||
[GeneratedRegex(AcRegExpression.PhoneNumberMask)]
|
||||
public static partial Regex PhoneNumberRegex();
|
||||
}
|
||||
|
|
@ -1,10 +1,16 @@
|
|||
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);
|
||||
|
|
@ -45,12 +51,23 @@ namespace AyCode.Core.Consts
|
|||
acErrorCode = AcErrorCode.Unset;
|
||||
|
||||
//a@a.a -> length == 5
|
||||
var isValid = !email.IsNullOrWhiteSpace() && email.Length >= 5 && email.Contains('@') && email.Contains('.') && !email.Contains(' ');
|
||||
//var isValid = !email.IsNullOrWhiteSpace() && email.Length >= 5 && email.Contains('@') && email.Contains('.') && !email.Contains(' ');
|
||||
var isValid = AcRegExpression.EmailRegex().IsMatch(email);
|
||||
|
||||
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;
|
||||
|
|
|
|||
|
|
@ -11,8 +11,8 @@
|
|||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.9.0" />
|
||||
<PackageReference Include="MSTest.TestAdapter" Version="3.2.2" />
|
||||
<PackageReference Include="MSTest.TestFramework" Version="3.2.2" />
|
||||
<PackageReference Include="MSTest.TestAdapter" Version="3.3.1" />
|
||||
<PackageReference Include="MSTest.TestFramework" Version="3.3.1" />
|
||||
<PackageReference Include="coverlet.collector" Version="6.0.2">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
|
|
|
|||
|
|
@ -7,8 +7,8 @@
|
|||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="8.0.3" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Proxies" Version="8.0.3" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="8.0.4" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Proxies" Version="8.0.4" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ 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;
|
||||
|
|
|
|||
|
|
@ -32,40 +32,51 @@ namespace AyCode.Database.DataLayers.Users
|
|||
public TUser? GetUserByEmail(string email) => Session(x => x.GetUserByEmail(email));
|
||||
public Task<TUser?> GetUserByEmailAsync(string email) => SessionAsync(x => x.GetUserByEmail(email));
|
||||
|
||||
public Task<bool> AddUser(TUser user, string profileName, TProfileAddress address, string? firstName = null, string? lastName = null)
|
||||
public Task<bool> AddUserAsync(TUser user)
|
||||
{
|
||||
return TransactionAsync(ctx => ctx.AddUser(user));
|
||||
}
|
||||
|
||||
public Task<bool> AddUserAsync(TUser user, string profileName, TProfileAddress address, string? firstName = null, string? lastName = null)
|
||||
{
|
||||
return TransactionAsync(ctx =>
|
||||
{
|
||||
var profile = Activator.CreateInstance<TProfile>();
|
||||
|
||||
profile.Id = Guid.NewGuid();
|
||||
profile.Name = profileName;
|
||||
profile.FirstName = firstName;
|
||||
profile.LastName = lastName;
|
||||
profile.Address = address;
|
||||
|
||||
var profile = CreateProfile(profileName, address, firstName, lastName);
|
||||
user.Profile= profile;
|
||||
|
||||
if (ctx.AddUser(user)) return false;
|
||||
|
||||
ctx.SaveChanges();
|
||||
|
||||
return true;
|
||||
return ctx.AddUser(user);
|
||||
});
|
||||
}
|
||||
|
||||
public Task<bool> AddUser(TUser user)
|
||||
public bool AddUser(TUser user, string profileName, TProfileAddress address, string? firstName = null, string? lastName = null)
|
||||
{
|
||||
return TransactionAsync(ctx =>
|
||||
return Transaction(ctx =>
|
||||
{
|
||||
if (ctx.AddUser(user)) return false;
|
||||
|
||||
ctx.SaveChanges();
|
||||
var profile = CreateProfile(profileName, address, firstName, lastName);
|
||||
|
||||
return true;
|
||||
user.Profile = profile;
|
||||
|
||||
return ctx.AddUser(user);
|
||||
});
|
||||
}
|
||||
|
||||
private static TProfile CreateProfile(string profileName, TProfileAddress 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.RemoveUserAsync(user));
|
||||
public Task<bool> RemoveUserAsync(Guid userId) => TransactionAsync(ctx => ctx.RemoveUserAsync(userId));
|
||||
|
||||
//public UserToken CreateUserToken(Guid userId, string verificationToken)
|
||||
//{
|
||||
// UserToken userToken = null;
|
||||
|
|
|
|||
|
|
@ -13,8 +13,8 @@ public abstract class AcAddress : IAcAddress
|
|||
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; }
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
using AyCode.Interfaces.Profiles;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
using AyCode.Core.Extensions;
|
||||
using AyCode.Interfaces.Addresses;
|
||||
using AyCode.Utils.Extensions;
|
||||
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ namespace AyCode.Entities.Users
|
|||
[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; }
|
||||
|
||||
|
|
|
|||
|
|
@ -6,4 +6,16 @@
|
|||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Folder Include="Logins\" />
|
||||
</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\AyCode.Interfaces.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,20 @@
|
|||
using System.Net;
|
||||
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<TUser, TUserToken, TProfile, TServiceProvider, TUserToServiceProvider, TProfileAddress> : IAcLoginServiceCommon<TUser, TProfile, TServiceProvider, TUserToServiceProvider, TProfileAddress>
|
||||
|
||||
where TUser : class, IAcUser<TProfile, TServiceProvider, TUserToServiceProvider, TProfileAddress>
|
||||
where TUserToken : class, IAcUserTokenBase
|
||||
where TProfile : class, IAcProfile<TProfileAddress>
|
||||
where TServiceProvider : class, IAcServiceProviderBase
|
||||
where TUserToServiceProvider : class, IAcUserToServiceProviderBase
|
||||
where TProfileAddress : class, IAcAddress
|
||||
{
|
||||
protected string GenerateDynamicSalt(Guid userId);
|
||||
}
|
||||
|
|
@ -8,7 +8,7 @@ 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 double? Latitude { get; set; }
|
||||
public double? Longitude { get; set; }
|
||||
public string? AddressText { get; set; }
|
||||
}
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
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, TServiceProvider, TUserToServiceProvider, TProfileAddress> 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
|
||||
{
|
||||
public TUser? LoggedInUser { get; }
|
||||
}
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
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, TServiceProvider, TUserToServiceProvider, TProfileAddress> : IAcLoginServiceCommon<TUser, TProfile, TServiceProvider, TUserToServiceProvider, TProfileAddress>
|
||||
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
|
||||
{
|
||||
}
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
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, TServiceProvider, TUserToServiceProvider, TProfileAddress> : IAcLoginServiceBase<TUser, TProfile, TServiceProvider, TUserToServiceProvider, TProfileAddress>
|
||||
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
|
||||
{
|
||||
public TUser? Login(string email, string password, out string accessToken);
|
||||
public Task<TUser?> LoginAsync(string email, string password);
|
||||
|
||||
public bool Logout();
|
||||
public Task<bool> LogoutAsync();
|
||||
|
||||
public TUser? Registration(string email, string password, string? phoneNumber = null);
|
||||
public TUser? Registration(Guid userId, string email, string password, string? phoneNumber = null);
|
||||
public Task<TUser?> RegistrationAsync(string email, string password, string? phoneNumber = null);
|
||||
public Task<TUser?> RegistrationAsync(Guid userId, string email, string password, string? phoneNumber = null);
|
||||
}
|
||||
|
|
@ -6,7 +6,7 @@ namespace AyCode.Interfaces.Users;
|
|||
|
||||
public interface IAcUserBase : IEntityGuid, IAcProfileForeignKey, IEmailAddress, IEmailConfirmed, IPassword, ITimeStampInfo
|
||||
{
|
||||
public string PhoneNumber { get; set; }
|
||||
public string? PhoneNumber { get; set; }
|
||||
public string? RefreshToken { get; set; }
|
||||
|
||||
public Guid? RefferalId { get; set; }
|
||||
|
|
|
|||
|
|
@ -0,0 +1,17 @@
|
|||
using AyCode.Interfaces.Addresses;
|
||||
using AyCode.Interfaces.Profiles;
|
||||
using AyCode.Interfaces.ServiceProviders;
|
||||
using AyCode.Interfaces.Users;
|
||||
using AyCode.Models.Logins;
|
||||
|
||||
namespace AyCode.Models.Server.Logins;
|
||||
|
||||
public class AcLoggedInModelServer<TUser, TProfile, TServiceProvider, TUserToServiceProvider, TProfileAddress> : IAcLoggedInModelBase<TUser, TProfile, TServiceProvider, TUserToServiceProvider, TProfileAddress>
|
||||
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
|
||||
{
|
||||
public TUser? LoggedInUser { get; set; }
|
||||
}
|
||||
|
|
@ -6,10 +6,6 @@
|
|||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Folder Include="Logins\" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\AyCode.Core\AyCode.Core.csproj" />
|
||||
<ProjectReference Include="..\AyCode.Entities\AyCode.Entities.csproj" />
|
||||
|
|
|
|||
|
|
@ -0,0 +1,18 @@
|
|||
using AyCode.Interfaces.Addresses;
|
||||
using AyCode.Interfaces.Logins;
|
||||
using AyCode.Interfaces.Profiles;
|
||||
using AyCode.Interfaces.ServiceProviders;
|
||||
using AyCode.Interfaces.TimeStampInfo;
|
||||
using AyCode.Interfaces.Users;
|
||||
|
||||
namespace AyCode.Models.Logins;
|
||||
|
||||
public interface IAcLoggedInModelBase<TUser, TProfile, TServiceProvider, TUserToServiceProvider, TProfileAddress> : IAcLoginDtoBase
|
||||
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
|
||||
{
|
||||
TUser? LoggedInUser { get; set; }
|
||||
}
|
||||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
namespace AyCode.Models.Logins;
|
||||
|
||||
public interface IAcLoginDtoBase : IEntityGuid
|
||||
public interface IAcLoginDtoBase
|
||||
{
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
|
||||
<IsPackable>false</IsPackable>
|
||||
<IsTestProject>true</IsTestProject>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="coverlet.collector" Version="6.0.2">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.9.0" />
|
||||
<PackageReference Include="MSTest.TestAdapter" Version="3.3.1" />
|
||||
<PackageReference Include="MSTest.TestFramework" Version="3.3.1" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\AyCode.Core.Server\AyCode.Core.Server.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\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>
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
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.Profiles;
|
||||
using AyCode.Interfaces.Server.Logins;
|
||||
using AyCode.Interfaces.ServiceProviders;
|
||||
using AyCode.Interfaces.Users;
|
||||
|
||||
namespace AyCode.Services.Server.Tests.LoginServices
|
||||
{
|
||||
public abstract class AcLoginServiceServerTestBase<TDal, TDbContext, TLoginServiceServer, 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 TLoginServiceServer : class, IAcLoginServiceServer<TUser, TUserToken, TProfile, 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 TServiceProvider : class, IAcServiceProviderBase
|
||||
where TUserToServiceProvider : class, IAcUserToServiceProviderBase
|
||||
{
|
||||
public TUser RegisterUserTest()
|
||||
{
|
||||
//Activator.CreateInstance(typeof(TLoginServiceServer), )
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -8,7 +8,7 @@
|
|||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration" Version="8.0.0" />
|
||||
<PackageReference Include="SendGrid" Version="9.29.2" />
|
||||
<PackageReference Include="SendGrid" Version="9.29.3" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,179 @@
|
|||
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.Database.DataLayers.Users;
|
||||
using AyCode.Database.DbContexts.Users;
|
||||
using AyCode.Models.Logins;
|
||||
using AyCode.Models.Server.Logins;
|
||||
using AyCode.Utils.Extensions;
|
||||
using AyCode.Utils.Helpers;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
|
||||
namespace AyCode.Services.Server.Logins;
|
||||
|
||||
public class AcLoginServiceServer<TResultLoggedInModel, TDal, TDbContext, TUser, TUserToken, TProfile, TServiceProvider, TUserToServiceProvider, TProfileAddress>(TDal userDal, IConfiguration configuration)
|
||||
: AcLoginServiceBase<TUser, TProfile, TServiceProvider, TUserToServiceProvider, TProfileAddress>, IAcLoginServiceServer<TUser, TUserToken, TProfile, TServiceProvider, TUserToServiceProvider, TProfileAddress>
|
||||
|
||||
where TResultLoggedInModel: class, IAcLoggedInModelBase<TUser, TProfile, TServiceProvider, TUserToServiceProvider, TProfileAddress>
|
||||
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 TUserToken : class, IAcUserTokenBase
|
||||
where TProfile : class, IAcProfile<TProfileAddress>
|
||||
where TServiceProvider : class, IAcServiceProviderBase
|
||||
where TUserToServiceProvider : class, IAcUserToServiceProviderBase
|
||||
where TProfileAddress : class, IAcAddress
|
||||
{
|
||||
public virtual TUser? Login(string email, string password, out string accessToken)
|
||||
{
|
||||
accessToken = string.Empty;
|
||||
//var loginModel = Activator.CreateInstance<TResultLoggedInModel>();
|
||||
|
||||
if (!AcValidate.IsValidEmailAndPasswordFormat(email, password, out var errorCode)) return null;//return loginModel;
|
||||
|
||||
var user = userDal.GetUserByEmail(email);
|
||||
if (user is not { EmailConfirmed: true } || !string.Equals(user.EmailAddress, email, StringComparison.CurrentCultureIgnoreCase)
|
||||
|| !PasswordHasher.VerifyPassword(password, user.Password, GenerateDynamicSalt(user.Id))) return null;
|
||||
|
||||
|
||||
//loginModel.LoggedInUser = user;
|
||||
return LoggedInUser = user;
|
||||
}
|
||||
|
||||
public virtual Task<TUser?> LoginAsync(string email, string password)
|
||||
{
|
||||
return TaskHelper.ToThreadPoolTask(() => Login(email, password, out _));
|
||||
}
|
||||
|
||||
public virtual bool Logout()
|
||||
{
|
||||
LoggedInUser = null;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public virtual Task<bool> LogoutAsync()
|
||||
{
|
||||
return TaskHelper.ToThreadPoolTask(Logout);
|
||||
}
|
||||
|
||||
public virtual TUser? Registration(string email, string password, string? phoneNumber = null)
|
||||
=> Registration(Guid.NewGuid(), email, password, phoneNumber);
|
||||
|
||||
public virtual TUser? Registration(Guid userId, string email, string password, string? phoneNumber = null)
|
||||
{
|
||||
if ((phoneNumber != null && !AcValidate.IsValidPhoneNumberFormat(phoneNumber, out var errorCode)) ||
|
||||
!AcValidate.IsValidEmailAndPasswordFormat(email, password, out errorCode)) return null;
|
||||
|
||||
var user = Activator.CreateInstance<TUser>();
|
||||
user.Id = userId;
|
||||
user.EmailAddress = email;
|
||||
user.EmailConfirmed = true;
|
||||
user.Password = PasswordHasher.HashPassword(password, GenerateDynamicSalt(userId));
|
||||
|
||||
var address = Activator.CreateInstance<TProfileAddress>();
|
||||
address.Id = Guid.NewGuid();
|
||||
|
||||
var userName = email.Split('@')[0]; //TODO: generálni egy nevet... - J.
|
||||
return userDal.AddUser(user, userName, address) ? null : userDal.GetUserById(userId);
|
||||
}
|
||||
|
||||
public virtual Task<TUser?> RegistrationAsync(string email, string password, string? phoneNumber = null)
|
||||
=> RegistrationAsync(Guid.NewGuid(), email, password, phoneNumber);
|
||||
public virtual Task<TUser?> RegistrationAsync(Guid userId, string email, string password, string? phoneNumber = null)
|
||||
{
|
||||
return TaskHelper.ToThreadPoolTask(() => Registration(userId, email, password, phoneNumber));
|
||||
}
|
||||
|
||||
//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 virtual string GenerateDynamicSalt(Guid userId)
|
||||
=> userId.ToString("N").ToLower().Reverse().MixCharacters(AcConst.ProjectSalt);
|
||||
|
||||
private string GenerateAccessToken(TUser user)
|
||||
{
|
||||
var tokenHandler = new JwtSecurityTokenHandler();
|
||||
Console.WriteLine("----------------------------------------------------------");
|
||||
|
||||
if (configuration["JWT:Key"] == null)
|
||||
throw new SecurityTokenException("Token is null");
|
||||
|
||||
var keyDetail = Encoding.UTF8.GetBytes(configuration["JWT:Key"] ?? string.Empty);
|
||||
Console.WriteLine(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.AddMinutes(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);
|
||||
Console.WriteLine(writtenToken);
|
||||
|
||||
return writtenToken;
|
||||
}
|
||||
|
||||
private ClaimsPrincipal GetPrincipalFromExpiredToken(string token)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
private string GenerateRefreshToken()
|
||||
{
|
||||
var randomNumber = new byte[32];
|
||||
using (var rng = RandomNumberGenerator.Create())
|
||||
{
|
||||
rng.GetBytes(randomNumber);
|
||||
return Convert.ToBase64String(randomNumber);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -6,6 +6,10 @@
|
|||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="8.0.4" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\AyCode.Core\AyCode.Core.csproj" />
|
||||
<ProjectReference Include="..\AyCode.Entities\AyCode.Entities.csproj" />
|
||||
|
|
|
|||
|
|
@ -0,0 +1,17 @@
|
|||
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, TServiceProvider, TUserToServiceProvider, TProfileAddress> : IAcLoginServiceBase<TUser, TProfile, TServiceProvider, TUserToServiceProvider, TProfileAddress>
|
||||
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
|
||||
{
|
||||
public TUser? LoggedInUser { get; protected set; }
|
||||
}
|
||||
|
|
@ -0,0 +1,58 @@
|
|||
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, TServiceProvider, TUserToServiceProvider, TProfileAddress>
|
||||
: AcLoginServiceBase<TUser, TProfile, TServiceProvider, TUserToServiceProvider, TProfileAddress>, IAcLoginServiceClient<TUser, TProfile, TServiceProvider, TUserToServiceProvider, TProfileAddress>
|
||||
|
||||
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
|
||||
{
|
||||
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 TUser? Registration(string email, string password, string? phoneNumber = null)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public TUser? Registration(Guid userId, string email, string password, string? phoneNumber = null)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public virtual Task<TUser?> RegistrationAsync(string email, string password, string? phoneNumber = null)
|
||||
{
|
||||
return TaskHelper.ToThreadPoolTask(() => Registration(email, password, phoneNumber));
|
||||
}
|
||||
|
||||
public Task<TUser?> RegistrationAsync(Guid userId, string email, string password, string? phoneNumber = null)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
|
|
@ -8,7 +8,7 @@
|
|||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="JetBrains.Annotations" Version="2023.3.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Cryptography.KeyDerivation" Version="8.0.3" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Cryptography.KeyDerivation" Version="8.0.4" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
|
|||
|
|
@ -1,7 +1,8 @@
|
|||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Text;
|
||||
using JetBrains.Annotations;
|
||||
|
||||
namespace AyCode.Utils.Extensions
|
||||
namespace AyCode.Core.Extensions
|
||||
{
|
||||
public static class StringExtensions
|
||||
{
|
||||
|
|
@ -36,5 +37,41 @@ 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,51 +1,50 @@
|
|||
using Microsoft.AspNetCore.Cryptography.KeyDerivation;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using AyCode.Core.Extensions;
|
||||
using AyCode.Utils.Extensions;
|
||||
|
||||
namespace AyCode.Utils.Helpers
|
||||
{
|
||||
public class PasswordHasher
|
||||
{
|
||||
public string HashPassword(string password)
|
||||
public static string HashPassword(string password, string? dynamicSalt = null)
|
||||
{
|
||||
// Generate a random salt
|
||||
byte[] salt = new byte[16];
|
||||
using (var rng = RandomNumberGenerator.Create())
|
||||
{
|
||||
rng.GetBytes(salt);
|
||||
}
|
||||
var 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));
|
||||
var hashedPassword = GenerateHashedPassword(password, salt, dynamicSalt);
|
||||
|
||||
// Combine the salt and hashed password
|
||||
string combinedHash = $"$bcrypt$v=1$salt={Convert.ToBase64String(salt)}$hash={hashedPassword}";
|
||||
var combinedHash = $"$bcrypt$v=1$salt={Convert.ToBase64String(salt)}$hash={hashedPassword}";
|
||||
|
||||
return combinedHash;
|
||||
}
|
||||
|
||||
public bool VerifyPassword(string password, string hashedPassword)
|
||||
public static bool VerifyPassword(string password, string hashedPassword, string? dynamicSalt = null)
|
||||
{
|
||||
// Extract the salt and hashed password from the combined hash
|
||||
string[] parts = hashedPassword.Split('$');
|
||||
byte[] salt = Convert.FromBase64String(parts[3]);
|
||||
string storedHash = parts[5];
|
||||
var parts = hashedPassword.Split('$');
|
||||
var salt = Convert.FromBase64String(parts[3].Replace("salt=", string.Empty));
|
||||
var storedHash = parts[4].Replace("hash=", string.Empty);
|
||||
|
||||
// Hash the provided password with the extracted salt
|
||||
string hashedProvidedPassword = Convert.ToBase64String(KeyDerivation.Pbkdf2(
|
||||
return storedHash == GenerateHashedPassword(password, salt, dynamicSalt);
|
||||
}
|
||||
|
||||
private static string GenerateHashedPassword(string password, byte[] salt, string? dynamicSalt)
|
||||
=> Convert.ToBase64String(KeyDerivation.Pbkdf2(
|
||||
password: password,
|
||||
salt: salt,
|
||||
salt: GenerateFinallySalt(salt, dynamicSalt),
|
||||
prf: KeyDerivationPrf.HMACSHA512,
|
||||
iterationCount: 10000,
|
||||
numBytesRequested: 32));
|
||||
|
||||
// Compare the hashed passwords
|
||||
return storedHash == hashedProvidedPassword;
|
||||
}
|
||||
//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();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue