132 lines
4.2 KiB
C#
132 lines
4.2 KiB
C#
// <copyright file="UserPresenceService.cs" company="alveus.dev">
|
|
// Copyright (c) alveus.dev. All rights reserved. Licensed under the MIT License.
|
|
// </copyright>
|
|
|
|
using Astral.Core.Entities;
|
|
using Astral.Core.Extensions;
|
|
using Astral.Core.RepositoryInterfaces;
|
|
using Astral.Services.Constants;
|
|
using Astral.Services.Dtos;
|
|
using Astral.Services.Exceptions;
|
|
using Astral.Services.Helpers;
|
|
using Astral.Services.Interfaces;
|
|
using AutoMapper;
|
|
using Injectio.Attributes;
|
|
|
|
namespace Astral.Services.Services;
|
|
|
|
/// <inheritdoc />
|
|
[RegisterScoped]
|
|
public class UserPresenceService : IUserPresenceService
|
|
{
|
|
private readonly IIdentityProvider _identityProvider;
|
|
private readonly ICryptographyService _cryptographyService;
|
|
private readonly IUserPresenceRepository _userPresenceRepository;
|
|
private readonly IMapper _mapper;
|
|
|
|
/// <summary>
|
|
/// Initializes a new instance of the <see cref="UserPresenceService"/> class.
|
|
/// </summary>
|
|
/// <param name="identityProvider">Instance of <see cref="IIdentityProvider"/>.</param>
|
|
/// <param name="cryptographyService">Instance of <see cref="ICryptographyService"/>.</param>
|
|
/// <param name="userPresenceRepository">Instance of <see cref="IUserPresenceRepository"/>.</param>
|
|
/// <param name="mapper">Instance of <see cref="IMapper"/>.</param>
|
|
public UserPresenceService(
|
|
IIdentityProvider identityProvider,
|
|
ICryptographyService cryptographyService,
|
|
IUserPresenceRepository userPresenceRepository,
|
|
IMapper mapper)
|
|
{
|
|
_identityProvider = identityProvider;
|
|
_cryptographyService = cryptographyService;
|
|
_userPresenceRepository = userPresenceRepository;
|
|
_mapper = mapper;
|
|
}
|
|
|
|
/// <inheritdoc />
|
|
public async Task HandleHeartbeat()
|
|
{
|
|
var userId = _identityProvider.GetUserId();
|
|
|
|
if (userId == Guid.Empty)
|
|
{
|
|
throw new UnauthorizedException();
|
|
}
|
|
|
|
var heartbeat = await _userPresenceRepository.FindByIdAsync(userId);
|
|
if (heartbeat is null)
|
|
{
|
|
heartbeat = new UserPresence()
|
|
{
|
|
CreatedAt = DateTime.UtcNow,
|
|
Id = userId,
|
|
LastHeartbeat = DateTime.UtcNow
|
|
};
|
|
|
|
await _userPresenceRepository.AddAsync(heartbeat);
|
|
}
|
|
else
|
|
{
|
|
heartbeat.LastHeartbeat = DateTime.UtcNow;
|
|
await _userPresenceRepository.UpdateAsync(heartbeat);
|
|
}
|
|
}
|
|
|
|
/// <inheritdoc />
|
|
public async Task ConsumeLocationHeartbeat(UserLocationHeartbeatDto heartbeat)
|
|
{
|
|
var userId = _identityProvider.GetUserId();
|
|
|
|
if (userId == Guid.Empty)
|
|
{
|
|
throw new UnauthorizedException();
|
|
}
|
|
|
|
var newHeartbeat = _mapper.Map<UserPresence>(heartbeat);
|
|
newHeartbeat.Id = userId;
|
|
|
|
var oldHeartbeat = await _userPresenceRepository.FindByIdAsync(userId) ?? new UserPresence()
|
|
{
|
|
CreatedAt = DateTime.UtcNow,
|
|
Id = userId
|
|
};
|
|
newHeartbeat.CreatedAt = oldHeartbeat.CreatedAt;
|
|
newHeartbeat.UpdatedAt = oldHeartbeat.UpdatedAt;
|
|
newHeartbeat.LastHeartbeat = oldHeartbeat.LastHeartbeat;
|
|
newHeartbeat = EntityHelpers.ApplyChanges(oldHeartbeat, newHeartbeat);
|
|
|
|
await _userPresenceRepository.UpdateAsync(newHeartbeat);
|
|
}
|
|
|
|
/// <inheritdoc />
|
|
public async Task ConsumePublicKey(Stream publicKey)
|
|
{
|
|
var userId = _identityProvider.GetUserId();
|
|
|
|
if (userId == Guid.Empty)
|
|
{
|
|
throw new UnauthorizedException();
|
|
}
|
|
|
|
var key = _cryptographyService.ConvertPublicKey(publicKey.ToByteArray(), PublicKeyType.Pkcs1PublicKey);
|
|
|
|
var heartbeat = await _userPresenceRepository.FindByIdAsync(userId);
|
|
if (heartbeat is null)
|
|
{
|
|
heartbeat = new UserPresence()
|
|
{
|
|
Id = userId,
|
|
LastHeartbeat = DateTime.UtcNow,
|
|
PublicKey = key
|
|
};
|
|
|
|
await _userPresenceRepository.AddAsync(heartbeat);
|
|
}
|
|
else
|
|
{
|
|
heartbeat.LastHeartbeat = DateTime.UtcNow;
|
|
heartbeat.PublicKey = key;
|
|
await _userPresenceRepository.UpdateAsync(heartbeat);
|
|
}
|
|
}
|
|
}
|