Skip to content

Commit

Permalink
Merge pull request #698 from Crypter-File-Transfer/bugfix/observe-use…
Browse files Browse the repository at this point in the history
…r-privacy-settings

Observe user privacy settings when validating transfer uploads
  • Loading branch information
Jack-Edwards authored Apr 12, 2024
2 parents 1d2eebe + 990f731 commit 719ae8b
Show file tree
Hide file tree
Showing 4 changed files with 26 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ from recipientId in Common.ValidateTransferUploadAsync(
_transferStorageSettings,
request.SenderId,
request.RecipientUsername,
TransferItemType.File,
request.Request.LifetimeHours,
request.CiphertextStream.Length)
let transferUserType = Common.DetermineUploadTransferUserType(request.SenderId, recipientId)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@
*/

using System;
using System.Collections.Generic;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
Expand Down Expand Up @@ -94,6 +93,7 @@ from recipientId in Common.ValidateTransferUploadAsync(
_transferStorageSettings,
request.SenderId,
request.RecipientUsername,
TransferItemType.Message,
request.Request.LifetimeHours,
request.CiphertextStream.Length)
let newTransferId = Guid.NewGuid()
Expand Down
9 changes: 7 additions & 2 deletions Crypter.Core/Features/Transfer/Common.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ internal static class Common
/// <param name="transferStorageSettings"></param>
/// <param name="senderId"></param>
/// <param name="recipientUsername"></param>
/// <param name="itemType"></param>
/// <param name="requestedTransferLifetimeHours"></param>
/// <param name="ciphertextStreamLength"></param>
/// <returns>
Expand All @@ -36,12 +37,13 @@ internal static async Task<Either<UploadTransferError, Maybe<Guid>>> ValidateTra
TransferStorageSettings transferStorageSettings,
Maybe<Guid> senderId,
Maybe<string> recipientUsername,
TransferItemType itemType,
int requestedTransferLifetimeHours,
long ciphertextStreamLength)
{
Maybe<Guid> recipientId = await recipientUsername
.BindAsync(async x =>
await GetUploadRecipientIdAsync(dataContext, senderId, x));
await GetUploadRecipientIdAsync(dataContext, senderId, x, itemType));

if (recipientUsername.IsSome && recipientId.IsNone)
{
Expand Down Expand Up @@ -83,13 +85,14 @@ internal static TransferUserType DetermineUploadTransferUserType(Maybe<Guid> sen

return TransferUserType.Anonymous;
}

/// <summary>
/// Query for a transfer recipient's user id.
/// </summary>
/// <param name="dataContext"></param>
/// <param name="senderId"></param>
/// <param name="recipientUsername"></param>
/// <param name="itemType"></param>
/// <param name="cancellationToken"></param>
/// <returns>
/// The recipient's id if the recipient exists and their privacy settings permit uploads from the sender.
Expand All @@ -99,6 +102,7 @@ private static async Task<Maybe<Guid>> GetUploadRecipientIdAsync(
DataContext dataContext,
Maybe<Guid> senderId,
string recipientUsername,
TransferItemType itemType,
CancellationToken cancellationToken = default)
{
Guid? nullableSenderId = senderId
Expand All @@ -107,6 +111,7 @@ private static async Task<Maybe<Guid>> GetUploadRecipientIdAsync(
var recipientData = await dataContext.Users
.Where(x => x.Username.ToLower() == recipientUsername.ToLower())
.Where(LinqUserExpressions.UserPrivacyAllowsVisitor(nullableSenderId))
.Where(LinqUserExpressions.UserPrivacyAllowsTransfer(nullableSenderId, itemType))
.Select(x => new { x.Id })
.FirstOrDefaultAsync(cancellationToken);

Expand Down
23 changes: 17 additions & 6 deletions Crypter.Core/LinqExpressions/LinqUserExpressions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -33,18 +33,29 @@

namespace Crypter.Core.LinqExpressions;

public static class LinqUserExpressions
internal static class LinqUserExpressions
{
public static Expression<Func<UserEntity, bool>> UserPrivacyAllowsVisitor(Guid? visitorId)
internal static Expression<Func<UserEntity, bool>> UserPrivacyAllowsVisitor(Guid? visitorId)
{
return x => x.Id == visitorId
|| x.PrivacySetting!.Visibility == UserVisibilityLevel.Everyone
|| (x.PrivacySetting!.Visibility == UserVisibilityLevel.Authenticated && visitorId != null)
|| (x.PrivacySetting!.Visibility == UserVisibilityLevel.Contacts &&
x.Contacts!.Any(y => y.ContactId == visitorId));
}

internal static Expression<Func<UserEntity, bool>> UserPrivacyAllowsTransfer(Guid? visitorId, TransferItemType itemType)
{
return x => x.Id == visitorId
|| (itemType == TransferItemType.File && x.PrivacySetting!.ReceiveFiles == UserItemTransferPermission.Everyone)
|| (itemType == TransferItemType.Message && x.PrivacySetting!.ReceiveMessages == UserItemTransferPermission.Everyone)
|| (itemType == TransferItemType.File && x.PrivacySetting!.ReceiveFiles == UserItemTransferPermission.Authenticated && visitorId != null)
|| (itemType == TransferItemType.Message && x.PrivacySetting!.ReceiveMessages == UserItemTransferPermission.Authenticated && visitorId != null)
|| (itemType == TransferItemType.File && x.PrivacySetting!.ReceiveFiles == UserItemTransferPermission.Contacts && x.Contacts!.Any(y => y.ContactId == visitorId))
|| (itemType == TransferItemType.Message && x.PrivacySetting!.ReceiveMessages == UserItemTransferPermission.Contacts && x.Contacts!.Any(y => y.ContactId == visitorId));
}

public static Expression<Func<UserEntity, bool>> UserProfileIsComplete()
internal static Expression<Func<UserEntity, bool>> UserProfileIsComplete()
{
return x => x.Profile != null
&& x.KeyPair != null
Expand All @@ -59,7 +70,7 @@ public static Expression<Func<UserEntity, bool>> UserProfileIsComplete()
/// </summary>
/// <param name="visitorId"></param>
/// <returns></returns>
public static Expression<Func<UserEntity, UserProfile>> ToUserProfileForVisitor(Guid? visitorId)
internal static Expression<Func<UserEntity, UserProfile>> ToUserProfileForVisitor(Guid? visitorId)
{
return x => new UserProfile(
x.Username,
Expand All @@ -80,7 +91,7 @@ public static Expression<Func<UserEntity, UserProfile>> ToUserProfileForVisitor(
x.EmailVerified);
}

public static Expression<Func<UserEntity?, bool>> UserReceivesEmailNotifications()
internal static Expression<Func<UserEntity?, bool>> UserReceivesEmailNotifications()
{
return x => x != null
&& x.EmailVerified
Expand All @@ -89,7 +100,7 @@ public static Expression<Func<UserEntity, UserProfile>> ToUserProfileForVisitor(
&& x.NotificationSetting.EmailNotifications;
}

public static Expression<Func<T, bool>> Inverse<T>(this Expression<Func<T, bool>> e)
internal static Expression<Func<T, bool>> Inverse<T>(this Expression<Func<T, bool>> e)
{
return Expression.Lambda<Func<T, bool>>(Expression.Not(e.Body), e.Parameters[0]);
}
Expand Down

0 comments on commit 719ae8b

Please sign in to comment.