Added equivalent domain checks to autofill listing filter. centralized logic in login service.

This commit is contained in:
Kyle Spearrin 2017-02-08 23:58:37 -05:00
parent 2a1bd92e1a
commit 539121070a
8 changed files with 114 additions and 69 deletions

View file

@ -1,11 +1,8 @@
using System.Collections.Generic;
using System.Threading.Tasks;
using Bit.App.Models.Data;
using Bit.App.Models.Data;
namespace Bit.App.Abstractions
{
public interface ISettingsRepository : IRepository<SettingsData, string>
{
Task<IEnumerable<IEnumerable<string>>> GetEquivablentDomains(string userId);
}
}

View file

@ -10,6 +10,7 @@ namespace Bit.App.Abstractions
Task<Login> GetByIdAsync(string id);
Task<IEnumerable<Login>> GetAllAsync();
Task<IEnumerable<Login>> GetAllAsync(bool favorites);
Task<IEnumerable<Login>> GetAllAsync(string uriString);
Task<ApiResult<LoginResponse>> SaveAsync(Login login);
Task<ApiResult> DeleteAsync(string id);
}

View file

@ -1,6 +1,10 @@
namespace Bit.App.Abstractions
using System.Collections.Generic;
using System.Threading.Tasks;
namespace Bit.App.Abstractions
{
public interface ISettingsService
{
Task<IEnumerable<IEnumerable<string>>> GetEquivalentDomainsAsync();
}
}

View file

@ -26,37 +26,6 @@ namespace Bit.App.Models.Page
public string Username { get; set; }
public Lazy<string> Password { get; set; }
public Lazy<string> Uri { get; set; }
public string BaseDomain
{
get
{
if(_baseDomain != null)
{
return _baseDomain;
}
if(string.IsNullOrWhiteSpace(Uri.Value))
{
return null;
}
Uri uri;
if(!System.Uri.TryCreate(Uri.Value, UriKind.Absolute, out uri))
{
return null;
}
DomainName domain;
if(!DomainName.TryParse(uri.Host, out domain))
{
return null;
}
_baseDomain = domain.BaseDomain;
return _baseDomain;
}
}
}
public class Folder : List<Login>

View file

@ -21,34 +21,35 @@ namespace Bit.App.Pages
private readonly IDeviceInfoService _deviceInfoService;
private readonly IUserDialogs _userDialogs;
private readonly IClipboardService _clipboardService;
private readonly ISettingsService _settingsService;
private CancellationTokenSource _filterResultsCancellationTokenSource;
private readonly DomainName _domainName;
private readonly string _name;
private readonly bool _androidApp = false;
public VaultAutofillListLoginsPage(string uriString)
: base(true)
{
Uri = uriString;
Uri uri;
DomainName domainName;
if(!System.Uri.TryCreate(uriString, UriKind.Absolute, out uri) ||
!DomainName.TryParse(uri.Host, out _domainName))
!DomainName.TryParse(uri.Host, out domainName))
{
if(uriString != null && uriString.StartsWith(Constants.AndroidAppProtocol))
{
_androidApp = true;
_name = uriString.Substring(Constants.AndroidAppProtocol.Length);
}
}
else
{
_name = _domainName.BaseDomain;
_name = domainName.BaseDomain;
}
_loginService = Resolver.Resolve<ILoginService>();
_deviceInfoService = Resolver.Resolve<IDeviceInfoService>();
_userDialogs = Resolver.Resolve<IUserDialogs>();
_clipboardService = Resolver.Resolve<IClipboardService>();
_settingsService = Resolver.Resolve<ISettingsService>();
GoogleAnalyticsService = Resolver.Resolve<IGoogleAnalyticsService>();
Init();
@ -149,17 +150,14 @@ namespace Bit.App.Pages
Task.Run(async () =>
{
var logins = await _loginService.GetAllAsync();
var filteredLogins = logins
.Select(s => new VaultListPageModel.Login(s))
.Where(s => (_androidApp && _domainName == null && s.Uri.Value == Uri) ||
(_domainName != null && s.BaseDomain != null && s.BaseDomain == _domainName.BaseDomain))
var logins = await _loginService.GetAllAsync(Uri);
var sortedLogins = logins.Select(l => new VaultListPageModel.Login(l))
.OrderBy(s => s.Name)
.ThenBy(s => s.Username);
Device.BeginInvokeOnMainThread(() =>
{
PresentationLogins.ResetWithRange(filteredLogins);
PresentationLogins.ResetWithRange(sortedLogins);
AdjustContent();
});
}, cts.Token);

View file

@ -1,9 +1,5 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Bit.App.Abstractions;
using Bit.App.Abstractions;
using Bit.App.Models.Data;
using Newtonsoft.Json;
namespace Bit.App.Repositories
{
@ -12,19 +8,5 @@ namespace Bit.App.Repositories
public SettingsRepository(ISqlService sqlService)
: base(sqlService)
{ }
public Task<IEnumerable<IEnumerable<string>>> GetEquivablentDomains(string userId)
{
var equivalentDomainsJson = Connection.Table<SettingsData>().Where(f => f.Id == userId)
.Select(f => f.EquivalentDomains).FirstOrDefault();
if(string.IsNullOrWhiteSpace(equivalentDomainsJson))
{
return Task.FromResult<IEnumerable<IEnumerable<string>>>(null);
}
var equivalentDomains = JsonConvert.DeserializeObject<IEnumerable<IEnumerable<string>>>(equivalentDomainsJson);
return Task.FromResult(equivalentDomains);
}
}
}

View file

@ -15,15 +15,18 @@ namespace Bit.App.Services
private readonly ILoginRepository _loginRepository;
private readonly IAuthService _authService;
private readonly ILoginApiRepository _loginApiRepository;
private readonly ISettingsService _settingsService;
public LoginService(
ILoginRepository loginRepository,
IAuthService authService,
ILoginApiRepository loginApiRepository)
ILoginApiRepository loginApiRepository,
ISettingsService settingsService)
{
_loginRepository = loginRepository;
_authService = authService;
_loginApiRepository = loginApiRepository;
_settingsService = settingsService;
}
public async Task<Login> GetByIdAsync(string id)
@ -52,6 +55,80 @@ namespace Bit.App.Services
return logins;
}
public async Task<IEnumerable<Login>> GetAllAsync(string uriString)
{
if(string.IsNullOrWhiteSpace(uriString))
{
return new List<Login>();
}
Uri uri = null;
DomainName domainName = null;
var androidApp = false;
if(!Uri.TryCreate(uriString, UriKind.Absolute, out uri) || !DomainName.TryParse(uri.Host, out domainName))
{
if(domainName == null)
{
androidApp = uriString.StartsWith(Constants.AndroidAppProtocol);
}
}
if(!androidApp && domainName == null)
{
return new List<Login>();
}
var eqDomains = (await _settingsService.GetEquivalentDomainsAsync()).Select(d => d.ToArray());
var matchingDomains = eqDomains
.Where(d => (androidApp && Array.IndexOf(d, uriString) >= 0) ||
(!androidApp && Array.IndexOf(d, domainName.BaseDomain) >= 0))
.SelectMany(d => d).ToList();
if(!matchingDomains.Any())
{
matchingDomains.Add(androidApp ? uriString : domainName.BaseDomain);
}
var matchingDomainsArray = matchingDomains.ToArray();
var matchingLogins = new List<Login>();
var logins = await _loginRepository.GetAllByUserIdAsync(_authService.UserId);
foreach(var login in logins)
{
if(string.IsNullOrWhiteSpace(login.Uri))
{
continue;
}
var loginUriString = new CipherString(login.Uri).Decrypt();
if(string.IsNullOrWhiteSpace(loginUriString))
{
continue;
}
if(androidApp && Array.IndexOf(matchingDomainsArray, loginUriString) >= 0)
{
matchingLogins.Add(new Login(login));
continue;
}
Uri loginUri;
DomainName loginDomainName;
if(!Uri.TryCreate(loginUriString, UriKind.Absolute, out loginUri)
|| !DomainName.TryParse(loginUri.Host, out loginDomainName))
{
continue;
}
if(Array.IndexOf(matchingDomainsArray, loginDomainName.BaseDomain) >= 0)
{
matchingLogins.Add(new Login(login));
}
}
return matchingLogins;
}
public async Task<ApiResult<LoginResponse>> SaveAsync(Login login)
{
ApiResult<LoginResponse> response = null;

View file

@ -1,5 +1,8 @@
using Bit.App.Abstractions;
using Plugin.Settings.Abstractions;
using System.Collections.Generic;
using System.Threading.Tasks;
using Newtonsoft.Json;
namespace Bit.App.Services
{
@ -7,13 +10,27 @@ namespace Bit.App.Services
{
private readonly ISettingsRepository _settingsRepository;
private readonly ISettings _settings;
private readonly IAuthService _authService;
public SettingsService(
ISettingsRepository settingsRepository,
ISettings settings)
ISettings settings,
IAuthService authService)
{
_settingsRepository = settingsRepository;
_settings = settings;
_authService = authService;
}
public async Task<IEnumerable<IEnumerable<string>>> GetEquivalentDomainsAsync()
{
var settings = await _settingsRepository.GetByIdAsync(_authService.UserId);
if(string.IsNullOrWhiteSpace(settings?.EquivalentDomains))
{
return null;
}
return JsonConvert.DeserializeObject<IEnumerable<IEnumerable<string>>>(settings.EquivalentDomains);
}
}
}