2021-02-11 03:50:10 +03:00
|
|
|
|
using System;
|
2019-05-30 06:35:34 +03:00
|
|
|
|
using System.Collections.Generic;
|
2020-02-10 22:07:06 +03:00
|
|
|
|
using System.Linq;
|
2022-03-02 20:32:43 +03:00
|
|
|
|
using System.Net;
|
2021-08-30 19:44:12 +03:00
|
|
|
|
using System.Text;
|
|
|
|
|
using System.Text.RegularExpressions;
|
2019-05-30 06:35:34 +03:00
|
|
|
|
using System.Threading.Tasks;
|
2021-02-11 03:50:10 +03:00
|
|
|
|
using Bit.App.Abstractions;
|
2022-03-07 20:28:06 +03:00
|
|
|
|
using Bit.App.Controls;
|
2020-09-03 19:30:40 +03:00
|
|
|
|
using Bit.App.Models;
|
2019-05-30 21:13:02 +03:00
|
|
|
|
using Bit.App.Pages;
|
2019-05-30 06:35:34 +03:00
|
|
|
|
using Bit.App.Resources;
|
|
|
|
|
using Bit.Core.Abstractions;
|
2021-02-19 00:58:20 +03:00
|
|
|
|
using Bit.Core.Enums;
|
2021-02-11 03:50:10 +03:00
|
|
|
|
using Bit.Core.Exceptions;
|
2022-02-23 20:40:17 +03:00
|
|
|
|
using Bit.Core.Models.Data;
|
2019-05-30 06:35:34 +03:00
|
|
|
|
using Bit.Core.Models.View;
|
|
|
|
|
using Bit.Core.Utilities;
|
2021-08-30 19:44:12 +03:00
|
|
|
|
using Newtonsoft.Json;
|
2021-02-11 03:50:10 +03:00
|
|
|
|
using Xamarin.Essentials;
|
2019-05-30 06:35:34 +03:00
|
|
|
|
using Xamarin.Forms;
|
|
|
|
|
|
|
|
|
|
namespace Bit.App.Utilities
|
|
|
|
|
{
|
|
|
|
|
public static class AppHelpers
|
|
|
|
|
{
|
2021-05-21 16:13:54 +03:00
|
|
|
|
public static async Task<string> CipherListOptions(ContentPage page, CipherView cipher, IPasswordRepromptService passwordRepromptService)
|
2019-05-30 06:35:34 +03:00
|
|
|
|
{
|
|
|
|
|
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");
|
2021-12-10 23:41:36 +03:00
|
|
|
|
var clipboardService = ServiceContainer.Resolve<IClipboardService>("clipboardService");
|
|
|
|
|
|
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
|
|
|
|
{
|
2022-02-23 20:40:17 +03:00
|
|
|
|
var stateService = ServiceContainer.Resolve<IStateService>("stateService");
|
|
|
|
|
var canAccessPremium = await stateService.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
|
|
|
|
{
|
2021-06-10 18:57:18 +03:00
|
|
|
|
if (cipher.Reprompt == CipherRepromptType.None || await passwordRepromptService.ShowPasswordPromptAsync())
|
|
|
|
|
{
|
|
|
|
|
await page.Navigation.PushModalAsync(new NavigationPage(new AddEditPage(cipher.Id)));
|
|
|
|
|
}
|
2019-05-30 06:35:34 +03:00
|
|
|
|
}
|
2020-03-28 16:16:28 +03:00
|
|
|
|
else if (selection == AppResources.CopyUsername)
|
2019-05-30 06:35:34 +03:00
|
|
|
|
{
|
2021-12-10 23:41:36 +03:00
|
|
|
|
await clipboardService.CopyTextAsync(cipher.Login.Username);
|
2022-06-10 19:02:17 +03:00
|
|
|
|
platformUtilsService.ShowToastForCopiedValue(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
|
|
|
|
{
|
2021-05-21 16:13:54 +03:00
|
|
|
|
if (cipher.Reprompt == CipherRepromptType.None || await passwordRepromptService.ShowPasswordPromptAsync())
|
|
|
|
|
{
|
2021-12-10 23:41:36 +03:00
|
|
|
|
await clipboardService.CopyTextAsync(cipher.Login.Password);
|
2022-06-10 19:02:17 +03:00
|
|
|
|
platformUtilsService.ShowToastForCopiedValue(AppResources.Password);
|
2021-05-21 16:13:54 +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
|
|
|
|
{
|
2021-05-21 16:13:54 +03:00
|
|
|
|
if (cipher.Reprompt == CipherRepromptType.None || await passwordRepromptService.ShowPasswordPromptAsync())
|
2019-05-30 06:35:34 +03:00
|
|
|
|
{
|
2021-05-21 16:13:54 +03:00
|
|
|
|
var totpService = ServiceContainer.Resolve<ITotpService>("totpService");
|
|
|
|
|
var totp = await totpService.GetCodeAsync(cipher.Login.Totp);
|
|
|
|
|
if (!string.IsNullOrWhiteSpace(totp))
|
|
|
|
|
{
|
2021-12-10 23:41:36 +03:00
|
|
|
|
await clipboardService.CopyTextAsync(totp);
|
2022-06-10 19:02:17 +03:00
|
|
|
|
platformUtilsService.ShowToastForCopiedValue(AppResources.VerificationCodeTotp);
|
2021-05-21 16:13:54 +03:00
|
|
|
|
}
|
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
|
|
|
|
{
|
2021-05-21 16:13:54 +03:00
|
|
|
|
if (cipher.Reprompt == CipherRepromptType.None || await passwordRepromptService.ShowPasswordPromptAsync())
|
|
|
|
|
{
|
2021-12-10 23:41:36 +03:00
|
|
|
|
await clipboardService.CopyTextAsync(cipher.Card.Number);
|
2022-06-10 19:02:17 +03:00
|
|
|
|
platformUtilsService.ShowToastForCopiedValue(AppResources.Number);
|
2021-05-21 16:13:54 +03:00
|
|
|
|
}
|
2019-05-30 06:35:34 +03:00
|
|
|
|
}
|
2020-03-28 16:16:28 +03:00
|
|
|
|
else if (selection == AppResources.CopySecurityCode)
|
2019-05-30 06:35:34 +03:00
|
|
|
|
{
|
2021-05-21 16:13:54 +03:00
|
|
|
|
if (cipher.Reprompt == CipherRepromptType.None || await passwordRepromptService.ShowPasswordPromptAsync())
|
|
|
|
|
{
|
2021-12-10 23:41:36 +03:00
|
|
|
|
await clipboardService.CopyTextAsync(cipher.Card.Code);
|
2022-06-10 19:02:17 +03:00
|
|
|
|
platformUtilsService.ShowToastForCopiedValue(AppResources.SecurityCode);
|
2021-05-21 16:13:54 +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
|
|
|
|
{
|
2021-12-10 23:41:36 +03:00
|
|
|
|
await clipboardService.CopyTextAsync(cipher.Notes);
|
2022-06-10 19:02:17 +03:00
|
|
|
|
platformUtilsService.ShowToastForCopiedValue(AppResources.Notes);
|
2019-05-30 06:35:34 +03:00
|
|
|
|
}
|
|
|
|
|
return selection;
|
|
|
|
|
}
|
2019-05-30 21:13:02 +03:00
|
|
|
|
|
2021-02-11 03:50:10 +03:00
|
|
|
|
public static async Task<string> SendListOptions(ContentPage page, SendView send)
|
|
|
|
|
{
|
|
|
|
|
var platformUtilsService = ServiceContainer.Resolve<IPlatformUtilsService>("platformUtilsService");
|
|
|
|
|
var vaultTimeoutService = ServiceContainer.Resolve<IVaultTimeoutService>("vaultTimeoutService");
|
|
|
|
|
var options = new List<string> { AppResources.Edit };
|
|
|
|
|
options.Add(AppResources.CopyLink);
|
|
|
|
|
options.Add(AppResources.ShareLink);
|
|
|
|
|
if (send.HasPassword)
|
|
|
|
|
{
|
|
|
|
|
options.Add(AppResources.RemovePassword);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var selection = await page.DisplayActionSheet(send.Name, AppResources.Cancel, AppResources.Delete,
|
|
|
|
|
options.ToArray());
|
|
|
|
|
if (await vaultTimeoutService.IsLockedAsync())
|
|
|
|
|
{
|
|
|
|
|
platformUtilsService.ShowToast("info", null, AppResources.VaultIsLocked);
|
|
|
|
|
}
|
|
|
|
|
else if (selection == AppResources.Edit)
|
|
|
|
|
{
|
2021-03-31 17:19:05 +03:00
|
|
|
|
await page.Navigation.PushModalAsync(new NavigationPage(new SendAddEditPage(null, send.Id)));
|
2021-02-11 03:50:10 +03:00
|
|
|
|
}
|
|
|
|
|
else if (selection == AppResources.CopyLink)
|
|
|
|
|
{
|
2021-02-19 00:58:20 +03:00
|
|
|
|
await CopySendUrlAsync(send);
|
2021-02-11 03:50:10 +03:00
|
|
|
|
}
|
|
|
|
|
else if (selection == AppResources.ShareLink)
|
|
|
|
|
{
|
2021-02-19 00:58:20 +03:00
|
|
|
|
await ShareSendUrlAsync(send);
|
2021-02-11 03:50:10 +03:00
|
|
|
|
}
|
|
|
|
|
else if (selection == AppResources.RemovePassword)
|
|
|
|
|
{
|
|
|
|
|
await RemoveSendPasswordAsync(send.Id);
|
|
|
|
|
}
|
|
|
|
|
else if (selection == AppResources.Delete)
|
|
|
|
|
{
|
|
|
|
|
await DeleteSendAsync(send.Id);
|
|
|
|
|
}
|
|
|
|
|
return selection;
|
|
|
|
|
}
|
|
|
|
|
|
2022-03-07 20:28:06 +03:00
|
|
|
|
public static async Task<string> AccountListOptions(ContentPage page, AccountViewCellViewModel accountViewCell)
|
|
|
|
|
{
|
|
|
|
|
var vaultTimeoutService = ServiceContainer.Resolve<IVaultTimeoutService>("vaultTimeoutService");
|
|
|
|
|
var platformUtilsService = ServiceContainer.Resolve<IPlatformUtilsService>("platformUtilsService");
|
|
|
|
|
|
|
|
|
|
var userId = accountViewCell.AccountView.UserId;
|
|
|
|
|
|
|
|
|
|
List<string> options;
|
|
|
|
|
if (await vaultTimeoutService.IsLoggedOutByTimeoutAsync(userId) ||
|
|
|
|
|
await vaultTimeoutService.ShouldLogOutByTimeoutAsync(userId))
|
|
|
|
|
{
|
|
|
|
|
options = new List<string> { AppResources.RemoveAccount };
|
|
|
|
|
}
|
|
|
|
|
else if (await vaultTimeoutService.IsLockedAsync(userId) ||
|
|
|
|
|
await vaultTimeoutService.ShouldLockAsync(userId))
|
|
|
|
|
{
|
|
|
|
|
options = new List<string> { AppResources.LogOut };
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
options = new List<string> { AppResources.Lock, AppResources.LogOut };
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var accountSummary = accountViewCell.AccountView.Email;
|
|
|
|
|
if (!string.IsNullOrWhiteSpace(accountViewCell.AccountView.Hostname))
|
|
|
|
|
{
|
|
|
|
|
accountSummary += "\n" + accountViewCell.AccountView.Hostname;
|
|
|
|
|
}
|
|
|
|
|
var selection = await page.DisplayActionSheet(accountSummary, AppResources.Cancel, null, options.ToArray());
|
|
|
|
|
|
|
|
|
|
if (selection == AppResources.Lock)
|
|
|
|
|
{
|
|
|
|
|
await vaultTimeoutService.LockAsync(true, true, userId);
|
|
|
|
|
}
|
|
|
|
|
else if (selection == AppResources.LogOut || selection == AppResources.RemoveAccount)
|
|
|
|
|
{
|
|
|
|
|
var title = selection == AppResources.LogOut ? AppResources.LogOut : AppResources.RemoveAccount;
|
|
|
|
|
var text = (selection == AppResources.LogOut ? AppResources.LogoutConfirmation
|
|
|
|
|
: AppResources.RemoveAccountConfirmation) + "\n\n" + accountSummary;
|
|
|
|
|
var confirmed =
|
|
|
|
|
await platformUtilsService.ShowDialogAsync(text, title, AppResources.Yes, AppResources.Cancel);
|
|
|
|
|
if (confirmed)
|
|
|
|
|
{
|
2022-03-07 23:15:21 +03:00
|
|
|
|
var stateService = ServiceContainer.Resolve<IStateService>("stateService");
|
|
|
|
|
if (await stateService.IsActiveAccountAsync(userId))
|
|
|
|
|
{
|
|
|
|
|
var messagingService = ServiceContainer.Resolve<IMessagingService>("messagingService");
|
|
|
|
|
messagingService.Send("logout");
|
|
|
|
|
return selection;
|
|
|
|
|
}
|
2022-03-07 20:28:06 +03:00
|
|
|
|
await LogOutAsync(userId, true);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return selection;
|
|
|
|
|
}
|
|
|
|
|
|
2021-02-19 00:58:20 +03:00
|
|
|
|
public static async Task CopySendUrlAsync(SendView send)
|
2021-02-11 03:50:10 +03:00
|
|
|
|
{
|
2021-02-19 00:58:20 +03:00
|
|
|
|
if (await IsSendDisabledByPolicyAsync())
|
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
var platformUtilsService = ServiceContainer.Resolve<IPlatformUtilsService>("platformUtilsService");
|
2021-12-10 23:41:36 +03:00
|
|
|
|
var clipboardService = ServiceContainer.Resolve<IClipboardService>("clipboardService");
|
|
|
|
|
await clipboardService.CopyTextAsync(GetSendUrl(send));
|
2022-06-10 19:02:17 +03:00
|
|
|
|
platformUtilsService.ShowToastForCopiedValue(AppResources.SendLink);
|
2021-02-11 03:50:10 +03:00
|
|
|
|
}
|
|
|
|
|
|
2021-02-19 00:58:20 +03:00
|
|
|
|
public static async Task ShareSendUrlAsync(SendView send)
|
2021-02-11 03:50:10 +03:00
|
|
|
|
{
|
2021-02-19 00:58:20 +03:00
|
|
|
|
if (await IsSendDisabledByPolicyAsync())
|
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
2021-02-11 03:50:10 +03:00
|
|
|
|
await Share.RequestAsync(new ShareTextRequest
|
|
|
|
|
{
|
|
|
|
|
Uri = new Uri(GetSendUrl(send)).ToString(),
|
|
|
|
|
Title = AppResources.Send + " " + send.Name,
|
|
|
|
|
Subject = send.Name
|
|
|
|
|
});
|
|
|
|
|
}
|
2022-04-26 18:21:17 +03:00
|
|
|
|
|
2021-02-19 00:58:20 +03:00
|
|
|
|
private static string GetSendUrl(SendView send)
|
|
|
|
|
{
|
|
|
|
|
var environmentService = ServiceContainer.Resolve<IEnvironmentService>("environmentService");
|
2022-02-24 16:27:08 +03:00
|
|
|
|
return environmentService.GetWebSendUrl() + send.AccessId + "/" + send.UrlB64Key;
|
2021-02-19 00:58:20 +03:00
|
|
|
|
}
|
2021-02-11 03:50:10 +03:00
|
|
|
|
|
|
|
|
|
public static async Task<bool> RemoveSendPasswordAsync(string sendId)
|
|
|
|
|
{
|
2021-02-19 00:58:20 +03:00
|
|
|
|
if (await IsSendDisabledByPolicyAsync())
|
|
|
|
|
{
|
|
|
|
|
return false;
|
|
|
|
|
}
|
2021-02-11 03:50:10 +03:00
|
|
|
|
var platformUtilsService = ServiceContainer.Resolve<IPlatformUtilsService>("platformUtilsService");
|
|
|
|
|
var deviceActionService = ServiceContainer.Resolve<IDeviceActionService>("deviceActionService");
|
|
|
|
|
var sendService = ServiceContainer.Resolve<ISendService>("sendService");
|
|
|
|
|
|
|
|
|
|
if (Connectivity.NetworkAccess == NetworkAccess.None)
|
|
|
|
|
{
|
|
|
|
|
await platformUtilsService.ShowDialogAsync(AppResources.InternetConnectionRequiredMessage,
|
|
|
|
|
AppResources.InternetConnectionRequiredTitle);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
var confirmed = await platformUtilsService.ShowDialogAsync(
|
|
|
|
|
AppResources.AreYouSureRemoveSendPassword,
|
|
|
|
|
null, AppResources.Yes, AppResources.Cancel);
|
|
|
|
|
if (!confirmed)
|
|
|
|
|
{
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
await deviceActionService.ShowLoadingAsync(AppResources.RemovingSendPassword);
|
|
|
|
|
await sendService.RemovePasswordWithServerAsync(sendId);
|
|
|
|
|
await deviceActionService.HideLoadingAsync();
|
|
|
|
|
platformUtilsService.ShowToast("success", null, AppResources.SendPasswordRemoved);
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
catch (ApiException e)
|
|
|
|
|
{
|
|
|
|
|
await deviceActionService.HideLoadingAsync();
|
|
|
|
|
if (e?.Error != null)
|
|
|
|
|
{
|
|
|
|
|
await platformUtilsService.ShowDialogAsync(e.Error.GetSingleMessage(),
|
|
|
|
|
AppResources.AnErrorHasOccurred);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static async Task<bool> DeleteSendAsync(string sendId)
|
|
|
|
|
{
|
|
|
|
|
var platformUtilsService = ServiceContainer.Resolve<IPlatformUtilsService>("platformUtilsService");
|
|
|
|
|
var deviceActionService = ServiceContainer.Resolve<IDeviceActionService>("deviceActionService");
|
|
|
|
|
var sendService = ServiceContainer.Resolve<ISendService>("sendService");
|
|
|
|
|
|
|
|
|
|
if (Connectivity.NetworkAccess == NetworkAccess.None)
|
|
|
|
|
{
|
|
|
|
|
await platformUtilsService.ShowDialogAsync(AppResources.InternetConnectionRequiredMessage,
|
|
|
|
|
AppResources.InternetConnectionRequiredTitle);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
var confirmed = await platformUtilsService.ShowDialogAsync(
|
|
|
|
|
AppResources.AreYouSureDeleteSend,
|
|
|
|
|
null, AppResources.Yes, AppResources.Cancel);
|
|
|
|
|
if (!confirmed)
|
|
|
|
|
{
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
await deviceActionService.ShowLoadingAsync(AppResources.Deleting);
|
|
|
|
|
await sendService.DeleteWithServerAsync(sendId);
|
|
|
|
|
await deviceActionService.HideLoadingAsync();
|
|
|
|
|
platformUtilsService.ShowToast("success", null, AppResources.SendDeleted);
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
catch (ApiException e)
|
|
|
|
|
{
|
|
|
|
|
await deviceActionService.HideLoadingAsync();
|
|
|
|
|
if (e?.Error != null)
|
|
|
|
|
{
|
|
|
|
|
await platformUtilsService.ShowDialogAsync(e.Error.GetSingleMessage(),
|
|
|
|
|
AppResources.AnErrorHasOccurred);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2021-02-19 00:58:20 +03:00
|
|
|
|
public static async Task<bool> IsSendDisabledByPolicyAsync()
|
|
|
|
|
{
|
|
|
|
|
var policyService = ServiceContainer.Resolve<IPolicyService>("policyService");
|
2021-09-24 02:51:02 +03:00
|
|
|
|
return await policyService.PolicyAppliesToUser(PolicyType.DisableSend);
|
2021-02-19 00:58:20 +03:00
|
|
|
|
}
|
|
|
|
|
|
2021-03-29 19:01:42 +03:00
|
|
|
|
public static async Task<bool> IsHideEmailDisabledByPolicyAsync()
|
|
|
|
|
{
|
|
|
|
|
var policyService = ServiceContainer.Resolve<IPolicyService>("policyService");
|
|
|
|
|
|
2021-09-24 02:51:02 +03:00
|
|
|
|
return await policyService.PolicyAppliesToUser(PolicyType.SendOptions,
|
|
|
|
|
policy => policy.Data.ContainsKey("disableHideEmail") && (bool)policy.Data["disableHideEmail"]);
|
2021-03-29 19:01:42 +03:00
|
|
|
|
}
|
|
|
|
|
|
2019-05-30 21:13:02 +03:00
|
|
|
|
public static async Task<bool> PerformUpdateTasksAsync(ISyncService syncService,
|
2022-02-23 20:40:17 +03:00
|
|
|
|
IDeviceActionService deviceActionService, IStateService stateService)
|
2019-05-30 21:13:02 +03:00
|
|
|
|
{
|
|
|
|
|
var currentBuild = deviceActionService.GetBuildNumber();
|
2022-02-23 20:40:17 +03:00
|
|
|
|
var lastBuild = await stateService.GetLastBuildAsync();
|
|
|
|
|
if (lastBuild == null || lastBuild != currentBuild)
|
2019-10-06 04:36:47 +03:00
|
|
|
|
{
|
|
|
|
|
// Updated
|
|
|
|
|
var tasks = Task.Run(() => syncService.FullSyncAsync(true));
|
2022-02-23 20:40:17 +03:00
|
|
|
|
await stateService.SetLastBuildAsync(currentBuild);
|
2019-05-30 21:13:02 +03:00
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
2020-02-10 22:07:06 +03:00
|
|
|
|
|
|
|
|
|
public static async Task SetPreconfiguredSettingsAsync(IDictionary<string, string> configSettings)
|
|
|
|
|
{
|
2021-08-11 17:36:36 +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
|
|
|
|
|
});
|
|
|
|
|
}
|
2021-08-11 17:36:36 +03:00
|
|
|
|
return;
|
2020-02-10 22:07:06 +03:00
|
|
|
|
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;
|
|
|
|
|
}
|
2021-03-31 17:19:05 +03:00
|
|
|
|
if (appOptions.CreateSend != null)
|
|
|
|
|
{
|
|
|
|
|
Application.Current.MainPage = new NavigationPage(new SendAddEditPage(appOptions));
|
|
|
|
|
return true;
|
|
|
|
|
}
|
2020-09-03 19:30:40 +03:00
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static async Task<PreviousPageInfo> ClearPreviousPage()
|
|
|
|
|
{
|
2022-02-23 20:40:17 +03:00
|
|
|
|
var stateService = ServiceContainer.Resolve<IStateService>("stateService");
|
|
|
|
|
var previousPage = await stateService.GetPreviousPageInfoAsync();
|
2020-09-03 19:30:40 +03:00
|
|
|
|
if (previousPage != null)
|
|
|
|
|
{
|
2022-02-23 20:40:17 +03:00
|
|
|
|
await stateService.SetPreviousPageInfoAsync(null);
|
2020-09-03 19:30:40 +03:00
|
|
|
|
}
|
|
|
|
|
return previousPage;
|
|
|
|
|
}
|
2021-06-09 17:03:05 +03:00
|
|
|
|
|
|
|
|
|
public static async Task<int> IncrementInvalidUnlockAttemptsAsync()
|
|
|
|
|
{
|
2022-02-23 20:40:17 +03:00
|
|
|
|
var stateService = ServiceContainer.Resolve<IStateService>("stateService");
|
|
|
|
|
var invalidUnlockAttempts = await stateService.GetInvalidUnlockAttemptsAsync();
|
2021-06-09 17:03:05 +03:00
|
|
|
|
invalidUnlockAttempts++;
|
2022-02-23 20:40:17 +03:00
|
|
|
|
await stateService.SetInvalidUnlockAttemptsAsync(invalidUnlockAttempts);
|
2021-06-09 17:03:05 +03:00
|
|
|
|
return invalidUnlockAttempts;
|
|
|
|
|
}
|
2022-04-26 18:21:17 +03:00
|
|
|
|
|
2021-06-09 17:03:05 +03:00
|
|
|
|
public static async Task ResetInvalidUnlockAttemptsAsync()
|
|
|
|
|
{
|
2022-02-23 20:40:17 +03:00
|
|
|
|
var stateService = ServiceContainer.Resolve<IStateService>("stateService");
|
|
|
|
|
await stateService.SetInvalidUnlockAttemptsAsync(null);
|
2021-06-09 17:03:05 +03:00
|
|
|
|
}
|
2021-07-12 17:58:17 +03:00
|
|
|
|
|
|
|
|
|
public static async Task<bool> IsVaultTimeoutImmediateAsync()
|
|
|
|
|
{
|
2022-02-23 20:40:17 +03:00
|
|
|
|
var stateService = ServiceContainer.Resolve<IStateService>("stateService");
|
|
|
|
|
var vaultTimeoutMinutes = await stateService.GetVaultTimeoutAsync();
|
2021-07-12 17:58:17 +03:00
|
|
|
|
if (vaultTimeoutMinutes.GetValueOrDefault(-1) == 0)
|
|
|
|
|
{
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
2021-08-30 19:44:12 +03:00
|
|
|
|
|
|
|
|
|
public static string EncodeDataParameter(object obj)
|
|
|
|
|
{
|
|
|
|
|
string EncodeMultibyte(Match match)
|
|
|
|
|
{
|
|
|
|
|
return Convert.ToChar(Convert.ToUInt32($"0x{match.Groups[1].Value}", 16)).ToString();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var escaped = Uri.EscapeDataString(JsonConvert.SerializeObject(obj));
|
|
|
|
|
var multiByteEscaped = Regex.Replace(escaped, "%([0-9A-F]{2})", EncodeMultibyte);
|
2022-03-02 20:32:43 +03:00
|
|
|
|
return WebUtility.UrlEncode(Convert.ToBase64String(Encoding.UTF8.GetBytes(multiByteEscaped)));
|
2021-08-30 19:44:12 +03:00
|
|
|
|
}
|
2021-09-24 21:14:26 +03:00
|
|
|
|
|
2022-02-23 20:40:17 +03:00
|
|
|
|
public static async Task LogOutAsync(string userId, bool userInitiated = false)
|
2021-09-24 21:14:26 +03:00
|
|
|
|
{
|
|
|
|
|
var stateService = ServiceContainer.Resolve<IStateService>("stateService");
|
2022-03-10 17:02:01 +03:00
|
|
|
|
var vaultTimeoutService = ServiceContainer.Resolve<IVaultTimeoutService>("vaultTimeoutService");
|
2021-09-24 21:14:26 +03:00
|
|
|
|
|
2022-03-07 23:15:21 +03:00
|
|
|
|
var isActiveAccount = await stateService.IsActiveAccountAsync(userId);
|
2022-03-07 20:28:06 +03:00
|
|
|
|
|
2022-03-10 17:02:01 +03:00
|
|
|
|
var isAccountRemoval = await vaultTimeoutService.IsLoggedOutByTimeoutAsync(userId) ||
|
|
|
|
|
await vaultTimeoutService.ShouldLogOutByTimeoutAsync(userId);
|
|
|
|
|
|
2022-02-23 20:40:17 +03:00
|
|
|
|
if (userId == null)
|
|
|
|
|
{
|
|
|
|
|
userId = await stateService.GetActiveUserIdAsync();
|
|
|
|
|
}
|
|
|
|
|
|
2022-03-10 17:02:01 +03:00
|
|
|
|
await stateService.LogoutAccountAsync(userId, userInitiated);
|
2022-02-23 20:40:17 +03:00
|
|
|
|
|
2022-03-10 17:02:01 +03:00
|
|
|
|
if (isActiveAccount)
|
|
|
|
|
{
|
|
|
|
|
await ClearServiceCacheAsync();
|
|
|
|
|
}
|
2022-02-23 20:40:17 +03:00
|
|
|
|
|
2022-03-07 20:28:06 +03:00
|
|
|
|
if (!userInitiated)
|
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// check if we switched active accounts automatically
|
|
|
|
|
if (isActiveAccount && await stateService.GetActiveUserIdAsync() != null)
|
2022-02-23 20:40:17 +03:00
|
|
|
|
{
|
|
|
|
|
var messagingService = ServiceContainer.Resolve<IMessagingService>("messagingService");
|
|
|
|
|
messagingService.Send("switchedAccount");
|
2022-03-07 20:28:06 +03:00
|
|
|
|
|
2022-02-23 20:40:17 +03:00
|
|
|
|
var platformUtilsService = ServiceContainer.Resolve<IPlatformUtilsService>("platformUtilsService");
|
|
|
|
|
platformUtilsService.ShowToast("info", null, AppResources.AccountSwitchedAutomatically);
|
2022-03-07 20:28:06 +03:00
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// check if we logged out a non-active account
|
|
|
|
|
if (!isActiveAccount)
|
|
|
|
|
{
|
|
|
|
|
var platformUtilsService = ServiceContainer.Resolve<IPlatformUtilsService>("platformUtilsService");
|
2022-03-10 17:02:01 +03:00
|
|
|
|
if (isAccountRemoval)
|
2022-03-07 20:28:06 +03:00
|
|
|
|
{
|
|
|
|
|
platformUtilsService.ShowToast("info", null, AppResources.AccountRemovedSuccessfully);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
platformUtilsService.ShowToast("info", null, AppResources.AccountLoggedOutSuccessfully);
|
2022-02-23 20:40:17 +03:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static async Task OnAccountSwitchAsync()
|
|
|
|
|
{
|
|
|
|
|
var environmentService = ServiceContainer.Resolve<IEnvironmentService>("environmentService");
|
2022-03-10 17:02:01 +03:00
|
|
|
|
await environmentService.SetUrlsFromStorageAsync();
|
|
|
|
|
await ClearServiceCacheAsync();
|
2022-03-17 21:27:01 +03:00
|
|
|
|
var deviceActionService = ServiceContainer.Resolve<IDeviceActionService>("deviceActionService");
|
|
|
|
|
await deviceActionService.OnAccountSwitchCompleteAsync();
|
2022-03-10 17:02:01 +03:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static async Task ClearServiceCacheAsync()
|
|
|
|
|
{
|
2022-02-23 20:40:17 +03:00
|
|
|
|
var tokenService = ServiceContainer.Resolve<ITokenService>("tokenService");
|
|
|
|
|
var cryptoService = ServiceContainer.Resolve<ICryptoService>("cryptoService");
|
|
|
|
|
var settingsService = ServiceContainer.Resolve<ISettingsService>("settingsService");
|
|
|
|
|
var cipherService = ServiceContainer.Resolve<ICipherService>("cipherService");
|
|
|
|
|
var folderService = ServiceContainer.Resolve<IFolderService>("folderService");
|
|
|
|
|
var collectionService = ServiceContainer.Resolve<ICollectionService>("collectionService");
|
|
|
|
|
var sendService = ServiceContainer.Resolve<ISendService>("sendService");
|
|
|
|
|
var passwordGenerationService = ServiceContainer.Resolve<IPasswordGenerationService>(
|
|
|
|
|
"passwordGenerationService");
|
|
|
|
|
var deviceActionService = ServiceContainer.Resolve<IDeviceActionService>("deviceActionService");
|
|
|
|
|
var policyService = ServiceContainer.Resolve<IPolicyService>("policyService");
|
|
|
|
|
var searchService = ServiceContainer.Resolve<ISearchService>("searchService");
|
|
|
|
|
|
|
|
|
|
await Task.WhenAll(
|
|
|
|
|
cipherService.ClearCacheAsync(),
|
2021-09-24 21:14:26 +03:00
|
|
|
|
deviceActionService.ClearCacheAsync());
|
2022-02-23 20:40:17 +03:00
|
|
|
|
tokenService.ClearCache();
|
|
|
|
|
cryptoService.ClearCache();
|
|
|
|
|
settingsService.ClearCache();
|
|
|
|
|
folderService.ClearCache();
|
|
|
|
|
collectionService.ClearCache();
|
|
|
|
|
sendService.ClearCache();
|
|
|
|
|
passwordGenerationService.ClearCache();
|
|
|
|
|
policyService.ClearCache();
|
2021-09-24 21:14:26 +03:00
|
|
|
|
searchService.ClearIndex();
|
|
|
|
|
}
|
2019-05-30 06:35:34 +03:00
|
|
|
|
}
|
|
|
|
|
}
|