1
0
mirror of https://github.com/bitwarden/mobile.git synced 2025-02-07 23:51:26 +01:00

[PM-3222] Migration of data from LiteDB to shared pref storage (#2724)

* Migration of data from LiteDB to shared pref storage

* tweaks
This commit is contained in:
mpbw2 2023-08-30 10:55:20 -04:00 committed by GitHub
parent 4d0f9d1c03
commit dbadf8c56f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 373 additions and 87 deletions

View File

@ -150,6 +150,12 @@ namespace Bit.App.Pages
private async Task SaveActivityAsync()
{
SetServices();
if (await _stateService.GetActiveUserIdAsync() == null)
{
// Fresh install and/or all users logged out won't have an active user, skip saving last active time
return;
}
await _stateService.SetLastActiveTimeAsync(_deviceActionService.GetActiveTime());
}
}

View File

@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Bit.Core;
using Bit.Core.Abstractions;
@ -11,27 +12,16 @@ namespace Bit.App.Services
private readonly IStorageService _preferencesStorageService;
private readonly IStorageService _liteDbStorageService;
private readonly HashSet<string> _preferenceStorageKeys = new HashSet<string>
private readonly HashSet<string> _liteDbStorageKeys = new HashSet<string>
{
Constants.StateVersionKey,
Constants.PreAuthEnvironmentUrlsKey,
Constants.AutofillTileAdded,
Constants.AddSitePromptShownKey,
Constants.PushInitialPromptShownKey,
Constants.LastFileCacheClearKey,
Constants.PushRegisteredTokenKey,
Constants.LastBuildKey,
Constants.ClearCiphersCacheKey,
Constants.BiometricIntegritySourceKey,
Constants.iOSExtensionActiveUserIdKey,
Constants.iOSAutoFillClearCiphersCacheKey,
Constants.iOSAutoFillBiometricIntegritySourceKey,
Constants.iOSExtensionClearCiphersCacheKey,
Constants.iOSExtensionBiometricIntegritySourceKey,
Constants.iOSShareExtensionClearCiphersCacheKey,
Constants.iOSShareExtensionBiometricIntegritySourceKey,
Constants.RememberedEmailKey,
Constants.RememberedOrgIdentifierKey
Constants.EventCollectionKey,
Constants.CiphersKey(""),
Constants.FoldersKey(""),
Constants.CollectionsKey(""),
Constants.CiphersLocalDataKey(""),
Constants.SendsKey(""),
Constants.PassGenHistoryKey(""),
Constants.SettingsKey(""),
};
public MobileStorageService(
@ -44,29 +34,30 @@ namespace Bit.App.Services
public async Task<T> GetAsync<T>(string key)
{
if (_preferenceStorageKeys.Contains(key))
if (IsLiteDbKey(key))
{
return await _preferencesStorageService.GetAsync<T>(key);
return await _liteDbStorageService.GetAsync<T>(key);
}
return await _liteDbStorageService.GetAsync<T>(key);
return await _preferencesStorageService.GetAsync<T>(key) ?? await TryMigrateLiteDbToPrefsAsync<T>(key);
}
public Task SaveAsync<T>(string key, T obj)
{
if (_preferenceStorageKeys.Contains(key))
if (IsLiteDbKey(key))
{
return _preferencesStorageService.SaveAsync(key, obj);
return _liteDbStorageService.SaveAsync(key, obj);
}
return _liteDbStorageService.SaveAsync(key, obj);
return _preferencesStorageService.SaveAsync(key, obj);
}
public Task RemoveAsync(string key)
{
if (_preferenceStorageKeys.Contains(key))
if (IsLiteDbKey(key))
{
return _preferencesStorageService.RemoveAsync(key);
return _liteDbStorageService.RemoveAsync(key);
}
return _liteDbStorageService.RemoveAsync(key);
return _preferencesStorageService.RemoveAsync(key);
}
public void Dispose()
@ -80,5 +71,25 @@ namespace Bit.App.Services
disposablePrefService.Dispose();
}
}
// Helpers
private bool IsLiteDbKey(string key)
{
return _liteDbStorageKeys.Any(key.StartsWith) ||
_liteDbStorageKeys.Contains(key);
}
private async Task<T> TryMigrateLiteDbToPrefsAsync<T>(string key)
{
var currentValue = await _liteDbStorageService.GetAsync<T>(key);
if (currentValue != null)
{
await _preferencesStorageService.SaveAsync(key, currentValue);
await _liteDbStorageService.RemoveAsync(key);
}
return currentValue;
}
}
}

View File

@ -5,6 +5,5 @@ namespace Bit.Core.Abstractions
public interface IAppIdService
{
Task<string> GetAppIdAsync();
Task<string> GetAnonymousAppIdAsync();
}
}

View File

@ -35,7 +35,6 @@ namespace Bit.Core.Abstractions
Task ReplaceAsync(Dictionary<string, CipherData> ciphers);
Task<Cipher> SaveAttachmentRawWithServerAsync(Cipher cipher, string filename, byte[] data);
Task SaveCollectionsWithServerAsync(Cipher cipher);
Task SaveNeverDomainAsync(string domain);
Task SaveWithServerAsync(Cipher cipher);
Task<ShareWithServerError> ShareWithServerAsync(CipherView cipher, string organizationId, HashSet<string> collectionIds);
Task UpdateLastUsedDateAsync(string id);

View File

@ -92,14 +92,12 @@ namespace Bit.Core.Abstractions
Task SetInlineAutofillEnabledAsync(bool? value, string userId = null);
Task<bool?> GetAutofillDisableSavePromptAsync(string userId = null);
Task SetAutofillDisableSavePromptAsync(bool? value, string userId = null);
Task<Dictionary<string, Dictionary<string, object>>> GetLocalDataAsync(string userId = null);
Task SetLocalDataAsync(Dictionary<string, Dictionary<string, object>> value, string userId = null);
Task<Dictionary<string, Dictionary<string, object>>> GetCiphersLocalDataAsync(string userId = null);
Task SetCiphersLocalDataAsync(Dictionary<string, Dictionary<string, object>> value, string userId = null);
Task<Dictionary<string, CipherData>> GetEncryptedCiphersAsync(string userId = null);
Task SetEncryptedCiphersAsync(Dictionary<string, CipherData> value, string userId = null);
Task<int?> GetDefaultUriMatchAsync(string userId = null);
Task SetDefaultUriMatchAsync(int? value, string userId = null);
Task<HashSet<string>> GetNeverDomainsAsync(string userId = null);
Task SetNeverDomainsAsync(HashSet<string> value, string userId = null);
Task<int?> GetClearClipboardAsync(string userId = null);
Task SetClearClipboardAsync(int? value, string userId = null);
Task<Dictionary<string, CollectionData>> GetEncryptedCollectionsAsync(string userId = null);

View File

@ -9,11 +9,12 @@ namespace Bit.Core
public const string AndroidAppProtocol = "androidapp://";
public const string iOSAppProtocol = "iosapp://";
public const string DefaultUsernameGenerated = "-";
public const string AppIdKey = "appId";
public const string StateVersionKey = "stateVersion";
public const string StateKey = "state";
public const string PreAuthEnvironmentUrlsKey = "preAuthEnvironmentUrls";
public const string LastFileCacheClearKey = "lastFileCacheClear";
public const string AutofillTileAdded = "autofillTileAdded";
public const string AutofillTileAddedKey = "autofillTileAdded";
public const string PushRegisteredTokenKey = "pushRegisteredToken";
public const string PushInitialPromptShownKey = "pushInitialPromptShown";
public const string PushInstallationRegistrationErrorKey = "pushInstallationRegistrationError";
@ -92,8 +93,7 @@ namespace Bit.Core
public static string FoldersKey(string userId) => $"folders_{userId}";
public static string CollectionsKey(string userId) => $"collections_{userId}";
public static string OrganizationsKey(string userId) => $"organizations_{userId}";
public static string LocalDataKey(string userId) => $"ciphersLocalData_{userId}";
public static string NeverDomainsKey(string userId) => $"neverDomains_{userId}";
public static string CiphersLocalDataKey(string userId) => $"ciphersLocalData_{userId}";
public static string SendsKey(string userId) => $"sends_{userId}";
public static string PoliciesKey(string userId) => $"policies_{userId}";
public static string EncOrgKeysKey(string userId) => $"encOrgKeys_{userId}";

View File

@ -15,12 +15,7 @@ namespace Bit.Core.Services
public Task<string> GetAppIdAsync()
{
return MakeAndGetAppIdAsync("appId");
}
public Task<string> GetAnonymousAppIdAsync()
{
return MakeAndGetAppIdAsync("anonymousAppId");
return MakeAndGetAppIdAsync(Constants.AppIdKey);
}
private async Task<string> MakeAndGetAppIdAsync(string key)

View File

@ -208,7 +208,7 @@ namespace Bit.Core.Services
public async Task<Cipher> GetAsync(string id)
{
var localData = await _stateService.GetLocalDataAsync();
var localData = await _stateService.GetCiphersLocalDataAsync();
var ciphers = await _stateService.GetEncryptedCiphersAsync();
if (!ciphers?.ContainsKey(id) ?? true)
{
@ -220,7 +220,7 @@ namespace Bit.Core.Services
public async Task<List<Cipher>> GetAllAsync()
{
var localData = await _stateService.GetLocalDataAsync();
var localData = await _stateService.GetCiphersLocalDataAsync();
var ciphers = await _stateService.GetEncryptedCiphersAsync();
var response = ciphers?.Select(c => new Cipher(c.Value, false,
localData?.ContainsKey(c.Key) ?? false ? localData[c.Key] : null));
@ -458,7 +458,7 @@ namespace Bit.Core.Services
public async Task UpdateLastUsedDateAsync(string id)
{
var ciphersLocalData = await _stateService.GetLocalDataAsync();
var ciphersLocalData = await _stateService.GetCiphersLocalDataAsync();
if (ciphersLocalData == null)
{
ciphersLocalData = new Dictionary<string, Dictionary<string, object>>();
@ -476,7 +476,7 @@ namespace Bit.Core.Services
ciphersLocalData[id].Add("lastUsedDate", DateTime.UtcNow);
}
await _stateService.SetLocalDataAsync(ciphersLocalData);
await _stateService.SetCiphersLocalDataAsync(ciphersLocalData);
// Update cache
if (DecryptedCipherCache == null)
{
@ -489,21 +489,6 @@ namespace Bit.Core.Services
}
}
public async Task SaveNeverDomainAsync(string domain)
{
if (string.IsNullOrWhiteSpace(domain))
{
return;
}
var domains = await _stateService.GetNeverDomainsAsync();
if (domains == null)
{
domains = new HashSet<string>();
}
domains.Add(domain);
await _stateService.SetNeverDomainsAsync(domains);
}
public async Task SaveWithServerAsync(Cipher cipher)
{
CipherResponse response;

View File

@ -13,7 +13,7 @@ namespace Bit.Core.Services
{
public class StateMigrationService : IStateMigrationService
{
private const int StateVersion = 5;
private const int StateVersion = 6;
private readonly DeviceType _deviceType;
private readonly IStorageService _preferencesStorageService;
@ -80,9 +80,12 @@ namespace Bit.Core.Services
goto case 3;
case 3:
await MigrateFrom3To4Async();
break;
goto case 4;
case 4:
await MigrateFrom4To5Async();
goto case 5;
case 5:
await MigrateFrom5To6Async();
break;
}
}
@ -544,6 +547,296 @@ namespace Bit.Core.Services
#endregion
#region v5 to v6 Migration
private async Task MigrateFrom5To6Async()
{
// global data
await MoveToPrefsAsync<string>(V6Keys.AppIdKey);
await MoveToPrefsAsync<bool?>(V6Keys.DisableFaviconKey);
await MoveToPrefsAsync<string>(V6Keys.ThemeKey);
await MoveToPrefsAsync<string>(V6Keys.AutoDarkThemeKey);
await MoveToPrefsAsync<V6Keys.PasswordlessRequestNotification>(V6Keys.PasswordlessLoginNotificationKey);
await MoveToPrefsAsync<string>(V6Keys.PreLoginEmailKey);
await MoveToPrefsAsync<bool?>(V6Keys.LastUserShouldConnectToWatchKey);
await MoveToPrefsAsync<string>(V6Keys.PushInstallationRegistrationErrorKey);
await MoveToPrefsAsync<bool?>(V6Keys.AutofillNeedsIdentityReplacementKey);
// account data
var state = await GetValueAsync<State>(Storage.LiteDb, Constants.StateKey);
if (state?.Accounts != null)
{
await SetValueAsync(Storage.Prefs, Constants.StateKey, state);
foreach (var account in state.Accounts.Where(a => a.Value?.Profile?.UserId != null))
{
var userId = account.Value.Profile.UserId;
await MoveToPrefsAsync<bool?>(V6Keys.BiometricUnlockKey(userId));
await MoveToPrefsAsync<string>(V6Keys.ProtectedPinKey(userId));
await MoveToPrefsAsync<string>(V6Keys.PinKeyEncryptedUserKeyKey(userId));
await MoveToPrefsAsync<string>(V6Keys.KeyHashKey(userId));
await MoveToPrefsAsync<string>(V6Keys.MasterKeyEncryptedUserKeyKey(userId));
await MoveToPrefsAsync<Dictionary<string, string>>(V6Keys.EncOrgKeysKey(userId));
await MoveToPrefsAsync<string>(V6Keys.EncPrivateKeyKey(userId));
await MoveToPrefsAsync<List<string>>(V6Keys.AutofillBlacklistedUrisKey(userId));
await MoveToPrefsAsync<long?>(V6Keys.LastActiveTimeKey(userId));
await MoveToPrefsAsync<int?>(V6Keys.VaultTimeoutKey(userId));
await MoveToPrefsAsync<V6Keys.VaultTimeoutAction?>(V6Keys.VaultTimeoutActionKey(userId));
await MoveToPrefsAsync<bool?>(V6Keys.ScreenCaptureAllowedKey(userId));
await MoveToPrefsAsync<V6Keys.PreviousPageInfo>(V6Keys.PreviousPageKey(userId));
await MoveToPrefsAsync<int>(V6Keys.InvalidUnlockAttemptsKey(userId));
await MoveToPrefsAsync<bool?>(V6Keys.DisableAutoTotpCopyKey(userId));
await MoveToPrefsAsync<bool?>(V6Keys.InlineAutofillEnabledKey(userId));
await MoveToPrefsAsync<bool?>(V6Keys.AutofillDisableSavePromptKey(userId));
await MoveToPrefsAsync<int?>(V6Keys.DefaultUriMatchKey(userId));
await MoveToPrefsAsync<int?>(V6Keys.ClearClipboardKey(userId));
await MoveToPrefsAsync<bool?>(V6Keys.PasswordRepromptAutofillKey(userId));
await MoveToPrefsAsync<bool?>(V6Keys.PasswordVerifiedAutofillKey(userId));
await MoveToPrefsAsync<DateTime?>(V6Keys.LastSyncKey(userId));
await MoveToPrefsAsync<bool?>(V6Keys.SyncOnRefreshKey(userId));
await MoveToPrefsAsync<DateTime?>(V6Keys.PushLastRegistrationDateKey(userId));
await MoveToPrefsAsync<string>(V6Keys.PushCurrentTokenKey(userId));
await MoveToPrefsAsync<Dictionary<string, V6Keys.PolicyData>>(V6Keys.PoliciesKey(userId));
await MoveToPrefsAsync<bool?>(V6Keys.UsesKeyConnectorKey(userId));
await MoveToPrefsAsync<Dictionary<string, V6Keys.OrganizationData>>(
V6Keys.OrganizationsKey(userId));
await MoveToPrefsAsync<V6Keys.PasswordGenerationOptions>(V6Keys.PassGenOptionsKey(userId));
await MoveToPrefsAsync<V6Keys.UsernameGenerationOptions>(V6Keys.UsernameGenOptionsKey(userId));
await MoveToPrefsAsync<string>(V6Keys.TwoFactorTokenKey(userId));
await MoveToPrefsAsync<bool?>(V6Keys.ApprovePasswordlessLoginsKey(userId));
await MoveToPrefsAsync<bool?>(V6Keys.ShouldConnectToWatchKey(userId));
await MoveToPrefsAsync<string>(V6Keys.DeviceKeyKey(userId));
}
}
await RemoveValueAsync(Storage.LiteDb, Constants.StateKey);
await RemoveValueAsync(Storage.LiteDb, V6Keys.LastActiveTimeKey(""));
// Update stored version
await SetLastStateVersionAsync(6);
}
private class V6Keys
{
// global keys
internal const string AppIdKey = "appId";
internal const string DisableFaviconKey = "disableFavicon";
internal const string ThemeKey = "theme";
internal const string AutoDarkThemeKey = "autoDarkTheme";
internal const string PasswordlessLoginNotificationKey = "passwordlessLoginNotificationKey";
internal const string PreLoginEmailKey = "preLoginEmailKey";
internal const string LastUserShouldConnectToWatchKey = "lastUserShouldConnectToWatch";
internal const string PushInstallationRegistrationErrorKey = "pushInstallationRegistrationError";
internal const string AutofillNeedsIdentityReplacementKey = "autofillNeedsIdentityReplacement";
// account keys
internal static string BiometricUnlockKey(string userId) => $"biometricUnlock_{userId}";
internal static string ProtectedPinKey(string userId) => $"protectedPin_{userId}";
internal static string PinKeyEncryptedUserKeyKey(string userId) => $"pinKeyEncryptedUserKey_{userId}";
internal static string KeyHashKey(string userId) => $"keyHash_{userId}";
internal static string MasterKeyEncryptedUserKeyKey(string userId) => $"masterKeyEncryptedUserKey_{userId}";
internal static string EncOrgKeysKey(string userId) => $"encOrgKeys_{userId}";
internal static string EncPrivateKeyKey(string userId) => $"encPrivateKey_{userId}";
internal static string AutofillBlacklistedUrisKey(string userId) => $"autofillBlacklistedUris_{userId}";
internal static string LastActiveTimeKey(string userId) => $"lastActiveTime_{userId}";
internal static string VaultTimeoutKey(string userId) => $"vaultTimeout_{userId}";
internal static string VaultTimeoutActionKey(string userId) => $"vaultTimeoutAction_{userId}";
internal static string ScreenCaptureAllowedKey(string userId) => $"screenCaptureAllowed_{userId}";
internal static string PreviousPageKey(string userId) => $"previousPage_{userId}";
internal static string InvalidUnlockAttemptsKey(string userId) => $"invalidUnlockAttempts_{userId}";
internal static string DisableAutoTotpCopyKey(string userId) => $"disableAutoTotpCopy_{userId}";
internal static string InlineAutofillEnabledKey(string userId) => $"inlineAutofillEnabled_{userId}";
internal static string AutofillDisableSavePromptKey(string userId) => $"autofillDisableSavePrompt_{userId}";
internal static string DefaultUriMatchKey(string userId) => $"defaultUriMatch_{userId}";
internal static string ClearClipboardKey(string userId) => $"clearClipboard_{userId}";
internal static string PasswordRepromptAutofillKey(string userId) => $"passwordRepromptAutofillKey_{userId}";
internal static string PasswordVerifiedAutofillKey(string userId) => $"passwordVerifiedAutofillKey_{userId}";
internal static string LastSyncKey(string userId) => $"lastSync_{userId}";
internal static string SyncOnRefreshKey(string userId) => $"syncOnRefresh_{userId}";
internal static string PushLastRegistrationDateKey(string userId) => $"pushLastRegistrationDate_{userId}";
internal static string PushCurrentTokenKey(string userId) => $"pushCurrentToken_{userId}";
internal static string PoliciesKey(string userId) => $"policies_{userId}";
internal static string UsesKeyConnectorKey(string userId) => $"usesKeyConnector_{userId}";
internal static string OrganizationsKey(string userId) => $"organizations_{userId}";
internal static string PassGenOptionsKey(string userId) => $"passwordGenerationOptions_{userId}";
internal static string UsernameGenOptionsKey(string userId) => $"usernameGenerationOptions_{userId}";
internal static string TwoFactorTokenKey(string email) => $"twoFactorToken_{email}";
internal static string ApprovePasswordlessLoginsKey(string userId) => $"approvePasswordlessLogins_{userId}";
internal static string ShouldConnectToWatchKey(string userId) => $"shouldConnectToWatch_{userId}";
internal static string DeviceKeyKey(string userId) => $"deviceKey_{userId}";
// objects
internal class PasswordlessRequestNotification
{
public string UserId { get; set; }
public string Id { get; set; }
}
internal enum VaultTimeoutAction
{
Lock = 0,
Logout = 1,
}
internal class PreviousPageInfo
{
public string Page { get; set; }
public string CipherId { get; set; }
public string SendId { get; set; }
public string SearchText { get; set; }
}
internal class PolicyData
{
public string Id { get; set; }
public string OrganizationId { get; set; }
public V6Keys.PolicyType Type { get; set; }
public Dictionary<string, object> Data { get; set; }
public bool Enabled { get; set; }
}
internal enum PolicyType : byte
{
TwoFactorAuthentication = 0,
MasterPassword = 1,
PasswordGenerator = 2,
OnlyOrg = 3,
RequireSso = 4,
PersonalOwnership = 5,
DisableSend = 6,
SendOptions = 7,
ResetPassword = 8,
MaximumVaultTimeout = 9,
DisablePersonalVaultExport = 10,
}
internal class OrganizationData
{
public string Id { get; set; }
public string Name { get; set; }
public V6Keys.OrganizationUserStatusType Status { get; set; }
public V6Keys.OrganizationUserType Type { get; set; }
public bool Enabled { get; set; }
public bool UseGroups { get; set; }
public bool UseDirectory { get; set; }
public bool UseEvents { get; set; }
public bool UseTotp { get; set; }
public bool Use2fa { get; set; }
public bool UseApi { get; set; }
public bool UsePolicies { get; set; }
public bool SelfHost { get; set; }
public bool UsersGetPremium { get; set; }
public int? Seats { get; set; }
public short? MaxCollections { get; set; }
public short? MaxStorageGb { get; set; }
public V6Keys.Permissions Permissions { get; set; } = new Permissions();
public string Identifier { get; set; }
public bool UsesKeyConnector { get; set; }
public string KeyConnectorUrl { get; set; }
}
internal enum OrganizationUserStatusType : byte
{
Invited = 0,
Accepted = 1,
Confirmed = 2
}
internal enum OrganizationUserType : byte
{
Owner = 0,
Admin = 1,
User = 2,
Manager = 3,
Custom = 4,
}
internal class Permissions
{
public bool AccessBusinessPortal { get; set; }
public bool AccessEventLogs { get; set; }
public bool AccessImportExport { get; set; }
public bool AccessReports { get; set; }
public bool EditAssignedCollections { get; set; }
public bool DeleteAssignedCollections { get; set; }
public bool CreateNewCollections { get; set; }
public bool EditAnyCollection { get; set; }
public bool DeleteAnyCollection { get; set; }
public bool ManageGroups { get; set; }
public bool ManagePolicies { get; set; }
public bool ManageSso { get; set; }
public bool ManageUsers { get; set; }
}
internal class PasswordGenerationOptions
{
public int? Length { get; set; }
public bool? AllowAmbiguousChar { get; set; }
public bool? Number { get; set; }
public int? MinNumber { get; set; }
public bool? Uppercase { get; set; }
public int? MinUppercase { get; set; }
public bool? Lowercase { get; set; }
public int? MinLowercase { get; set; }
public bool? Special { get; set; }
public int? MinSpecial { get; set; }
public string Type { get; set; }
public int? NumWords { get; set; }
public string WordSeparator { get; set; }
public bool? Capitalize { get; set; }
public bool? IncludeNumber { get; set; }
}
internal class UsernameGenerationOptions
{
public V6Keys.UsernameType Type { get; set; }
public V6Keys.ForwardedEmailServiceType ServiceType { get; set; }
public V6Keys.UsernameEmailType PlusAddressedEmailType { get; set; }
public V6Keys.UsernameEmailType CatchAllEmailType { get; set; }
public bool CapitalizeRandomWordUsername { get; set; }
public bool IncludeNumberRandomWordUsername { get; set; }
public string PlusAddressedEmail { get; set; }
public string CatchAllEmailDomain { get; set; }
public string FirefoxRelayApiAccessToken { get; set; }
public string SimpleLoginApiKey { get; set; }
public string DuckDuckGoApiKey { get; set; }
public string FastMailApiKey { get; set; }
public string AnonAddyApiAccessToken { get; set; }
public string AnonAddyDomainName { get; set; }
public string EmailWebsite { get; set; }
}
internal enum UsernameType
{
PlusAddressedEmail = 0,
CatchAllEmail = 1,
ForwardedEmailAlias = 2,
RandomWord = 3,
}
internal enum ForwardedEmailServiceType
{
None = -1,
AnonAddy = 0,
FirefoxRelay = 1,
SimpleLogin = 2,
DuckDuckGo = 3,
Fastmail = 4,
}
internal enum UsernameEmailType
{
Random = 0,
Website = 1,
}
}
#endregion
// Helpers
private async Task<int> GetLastStateVersionAsync()
@ -612,5 +905,20 @@ namespace Bit.Core.Services
return _liteDbStorageService;
}
}
private async Task MoveToPrefsAsync<T>(string key)
{
var value = await GetValueAsync<T>(Storage.LiteDb, key);
if (value == null)
{
return;
}
if (await GetValueAsync<T>(Storage.Prefs, key) == null)
{
await SetValueAsync(Storage.Prefs, key, value);
}
await RemoveValueAsync(Storage.LiteDb, key);
}
}
}

View File

@ -548,12 +548,12 @@ namespace Bit.Core.Services
public async Task<bool?> GetAutofillTileAddedAsync()
{
return await GetValueAsync<bool?>(Constants.AutofillTileAdded, await GetDefaultStorageOptionsAsync());
return await GetValueAsync<bool?>(Constants.AutofillTileAddedKey, await GetDefaultStorageOptionsAsync());
}
public async Task SetAutofillTileAddedAsync(bool? value)
{
await SetValueAsync(Constants.AutofillTileAdded, value, await GetDefaultStorageOptionsAsync());
await SetValueAsync(Constants.AutofillTileAddedKey, value, await GetDefaultStorageOptionsAsync());
}
public async Task<string> GetEmailAsync(string userId = null)
@ -751,19 +751,19 @@ namespace Bit.Core.Services
reconciledOptions);
}
public async Task<Dictionary<string, Dictionary<string, object>>> GetLocalDataAsync(string userId = null)
public async Task<Dictionary<string, Dictionary<string, object>>> GetCiphersLocalDataAsync(string userId = null)
{
var reconciledOptions = ReconcileOptions(new StorageOptions { UserId = userId },
await GetDefaultStorageOptionsAsync());
return await GetValueAsync<Dictionary<string, Dictionary<string, object>>>(
Constants.LocalDataKey(reconciledOptions.UserId), reconciledOptions);
Constants.CiphersLocalDataKey(reconciledOptions.UserId), reconciledOptions);
}
public async Task SetLocalDataAsync(Dictionary<string, Dictionary<string, object>> value, string userId = null)
public async Task SetCiphersLocalDataAsync(Dictionary<string, Dictionary<string, object>> value, string userId = null)
{
var reconciledOptions = ReconcileOptions(new StorageOptions { UserId = userId },
await GetDefaultStorageOptionsAsync());
await SetValueAsync(Constants.LocalDataKey(reconciledOptions.UserId), value, reconciledOptions);
await SetValueAsync(Constants.CiphersLocalDataKey(reconciledOptions.UserId), value, reconciledOptions);
}
public async Task<Dictionary<string, CipherData>> GetEncryptedCiphersAsync(string userId = null)
@ -795,21 +795,6 @@ namespace Bit.Core.Services
await SetValueAsync(Constants.DefaultUriMatchKey(reconciledOptions.UserId), value, reconciledOptions);
}
public async Task<HashSet<string>> GetNeverDomainsAsync(string userId = null)
{
var reconciledOptions = ReconcileOptions(new StorageOptions { UserId = userId },
await GetDefaultStorageOptionsAsync());
return await GetValueAsync<HashSet<string>>(Constants.NeverDomainsKey(reconciledOptions.UserId),
reconciledOptions);
}
public async Task SetNeverDomainsAsync(HashSet<string> value, string userId = null)
{
var reconciledOptions = ReconcileOptions(new StorageOptions { UserId = userId },
await GetDefaultStorageOptionsAsync());
await SetValueAsync(Constants.NeverDomainsKey(reconciledOptions.UserId), value, reconciledOptions);
}
public async Task<int?> GetClearClipboardAsync(string userId = null)
{
var reconciledOptions = ReconcileOptions(new StorageOptions { UserId = userId },
@ -1542,7 +1527,7 @@ namespace Bit.Core.Services
SetLastActiveTimeAsync(null, userId),
SetPreviousPageInfoAsync(null, userId),
SetInvalidUnlockAttemptsAsync(null, userId),
SetLocalDataAsync(null, userId),
SetCiphersLocalDataAsync(null, userId),
SetEncryptedCiphersAsync(null, userId),
SetEncryptedCollectionsAsync(null, userId),
SetLastSyncAsync(null, userId),