using Newtonsoft.Json; using RelayCore.Endpoints; using RelayCore.Enums; using RelayCore.Models; using SurrealDb.Net; using SurrealDb.Net.Models; namespace RelayCore.Services; public class APIAuthService(SurrealDbClient _db) { public async Task> GetUsersAsync() { var users = await _db.Select("auth_users"); return users.Where(x => x.Username is not null).OrderByDescending(x=>x.CreatedAt).ToList(); } public async Task UserSigninAsync(AuthSignin request, string ip, string userAgent) { var hasher = new PasswordHasher(); var users = await _db.Select("auth_users"); var user = users.FirstOrDefault(x => (x.Username.ToLower() == request.UserName.ToLower() || x.Email.ToLower() == request.UserName.ToLower()) && hasher.VerifyPassword(x.Id + request.Password, x.Password)); if (user == null) return null; var tokens = await _db.Select("auth_sessions"); var token = tokens.Where(x => x.UserId == user.Id && x.IpAddress == ip && x.UserAgent == userAgent && !x.Revoked) .OrderByDescending(x => x.ExpiresAt).FirstOrDefault(); if (token != null) if (token.ExpiresAt > DateTime.UtcNow) return token.TokenHash; //TODO: Generate TOKEN var newToken = hasher.HashPassword($"{request.UserName}{userAgent}"); //TODO: Store TOKEN and Username for verification var sessionId = await _db.Create("auth_sessions", new Sessions { UserId = user.Id, TokenHash = newToken, IssuedAt = DateTime.UtcNow, ExpiresAt = DateTime.UtcNow.AddDays(30), DeviceName = "", Revoked = false, IpAddress = ip, UserAgent = userAgent }); //TODO: Add invalidation to TOKENs return newToken; } public async Task UserRegisterAsync(AuthRegister request, string ip, string userAgent) { var hasher = new PasswordHasher(); var users = await _db.Select("auth_users"); var user = users.FirstOrDefault(x => x.Username.ToLower() == request.Username.ToLower() || x.Email.ToLower() == request.Email.ToLower()); if (user == null) { var now = DateTime.Now; var created = await _db.Create("auth_users", new Users { Username = request.Username, Email = request.Email, CreatedAt = now, UpdatedAt = now, LastLogin = now, TwoFactorEnabled = false, EmailVerified = false, AccountStatus = (int)AccountStatuses.Active, OnlineStatus = (int)OnlineStatuses.Online, }); var passwordHash = hasher.HashPassword(created.Id + request.Password); await _db.Merge(new PasswordHash { Id = created.Id, Password = passwordHash }); return await UserSigninAsync(new AuthSignin{UserName=request.Username, Password = request.Password}, ip, userAgent); } return null; } public async Task ServerVerifyUser(AuthUserVerify request) { var users = await _db.Select("auth_users"); var user = users.FirstOrDefault(x => x.Username == request.Username); if (user == null) return false; var sessions = await _db.Select("auth_sessions"); var session = sessions.FirstOrDefault(x => x.TokenHash == request.Token && x.UserId == user.Id); if (session == null) return false; return true; } }