mirror of
https://github.com/bitwarden/android.git
synced 2024-12-26 02:48:29 +03:00
[PS-2280] Retain app settings on logout (#2366)
* [PS-2280] Retain app settings on logout * adjustments
This commit is contained in:
parent
44e5682b1d
commit
e7d6783156
8 changed files with 148 additions and 178 deletions
|
@ -502,11 +502,6 @@ namespace Bit.Droid.Services
|
||||||
|
|
||||||
public async Task SetScreenCaptureAllowedAsync()
|
public async Task SetScreenCaptureAllowedAsync()
|
||||||
{
|
{
|
||||||
if (CoreHelpers.ForceScreenCaptureEnabled())
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var activity = CrossCurrentActivity.Current?.Activity;
|
var activity = CrossCurrentActivity.Current?.Activity;
|
||||||
if (await _stateService.GetScreenCaptureAllowedAsync())
|
if (await _stateService.GetScreenCaptureAllowedAsync())
|
||||||
{
|
{
|
||||||
|
|
|
@ -806,11 +806,6 @@ namespace Bit.App.Pages
|
||||||
|
|
||||||
public async Task SetScreenCaptureAllowedAsync()
|
public async Task SetScreenCaptureAllowedAsync()
|
||||||
{
|
{
|
||||||
if (CoreHelpers.ForceScreenCaptureEnabled())
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (!_screenCaptureAllowed
|
if (!_screenCaptureAllowed
|
||||||
|
|
|
@ -73,8 +73,8 @@ namespace Bit.Core.Abstractions
|
||||||
Task SetInvalidUnlockAttemptsAsync(int? value, string userId = null);
|
Task SetInvalidUnlockAttemptsAsync(int? value, string userId = null);
|
||||||
Task<string> GetLastBuildAsync();
|
Task<string> GetLastBuildAsync();
|
||||||
Task SetLastBuildAsync(string value);
|
Task SetLastBuildAsync(string value);
|
||||||
Task<bool?> GetDisableFaviconAsync(string userId = null);
|
Task<bool?> GetDisableFaviconAsync();
|
||||||
Task SetDisableFaviconAsync(bool? value, string userId = null);
|
Task SetDisableFaviconAsync(bool? value);
|
||||||
Task<bool?> GetDisableAutoTotpCopyAsync(string userId = null);
|
Task<bool?> GetDisableAutoTotpCopyAsync(string userId = null);
|
||||||
Task SetDisableAutoTotpCopyAsync(bool? value, string userId = null);
|
Task SetDisableAutoTotpCopyAsync(bool? value, string userId = null);
|
||||||
Task<bool?> GetInlineAutofillEnabledAsync(string userId = null);
|
Task<bool?> GetInlineAutofillEnabledAsync(string userId = null);
|
||||||
|
@ -109,10 +109,10 @@ namespace Bit.Core.Abstractions
|
||||||
Task SetRememberedEmailAsync(string value);
|
Task SetRememberedEmailAsync(string value);
|
||||||
Task<string> GetRememberedOrgIdentifierAsync();
|
Task<string> GetRememberedOrgIdentifierAsync();
|
||||||
Task SetRememberedOrgIdentifierAsync(string value);
|
Task SetRememberedOrgIdentifierAsync(string value);
|
||||||
Task<string> GetThemeAsync(string userId = null);
|
Task<string> GetThemeAsync();
|
||||||
Task SetThemeAsync(string value, string userId = null);
|
Task SetThemeAsync(string value);
|
||||||
Task<string> GetAutoDarkThemeAsync(string userId = null);
|
Task<string> GetAutoDarkThemeAsync();
|
||||||
Task SetAutoDarkThemeAsync(string value, string userId = null);
|
Task SetAutoDarkThemeAsync(string value);
|
||||||
Task<bool?> GetAddSitePromptShownAsync(string userId = null);
|
Task<bool?> GetAddSitePromptShownAsync(string userId = null);
|
||||||
Task SetAddSitePromptShownAsync(bool? value, string userId = null);
|
Task SetAddSitePromptShownAsync(bool? value, string userId = null);
|
||||||
Task<bool?> GetPushInitialPromptShownAsync();
|
Task<bool?> GetPushInitialPromptShownAsync();
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
public static class Constants
|
public static class Constants
|
||||||
{
|
{
|
||||||
public const int MaxAccounts = 5;
|
public const int MaxAccounts = 5;
|
||||||
|
public const int VaultTimeoutDefault = 15;
|
||||||
public const string AndroidAppProtocol = "androidapp://";
|
public const string AndroidAppProtocol = "androidapp://";
|
||||||
public const string iOSAppProtocol = "iosapp://";
|
public const string iOSAppProtocol = "iosapp://";
|
||||||
public const string DefaultUsernameGenerated = "-";
|
public const string DefaultUsernameGenerated = "-";
|
||||||
|
@ -29,6 +30,9 @@
|
||||||
public static string RememberedEmailKey = "rememberedEmail";
|
public static string RememberedEmailKey = "rememberedEmail";
|
||||||
public static string RememberedOrgIdentifierKey = "rememberedOrgIdentifier";
|
public static string RememberedOrgIdentifierKey = "rememberedOrgIdentifier";
|
||||||
public static string PasswordlessLoginNotificationKey = "passwordlessLoginNotificationKey";
|
public static string PasswordlessLoginNotificationKey = "passwordlessLoginNotificationKey";
|
||||||
|
public const string ThemeKey = "theme";
|
||||||
|
public const string AutoDarkThemeKey = "autoDarkTheme";
|
||||||
|
public const string DisableFaviconKey = "disableFavicon";
|
||||||
public const string PasswordlessNotificationId = "26072022";
|
public const string PasswordlessNotificationId = "26072022";
|
||||||
public const string AndroidNotificationChannelId = "general_notification_channel";
|
public const string AndroidNotificationChannelId = "general_notification_channel";
|
||||||
public const string iOSNotificationCategoryId = "dismissableCategory";
|
public const string iOSNotificationCategoryId = "dismissableCategory";
|
||||||
|
@ -65,6 +69,8 @@
|
||||||
iOSShareExtensionClearCiphersCacheKey
|
iOSShareExtensionClearCiphersCacheKey
|
||||||
};
|
};
|
||||||
|
|
||||||
|
public static string VaultTimeoutKey(string userId) => $"vaultTimeout_{userId}";
|
||||||
|
public static string VaultTimeoutActionKey(string userId) => $"vaultTimeoutAction_{userId}";
|
||||||
public static string CiphersKey(string userId) => $"ciphers_{userId}";
|
public static string CiphersKey(string userId) => $"ciphers_{userId}";
|
||||||
public static string FoldersKey(string userId) => $"folders_{userId}";
|
public static string FoldersKey(string userId) => $"folders_{userId}";
|
||||||
public static string CollectionsKey(string userId) => $"collections_{userId}";
|
public static string CollectionsKey(string userId) => $"collections_{userId}";
|
||||||
|
@ -89,10 +95,7 @@
|
||||||
public static string AutofillBlacklistedUrisKey(string userId) => $"autofillBlacklistedUris_{userId}";
|
public static string AutofillBlacklistedUrisKey(string userId) => $"autofillBlacklistedUris_{userId}";
|
||||||
public static string ClearClipboardKey(string userId) => $"clearClipboard_{userId}";
|
public static string ClearClipboardKey(string userId) => $"clearClipboard_{userId}";
|
||||||
public static string SyncOnRefreshKey(string userId) => $"syncOnRefresh_{userId}";
|
public static string SyncOnRefreshKey(string userId) => $"syncOnRefresh_{userId}";
|
||||||
public static string DisableFaviconKey(string userId) => $"disableFavicon_{userId}";
|
|
||||||
public static string DefaultUriMatchKey(string userId) => $"defaultUriMatch_{userId}";
|
public static string DefaultUriMatchKey(string userId) => $"defaultUriMatch_{userId}";
|
||||||
public static string ThemeKey(string userId) => $"theme_{userId}";
|
|
||||||
public static string AutoDarkThemeKey(string userId) => $"autoDarkTheme_{userId}";
|
|
||||||
public static string DisableAutoTotpCopyKey(string userId) => $"disableAutoTotpCopy_{userId}";
|
public static string DisableAutoTotpCopyKey(string userId) => $"disableAutoTotpCopy_{userId}";
|
||||||
public static string PreviousPageKey(string userId) => $"previousPage_{userId}";
|
public static string PreviousPageKey(string userId) => $"previousPage_{userId}";
|
||||||
public static string PasswordRepromptAutofillKey(string userId) => $"passwordRepromptAutofillKey_{userId}";
|
public static string PasswordRepromptAutofillKey(string userId) => $"passwordRepromptAutofillKey_{userId}";
|
||||||
|
@ -107,5 +110,6 @@
|
||||||
public static string PushLastRegistrationDateKey(string userId) => $"pushLastRegistrationDate_{userId}";
|
public static string PushLastRegistrationDateKey(string userId) => $"pushLastRegistrationDate_{userId}";
|
||||||
public static string PushCurrentTokenKey(string userId) => $"pushCurrentToken_{userId}";
|
public static string PushCurrentTokenKey(string userId) => $"pushCurrentToken_{userId}";
|
||||||
public static string ShouldConnectToWatchKey(string userId) => $"shouldConnectToWatch_{userId}";
|
public static string ShouldConnectToWatchKey(string userId) => $"shouldConnectToWatch_{userId}";
|
||||||
|
public static string ScreenCaptureAllowedKey(string userId) => $"screenCaptureAllowed_{userId}";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
using Bit.Core.Enums;
|
using System;
|
||||||
|
using Bit.Core.Enums;
|
||||||
using Bit.Core.Models.Data;
|
using Bit.Core.Models.Data;
|
||||||
|
|
||||||
namespace Bit.Core.Models.Domain
|
namespace Bit.Core.Models.Domain
|
||||||
|
@ -104,9 +105,12 @@ namespace Bit.Core.Models.Domain
|
||||||
}
|
}
|
||||||
|
|
||||||
public EnvironmentUrlData EnvironmentUrls;
|
public EnvironmentUrlData EnvironmentUrls;
|
||||||
|
[Obsolete("Feb 10 2023: VaultTimeout has been deprecated in favor of stored prefs to retain value after logout. It remains here to allow for migration during app upgrade.")]
|
||||||
public int? VaultTimeout;
|
public int? VaultTimeout;
|
||||||
|
[Obsolete("Feb 10 2023: VaultTimeoutAction has been deprecated in favor of stored prefs to retain value after logout. It remains here to allow for migration during app upgrade.")]
|
||||||
public VaultTimeoutAction? VaultTimeoutAction;
|
public VaultTimeoutAction? VaultTimeoutAction;
|
||||||
public bool ScreenCaptureAllowed;
|
[Obsolete("Feb 10 2023: ScreenCaptureAllowed has been deprecated in favor of stored prefs to retain value after logout. It remains here to allow for migration during app upgrade.")]
|
||||||
|
public bool? ScreenCaptureAllowed;
|
||||||
}
|
}
|
||||||
|
|
||||||
public class AccountVolatileData
|
public class AccountVolatileData
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Bit.Core.Abstractions;
|
using Bit.Core.Abstractions;
|
||||||
using Bit.Core.Enums;
|
using Bit.Core.Enums;
|
||||||
|
@ -11,7 +12,7 @@ namespace Bit.Core.Services
|
||||||
{
|
{
|
||||||
public class StateMigrationService : IStateMigrationService
|
public class StateMigrationService : IStateMigrationService
|
||||||
{
|
{
|
||||||
private const int StateVersion = 3;
|
private const int StateVersion = 4;
|
||||||
|
|
||||||
private readonly IStorageService _preferencesStorageService;
|
private readonly IStorageService _preferencesStorageService;
|
||||||
private readonly IStorageService _liteDbStorageService;
|
private readonly IStorageService _liteDbStorageService;
|
||||||
|
@ -54,6 +55,9 @@ namespace Bit.Core.Services
|
||||||
goto case 2;
|
goto case 2;
|
||||||
case 2:
|
case 2:
|
||||||
await MigrateFrom2To3Async();
|
await MigrateFrom2To3Async();
|
||||||
|
goto case 3;
|
||||||
|
case 3:
|
||||||
|
await MigrateFrom3To4Async();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -220,9 +224,9 @@ namespace Bit.Core.Services
|
||||||
await GetValueAsync<List<string>>(Storage.LiteDb, V2Keys.AutofillBlacklistedUrisKey);
|
await GetValueAsync<List<string>>(Storage.LiteDb, V2Keys.AutofillBlacklistedUrisKey);
|
||||||
await SetValueAsync(Storage.LiteDb, Constants.AutofillBlacklistedUrisKey(userId), autofillBlacklistedUris);
|
await SetValueAsync(Storage.LiteDb, Constants.AutofillBlacklistedUrisKey(userId), autofillBlacklistedUris);
|
||||||
var disableFavicon = await GetValueAsync<bool?>(Storage.Prefs, V2Keys.DisableFaviconKey);
|
var disableFavicon = await GetValueAsync<bool?>(Storage.Prefs, V2Keys.DisableFaviconKey);
|
||||||
await SetValueAsync(Storage.LiteDb, Constants.DisableFaviconKey(userId), disableFavicon);
|
await SetValueAsync(Storage.LiteDb, V3Keys.DisableFaviconKey(userId), disableFavicon);
|
||||||
var theme = await GetValueAsync<string>(Storage.Prefs, V2Keys.ThemeKey);
|
var theme = await GetValueAsync<string>(Storage.Prefs, V2Keys.ThemeKey);
|
||||||
await SetValueAsync(Storage.LiteDb, Constants.ThemeKey(userId), theme);
|
await SetValueAsync(Storage.LiteDb, V3Keys.ThemeKey(userId), theme);
|
||||||
var clearClipboard = await GetValueAsync<int?>(Storage.Prefs, V2Keys.ClearClipboardKey);
|
var clearClipboard = await GetValueAsync<int?>(Storage.Prefs, V2Keys.ClearClipboardKey);
|
||||||
await SetValueAsync(Storage.LiteDb, Constants.ClearClipboardKey(userId), clearClipboard);
|
await SetValueAsync(Storage.LiteDb, Constants.ClearClipboardKey(userId), clearClipboard);
|
||||||
var previousPage = await GetValueAsync<PreviousPageInfo>(Storage.LiteDb, V2Keys.PreviousPageKey);
|
var previousPage = await GetValueAsync<PreviousPageInfo>(Storage.LiteDb, V2Keys.PreviousPageKey);
|
||||||
|
@ -314,6 +318,86 @@ namespace Bit.Core.Services
|
||||||
await RemoveValueAsync(Storage.LiteDb, V2Keys.Keys_PassGenHistory);
|
await RemoveValueAsync(Storage.LiteDb, V2Keys.Keys_PassGenHistory);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// v3 to v4 Migration
|
||||||
|
|
||||||
|
private class V3Keys
|
||||||
|
{
|
||||||
|
internal static string ThemeKey(string userId) => $"theme_{userId}";
|
||||||
|
internal static string AutoDarkThemeKey(string userId) => $"autoDarkTheme_{userId}";
|
||||||
|
internal static string DisableFaviconKey(string userId) => $"disableFavicon_{userId}";
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task MigrateFrom3To4Async()
|
||||||
|
{
|
||||||
|
var state = await GetValueAsync<State>(Storage.LiteDb, Constants.StateKey);
|
||||||
|
if (state?.Accounts is null)
|
||||||
|
{
|
||||||
|
// Update stored version
|
||||||
|
await SetLastStateVersionAsync(4);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
string firstUserId = null;
|
||||||
|
|
||||||
|
// move values from state to standalone values in LiteDB
|
||||||
|
foreach (var account in state.Accounts.Where(a => a.Value?.Profile?.UserId != null))
|
||||||
|
{
|
||||||
|
var userId = account.Value.Profile.UserId;
|
||||||
|
if (firstUserId == null)
|
||||||
|
{
|
||||||
|
firstUserId = userId;
|
||||||
|
}
|
||||||
|
var vaultTimeout = account.Value.Settings?.VaultTimeout;
|
||||||
|
await SetValueAsync(Storage.LiteDb, V4Keys.VaultTimeoutKey(userId), vaultTimeout);
|
||||||
|
|
||||||
|
var vaultTimeoutAction = account.Value.Settings?.VaultTimeoutAction;
|
||||||
|
await SetValueAsync(Storage.LiteDb, V4Keys.VaultTimeoutActionKey(userId), vaultTimeoutAction);
|
||||||
|
|
||||||
|
var screenCaptureAllowed = account.Value.Settings?.ScreenCaptureAllowed;
|
||||||
|
await SetValueAsync(Storage.LiteDb, V4Keys.ScreenCaptureAllowedKey(userId), screenCaptureAllowed);
|
||||||
|
}
|
||||||
|
|
||||||
|
// use values from first userId to apply globals
|
||||||
|
if (firstUserId != null)
|
||||||
|
{
|
||||||
|
var theme = await GetValueAsync<int?>(Storage.LiteDb, V3Keys.ThemeKey(firstUserId));
|
||||||
|
await SetValueAsync(Storage.LiteDb, V4Keys.ThemeKey, theme);
|
||||||
|
|
||||||
|
var autoDarkTheme = await GetValueAsync<int?>(Storage.LiteDb, V3Keys.AutoDarkThemeKey(firstUserId));
|
||||||
|
await SetValueAsync(Storage.LiteDb, V4Keys.AutoDarkThemeKey, autoDarkTheme);
|
||||||
|
|
||||||
|
var disableFavicon = await GetValueAsync<bool?>(Storage.LiteDb, V3Keys.DisableFaviconKey(firstUserId));
|
||||||
|
await SetValueAsync(Storage.LiteDb, V4Keys.DisableFaviconKey, disableFavicon);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update stored version
|
||||||
|
await SetLastStateVersionAsync(4);
|
||||||
|
|
||||||
|
// Remove old data
|
||||||
|
foreach (var account in state.Accounts)
|
||||||
|
{
|
||||||
|
var userId = account.Value?.Profile?.UserId;
|
||||||
|
if (userId != null)
|
||||||
|
{
|
||||||
|
await RemoveValueAsync(Storage.LiteDb, V3Keys.ThemeKey(userId));
|
||||||
|
await RemoveValueAsync(Storage.LiteDb, V3Keys.AutoDarkThemeKey(userId));
|
||||||
|
await RemoveValueAsync(Storage.LiteDb, V3Keys.DisableFaviconKey(userId));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Removal of old state data will happen organically as state is rebuilt in app
|
||||||
|
}
|
||||||
|
|
||||||
|
private class V4Keys
|
||||||
|
{
|
||||||
|
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 const string ThemeKey = "theme";
|
||||||
|
internal const string AutoDarkThemeKey = "autoDarkTheme";
|
||||||
|
internal const string DisableFaviconKey = "disableFavicon";
|
||||||
|
}
|
||||||
|
|
||||||
// Helpers
|
// Helpers
|
||||||
|
|
||||||
private async Task<int> GetLastStateVersionAsync()
|
private async Task<int> GetLastStateVersionAsync()
|
||||||
|
|
|
@ -539,55 +539,50 @@ namespace Bit.Core.Services
|
||||||
|
|
||||||
public async Task<int?> GetVaultTimeoutAsync(string userId = null)
|
public async Task<int?> GetVaultTimeoutAsync(string userId = null)
|
||||||
{
|
{
|
||||||
return (await GetAccountAsync(
|
var reconciledOptions = ReconcileOptions(new StorageOptions { UserId = userId },
|
||||||
ReconcileOptions(new StorageOptions { UserId = userId }, await GetDefaultStorageOptionsAsync())
|
await GetDefaultStorageOptionsAsync());
|
||||||
))?.Settings?.VaultTimeout;
|
var key = Constants.VaultTimeoutKey(reconciledOptions.UserId);
|
||||||
|
return await GetValueAsync<int?>(key, reconciledOptions) ?? Constants.VaultTimeoutDefault;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task SetVaultTimeoutAsync(int? value, string userId = null)
|
public async Task SetVaultTimeoutAsync(int? value, string userId = null)
|
||||||
{
|
{
|
||||||
var reconciledOptions = ReconcileOptions(new StorageOptions { UserId = userId },
|
var reconciledOptions = ReconcileOptions(new StorageOptions { UserId = userId },
|
||||||
await GetDefaultStorageOptionsAsync());
|
await GetDefaultStorageOptionsAsync());
|
||||||
var account = await GetAccountAsync(reconciledOptions);
|
var key = Constants.VaultTimeoutKey(reconciledOptions.UserId);
|
||||||
account.Settings.VaultTimeout = value;
|
await SetValueAsync(key, value, reconciledOptions);
|
||||||
await SaveAccountAsync(account, reconciledOptions);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<VaultTimeoutAction?> GetVaultTimeoutActionAsync(string userId = null)
|
public async Task<VaultTimeoutAction?> GetVaultTimeoutActionAsync(string userId = null)
|
||||||
{
|
{
|
||||||
return (await GetAccountAsync(
|
var reconciledOptions = ReconcileOptions(new StorageOptions { UserId = userId },
|
||||||
ReconcileOptions(new StorageOptions { UserId = userId }, await GetDefaultStorageOptionsAsync())
|
await GetDefaultStorageOptionsAsync());
|
||||||
))?.Settings?.VaultTimeoutAction;
|
var key = Constants.VaultTimeoutActionKey(reconciledOptions.UserId);
|
||||||
|
return await GetValueAsync<VaultTimeoutAction?>(key, reconciledOptions) ?? VaultTimeoutAction.Lock;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task SetVaultTimeoutActionAsync(VaultTimeoutAction? value, string userId = null)
|
public async Task SetVaultTimeoutActionAsync(VaultTimeoutAction? value, string userId = null)
|
||||||
{
|
{
|
||||||
var reconciledOptions = ReconcileOptions(new StorageOptions { UserId = userId },
|
var reconciledOptions = ReconcileOptions(new StorageOptions { UserId = userId },
|
||||||
await GetDefaultStorageOptionsAsync());
|
await GetDefaultStorageOptionsAsync());
|
||||||
var account = await GetAccountAsync(reconciledOptions);
|
var key = Constants.VaultTimeoutActionKey(reconciledOptions.UserId);
|
||||||
account.Settings.VaultTimeoutAction = value;
|
await SetValueAsync(key, value, reconciledOptions);
|
||||||
await SaveAccountAsync(account, reconciledOptions);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<bool> GetScreenCaptureAllowedAsync(string userId = null)
|
public async Task<bool> GetScreenCaptureAllowedAsync(string userId = null)
|
||||||
{
|
{
|
||||||
if (CoreHelpers.ForceScreenCaptureEnabled())
|
var reconciledOptions = ReconcileOptions(new StorageOptions { UserId = userId },
|
||||||
{
|
await GetDefaultStorageOptionsAsync());
|
||||||
return true;
|
var key = Constants.ScreenCaptureAllowedKey(reconciledOptions.UserId);
|
||||||
}
|
return await GetValueAsync<bool?>(key, reconciledOptions) ?? CoreHelpers.InDebugMode();
|
||||||
|
|
||||||
return (await GetAccountAsync(
|
|
||||||
ReconcileOptions(new StorageOptions { UserId = userId }, await GetDefaultStorageOptionsAsync())
|
|
||||||
))?.Settings?.ScreenCaptureAllowed ?? false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task SetScreenCaptureAllowedAsync(bool value, string userId = null)
|
public async Task SetScreenCaptureAllowedAsync(bool value, string userId = null)
|
||||||
{
|
{
|
||||||
var reconciledOptions = ReconcileOptions(new StorageOptions { UserId = userId },
|
var reconciledOptions = ReconcileOptions(new StorageOptions { UserId = userId },
|
||||||
await GetDefaultStorageOptionsAsync());
|
await GetDefaultStorageOptionsAsync());
|
||||||
var account = await GetAccountAsync(reconciledOptions);
|
var key = Constants.ScreenCaptureAllowedKey(reconciledOptions.UserId);
|
||||||
account.Settings.ScreenCaptureAllowed = value;
|
await SetValueAsync(key, value, reconciledOptions);
|
||||||
await SaveAccountAsync(account, reconciledOptions);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<DateTime?> GetLastFileCacheClearAsync()
|
public async Task<DateTime?> GetLastFileCacheClearAsync()
|
||||||
|
@ -650,23 +645,18 @@ namespace Bit.Core.Services
|
||||||
await SetValueAsync(key, value, options);
|
await SetValueAsync(key, value, options);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<bool?> GetDisableFaviconAsync(string userId = null)
|
public async Task<bool?> GetDisableFaviconAsync()
|
||||||
{
|
{
|
||||||
var reconciledOptions = ReconcileOptions(new StorageOptions { UserId = userId },
|
var options = await GetDefaultStorageOptionsAsync();
|
||||||
await GetDefaultStorageOptionsAsync());
|
var key = Constants.DisableFaviconKey;
|
||||||
var key = Constants.DisableFaviconKey(reconciledOptions.UserId);
|
return await GetValueAsync<bool?>(key, options);
|
||||||
return await GetValueAsync<bool?>(key, reconciledOptions);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task SetDisableFaviconAsync(bool? value, string userId = null)
|
public async Task SetDisableFaviconAsync(bool? value)
|
||||||
{
|
{
|
||||||
var reconciledOptions = ReconcileOptions(new StorageOptions { UserId = userId },
|
var options = await GetDefaultStorageOptionsAsync();
|
||||||
await GetDefaultStorageOptionsAsync());
|
var key = Constants.DisableFaviconKey;
|
||||||
var key = Constants.DisableFaviconKey(reconciledOptions.UserId);
|
await SetValueAsync(key, value, options);
|
||||||
await SetValueAsync(key, value, reconciledOptions);
|
|
||||||
|
|
||||||
// TODO remove this to restore per-account DisableFavicon support
|
|
||||||
SetValueGloballyAsync(Constants.DisableFaviconKey, value, reconciledOptions).FireAndForget();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<bool?> GetDisableAutoTotpCopyAsync(string userId = null)
|
public async Task<bool?> GetDisableAutoTotpCopyAsync(string userId = null)
|
||||||
|
@ -937,42 +927,32 @@ namespace Bit.Core.Services
|
||||||
await SetValueAsync(key, value, options);
|
await SetValueAsync(key, value, options);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<string> GetThemeAsync(string userId = null)
|
public async Task<string> GetThemeAsync()
|
||||||
{
|
{
|
||||||
var reconciledOptions = ReconcileOptions(new StorageOptions { UserId = userId },
|
var options = await GetDefaultStorageOptionsAsync();
|
||||||
await GetDefaultStorageOptionsAsync());
|
var key = Constants.ThemeKey;
|
||||||
var key = Constants.ThemeKey(reconciledOptions.UserId);
|
return await GetValueAsync<string>(key, options);
|
||||||
return await GetValueAsync<string>(key, reconciledOptions);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task SetThemeAsync(string value, string userId = null)
|
public async Task SetThemeAsync(string value)
|
||||||
{
|
{
|
||||||
var reconciledOptions = ReconcileOptions(new StorageOptions { UserId = userId },
|
var options = await GetDefaultStorageOptionsAsync();
|
||||||
await GetDefaultStorageOptionsAsync());
|
var key = Constants.ThemeKey;
|
||||||
var key = Constants.ThemeKey(reconciledOptions.UserId);
|
await SetValueAsync(key, value, options);
|
||||||
await SetValueAsync(key, value, reconciledOptions);
|
|
||||||
|
|
||||||
// TODO remove this to restore per-account Theme support
|
|
||||||
SetValueGloballyAsync(Constants.ThemeKey, value, reconciledOptions).FireAndForget();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<string> GetAutoDarkThemeAsync(string userId = null)
|
public async Task<string> GetAutoDarkThemeAsync()
|
||||||
{
|
{
|
||||||
var reconciledOptions = ReconcileOptions(new StorageOptions { UserId = userId },
|
var options = await GetDefaultStorageOptionsAsync();
|
||||||
await GetDefaultStorageOptionsAsync());
|
var key = Constants.AutoDarkThemeKey;
|
||||||
var key = Constants.AutoDarkThemeKey(reconciledOptions.UserId);
|
return await GetValueAsync<string>(key, options);
|
||||||
return await GetValueAsync<string>(key, reconciledOptions);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task SetAutoDarkThemeAsync(string value, string userId = null)
|
public async Task SetAutoDarkThemeAsync(string value)
|
||||||
{
|
{
|
||||||
var reconciledOptions = ReconcileOptions(new StorageOptions { UserId = userId },
|
var options = await GetDefaultStorageOptionsAsync();
|
||||||
await GetDefaultStorageOptionsAsync());
|
var key = Constants.AutoDarkThemeKey;
|
||||||
var key = Constants.AutoDarkThemeKey(reconciledOptions.UserId);
|
await SetValueAsync(key, value, options);
|
||||||
await SetValueAsync(key, value, reconciledOptions);
|
|
||||||
|
|
||||||
// TODO remove this to restore per-account Theme support
|
|
||||||
SetValueGloballyAsync(Constants.AutoDarkThemeKey, value, reconciledOptions).FireAndForget();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<bool?> GetAddSitePromptShownAsync(string userId = null)
|
public async Task<bool?> GetAddSitePromptShownAsync(string userId = null)
|
||||||
|
@ -1333,30 +1313,6 @@ namespace Bit.Core.Services
|
||||||
await GetStorageService(options).SaveAsync(key, value);
|
await GetStorageService(options).SaveAsync(key, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task SetValueGloballyAsync<T>(Func<string, string> keyPrefix, T value, StorageOptions options)
|
|
||||||
{
|
|
||||||
if (value == null)
|
|
||||||
{
|
|
||||||
// don't remove values globally
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
await CheckStateAsync();
|
|
||||||
if (_state?.Accounts == null)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// userId from options was already applied, skip those
|
|
||||||
var userIdToSkip = options.UserId;
|
|
||||||
foreach (var account in _state.Accounts)
|
|
||||||
{
|
|
||||||
var uid = account.Value?.Profile?.UserId;
|
|
||||||
if (uid != null && uid != userIdToSkip)
|
|
||||||
{
|
|
||||||
await SetValueAsync(keyPrefix(uid), value, options);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private IStorageService GetStorageService(StorageOptions options)
|
private IStorageService GetStorageService(StorageOptions options)
|
||||||
{
|
{
|
||||||
return options.UseSecureStorage.GetValueOrDefault(false) ? _secureStorageService : _storageService;
|
return options.UseSecureStorage.GetValueOrDefault(false) ? _secureStorageService : _storageService;
|
||||||
|
@ -1489,7 +1445,6 @@ namespace Bit.Core.Services
|
||||||
}
|
}
|
||||||
|
|
||||||
// Non-state storage
|
// Non-state storage
|
||||||
await SetBiometricUnlockAsync(null, userId);
|
|
||||||
await SetProtectedPinAsync(null, userId);
|
await SetProtectedPinAsync(null, userId);
|
||||||
await SetPinProtectedAsync(null, userId);
|
await SetPinProtectedAsync(null, userId);
|
||||||
await SetKeyEncryptedAsync(null, userId);
|
await SetKeyEncryptedAsync(null, userId);
|
||||||
|
@ -1511,37 +1466,11 @@ namespace Bit.Core.Services
|
||||||
await SetEncryptedPasswordGenerationHistoryAsync(null, userId);
|
await SetEncryptedPasswordGenerationHistoryAsync(null, userId);
|
||||||
await SetEncryptedSendsAsync(null, userId);
|
await SetEncryptedSendsAsync(null, userId);
|
||||||
await SetSettingsAsync(null, userId);
|
await SetSettingsAsync(null, userId);
|
||||||
await SetApprovePasswordlessLoginsAsync(null, userId);
|
|
||||||
|
|
||||||
if (userInitiated)
|
|
||||||
{
|
|
||||||
// user initiated logout (not vault timeout or scaffolding new account) so remove remaining settings
|
|
||||||
await SetAutofillBlacklistedUrisAsync(null, userId);
|
|
||||||
await SetDisableFaviconAsync(null, userId);
|
|
||||||
await SetDisableAutoTotpCopyAsync(null, userId);
|
|
||||||
await SetInlineAutofillEnabledAsync(null, userId);
|
|
||||||
await SetAutofillDisableSavePromptAsync(null, userId);
|
|
||||||
await SetDefaultUriMatchAsync(null, userId);
|
|
||||||
await SetNeverDomainsAsync(null, userId);
|
|
||||||
await SetClearClipboardAsync(null, userId);
|
|
||||||
await SetPasswordRepromptAutofillAsync(null, userId);
|
|
||||||
await SetPasswordVerifiedAutofillAsync(null, userId);
|
|
||||||
await SetSyncOnRefreshAsync(null, userId);
|
|
||||||
await SetThemeAsync(null, userId);
|
|
||||||
await SetAutoDarkThemeAsync(null, userId);
|
|
||||||
await SetAddSitePromptShownAsync(null, userId);
|
|
||||||
await SetPasswordGenerationOptionsAsync(null, userId);
|
|
||||||
await SetApprovePasswordlessLoginsAsync(null, userId);
|
|
||||||
await SetUsernameGenerationOptionsAsync(null, userId);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task ScaffoldNewAccountAsync(Account account)
|
private async Task ScaffoldNewAccountAsync(Account account)
|
||||||
{
|
{
|
||||||
await CheckStateAsync();
|
await CheckStateAsync();
|
||||||
var currentTheme = await GetThemeAsync();
|
|
||||||
var currentAutoDarkTheme = await GetAutoDarkThemeAsync();
|
|
||||||
var currentDisableFavicons = await GetDisableFaviconAsync();
|
|
||||||
|
|
||||||
account.Settings.EnvironmentUrls = await GetPreAuthEnvironmentUrlsAsync();
|
account.Settings.EnvironmentUrls = await GetPreAuthEnvironmentUrlsAsync();
|
||||||
|
|
||||||
|
@ -1551,28 +1480,6 @@ namespace Bit.Core.Services
|
||||||
{
|
{
|
||||||
state.Accounts = new Dictionary<string, Account>();
|
state.Accounts = new Dictionary<string, Account>();
|
||||||
}
|
}
|
||||||
if (state.Accounts.ContainsKey(account.Profile.UserId))
|
|
||||||
{
|
|
||||||
// Run cleanup pass on existing account before proceeding
|
|
||||||
await RemoveAccountAsync(account.Profile.UserId, false);
|
|
||||||
var existingAccount = state.Accounts[account.Profile.UserId];
|
|
||||||
account.Settings.VaultTimeout = existingAccount.Settings.VaultTimeout;
|
|
||||||
account.Settings.VaultTimeoutAction = existingAccount.Settings.VaultTimeoutAction;
|
|
||||||
account.Settings.ScreenCaptureAllowed = existingAccount.Settings.ScreenCaptureAllowed;
|
|
||||||
}
|
|
||||||
|
|
||||||
// New account defaults
|
|
||||||
if (account.Settings.VaultTimeout == null)
|
|
||||||
{
|
|
||||||
account.Settings.VaultTimeout = 15;
|
|
||||||
}
|
|
||||||
if (account.Settings.VaultTimeoutAction == null)
|
|
||||||
{
|
|
||||||
account.Settings.VaultTimeoutAction = VaultTimeoutAction.Lock;
|
|
||||||
}
|
|
||||||
await SetThemeAsync(currentTheme, account.Profile.UserId);
|
|
||||||
await SetAutoDarkThemeAsync(currentAutoDarkTheme, account.Profile.UserId);
|
|
||||||
await SetDisableFaviconAsync(currentDisableFavicons, account.Profile.UserId);
|
|
||||||
|
|
||||||
state.Accounts[account.Profile.UserId] = account;
|
state.Accounts[account.Profile.UserId] = account;
|
||||||
await SaveStateToStorageAsync(state);
|
await SaveStateToStorageAsync(state);
|
||||||
|
|
|
@ -37,25 +37,6 @@ namespace Bit.Core.Utilities
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Returns whether to force enabling the screen capture.
|
|
||||||
/// On Debug it will allow screen capture by default but this method
|
|
||||||
/// makes it easier to test the change on enabling/disabling the feature
|
|
||||||
/// on debug.
|
|
||||||
/// </summary>
|
|
||||||
/// <remarks>
|
|
||||||
/// To test enabling/disabling in DEBUG, just return <c>false</c> in the #if condition
|
|
||||||
/// and that's it.
|
|
||||||
/// </remarks>
|
|
||||||
public static bool ForceScreenCaptureEnabled()
|
|
||||||
{
|
|
||||||
#if DEBUG
|
|
||||||
return true;
|
|
||||||
#else
|
|
||||||
return false;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
public static string GetHostname(string uriString)
|
public static string GetHostname(string uriString)
|
||||||
{
|
{
|
||||||
var uri = GetUri(uriString);
|
var uri = GetUri(uriString);
|
||||||
|
|
Loading…
Reference in a new issue