using BCrypt.Net;
using Biskilog_Accounting.Shared.ClientContractModels;
using Biskilog_Accounting.Shared.Enums;
using Biskilog_Accounting.Shared.Interfaces;
using Microsoft.EntityFrameworkCore;
namespace Biskilog_Accounting.Server.Services
{
public class AuthenticationService : IAuthService
{
private readonly BiskilogContext m_context;
private readonly ITokenService m_tokenService;
public AuthenticationService(BiskilogContext a_context, ITokenService a_tokenService)
{
m_context = a_context;
m_tokenService = a_tokenService;
}
///
/// Returns the status of a user account
///
/// AuthEnums
public AuthEnums AccountStatus(int? a_id, string? a_username)
{
if (m_context.Userauths.Any(i => i.UserId == a_id || i.Username == a_username))
{
return AuthEnums.Found;
}
else
{
return AuthEnums.NotFound;
}
}
///
/// Autenticates a user and returns a tokenized string
///
///
///
/// strings
public async Task AuthenticateClient(string a_username, string a_password)
{
var user = await GetUserAsync(a_username, a_password);
if (user == null)
{
return null;
}
user.LastLogin = DateTime.Now;
m_context.Userauths.Update(user);
m_context.SaveChanges();
Databasemap databasemap = GetClientDB(user.ClientId);
List businessIds = GetSiteaccesspermission(user.ClientId, user.UserId).Select(t => t.BusinessId).ToList();
Contract? contract = GetContract(user.ClientId, businessIds);
List businesses = GetClientbusiness(user.ClientId, user.UserId).Select(t => t.BusinessExternalId).ToList();
if (contract == null)
return AuthEnums.Invalid.ToString();
return m_tokenService.GenerateToken(user, contract, databasemap, businesses, false);
}
///
/// Creates a new user account
///
/// returns AuthEnums.successful if the account was created successfully
public AuthEnums CreateUser(Userauth a_user)
{
throw new NotImplementedException();
//if (AccountStatus(null, a_user.Username) == AuthEnums.Found)
// return AuthEnums.Registered;
//a_user.Role = m_context.UserRoles.First(i => i.RoleId== a_user.RoleId);
//a_user.Password = BCrypt.Net.BCrypt.HashPassword(a_user.Password);
//m_context.Users.Add(a_user);
//var result = m_context.SaveChangesAsync();
//result.Wait();
//if(result.Result > 0)
//{
// return AuthEnums.Successful;
//}
//return AuthEnums.Error;
}
///
/// Deletes a user account
///
///
public void DeleteUser(int a_id)
{
throw new NotImplementedException();
}
public List GetClientbusiness(int a_clientId, int userId)
{
return (from b in m_context.Clientbusinesses
join p in m_context.Siteaccesspermissions on new { b.ClientId, b.BusinessId } equals new { p.ClientId, p.BusinessId }
where p.UserId == userId && p.ClientId == a_clientId
select b).ToList();
}
public Databasemap GetClientDB(int a_clientId)
{
return m_context.Databasemaps.First(t => t.ClientId == a_clientId);
}
public Contract? GetContract(int a_clientId, List a_businessId)
{
return m_context.Contracts.FirstOrDefault(c => c.ClientId == a_clientId && a_businessId.Contains(c.BusinessId!.Value) && c.EndDate >= DateTime.Now);
}
public List GetSiteaccesspermission(int a_clientId, int a_userId)
{
return m_context.Siteaccesspermissions.Where(t => t.ClientId == a_clientId && t.UserId == a_userId).ToList();
}
private async Task GetUserAsync(string username, string password)
{
//Todo have complete implementation after means of creating user is done
try
{
string? pa = await m_context.Userauths.Where(u => u.Username == username || u.Email == username).Select(u => u.Passsword).FirstOrDefaultAsync();
if (String.IsNullOrEmpty(pa))
{
return null;
}
bool verified = BCrypt.Net.BCrypt.Verify(password, pa);
if (verified)
{
return await m_context.Userauths.FirstAsync(u => u.Username == username || u.Email == username);
}
else
{
return null;
}
}
catch (Exception ex)
{
//possible is user not found
return null;
}
}
}
}