mirror of
https://github.com/bitwarden/android.git
synced 2024-12-18 23:31:52 +03:00
Added equivalent domain checks to autofill listing filter. centralized logic in login service.
This commit is contained in:
parent
2a1bd92e1a
commit
539121070a
8 changed files with 114 additions and 69 deletions
|
@ -1,11 +1,8 @@
|
||||||
using System.Collections.Generic;
|
using Bit.App.Models.Data;
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Bit.App.Models.Data;
|
|
||||||
|
|
||||||
namespace Bit.App.Abstractions
|
namespace Bit.App.Abstractions
|
||||||
{
|
{
|
||||||
public interface ISettingsRepository : IRepository<SettingsData, string>
|
public interface ISettingsRepository : IRepository<SettingsData, string>
|
||||||
{
|
{
|
||||||
Task<IEnumerable<IEnumerable<string>>> GetEquivablentDomains(string userId);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,6 +10,7 @@ namespace Bit.App.Abstractions
|
||||||
Task<Login> GetByIdAsync(string id);
|
Task<Login> GetByIdAsync(string id);
|
||||||
Task<IEnumerable<Login>> GetAllAsync();
|
Task<IEnumerable<Login>> GetAllAsync();
|
||||||
Task<IEnumerable<Login>> GetAllAsync(bool favorites);
|
Task<IEnumerable<Login>> GetAllAsync(bool favorites);
|
||||||
|
Task<IEnumerable<Login>> GetAllAsync(string uriString);
|
||||||
Task<ApiResult<LoginResponse>> SaveAsync(Login login);
|
Task<ApiResult<LoginResponse>> SaveAsync(Login login);
|
||||||
Task<ApiResult> DeleteAsync(string id);
|
Task<ApiResult> DeleteAsync(string id);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,10 @@
|
||||||
namespace Bit.App.Abstractions
|
using System.Collections.Generic;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Bit.App.Abstractions
|
||||||
{
|
{
|
||||||
public interface ISettingsService
|
public interface ISettingsService
|
||||||
{
|
{
|
||||||
|
Task<IEnumerable<IEnumerable<string>>> GetEquivalentDomainsAsync();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,37 +26,6 @@ namespace Bit.App.Models.Page
|
||||||
public string Username { get; set; }
|
public string Username { get; set; }
|
||||||
public Lazy<string> Password { get; set; }
|
public Lazy<string> Password { get; set; }
|
||||||
public Lazy<string> Uri { 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>
|
public class Folder : List<Login>
|
||||||
|
|
|
@ -21,34 +21,35 @@ namespace Bit.App.Pages
|
||||||
private readonly IDeviceInfoService _deviceInfoService;
|
private readonly IDeviceInfoService _deviceInfoService;
|
||||||
private readonly IUserDialogs _userDialogs;
|
private readonly IUserDialogs _userDialogs;
|
||||||
private readonly IClipboardService _clipboardService;
|
private readonly IClipboardService _clipboardService;
|
||||||
|
private readonly ISettingsService _settingsService;
|
||||||
private CancellationTokenSource _filterResultsCancellationTokenSource;
|
private CancellationTokenSource _filterResultsCancellationTokenSource;
|
||||||
private readonly DomainName _domainName;
|
|
||||||
private readonly string _name;
|
private readonly string _name;
|
||||||
private readonly bool _androidApp = false;
|
|
||||||
|
|
||||||
public VaultAutofillListLoginsPage(string uriString)
|
public VaultAutofillListLoginsPage(string uriString)
|
||||||
: base(true)
|
: base(true)
|
||||||
{
|
{
|
||||||
Uri = uriString;
|
Uri = uriString;
|
||||||
|
|
||||||
Uri uri;
|
Uri uri;
|
||||||
|
DomainName domainName;
|
||||||
if(!System.Uri.TryCreate(uriString, UriKind.Absolute, out uri) ||
|
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))
|
if(uriString != null && uriString.StartsWith(Constants.AndroidAppProtocol))
|
||||||
{
|
{
|
||||||
_androidApp = true;
|
|
||||||
_name = uriString.Substring(Constants.AndroidAppProtocol.Length);
|
_name = uriString.Substring(Constants.AndroidAppProtocol.Length);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_name = _domainName.BaseDomain;
|
_name = domainName.BaseDomain;
|
||||||
}
|
}
|
||||||
|
|
||||||
_loginService = Resolver.Resolve<ILoginService>();
|
_loginService = Resolver.Resolve<ILoginService>();
|
||||||
_deviceInfoService = Resolver.Resolve<IDeviceInfoService>();
|
_deviceInfoService = Resolver.Resolve<IDeviceInfoService>();
|
||||||
_userDialogs = Resolver.Resolve<IUserDialogs>();
|
_userDialogs = Resolver.Resolve<IUserDialogs>();
|
||||||
_clipboardService = Resolver.Resolve<IClipboardService>();
|
_clipboardService = Resolver.Resolve<IClipboardService>();
|
||||||
|
_settingsService = Resolver.Resolve<ISettingsService>();
|
||||||
GoogleAnalyticsService = Resolver.Resolve<IGoogleAnalyticsService>();
|
GoogleAnalyticsService = Resolver.Resolve<IGoogleAnalyticsService>();
|
||||||
|
|
||||||
Init();
|
Init();
|
||||||
|
@ -149,17 +150,14 @@ namespace Bit.App.Pages
|
||||||
|
|
||||||
Task.Run(async () =>
|
Task.Run(async () =>
|
||||||
{
|
{
|
||||||
var logins = await _loginService.GetAllAsync();
|
var logins = await _loginService.GetAllAsync(Uri);
|
||||||
var filteredLogins = logins
|
var sortedLogins = logins.Select(l => new VaultListPageModel.Login(l))
|
||||||
.Select(s => new VaultListPageModel.Login(s))
|
|
||||||
.Where(s => (_androidApp && _domainName == null && s.Uri.Value == Uri) ||
|
|
||||||
(_domainName != null && s.BaseDomain != null && s.BaseDomain == _domainName.BaseDomain))
|
|
||||||
.OrderBy(s => s.Name)
|
.OrderBy(s => s.Name)
|
||||||
.ThenBy(s => s.Username);
|
.ThenBy(s => s.Username);
|
||||||
|
|
||||||
Device.BeginInvokeOnMainThread(() =>
|
Device.BeginInvokeOnMainThread(() =>
|
||||||
{
|
{
|
||||||
PresentationLogins.ResetWithRange(filteredLogins);
|
PresentationLogins.ResetWithRange(sortedLogins);
|
||||||
AdjustContent();
|
AdjustContent();
|
||||||
});
|
});
|
||||||
}, cts.Token);
|
}, cts.Token);
|
||||||
|
|
|
@ -1,9 +1,5 @@
|
||||||
using System;
|
using Bit.App.Abstractions;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Bit.App.Abstractions;
|
|
||||||
using Bit.App.Models.Data;
|
using Bit.App.Models.Data;
|
||||||
using Newtonsoft.Json;
|
|
||||||
|
|
||||||
namespace Bit.App.Repositories
|
namespace Bit.App.Repositories
|
||||||
{
|
{
|
||||||
|
@ -12,19 +8,5 @@ namespace Bit.App.Repositories
|
||||||
public SettingsRepository(ISqlService sqlService)
|
public SettingsRepository(ISqlService sqlService)
|
||||||
: base(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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,15 +15,18 @@ namespace Bit.App.Services
|
||||||
private readonly ILoginRepository _loginRepository;
|
private readonly ILoginRepository _loginRepository;
|
||||||
private readonly IAuthService _authService;
|
private readonly IAuthService _authService;
|
||||||
private readonly ILoginApiRepository _loginApiRepository;
|
private readonly ILoginApiRepository _loginApiRepository;
|
||||||
|
private readonly ISettingsService _settingsService;
|
||||||
|
|
||||||
public LoginService(
|
public LoginService(
|
||||||
ILoginRepository loginRepository,
|
ILoginRepository loginRepository,
|
||||||
IAuthService authService,
|
IAuthService authService,
|
||||||
ILoginApiRepository loginApiRepository)
|
ILoginApiRepository loginApiRepository,
|
||||||
|
ISettingsService settingsService)
|
||||||
{
|
{
|
||||||
_loginRepository = loginRepository;
|
_loginRepository = loginRepository;
|
||||||
_authService = authService;
|
_authService = authService;
|
||||||
_loginApiRepository = loginApiRepository;
|
_loginApiRepository = loginApiRepository;
|
||||||
|
_settingsService = settingsService;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<Login> GetByIdAsync(string id)
|
public async Task<Login> GetByIdAsync(string id)
|
||||||
|
@ -52,6 +55,80 @@ namespace Bit.App.Services
|
||||||
return logins;
|
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)
|
public async Task<ApiResult<LoginResponse>> SaveAsync(Login login)
|
||||||
{
|
{
|
||||||
ApiResult<LoginResponse> response = null;
|
ApiResult<LoginResponse> response = null;
|
||||||
|
|
|
@ -1,5 +1,8 @@
|
||||||
using Bit.App.Abstractions;
|
using Bit.App.Abstractions;
|
||||||
using Plugin.Settings.Abstractions;
|
using Plugin.Settings.Abstractions;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
namespace Bit.App.Services
|
namespace Bit.App.Services
|
||||||
{
|
{
|
||||||
|
@ -7,13 +10,27 @@ namespace Bit.App.Services
|
||||||
{
|
{
|
||||||
private readonly ISettingsRepository _settingsRepository;
|
private readonly ISettingsRepository _settingsRepository;
|
||||||
private readonly ISettings _settings;
|
private readonly ISettings _settings;
|
||||||
|
private readonly IAuthService _authService;
|
||||||
|
|
||||||
public SettingsService(
|
public SettingsService(
|
||||||
ISettingsRepository settingsRepository,
|
ISettingsRepository settingsRepository,
|
||||||
ISettings settings)
|
ISettings settings,
|
||||||
|
IAuthService authService)
|
||||||
{
|
{
|
||||||
_settingsRepository = settingsRepository;
|
_settingsRepository = settingsRepository;
|
||||||
_settings = settings;
|
_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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue