Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ public interface IUserTransferSettingsService
{
Task<Maybe<GetTransferSettingsResponse>> GetTransferSettingsAsync();
Task<long> GetAbsoluteMaximumUploadSizeAsync();
Task<int> GetAbsoluteMaximumMessageLengthAsync();
Task<long> GetCurrentMaximumUploadSizeAsync();
Task<bool> IsUserQuotaReachedAsync();
Task<bool> IsFreeTransferQuotaReachedAsync();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,28 +36,32 @@

namespace Crypter.Common.Client.Services.UserSettings;

public class UserTransferSettingsService : IUserTransferSettingsService
public class UserTransferSettingsService : IUserTransferSettingsService, IDisposable
{
private readonly IUserSessionService _userSessionService;
private readonly ICrypterApiClient _crypterApiClient;

private readonly IMemoryCache _memoryCache;
private readonly SemaphoreSlim _memoryCacheLock = new SemaphoreSlim(1, 1);

private const string TransferSettingsCacheKey = $"{nameof(UserTransferSettingsService)}:TransferSettings";

public UserTransferSettingsService(IUserSessionService userSessionService, ICrypterApiClient crypterApiClient, IMemoryCache memoryCache)
{
_userSessionService = userSessionService;
_crypterApiClient = crypterApiClient;
_memoryCache = memoryCache;

userSessionService.UserLoggedInEventHandler += RecycleAsync;
userSessionService.UserLoggedOutEventHandler += RecycleAsync;
}

public async Task<Maybe<GetTransferSettingsResponse>> GetTransferSettingsAsync()
{
const string cacheKey = $"{nameof(UserTransferSettingsService)}:{nameof(GetTransferSettingsAsync)}";
try
{
await _memoryCacheLock.WaitAsync();
return await _memoryCache.GetOrCreateAsync<GetTransferSettingsResponse?>(cacheKey, async entry =>
return await _memoryCache.GetOrCreateAsync<GetTransferSettingsResponse?>(TransferSettingsCacheKey, async entry =>
{
bool isLoggedIn = await _userSessionService.IsLoggedInAsync();
Maybe<GetTransferSettingsResponse> uploadSettings = await _crypterApiClient.UserSetting.GetTransferSettingsAsync(isLoggedIn);
Expand All @@ -76,32 +80,55 @@ public async Task<Maybe<GetTransferSettingsResponse>> GetTransferSettingsAsync()
public async Task<long> GetAbsoluteMaximumUploadSizeAsync()
{
return await GetTransferSettingsAsync()
.MatchAsync(
() => 0,
x => x.MaximumUploadSize);
.Select(x => x.MaximumUploadSize)
.SomeOrDefaultAsync(0);
}

public async Task<int> GetAbsoluteMaximumMessageLengthAsync()
{
return await GetTransferSettingsAsync()
.Select(x => x.MaximumMessageLength)
.SomeOrDefaultAsync(0);
}

public async Task<long> GetCurrentMaximumUploadSizeAsync()
{
return await GetTransferSettingsAsync()
.MatchAsync(
() => 0,
x => Math.Min(x.MaximumUploadSize, Math.Min(x.AvailableUserSpace, x.AvailableFreeTransferSpace)));
.Select(x => Math.Min(x.MaximumUploadSize, Math.Min(x.AvailableUserSpace, x.AvailableFreeTransferSpace)))
.SomeOrDefaultAsync(0);
}

public async Task<bool> IsUserQuotaReachedAsync()
{
return await GetTransferSettingsAsync()
.MatchAsync(
() => true,
x => x.AvailableUserSpace == 0);
.Select(x => x.AvailableUserSpace == 0)
.SomeOrDefaultAsync(true);
}

public async Task<bool> IsFreeTransferQuotaReachedAsync()
{
return await GetTransferSettingsAsync()
.MatchAsync(
() => true,
x => x.AvailableFreeTransferSpace == 0);
.Select(x => x.AvailableFreeTransferSpace == 0)
.SomeOrDefaultAsync(true);
}

private async void RecycleAsync(object? _, EventArgs __)
{
try
{
await _memoryCacheLock.WaitAsync();
_memoryCache.Remove(TransferSettingsCacheKey);
}
finally
{
_memoryCacheLock.Release();
}
}

public void Dispose()
{
_userSessionService.UserLoggedInEventHandler -= RecycleAsync;
_userSessionService.UserLoggedOutEventHandler -= RecycleAsync;
GC.SuppressFinalize(this);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,17 +30,19 @@ public sealed record GetTransferSettingsResponse
{
public string TierName { get; set; }
public long MaximumUploadSize { get; init; }
public int MaximumMessageLength { get; init; }
public long AvailableUserSpace { get; init; }
public long UsedUserSpace { get; init; }
public long UserQuota { get; init; }
public long AvailableFreeTransferSpace { get; init; }
public long UsedFreeTransferSpace { get; init; }
public long FreeTransferQuota { get; init; }

public GetTransferSettingsResponse(string tierName, long maximumUploadSize, long availableUserSpace, long usedUserSpace, long userQuota, long availableFreeTransferSpace, long usedFreeTransferSpace, long freeTransferQuota)
public GetTransferSettingsResponse(string tierName, long maximumUploadSize, int maximumMessageLength, long availableUserSpace, long usedUserSpace, long userQuota, long availableFreeTransferSpace, long usedFreeTransferSpace, long freeTransferQuota)
{
TierName = tierName;
MaximumUploadSize = maximumUploadSize;
MaximumMessageLength = maximumMessageLength;
AvailableUserSpace = availableUserSpace;
UsedUserSpace = usedUserSpace;
UserQuota = userQuota;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,6 @@ internal class SaveFileTransferCommandHandler
private readonly IHashIdService _hashIdService;
private readonly IPublisher _publisher;
private readonly ITransferRepository _transferRepository;
private readonly TransferStorageSettings _transferStorageSettings;

public SaveFileTransferCommandHandler(
DataContext dataContext,
Expand All @@ -71,7 +70,6 @@ public SaveFileTransferCommandHandler(
_hashIdService = hashIdService;
_publisher = publisher;
_transferRepository = transferRepository;
_transferStorageSettings = transferStorageSettings.Value;
}

public async Task<Either<UploadTransferError, UploadTransferResponse>> Handle(SaveFileTransferCommand request, CancellationToken cancellationToken)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,6 @@ internal class SaveMessageTransferCommandHandler
private readonly IHashIdService _hashIdService;
private readonly IPublisher _publisher;
private readonly ITransferRepository _transferRepository;
private readonly TransferStorageSettings _transferStorageSettings;

public SaveMessageTransferCommandHandler(
DataContext dataContext,
Expand All @@ -71,7 +70,6 @@ public SaveMessageTransferCommandHandler(
_hashIdService = hashIdService;
_publisher = publisher;
_transferRepository = transferRepository;
_transferStorageSettings = transferStorageSettings.Value;
}

public async Task<Either<UploadTransferError, UploadTransferResponse>> Handle(SaveMessageTransferCommand request, CancellationToken cancellationToken)
Expand Down
5 changes: 2 additions & 3 deletions Crypter.Core/Features/Transfer/Common.cs
Original file line number Diff line number Diff line change
Expand Up @@ -178,8 +178,7 @@ private static async Task<Maybe<Guid>> GetUploadRecipientIdAsync(
private static async Task<bool> HasSpaceForTransferAsync(DataContext dataContext, Maybe<Guid> possibleUserId, long ciphertextStreamLength, CancellationToken cancellationToken = default)
{
return await UserSettings.Common.GetUserTransferSettingsAsync(dataContext, possibleUserId, cancellationToken)
.MatchAsync(
() => false,
x => Math.Min(x.MaximumUploadSize, Math.Min(x.AvailableFreeTransferSpace, x.AvailableUserSpace)) >= ciphertextStreamLength);
.Select(x => Math.Min(x.MaximumUploadSize, Math.Min(x.AvailableFreeTransferSpace, x.AvailableUserSpace)) >= ciphertextStreamLength)
.SomeOrDefaultAsync(false);
}
}
3 changes: 2 additions & 1 deletion Crypter.Core/Features/UserSettings/Common.cs
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ internal static async Task<Maybe<GetTransferSettingsResponse>> GetUserTransferSe
{
x.Name,
x.MaximumUploadSize,
x.MaximumMessageLength,
x.UserQuota,
UsedUserSpace = x.DefaultForUserCategory == UserCategory.Anonymous
? dataContext.AnonymousFileTransfers
Expand Down Expand Up @@ -124,6 +125,6 @@ internal static async Task<Maybe<GetTransferSettingsResponse>> GetUserTransferSe

return data is null
? Maybe<GetTransferSettingsResponse>.None
: new GetTransferSettingsResponse(data.Name, data.MaximumUploadSize, data.UserQuota - data.UsedUserSpace, data.UsedUserSpace, data.UserQuota, data.FreeTransferQuota - data.UsedFreeTransferSpace, data.UsedFreeTransferSpace, data.FreeTransferQuota);
: new GetTransferSettingsResponse(data.Name, data.MaximumUploadSize, data.MaximumMessageLength, data.UserQuota - data.UsedUserSpace, data.UsedUserSpace, data.UserQuota, data.FreeTransferQuota - data.UsedFreeTransferSpace, data.UsedFreeTransferSpace, data.FreeTransferQuota);
}
}
1 change: 1 addition & 0 deletions Crypter.DataAccess/Entities/TransferTierEntity.cs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ public class TransferTierEntity
public string Name { get; set; } = null!;
public string? Description { get; set; }
public long MaximumUploadSize { get; set; }
public int MaximumMessageLength { get; set; }
public long UserQuota { get; set; }
public UserCategory? DefaultForUserCategory { get; set; }
}
Expand Down
Loading
Loading