Skip to content

Commit 93f93d8

Browse files
committed
new endpoints added but lack test coverage
1 parent 0bc27d0 commit 93f93d8

File tree

2 files changed

+85
-14
lines changed

2 files changed

+85
-14
lines changed

src/Api/Tools/Controllers/SendsController.cs

Lines changed: 79 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
using Bit.Api.Tools.Models.Response;
66
using Bit.Api.Utilities;
77
using Bit.Core;
8+
using Bit.Core.Auth.Identity;
9+
using Bit.Core.Auth.UserFeatures.SendAccess;
810
using Bit.Core.Exceptions;
911
using Bit.Core.Services;
1012
using Bit.Core.Tools.Enums;
@@ -30,10 +32,10 @@ public class SendsController : Controller
3032
private readonly ISendFileStorageService _sendFileStorageService;
3133
private readonly IAnonymousSendCommand _anonymousSendCommand;
3234
private readonly INonAnonymousSendCommand _nonAnonymousSendCommand;
33-
3435
private readonly ISendOwnerQuery _sendOwnerQuery;
35-
3636
private readonly ILogger<SendsController> _logger;
37+
private readonly IFeatureService _featureService;
38+
private readonly ISendAuthenticationQuery _sendAuthenticationQuery;
3739

3840
public SendsController(
3941
ISendRepository sendRepository,
@@ -43,7 +45,9 @@ public SendsController(
4345
INonAnonymousSendCommand nonAnonymousSendCommand,
4446
ISendOwnerQuery sendOwnerQuery,
4547
ISendFileStorageService sendFileStorageService,
46-
ILogger<SendsController> logger)
48+
ILogger<SendsController> logger,
49+
IFeatureService featureService,
50+
ISendAuthenticationQuery sendAuthenticationQuery)
4751
{
4852
_sendRepository = sendRepository;
4953
_userService = userService;
@@ -53,6 +57,8 @@ public SendsController(
5357
_sendOwnerQuery = sendOwnerQuery;
5458
_sendFileStorageService = sendFileStorageService;
5559
_logger = logger;
60+
_featureService = featureService;
61+
_sendAuthenticationQuery = sendAuthenticationQuery;
5662
}
5763

5864
#region Anonymous endpoints
@@ -69,21 +75,33 @@ public async Task<IActionResult> Access(string id, [FromBody] SendAccessRequestM
6975

7076
var guid = new Guid(CoreHelpers.Base64UrlDecode(id));
7177
var send = await _sendRepository.GetByIdAsync(guid);
78+
79+
var sendEmailOtpEnabled = _featureService.IsEnabled(FeatureFlagKeys.SendEmailOTP);
80+
var authMethod = await _sendAuthenticationQuery.GetAuthenticationMethod(guid);
81+
82+
if (authMethod is EmailOtp && sendEmailOtpEnabled)
83+
{
84+
return new UnauthorizedResult();
85+
}
86+
7287
if (send == null)
7388
{
7489
throw new BadRequestException("Could not locate send");
7590
}
91+
7692
var sendAuthResult =
7793
await _sendAuthorizationService.AccessAsync(send, model.Password);
7894
if (sendAuthResult.Equals(SendAccessResult.PasswordRequired))
7995
{
8096
return new UnauthorizedResult();
8197
}
98+
8299
if (sendAuthResult.Equals(SendAccessResult.PasswordInvalid))
83100
{
84101
await Task.Delay(2000);
85102
throw new BadRequestException("Invalid password.");
86103
}
104+
87105
if (sendAuthResult.Equals(SendAccessResult.Denied))
88106
{
89107
throw new NotFoundException();
@@ -95,6 +113,7 @@ public async Task<IActionResult> Access(string id, [FromBody] SendAccessRequestM
95113
var creator = await _userService.GetUserByIdAsync(send.UserId.Value);
96114
sendResponse.CreatorIdentifier = creator.Email;
97115
}
116+
98117
return new ObjectResult(sendResponse);
99118
}
100119

@@ -113,6 +132,14 @@ public async Task<IActionResult> GetSendFileDownloadData(string encodedSendId,
113132
var sendId = new Guid(CoreHelpers.Base64UrlDecode(encodedSendId));
114133
var send = await _sendRepository.GetByIdAsync(sendId);
115134

135+
var sendEmailOtpEnabled = _featureService.IsEnabled(FeatureFlagKeys.SendEmailOTP);
136+
var authMethod = await _sendAuthenticationQuery.GetAuthenticationMethod(sendId);
137+
138+
if (authMethod is EmailOtp && sendEmailOtpEnabled)
139+
{
140+
return new UnauthorizedResult();
141+
}
142+
116143
if (send == null)
117144
{
118145
throw new BadRequestException("Could not locate send");
@@ -125,21 +152,19 @@ public async Task<IActionResult> GetSendFileDownloadData(string encodedSendId,
125152
{
126153
return new UnauthorizedResult();
127154
}
155+
128156
if (result.Equals(SendAccessResult.PasswordInvalid))
129157
{
130158
await Task.Delay(2000);
131159
throw new BadRequestException("Invalid password.");
132160
}
161+
133162
if (result.Equals(SendAccessResult.Denied))
134163
{
135164
throw new NotFoundException();
136165
}
137166

138-
return new ObjectResult(new SendFileDownloadDataResponseModel()
139-
{
140-
Id = fileId,
141-
Url = url,
142-
});
167+
return new ObjectResult(new SendFileDownloadDataResponseModel() { Id = fileId, Url = url, });
143168
}
144169

145170
[AllowAnonymous]
@@ -153,7 +178,8 @@ public async Task<ObjectResult> AzureValidateFile()
153178
{
154179
try
155180
{
156-
var blobName = eventGridEvent.Subject.Split($"{AzureSendFileStorageService.FilesContainerName}/blobs/")[1];
181+
var blobName =
182+
eventGridEvent.Subject.Split($"{AzureSendFileStorageService.FilesContainerName}/blobs/")[1];
157183
var sendId = AzureSendFileStorageService.SendIdFromBlobName(blobName);
158184
var send = await _sendRepository.GetByIdAsync(new Guid(sendId));
159185
if (send == null)
@@ -162,14 +188,16 @@ public async Task<ObjectResult> AzureValidateFile()
162188
{
163189
await azureSendFileStorageService.DeleteBlobAsync(blobName);
164190
}
191+
165192
return;
166193
}
167194

168195
await _nonAnonymousSendCommand.ConfirmFileSize(send);
169196
}
170197
catch (Exception e)
171198
{
172-
_logger.LogError(e, "Uncaught exception occurred while handling event grid event: {Event}", JsonSerializer.Serialize(eventGridEvent));
199+
_logger.LogError(e, "Uncaught exception occurred while handling event grid event: {Event}",
200+
JsonSerializer.Serialize(eventGridEvent));
173201
return;
174202
}
175203
}
@@ -199,6 +227,46 @@ public async Task<ListResponseModel<SendResponseModel>> GetAll()
199227
return result;
200228
}
201229

230+
[Authorize(Policy = Policies.Send)]
231+
[RequireFeature(FeatureFlagKeys.SendEmailOTP)]
232+
[HttpPost("access/")]
233+
public async Task<IActionResult> Access([FromBody] SendAccessRequestModel model)
234+
{
235+
var guid = User.GetSendId();
236+
var send = await _sendRepository.GetByIdAsync(guid);
237+
if (send == null)
238+
{
239+
throw new BadRequestException("Could not locate send");
240+
}
241+
242+
var sendResponse = new SendAccessResponseModel(send);
243+
if (send.UserId.HasValue && !send.HideEmail.GetValueOrDefault())
244+
{
245+
var creator = await _userService.GetUserByIdAsync(send.UserId.Value);
246+
sendResponse.CreatorIdentifier = creator.Email;
247+
}
248+
249+
return new ObjectResult(sendResponse);
250+
}
251+
252+
[Authorize(Policy = Policies.Send)]
253+
[RequireFeature(FeatureFlagKeys.SendEmailOTP)]
254+
[HttpPost("access/file/{fileId}")]
255+
public async Task<IActionResult> GetSendFileDownloadData(string fileId)
256+
{
257+
var sendId = User.GetSendId();
258+
var send = await _sendRepository.GetByIdAsync(sendId);
259+
260+
if (send == null)
261+
{
262+
throw new BadRequestException("Could not locate send");
263+
}
264+
265+
var url = await _sendFileStorageService.GetSendFileDownloadUrlAsync(send, fileId);
266+
267+
return new ObjectResult(new SendFileDownloadDataResponseModel() { Id = fileId, Url = url });
268+
}
269+
202270
[HttpPost("")]
203271
public async Task<SendResponseModel> Post([FromBody] SendRequestModel model)
204272
{
@@ -279,6 +347,7 @@ public async Task PostFileForExistingSend(string id, string fileId)
279347
{
280348
throw new BadRequestException("Could not locate send");
281349
}
350+
282351
await Request.GetFileAsync(async (stream) =>
283352
{
284353
await _nonAnonymousSendCommand.UploadFileToExistingSendAsync(stream, send);

test/Api.Test/Tools/Controllers/SendsControllerTests.cs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99
using Bit.Core.Entities;
1010
using Bit.Core.Exceptions;
1111
using Bit.Core.Services;
12-
using Bit.Core.Settings;
1312
using Bit.Core.Tools.Entities;
1413
using Bit.Core.Tools.Enums;
1514
using Bit.Core.Tools.Models.Data;
@@ -28,7 +27,6 @@ namespace Bit.Api.Test.Tools.Controllers;
2827
public class SendsControllerTests : IDisposable
2928
{
3029
private readonly SendsController _sut;
31-
private readonly GlobalSettings _globalSettings;
3230
private readonly IUserService _userService;
3331
private readonly ISendRepository _sendRepository;
3432
private readonly INonAnonymousSendCommand _nonAnonymousSendCommand;
@@ -37,6 +35,8 @@ public class SendsControllerTests : IDisposable
3735
private readonly ISendAuthorizationService _sendAuthorizationService;
3836
private readonly ISendFileStorageService _sendFileStorageService;
3937
private readonly ILogger<SendsController> _logger;
38+
private readonly IFeatureService _featureService;
39+
private readonly ISendAuthenticationQuery _sendAuthenticationQuery;
4040

4141
public SendsControllerTests()
4242
{
@@ -47,8 +47,9 @@ public SendsControllerTests()
4747
_sendOwnerQuery = Substitute.For<ISendOwnerQuery>();
4848
_sendAuthorizationService = Substitute.For<ISendAuthorizationService>();
4949
_sendFileStorageService = Substitute.For<ISendFileStorageService>();
50-
_globalSettings = new GlobalSettings();
5150
_logger = Substitute.For<ILogger<SendsController>>();
51+
_featureService = Substitute.For<IFeatureService>();
52+
_sendAuthenticationQuery = Substitute.For<ISendAuthenticationQuery>();
5253

5354
_sut = new SendsController(
5455
_sendRepository,
@@ -59,7 +60,8 @@ public SendsControllerTests()
5960
_sendOwnerQuery,
6061
_sendFileStorageService,
6162
_logger,
62-
_globalSettings
63+
_featureService,
64+
_sendAuthenticationQuery
6365
);
6466
}
6567

0 commit comments

Comments
 (0)