2019-05-30 21:13:02 +03:00
|
|
|
|
using Bit.App.Abstractions;
|
|
|
|
|
using Bit.App.Pages;
|
2019-05-30 06:35:34 +03:00
|
|
|
|
using Bit.App.Resources;
|
2019-05-30 21:13:02 +03:00
|
|
|
|
using Bit.Core;
|
2019-05-30 06:35:34 +03:00
|
|
|
|
using Bit.Core.Abstractions;
|
|
|
|
|
using Bit.Core.Models.View;
|
|
|
|
|
using Bit.Core.Utilities;
|
|
|
|
|
using System.Collections.Generic;
|
2020-02-10 22:07:06 +03:00
|
|
|
|
using System.Linq;
|
2019-05-30 06:35:34 +03:00
|
|
|
|
using System.Threading.Tasks;
|
2020-09-03 19:30:40 +03:00
|
|
|
|
using Bit.App.Models;
|
2019-05-30 06:35:34 +03:00
|
|
|
|
using Xamarin.Forms;
|
|
|
|
|
|
|
|
|
|
namespace Bit.App.Utilities
|
|
|
|
|
{
|
|
|
|
|
public static class AppHelpers
|
|
|
|
|
{
|
|
|
|
|
public static async Task<string> CipherListOptions(ContentPage page, CipherView cipher)
|
|
|
|
|
{
|
|
|
|
|
var platformUtilsService = ServiceContainer.Resolve<IPlatformUtilsService>("platformUtilsService");
|
2019-07-13 00:29:40 +03:00
|
|
|
|
var eventService = ServiceContainer.Resolve<IEventService>("eventService");
|
2020-05-29 19:26:36 +03:00
|
|
|
|
var vaultTimeoutService = ServiceContainer.Resolve<IVaultTimeoutService>("vaultTimeoutService");
|
2020-05-20 20:35:20 +03:00
|
|
|
|
var options = new List<string> { AppResources.View };
|
|
|
|
|
if (!cipher.IsDeleted)
|
|
|
|
|
{
|
|
|
|
|
options.Add(AppResources.Edit);
|
|
|
|
|
}
|
2020-03-28 16:16:28 +03:00
|
|
|
|
if (cipher.Type == Core.Enums.CipherType.Login)
|
2019-05-30 06:35:34 +03:00
|
|
|
|
{
|
2020-03-28 16:16:28 +03:00
|
|
|
|
if (!string.IsNullOrWhiteSpace(cipher.Login.Username))
|
2019-05-30 06:35:34 +03:00
|
|
|
|
{
|
|
|
|
|
options.Add(AppResources.CopyUsername);
|
|
|
|
|
}
|
2020-06-11 23:16:43 +03:00
|
|
|
|
if (!string.IsNullOrWhiteSpace(cipher.Login.Password) && cipher.ViewPassword)
|
2019-05-30 06:35:34 +03:00
|
|
|
|
{
|
|
|
|
|
options.Add(AppResources.CopyPassword);
|
|
|
|
|
}
|
2020-03-28 16:16:28 +03:00
|
|
|
|
if (!string.IsNullOrWhiteSpace(cipher.Login.Totp))
|
2019-05-30 06:35:34 +03:00
|
|
|
|
{
|
2019-06-13 15:44:07 +03:00
|
|
|
|
var userService = ServiceContainer.Resolve<IUserService>("userService");
|
|
|
|
|
var canAccessPremium = await userService.CanAccessPremiumAsync();
|
2020-03-28 16:16:28 +03:00
|
|
|
|
if (canAccessPremium || cipher.OrganizationUseTotp)
|
2019-06-13 15:44:07 +03:00
|
|
|
|
{
|
|
|
|
|
options.Add(AppResources.CopyTotp);
|
|
|
|
|
}
|
2019-05-30 06:35:34 +03:00
|
|
|
|
}
|
2020-03-28 16:16:28 +03:00
|
|
|
|
if (cipher.Login.CanLaunch)
|
2019-05-30 06:35:34 +03:00
|
|
|
|
{
|
|
|
|
|
options.Add(AppResources.Launch);
|
|
|
|
|
}
|
|
|
|
|
}
|
2020-03-28 16:16:28 +03:00
|
|
|
|
else if (cipher.Type == Core.Enums.CipherType.Card)
|
2019-05-30 06:35:34 +03:00
|
|
|
|
{
|
2020-03-28 16:16:28 +03:00
|
|
|
|
if (!string.IsNullOrWhiteSpace(cipher.Card.Number))
|
2019-05-30 06:35:34 +03:00
|
|
|
|
{
|
|
|
|
|
options.Add(AppResources.CopyNumber);
|
|
|
|
|
}
|
2020-03-28 16:16:28 +03:00
|
|
|
|
if (!string.IsNullOrWhiteSpace(cipher.Card.Code))
|
2019-05-30 06:35:34 +03:00
|
|
|
|
{
|
|
|
|
|
options.Add(AppResources.CopySecurityCode);
|
|
|
|
|
}
|
|
|
|
|
}
|
2020-03-28 16:16:28 +03:00
|
|
|
|
else if (cipher.Type == Core.Enums.CipherType.SecureNote)
|
2019-05-30 06:35:34 +03:00
|
|
|
|
{
|
2020-03-28 16:16:28 +03:00
|
|
|
|
if (!string.IsNullOrWhiteSpace(cipher.Notes))
|
2019-05-30 06:35:34 +03:00
|
|
|
|
{
|
|
|
|
|
options.Add(AppResources.CopyNotes);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
var selection = await page.DisplayActionSheet(cipher.Name, AppResources.Cancel, null, options.ToArray());
|
2020-05-29 19:26:36 +03:00
|
|
|
|
if (await vaultTimeoutService.IsLockedAsync())
|
2020-04-28 17:25:13 +03:00
|
|
|
|
{
|
|
|
|
|
platformUtilsService.ShowToast("info", null, AppResources.VaultIsLocked);
|
|
|
|
|
}
|
|
|
|
|
else if (selection == AppResources.View)
|
2019-05-30 06:35:34 +03:00
|
|
|
|
{
|
|
|
|
|
await page.Navigation.PushModalAsync(new NavigationPage(new ViewPage(cipher.Id)));
|
|
|
|
|
}
|
2020-03-28 16:16:28 +03:00
|
|
|
|
else if (selection == AppResources.Edit)
|
2019-05-30 06:35:34 +03:00
|
|
|
|
{
|
|
|
|
|
await page.Navigation.PushModalAsync(new NavigationPage(new AddEditPage(cipher.Id)));
|
|
|
|
|
}
|
2020-03-28 16:16:28 +03:00
|
|
|
|
else if (selection == AppResources.CopyUsername)
|
2019-05-30 06:35:34 +03:00
|
|
|
|
{
|
|
|
|
|
await platformUtilsService.CopyToClipboardAsync(cipher.Login.Username);
|
2019-05-30 16:15:59 +03:00
|
|
|
|
platformUtilsService.ShowToast("info", null,
|
|
|
|
|
string.Format(AppResources.ValueHasBeenCopied, AppResources.Username));
|
2019-05-30 06:35:34 +03:00
|
|
|
|
}
|
2020-03-28 16:16:28 +03:00
|
|
|
|
else if (selection == AppResources.CopyPassword)
|
2019-05-30 06:35:34 +03:00
|
|
|
|
{
|
|
|
|
|
await platformUtilsService.CopyToClipboardAsync(cipher.Login.Password);
|
2019-05-30 16:15:59 +03:00
|
|
|
|
platformUtilsService.ShowToast("info", null,
|
|
|
|
|
string.Format(AppResources.ValueHasBeenCopied, AppResources.Password));
|
2019-07-13 00:29:40 +03:00
|
|
|
|
var task = eventService.CollectAsync(Core.Enums.EventType.Cipher_ClientCopiedPassword, cipher.Id);
|
2019-05-30 06:35:34 +03:00
|
|
|
|
}
|
2020-03-28 16:16:28 +03:00
|
|
|
|
else if (selection == AppResources.CopyTotp)
|
2019-05-30 06:35:34 +03:00
|
|
|
|
{
|
|
|
|
|
var totpService = ServiceContainer.Resolve<ITotpService>("totpService");
|
|
|
|
|
var totp = await totpService.GetCodeAsync(cipher.Login.Totp);
|
2020-03-28 16:16:28 +03:00
|
|
|
|
if (!string.IsNullOrWhiteSpace(totp))
|
2019-05-30 06:35:34 +03:00
|
|
|
|
{
|
|
|
|
|
await platformUtilsService.CopyToClipboardAsync(totp);
|
2019-05-30 16:15:59 +03:00
|
|
|
|
platformUtilsService.ShowToast("info", null,
|
|
|
|
|
string.Format(AppResources.ValueHasBeenCopied, AppResources.VerificationCodeTotp));
|
2019-05-30 06:35:34 +03:00
|
|
|
|
}
|
|
|
|
|
}
|
2020-03-28 16:16:28 +03:00
|
|
|
|
else if (selection == AppResources.Launch)
|
2019-05-30 06:35:34 +03:00
|
|
|
|
{
|
|
|
|
|
platformUtilsService.LaunchUri(cipher.Login.LaunchUri);
|
|
|
|
|
}
|
2020-03-28 16:16:28 +03:00
|
|
|
|
else if (selection == AppResources.CopyNumber)
|
2019-05-30 06:35:34 +03:00
|
|
|
|
{
|
|
|
|
|
await platformUtilsService.CopyToClipboardAsync(cipher.Card.Number);
|
|
|
|
|
platformUtilsService.ShowToast("info", null,
|
|
|
|
|
string.Format(AppResources.ValueHasBeenCopied, AppResources.Number));
|
|
|
|
|
}
|
2020-03-28 16:16:28 +03:00
|
|
|
|
else if (selection == AppResources.CopySecurityCode)
|
2019-05-30 06:35:34 +03:00
|
|
|
|
{
|
|
|
|
|
await platformUtilsService.CopyToClipboardAsync(cipher.Card.Code);
|
|
|
|
|
platformUtilsService.ShowToast("info", null,
|
|
|
|
|
string.Format(AppResources.ValueHasBeenCopied, AppResources.SecurityCode));
|
2019-07-13 00:29:40 +03:00
|
|
|
|
var task = eventService.CollectAsync(Core.Enums.EventType.Cipher_ClientCopiedCardCode, cipher.Id);
|
2019-05-30 06:35:34 +03:00
|
|
|
|
}
|
2020-03-28 16:16:28 +03:00
|
|
|
|
else if (selection == AppResources.CopyNotes)
|
2019-05-30 06:35:34 +03:00
|
|
|
|
{
|
|
|
|
|
await platformUtilsService.CopyToClipboardAsync(cipher.Notes);
|
|
|
|
|
platformUtilsService.ShowToast("info", null,
|
|
|
|
|
string.Format(AppResources.ValueHasBeenCopied, AppResources.Notes));
|
|
|
|
|
}
|
|
|
|
|
return selection;
|
|
|
|
|
}
|
2019-05-30 21:13:02 +03:00
|
|
|
|
|
|
|
|
|
public static async Task<bool> PerformUpdateTasksAsync(ISyncService syncService,
|
|
|
|
|
IDeviceActionService deviceActionService, IStorageService storageService)
|
|
|
|
|
{
|
|
|
|
|
var currentBuild = deviceActionService.GetBuildNumber();
|
|
|
|
|
var lastBuild = await storageService.GetAsync<string>(Constants.LastBuildKey);
|
2020-03-28 16:16:28 +03:00
|
|
|
|
if (lastBuild == null)
|
2019-05-30 21:13:02 +03:00
|
|
|
|
{
|
2019-10-06 04:36:47 +03:00
|
|
|
|
// Installed
|
2020-05-29 19:26:36 +03:00
|
|
|
|
var currentTimeout = await storageService.GetAsync<int?>(Constants.VaultTimeoutKey);
|
|
|
|
|
if (currentTimeout == null)
|
2019-05-30 22:11:22 +03:00
|
|
|
|
{
|
2020-05-29 19:26:36 +03:00
|
|
|
|
await storageService.SaveAsync(Constants.VaultTimeoutKey, 15);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var currentAction = await storageService.GetAsync<string>(Constants.VaultTimeoutActionKey);
|
|
|
|
|
if (currentAction == null)
|
|
|
|
|
{
|
|
|
|
|
await storageService.SaveAsync(Constants.VaultTimeoutActionKey, "lock");
|
2019-05-30 22:11:22 +03:00
|
|
|
|
}
|
2019-05-30 21:13:02 +03:00
|
|
|
|
}
|
2020-03-28 16:16:28 +03:00
|
|
|
|
else if (lastBuild != currentBuild)
|
2019-10-06 04:36:47 +03:00
|
|
|
|
{
|
|
|
|
|
// Updated
|
|
|
|
|
var tasks = Task.Run(() => syncService.FullSyncAsync(true));
|
|
|
|
|
}
|
2020-03-28 16:16:28 +03:00
|
|
|
|
if (lastBuild != currentBuild)
|
2019-05-30 21:13:02 +03:00
|
|
|
|
{
|
|
|
|
|
await storageService.SaveAsync(Constants.LastBuildKey, currentBuild);
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
2020-02-10 22:07:06 +03:00
|
|
|
|
|
|
|
|
|
public static async Task SetPreconfiguredSettingsAsync(IDictionary<string, string> configSettings)
|
|
|
|
|
{
|
2020-03-28 16:16:28 +03:00
|
|
|
|
if (configSettings?.Any() ?? true)
|
2020-02-10 22:07:06 +03:00
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
2020-03-28 16:16:28 +03:00
|
|
|
|
foreach (var setting in configSettings)
|
2020-02-10 22:07:06 +03:00
|
|
|
|
{
|
2020-03-28 16:16:28 +03:00
|
|
|
|
switch (setting.Key)
|
2020-02-10 22:07:06 +03:00
|
|
|
|
{
|
|
|
|
|
case "baseEnvironmentUrl":
|
|
|
|
|
var environmentService = ServiceContainer.Resolve<IEnvironmentService>("environmentService");
|
2020-02-29 08:44:36 +03:00
|
|
|
|
var settingValue = string.IsNullOrWhiteSpace(setting.Value) ? null : setting.Value;
|
2020-03-28 16:16:28 +03:00
|
|
|
|
if (environmentService.BaseUrl != settingValue)
|
2020-02-10 22:07:06 +03:00
|
|
|
|
{
|
|
|
|
|
await environmentService.SetUrlsAsync(new Core.Models.Data.EnvironmentUrlData
|
|
|
|
|
{
|
2020-02-29 08:44:36 +03:00
|
|
|
|
Base = settingValue,
|
2020-02-10 22:07:06 +03:00
|
|
|
|
Api = environmentService.ApiUrl,
|
|
|
|
|
Identity = environmentService.IdentityUrl,
|
|
|
|
|
WebVault = environmentService.WebVaultUrl,
|
|
|
|
|
Icons = environmentService.IconsUrl
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2020-09-03 19:30:40 +03:00
|
|
|
|
|
|
|
|
|
public static bool SetAlternateMainPage(AppOptions appOptions)
|
|
|
|
|
{
|
|
|
|
|
if (appOptions != null)
|
|
|
|
|
{
|
|
|
|
|
if (appOptions.FromAutofillFramework && appOptions.SaveType.HasValue)
|
|
|
|
|
{
|
|
|
|
|
Application.Current.MainPage = new NavigationPage(new AddEditPage(appOptions: appOptions));
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
if (appOptions.Uri != null)
|
|
|
|
|
{
|
|
|
|
|
Application.Current.MainPage = new NavigationPage(new AutofillCiphersPage(appOptions));
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static async Task<PreviousPageInfo> ClearPreviousPage()
|
|
|
|
|
{
|
|
|
|
|
var storageService = ServiceContainer.Resolve<IStorageService>("storageService");
|
|
|
|
|
var previousPage = await storageService.GetAsync<PreviousPageInfo>(Constants.PreviousPageKey);
|
|
|
|
|
if (previousPage != null)
|
|
|
|
|
{
|
|
|
|
|
await storageService.RemoveAsync(Constants.PreviousPageKey);
|
|
|
|
|
}
|
|
|
|
|
return previousPage;
|
|
|
|
|
}
|
2019-05-30 06:35:34 +03:00
|
|
|
|
}
|
|
|
|
|
}
|