Skip to content
Open
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
140 changes: 2 additions & 138 deletions src/Api/Tools/Controllers/SendsController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,10 @@ public class SendsController : Controller
private readonly IUserService _userService;
private readonly ISendAuthorizationService _sendAuthorizationService;
private readonly ISendFileStorageService _sendFileStorageService;
private readonly IAnonymousSendCommand _anonymousSendCommand;
private readonly INonAnonymousSendCommand _nonAnonymousSendCommand;
private readonly ISendOwnerQuery _sendOwnerQuery;
private readonly ILogger<SendsController> _logger;
private readonly IFeatureService _featureService;
private readonly Bitwarden.Server.Sdk.Features.IFeatureService _featureService;
private readonly IPushNotificationService _pushNotificationService;
private readonly IHasPremiumAccessQuery _hasPremiumAccessQuery;
private readonly IEventService _eventService;
Expand All @@ -47,12 +46,11 @@ public SendsController(
ISendRepository sendRepository,
IUserService userService,
ISendAuthorizationService sendAuthorizationService,
IAnonymousSendCommand anonymousSendCommand,
INonAnonymousSendCommand nonAnonymousSendCommand,
ISendOwnerQuery sendOwnerQuery,
ISendFileStorageService sendFileStorageService,
ILogger<SendsController> logger,
IFeatureService featureService,
Bitwarden.Server.Sdk.Features.IFeatureService featureService,
IPushNotificationService pushNotificationService,
IHasPremiumAccessQuery hasPremiumAccessQuery,
IEventService eventService,
Expand All @@ -62,7 +60,6 @@ ISendEventClassifier sendEventClassifier
_sendRepository = sendRepository;
_userService = userService;
_sendAuthorizationService = sendAuthorizationService;
_anonymousSendCommand = anonymousSendCommand;
_nonAnonymousSendCommand = nonAnonymousSendCommand;
_sendOwnerQuery = sendOwnerQuery;
_sendFileStorageService = sendFileStorageService;
Expand All @@ -76,139 +73,6 @@ ISendEventClassifier sendEventClassifier

#region Anonymous endpoints

[AllowAnonymous]
[HttpPost("access/{id}")]
Comment thread
mcamirault marked this conversation as resolved.
[ProducesResponseType<SendAccessResponseModel>(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
[ProducesResponseType(StatusCodes.Status401Unauthorized)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
public async Task<SendAccessResponseModel> Access(string id, [FromBody] SendAccessRequestModel model)
{
// Uncomment whenever we want to require the `send-id` header
//if (!_currentContext.HttpContext.Request.Headers.ContainsKey("Send-Id") ||
// _currentContext.HttpContext.Request.Headers["Send-Id"] != id)
//{
// throw new BadRequestException("Invalid Send-Id header.");
//}

var guid = new Guid(CoreHelpers.Base64UrlDecode(id));
var send = await _sendRepository.GetByIdAsync(guid);

if (send == null)
{
throw new BadRequestException("Could not locate send");
}

if (send.AuthType == AuthType.Email && send.Emails is not null)
{
throw new NotFoundException();
}

var sendAuthResult =
await _sendAuthorizationService.AccessAsync(send, model.Password);
if (sendAuthResult.Equals(SendAccessResult.PasswordRequired))
{
throw new UnauthorizedAccessException();
}

if (sendAuthResult.Equals(SendAccessResult.PasswordInvalid))
{
await Task.Delay(2000);
throw new BadRequestException("Invalid password.");
}

if (sendAuthResult.Equals(SendAccessResult.Denied))
{
throw new NotFoundException();
}

var sendResponse = new SendAccessResponseModel(send);
if (send.UserId.HasValue && !send.HideEmail.GetValueOrDefault())
{
var creator = await _userService.GetUserByIdAsync(send.UserId.Value);
sendResponse.CreatorIdentifier = creator.Email;
}

if (_featureService.IsEnabled(FeatureFlagKeys.SendEventLogging)
&& send.UserId.HasValue
&& send.Type == SendType.Text)
{
var orgContext = await _sendEventClassifier.BuildAccessContextAsync(
send.UserId.Value, accessorEmail: null);

await _eventService.LogSendEventAsync(
send.UserId.Value,
send.Id,
EventType.Send_Accessed_Text,
orgContext);
}

return sendResponse;
}

[AllowAnonymous]
[HttpPost("{encodedSendId}/access/file/{fileId}")]
[ProducesResponseType<SendFileDownloadDataResponseModel>(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
[ProducesResponseType(StatusCodes.Status401Unauthorized)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
public async Task<SendFileDownloadDataResponseModel> GetSendFileDownloadData(string encodedSendId,
string fileId, [FromBody] SendAccessRequestModel model)
{
// Uncomment whenever we want to require the `send-id` header
//if (!_currentContext.HttpContext.Request.Headers.ContainsKey("Send-Id") ||
// _currentContext.HttpContext.Request.Headers["Send-Id"] != encodedSendId)
//{
// throw new BadRequestException("Invalid Send-Id header.");
//}

var sendId = new Guid(CoreHelpers.Base64UrlDecode(encodedSendId));
var send = await _sendRepository.GetByIdAsync(sendId);

if (send == null)
{
throw new BadRequestException("Could not locate send");
}

if (send.AuthType == AuthType.Email && send.Emails is not null)
{
throw new NotFoundException();
}

var (url, result) = await _anonymousSendCommand.GetSendFileDownloadUrlAsync(send, fileId,
Comment thread
mcamirault marked this conversation as resolved.
model.Password);

if (result.Equals(SendAccessResult.PasswordRequired))
{
throw new UnauthorizedAccessException();
}

if (result.Equals(SendAccessResult.PasswordInvalid))
{
await Task.Delay(2000);
throw new BadRequestException("Invalid password.");
}

if (result.Equals(SendAccessResult.Denied))
{
throw new NotFoundException();
}

if (_featureService.IsEnabled(FeatureFlagKeys.SendEventLogging) && send.UserId.HasValue)
{
var orgContext = await _sendEventClassifier.BuildAccessContextAsync(
send.UserId.Value, accessorEmail: null);

await _eventService.LogSendEventAsync(
send.UserId.Value,
send.Id,
EventType.Send_Accessed_File,
orgContext);
}

return new SendFileDownloadDataResponseModel { Id = fileId, Url = url };
}

[AllowAnonymous]
[HttpPost("file/validate/azure")]
public async Task<ObjectResult> AzureValidateFile()
Expand Down
4 changes: 2 additions & 2 deletions src/Api/Tools/Models/Response/SendAccessResponseModel.cs
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
using System.Text.Json;
using Bit.Core.Models.Api;
using Bit.Core.Tools.Entities;
using Bit.Core.Tools.Enums;
using Bit.Core.Tools.Models.Data;
using Bit.Core.Utilities;
using Bit.HttpExtensions;

namespace Bit.Api.Tools.Models.Response;

Expand Down Expand Up @@ -92,7 +92,7 @@ public SendAccessResponseModel(Send send)
/// </summary>
/// <remarks>
/// File content is downloaded separately using
/// <see cref="Bit.Api.Tools.Controllers.SendsController.GetSendFileDownloadData" />
/// <see cref="Controllers.SendsController.GetSendFileDownloadDataUsingAuth" />
/// </remarks>
public SendFileModel? File { get; set; }

Expand Down
1 change: 0 additions & 1 deletion src/Core/Constants.cs
Original file line number Diff line number Diff line change
Expand Up @@ -245,7 +245,6 @@ public static class FeatureFlagKeys
/// on the desktop client.
/// </summary>
public const string UseSdkPasswordGenerators = "pm-19976-use-sdk-password-generators";
public const string SendEmailOTP = "pm-19051-send-email-verification";
public const string SendControls = "pm-31885-send-controls";
public const string SdkSendsApi = "pm-30110-sdk-sends-api";
public const string SendEventLogging = "pm-36560-send-event-logging";
Expand Down
52 changes: 0 additions & 52 deletions src/Core/Tools/SendFeatures/Commands/AnonymousSendCommand.cs

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ public static class SendServiceCollectionExtension
public static void AddSendServices(this IServiceCollection services)
{
services.AddScoped<INonAnonymousSendCommand, NonAnonymousSendCommand>();
services.AddScoped<IAnonymousSendCommand, AnonymousSendCommand>();
services.AddScoped<ISendAuthorizationService, SendAuthorizationService>();
services.AddScoped<ISendValidationService, SendValidationService>();
services.AddScoped<ISendCoreHelperService, SendCoreHelperService>();
Expand Down
Loading
Loading