1
0
mirror of https://github.com/bitwarden/mobile.git synced 2024-06-28 10:54:59 +02:00

PM-1575 Display error toast if there is a duplicate passkey when moving a cipher to an org

This commit is contained in:
Federico Maccaroni 2023-06-29 17:55:46 -03:00
parent 09bbf6f875
commit 78e6353602
No known key found for this signature in database
GPG Key ID: 5D233F8F2B034536
5 changed files with 58 additions and 3 deletions

View File

@ -113,8 +113,15 @@ namespace Bit.App.Pages
try try
{ {
await _deviceActionService.ShowLoadingAsync(AppResources.Saving); await _deviceActionService.ShowLoadingAsync(AppResources.Saving);
await _cipherService.ShareWithServerAsync(cipherView, OrganizationId, checkedCollectionIds); var error = await _cipherService.ShareWithServerAsync(cipherView, OrganizationId, checkedCollectionIds);
await _deviceActionService.HideLoadingAsync(); await _deviceActionService.HideLoadingAsync();
if (error == ICipherService.ShareWithServerError.DuplicatedPasskeyInOrg)
{
_platformUtilsService.ShowToast(null, null, AppResources.ThisItemCannotBeSharedWithTheOrganizationBecauseThereIsOneAlreadyWithTheSamePasskey);
return false;
}
var movedItemToOrgText = string.Format(AppResources.MovedItemToOrg, cipherView.Name, var movedItemToOrgText = string.Format(AppResources.MovedItemToOrg, cipherView.Name,
(await _organizationService.GetAsync(OrganizationId)).Name); (await _organizationService.GetAsync(OrganizationId)).Name);
_platformUtilsService.ShowToast("success", null, movedItemToOrgText); _platformUtilsService.ShowToast("success", null, movedItemToOrgText);

View File

@ -6236,6 +6236,16 @@ namespace Bit.App.Resources {
} }
} }
/// <summary>
/// Looks up a localized string similar to This item cannot be shared with the organization because there is one already with the same passkey..
/// </summary>
public static string ThisItemCannotBeSharedWithTheOrganizationBecauseThereIsOneAlreadyWithTheSamePasskey {
get {
return ResourceManager.GetString("ThisItemCannotBeSharedWithTheOrganizationBecauseThereIsOneAlreadyWithTheSamePassk" +
"ey", resourceCulture);
}
}
/// <summary> /// <summary>
/// Looks up a localized string similar to This request is no longer valid. /// Looks up a localized string similar to This request is no longer valid.
/// </summary> /// </summary>

View File

@ -2671,4 +2671,7 @@ Do you want to switch to this account?</value>
<data name="InvalidAPIToken" xml:space="preserve"> <data name="InvalidAPIToken" xml:space="preserve">
<value>Invalid API token</value> <value>Invalid API token</value>
</data> </data>
<data name="ThisItemCannotBeSharedWithTheOrganizationBecauseThereIsOneAlreadyWithTheSamePasskey" xml:space="preserve">
<value>This item cannot be shared with the organization because there is one already with the same passkey.</value>
</data>
</root> </root>

View File

@ -10,6 +10,12 @@ namespace Bit.Core.Abstractions
{ {
public interface ICipherService public interface ICipherService
{ {
public enum ShareWithServerError
{
None,
DuplicatedPasskeyInOrg
}
Task ClearAsync(string userId); Task ClearAsync(string userId);
Task ClearCacheAsync(); Task ClearCacheAsync();
Task DeleteAsync(List<string> ids); Task DeleteAsync(List<string> ids);
@ -31,7 +37,7 @@ namespace Bit.Core.Abstractions
Task SaveCollectionsWithServerAsync(Cipher cipher); Task SaveCollectionsWithServerAsync(Cipher cipher);
Task SaveNeverDomainAsync(string domain); Task SaveNeverDomainAsync(string domain);
Task SaveWithServerAsync(Cipher cipher); Task SaveWithServerAsync(Cipher cipher);
Task ShareWithServerAsync(CipherView cipher, string organizationId, HashSet<string> collectionIds); Task<ShareWithServerError> ShareWithServerAsync(CipherView cipher, string organizationId, HashSet<string> collectionIds);
Task UpdateLastUsedDateAsync(string id); Task UpdateLastUsedDateAsync(string id);
Task UpsertAsync(CipherData cipher); Task UpsertAsync(CipherData cipher);
Task UpsertAsync(List<CipherData> cipher); Task UpsertAsync(List<CipherData> cipher);

View File

@ -532,8 +532,13 @@ namespace Bit.Core.Services
await UpsertAsync(data); await UpsertAsync(data);
} }
public async Task ShareWithServerAsync(CipherView cipher, string organizationId, HashSet<string> collectionIds) public async Task<ICipherService.ShareWithServerError> ShareWithServerAsync(CipherView cipher, string organizationId, HashSet<string> collectionIds)
{ {
if (!await ValidateCanBeSharedWithOrgAsync(cipher, organizationId))
{
return ICipherService.ShareWithServerError.DuplicatedPasskeyInOrg;
}
var attachmentTasks = new List<Task>(); var attachmentTasks = new List<Task>();
if (cipher.Attachments != null) if (cipher.Attachments != null)
{ {
@ -554,6 +559,30 @@ namespace Bit.Core.Services
var userId = await _stateService.GetActiveUserIdAsync(); var userId = await _stateService.GetActiveUserIdAsync();
var data = new CipherData(response, userId, collectionIds); var data = new CipherData(response, userId, collectionIds);
await UpsertAsync(data); await UpsertAsync(data);
return ICipherService.ShareWithServerError.None;
}
private async Task<bool> ValidateCanBeSharedWithOrgAsync(CipherView cipher, string organizationId)
{
if (cipher.Login?.Fido2Key is null && cipher.Fido2Key is null)
{
return true;
}
var decCiphers = await GetAllDecryptedAsync();
var orgCiphers = decCiphers.Where(c => c.OrganizationId == organizationId);
if (cipher.Login?.Fido2Key != null)
{
return !orgCiphers.Any(c => c.Login?.Fido2Key?.RpId == cipher.Login.Fido2Key.RpId);
}
if (cipher.Fido2Key != null)
{
return !orgCiphers.Any(c => c.Fido2Key?.RpId == cipher.Fido2Key.RpId);
}
return true;
} }
public async Task<Cipher> SaveAttachmentRawWithServerAsync(Cipher cipher, string filename, byte[] data) public async Task<Cipher> SaveAttachmentRawWithServerAsync(Cipher cipher, string filename, byte[] data)