55using Bit . Api . Tools . Models . Response ;
66using Bit . Api . Utilities ;
77using Bit . Core ;
8+ using Bit . Core . Auth . Identity ;
9+ using Bit . Core . Auth . UserFeatures . SendAccess ;
810using Bit . Core . Exceptions ;
911using Bit . Core . Services ;
1012using 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 ) ;
0 commit comments