143 lines
4.9 KiB
C#
143 lines
4.9 KiB
C#
using System.Linq;
|
|
using System.Threading.Tasks;
|
|
using Bit.Core.Abstractions;
|
|
using Bit.Core.Enums;
|
|
using Bit.Core.Models;
|
|
using Bit.Core.Models.View;
|
|
using MessagePack;
|
|
using MessagePack.Resolvers;
|
|
|
|
namespace Bit.App.Services
|
|
{
|
|
public abstract class BaseWatchDeviceService : IWatchDeviceService
|
|
{
|
|
private readonly ICipherService _cipherService;
|
|
private readonly IEnvironmentService _environmentService;
|
|
private readonly IStateService _stateService;
|
|
private readonly IVaultTimeoutService _vaultTimeoutService;
|
|
|
|
protected BaseWatchDeviceService(ICipherService cipherService,
|
|
IEnvironmentService environmentService,
|
|
IStateService stateService,
|
|
IVaultTimeoutService vaultTimeoutService)
|
|
{
|
|
_cipherService = cipherService;
|
|
_environmentService = environmentService;
|
|
_stateService = stateService;
|
|
_vaultTimeoutService = vaultTimeoutService;
|
|
}
|
|
|
|
public abstract bool IsConnected { get; }
|
|
|
|
protected abstract bool CanSendData { get; }
|
|
protected abstract bool IsSupported { get; }
|
|
|
|
public async Task SyncDataToWatchAsync()
|
|
{
|
|
if (!IsSupported)
|
|
{
|
|
return;
|
|
}
|
|
|
|
var shouldConnect = await _stateService.GetShouldConnectToWatchAsync();
|
|
if (shouldConnect && !IsConnected)
|
|
{
|
|
ConnectToWatch();
|
|
}
|
|
|
|
if (!CanSendData)
|
|
{
|
|
return;
|
|
}
|
|
|
|
var userData = await _stateService.GetActiveUserCustomDataAsync(a => a?.Profile is null ? null : new WatchDTO.UserDataDto
|
|
{
|
|
Id = a.Profile.UserId,
|
|
Name = a.Profile.Name,
|
|
Email = a.Profile.Email
|
|
});
|
|
var state = await GetStateAsync(userData?.Id, shouldConnect);
|
|
if (state != WatchState.Valid)
|
|
{
|
|
await SendDataToWatchAsync(new WatchDTO(state));
|
|
return;
|
|
}
|
|
|
|
var ciphersWithTotp = await _cipherService.GetAllDecryptedAsync(c => c.DeletedDate == null && c.Login?.Totp != null);
|
|
|
|
if (!ciphersWithTotp.Any())
|
|
{
|
|
await SendDataToWatchAsync(new WatchDTO(WatchState.Need2FAItem));
|
|
return;
|
|
}
|
|
|
|
var watchDto = new WatchDTO(state)
|
|
{
|
|
Ciphers = ciphersWithTotp.Select(c => new SimpleCipherView(c)).ToList(),
|
|
UserData = userData,
|
|
EnvironmentData = new WatchDTO.EnvironmentUrlDataDto
|
|
{
|
|
Base = _environmentService.BaseUrl,
|
|
Icons = _environmentService.IconsUrl
|
|
}
|
|
//SettingsData = new WatchDTO.SettingsDataDto
|
|
//{
|
|
// VaultTimeoutInMinutes = await _vaultTimeoutService.GetVaultTimeout(userData?.Id),
|
|
// VaultTimeoutAction = await _stateService.GetVaultTimeoutActionAsync(userData?.Id) ?? VaultTimeoutAction.Lock
|
|
//}
|
|
};
|
|
await SendDataToWatchAsync(watchDto);
|
|
}
|
|
|
|
private async Task<WatchState> GetStateAsync(string userId, bool shouldConnectToWatch)
|
|
{
|
|
if (await _stateService.GetLastUserShouldConnectToWatchAsync()
|
|
&&
|
|
(userId is null || !await _stateService.IsAuthenticatedAsync()))
|
|
{
|
|
// if the last user had "Connect to Watch" enabled and there's no user authenticated
|
|
return WatchState.NeedLogin;
|
|
}
|
|
|
|
if (!shouldConnectToWatch)
|
|
{
|
|
return WatchState.NeedSetup;
|
|
}
|
|
|
|
//if (await _vaultTimeoutService.IsLockedAsync() ||
|
|
// await _vaultTimeoutService.ShouldLockAsync())
|
|
//{
|
|
// return WatchState.NeedUnlock;
|
|
//}
|
|
|
|
if (!await _stateService.CanAccessPremiumAsync(userId))
|
|
{
|
|
return WatchState.NeedPremium;
|
|
}
|
|
|
|
return WatchState.Valid;
|
|
}
|
|
|
|
public async Task SetShouldConnectToWatchAsync(bool shouldConnectToWatch)
|
|
{
|
|
await _stateService.SetShouldConnectToWatchAsync(shouldConnectToWatch);
|
|
await SyncDataToWatchAsync();
|
|
}
|
|
|
|
protected async Task SendDataToWatchAsync(WatchDTO watchDto)
|
|
{
|
|
var options = MessagePackSerializerOptions.Standard
|
|
.WithResolver(CompositeResolver.Create(
|
|
GeneratedResolver.Instance,
|
|
StandardResolver.Instance
|
|
));
|
|
|
|
await SendDataToWatchAsync(MessagePackSerializer.Serialize(watchDto, options));
|
|
}
|
|
|
|
protected abstract Task SendDataToWatchAsync(byte[] rawData);
|
|
|
|
protected abstract void ConnectToWatch();
|
|
}
|
|
}
|