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:
parent
4d0f9d1c03
commit
dbadf8c56f
@ -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());
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -5,6 +5,5 @@ namespace Bit.Core.Abstractions
|
||||
public interface IAppIdService
|
||||
{
|
||||
Task<string> GetAppIdAsync();
|
||||
Task<string> GetAnonymousAppIdAsync();
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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}";
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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),
|
||||
|
Loading…
Reference in New Issue
Block a user