mirror of
https://github.com/bitwarden/android.git
synced 2024-12-25 02:18:27 +03:00
refactoring code for login => cipher support
This commit is contained in:
parent
37f05f0a12
commit
1d6ec0f953
46 changed files with 731 additions and 410 deletions
|
@ -195,7 +195,7 @@ namespace Bit.Android
|
||||||
container.RegisterSingleton<IKeyDerivationService, BouncyCastleKeyDerivationService>();
|
container.RegisterSingleton<IKeyDerivationService, BouncyCastleKeyDerivationService>();
|
||||||
container.RegisterSingleton<IAuthService, AuthService>();
|
container.RegisterSingleton<IAuthService, AuthService>();
|
||||||
container.RegisterSingleton<IFolderService, FolderService>();
|
container.RegisterSingleton<IFolderService, FolderService>();
|
||||||
container.RegisterSingleton<ILoginService, LoginService>();
|
container.RegisterSingleton<ICipherService, CipherService>();
|
||||||
container.RegisterSingleton<ISyncService, SyncService>();
|
container.RegisterSingleton<ISyncService, SyncService>();
|
||||||
container.RegisterSingleton<IDeviceActionService, DeviceActionService>();
|
container.RegisterSingleton<IDeviceActionService, DeviceActionService>();
|
||||||
container.RegisterSingleton<IAppIdService, AppIdService>();
|
container.RegisterSingleton<IAppIdService, AppIdService>();
|
||||||
|
@ -216,7 +216,7 @@ namespace Bit.Android
|
||||||
// Repositories
|
// Repositories
|
||||||
container.RegisterSingleton<IFolderRepository, FolderRepository>();
|
container.RegisterSingleton<IFolderRepository, FolderRepository>();
|
||||||
container.RegisterSingleton<IFolderApiRepository, FolderApiRepository>();
|
container.RegisterSingleton<IFolderApiRepository, FolderApiRepository>();
|
||||||
container.RegisterSingleton<ILoginRepository, LoginRepository>();
|
container.RegisterSingleton<ICipherRepository, CipherRepository>();
|
||||||
container.RegisterSingleton<IAttachmentRepository, AttachmentRepository>();
|
container.RegisterSingleton<IAttachmentRepository, AttachmentRepository>();
|
||||||
container.RegisterSingleton<IConnectApiRepository, ConnectApiRepository>();
|
container.RegisterSingleton<IConnectApiRepository, ConnectApiRepository>();
|
||||||
container.RegisterSingleton<IDeviceApiRepository, DeviceApiRepository>();
|
container.RegisterSingleton<IDeviceApiRepository, DeviceApiRepository>();
|
||||||
|
|
|
@ -7,7 +7,7 @@ namespace Bit.App.Abstractions
|
||||||
{
|
{
|
||||||
public interface IAttachmentRepository : IRepository<AttachmentData, string>
|
public interface IAttachmentRepository : IRepository<AttachmentData, string>
|
||||||
{
|
{
|
||||||
Task<IEnumerable<AttachmentData>> GetAllByLoginIdAsync(string loginId);
|
Task<IEnumerable<AttachmentData>> GetAllByCipherIdAsync(string cipherId);
|
||||||
Task<IEnumerable<AttachmentData>> GetAllByUserIdAsync(string userId);
|
Task<IEnumerable<AttachmentData>> GetAllByUserIdAsync(string userId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
13
src/App/Abstractions/Repositories/ICipherRepository.cs
Normal file
13
src/App/Abstractions/Repositories/ICipherRepository.cs
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Bit.App.Models.Data;
|
||||||
|
|
||||||
|
namespace Bit.App.Abstractions
|
||||||
|
{
|
||||||
|
public interface ICipherRepository : IRepository<CipherData, string>
|
||||||
|
{
|
||||||
|
Task<IEnumerable<CipherData>> GetAllByUserIdAsync(string userId);
|
||||||
|
Task<IEnumerable<CipherData>> GetAllByUserIdAsync(string userId, bool favorite);
|
||||||
|
}
|
||||||
|
}
|
|
@ -8,6 +8,6 @@ namespace Bit.App.Abstractions
|
||||||
public interface IFolderRepository : IRepository<FolderData, string>
|
public interface IFolderRepository : IRepository<FolderData, string>
|
||||||
{
|
{
|
||||||
Task<IEnumerable<FolderData>> GetAllByUserIdAsync(string userId);
|
Task<IEnumerable<FolderData>> GetAllByUserIdAsync(string userId);
|
||||||
Task DeleteWithLoginUpdateAsync(string id, DateTime revisionDate);
|
Task DeleteWithCipherUpdateAsync(string id, DateTime revisionDate);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,13 +0,0 @@
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Bit.App.Models.Data;
|
|
||||||
|
|
||||||
namespace Bit.App.Abstractions
|
|
||||||
{
|
|
||||||
public interface ILoginRepository : IRepository<LoginData, string>
|
|
||||||
{
|
|
||||||
Task<IEnumerable<LoginData>> GetAllByUserIdAsync(string userId);
|
|
||||||
Task<IEnumerable<LoginData>> GetAllByUserIdAsync(string userId, bool favorite);
|
|
||||||
}
|
|
||||||
}
|
|
21
src/App/Abstractions/Services/ICipherService.cs
Normal file
21
src/App/Abstractions/Services/ICipherService.cs
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Bit.App.Models;
|
||||||
|
using Bit.App.Models.Api;
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace Bit.App.Abstractions
|
||||||
|
{
|
||||||
|
public interface ICipherService
|
||||||
|
{
|
||||||
|
Task<Cipher> GetByIdAsync(string id);
|
||||||
|
Task<IEnumerable<Cipher>> GetAllAsync();
|
||||||
|
Task<IEnumerable<Cipher>> GetAllAsync(bool favorites);
|
||||||
|
Task<Tuple<IEnumerable<Cipher>, IEnumerable<Cipher>>> GetAllAsync(string uriString);
|
||||||
|
Task<ApiResult<CipherResponse>> SaveAsync(Cipher login);
|
||||||
|
Task<ApiResult> DeleteAsync(string id);
|
||||||
|
Task<byte[]> DownloadAndDecryptAttachmentAsync(string url, string orgId = null);
|
||||||
|
Task<ApiResult<CipherResponse>> EncryptAndSaveAttachmentAsync(Cipher login, byte[] data, string fileName);
|
||||||
|
Task<ApiResult> DeleteAttachmentAsync(Cipher login, string attachmentId);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,21 +0,0 @@
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Bit.App.Models;
|
|
||||||
using Bit.App.Models.Api;
|
|
||||||
using System;
|
|
||||||
|
|
||||||
namespace Bit.App.Abstractions
|
|
||||||
{
|
|
||||||
public interface ILoginService
|
|
||||||
{
|
|
||||||
Task<Login> GetByIdAsync(string id);
|
|
||||||
Task<IEnumerable<Login>> GetAllAsync();
|
|
||||||
Task<IEnumerable<Login>> GetAllAsync(bool favorites);
|
|
||||||
Task<Tuple<IEnumerable<Login>, IEnumerable<Login>>> GetAllAsync(string uriString);
|
|
||||||
Task<ApiResult<CipherResponse>> SaveAsync(Login login);
|
|
||||||
Task<ApiResult> DeleteAsync(string id);
|
|
||||||
Task<byte[]> DownloadAndDecryptAttachmentAsync(string url, string orgId = null);
|
|
||||||
Task<ApiResult<CipherResponse>> EncryptAndSaveAttachmentAsync(Login login, byte[] data, string fileName);
|
|
||||||
Task<ApiResult> DeleteAttachmentAsync(Login login, string attachmentId);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -9,7 +9,7 @@ namespace Bit.App.Abstractions
|
||||||
Task<bool> SyncCipherAsync(string id);
|
Task<bool> SyncCipherAsync(string id);
|
||||||
Task<bool> SyncFolderAsync(string id);
|
Task<bool> SyncFolderAsync(string id);
|
||||||
Task<bool> SyncDeleteFolderAsync(string id, DateTime revisionDate);
|
Task<bool> SyncDeleteFolderAsync(string id, DateTime revisionDate);
|
||||||
Task<bool> SyncDeleteLoginAsync(string id);
|
Task<bool> SyncDeleteCipherAsync(string id);
|
||||||
Task<bool> SyncSettingsAsync();
|
Task<bool> SyncSettingsAsync();
|
||||||
Task<bool> SyncProfileAsync();
|
Task<bool> SyncProfileAsync();
|
||||||
Task<bool> FullSyncAsync(bool forceSync = false);
|
Task<bool> FullSyncAsync(bool forceSync = false);
|
||||||
|
|
|
@ -58,7 +58,7 @@
|
||||||
<Compile Include="Abstractions\Services\IKeyDerivationService.cs" />
|
<Compile Include="Abstractions\Services\IKeyDerivationService.cs" />
|
||||||
<Compile Include="Abstractions\Services\ILogService.cs" />
|
<Compile Include="Abstractions\Services\ILogService.cs" />
|
||||||
<Compile Include="Abstractions\Services\IReflectionService.cs" />
|
<Compile Include="Abstractions\Services\IReflectionService.cs" />
|
||||||
<Compile Include="Abstractions\Services\ILoginService.cs" />
|
<Compile Include="Abstractions\Services\ICipherService.cs" />
|
||||||
<Compile Include="Abstractions\Services\IFolderService.cs" />
|
<Compile Include="Abstractions\Services\IFolderService.cs" />
|
||||||
<Compile Include="App.cs" />
|
<Compile Include="App.cs" />
|
||||||
<Compile Include="Abstractions\Services\ISecureStorageService.cs" />
|
<Compile Include="Abstractions\Services\ISecureStorageService.cs" />
|
||||||
|
@ -91,6 +91,7 @@
|
||||||
<Compile Include="Controls\VaultListViewCell.cs" />
|
<Compile Include="Controls\VaultListViewCell.cs" />
|
||||||
<Compile Include="Enums\DeviceType.cs" />
|
<Compile Include="Enums\DeviceType.cs" />
|
||||||
<Compile Include="Enums\FieldType.cs" />
|
<Compile Include="Enums\FieldType.cs" />
|
||||||
|
<Compile Include="Enums\SecureNoteType.cs" />
|
||||||
<Compile Include="Enums\TwoFactorProviderType.cs" />
|
<Compile Include="Enums\TwoFactorProviderType.cs" />
|
||||||
<Compile Include="Enums\EncryptionType.cs" />
|
<Compile Include="Enums\EncryptionType.cs" />
|
||||||
<Compile Include="Enums\OrganizationUserType.cs" />
|
<Compile Include="Enums\OrganizationUserType.cs" />
|
||||||
|
@ -104,6 +105,9 @@
|
||||||
<Compile Include="Models\Api\ApiResult.cs" />
|
<Compile Include="Models\Api\ApiResult.cs" />
|
||||||
<Compile Include="Models\Api\CipherDataModel.cs" />
|
<Compile Include="Models\Api\CipherDataModel.cs" />
|
||||||
<Compile Include="Models\Api\FieldDataModel.cs" />
|
<Compile Include="Models\Api\FieldDataModel.cs" />
|
||||||
|
<Compile Include="Models\Api\CardDataModel.cs" />
|
||||||
|
<Compile Include="Models\Api\IdentityDataModel.cs" />
|
||||||
|
<Compile Include="Models\Api\SecureNoteDataModel.cs" />
|
||||||
<Compile Include="Models\Api\Request\DeviceTokenRequest.cs" />
|
<Compile Include="Models\Api\Request\DeviceTokenRequest.cs" />
|
||||||
<Compile Include="Models\Api\Request\FolderRequest.cs" />
|
<Compile Include="Models\Api\Request\FolderRequest.cs" />
|
||||||
<Compile Include="Models\Api\Request\DeviceRequest.cs" />
|
<Compile Include="Models\Api\Request\DeviceRequest.cs" />
|
||||||
|
@ -125,16 +129,20 @@
|
||||||
<Compile Include="Models\Api\Response\TokenResponse.cs" />
|
<Compile Include="Models\Api\Response\TokenResponse.cs" />
|
||||||
<Compile Include="Models\Api\Response\ProfileResponse.cs" />
|
<Compile Include="Models\Api\Response\ProfileResponse.cs" />
|
||||||
<Compile Include="Models\Api\LoginDataModel.cs" />
|
<Compile Include="Models\Api\LoginDataModel.cs" />
|
||||||
|
<Compile Include="Models\Card.cs" />
|
||||||
<Compile Include="Models\CipherString.cs" />
|
<Compile Include="Models\CipherString.cs" />
|
||||||
<Compile Include="Models\Data\AttachmentData.cs" />
|
<Compile Include="Models\Data\AttachmentData.cs" />
|
||||||
<Compile Include="Models\Attachment.cs" />
|
<Compile Include="Models\Attachment.cs" />
|
||||||
<Compile Include="Models\Field.cs" />
|
<Compile Include="Models\Field.cs" />
|
||||||
|
<Compile Include="Models\Identity.cs" />
|
||||||
|
<Compile Include="Models\Login.cs" />
|
||||||
<Compile Include="Models\Page\VaultAttachmentsPageModel.cs" />
|
<Compile Include="Models\Page\VaultAttachmentsPageModel.cs" />
|
||||||
|
<Compile Include="Models\SecureNote.cs" />
|
||||||
<Compile Include="Models\SymmetricCryptoKey.cs" />
|
<Compile Include="Models\SymmetricCryptoKey.cs" />
|
||||||
<Compile Include="Models\Data\SettingsData.cs" />
|
<Compile Include="Models\Data\SettingsData.cs" />
|
||||||
<Compile Include="Models\Data\FolderData.cs" />
|
<Compile Include="Models\Data\FolderData.cs" />
|
||||||
<Compile Include="Abstractions\IDataObject.cs" />
|
<Compile Include="Abstractions\IDataObject.cs" />
|
||||||
<Compile Include="Models\Data\LoginData.cs" />
|
<Compile Include="Models\Data\CipherData.cs" />
|
||||||
<Compile Include="Models\DomainName.cs" />
|
<Compile Include="Models\DomainName.cs" />
|
||||||
<Compile Include="Models\Folder.cs" />
|
<Compile Include="Models\Folder.cs" />
|
||||||
<Compile Include="Models\LoginResult.cs" />
|
<Compile Include="Models\LoginResult.cs" />
|
||||||
|
@ -144,7 +152,7 @@
|
||||||
<Compile Include="Models\Page\PasswordGeneratorPageModel.cs" />
|
<Compile Include="Models\Page\PasswordGeneratorPageModel.cs" />
|
||||||
<Compile Include="Models\PlatformCulture.cs" />
|
<Compile Include="Models\PlatformCulture.cs" />
|
||||||
<Compile Include="Models\PushNotification.cs" />
|
<Compile Include="Models\PushNotification.cs" />
|
||||||
<Compile Include="Models\Login.cs" />
|
<Compile Include="Models\Cipher.cs" />
|
||||||
<Compile Include="Models\Page\VaultViewLoginPageModel.cs" />
|
<Compile Include="Models\Page\VaultViewLoginPageModel.cs" />
|
||||||
<Compile Include="Pages\HomePage.cs" />
|
<Compile Include="Pages\HomePage.cs" />
|
||||||
<Compile Include="Pages\Lock\BaseLockPage.cs" />
|
<Compile Include="Pages\Lock\BaseLockPage.cs" />
|
||||||
|
@ -175,7 +183,7 @@
|
||||||
<Compile Include="Pages\Vault\VaultAutofillListLoginsPage.cs" />
|
<Compile Include="Pages\Vault\VaultAutofillListLoginsPage.cs" />
|
||||||
<Compile Include="Pages\Vault\VaultAttachmentsPage.cs" />
|
<Compile Include="Pages\Vault\VaultAttachmentsPage.cs" />
|
||||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||||
<Compile Include="Abstractions\Repositories\ILoginRepository.cs" />
|
<Compile Include="Abstractions\Repositories\ICipherRepository.cs" />
|
||||||
<Compile Include="Repositories\AttachmentRepository.cs" />
|
<Compile Include="Repositories\AttachmentRepository.cs" />
|
||||||
<Compile Include="Repositories\SyncApiRepository.cs" />
|
<Compile Include="Repositories\SyncApiRepository.cs" />
|
||||||
<Compile Include="Repositories\TwoFactorApiRepository.cs" />
|
<Compile Include="Repositories\TwoFactorApiRepository.cs" />
|
||||||
|
@ -192,7 +200,7 @@
|
||||||
<Compile Include="Abstractions\Repositories\ICipherApiRepository.cs" />
|
<Compile Include="Abstractions\Repositories\ICipherApiRepository.cs" />
|
||||||
<Compile Include="Repositories\SettingsRepository.cs" />
|
<Compile Include="Repositories\SettingsRepository.cs" />
|
||||||
<Compile Include="Repositories\FolderApiRepository.cs" />
|
<Compile Include="Repositories\FolderApiRepository.cs" />
|
||||||
<Compile Include="Repositories\LoginRepository.cs" />
|
<Compile Include="Repositories\CipherRepository.cs" />
|
||||||
<Compile Include="Repositories\FolderRepository.cs" />
|
<Compile Include="Repositories\FolderRepository.cs" />
|
||||||
<Compile Include="Abstractions\Repositories\IFolderRepository.cs" />
|
<Compile Include="Abstractions\Repositories\IFolderRepository.cs" />
|
||||||
<Compile Include="Abstractions\Repositories\IRepository.cs" />
|
<Compile Include="Abstractions\Repositories\IRepository.cs" />
|
||||||
|
@ -340,7 +348,7 @@
|
||||||
<Compile Include="Abstractions\Services\ISyncService.cs" />
|
<Compile Include="Abstractions\Services\ISyncService.cs" />
|
||||||
<Compile Include="Abstractions\Services\IPasswordGenerationService.cs" />
|
<Compile Include="Abstractions\Services\IPasswordGenerationService.cs" />
|
||||||
<Compile Include="Services\SyncService.cs" />
|
<Compile Include="Services\SyncService.cs" />
|
||||||
<Compile Include="Services\LoginService.cs" />
|
<Compile Include="Services\CipherService.cs" />
|
||||||
<Compile Include="Services\AuthService.cs" />
|
<Compile Include="Services\AuthService.cs" />
|
||||||
<Compile Include="Services\CryptoService.cs" />
|
<Compile Include="Services\CryptoService.cs" />
|
||||||
<Compile Include="Models\Page\VaultListPageModel.cs" />
|
<Compile Include="Models\Page\VaultListPageModel.cs" />
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
//Folder = 0,
|
//Folder = 0,
|
||||||
Login = 1,
|
Login = 1,
|
||||||
SecureNote = 2,
|
SecureNote = 2,
|
||||||
Card = 3
|
Card = 3,
|
||||||
|
Identity = 4
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
7
src/App/Enums/SecureNoteType.cs
Normal file
7
src/App/Enums/SecureNoteType.cs
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
namespace Bit.App.Enums
|
||||||
|
{
|
||||||
|
public enum SecureNoteType : byte
|
||||||
|
{
|
||||||
|
Generic = 0
|
||||||
|
}
|
||||||
|
}
|
12
src/App/Models/Api/CardDataModel.cs
Normal file
12
src/App/Models/Api/CardDataModel.cs
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
namespace Bit.App.Models.Api
|
||||||
|
{
|
||||||
|
public class CardDataModel : CipherDataModel
|
||||||
|
{
|
||||||
|
public string CardholderName { get; set; }
|
||||||
|
public string Brand { get; set; }
|
||||||
|
public string Number { get; set; }
|
||||||
|
public string ExpMonth { get; set; }
|
||||||
|
public string ExpYear { get; set; }
|
||||||
|
public string Code { get; set; }
|
||||||
|
}
|
||||||
|
}
|
24
src/App/Models/Api/IdentityDataModel.cs
Normal file
24
src/App/Models/Api/IdentityDataModel.cs
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
namespace Bit.App.Models.Api
|
||||||
|
{
|
||||||
|
public class IdentityDataModel : CipherDataModel
|
||||||
|
{
|
||||||
|
public string Title { get; set; }
|
||||||
|
public string FirstName { get; set; }
|
||||||
|
public string MiddleName { get; set; }
|
||||||
|
public string LastName { get; set; }
|
||||||
|
public string Address1 { get; set; }
|
||||||
|
public string Address2 { get; set; }
|
||||||
|
public string Address3 { get; set; }
|
||||||
|
public string City { get; set; }
|
||||||
|
public string State { get; set; }
|
||||||
|
public string PostalCode { get; set; }
|
||||||
|
public string Country { get; set; }
|
||||||
|
public string Company { get; set; }
|
||||||
|
public string Email { get; set; }
|
||||||
|
public string Phone { get; set; }
|
||||||
|
public string SSN { get; set; }
|
||||||
|
public string Username { get; set; }
|
||||||
|
public string PassportNumber { get; set; }
|
||||||
|
public string LicenseNumber { get; set; }
|
||||||
|
}
|
||||||
|
}
|
|
@ -6,18 +6,18 @@ namespace Bit.App.Models.Api
|
||||||
{
|
{
|
||||||
public class CipherRequest
|
public class CipherRequest
|
||||||
{
|
{
|
||||||
public CipherRequest(Login login)
|
public CipherRequest(Cipher cipher)
|
||||||
{
|
{
|
||||||
Type = CipherType.Login;
|
Type = cipher.Type;
|
||||||
OrganizationId = login.OrganizationId;
|
OrganizationId = cipher.OrganizationId;
|
||||||
FolderId = login.FolderId;
|
FolderId = cipher.FolderId;
|
||||||
Name = login.Name?.EncryptedString;
|
Name = cipher.Name?.EncryptedString;
|
||||||
Notes = login.Notes?.EncryptedString;
|
Notes = cipher.Notes?.EncryptedString;
|
||||||
Favorite = login.Favorite;
|
Favorite = cipher.Favorite;
|
||||||
|
|
||||||
if(login.Fields != null)
|
if(cipher.Fields != null)
|
||||||
{
|
{
|
||||||
Fields = login.Fields.Select(f => new FieldDataModel
|
Fields = cipher.Fields.Select(f => new FieldDataModel
|
||||||
{
|
{
|
||||||
Name = f.Name?.EncryptedString,
|
Name = f.Name?.EncryptedString,
|
||||||
Value = f.Value?.EncryptedString,
|
Value = f.Value?.EncryptedString,
|
||||||
|
@ -28,7 +28,16 @@ namespace Bit.App.Models.Api
|
||||||
switch(Type)
|
switch(Type)
|
||||||
{
|
{
|
||||||
case CipherType.Login:
|
case CipherType.Login:
|
||||||
Login = new LoginType(login);
|
Login = new LoginType(cipher);
|
||||||
|
break;
|
||||||
|
case CipherType.Card:
|
||||||
|
Card = new CardType(cipher);
|
||||||
|
break;
|
||||||
|
case CipherType.Identity:
|
||||||
|
Identity = new IdentityType(cipher);
|
||||||
|
break;
|
||||||
|
case CipherType.SecureNote:
|
||||||
|
SecureNote = new SecureNoteType(cipher);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
@ -42,16 +51,20 @@ namespace Bit.App.Models.Api
|
||||||
public string Name { get; set; }
|
public string Name { get; set; }
|
||||||
public string Notes { get; set; }
|
public string Notes { get; set; }
|
||||||
public IEnumerable<FieldDataModel> Fields { get; set; }
|
public IEnumerable<FieldDataModel> Fields { get; set; }
|
||||||
|
|
||||||
public LoginType Login { get; set; }
|
public LoginType Login { get; set; }
|
||||||
|
public CardType Card { get; set; }
|
||||||
|
public IdentityType Identity { get; set; }
|
||||||
|
public SecureNoteType SecureNote { get; set; }
|
||||||
|
|
||||||
public class LoginType
|
public class LoginType
|
||||||
{
|
{
|
||||||
public LoginType(Login login)
|
public LoginType(Cipher cipher)
|
||||||
{
|
{
|
||||||
Uri = login.Uri?.EncryptedString;
|
Uri = cipher.Login.Uri?.EncryptedString;
|
||||||
Username = login.Username?.EncryptedString;
|
Username = cipher.Login.Username?.EncryptedString;
|
||||||
Password = login.Password?.EncryptedString;
|
Password = cipher.Login.Password?.EncryptedString;
|
||||||
Totp = login.Totp?.EncryptedString;
|
Totp = cipher.Login.Totp?.EncryptedString;
|
||||||
}
|
}
|
||||||
|
|
||||||
public string Uri { get; set; }
|
public string Uri { get; set; }
|
||||||
|
@ -59,5 +72,79 @@ namespace Bit.App.Models.Api
|
||||||
public string Password { get; set; }
|
public string Password { get; set; }
|
||||||
public string Totp { get; set; }
|
public string Totp { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public class CardType
|
||||||
|
{
|
||||||
|
public CardType(Cipher cipher)
|
||||||
|
{
|
||||||
|
CardholderName = cipher.Card.CardholderName?.EncryptedString;
|
||||||
|
Brand = cipher.Card.Brand?.EncryptedString;
|
||||||
|
Number = cipher.Card.Number?.EncryptedString;
|
||||||
|
ExpMonth = cipher.Card.ExpMonth?.EncryptedString;
|
||||||
|
ExpYear = cipher.Card.ExpYear?.EncryptedString;
|
||||||
|
Code = cipher.Card.Code?.EncryptedString;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string CardholderName { get; set; }
|
||||||
|
public string Brand { get; set; }
|
||||||
|
public string Number { get; set; }
|
||||||
|
public string ExpMonth { get; set; }
|
||||||
|
public string ExpYear { get; set; }
|
||||||
|
public string Code { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class IdentityType
|
||||||
|
{
|
||||||
|
public IdentityType(Cipher cipher)
|
||||||
|
{
|
||||||
|
Title = cipher.Identity.Title?.EncryptedString;
|
||||||
|
FirstName = cipher.Identity.FirstName?.EncryptedString;
|
||||||
|
MiddleName = cipher.Identity.MiddleName?.EncryptedString;
|
||||||
|
LastName = cipher.Identity.LastName?.EncryptedString;
|
||||||
|
Address1 = cipher.Identity.Address1?.EncryptedString;
|
||||||
|
Address2 = cipher.Identity.Address2?.EncryptedString;
|
||||||
|
Address3 = cipher.Identity.Address3?.EncryptedString;
|
||||||
|
City = cipher.Identity.City?.EncryptedString;
|
||||||
|
State = cipher.Identity.State?.EncryptedString;
|
||||||
|
PostalCode = cipher.Identity.PostalCode?.EncryptedString;
|
||||||
|
Country = cipher.Identity.Country?.EncryptedString;
|
||||||
|
Company = cipher.Identity.Company?.EncryptedString;
|
||||||
|
Email = cipher.Identity.Email?.EncryptedString;
|
||||||
|
Phone = cipher.Identity.Phone?.EncryptedString;
|
||||||
|
SSN = cipher.Identity.SSN?.EncryptedString;
|
||||||
|
Username = cipher.Identity.Username?.EncryptedString;
|
||||||
|
PassportNumber = cipher.Identity.PassportNumber?.EncryptedString;
|
||||||
|
LicenseNumber = cipher.Identity.LicenseNumber?.EncryptedString;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string Title { get; set; }
|
||||||
|
public string FirstName { get; set; }
|
||||||
|
public string MiddleName { get; set; }
|
||||||
|
public string LastName { get; set; }
|
||||||
|
public string Address1 { get; set; }
|
||||||
|
public string Address2 { get; set; }
|
||||||
|
public string Address3 { get; set; }
|
||||||
|
public string City { get; set; }
|
||||||
|
public string State { get; set; }
|
||||||
|
public string PostalCode { get; set; }
|
||||||
|
public string Country { get; set; }
|
||||||
|
public string Company { get; set; }
|
||||||
|
public string Email { get; set; }
|
||||||
|
public string Phone { get; set; }
|
||||||
|
public string SSN { get; set; }
|
||||||
|
public string Username { get; set; }
|
||||||
|
public string PassportNumber { get; set; }
|
||||||
|
public string LicenseNumber { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class SecureNoteType
|
||||||
|
{
|
||||||
|
public SecureNoteType(Cipher cipher)
|
||||||
|
{
|
||||||
|
Type = cipher.SecureNote.Type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Enums.SecureNoteType Type { get; set; }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
9
src/App/Models/Api/SecureNoteDataModel.cs
Normal file
9
src/App/Models/Api/SecureNoteDataModel.cs
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
using Bit.App.Enums;
|
||||||
|
|
||||||
|
namespace Bit.App.Models.Api
|
||||||
|
{
|
||||||
|
public class SecureNoteDataModel : CipherDataModel
|
||||||
|
{
|
||||||
|
public SecureNoteType Type { get; set; }
|
||||||
|
}
|
||||||
|
}
|
29
src/App/Models/Card.cs
Normal file
29
src/App/Models/Card.cs
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
using Bit.App.Models.Api;
|
||||||
|
using Bit.App.Models.Data;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
|
namespace Bit.App.Models
|
||||||
|
{
|
||||||
|
public class Card
|
||||||
|
{
|
||||||
|
public Card(CipherData data)
|
||||||
|
{
|
||||||
|
var deserializedData = JsonConvert.DeserializeObject<CardDataModel>(data.Data);
|
||||||
|
|
||||||
|
CardholderName = deserializedData.CardholderName != null ?
|
||||||
|
new CipherString(deserializedData.CardholderName) : null;
|
||||||
|
Brand = deserializedData.Brand != null ? new CipherString(deserializedData.Brand) : null;
|
||||||
|
Number = deserializedData.Number != null ? new CipherString(deserializedData.Number) : null;
|
||||||
|
ExpMonth = deserializedData.ExpMonth != null ? new CipherString(deserializedData.ExpMonth) : null;
|
||||||
|
ExpYear = deserializedData.ExpYear != null ? new CipherString(deserializedData.ExpYear) : null;
|
||||||
|
Code = deserializedData.Code != null ? new CipherString(deserializedData.Code) : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CipherString CardholderName { get; set; }
|
||||||
|
public CipherString Brand { get; set; }
|
||||||
|
public CipherString Number { get; set; }
|
||||||
|
public CipherString ExpMonth { get; set; }
|
||||||
|
public CipherString ExpYear { get; set; }
|
||||||
|
public CipherString Code { get; set; }
|
||||||
|
}
|
||||||
|
}
|
76
src/App/Models/Cipher.cs
Normal file
76
src/App/Models/Cipher.cs
Normal file
|
@ -0,0 +1,76 @@
|
||||||
|
using Bit.App.Enums;
|
||||||
|
using Bit.App.Models.Api;
|
||||||
|
using Bit.App.Models.Data;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
namespace Bit.App.Models
|
||||||
|
{
|
||||||
|
public class Cipher
|
||||||
|
{
|
||||||
|
public Cipher()
|
||||||
|
{ }
|
||||||
|
|
||||||
|
public Cipher(CipherData data, IEnumerable<AttachmentData> attachments = null)
|
||||||
|
{
|
||||||
|
Id = data.Id;
|
||||||
|
UserId = data.UserId;
|
||||||
|
OrganizationId = data.OrganizationId;
|
||||||
|
FolderId = data.FolderId;
|
||||||
|
Type = data.Type;
|
||||||
|
Name = data.Name != null ? new CipherString(data.Name) : null;
|
||||||
|
Notes = data.Notes != null ? new CipherString(data.Notes) : null;
|
||||||
|
Favorite = data.Favorite;
|
||||||
|
Edit = data.Edit;
|
||||||
|
OrganizationUseTotp = data.OrganizationUseTotp;
|
||||||
|
Attachments = attachments?.Select(a => new Attachment(a));
|
||||||
|
|
||||||
|
switch(Type)
|
||||||
|
{
|
||||||
|
case CipherType.Login:
|
||||||
|
Login = new Login(data);
|
||||||
|
break;
|
||||||
|
case CipherType.SecureNote:
|
||||||
|
SecureNote = new SecureNote(data);
|
||||||
|
break;
|
||||||
|
case CipherType.Card:
|
||||||
|
Card = new Card(data);
|
||||||
|
break;
|
||||||
|
case CipherType.Identity:
|
||||||
|
Identity = new Identity(data);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!string.IsNullOrWhiteSpace(data.Fields))
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var fieldModels = JsonConvert.DeserializeObject<IEnumerable<FieldDataModel>>(data.Fields);
|
||||||
|
Fields = fieldModels?.Select(f => new Field(f));
|
||||||
|
}
|
||||||
|
catch(JsonSerializationException) { }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public string Id { get; set; }
|
||||||
|
public string UserId { get; set; }
|
||||||
|
public string OrganizationId { get; set; }
|
||||||
|
public string FolderId { get; set; }
|
||||||
|
public CipherType Type { get; set; }
|
||||||
|
public CipherString Name { get; set; }
|
||||||
|
public CipherString Notes { get; set; }
|
||||||
|
public IEnumerable<Field> Fields { get; set; }
|
||||||
|
public bool Favorite { get; set; }
|
||||||
|
public bool Edit { get; set; }
|
||||||
|
public bool OrganizationUseTotp { get; set; }
|
||||||
|
public IEnumerable<Attachment> Attachments { get; set; }
|
||||||
|
|
||||||
|
public Login Login { get; set; }
|
||||||
|
public Identity Identity { get; set; }
|
||||||
|
public Card Card { get; set; }
|
||||||
|
public SecureNote SecureNote { get; set; }
|
||||||
|
}
|
||||||
|
}
|
|
@ -10,20 +10,20 @@ namespace Bit.App.Models.Data
|
||||||
public AttachmentData()
|
public AttachmentData()
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
public AttachmentData(Attachment attachment, string loginId)
|
public AttachmentData(Attachment attachment, string cipherId)
|
||||||
{
|
{
|
||||||
Id = attachment.Id;
|
Id = attachment.Id;
|
||||||
LoginId = loginId;
|
LoginId = cipherId;
|
||||||
Url = attachment.Url;
|
Url = attachment.Url;
|
||||||
FileName = attachment.FileName?.EncryptedString;
|
FileName = attachment.FileName?.EncryptedString;
|
||||||
Size = attachment.Size.ToString();
|
Size = attachment.Size.ToString();
|
||||||
SizeName = attachment.SizeName;
|
SizeName = attachment.SizeName;
|
||||||
}
|
}
|
||||||
|
|
||||||
public AttachmentData(AttachmentResponse response, string loginId)
|
public AttachmentData(AttachmentResponse response, string cipherId)
|
||||||
{
|
{
|
||||||
Id = response.Id;
|
Id = response.Id;
|
||||||
LoginId = loginId;
|
LoginId = cipherId;
|
||||||
Url = response.Url;
|
Url = response.Url;
|
||||||
FileName = response.FileName;
|
FileName = response.FileName;
|
||||||
Size = response.Size;
|
Size = response.Size;
|
||||||
|
@ -32,6 +32,7 @@ namespace Bit.App.Models.Data
|
||||||
|
|
||||||
[PrimaryKey]
|
[PrimaryKey]
|
||||||
public string Id { get; set; }
|
public string Id { get; set; }
|
||||||
|
// Really should be called CipherId
|
||||||
[Indexed]
|
[Indexed]
|
||||||
public string LoginId { get; set; }
|
public string LoginId { get; set; }
|
||||||
public string Url { get; set; }
|
public string Url { get; set; }
|
||||||
|
|
100
src/App/Models/Data/CipherData.cs
Normal file
100
src/App/Models/Data/CipherData.cs
Normal file
|
@ -0,0 +1,100 @@
|
||||||
|
using System;
|
||||||
|
using SQLite;
|
||||||
|
using Bit.App.Abstractions;
|
||||||
|
using Bit.App.Models.Api;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using System.Linq;
|
||||||
|
using Bit.App.Enums;
|
||||||
|
|
||||||
|
namespace Bit.App.Models.Data
|
||||||
|
{
|
||||||
|
// Old table that has just carried over for backward compat. sake. Should really be "Cipher"
|
||||||
|
[Table("Site")]
|
||||||
|
public class CipherData : IDataObject<string>
|
||||||
|
{
|
||||||
|
public CipherData()
|
||||||
|
{ }
|
||||||
|
|
||||||
|
public CipherData(CipherResponse cipher, string userId)
|
||||||
|
{
|
||||||
|
Id = cipher.Id;
|
||||||
|
FolderId = cipher.FolderId;
|
||||||
|
UserId = userId;
|
||||||
|
OrganizationId = cipher.OrganizationId;
|
||||||
|
Favorite = cipher.Favorite;
|
||||||
|
Edit = cipher.Edit;
|
||||||
|
OrganizationUseTotp = cipher.OrganizationUseTotp;
|
||||||
|
RevisionDateTime = cipher.RevisionDate;
|
||||||
|
Type = cipher.Type;
|
||||||
|
Data = JsonConvert.SerializeObject(cipher.Data);
|
||||||
|
|
||||||
|
CipherDataModel cipherData = null;
|
||||||
|
switch(cipher.Type)
|
||||||
|
{
|
||||||
|
case CipherType.Login:
|
||||||
|
var loginData = cipher.Data.ToObject<LoginDataModel>();
|
||||||
|
cipherData = loginData;
|
||||||
|
|
||||||
|
Uri = loginData.Uri;
|
||||||
|
Username = loginData.Username;
|
||||||
|
Password = loginData.Password;
|
||||||
|
Totp = loginData.Totp;
|
||||||
|
break;
|
||||||
|
case CipherType.SecureNote:
|
||||||
|
var noteData = cipher.Data.ToObject<SecureNoteDataModel>();
|
||||||
|
cipherData = noteData;
|
||||||
|
|
||||||
|
SecureNoteType = noteData.Type;
|
||||||
|
break;
|
||||||
|
case CipherType.Card:
|
||||||
|
var cardData = cipher.Data.ToObject<CardDataModel>();
|
||||||
|
cipherData = cardData;
|
||||||
|
break;
|
||||||
|
case CipherType.Identity:
|
||||||
|
var idData = cipher.Data.ToObject<IdentityDataModel>();
|
||||||
|
cipherData = idData;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new ArgumentException(nameof(cipher.Type));
|
||||||
|
}
|
||||||
|
|
||||||
|
Name = cipherData.Name;
|
||||||
|
Notes = cipherData.Notes;
|
||||||
|
|
||||||
|
if(cipherData.Fields != null && cipherData.Fields.Any())
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Fields = JsonConvert.SerializeObject(cipherData.Fields);
|
||||||
|
}
|
||||||
|
catch(JsonSerializationException) { }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[PrimaryKey]
|
||||||
|
public string Id { get; set; }
|
||||||
|
public string FolderId { get; set; }
|
||||||
|
[Indexed]
|
||||||
|
public string UserId { get; set; }
|
||||||
|
public string OrganizationId { get; set; }
|
||||||
|
public string Name { get; set; }
|
||||||
|
public string Notes { get; set; }
|
||||||
|
public string Fields { get; set; }
|
||||||
|
public bool Favorite { get; set; }
|
||||||
|
public bool Edit { get; set; }
|
||||||
|
public bool OrganizationUseTotp { get; set; }
|
||||||
|
public DateTime RevisionDateTime { get; set; } = DateTime.UtcNow;
|
||||||
|
[Indexed]
|
||||||
|
public CipherType Type { get; set; } = CipherType.Login;
|
||||||
|
public string Data { get; set; }
|
||||||
|
|
||||||
|
// Login metadata
|
||||||
|
public string Uri { get; set; }
|
||||||
|
public string Username { get; set; }
|
||||||
|
public string Password { get; set; }
|
||||||
|
public string Totp { get; set; }
|
||||||
|
|
||||||
|
// Secure Note metadata
|
||||||
|
public SecureNoteType? SecureNoteType { get; set; }
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,73 +0,0 @@
|
||||||
using System;
|
|
||||||
using SQLite;
|
|
||||||
using Bit.App.Abstractions;
|
|
||||||
using Bit.App.Models.Api;
|
|
||||||
using Newtonsoft.Json;
|
|
||||||
using System.Linq;
|
|
||||||
|
|
||||||
namespace Bit.App.Models.Data
|
|
||||||
{
|
|
||||||
[Table("Site")]
|
|
||||||
public class LoginData : IDataObject<string>
|
|
||||||
{
|
|
||||||
public LoginData()
|
|
||||||
{ }
|
|
||||||
|
|
||||||
public LoginData(CipherResponse cipher, string userId)
|
|
||||||
{
|
|
||||||
if(cipher.Type != Enums.CipherType.Login)
|
|
||||||
{
|
|
||||||
throw new ArgumentException(nameof(cipher.Type));
|
|
||||||
}
|
|
||||||
|
|
||||||
var data = cipher.Data.ToObject<LoginDataModel>();
|
|
||||||
|
|
||||||
Id = cipher.Id;
|
|
||||||
FolderId = cipher.FolderId;
|
|
||||||
UserId = userId;
|
|
||||||
OrganizationId = cipher.OrganizationId;
|
|
||||||
Name = data.Name;
|
|
||||||
Uri = data.Uri;
|
|
||||||
Username = data.Username;
|
|
||||||
Password = data.Password;
|
|
||||||
Notes = data.Notes;
|
|
||||||
Totp = data.Totp;
|
|
||||||
Favorite = cipher.Favorite;
|
|
||||||
Edit = cipher.Edit;
|
|
||||||
OrganizationUseTotp = cipher.OrganizationUseTotp;
|
|
||||||
RevisionDateTime = cipher.RevisionDate;
|
|
||||||
|
|
||||||
if(data.Fields != null && data.Fields.Any())
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
Fields = JsonConvert.SerializeObject(data.Fields);
|
|
||||||
}
|
|
||||||
catch(JsonSerializationException) { }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[PrimaryKey]
|
|
||||||
public string Id { get; set; }
|
|
||||||
public string FolderId { get; set; }
|
|
||||||
[Indexed]
|
|
||||||
public string UserId { get; set; }
|
|
||||||
public string OrganizationId { get; set; }
|
|
||||||
public string Name { get; set; }
|
|
||||||
public string Uri { get; set; }
|
|
||||||
public string Username { get; set; }
|
|
||||||
public string Password { get; set; }
|
|
||||||
public string Notes { get; set; }
|
|
||||||
public string Totp { get; set; }
|
|
||||||
public string Fields { get; set; }
|
|
||||||
public bool Favorite { get; set; }
|
|
||||||
public bool Edit { get; set; }
|
|
||||||
public bool OrganizationUseTotp { get; set; }
|
|
||||||
public DateTime RevisionDateTime { get; set; } = DateTime.UtcNow;
|
|
||||||
|
|
||||||
public Login ToLogin()
|
|
||||||
{
|
|
||||||
return new Login(this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
54
src/App/Models/Identity.cs
Normal file
54
src/App/Models/Identity.cs
Normal file
|
@ -0,0 +1,54 @@
|
||||||
|
using Bit.App.Models.Api;
|
||||||
|
using Bit.App.Models.Data;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
|
namespace Bit.App.Models
|
||||||
|
{
|
||||||
|
public class Identity
|
||||||
|
{
|
||||||
|
public Identity(CipherData data)
|
||||||
|
{
|
||||||
|
var deserializedData = JsonConvert.DeserializeObject<IdentityDataModel>(data.Data);
|
||||||
|
|
||||||
|
Title = deserializedData.Title != null ? new CipherString(deserializedData.Title) : null;
|
||||||
|
FirstName = deserializedData.FirstName != null ? new CipherString(deserializedData.FirstName) : null;
|
||||||
|
MiddleName = deserializedData.MiddleName != null ? new CipherString(deserializedData.MiddleName) : null;
|
||||||
|
LastName = deserializedData.LastName != null ? new CipherString(deserializedData.LastName) : null;
|
||||||
|
Address1 = deserializedData.Address1 != null ? new CipherString(deserializedData.Address1) : null;
|
||||||
|
Address2 = deserializedData.Address2 != null ? new CipherString(deserializedData.Address2) : null;
|
||||||
|
Address3 = deserializedData.Address3 != null ? new CipherString(deserializedData.Address3) : null;
|
||||||
|
City = deserializedData.City != null ? new CipherString(deserializedData.City) : null;
|
||||||
|
State = deserializedData.State != null ? new CipherString(deserializedData.State) : null;
|
||||||
|
PostalCode = deserializedData.PostalCode != null ? new CipherString(deserializedData.PostalCode) : null;
|
||||||
|
Country = deserializedData.Country != null ? new CipherString(deserializedData.Country) : null;
|
||||||
|
Company = deserializedData.Company != null ? new CipherString(deserializedData.Company) : null;
|
||||||
|
Email = deserializedData.Email != null ? new CipherString(deserializedData.Email) : null;
|
||||||
|
Phone = deserializedData.Phone != null ? new CipherString(deserializedData.Phone) : null;
|
||||||
|
SSN = deserializedData.SSN != null ? new CipherString(deserializedData.SSN) : null;
|
||||||
|
Username = deserializedData.Username != null ? new CipherString(deserializedData.Username) : null;
|
||||||
|
PassportNumber = deserializedData.PassportNumber != null ?
|
||||||
|
new CipherString(deserializedData.PassportNumber) : null;
|
||||||
|
LicenseNumber = deserializedData.LicenseNumber != null ?
|
||||||
|
new CipherString(deserializedData.LicenseNumber) : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CipherString Title { get; set; }
|
||||||
|
public CipherString FirstName { get; set; }
|
||||||
|
public CipherString MiddleName { get; set; }
|
||||||
|
public CipherString LastName { get; set; }
|
||||||
|
public CipherString Address1 { get; set; }
|
||||||
|
public CipherString Address2 { get; set; }
|
||||||
|
public CipherString Address3 { get; set; }
|
||||||
|
public CipherString City { get; set; }
|
||||||
|
public CipherString State { get; set; }
|
||||||
|
public CipherString PostalCode { get; set; }
|
||||||
|
public CipherString Country { get; set; }
|
||||||
|
public CipherString Company { get; set; }
|
||||||
|
public CipherString Email { get; set; }
|
||||||
|
public CipherString Phone { get; set; }
|
||||||
|
public CipherString SSN { get; set; }
|
||||||
|
public CipherString Username { get; set; }
|
||||||
|
public CipherString PassportNumber { get; set; }
|
||||||
|
public CipherString LicenseNumber { get; set; }
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,58 +1,22 @@
|
||||||
using Bit.App.Models.Api;
|
using Bit.App.Models.Data;
|
||||||
using Bit.App.Models.Data;
|
|
||||||
using Newtonsoft.Json;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
|
|
||||||
namespace Bit.App.Models
|
namespace Bit.App.Models
|
||||||
{
|
{
|
||||||
public class Login
|
public class Login
|
||||||
{
|
{
|
||||||
public Login()
|
public Login() { }
|
||||||
{ }
|
|
||||||
|
|
||||||
public Login(LoginData data, IEnumerable<AttachmentData> attachments = null)
|
public Login(CipherData data)
|
||||||
{
|
{
|
||||||
Id = data.Id;
|
|
||||||
UserId = data.UserId;
|
|
||||||
OrganizationId = data.OrganizationId;
|
|
||||||
FolderId = data.FolderId;
|
|
||||||
Name = data.Name != null ? new CipherString(data.Name) : null;
|
|
||||||
Uri = data.Uri != null ? new CipherString(data.Uri) : null;
|
Uri = data.Uri != null ? new CipherString(data.Uri) : null;
|
||||||
Username = data.Username != null ? new CipherString(data.Username) : null;
|
Username = data.Username != null ? new CipherString(data.Username) : null;
|
||||||
Password = data.Password != null ? new CipherString(data.Password) : null;
|
Password = data.Password != null ? new CipherString(data.Password) : null;
|
||||||
Notes = data.Notes != null ? new CipherString(data.Notes) : null;
|
|
||||||
Totp = data.Totp != null ? new CipherString(data.Totp) : null;
|
Totp = data.Totp != null ? new CipherString(data.Totp) : null;
|
||||||
Favorite = data.Favorite;
|
|
||||||
Edit = data.Edit;
|
|
||||||
OrganizationUseTotp = data.OrganizationUseTotp;
|
|
||||||
Attachments = attachments?.Select(a => new Attachment(a));
|
|
||||||
|
|
||||||
if(!string.IsNullOrWhiteSpace(data.Fields))
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var fieldModels = JsonConvert.DeserializeObject<IEnumerable<FieldDataModel>>(data.Fields);
|
|
||||||
Fields = fieldModels?.Select(f => new Field(f));
|
|
||||||
}
|
|
||||||
catch(JsonSerializationException) { }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public string Id { get; set; }
|
|
||||||
public string UserId { get; set; }
|
|
||||||
public string OrganizationId { get; set; }
|
|
||||||
public string FolderId { get; set; }
|
|
||||||
public CipherString Name { get; set; }
|
|
||||||
public CipherString Uri { get; set; }
|
public CipherString Uri { get; set; }
|
||||||
public CipherString Username { get; set; }
|
public CipherString Username { get; set; }
|
||||||
public CipherString Password { get; set; }
|
public CipherString Password { get; set; }
|
||||||
public CipherString Notes { get; set; }
|
|
||||||
public CipherString Totp { get; set; }
|
public CipherString Totp { get; set; }
|
||||||
public IEnumerable<Field> Fields { get; set; }
|
|
||||||
public bool Favorite { get; set; }
|
|
||||||
public bool Edit { get; set; }
|
|
||||||
public bool OrganizationUseTotp { get; set; }
|
|
||||||
public IEnumerable<Attachment> Attachments { get; set; }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,17 +9,17 @@ namespace Bit.App.Models.Page
|
||||||
{
|
{
|
||||||
public class Login
|
public class Login
|
||||||
{
|
{
|
||||||
public Login(Models.Login login)
|
public Login(Models.Cipher cipher)
|
||||||
{
|
{
|
||||||
Id = login.Id;
|
Id = cipher.Id;
|
||||||
Shared = !string.IsNullOrWhiteSpace(login.OrganizationId);
|
Shared = !string.IsNullOrWhiteSpace(cipher.OrganizationId);
|
||||||
HasAttachments = login.Attachments?.Any() ?? false;
|
HasAttachments = cipher.Attachments?.Any() ?? false;
|
||||||
FolderId = login.FolderId;
|
FolderId = cipher.FolderId;
|
||||||
Name = login.Name?.Decrypt(login.OrganizationId);
|
Name = cipher.Name?.Decrypt(cipher.OrganizationId);
|
||||||
Username = login.Username?.Decrypt(login.OrganizationId) ?? " ";
|
Username = cipher.Login?.Username?.Decrypt(cipher.OrganizationId) ?? " ";
|
||||||
Password = new Lazy<string>(() => login.Password?.Decrypt(login.OrganizationId));
|
Password = new Lazy<string>(() => cipher.Login?.Password?.Decrypt(cipher.OrganizationId));
|
||||||
Uri = new Lazy<string>(() => login.Uri?.Decrypt(login.OrganizationId));
|
Uri = new Lazy<string>(() => cipher.Login?.Uri?.Decrypt(cipher.OrganizationId));
|
||||||
Totp = new Lazy<string>(() => login.Totp?.Decrypt(login.OrganizationId));
|
Totp = new Lazy<string>(() => cipher.Login?.Totp?.Decrypt(cipher.OrganizationId));
|
||||||
}
|
}
|
||||||
|
|
||||||
public string Id { get; set; }
|
public string Id { get; set; }
|
||||||
|
@ -35,7 +35,7 @@ namespace Bit.App.Models.Page
|
||||||
|
|
||||||
public class AutofillLogin : Login
|
public class AutofillLogin : Login
|
||||||
{
|
{
|
||||||
public AutofillLogin(Models.Login login, bool fuzzy = false)
|
public AutofillLogin(Models.Cipher login, bool fuzzy = false)
|
||||||
: base(login)
|
: base(login)
|
||||||
{
|
{
|
||||||
Fuzzy = fuzzy;
|
Fuzzy = fuzzy;
|
||||||
|
|
|
@ -201,23 +201,23 @@ namespace Bit.App.Models.Page
|
||||||
}
|
}
|
||||||
public bool ShowFields => (Fields?.Count ?? 0) > 0;
|
public bool ShowFields => (Fields?.Count ?? 0) > 0;
|
||||||
|
|
||||||
public void Update(Login login)
|
public void Update(Cipher cipher)
|
||||||
{
|
{
|
||||||
Name = login.Name?.Decrypt(login.OrganizationId);
|
Name = cipher.Name?.Decrypt(cipher.OrganizationId);
|
||||||
Username = login.Username?.Decrypt(login.OrganizationId);
|
Username = cipher.Login?.Username?.Decrypt(cipher.OrganizationId);
|
||||||
Password = login.Password?.Decrypt(login.OrganizationId);
|
Password = cipher.Login?.Password?.Decrypt(cipher.OrganizationId);
|
||||||
Uri = login.Uri?.Decrypt(login.OrganizationId);
|
Uri = cipher.Login?.Uri?.Decrypt(cipher.OrganizationId);
|
||||||
Notes = login.Notes?.Decrypt(login.OrganizationId);
|
Notes = cipher.Notes?.Decrypt(cipher.OrganizationId);
|
||||||
|
|
||||||
if(login.Attachments != null)
|
if(cipher.Attachments != null)
|
||||||
{
|
{
|
||||||
var attachments = new List<Attachment>();
|
var attachments = new List<Attachment>();
|
||||||
foreach(var attachment in login.Attachments)
|
foreach(var attachment in cipher.Attachments)
|
||||||
{
|
{
|
||||||
attachments.Add(new Attachment
|
attachments.Add(new Attachment
|
||||||
{
|
{
|
||||||
Id = attachment.Id,
|
Id = attachment.Id,
|
||||||
Name = attachment.FileName?.Decrypt(login.OrganizationId),
|
Name = attachment.FileName?.Decrypt(cipher.OrganizationId),
|
||||||
SizeName = attachment.SizeName,
|
SizeName = attachment.SizeName,
|
||||||
Size = attachment.Size,
|
Size = attachment.Size,
|
||||||
Url = attachment.Url
|
Url = attachment.Url
|
||||||
|
@ -227,18 +227,18 @@ namespace Bit.App.Models.Page
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
login.Attachments = null;
|
cipher.Attachments = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(login.Fields != null)
|
if(cipher.Fields != null)
|
||||||
{
|
{
|
||||||
var fields = new List<Field>();
|
var fields = new List<Field>();
|
||||||
foreach(var field in login.Fields)
|
foreach(var field in cipher.Fields)
|
||||||
{
|
{
|
||||||
fields.Add(new Field
|
fields.Add(new Field
|
||||||
{
|
{
|
||||||
Name = field.Name?.Decrypt(login.OrganizationId),
|
Name = field.Name?.Decrypt(cipher.OrganizationId),
|
||||||
Value = field.Value?.Decrypt(login.OrganizationId),
|
Value = field.Value?.Decrypt(cipher.OrganizationId),
|
||||||
Type = field.Type
|
Type = field.Type
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -246,7 +246,7 @@ namespace Bit.App.Models.Page
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
login.Fields = null;
|
cipher.Fields = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
15
src/App/Models/SecureNote.cs
Normal file
15
src/App/Models/SecureNote.cs
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
using Bit.App.Enums;
|
||||||
|
using Bit.App.Models.Data;
|
||||||
|
|
||||||
|
namespace Bit.App.Models
|
||||||
|
{
|
||||||
|
public class SecureNote
|
||||||
|
{
|
||||||
|
public SecureNote(CipherData data)
|
||||||
|
{
|
||||||
|
Type = data.SecureNoteType.Value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SecureNoteType Type { get; set; }
|
||||||
|
}
|
||||||
|
}
|
|
@ -18,7 +18,7 @@ namespace Bit.App.Pages
|
||||||
{
|
{
|
||||||
private const string AddedLoginAlertKey = "addedSiteAlert";
|
private const string AddedLoginAlertKey = "addedSiteAlert";
|
||||||
|
|
||||||
private readonly ILoginService _loginService;
|
private readonly ICipherService _cipherService;
|
||||||
private readonly IFolderService _folderService;
|
private readonly IFolderService _folderService;
|
||||||
private readonly IUserDialogs _userDialogs;
|
private readonly IUserDialogs _userDialogs;
|
||||||
private readonly IConnectivity _connectivity;
|
private readonly IConnectivity _connectivity;
|
||||||
|
@ -37,7 +37,7 @@ namespace Bit.App.Pages
|
||||||
_defaultName = defaultName;
|
_defaultName = defaultName;
|
||||||
_fromAutofill = fromAutofill;
|
_fromAutofill = fromAutofill;
|
||||||
|
|
||||||
_loginService = Resolver.Resolve<ILoginService>();
|
_cipherService = Resolver.Resolve<ICipherService>();
|
||||||
_folderService = Resolver.Resolve<IFolderService>();
|
_folderService = Resolver.Resolve<IFolderService>();
|
||||||
_userDialogs = Resolver.Resolve<IUserDialogs>();
|
_userDialogs = Resolver.Resolve<IUserDialogs>();
|
||||||
_connectivity = Resolver.Resolve<IConnectivity>();
|
_connectivity = Resolver.Resolve<IConnectivity>();
|
||||||
|
@ -177,24 +177,31 @@ namespace Bit.App.Pages
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var login = new Login
|
var cipher = new Cipher
|
||||||
{
|
{
|
||||||
Name = NameCell.Entry.Text.Encrypt(),
|
Name = NameCell.Entry.Text.Encrypt(),
|
||||||
Uri = string.IsNullOrWhiteSpace(UriCell.Entry.Text) ? null : UriCell.Entry.Text.Encrypt(),
|
|
||||||
Username = string.IsNullOrWhiteSpace(UsernameCell.Entry.Text) ? null : UsernameCell.Entry.Text.Encrypt(),
|
|
||||||
Password = string.IsNullOrWhiteSpace(PasswordCell.Entry.Text) ? null : PasswordCell.Entry.Text.Encrypt(),
|
|
||||||
Notes = string.IsNullOrWhiteSpace(NotesCell.Editor.Text) ? null : NotesCell.Editor.Text.Encrypt(),
|
Notes = string.IsNullOrWhiteSpace(NotesCell.Editor.Text) ? null : NotesCell.Editor.Text.Encrypt(),
|
||||||
Totp = string.IsNullOrWhiteSpace(TotpCell.Entry.Text) ? null : TotpCell.Entry.Text.Encrypt(),
|
Favorite = favoriteCell.On,
|
||||||
Favorite = favoriteCell.On
|
Login = new Login
|
||||||
|
{
|
||||||
|
Uri = string.IsNullOrWhiteSpace(UriCell.Entry.Text) ? null :
|
||||||
|
UriCell.Entry.Text.Encrypt(),
|
||||||
|
Username = string.IsNullOrWhiteSpace(UsernameCell.Entry.Text) ? null :
|
||||||
|
UsernameCell.Entry.Text.Encrypt(),
|
||||||
|
Password = string.IsNullOrWhiteSpace(PasswordCell.Entry.Text) ? null :
|
||||||
|
PasswordCell.Entry.Text.Encrypt(),
|
||||||
|
Totp = string.IsNullOrWhiteSpace(TotpCell.Entry.Text) ? null :
|
||||||
|
TotpCell.Entry.Text.Encrypt(),
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if(FolderCell.Picker.SelectedIndex > 0)
|
if(FolderCell.Picker.SelectedIndex > 0)
|
||||||
{
|
{
|
||||||
login.FolderId = folders.ElementAt(FolderCell.Picker.SelectedIndex - 1).Id;
|
cipher.FolderId = folders.ElementAt(FolderCell.Picker.SelectedIndex - 1).Id;
|
||||||
}
|
}
|
||||||
|
|
||||||
_userDialogs.ShowLoading(AppResources.Saving, MaskType.Black);
|
_userDialogs.ShowLoading(AppResources.Saving, MaskType.Black);
|
||||||
var saveTask = await _loginService.SaveAsync(login);
|
var saveTask = await _cipherService.SaveAsync(cipher);
|
||||||
_userDialogs.HideLoading();
|
_userDialogs.HideLoading();
|
||||||
|
|
||||||
if(saveTask.Succeeded)
|
if(saveTask.Succeeded)
|
||||||
|
|
|
@ -17,7 +17,7 @@ namespace Bit.App.Pages
|
||||||
{
|
{
|
||||||
public class VaultAttachmentsPage : ExtendedContentPage
|
public class VaultAttachmentsPage : ExtendedContentPage
|
||||||
{
|
{
|
||||||
private readonly ILoginService _loginService;
|
private readonly ICipherService _cipherService;
|
||||||
private readonly IUserDialogs _userDialogs;
|
private readonly IUserDialogs _userDialogs;
|
||||||
private readonly IConnectivity _connectivity;
|
private readonly IConnectivity _connectivity;
|
||||||
private readonly IDeviceActionService _deviceActiveService;
|
private readonly IDeviceActionService _deviceActiveService;
|
||||||
|
@ -25,7 +25,7 @@ namespace Bit.App.Pages
|
||||||
private readonly ITokenService _tokenService;
|
private readonly ITokenService _tokenService;
|
||||||
private readonly ICryptoService _cryptoService;
|
private readonly ICryptoService _cryptoService;
|
||||||
private readonly string _loginId;
|
private readonly string _loginId;
|
||||||
private Login _login;
|
private Cipher _login;
|
||||||
private byte[] _fileBytes;
|
private byte[] _fileBytes;
|
||||||
private DateTime? _lastAction;
|
private DateTime? _lastAction;
|
||||||
private bool _canUseAttachments = true;
|
private bool _canUseAttachments = true;
|
||||||
|
@ -34,7 +34,7 @@ namespace Bit.App.Pages
|
||||||
: base(true)
|
: base(true)
|
||||||
{
|
{
|
||||||
_loginId = loginId;
|
_loginId = loginId;
|
||||||
_loginService = Resolver.Resolve<ILoginService>();
|
_cipherService = Resolver.Resolve<ICipherService>();
|
||||||
_connectivity = Resolver.Resolve<IConnectivity>();
|
_connectivity = Resolver.Resolve<IConnectivity>();
|
||||||
_userDialogs = Resolver.Resolve<IUserDialogs>();
|
_userDialogs = Resolver.Resolve<IUserDialogs>();
|
||||||
_deviceActiveService = Resolver.Resolve<IDeviceActionService>();
|
_deviceActiveService = Resolver.Resolve<IDeviceActionService>();
|
||||||
|
@ -162,7 +162,7 @@ namespace Bit.App.Pages
|
||||||
}
|
}
|
||||||
|
|
||||||
_userDialogs.ShowLoading(AppResources.Saving, MaskType.Black);
|
_userDialogs.ShowLoading(AppResources.Saving, MaskType.Black);
|
||||||
var saveTask = await _loginService.EncryptAndSaveAttachmentAsync(_login, _fileBytes, FileLabel.Text);
|
var saveTask = await _cipherService.EncryptAndSaveAttachmentAsync(_login, _fileBytes, FileLabel.Text);
|
||||||
|
|
||||||
_userDialogs.HideLoading();
|
_userDialogs.HideLoading();
|
||||||
|
|
||||||
|
@ -223,7 +223,7 @@ namespace Bit.App.Pages
|
||||||
|
|
||||||
private async Task LoadAttachmentsAsync()
|
private async Task LoadAttachmentsAsync()
|
||||||
{
|
{
|
||||||
_login = await _loginService.GetByIdAsync(_loginId);
|
_login = await _cipherService.GetByIdAsync(_loginId);
|
||||||
if(_login == null)
|
if(_login == null)
|
||||||
{
|
{
|
||||||
await Navigation.PopForDeviceAsync();
|
await Navigation.PopForDeviceAsync();
|
||||||
|
@ -268,7 +268,7 @@ namespace Bit.App.Pages
|
||||||
}
|
}
|
||||||
|
|
||||||
_userDialogs.ShowLoading(AppResources.Deleting, MaskType.Black);
|
_userDialogs.ShowLoading(AppResources.Deleting, MaskType.Black);
|
||||||
var saveTask = await _loginService.DeleteAttachmentAsync(_login, attachment.Id);
|
var saveTask = await _cipherService.DeleteAttachmentAsync(_login, attachment.Id);
|
||||||
_userDialogs.HideLoading();
|
_userDialogs.HideLoading();
|
||||||
|
|
||||||
if(saveTask.Succeeded)
|
if(saveTask.Succeeded)
|
||||||
|
|
|
@ -17,7 +17,7 @@ namespace Bit.App.Pages
|
||||||
{
|
{
|
||||||
public class VaultAutofillListLoginsPage : ExtendedContentPage
|
public class VaultAutofillListLoginsPage : ExtendedContentPage
|
||||||
{
|
{
|
||||||
private readonly ILoginService _loginService;
|
private readonly ICipherService _cipherService;
|
||||||
private readonly IDeviceInfoService _deviceInfoService;
|
private readonly IDeviceInfoService _deviceInfoService;
|
||||||
private readonly IDeviceActionService _clipboardService;
|
private readonly IDeviceActionService _clipboardService;
|
||||||
private readonly ISettingsService _settingsService;
|
private readonly ISettingsService _settingsService;
|
||||||
|
@ -40,7 +40,7 @@ namespace Bit.App.Pages
|
||||||
_name = "--";
|
_name = "--";
|
||||||
}
|
}
|
||||||
|
|
||||||
_loginService = Resolver.Resolve<ILoginService>();
|
_cipherService = Resolver.Resolve<ICipherService>();
|
||||||
_deviceInfoService = Resolver.Resolve<IDeviceInfoService>();
|
_deviceInfoService = Resolver.Resolve<IDeviceInfoService>();
|
||||||
_clipboardService = Resolver.Resolve<IDeviceActionService>();
|
_clipboardService = Resolver.Resolve<IDeviceActionService>();
|
||||||
_settingsService = Resolver.Resolve<ISettingsService>();
|
_settingsService = Resolver.Resolve<ISettingsService>();
|
||||||
|
@ -162,7 +162,7 @@ namespace Bit.App.Pages
|
||||||
Task.Run(async () =>
|
Task.Run(async () =>
|
||||||
{
|
{
|
||||||
var autofillGroupings = new List<VaultListPageModel.AutofillGrouping>();
|
var autofillGroupings = new List<VaultListPageModel.AutofillGrouping>();
|
||||||
var logins = await _loginService.GetAllAsync(Uri);
|
var logins = await _cipherService.GetAllAsync(Uri);
|
||||||
|
|
||||||
var normalLogins = logins?.Item1.Select(l => new VaultListPageModel.AutofillLogin(l, false))
|
var normalLogins = logins?.Item1.Select(l => new VaultListPageModel.AutofillLogin(l, false))
|
||||||
.OrderBy(s => s.Name)
|
.OrderBy(s => s.Name)
|
||||||
|
|
|
@ -16,19 +16,19 @@ namespace Bit.App.Pages
|
||||||
{
|
{
|
||||||
public class VaultCustomFieldsPage : ExtendedContentPage
|
public class VaultCustomFieldsPage : ExtendedContentPage
|
||||||
{
|
{
|
||||||
private readonly ILoginService _loginService;
|
private readonly ICipherService _cipherService;
|
||||||
private readonly IUserDialogs _userDialogs;
|
private readonly IUserDialogs _userDialogs;
|
||||||
private readonly IConnectivity _connectivity;
|
private readonly IConnectivity _connectivity;
|
||||||
private readonly IGoogleAnalyticsService _googleAnalyticsService;
|
private readonly IGoogleAnalyticsService _googleAnalyticsService;
|
||||||
private readonly string _loginId;
|
private readonly string _loginId;
|
||||||
private Login _login;
|
private Cipher _login;
|
||||||
private DateTime? _lastAction;
|
private DateTime? _lastAction;
|
||||||
|
|
||||||
public VaultCustomFieldsPage(string loginId)
|
public VaultCustomFieldsPage(string loginId)
|
||||||
: base(true)
|
: base(true)
|
||||||
{
|
{
|
||||||
_loginId = loginId;
|
_loginId = loginId;
|
||||||
_loginService = Resolver.Resolve<ILoginService>();
|
_cipherService = Resolver.Resolve<ICipherService>();
|
||||||
_connectivity = Resolver.Resolve<IConnectivity>();
|
_connectivity = Resolver.Resolve<IConnectivity>();
|
||||||
_userDialogs = Resolver.Resolve<IUserDialogs>();
|
_userDialogs = Resolver.Resolve<IUserDialogs>();
|
||||||
_googleAnalyticsService = Resolver.Resolve<IGoogleAnalyticsService>();
|
_googleAnalyticsService = Resolver.Resolve<IGoogleAnalyticsService>();
|
||||||
|
@ -114,7 +114,7 @@ namespace Bit.App.Pages
|
||||||
}
|
}
|
||||||
|
|
||||||
_userDialogs.ShowLoading(AppResources.Saving, MaskType.Black);
|
_userDialogs.ShowLoading(AppResources.Saving, MaskType.Black);
|
||||||
var saveTask = await _loginService.SaveAsync(_login);
|
var saveTask = await _cipherService.SaveAsync(_login);
|
||||||
|
|
||||||
_userDialogs.HideLoading();
|
_userDialogs.HideLoading();
|
||||||
|
|
||||||
|
@ -148,7 +148,7 @@ namespace Bit.App.Pages
|
||||||
{
|
{
|
||||||
base.OnAppearing();
|
base.OnAppearing();
|
||||||
|
|
||||||
_login = await _loginService.GetByIdAsync(_loginId);
|
_login = await _cipherService.GetByIdAsync(_loginId);
|
||||||
if(_login == null)
|
if(_login == null)
|
||||||
{
|
{
|
||||||
await Navigation.PopForDeviceAsync();
|
await Navigation.PopForDeviceAsync();
|
||||||
|
|
|
@ -15,7 +15,7 @@ namespace Bit.App.Pages
|
||||||
public class VaultEditLoginPage : ExtendedContentPage
|
public class VaultEditLoginPage : ExtendedContentPage
|
||||||
{
|
{
|
||||||
private readonly string _loginId;
|
private readonly string _loginId;
|
||||||
private readonly ILoginService _loginService;
|
private readonly ICipherService _cipherService;
|
||||||
private readonly IFolderService _folderService;
|
private readonly IFolderService _folderService;
|
||||||
private readonly IUserDialogs _userDialogs;
|
private readonly IUserDialogs _userDialogs;
|
||||||
private readonly IConnectivity _connectivity;
|
private readonly IConnectivity _connectivity;
|
||||||
|
@ -26,7 +26,7 @@ namespace Bit.App.Pages
|
||||||
public VaultEditLoginPage(string loginId)
|
public VaultEditLoginPage(string loginId)
|
||||||
{
|
{
|
||||||
_loginId = loginId;
|
_loginId = loginId;
|
||||||
_loginService = Resolver.Resolve<ILoginService>();
|
_cipherService = Resolver.Resolve<ICipherService>();
|
||||||
_folderService = Resolver.Resolve<IFolderService>();
|
_folderService = Resolver.Resolve<IFolderService>();
|
||||||
_userDialogs = Resolver.Resolve<IUserDialogs>();
|
_userDialogs = Resolver.Resolve<IUserDialogs>();
|
||||||
_connectivity = Resolver.Resolve<IConnectivity>();
|
_connectivity = Resolver.Resolve<IConnectivity>();
|
||||||
|
@ -50,8 +50,8 @@ namespace Bit.App.Pages
|
||||||
|
|
||||||
private void Init()
|
private void Init()
|
||||||
{
|
{
|
||||||
var login = _loginService.GetByIdAsync(_loginId).GetAwaiter().GetResult();
|
var cipher = _cipherService.GetByIdAsync(_loginId).GetAwaiter().GetResult();
|
||||||
if(login == null)
|
if(cipher == null)
|
||||||
{
|
{
|
||||||
// TODO: handle error. navigate back? should never happen...
|
// TODO: handle error. navigate back? should never happen...
|
||||||
return;
|
return;
|
||||||
|
@ -59,7 +59,7 @@ namespace Bit.App.Pages
|
||||||
|
|
||||||
NotesCell = new FormEditorCell(height: 300);
|
NotesCell = new FormEditorCell(height: 300);
|
||||||
NotesCell.Editor.Keyboard = Keyboard.Text;
|
NotesCell.Editor.Keyboard = Keyboard.Text;
|
||||||
NotesCell.Editor.Text = login.Notes?.Decrypt(login.OrganizationId);
|
NotesCell.Editor.Text = cipher.Notes?.Decrypt(cipher.OrganizationId);
|
||||||
|
|
||||||
TotpCell = new FormEntryCell(AppResources.AuthenticatorKey, nextElement: NotesCell.Editor,
|
TotpCell = new FormEntryCell(AppResources.AuthenticatorKey, nextElement: NotesCell.Editor,
|
||||||
useButton: _deviceInfo.HasCamera);
|
useButton: _deviceInfo.HasCamera);
|
||||||
|
@ -67,28 +67,28 @@ namespace Bit.App.Pages
|
||||||
{
|
{
|
||||||
TotpCell.Button.Image = "camera";
|
TotpCell.Button.Image = "camera";
|
||||||
}
|
}
|
||||||
TotpCell.Entry.Text = login.Totp?.Decrypt(login.OrganizationId);
|
TotpCell.Entry.Text = cipher.Login?.Totp?.Decrypt(cipher.OrganizationId);
|
||||||
TotpCell.Entry.DisableAutocapitalize = true;
|
TotpCell.Entry.DisableAutocapitalize = true;
|
||||||
TotpCell.Entry.Autocorrect = false;
|
TotpCell.Entry.Autocorrect = false;
|
||||||
TotpCell.Entry.FontFamily = Helpers.OnPlatform(iOS: "Menlo-Regular", Android: "monospace", WinPhone: "Courier");
|
TotpCell.Entry.FontFamily = Helpers.OnPlatform(iOS: "Menlo-Regular", Android: "monospace", WinPhone: "Courier");
|
||||||
|
|
||||||
PasswordCell = new FormEntryCell(AppResources.Password, isPassword: true, nextElement: TotpCell.Entry,
|
PasswordCell = new FormEntryCell(AppResources.Password, isPassword: true, nextElement: TotpCell.Entry,
|
||||||
useButton: true);
|
useButton: true);
|
||||||
PasswordCell.Entry.Text = login.Password?.Decrypt(login.OrganizationId);
|
PasswordCell.Entry.Text = cipher.Login?.Password?.Decrypt(cipher.OrganizationId);
|
||||||
PasswordCell.Button.Image = "eye";
|
PasswordCell.Button.Image = "eye";
|
||||||
PasswordCell.Entry.DisableAutocapitalize = true;
|
PasswordCell.Entry.DisableAutocapitalize = true;
|
||||||
PasswordCell.Entry.Autocorrect = false;
|
PasswordCell.Entry.Autocorrect = false;
|
||||||
PasswordCell.Entry.FontFamily = Helpers.OnPlatform(iOS: "Menlo-Regular", Android: "monospace", WinPhone: "Courier");
|
PasswordCell.Entry.FontFamily = Helpers.OnPlatform(iOS: "Menlo-Regular", Android: "monospace", WinPhone: "Courier");
|
||||||
|
|
||||||
UsernameCell = new FormEntryCell(AppResources.Username, nextElement: PasswordCell.Entry);
|
UsernameCell = new FormEntryCell(AppResources.Username, nextElement: PasswordCell.Entry);
|
||||||
UsernameCell.Entry.Text = login.Username?.Decrypt(login.OrganizationId);
|
UsernameCell.Entry.Text = cipher.Login?.Username?.Decrypt(cipher.OrganizationId);
|
||||||
UsernameCell.Entry.DisableAutocapitalize = true;
|
UsernameCell.Entry.DisableAutocapitalize = true;
|
||||||
UsernameCell.Entry.Autocorrect = false;
|
UsernameCell.Entry.Autocorrect = false;
|
||||||
|
|
||||||
UriCell = new FormEntryCell(AppResources.URI, Keyboard.Url, nextElement: UsernameCell.Entry);
|
UriCell = new FormEntryCell(AppResources.URI, Keyboard.Url, nextElement: UsernameCell.Entry);
|
||||||
UriCell.Entry.Text = login.Uri?.Decrypt(login.OrganizationId);
|
UriCell.Entry.Text = cipher.Login?.Uri?.Decrypt(cipher.OrganizationId);
|
||||||
NameCell = new FormEntryCell(AppResources.Name, nextElement: UriCell.Entry);
|
NameCell = new FormEntryCell(AppResources.Name, nextElement: UriCell.Entry);
|
||||||
NameCell.Entry.Text = login.Name?.Decrypt(login.OrganizationId);
|
NameCell.Entry.Text = cipher.Name?.Decrypt(cipher.OrganizationId);
|
||||||
|
|
||||||
GenerateCell = new ExtendedTextCell
|
GenerateCell = new ExtendedTextCell
|
||||||
{
|
{
|
||||||
|
@ -104,7 +104,7 @@ namespace Bit.App.Pages
|
||||||
foreach(var folder in folders)
|
foreach(var folder in folders)
|
||||||
{
|
{
|
||||||
i++;
|
i++;
|
||||||
if(folder.Id == login.FolderId)
|
if(folder.Id == cipher.FolderId)
|
||||||
{
|
{
|
||||||
selectedIndex = i;
|
selectedIndex = i;
|
||||||
}
|
}
|
||||||
|
@ -117,7 +117,7 @@ namespace Bit.App.Pages
|
||||||
var favoriteCell = new ExtendedSwitchCell
|
var favoriteCell = new ExtendedSwitchCell
|
||||||
{
|
{
|
||||||
Text = AppResources.Favorite,
|
Text = AppResources.Favorite,
|
||||||
On = login.Favorite
|
On = cipher.Favorite
|
||||||
};
|
};
|
||||||
|
|
||||||
AttachmentsCell = new ExtendedTextCell
|
AttachmentsCell = new ExtendedTextCell
|
||||||
|
@ -204,30 +204,34 @@ namespace Bit.App.Pages
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
login.Name = NameCell.Entry.Text.Encrypt(login.OrganizationId);
|
cipher.Name = NameCell.Entry.Text.Encrypt(cipher.OrganizationId);
|
||||||
login.Uri = string.IsNullOrWhiteSpace(UriCell.Entry.Text) ? null :
|
cipher.Notes = string.IsNullOrWhiteSpace(NotesCell.Editor.Text) ? null :
|
||||||
UriCell.Entry.Text.Encrypt(login.OrganizationId);
|
NotesCell.Editor.Text.Encrypt(cipher.OrganizationId);
|
||||||
login.Username = string.IsNullOrWhiteSpace(UsernameCell.Entry.Text) ? null :
|
cipher.Favorite = favoriteCell.On;
|
||||||
UsernameCell.Entry.Text.Encrypt(login.OrganizationId);
|
|
||||||
login.Password = string.IsNullOrWhiteSpace(PasswordCell.Entry.Text) ? null :
|
cipher.Login = new Models.Login
|
||||||
PasswordCell.Entry.Text.Encrypt(login.OrganizationId);
|
{
|
||||||
login.Notes = string.IsNullOrWhiteSpace(NotesCell.Editor.Text) ? null :
|
Uri = string.IsNullOrWhiteSpace(UriCell.Entry.Text) ? null :
|
||||||
NotesCell.Editor.Text.Encrypt(login.OrganizationId);
|
UriCell.Entry.Text.Encrypt(cipher.OrganizationId),
|
||||||
login.Totp = string.IsNullOrWhiteSpace(TotpCell.Entry.Text) ? null :
|
Username = string.IsNullOrWhiteSpace(UsernameCell.Entry.Text) ? null :
|
||||||
TotpCell.Entry.Text.Encrypt(login.OrganizationId);
|
UsernameCell.Entry.Text.Encrypt(cipher.OrganizationId),
|
||||||
login.Favorite = favoriteCell.On;
|
Password = string.IsNullOrWhiteSpace(PasswordCell.Entry.Text) ? null :
|
||||||
|
PasswordCell.Entry.Text.Encrypt(cipher.OrganizationId),
|
||||||
|
Totp = string.IsNullOrWhiteSpace(TotpCell.Entry.Text) ? null :
|
||||||
|
TotpCell.Entry.Text.Encrypt(cipher.OrganizationId)
|
||||||
|
};
|
||||||
|
|
||||||
if(FolderCell.Picker.SelectedIndex > 0)
|
if(FolderCell.Picker.SelectedIndex > 0)
|
||||||
{
|
{
|
||||||
login.FolderId = folders.ElementAt(FolderCell.Picker.SelectedIndex - 1).Id;
|
cipher.FolderId = folders.ElementAt(FolderCell.Picker.SelectedIndex - 1).Id;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
login.FolderId = null;
|
cipher.FolderId = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
_userDialogs.ShowLoading(AppResources.Saving, MaskType.Black);
|
_userDialogs.ShowLoading(AppResources.Saving, MaskType.Black);
|
||||||
var saveTask = await _loginService.SaveAsync(login);
|
var saveTask = await _cipherService.SaveAsync(cipher);
|
||||||
|
|
||||||
_userDialogs.HideLoading();
|
_userDialogs.HideLoading();
|
||||||
|
|
||||||
|
@ -405,7 +409,7 @@ namespace Bit.App.Pages
|
||||||
}
|
}
|
||||||
|
|
||||||
_userDialogs.ShowLoading(AppResources.Deleting, MaskType.Black);
|
_userDialogs.ShowLoading(AppResources.Deleting, MaskType.Black);
|
||||||
var deleteTask = await _loginService.DeleteAsync(_loginId);
|
var deleteTask = await _cipherService.DeleteAsync(_loginId);
|
||||||
_userDialogs.HideLoading();
|
_userDialogs.HideLoading();
|
||||||
|
|
||||||
if(deleteTask.Succeeded)
|
if(deleteTask.Succeeded)
|
||||||
|
|
|
@ -20,7 +20,7 @@ namespace Bit.App.Pages
|
||||||
public class VaultListLoginsPage : ExtendedContentPage
|
public class VaultListLoginsPage : ExtendedContentPage
|
||||||
{
|
{
|
||||||
private readonly IFolderService _folderService;
|
private readonly IFolderService _folderService;
|
||||||
private readonly ILoginService _loginService;
|
private readonly ICipherService _cipherService;
|
||||||
private readonly IUserDialogs _userDialogs;
|
private readonly IUserDialogs _userDialogs;
|
||||||
private readonly IConnectivity _connectivity;
|
private readonly IConnectivity _connectivity;
|
||||||
private readonly IDeviceActionService _clipboardService;
|
private readonly IDeviceActionService _clipboardService;
|
||||||
|
@ -37,7 +37,7 @@ namespace Bit.App.Pages
|
||||||
{
|
{
|
||||||
_favorites = favorites;
|
_favorites = favorites;
|
||||||
_folderService = Resolver.Resolve<IFolderService>();
|
_folderService = Resolver.Resolve<IFolderService>();
|
||||||
_loginService = Resolver.Resolve<ILoginService>();
|
_cipherService = Resolver.Resolve<ICipherService>();
|
||||||
_connectivity = Resolver.Resolve<IConnectivity>();
|
_connectivity = Resolver.Resolve<IConnectivity>();
|
||||||
_userDialogs = Resolver.Resolve<IUserDialogs>();
|
_userDialogs = Resolver.Resolve<IUserDialogs>();
|
||||||
_clipboardService = Resolver.Resolve<IDeviceActionService>();
|
_clipboardService = Resolver.Resolve<IDeviceActionService>();
|
||||||
|
@ -310,7 +310,7 @@ namespace Bit.App.Pages
|
||||||
Task.Run(async () =>
|
Task.Run(async () =>
|
||||||
{
|
{
|
||||||
var foldersTask = _folderService.GetAllAsync();
|
var foldersTask = _folderService.GetAllAsync();
|
||||||
var loginsTask = _favorites ? _loginService.GetAllAsync(true) : _loginService.GetAllAsync();
|
var loginsTask = _favorites ? _cipherService.GetAllAsync(true) : _cipherService.GetAllAsync();
|
||||||
await Task.WhenAll(foldersTask, loginsTask);
|
await Task.WhenAll(foldersTask, loginsTask);
|
||||||
|
|
||||||
var folders = await foldersTask;
|
var folders = await foldersTask;
|
||||||
|
|
|
@ -18,7 +18,7 @@ namespace Bit.App.Pages
|
||||||
public class VaultViewLoginPage : ExtendedContentPage
|
public class VaultViewLoginPage : ExtendedContentPage
|
||||||
{
|
{
|
||||||
private readonly string _loginId;
|
private readonly string _loginId;
|
||||||
private readonly ILoginService _loginService;
|
private readonly ICipherService _cipherService;
|
||||||
private readonly IUserDialogs _userDialogs;
|
private readonly IUserDialogs _userDialogs;
|
||||||
private readonly IDeviceActionService _deviceActionService;
|
private readonly IDeviceActionService _deviceActionService;
|
||||||
private readonly ITokenService _tokenService;
|
private readonly ITokenService _tokenService;
|
||||||
|
@ -27,7 +27,7 @@ namespace Bit.App.Pages
|
||||||
public VaultViewLoginPage(string loginId)
|
public VaultViewLoginPage(string loginId)
|
||||||
{
|
{
|
||||||
_loginId = loginId;
|
_loginId = loginId;
|
||||||
_loginService = Resolver.Resolve<ILoginService>();
|
_cipherService = Resolver.Resolve<ICipherService>();
|
||||||
_userDialogs = Resolver.Resolve<IUserDialogs>();
|
_userDialogs = Resolver.Resolve<IUserDialogs>();
|
||||||
_deviceActionService = Resolver.Resolve<IDeviceActionService>();
|
_deviceActionService = Resolver.Resolve<IDeviceActionService>();
|
||||||
_tokenService = Resolver.Resolve<ITokenService>();
|
_tokenService = Resolver.Resolve<ITokenService>();
|
||||||
|
@ -161,14 +161,14 @@ namespace Bit.App.Pages
|
||||||
NotesCell.Tapped += NotesCell_Tapped;
|
NotesCell.Tapped += NotesCell_Tapped;
|
||||||
EditItem.InitEvents();
|
EditItem.InitEvents();
|
||||||
|
|
||||||
var login = await _loginService.GetByIdAsync(_loginId);
|
var cipher = await _cipherService.GetByIdAsync(_loginId);
|
||||||
if(login == null)
|
if(cipher == null)
|
||||||
{
|
{
|
||||||
await Navigation.PopForDeviceAsync();
|
await Navigation.PopForDeviceAsync();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Model.Update(login);
|
Model.Update(cipher);
|
||||||
|
|
||||||
if(LoginInformationSection.Contains(UriCell))
|
if(LoginInformationSection.Contains(UriCell))
|
||||||
{
|
{
|
||||||
|
@ -211,9 +211,9 @@ namespace Bit.App.Pages
|
||||||
{
|
{
|
||||||
LoginInformationSection.Remove(TotpCodeCell);
|
LoginInformationSection.Remove(TotpCodeCell);
|
||||||
}
|
}
|
||||||
if(login.Totp != null && (_tokenService.TokenPremium || login.OrganizationUseTotp))
|
if(cipher.Login?.Totp != null && (_tokenService.TokenPremium || cipher.OrganizationUseTotp))
|
||||||
{
|
{
|
||||||
var totpKey = login.Totp.Decrypt(login.OrganizationId);
|
var totpKey = cipher.Login?.Totp.Decrypt(cipher.OrganizationId);
|
||||||
if(!string.IsNullOrWhiteSpace(totpKey))
|
if(!string.IsNullOrWhiteSpace(totpKey))
|
||||||
{
|
{
|
||||||
Model.TotpCode = Crypto.Totp(totpKey);
|
Model.TotpCode = Crypto.Totp(totpKey);
|
||||||
|
@ -249,7 +249,7 @@ namespace Bit.App.Pages
|
||||||
{
|
{
|
||||||
var attachmentCell = new AttachmentViewCell(attachment, async () =>
|
var attachmentCell = new AttachmentViewCell(attachment, async () =>
|
||||||
{
|
{
|
||||||
await OpenAttachmentAsync(login, attachment);
|
await OpenAttachmentAsync(cipher, attachment);
|
||||||
});
|
});
|
||||||
AttachmentCells.Add(attachmentCell);
|
AttachmentCells.Add(attachmentCell);
|
||||||
AttachmentsSection.Add(attachmentCell);
|
AttachmentsSection.Add(attachmentCell);
|
||||||
|
@ -309,7 +309,7 @@ namespace Bit.App.Pages
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task OpenAttachmentAsync(Login login, VaultViewLoginPageModel.Attachment attachment)
|
private async Task OpenAttachmentAsync(Cipher login, VaultViewLoginPageModel.Attachment attachment)
|
||||||
{
|
{
|
||||||
if(!_tokenService.TokenPremium && !login.OrganizationUseTotp)
|
if(!_tokenService.TokenPremium && !login.OrganizationUseTotp)
|
||||||
{
|
{
|
||||||
|
@ -332,7 +332,7 @@ namespace Bit.App.Pages
|
||||||
}
|
}
|
||||||
|
|
||||||
_userDialogs.ShowLoading(AppResources.Downloading, MaskType.Black);
|
_userDialogs.ShowLoading(AppResources.Downloading, MaskType.Black);
|
||||||
var data = await _loginService.DownloadAndDecryptAttachmentAsync(attachment.Url, login.OrganizationId);
|
var data = await _cipherService.DownloadAndDecryptAttachmentAsync(attachment.Url, login.OrganizationId);
|
||||||
_userDialogs.HideLoading();
|
_userDialogs.HideLoading();
|
||||||
if(data == null)
|
if(data == null)
|
||||||
{
|
{
|
||||||
|
|
|
@ -13,9 +13,10 @@ namespace Bit.App.Repositories
|
||||||
: base(sqlService)
|
: base(sqlService)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
public Task<IEnumerable<AttachmentData>> GetAllByLoginIdAsync(string loginId)
|
public Task<IEnumerable<AttachmentData>> GetAllByCipherIdAsync(string cipherId)
|
||||||
{
|
{
|
||||||
var attachments = Connection.Table<AttachmentData>().Where(a => a.LoginId == loginId).Cast<AttachmentData>();
|
var attachments = Connection.Table<AttachmentData>().Where(a => a.LoginId == cipherId)
|
||||||
|
.Cast<AttachmentData>();
|
||||||
return Task.FromResult(attachments);
|
return Task.FromResult(attachments);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
29
src/App/Repositories/CipherRepository.cs
Normal file
29
src/App/Repositories/CipherRepository.cs
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Bit.App.Abstractions;
|
||||||
|
using Bit.App.Models.Data;
|
||||||
|
|
||||||
|
namespace Bit.App.Repositories
|
||||||
|
{
|
||||||
|
public class CipherRepository : Repository<CipherData, string>, ICipherRepository
|
||||||
|
{
|
||||||
|
public CipherRepository(ISqlService sqlService)
|
||||||
|
: base(sqlService)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
public Task<IEnumerable<CipherData>> GetAllByUserIdAsync(string userId)
|
||||||
|
{
|
||||||
|
var logins = Connection.Table<CipherData>().Where(l => l.UserId == userId).Cast<CipherData>();
|
||||||
|
return Task.FromResult(logins);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task<IEnumerable<CipherData>> GetAllByUserIdAsync(string userId, bool favorite)
|
||||||
|
{
|
||||||
|
var logins = Connection.Table<CipherData>().Where(l => l.UserId == userId && l.Favorite == favorite)
|
||||||
|
.Cast<CipherData>();
|
||||||
|
return Task.FromResult(logins);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -22,11 +22,11 @@ namespace Bit.App.Repositories
|
||||||
public override Task DeleteAsync(string id)
|
public override Task DeleteAsync(string id)
|
||||||
{
|
{
|
||||||
var now = DateTime.UtcNow;
|
var now = DateTime.UtcNow;
|
||||||
DeleteWithLoginUpdateAsync(id, now);
|
DeleteWithCipherUpdateAsync(id, now);
|
||||||
return Task.FromResult(0);
|
return Task.FromResult(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task DeleteWithLoginUpdateAsync(string id, DateTime revisionDate)
|
public Task DeleteWithCipherUpdateAsync(string id, DateTime revisionDate)
|
||||||
{
|
{
|
||||||
Connection.RunInTransaction(() =>
|
Connection.RunInTransaction(() =>
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,29 +0,0 @@
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Bit.App.Abstractions;
|
|
||||||
using Bit.App.Models.Data;
|
|
||||||
|
|
||||||
namespace Bit.App.Repositories
|
|
||||||
{
|
|
||||||
public class LoginRepository : Repository<LoginData, string>, ILoginRepository
|
|
||||||
{
|
|
||||||
public LoginRepository(ISqlService sqlService)
|
|
||||||
: base(sqlService)
|
|
||||||
{ }
|
|
||||||
|
|
||||||
public Task<IEnumerable<LoginData>> GetAllByUserIdAsync(string userId)
|
|
||||||
{
|
|
||||||
var logins = Connection.Table<LoginData>().Where(l => l.UserId == userId).Cast<LoginData>();
|
|
||||||
return Task.FromResult(logins);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Task<IEnumerable<LoginData>> GetAllByUserIdAsync(string userId, bool favorite)
|
|
||||||
{
|
|
||||||
var logins = Connection.Table<LoginData>().Where(l => l.UserId == userId && l.Favorite == favorite)
|
|
||||||
.Cast<LoginData>();
|
|
||||||
return Task.FromResult(logins);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -11,26 +11,26 @@ using System.Net.Http;
|
||||||
|
|
||||||
namespace Bit.App.Services
|
namespace Bit.App.Services
|
||||||
{
|
{
|
||||||
public class LoginService : ILoginService
|
public class CipherService : ICipherService
|
||||||
{
|
{
|
||||||
private readonly string[] _ignoredSearchTerms = new string[] { "com", "net", "org", "android",
|
private readonly string[] _ignoredSearchTerms = new string[] { "com", "net", "org", "android",
|
||||||
"io", "co", "uk", "au", "nz", "fr", "de", "tv", "info", "app", "apps", "eu", "me", "dev", "jp", "mobile" };
|
"io", "co", "uk", "au", "nz", "fr", "de", "tv", "info", "app", "apps", "eu", "me", "dev", "jp", "mobile" };
|
||||||
private readonly ILoginRepository _loginRepository;
|
private readonly ICipherRepository _cipherRepository;
|
||||||
private readonly IAttachmentRepository _attachmentRepository;
|
private readonly IAttachmentRepository _attachmentRepository;
|
||||||
private readonly IAuthService _authService;
|
private readonly IAuthService _authService;
|
||||||
private readonly ICipherApiRepository _cipherApiRepository;
|
private readonly ICipherApiRepository _cipherApiRepository;
|
||||||
private readonly ISettingsService _settingsService;
|
private readonly ISettingsService _settingsService;
|
||||||
private readonly ICryptoService _cryptoService;
|
private readonly ICryptoService _cryptoService;
|
||||||
|
|
||||||
public LoginService(
|
public CipherService(
|
||||||
ILoginRepository loginRepository,
|
ICipherRepository cipherRepository,
|
||||||
IAttachmentRepository attachmentRepository,
|
IAttachmentRepository attachmentRepository,
|
||||||
IAuthService authService,
|
IAuthService authService,
|
||||||
ICipherApiRepository cipherApiRepository,
|
ICipherApiRepository cipherApiRepository,
|
||||||
ISettingsService settingsService,
|
ISettingsService settingsService,
|
||||||
ICryptoService cryptoService)
|
ICryptoService cryptoService)
|
||||||
{
|
{
|
||||||
_loginRepository = loginRepository;
|
_cipherRepository = cipherRepository;
|
||||||
_attachmentRepository = attachmentRepository;
|
_attachmentRepository = attachmentRepository;
|
||||||
_authService = authService;
|
_authService = authService;
|
||||||
_cipherApiRepository = cipherApiRepository;
|
_cipherApiRepository = cipherApiRepository;
|
||||||
|
@ -38,38 +38,38 @@ namespace Bit.App.Services
|
||||||
_cryptoService = cryptoService;
|
_cryptoService = cryptoService;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<Login> GetByIdAsync(string id)
|
public async Task<Cipher> GetByIdAsync(string id)
|
||||||
{
|
{
|
||||||
var data = await _loginRepository.GetByIdAsync(id);
|
var data = await _cipherRepository.GetByIdAsync(id);
|
||||||
if(data == null || data.UserId != _authService.UserId)
|
if(data == null || data.UserId != _authService.UserId)
|
||||||
{
|
{
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
var attachments = await _attachmentRepository.GetAllByLoginIdAsync(id);
|
var attachments = await _attachmentRepository.GetAllByCipherIdAsync(id);
|
||||||
var login = new Login(data, attachments);
|
var cipher = new Cipher(data, attachments);
|
||||||
return login;
|
return cipher;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<IEnumerable<Login>> GetAllAsync()
|
public async Task<IEnumerable<Cipher>> GetAllAsync()
|
||||||
{
|
{
|
||||||
var attachmentData = await _attachmentRepository.GetAllByUserIdAsync(_authService.UserId);
|
var attachmentData = await _attachmentRepository.GetAllByUserIdAsync(_authService.UserId);
|
||||||
var attachmentDict = attachmentData.GroupBy(a => a.LoginId).ToDictionary(g => g.Key, g => g.ToList());
|
var attachmentDict = attachmentData.GroupBy(a => a.LoginId).ToDictionary(g => g.Key, g => g.ToList());
|
||||||
var data = await _loginRepository.GetAllByUserIdAsync(_authService.UserId);
|
var data = await _cipherRepository.GetAllByUserIdAsync(_authService.UserId);
|
||||||
var logins = data.Select(f => new Login(f, attachmentDict.ContainsKey(f.Id) ? attachmentDict[f.Id] : null));
|
var logins = data.Select(f => new Cipher(f, attachmentDict.ContainsKey(f.Id) ? attachmentDict[f.Id] : null));
|
||||||
return logins;
|
return logins;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<IEnumerable<Login>> GetAllAsync(bool favorites)
|
public async Task<IEnumerable<Cipher>> GetAllAsync(bool favorites)
|
||||||
{
|
{
|
||||||
var attachmentData = await _attachmentRepository.GetAllByUserIdAsync(_authService.UserId);
|
var attachmentData = await _attachmentRepository.GetAllByUserIdAsync(_authService.UserId);
|
||||||
var attachmentDict = attachmentData.GroupBy(a => a.LoginId).ToDictionary(g => g.Key, g => g.ToList());
|
var attachmentDict = attachmentData.GroupBy(a => a.LoginId).ToDictionary(g => g.Key, g => g.ToList());
|
||||||
var data = await _loginRepository.GetAllByUserIdAsync(_authService.UserId, favorites);
|
var data = await _cipherRepository.GetAllByUserIdAsync(_authService.UserId, favorites);
|
||||||
var logins = data.Select(f => new Login(f, attachmentDict.ContainsKey(f.Id) ? attachmentDict[f.Id] : null));
|
var logins = data.Select(f => new Cipher(f, attachmentDict.ContainsKey(f.Id) ? attachmentDict[f.Id] : null));
|
||||||
return logins;
|
return logins;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<Tuple<IEnumerable<Login>, IEnumerable<Login>>> GetAllAsync(string uriString)
|
public async Task<Tuple<IEnumerable<Cipher>, IEnumerable<Cipher>>> GetAllAsync(string uriString)
|
||||||
{
|
{
|
||||||
if(string.IsNullOrWhiteSpace(uriString))
|
if(string.IsNullOrWhiteSpace(uriString))
|
||||||
{
|
{
|
||||||
|
@ -125,9 +125,9 @@ namespace Bit.App.Services
|
||||||
|
|
||||||
var matchingDomainsArray = matchingDomains.ToArray();
|
var matchingDomainsArray = matchingDomains.ToArray();
|
||||||
var matchingFuzzyDomainsArray = matchingFuzzyDomains.ToArray();
|
var matchingFuzzyDomainsArray = matchingFuzzyDomains.ToArray();
|
||||||
var matchingLogins = new List<Login>();
|
var matchingLogins = new List<Cipher>();
|
||||||
var matchingFuzzyLogins = new List<Login>();
|
var matchingFuzzyLogins = new List<Cipher>();
|
||||||
var logins = await _loginRepository.GetAllByUserIdAsync(_authService.UserId);
|
var logins = await _cipherRepository.GetAllByUserIdAsync(_authService.UserId);
|
||||||
foreach(var login in logins)
|
foreach(var login in logins)
|
||||||
{
|
{
|
||||||
if(string.IsNullOrWhiteSpace(login.Uri))
|
if(string.IsNullOrWhiteSpace(login.Uri))
|
||||||
|
@ -143,12 +143,12 @@ namespace Bit.App.Services
|
||||||
|
|
||||||
if(Array.IndexOf(matchingDomainsArray, loginUriString) >= 0)
|
if(Array.IndexOf(matchingDomainsArray, loginUriString) >= 0)
|
||||||
{
|
{
|
||||||
matchingLogins.Add(new Login(login));
|
matchingLogins.Add(new Cipher(login));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
else if(mobileApp && Array.IndexOf(matchingFuzzyDomainsArray, loginUriString) >= 0)
|
else if(mobileApp && Array.IndexOf(matchingFuzzyDomainsArray, loginUriString) >= 0)
|
||||||
{
|
{
|
||||||
matchingFuzzyLogins.Add(new Login(login));
|
matchingFuzzyLogins.Add(new Cipher(login));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
else if(!mobileApp)
|
else if(!mobileApp)
|
||||||
|
@ -156,7 +156,7 @@ namespace Bit.App.Services
|
||||||
var info = InfoFromMobileAppUri(loginUriString);
|
var info = InfoFromMobileAppUri(loginUriString);
|
||||||
if(info?.Item1 != null && Array.IndexOf(matchingDomainsArray, info.Item1) >= 0)
|
if(info?.Item1 != null && Array.IndexOf(matchingDomainsArray, info.Item1) >= 0)
|
||||||
{
|
{
|
||||||
matchingFuzzyLogins.Add(new Login(login));
|
matchingFuzzyLogins.Add(new Cipher(login));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -170,12 +170,12 @@ namespace Bit.App.Services
|
||||||
|
|
||||||
if(Array.IndexOf(matchingDomainsArray, loginDomainName) >= 0)
|
if(Array.IndexOf(matchingDomainsArray, loginDomainName) >= 0)
|
||||||
{
|
{
|
||||||
matchingLogins.Add(new Login(login));
|
matchingLogins.Add(new Cipher(login));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
else if(mobileApp && Array.IndexOf(matchingFuzzyDomainsArray, loginDomainName) >= 0)
|
else if(mobileApp && Array.IndexOf(matchingFuzzyDomainsArray, loginDomainName) >= 0)
|
||||||
{
|
{
|
||||||
matchingFuzzyLogins.Add(new Login(login));
|
matchingFuzzyLogins.Add(new Cipher(login));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -197,7 +197,7 @@ namespace Bit.App.Services
|
||||||
|
|
||||||
if(addedFromSearchTerm)
|
if(addedFromSearchTerm)
|
||||||
{
|
{
|
||||||
matchingFuzzyLogins.Add(new Login(login));
|
matchingFuzzyLogins.Add(new Cipher(login));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -209,10 +209,10 @@ namespace Bit.App.Services
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return new Tuple<IEnumerable<Login>, IEnumerable<Login>>(matchingLogins, matchingFuzzyLogins);
|
return new Tuple<IEnumerable<Cipher>, IEnumerable<Cipher>>(matchingLogins, matchingFuzzyLogins);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<ApiResult<CipherResponse>> SaveAsync(Login login)
|
public async Task<ApiResult<CipherResponse>> SaveAsync(Cipher login)
|
||||||
{
|
{
|
||||||
ApiResult<CipherResponse> response = null;
|
ApiResult<CipherResponse> response = null;
|
||||||
var request = new CipherRequest(login);
|
var request = new CipherRequest(login);
|
||||||
|
@ -228,15 +228,15 @@ namespace Bit.App.Services
|
||||||
|
|
||||||
if(response.Succeeded)
|
if(response.Succeeded)
|
||||||
{
|
{
|
||||||
var data = new LoginData(response.Result, _authService.UserId);
|
var data = new CipherData(response.Result, _authService.UserId);
|
||||||
if(login.Id == null)
|
if(login.Id == null)
|
||||||
{
|
{
|
||||||
await _loginRepository.InsertAsync(data);
|
await _cipherRepository.InsertAsync(data);
|
||||||
login.Id = data.Id;
|
login.Id = data.Id;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
await _loginRepository.UpdateAsync(data);
|
await _cipherRepository.UpdateAsync(data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if(response.StatusCode == System.Net.HttpStatusCode.Forbidden
|
else if(response.StatusCode == System.Net.HttpStatusCode.Forbidden
|
||||||
|
@ -253,7 +253,7 @@ namespace Bit.App.Services
|
||||||
var response = await _cipherApiRepository.DeleteAsync(id);
|
var response = await _cipherApiRepository.DeleteAsync(id);
|
||||||
if(response.Succeeded)
|
if(response.Succeeded)
|
||||||
{
|
{
|
||||||
await _loginRepository.DeleteAsync(id);
|
await _cipherRepository.DeleteAsync(id);
|
||||||
}
|
}
|
||||||
else if(response.StatusCode == System.Net.HttpStatusCode.Forbidden
|
else if(response.StatusCode == System.Net.HttpStatusCode.Forbidden
|
||||||
|| response.StatusCode == System.Net.HttpStatusCode.Unauthorized)
|
|| response.StatusCode == System.Net.HttpStatusCode.Unauthorized)
|
||||||
|
@ -298,7 +298,7 @@ namespace Bit.App.Services
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<ApiResult<CipherResponse>> EncryptAndSaveAttachmentAsync(Login login, byte[] data, string fileName)
|
public async Task<ApiResult<CipherResponse>> EncryptAndSaveAttachmentAsync(Cipher login, byte[] data, string fileName)
|
||||||
{
|
{
|
||||||
var encFileName = fileName.Encrypt(login.OrganizationId);
|
var encFileName = fileName.Encrypt(login.OrganizationId);
|
||||||
var encBytes = _cryptoService.EncryptToBytes(data,
|
var encBytes = _cryptoService.EncryptToBytes(data,
|
||||||
|
@ -323,7 +323,7 @@ namespace Bit.App.Services
|
||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<ApiResult> DeleteAttachmentAsync(Login login, string attachmentId)
|
public async Task<ApiResult> DeleteAttachmentAsync(Cipher login, string attachmentId)
|
||||||
{
|
{
|
||||||
var response = await _cipherApiRepository.DeleteAttachmentAsync(login.Id, attachmentId);
|
var response = await _cipherApiRepository.DeleteAttachmentAsync(login.Id, attachmentId);
|
||||||
if(response.Succeeded)
|
if(response.Succeeded)
|
|
@ -17,7 +17,7 @@ namespace Bit.App.Services
|
||||||
public void CreateTables()
|
public void CreateTables()
|
||||||
{
|
{
|
||||||
_connection.CreateTable<FolderData>();
|
_connection.CreateTable<FolderData>();
|
||||||
_connection.CreateTable<LoginData>();
|
_connection.CreateTable<CipherData>();
|
||||||
_connection.CreateTable<AttachmentData>();
|
_connection.CreateTable<AttachmentData>();
|
||||||
_connection.CreateTable<SettingsData>();
|
_connection.CreateTable<SettingsData>();
|
||||||
}
|
}
|
||||||
|
|
|
@ -110,7 +110,7 @@ namespace Bit.App.Services
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
_syncService.SyncDeleteLoginAsync(loginDeleteMessage.Id);
|
_syncService.SyncDeleteCipherAsync(loginDeleteMessage.Id);
|
||||||
break;
|
break;
|
||||||
case Enums.PushType.SyncCiphers:
|
case Enums.PushType.SyncCiphers:
|
||||||
case Enums.PushType.SyncVault:
|
case Enums.PushType.SyncVault:
|
||||||
|
|
|
@ -20,7 +20,7 @@ namespace Bit.App.Services
|
||||||
private readonly ISettingsApiRepository _settingsApiRepository;
|
private readonly ISettingsApiRepository _settingsApiRepository;
|
||||||
private readonly ISyncApiRepository _syncApiRepository;
|
private readonly ISyncApiRepository _syncApiRepository;
|
||||||
private readonly IFolderRepository _folderRepository;
|
private readonly IFolderRepository _folderRepository;
|
||||||
private readonly ILoginRepository _loginRepository;
|
private readonly ICipherRepository _cipherRepository;
|
||||||
private readonly IAttachmentRepository _attachmentRepository;
|
private readonly IAttachmentRepository _attachmentRepository;
|
||||||
private readonly ISettingsRepository _settingsRepository;
|
private readonly ISettingsRepository _settingsRepository;
|
||||||
private readonly IAuthService _authService;
|
private readonly IAuthService _authService;
|
||||||
|
@ -35,7 +35,7 @@ namespace Bit.App.Services
|
||||||
ISettingsApiRepository settingsApiRepository,
|
ISettingsApiRepository settingsApiRepository,
|
||||||
ISyncApiRepository syncApiRepository,
|
ISyncApiRepository syncApiRepository,
|
||||||
IFolderRepository folderRepository,
|
IFolderRepository folderRepository,
|
||||||
ILoginRepository loginRepository,
|
ICipherRepository cipherRepository,
|
||||||
IAttachmentRepository attachmentRepository,
|
IAttachmentRepository attachmentRepository,
|
||||||
ISettingsRepository settingsRepository,
|
ISettingsRepository settingsRepository,
|
||||||
IAuthService authService,
|
IAuthService authService,
|
||||||
|
@ -49,7 +49,7 @@ namespace Bit.App.Services
|
||||||
_settingsApiRepository = settingsApiRepository;
|
_settingsApiRepository = settingsApiRepository;
|
||||||
_syncApiRepository = syncApiRepository;
|
_syncApiRepository = syncApiRepository;
|
||||||
_folderRepository = folderRepository;
|
_folderRepository = folderRepository;
|
||||||
_loginRepository = loginRepository;
|
_cipherRepository = cipherRepository;
|
||||||
_attachmentRepository = attachmentRepository;
|
_attachmentRepository = attachmentRepository;
|
||||||
_settingsRepository = settingsRepository;
|
_settingsRepository = settingsRepository;
|
||||||
_authService = authService;
|
_authService = authService;
|
||||||
|
@ -77,20 +77,17 @@ namespace Bit.App.Services
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
switch(cipher.Result.Type)
|
var cipherData = new CipherData(cipher.Result, _authService.UserId);
|
||||||
{
|
await _cipherRepository.UpsertAsync(cipherData).ConfigureAwait(false);
|
||||||
case Enums.CipherType.Login:
|
|
||||||
var loginData = new LoginData(cipher.Result, _authService.UserId);
|
|
||||||
await _loginRepository.UpsertAsync(loginData).ConfigureAwait(false);
|
|
||||||
|
|
||||||
var localAttachments = (await _attachmentRepository.GetAllByLoginIdAsync(loginData.Id)
|
var localAttachments = (await _attachmentRepository.GetAllByCipherIdAsync(cipherData.Id)
|
||||||
.ConfigureAwait(false));
|
.ConfigureAwait(false));
|
||||||
|
|
||||||
if(cipher.Result.Attachments != null)
|
if(cipher.Result.Attachments != null)
|
||||||
{
|
{
|
||||||
foreach(var attachment in cipher.Result.Attachments)
|
foreach(var attachment in cipher.Result.Attachments)
|
||||||
{
|
{
|
||||||
var attachmentData = new AttachmentData(attachment, loginData.Id);
|
var attachmentData = new AttachmentData(attachment, cipherData.Id);
|
||||||
await _attachmentRepository.UpsertAsync(attachmentData).ConfigureAwait(false);
|
await _attachmentRepository.UpsertAsync(attachmentData).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -107,11 +104,6 @@ namespace Bit.App.Services
|
||||||
catch(SQLite.SQLiteException) { }
|
catch(SQLite.SQLiteException) { }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
default:
|
|
||||||
SyncCompleted(false);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
catch(SQLite.SQLiteException)
|
catch(SQLite.SQLiteException)
|
||||||
{
|
{
|
||||||
|
@ -164,7 +156,7 @@ namespace Bit.App.Services
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
await _folderRepository.DeleteWithLoginUpdateAsync(id, revisionDate).ConfigureAwait(false);
|
await _folderRepository.DeleteWithCipherUpdateAsync(id, revisionDate).ConfigureAwait(false);
|
||||||
SyncCompleted(true);
|
SyncCompleted(true);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -175,7 +167,7 @@ namespace Bit.App.Services
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<bool> SyncDeleteLoginAsync(string id)
|
public async Task<bool> SyncDeleteCipherAsync(string id)
|
||||||
{
|
{
|
||||||
if(!_authService.IsAuthenticated)
|
if(!_authService.IsAuthenticated)
|
||||||
{
|
{
|
||||||
|
@ -186,7 +178,7 @@ namespace Bit.App.Services
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
await _loginRepository.DeleteAsync(id).ConfigureAwait(false);
|
await _cipherRepository.DeleteAsync(id).ConfigureAwait(false);
|
||||||
SyncCompleted(true);
|
SyncCompleted(true);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -277,17 +269,16 @@ namespace Bit.App.Services
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
var loginsDict = syncResponse.Result.Ciphers.Where(c => c.Type == Enums.CipherType.Login)
|
var ciphersDict = syncResponse.Result.Ciphers.ToDictionary(s => s.Id);
|
||||||
.ToDictionary(s => s.Id);
|
|
||||||
var foldersDict = syncResponse.Result.Folders.ToDictionary(f => f.Id);
|
var foldersDict = syncResponse.Result.Folders.ToDictionary(f => f.Id);
|
||||||
|
|
||||||
var loginTask = SyncLoginsAsync(loginsDict);
|
var cipherTask = SyncCiphersAsync(ciphersDict);
|
||||||
var folderTask = SyncFoldersAsync(foldersDict);
|
var folderTask = SyncFoldersAsync(foldersDict);
|
||||||
var domainsTask = SyncDomainsAsync(syncResponse.Result.Domains);
|
var domainsTask = SyncDomainsAsync(syncResponse.Result.Domains);
|
||||||
var profileTask = SyncProfileKeysAsync(syncResponse.Result.Profile);
|
var profileTask = SyncProfileKeysAsync(syncResponse.Result.Profile);
|
||||||
await Task.WhenAll(loginTask, folderTask, domainsTask, profileTask).ConfigureAwait(false);
|
await Task.WhenAll(cipherTask, folderTask, domainsTask, profileTask).ConfigureAwait(false);
|
||||||
|
|
||||||
if(folderTask.Exception != null || loginTask.Exception != null || domainsTask.Exception != null ||
|
if(folderTask.Exception != null || cipherTask.Exception != null || domainsTask.Exception != null ||
|
||||||
profileTask.Exception != null)
|
profileTask.Exception != null)
|
||||||
{
|
{
|
||||||
SyncCompleted(false);
|
SyncCompleted(false);
|
||||||
|
@ -361,14 +352,14 @@ namespace Bit.App.Services
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task SyncLoginsAsync(IDictionary<string, CipherResponse> serverLogins)
|
private async Task SyncCiphersAsync(IDictionary<string, CipherResponse> serviceCiphers)
|
||||||
{
|
{
|
||||||
if(!_authService.IsAuthenticated)
|
if(!_authService.IsAuthenticated)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var localLogins = (await _loginRepository.GetAllByUserIdAsync(_authService.UserId)
|
var localCiphers = (await _cipherRepository.GetAllByUserIdAsync(_authService.UserId)
|
||||||
.ConfigureAwait(false))
|
.ConfigureAwait(false))
|
||||||
.GroupBy(s => s.Id)
|
.GroupBy(s => s.Id)
|
||||||
.Select(s => s.First())
|
.Select(s => s.First())
|
||||||
|
@ -379,7 +370,7 @@ namespace Bit.App.Services
|
||||||
.GroupBy(a => a.LoginId)
|
.GroupBy(a => a.LoginId)
|
||||||
.ToDictionary(g => g.Key);
|
.ToDictionary(g => g.Key);
|
||||||
|
|
||||||
foreach(var serverLogin in serverLogins)
|
foreach(var serverCipher in serviceCiphers)
|
||||||
{
|
{
|
||||||
if(!_authService.IsAuthenticated)
|
if(!_authService.IsAuthenticated)
|
||||||
{
|
{
|
||||||
|
@ -388,24 +379,25 @@ namespace Bit.App.Services
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var localLogin = localLogins.ContainsKey(serverLogin.Value.Id) ? localLogins[serverLogin.Value.Id] : null;
|
var localCipher = localCiphers.ContainsKey(serverCipher.Value.Id) ?
|
||||||
|
localCiphers[serverCipher.Value.Id] : null;
|
||||||
|
|
||||||
var data = new LoginData(serverLogin.Value, _authService.UserId);
|
var data = new CipherData(serverCipher.Value, _authService.UserId);
|
||||||
await _loginRepository.UpsertAsync(data).ConfigureAwait(false);
|
await _cipherRepository.UpsertAsync(data).ConfigureAwait(false);
|
||||||
|
|
||||||
if(serverLogin.Value.Attachments != null)
|
if(serverCipher.Value.Attachments != null)
|
||||||
{
|
{
|
||||||
foreach(var attachment in serverLogin.Value.Attachments)
|
foreach(var attachment in serverCipher.Value.Attachments)
|
||||||
{
|
{
|
||||||
var attachmentData = new AttachmentData(attachment, data.Id);
|
var attachmentData = new AttachmentData(attachment, data.Id);
|
||||||
await _attachmentRepository.UpsertAsync(attachmentData).ConfigureAwait(false);
|
await _attachmentRepository.UpsertAsync(attachmentData).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(localLogin != null && localAttachments != null && localAttachments.ContainsKey(localLogin.Id))
|
if(localCipher != null && localAttachments != null && localAttachments.ContainsKey(localCipher.Id))
|
||||||
{
|
{
|
||||||
foreach(var attachment in localAttachments[localLogin.Id]
|
foreach(var attachment in localAttachments[localCipher.Id]
|
||||||
.Where(a => !serverLogin.Value.Attachments.Any(sa => sa.Id == a.Id)))
|
.Where(a => !serverCipher.Value.Attachments.Any(sa => sa.Id == a.Id)))
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
@ -418,11 +410,11 @@ namespace Bit.App.Services
|
||||||
catch(SQLite.SQLiteException) { }
|
catch(SQLite.SQLiteException) { }
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach(var login in localLogins.Where(localLogin => !serverLogins.ContainsKey(localLogin.Key)))
|
foreach(var cipher in localCiphers.Where(local => !serviceCiphers.ContainsKey(local.Key)))
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
await _loginRepository.DeleteAsync(login.Value.Id).ConfigureAwait(false);
|
await _cipherRepository.DeleteAsync(cipher.Value.Id).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
catch(SQLite.SQLiteException) { }
|
catch(SQLite.SQLiteException) { }
|
||||||
}
|
}
|
||||||
|
|
|
@ -88,7 +88,7 @@ namespace Bit.UWP
|
||||||
container.RegisterSingleton<IKeyDerivationService, KeyDerivationService>();
|
container.RegisterSingleton<IKeyDerivationService, KeyDerivationService>();
|
||||||
container.RegisterSingleton<IAuthService, AuthService>();
|
container.RegisterSingleton<IAuthService, AuthService>();
|
||||||
container.RegisterSingleton<IFolderService, FolderService>();
|
container.RegisterSingleton<IFolderService, FolderService>();
|
||||||
container.RegisterSingleton<ILoginService, LoginService>();
|
container.RegisterSingleton<ICipherService, CipherService>();
|
||||||
container.RegisterSingleton<ISyncService, SyncService>();
|
container.RegisterSingleton<ISyncService, SyncService>();
|
||||||
container.RegisterSingleton<IDeviceActionService, DeviceActionService>();
|
container.RegisterSingleton<IDeviceActionService, DeviceActionService>();
|
||||||
container.RegisterSingleton<IAppIdService, AppIdService>();
|
container.RegisterSingleton<IAppIdService, AppIdService>();
|
||||||
|
@ -108,7 +108,7 @@ namespace Bit.UWP
|
||||||
// Repositories
|
// Repositories
|
||||||
container.RegisterSingleton<IFolderRepository, FolderRepository>();
|
container.RegisterSingleton<IFolderRepository, FolderRepository>();
|
||||||
container.RegisterSingleton<IFolderApiRepository, FolderApiRepository>();
|
container.RegisterSingleton<IFolderApiRepository, FolderApiRepository>();
|
||||||
container.RegisterSingleton<ILoginRepository, LoginRepository>();
|
container.RegisterSingleton<ICipherRepository, CipherRepository>();
|
||||||
container.RegisterSingleton<IAttachmentRepository, AttachmentRepository>();
|
container.RegisterSingleton<IAttachmentRepository, AttachmentRepository>();
|
||||||
container.RegisterSingleton<IConnectApiRepository, ConnectApiRepository>();
|
container.RegisterSingleton<IConnectApiRepository, ConnectApiRepository>();
|
||||||
container.RegisterSingleton<IDeviceApiRepository, DeviceApiRepository>();
|
container.RegisterSingleton<IDeviceApiRepository, DeviceApiRepository>();
|
||||||
|
|
|
@ -277,7 +277,7 @@ namespace Bit.iOS.Extension
|
||||||
container.RegisterSingleton<IKeyDerivationService, CommonCryptoKeyDerivationService>();
|
container.RegisterSingleton<IKeyDerivationService, CommonCryptoKeyDerivationService>();
|
||||||
container.RegisterSingleton<IAuthService, AuthService>();
|
container.RegisterSingleton<IAuthService, AuthService>();
|
||||||
container.RegisterSingleton<IFolderService, FolderService>();
|
container.RegisterSingleton<IFolderService, FolderService>();
|
||||||
container.RegisterSingleton<ILoginService, LoginService>();
|
container.RegisterSingleton<ICipherService, CipherService>();
|
||||||
container.RegisterSingleton<ISyncService, SyncService>();
|
container.RegisterSingleton<ISyncService, SyncService>();
|
||||||
container.RegisterSingleton<IPasswordGenerationService, PasswordGenerationService>();
|
container.RegisterSingleton<IPasswordGenerationService, PasswordGenerationService>();
|
||||||
container.RegisterSingleton<IAppIdService, AppIdService>();
|
container.RegisterSingleton<IAppIdService, AppIdService>();
|
||||||
|
@ -294,7 +294,7 @@ namespace Bit.iOS.Extension
|
||||||
// Repositories
|
// Repositories
|
||||||
container.RegisterSingleton<IFolderRepository, FolderRepository>();
|
container.RegisterSingleton<IFolderRepository, FolderRepository>();
|
||||||
container.RegisterSingleton<IFolderApiRepository, FolderApiRepository>();
|
container.RegisterSingleton<IFolderApiRepository, FolderApiRepository>();
|
||||||
container.RegisterSingleton<ILoginRepository, LoginRepository>();
|
container.RegisterSingleton<ICipherRepository, CipherRepository>();
|
||||||
container.RegisterSingleton<IAttachmentRepository, AttachmentRepository>();
|
container.RegisterSingleton<IAttachmentRepository, AttachmentRepository>();
|
||||||
container.RegisterSingleton<IConnectApiRepository, ConnectApiRepository>();
|
container.RegisterSingleton<IConnectApiRepository, ConnectApiRepository>();
|
||||||
container.RegisterSingleton<ISettingsRepository, SettingsRepository>();
|
container.RegisterSingleton<ISettingsRepository, SettingsRepository>();
|
||||||
|
|
|
@ -19,7 +19,7 @@ namespace Bit.iOS.Extension
|
||||||
{
|
{
|
||||||
public partial class LoginAddViewController : ExtendedUITableViewController
|
public partial class LoginAddViewController : ExtendedUITableViewController
|
||||||
{
|
{
|
||||||
private ILoginService _loginService;
|
private ICipherService _cipherService;
|
||||||
private IFolderService _folderService;
|
private IFolderService _folderService;
|
||||||
private IConnectivity _connectivity;
|
private IConnectivity _connectivity;
|
||||||
private IEnumerable<Folder> _folders;
|
private IEnumerable<Folder> _folders;
|
||||||
|
@ -49,7 +49,7 @@ namespace Bit.iOS.Extension
|
||||||
|
|
||||||
public override void ViewDidLoad()
|
public override void ViewDidLoad()
|
||||||
{
|
{
|
||||||
_loginService = Resolver.Resolve<ILoginService>();
|
_cipherService = Resolver.Resolve<ICipherService>();
|
||||||
_connectivity = Resolver.Resolve<IConnectivity>();
|
_connectivity = Resolver.Resolve<IConnectivity>();
|
||||||
_folderService = Resolver.Resolve<IFolderService>();
|
_folderService = Resolver.Resolve<IFolderService>();
|
||||||
_googleAnalyticsService = Resolver.Resolve<IGoogleAnalyticsService>();
|
_googleAnalyticsService = Resolver.Resolve<IGoogleAnalyticsService>();
|
||||||
|
@ -151,18 +151,21 @@ namespace Bit.iOS.Extension
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var login = new Login
|
var cipher = new Cipher
|
||||||
{
|
{
|
||||||
Uri = string.IsNullOrWhiteSpace(UriCell.TextField.Text) ? null : UriCell.TextField.Text.Encrypt(),
|
|
||||||
Name = string.IsNullOrWhiteSpace(NameCell.TextField.Text) ? null : NameCell.TextField.Text.Encrypt(),
|
Name = string.IsNullOrWhiteSpace(NameCell.TextField.Text) ? null : NameCell.TextField.Text.Encrypt(),
|
||||||
Username = string.IsNullOrWhiteSpace(UsernameCell.TextField.Text) ? null : UsernameCell.TextField.Text.Encrypt(),
|
|
||||||
Password = string.IsNullOrWhiteSpace(PasswordCell.TextField.Text) ? null : PasswordCell.TextField.Text.Encrypt(),
|
|
||||||
Notes = string.IsNullOrWhiteSpace(NotesCell.TextView.Text) ? null : NotesCell.TextView.Text.Encrypt(),
|
Notes = string.IsNullOrWhiteSpace(NotesCell.TextView.Text) ? null : NotesCell.TextView.Text.Encrypt(),
|
||||||
Favorite = FavoriteCell.Switch.On,
|
Favorite = FavoriteCell.Switch.On,
|
||||||
FolderId = FolderCell.SelectedIndex == 0 ? null : _folders.ElementAtOrDefault(FolderCell.SelectedIndex - 1)?.Id
|
FolderId = FolderCell.SelectedIndex == 0 ? null : _folders.ElementAtOrDefault(FolderCell.SelectedIndex - 1)?.Id,
|
||||||
|
Login = new Login
|
||||||
|
{
|
||||||
|
Uri = string.IsNullOrWhiteSpace(UriCell.TextField.Text) ? null : UriCell.TextField.Text.Encrypt(),
|
||||||
|
Username = string.IsNullOrWhiteSpace(UsernameCell.TextField.Text) ? null : UsernameCell.TextField.Text.Encrypt(),
|
||||||
|
Password = string.IsNullOrWhiteSpace(PasswordCell.TextField.Text) ? null : PasswordCell.TextField.Text.Encrypt()
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
var saveTask = _loginService.SaveAsync(login);
|
var saveTask = _cipherService.SaveAsync(cipher);
|
||||||
var loadingAlert = Dialogs.CreateLoadingAlert(AppResources.Saving);
|
var loadingAlert = Dialogs.CreateLoadingAlert(AppResources.Saving);
|
||||||
PresentViewController(loadingAlert, true, null);
|
PresentViewController(loadingAlert, true, null);
|
||||||
await saveTask;
|
await saveTask;
|
||||||
|
|
|
@ -105,7 +105,7 @@ namespace Bit.iOS.Extension
|
||||||
private IEnumerable<LoginViewModel> _tableItems = new List<LoginViewModel>();
|
private IEnumerable<LoginViewModel> _tableItems = new List<LoginViewModel>();
|
||||||
private Context _context;
|
private Context _context;
|
||||||
private LoginListViewController _controller;
|
private LoginListViewController _controller;
|
||||||
private ILoginService _loginService;
|
private ICipherService _cipherService;
|
||||||
private ISettings _settings;
|
private ISettings _settings;
|
||||||
private bool _isPremium;
|
private bool _isPremium;
|
||||||
|
|
||||||
|
@ -114,15 +114,15 @@ namespace Bit.iOS.Extension
|
||||||
_context = controller.Context;
|
_context = controller.Context;
|
||||||
_controller = controller;
|
_controller = controller;
|
||||||
_isPremium = Resolver.Resolve<ITokenService>()?.TokenPremium ?? false;
|
_isPremium = Resolver.Resolve<ITokenService>()?.TokenPremium ?? false;
|
||||||
_loginService = Resolver.Resolve<ILoginService>();
|
_cipherService = Resolver.Resolve<ICipherService>();
|
||||||
_settings = Resolver.Resolve<ISettings>();
|
_settings = Resolver.Resolve<ISettings>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task LoadItemsAsync()
|
public async Task LoadItemsAsync()
|
||||||
{
|
{
|
||||||
var combinedLogins = new List<Login>();
|
var combinedLogins = new List<Cipher>();
|
||||||
|
|
||||||
var logins = await _loginService.GetAllAsync(_context.UrlString);
|
var logins = await _cipherService.GetAllAsync(_context.UrlString);
|
||||||
if(logins?.Item1 != null)
|
if(logins?.Item1 != null)
|
||||||
{
|
{
|
||||||
combinedLogins.AddRange(logins.Item1);
|
combinedLogins.AddRange(logins.Item1);
|
||||||
|
|
|
@ -7,7 +7,7 @@ namespace Bit.iOS.Extension.Models
|
||||||
{
|
{
|
||||||
public class LoginViewModel
|
public class LoginViewModel
|
||||||
{
|
{
|
||||||
public LoginViewModel(Login login)
|
public LoginViewModel(Cipher login)
|
||||||
{
|
{
|
||||||
Id = login.Id;
|
Id = login.Id;
|
||||||
Name = login.Name?.Decrypt(login.OrganizationId);
|
Name = login.Name?.Decrypt(login.OrganizationId);
|
||||||
|
|
|
@ -256,7 +256,7 @@ namespace Bit.iOS
|
||||||
container.RegisterSingleton<IKeyDerivationService, CommonCryptoKeyDerivationService>();
|
container.RegisterSingleton<IKeyDerivationService, CommonCryptoKeyDerivationService>();
|
||||||
container.RegisterSingleton<IAuthService, AuthService>();
|
container.RegisterSingleton<IAuthService, AuthService>();
|
||||||
container.RegisterSingleton<IFolderService, FolderService>();
|
container.RegisterSingleton<IFolderService, FolderService>();
|
||||||
container.RegisterSingleton<ILoginService, LoginService>();
|
container.RegisterSingleton<ICipherService, CipherService>();
|
||||||
container.RegisterSingleton<ISyncService, SyncService>();
|
container.RegisterSingleton<ISyncService, SyncService>();
|
||||||
container.RegisterSingleton<IDeviceActionService, DeviceActionService>();
|
container.RegisterSingleton<IDeviceActionService, DeviceActionService>();
|
||||||
container.RegisterSingleton<IAppIdService, AppIdService>();
|
container.RegisterSingleton<IAppIdService, AppIdService>();
|
||||||
|
@ -276,7 +276,7 @@ namespace Bit.iOS
|
||||||
// Repositories
|
// Repositories
|
||||||
container.RegisterSingleton<IFolderRepository, FolderRepository>();
|
container.RegisterSingleton<IFolderRepository, FolderRepository>();
|
||||||
container.RegisterSingleton<IFolderApiRepository, FolderApiRepository>();
|
container.RegisterSingleton<IFolderApiRepository, FolderApiRepository>();
|
||||||
container.RegisterSingleton<ILoginRepository, LoginRepository>();
|
container.RegisterSingleton<ICipherRepository, CipherRepository>();
|
||||||
container.RegisterSingleton<IAttachmentRepository, AttachmentRepository>();
|
container.RegisterSingleton<IAttachmentRepository, AttachmentRepository>();
|
||||||
container.RegisterSingleton<IConnectApiRepository, ConnectApiRepository>();
|
container.RegisterSingleton<IConnectApiRepository, ConnectApiRepository>();
|
||||||
container.RegisterSingleton<IDeviceApiRepository, DeviceApiRepository>();
|
container.RegisterSingleton<IDeviceApiRepository, DeviceApiRepository>();
|
||||||
|
|
Loading…
Reference in a new issue