1
0
mirror of https://github.com/bitwarden/mobile synced 2026-01-21 03:43:17 +00:00

multibutton alert, autofill and save new uri

This commit is contained in:
Kyle Spearrin
2018-04-02 13:37:46 -04:00
parent be11933c60
commit 10df9e7cd5
12 changed files with 313 additions and 40 deletions

View File

@@ -23,5 +23,6 @@ namespace Bit.App.Abstractions
void OpenAutofillSettings();
Task LaunchAppAsync(string appName, Page page);
Task<string> DisplayPromptAync(string title = null, string description = null, string text = null);
Task<string> DisplayAlertAsync(string title, string message, string cancel, params string[] buttons);
}
}

View File

@@ -13,6 +13,7 @@ using Bit.App.Models;
using System.Collections.Generic;
using Bit.App.Enums;
using static Bit.App.Models.Page.VaultListPageModel;
using Plugin.Connectivity.Abstractions;
namespace Bit.App.Pages
{
@@ -22,6 +23,7 @@ namespace Bit.App.Pages
private readonly IDeviceInfoService _deviceInfoService;
private readonly ISettingsService _settingsService;
private readonly IAppSettingsService _appSettingsService;
public readonly IConnectivity _connectivity;
private CancellationTokenSource _filterResultsCancellationTokenSource;
private readonly string _name;
private readonly AppOptions _appOptions;
@@ -47,6 +49,7 @@ namespace Bit.App.Pages
_settingsService = Resolver.Resolve<ISettingsService>();
_appSettingsService = Resolver.Resolve<IAppSettingsService>();
GoogleAnalyticsService = Resolver.Resolve<IGoogleAnalyticsService>();
_connectivity = Resolver.Resolve<IConnectivity>();
Init();
}
@@ -237,17 +240,57 @@ namespace Bit.App.Pages
}
else
{
bool doAutofill = true;
var autofillResponse = AppResources.Yes;
if(cipher.Fuzzy)
{
doAutofill = await DisplayAlert(null,
string.Format(AppResources.BitwardenAutofillServiceMatchConfirm, _name),
AppResources.Yes, AppResources.No);
var options = new List<string> { AppResources.Yes };
if(cipher.Type == CipherType.Login && _connectivity.IsConnected)
{
options.Add(AppResources.YesAndSave);
}
autofillResponse = await DeviceActionService.DisplayAlertAsync(null,
string.Format(AppResources.BitwardenAutofillServiceMatchConfirm, _name), AppResources.No,
options.ToArray());
}
if(doAutofill)
if(autofillResponse == AppResources.YesAndSave && cipher.Type == CipherType.Login)
{
GoogleAnalyticsService.TrackExtensionEvent("AutoFilled", Uri.StartsWith("http") ? "Website" : "App");
if(!_connectivity.IsConnected)
{
Helpers.AlertNoConnection(this);
}
else
{
var uris = cipher.CipherModel.Login?.Uris?.ToList();
if(uris == null)
{
uris = new List<LoginUri>();
}
uris.Add(new LoginUri
{
Uri = Uri.Encrypt(cipher.CipherModel.OrganizationId),
Match = null
});
cipher.CipherModel.Login.Uris = uris;
await DeviceActionService.ShowLoadingAsync(AppResources.Saving);
var saveTask = await _cipherService.SaveAsync(cipher.CipherModel);
await DeviceActionService.HideLoadingAsync();
if(saveTask.Succeeded)
{
GoogleAnalyticsService.TrackAppEvent("AddedLoginUriDuringAutofill");
}
}
}
if(autofillResponse == AppResources.Yes || autofillResponse == AppResources.YesAndSave)
{
GoogleAnalyticsService.TrackExtensionEvent("AutoFilled",
Uri.StartsWith("http") ? "Website" : "App");
DeviceActionService.Autofill(cipher);
}
}

View File

@@ -403,8 +403,14 @@ namespace Bit.App.Pages
string selection = null;
if(!string.IsNullOrWhiteSpace(_uri))
{
var options = new List<string> { AppResources.Autofill };
if(cipher.Type == Enums.CipherType.Login && _connectivity.IsConnected)
{
options.Add(AppResources.AutofillAndSave);
}
options.Add(AppResources.View);
selection = await DisplayActionSheet(AppResources.AutofillOrView, AppResources.Cancel, null,
AppResources.Autofill, AppResources.View);
options.ToArray());
}
if(selection == AppResources.View || string.IsNullOrWhiteSpace(_uri))
@@ -412,8 +418,40 @@ namespace Bit.App.Pages
var page = new VaultViewCipherPage(cipher.Type, cipher.Id);
await Navigation.PushForDeviceAsync(page);
}
else if(selection == AppResources.Autofill)
else if(selection == AppResources.Autofill || selection == AppResources.AutofillAndSave)
{
if(selection == AppResources.AutofillAndSave)
{
if(!_connectivity.IsConnected)
{
Helpers.AlertNoConnection(this);
}
else
{
var uris = cipher.CipherModel.Login?.Uris?.ToList();
if(uris == null)
{
uris = new List<Models.LoginUri>();
}
uris.Add(new Models.LoginUri
{
Uri = _uri.Encrypt(cipher.CipherModel.OrganizationId),
Match = null
});
cipher.CipherModel.Login.Uris = uris;
await _deviceActionService.ShowLoadingAsync(AppResources.Saving);
var saveTask = await _cipherService.SaveAsync(cipher.CipherModel);
await _deviceActionService.HideLoadingAsync();
if(saveTask.Succeeded)
{
_googleAnalyticsService.TrackAppEvent("AddedLoginUriDuringAutofill");
}
}
}
if(_deviceInfoService.Version < 21)
{
Helpers.CipherMoreClickedAsync(this, cipher, !string.IsNullOrWhiteSpace(_uri));

View File

@@ -330,6 +330,15 @@ namespace Bit.App.Resources {
}
}
/// <summary>
/// Looks up a localized string similar to Auto-fill and save.
/// </summary>
public static string AutofillAndSave {
get {
return ResourceManager.GetString("AutofillAndSave", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Do you want to auto-fill or view this item?.
/// </summary>
@@ -3291,6 +3300,15 @@ namespace Bit.App.Resources {
}
}
/// <summary>
/// Looks up a localized string similar to Yes, and Save.
/// </summary>
public static string YesAndSave {
get {
return ResourceManager.GetString("YesAndSave", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to To continue, hold your YubiKey NEO against the back of the device or insert your YubiKey into your device&apos;s USB port, then touch its button..
/// </summary>

View File

@@ -1283,4 +1283,10 @@
<value>Match Detection</value>
<comment>URI match detection for auto-fill.</comment>
</data>
<data name="YesAndSave" xml:space="preserve">
<value>Yes, and Save</value>
</data>
<data name="AutofillAndSave" xml:space="preserve">
<value>Auto-fill and save</value>
</data>
</root>

View File

@@ -93,7 +93,8 @@ namespace Bit.App.Services
return ciphers.Where(c => cipherIds.Contains(c.Id));
}
public async Task<Tuple<IEnumerable<Cipher>, IEnumerable<Cipher>, IEnumerable<Cipher>>> GetAllAsync(string uriString)
public async Task<Tuple<IEnumerable<Cipher>, IEnumerable<Cipher>, IEnumerable<Cipher>>> GetAllAsync(
string uriString)
{
if(string.IsNullOrWhiteSpace(uriString))
{
@@ -173,42 +174,42 @@ namespace Bit.App.Services
break;
}
var added = false;
var match = false;
switch(u.Match)
{
case null:
case Enums.UriMatchType.Domain:
added = CheckDefaultUriMatch(cipher, loginUriString, matchingLogins, matchingFuzzyLogins,
match = CheckDefaultUriMatch(cipher, loginUriString, matchingLogins, matchingFuzzyLogins,
matchingDomainsArray, matchingFuzzyDomainsArray, mobileApp, mobileAppSearchTerms);
break;
case Enums.UriMatchType.Host:
var urlHost = Helpers.GetUrlHost(uriString);
added = urlHost != null && urlHost == Helpers.GetUrlHost(loginUriString);
if(added)
match = urlHost != null && urlHost == Helpers.GetUrlHost(loginUriString);
if(match)
{
matchingLogins.Add(cipher);
AddMatchingLogin(cipher, matchingLogins, matchingFuzzyLogins);
}
break;
case Enums.UriMatchType.Exact:
added = uriString == loginUriString;
if(added)
match = uriString == loginUriString;
if(match)
{
matchingLogins.Add(cipher);
AddMatchingLogin(cipher, matchingLogins, matchingFuzzyLogins);
}
break;
case Enums.UriMatchType.StartsWith:
added = uriString.StartsWith(loginUriString);
if(added)
match = uriString.StartsWith(loginUriString);
if(match)
{
matchingLogins.Add(cipher);
AddMatchingLogin(cipher, matchingLogins, matchingFuzzyLogins);
}
break;
case Enums.UriMatchType.RegularExpression:
var regex = new Regex(loginUriString, RegexOptions.IgnoreCase, TimeSpan.FromSeconds(1));
added = regex.IsMatch(uriString);
if(added)
match = regex.IsMatch(uriString);
if(match)
{
matchingLogins.Add(cipher);
AddMatchingLogin(cipher, matchingLogins, matchingFuzzyLogins);
}
break;
case Enums.UriMatchType.Never:
@@ -216,7 +217,7 @@ namespace Bit.App.Services
break;
}
if(added)
if(match)
{
break;
}
@@ -436,21 +437,21 @@ namespace Bit.App.Services
{
if(Array.IndexOf(matchingDomainsArray, loginUriString) >= 0)
{
matchingLogins.Add(cipher);
AddMatchingLogin(cipher, matchingLogins, matchingFuzzyLogins);
return true;
}
else if(mobileApp && Array.IndexOf(matchingFuzzyDomainsArray, loginUriString) >= 0)
{
matchingFuzzyLogins.Add(cipher);
return true;
AddMatchingFuzzyLogin(cipher, matchingLogins, matchingFuzzyLogins);
return false;
}
else if(!mobileApp)
{
var info = InfoFromMobileAppUri(loginUriString);
if(info?.Item1 != null && Array.IndexOf(matchingDomainsArray, info.Item1) >= 0)
{
matchingFuzzyLogins.Add(cipher);
return true;
AddMatchingFuzzyLogin(cipher, matchingLogins, matchingFuzzyLogins);
return false;
}
}
@@ -462,13 +463,13 @@ namespace Bit.App.Services
if(Array.IndexOf(matchingDomainsArray, loginDomainName) >= 0)
{
matchingLogins.Add(cipher);
AddMatchingLogin(cipher, matchingLogins, matchingFuzzyLogins);
return true;
}
else if(mobileApp && Array.IndexOf(matchingFuzzyDomainsArray, loginDomainName) >= 0)
{
matchingFuzzyLogins.Add(cipher);
return true;
AddMatchingFuzzyLogin(cipher, matchingLogins, matchingFuzzyLogins);
return false;
}
}
@@ -491,13 +492,31 @@ namespace Bit.App.Services
if(addedFromSearchTerm)
{
matchingFuzzyLogins.Add(cipher);
return true;
AddMatchingFuzzyLogin(cipher, matchingLogins, matchingFuzzyLogins);
return false;
}
}
}
return false;
}
private void AddMatchingLogin(Cipher cipher, List<Cipher> matchingLogins, List<Cipher> matchingFuzzyLogins)
{
if(matchingFuzzyLogins.Contains(cipher))
{
matchingFuzzyLogins.Remove(cipher);
}
matchingLogins.Add(cipher);
}
private void AddMatchingFuzzyLogin(Cipher cipher, List<Cipher> matchingLogins, List<Cipher> matchingFuzzyLogins)
{
if(!matchingFuzzyLogins.Contains(cipher) && !matchingLogins.Contains(cipher))
{
matchingFuzzyLogins.Add(cipher);
}
}
}
}

View File

@@ -521,5 +521,11 @@ namespace Bit.App.Utilities
return host;
}
public static void AlertNoConnection(Page page)
{
page.DisplayAlert(AppResources.InternetConnectionRequiredTitle,
AppResources.InternetConnectionRequiredMessage, AppResources.Ok);
}
}
}