@ -40,6 +40,10 @@ public class CiphersController : Controller
private readonly ILogger < CiphersController > _l ogger ;
private readonly ILogger < CiphersController > _l ogger ;
private readonly GlobalSettings _ globalSettings ;
private readonly GlobalSettings _ globalSettings ;
private readonly Version _ cipherKeyEncryptionMinimumVersion = new Version ( Constants . CipherKeyEncryptionMinimumVersion ) ;
private readonly Version _ cipherKeyEncryptionMinimumVersion = new Version ( Constants . CipherKeyEncryptionMinimumVersion ) ;
private readonly IFeatureService _f eatureService ;
private bool UseFlexibleCollections = >
_f eatureService . IsEnabled ( FeatureFlagKeys . FlexibleCollections , _ currentContext ) ;
public CiphersController (
public CiphersController (
ICipherRepository cipherRepository ,
ICipherRepository cipherRepository ,
@ -50,7 +54,8 @@ public class CiphersController : Controller
IProviderService providerService ,
IProviderService providerService ,
ICurrentContext currentContext ,
ICurrentContext currentContext ,
ILogger < CiphersController > logger ,
ILogger < CiphersController > logger ,
GlobalSettings globalSettings )
GlobalSettings globalSettings ,
IFeatureService featureService )
{
{
_ cipherRepository = cipherRepository ;
_ cipherRepository = cipherRepository ;
_ collectionCipherRepository = collectionCipherRepository ;
_ collectionCipherRepository = collectionCipherRepository ;
@ -61,13 +66,14 @@ public class CiphersController : Controller
_ currentContext = currentContext ;
_ currentContext = currentContext ;
_l ogger = logger ;
_l ogger = logger ;
_ globalSettings = globalSettings ;
_ globalSettings = globalSettings ;
_f eatureService = featureService ;
}
}
[HttpGet("{id}")]
[HttpGet("{id}")]
public async Task < CipherResponseModel > Get ( string id )
public async Task < CipherResponseModel > Get ( Guid id )
{
{
var userId = _ userService . GetProperUserId ( User ) . Value ;
var userId = _ userService . GetProperUserId ( User ) . Value ;
var cipher = await _ cipherRepository . GetByIdAsync ( new Guid ( id ) , userId ) ;
var cipher = await GetByIdAsync ( id , userId ) ;
if ( cipher = = null )
if ( cipher = = null )
{
{
throw new NotFoundException ( ) ;
throw new NotFoundException ( ) ;
@ -91,17 +97,16 @@ public class CiphersController : Controller
[HttpGet("{id}/full-details")]
[HttpGet("{id}/full-details")]
[HttpGet("{id}/details")]
[HttpGet("{id}/details")]
public async Task < CipherDetailsResponseModel > GetDetails ( string id )
public async Task < CipherDetailsResponseModel > GetDetails ( Guid id )
{
{
var userId = _ userService . GetProperUserId ( User ) . Value ;
var userId = _ userService . GetProperUserId ( User ) . Value ;
var cipherId = new Guid ( id ) ;
var cipher = await GetByIdAsync ( id , userId ) ;
var cipher = await _ cipherRepository . GetByIdAsync ( cipherId , userId ) ;
if ( cipher = = null )
if ( cipher = = null )
{
{
throw new NotFoundException ( ) ;
throw new NotFoundException ( ) ;
}
}
var collectionCiphers = await _ collectionCipherRepository . GetManyByUserIdCipherIdAsync ( userId , c ipherI d) ;
var collectionCiphers = await _ collectionCipherRepository . GetManyByUserIdCipherIdAsync ( userId , id ) ;
return new CipherDetailsResponseModel ( cipher , _ globalSettings , collectionCiphers ) ;
return new CipherDetailsResponseModel ( cipher , _ globalSettings , collectionCiphers ) ;
}
}
@ -111,7 +116,7 @@ public class CiphersController : Controller
var userId = _ userService . GetProperUserId ( User ) . Value ;
var userId = _ userService . GetProperUserId ( User ) . Value ;
var hasOrgs = _ currentContext . Organizations ? . Any ( ) ? ? false ;
var hasOrgs = _ currentContext . Organizations ? . Any ( ) ? ? false ;
// TODO: Use hasOrgs proper for cipher listing here?
// TODO: Use hasOrgs proper for cipher listing here?
var ciphers = await _ cipherRepository . GetManyByUserIdAsync ( userId , true | | hasOrgs ) ;
var ciphers = await _ cipherRepository . GetManyByUserIdAsync ( userId , useFlexibleCollections : UseFlexibleCollections , withOrganizations : true | | hasOrgs ) ;
Dictionary < Guid , IGrouping < Guid , CollectionCipher > > collectionCiphersGroupDict = null ;
Dictionary < Guid , IGrouping < Guid , CollectionCipher > > collectionCiphersGroupDict = null ;
if ( hasOrgs )
if ( hasOrgs )
{
{
@ -175,7 +180,7 @@ public class CiphersController : Controller
public async Task < CipherResponseModel > Put ( Guid id , [ FromBody ] CipherRequestModel model )
public async Task < CipherResponseModel > Put ( Guid id , [ FromBody ] CipherRequestModel model )
{
{
var userId = _ userService . GetProperUserId ( User ) . Value ;
var userId = _ userService . GetProperUserId ( User ) . Value ;
var cipher = await _ cipherRepository . GetByIdAsync ( id , userId ) ;
var cipher = await GetByIdAsync ( id , userId ) ;
if ( cipher = = null )
if ( cipher = = null )
{
{
throw new NotFoundException ( ) ;
throw new NotFoundException ( ) ;
@ -247,25 +252,23 @@ public class CiphersController : Controller
[HttpPut("{id}/partial")]
[HttpPut("{id}/partial")]
[HttpPost("{id}/partial")]
[HttpPost("{id}/partial")]
public async Task < CipherResponseModel > PutPartial ( string id , [ FromBody ] CipherPartialRequestModel model )
public async Task < CipherResponseModel > PutPartial ( Guid id , [ FromBody ] CipherPartialRequestModel model )
{
{
var userId = _ userService . GetProperUserId ( User ) . Value ;
var userId = _ userService . GetProperUserId ( User ) . Value ;
var folderId = string . IsNullOrWhiteSpace ( model . FolderId ) ? null : ( Guid ? ) new Guid ( model . FolderId ) ;
var folderId = string . IsNullOrWhiteSpace ( model . FolderId ) ? null : ( Guid ? ) new Guid ( model . FolderId ) ;
var cipherId = new Guid ( id ) ;
await _ cipherRepository . UpdatePartialAsync ( id , userId , folderId , model . Favorite ) ;
await _ cipherRepository . UpdatePartialAsync ( cipherId , userId , folderId , model . Favorite ) ;
var cipher = await _ cipherRepository . GetByIdAsync ( c ipherI d, userId ) ;
var cipher = await GetByIdAsync ( id , userId ) ;
var response = new CipherResponseModel ( cipher , _ globalSettings ) ;
var response = new CipherResponseModel ( cipher , _ globalSettings ) ;
return response ;
return response ;
}
}
[HttpPut("{id}/share")]
[HttpPut("{id}/share")]
[HttpPost("{id}/share")]
[HttpPost("{id}/share")]
public async Task < CipherResponseModel > PutShare ( string id , [ FromBody ] CipherShareRequestModel model )
public async Task < CipherResponseModel > PutShare ( Guid id , [ FromBody ] CipherShareRequestModel model )
{
{
var userId = _ userService . GetProperUserId ( User ) . Value ;
var userId = _ userService . GetProperUserId ( User ) . Value ;
var cipherId = new Guid ( id ) ;
var cipher = await _ cipherRepository . GetByIdAsync ( id ) ;
var cipher = await _ cipherRepository . GetByIdAsync ( cipherId ) ;
if ( cipher = = null | | cipher . UserId ! = userId | |
if ( cipher = = null | | cipher . UserId ! = userId | |
! await _ currentContext . OrganizationUser ( new Guid ( model . Cipher . OrganizationId ) ) )
! await _ currentContext . OrganizationUser ( new Guid ( model . Cipher . OrganizationId ) ) )
{
{
@ -279,17 +282,17 @@ public class CiphersController : Controller
await _ cipherService . ShareAsync ( original , model . Cipher . ToCipher ( cipher ) , new Guid ( model . Cipher . OrganizationId ) ,
await _ cipherService . ShareAsync ( original , model . Cipher . ToCipher ( cipher ) , new Guid ( model . Cipher . OrganizationId ) ,
model . CollectionIds . Select ( c = > new Guid ( c ) ) , userId , model . Cipher . LastKnownRevisionDate ) ;
model . CollectionIds . Select ( c = > new Guid ( c ) ) , userId , model . Cipher . LastKnownRevisionDate ) ;
var sharedCipher = await _ cipherRepository . GetByIdAsync ( c ipherI d, userId ) ;
var sharedCipher = await GetByIdAsync ( id , userId ) ;
var response = new CipherResponseModel ( sharedCipher , _ globalSettings ) ;
var response = new CipherResponseModel ( sharedCipher , _ globalSettings ) ;
return response ;
return response ;
}
}
[HttpPut("{id}/collections")]
[HttpPut("{id}/collections")]
[HttpPost("{id}/collections")]
[HttpPost("{id}/collections")]
public async Task PutCollections ( string id , [ FromBody ] CipherCollectionsRequestModel model )
public async Task PutCollections ( Guid id , [ FromBody ] CipherCollectionsRequestModel model )
{
{
var userId = _ userService . GetProperUserId ( User ) . Value ;
var userId = _ userService . GetProperUserId ( User ) . Value ;
var cipher = await _ cipherRepository . GetByIdAsync ( new Guid ( id ) , userId ) ;
var cipher = await GetByIdAsync ( id , userId ) ;
if ( cipher = = null | | ! cipher . OrganizationId . HasValue | |
if ( cipher = = null | | ! cipher . OrganizationId . HasValue | |
! await _ currentContext . OrganizationUser ( cipher . OrganizationId . Value ) )
! await _ currentContext . OrganizationUser ( cipher . OrganizationId . Value ) )
{
{
@ -318,10 +321,10 @@ public class CiphersController : Controller
[HttpDelete("{id}")]
[HttpDelete("{id}")]
[HttpPost("{id}/delete")]
[HttpPost("{id}/delete")]
public async Task Delete ( string id )
public async Task Delete ( Guid id )
{
{
var userId = _ userService . GetProperUserId ( User ) . Value ;
var userId = _ userService . GetProperUserId ( User ) . Value ;
var cipher = await _ cipherRepository . GetByIdAsync ( new Guid ( id ) , userId ) ;
var cipher = await GetByIdAsync ( id , userId ) ;
if ( cipher = = null )
if ( cipher = = null )
{
{
throw new NotFoundException ( ) ;
throw new NotFoundException ( ) ;
@ -380,10 +383,10 @@ public class CiphersController : Controller
}
}
[HttpPut("{id}/delete")]
[HttpPut("{id}/delete")]
public async Task PutDelete ( string id )
public async Task PutDelete ( Guid id )
{
{
var userId = _ userService . GetProperUserId ( User ) . Value ;
var userId = _ userService . GetProperUserId ( User ) . Value ;
var cipher = await _ cipherRepository . GetByIdAsync ( new Guid ( id ) , userId ) ;
var cipher = await GetByIdAsync ( id , userId ) ;
if ( cipher = = null )
if ( cipher = = null )
{
{
throw new NotFoundException ( ) ;
throw new NotFoundException ( ) ;
@ -436,10 +439,10 @@ public class CiphersController : Controller
}
}
[HttpPut("{id}/restore")]
[HttpPut("{id}/restore")]
public async Task < CipherResponseModel > PutRestore ( string id )
public async Task < CipherResponseModel > PutRestore ( Guid id )
{
{
var userId = _ userService . GetProperUserId ( User ) . Value ;
var userId = _ userService . GetProperUserId ( User ) . Value ;
var cipher = await _ cipherRepository . GetByIdAsync ( new Guid ( id ) , userId ) ;
var cipher = await GetByIdAsync ( id , userId ) ;
if ( cipher = = null )
if ( cipher = = null )
{
{
throw new NotFoundException ( ) ;
throw new NotFoundException ( ) ;
@ -526,7 +529,7 @@ public class CiphersController : Controller
}
}
var userId = _ userService . GetProperUserId ( User ) . Value ;
var userId = _ userService . GetProperUserId ( User ) . Value ;
var ciphers = await _ cipherRepository . GetManyByUserIdAsync ( userId , false ) ;
var ciphers = await _ cipherRepository . GetManyByUserIdAsync ( userId , useFlexibleCollections : UseFlexibleCollections , withOrganizations : false ) ;
var ciphersDict = ciphers . ToDictionary ( c = > c . Id ) ;
var ciphersDict = ciphers . ToDictionary ( c = > c . Id ) ;
var shareCiphers = new List < ( Cipher , DateTime ? ) > ( ) ;
var shareCiphers = new List < ( Cipher , DateTime ? ) > ( ) ;
@ -581,13 +584,12 @@ public class CiphersController : Controller
}
}
[HttpPost("{id}/attachment/v2")]
[HttpPost("{id}/attachment/v2")]
public async Task < AttachmentUploadDataResponseModel > PostAttachment ( string id , [ FromBody ] AttachmentRequestModel request )
public async Task < AttachmentUploadDataResponseModel > PostAttachment ( Guid id , [ FromBody ] AttachmentRequestModel request )
{
{
var idGuid = new Guid ( id ) ;
var userId = _ userService . GetProperUserId ( User ) . Value ;
var userId = _ userService . GetProperUserId ( User ) . Value ;
var cipher = request . AdminRequest ?
var cipher = request . AdminRequest ?
await _ cipherRepository . GetOrganizationDetailsByIdAsync ( idGuid ) :
await _ cipherRepository . GetOrganizationDetailsByIdAsync ( id ) :
await _ cipherRepository . GetByIdAsync ( idGu id, userId ) ;
await GetByIdAsync ( id , userId ) ;
if ( cipher = = null | | ( request . AdminRequest & & ( ! cipher . OrganizationId . HasValue | |
if ( cipher = = null | | ( request . AdminRequest & & ( ! cipher . OrganizationId . HasValue | |
! await _ currentContext . EditAnyCollection ( cipher . OrganizationId . Value ) ) ) )
! await _ currentContext . EditAnyCollection ( cipher . OrganizationId . Value ) ) ) )
@ -615,11 +617,10 @@ public class CiphersController : Controller
}
}
[HttpGet("{id}/attachment/{attachmentId}/renew")]
[HttpGet("{id}/attachment/{attachmentId}/renew")]
public async Task < AttachmentUploadDataResponseModel > RenewFileUploadUrl ( string id , string attachmentId )
public async Task < AttachmentUploadDataResponseModel > RenewFileUploadUrl ( Guid id , string attachmentId )
{
{
var userId = _ userService . GetProperUserId ( User ) . Value ;
var userId = _ userService . GetProperUserId ( User ) . Value ;
var cipherId = new Guid ( id ) ;
var cipher = await GetByIdAsync ( id , userId ) ;
var cipher = await _ cipherRepository . GetByIdAsync ( cipherId , userId ) ;
var attachments = cipher ? . GetAttachments ( ) ;
var attachments = cipher ? . GetAttachments ( ) ;
if ( attachments = = null | | ! attachments . ContainsKey ( attachmentId ) | | attachments [ attachmentId ] . Validated )
if ( attachments = = null | | ! attachments . ContainsKey ( attachmentId ) | | attachments [ attachmentId ] . Validated )
@ -638,7 +639,7 @@ public class CiphersController : Controller
[SelfHosted(SelfHostedOnly = true)]
[SelfHosted(SelfHostedOnly = true)]
[RequestSizeLimit(Constants.FileSize501mb)]
[RequestSizeLimit(Constants.FileSize501mb)]
[DisableFormValueModelBinding]
[DisableFormValueModelBinding]
public async Task PostFileForExistingAttachment ( string id , string attachmentId )
public async Task PostFileForExistingAttachment ( Guid id , string attachmentId )
{
{
if ( ! Request ? . ContentType . Contains ( "multipart/" ) ? ? true )
if ( ! Request ? . ContentType . Contains ( "multipart/" ) ? ? true )
{
{
@ -646,7 +647,7 @@ public class CiphersController : Controller
}
}
var userId = _ userService . GetProperUserId ( User ) . Value ;
var userId = _ userService . GetProperUserId ( User ) . Value ;
var cipher = await _ cipherRepository . GetByIdAsync ( new Guid ( id ) , userId ) ;
var cipher = await GetByIdAsync ( id , userId ) ;
var attachments = cipher ? . GetAttachments ( ) ;
var attachments = cipher ? . GetAttachments ( ) ;
if ( attachments = = null | | ! attachments . ContainsKey ( attachmentId ) )
if ( attachments = = null | | ! attachments . ContainsKey ( attachmentId ) )
{
{
@ -664,13 +665,12 @@ public class CiphersController : Controller
[Obsolete("Deprecated Attachments API", false)]
[Obsolete("Deprecated Attachments API", false)]
[RequestSizeLimit(Constants.FileSize101mb)]
[RequestSizeLimit(Constants.FileSize101mb)]
[DisableFormValueModelBinding]
[DisableFormValueModelBinding]
public async Task < CipherResponseModel > PostAttachment ( string id )
public async Task < CipherResponseModel > PostAttachment ( Guid id )
{
{
ValidateAttachment ( ) ;
ValidateAttachment ( ) ;
var idGuid = new Guid ( id ) ;
var userId = _ userService . GetProperUserId ( User ) . Value ;
var userId = _ userService . GetProperUserId ( User ) . Value ;
var cipher = await _ cipherRepository . GetByIdAsync ( idGu id, userId ) ;
var cipher = await GetByIdAsync ( id , userId ) ;
if ( cipher = = null )
if ( cipher = = null )
{
{
throw new NotFoundException ( ) ;
throw new NotFoundException ( ) ;
@ -711,10 +711,10 @@ public class CiphersController : Controller
}
}
[HttpGet("{id}/attachment/{attachmentId}")]
[HttpGet("{id}/attachment/{attachmentId}")]
public async Task < AttachmentResponseModel > GetAttachmentData ( string id , string attachmentId )
public async Task < AttachmentResponseModel > GetAttachmentData ( Guid id , string attachmentId )
{
{
var userId = _ userService . GetProperUserId ( User ) . Value ;
var userId = _ userService . GetProperUserId ( User ) . Value ;
var cipher = await _ cipherRepository . GetByIdAsync ( new Guid ( id ) , userId ) ;
var cipher = await GetByIdAsync ( id , userId ) ;
var result = await _ cipherService . GetAttachmentDownloadDataAsync ( cipher , attachmentId ) ;
var result = await _ cipherService . GetAttachmentDownloadDataAsync ( cipher , attachmentId ) ;
return new AttachmentResponseModel ( result ) ;
return new AttachmentResponseModel ( result ) ;
}
}
@ -742,11 +742,10 @@ public class CiphersController : Controller
[HttpDelete("{id}/attachment/{attachmentId}")]
[HttpDelete("{id}/attachment/{attachmentId}")]
[HttpPost("{id}/attachment/{attachmentId}/delete")]
[HttpPost("{id}/attachment/{attachmentId}/delete")]
public async Task DeleteAttachment ( string id , string attachmentId )
public async Task DeleteAttachment ( Guid id , string attachmentId )
{
{
var idGuid = new Guid ( id ) ;
var userId = _ userService . GetProperUserId ( User ) . Value ;
var userId = _ userService . GetProperUserId ( User ) . Value ;
var cipher = await _ cipherRepository . GetByIdAsync ( idGu id, userId ) ;
var cipher = await GetByIdAsync ( id , userId ) ;
if ( cipher = = null )
if ( cipher = = null )
{
{
throw new NotFoundException ( ) ;
throw new NotFoundException ( ) ;
@ -836,4 +835,9 @@ public class CiphersController : Controller
}
}
}
}
}
}
private async Task < CipherDetails > GetByIdAsync ( Guid cipherId , Guid userId )
{
return await _ cipherRepository . GetByIdAsync ( cipherId , userId , UseFlexibleCollections ) ;
}
}
}